2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS
check_access(connection_struct
*conn
,
60 const struct smb_filename
*smb_fname
,
64 if (!(fsp
->access_mask
& access_mask
)) {
65 return NT_STATUS_ACCESS_DENIED
;
68 NTSTATUS status
= smbd_check_access_rights(conn
,
71 if (!NT_STATUS_IS_OK(status
)) {
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
85 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type
= get_remote_arch();
89 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
90 val
= SMB_ROUNDUP(val
,rval
);
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
104 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
105 return (uint64_t)psbuf
->st_ex_ino
;
107 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
108 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name
)
122 static const char * const prohibited_ea_names
[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME
,
124 SAMBA_XATTR_DOS_ATTRIB
,
132 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
133 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
136 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
148 files_struct
*fsp
, const char *fname
,
149 const char *ea_name
, struct ea_struct
*pea
)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size
= 256;
158 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
160 return NT_STATUS_NO_MEMORY
;
163 if (fsp
&& fsp
->fh
->fd
!= -1) {
164 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
166 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
169 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
175 return map_nt_error_from_unix(errno
);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
179 dump_data(10, (uint8
*)val
, sizeret
);
182 if (strnequal(ea_name
, "user.", 5)) {
183 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
185 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
187 if (pea
->name
== NULL
) {
189 return NT_STATUS_NO_MEMORY
;
191 pea
->value
.data
= (unsigned char *)val
;
192 pea
->value
.length
= (size_t)sizeret
;
196 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
197 files_struct
*fsp
, const char *fname
,
198 char ***pnames
, size_t *pnum_names
)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size
= 1024;
202 char *ea_namelist
= NULL
;
207 ssize_t sizeret
= -1;
209 if (!lp_ea_support(SNUM(conn
))) {
218 * TALLOC the result early to get the talloc hierarchy right.
221 names
= talloc_array(mem_ctx
, char *, 1);
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY
;
227 while (ea_namelist_size
<= 65536) {
229 ea_namelist
= talloc_realloc(
230 names
, ea_namelist
, char, ea_namelist_size
);
231 if (ea_namelist
== NULL
) {
232 DEBUG(0, ("talloc failed\n"));
234 return NT_STATUS_NO_MEMORY
;
237 if (fsp
&& fsp
->fh
->fd
!= -1) {
238 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
241 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
245 if ((sizeret
== -1) && (errno
== ERANGE
)) {
246 ea_namelist_size
*= 2;
255 return map_nt_error_from_unix(errno
);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret
));
271 * Ensure the result is 0-terminated
274 if (ea_namelist
[sizeret
-1] != '\0') {
276 return NT_STATUS_INTERNAL_ERROR
;
284 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
288 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
290 DEBUG(0, ("talloc failed\n"));
292 return NT_STATUS_NO_MEMORY
;
298 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
299 names
[num_names
++] = p
;
307 *pnum_names
= num_names
;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
316 const char *fname
, size_t *pea_total_len
)
318 /* Get a list of all xattrs. Max namesize is 64k. */
321 struct ea_list
*ea_list_head
= NULL
;
326 if (!lp_ea_support(SNUM(conn
))) {
330 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
333 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
337 for (i
=0; i
<num_names
; i
++) {
338 struct ea_list
*listp
;
341 if (strnequal(names
[i
], "system.", 7)
342 || samba_private_attr_name(names
[i
]))
345 listp
= talloc(mem_ctx
, struct ea_list
);
350 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
356 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
359 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
361 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
362 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
363 (unsigned int)listp
->ea
.value
.length
));
365 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
369 /* Add on 4 for total length. */
370 if (*pea_total_len
) {
374 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
375 (unsigned int)*pea_total_len
));
380 /****************************************************************************
381 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
383 ****************************************************************************/
385 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
386 connection_struct
*conn
, struct ea_list
*ea_list
)
388 unsigned int ret_data_size
= 4;
391 SMB_ASSERT(total_data_size
>= 4);
393 if (!lp_ea_support(SNUM(conn
))) {
398 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
401 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
402 dos_namelen
= strlen(dos_ea_name
);
403 if (dos_namelen
> 255 || dos_namelen
== 0) {
406 if (ea_list
->ea
.value
.length
> 65535) {
409 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
413 /* We know we have room. */
414 SCVAL(p
,0,ea_list
->ea
.flags
);
415 SCVAL(p
,1,dos_namelen
);
416 SSVAL(p
,2,ea_list
->ea
.value
.length
);
417 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
418 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
420 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
421 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
424 ret_data_size
= PTR_DIFF(p
, pdata
);
425 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
426 SIVAL(pdata
,0,ret_data_size
);
427 return ret_data_size
;
430 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
432 unsigned int total_data_size
,
433 unsigned int *ret_data_size
,
434 connection_struct
*conn
,
435 struct ea_list
*ea_list
)
437 uint8_t *p
= (uint8_t *)pdata
;
438 uint8_t *last_start
= NULL
;
442 if (!lp_ea_support(SNUM(conn
))) {
443 return NT_STATUS_NO_EAS_ON_FILE
;
446 for (; ea_list
; ea_list
= ea_list
->next
) {
452 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
456 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
457 dos_namelen
= strlen(dos_ea_name
);
458 if (dos_namelen
> 255 || dos_namelen
== 0) {
459 return NT_STATUS_INTERNAL_ERROR
;
461 if (ea_list
->ea
.value
.length
> 65535) {
462 return NT_STATUS_INTERNAL_ERROR
;
465 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
468 size_t pad
= 4 - (this_size
% 4);
472 if (this_size
> total_data_size
) {
473 return NT_STATUS_INFO_LENGTH_MISMATCH
;
476 /* We know we have room. */
477 SIVAL(p
, 0x00, 0); /* next offset */
478 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
479 SCVAL(p
, 0x05, dos_namelen
);
480 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
481 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
482 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
484 total_data_size
-= this_size
;
488 *ret_data_size
= PTR_DIFF(p
, pdata
);
489 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
493 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
495 size_t total_ea_len
= 0;
496 TALLOC_CTX
*mem_ctx
= NULL
;
498 if (!lp_ea_support(SNUM(conn
))) {
501 mem_ctx
= talloc_tos();
502 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
506 /****************************************************************************
507 Ensure the EA name is case insensitive by matching any existing EA name.
508 ****************************************************************************/
510 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
513 TALLOC_CTX
*mem_ctx
= talloc_tos();
514 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
516 for (; ea_list
; ea_list
= ea_list
->next
) {
517 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
518 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
519 &unix_ea_name
[5], ea_list
->ea
.name
));
520 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
526 /****************************************************************************
527 Set or delete an extended attribute.
528 ****************************************************************************/
530 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
531 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
536 if (!lp_ea_support(SNUM(conn
))) {
537 return NT_STATUS_EAS_NOT_SUPPORTED
;
540 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
541 if (!NT_STATUS_IS_OK(status
)) {
545 /* For now setting EAs on streams isn't supported. */
546 fname
= smb_fname
->base_name
;
548 for (;ea_list
; ea_list
= ea_list
->next
) {
550 fstring unix_ea_name
;
552 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
553 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
555 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
557 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
559 if (samba_private_attr_name(unix_ea_name
)) {
560 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
561 return NT_STATUS_ACCESS_DENIED
;
564 if (ea_list
->ea
.value
.length
== 0) {
565 /* Remove the attribute. */
566 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
567 DEBUG(10,("set_ea: deleting ea name %s on "
568 "file %s by file descriptor.\n",
569 unix_ea_name
, fsp_str_dbg(fsp
)));
570 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
572 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
573 unix_ea_name
, fname
));
574 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
577 /* Removing a non existent attribute always succeeds. */
578 if (ret
== -1 && errno
== ENOATTR
) {
579 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
585 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
586 DEBUG(10,("set_ea: setting ea name %s on file "
587 "%s by file descriptor.\n",
588 unix_ea_name
, fsp_str_dbg(fsp
)));
589 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
590 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
592 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
593 unix_ea_name
, fname
));
594 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
595 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
601 if (errno
== ENOTSUP
) {
602 return NT_STATUS_EAS_NOT_SUPPORTED
;
605 return map_nt_error_from_unix(errno
);
611 /****************************************************************************
612 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
613 ****************************************************************************/
615 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
617 struct ea_list
*ea_list_head
= NULL
;
618 size_t converted_size
, offset
= 0;
620 while (offset
+ 2 < data_size
) {
621 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
622 unsigned int namelen
= CVAL(pdata
,offset
);
624 offset
++; /* Go past the namelen byte. */
626 /* integer wrap paranioa. */
627 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
628 (offset
> data_size
) || (namelen
> data_size
) ||
629 (offset
+ namelen
>= data_size
)) {
632 /* Ensure the name is null terminated. */
633 if (pdata
[offset
+ namelen
] != '\0') {
636 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
638 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
639 "failed: %s", strerror(errno
)));
645 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
646 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
647 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
653 /****************************************************************************
654 Read one EA list entry from the buffer.
655 ****************************************************************************/
657 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
659 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
661 unsigned int namelen
;
662 size_t converted_size
;
672 eal
->ea
.flags
= CVAL(pdata
,0);
673 namelen
= CVAL(pdata
,1);
674 val_len
= SVAL(pdata
,2);
676 if (4 + namelen
+ 1 + val_len
> data_size
) {
680 /* Ensure the name is null terminated. */
681 if (pdata
[namelen
+ 4] != '\0') {
684 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
685 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
692 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
693 if (!eal
->ea
.value
.data
) {
697 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
699 /* Ensure we're null terminated just in case we print the value. */
700 eal
->ea
.value
.data
[val_len
] = '\0';
701 /* But don't count the null. */
702 eal
->ea
.value
.length
--;
705 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
708 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
709 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
714 /****************************************************************************
715 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
716 ****************************************************************************/
718 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
720 struct ea_list
*ea_list_head
= NULL
;
722 size_t bytes_used
= 0;
724 while (offset
< data_size
) {
725 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
731 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
732 offset
+= bytes_used
;
738 /****************************************************************************
739 Count the total EA size needed.
740 ****************************************************************************/
742 static size_t ea_list_size(struct ea_list
*ealist
)
745 struct ea_list
*listp
;
748 for (listp
= ealist
; listp
; listp
= listp
->next
) {
749 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
750 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
752 /* Add on 4 for total length. */
760 /****************************************************************************
761 Return a union of EA's from a file list and a list of names.
762 The TALLOC context for the two lists *MUST* be identical as we steal
763 memory from one list to add to another. JRA.
764 ****************************************************************************/
766 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
768 struct ea_list
*nlistp
, *flistp
;
770 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
771 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
772 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
778 /* Copy the data from this entry. */
779 nlistp
->ea
.flags
= flistp
->ea
.flags
;
780 nlistp
->ea
.value
= flistp
->ea
.value
;
783 nlistp
->ea
.flags
= 0;
784 ZERO_STRUCT(nlistp
->ea
.value
);
788 *total_ea_len
= ea_list_size(name_list
);
792 /****************************************************************************
793 Send the required number of replies back.
794 We assume all fields other than the data fields are
795 set correctly for the type of call.
796 HACK ! Always assumes smb_setup field is zero.
797 ****************************************************************************/
799 void send_trans2_replies(connection_struct
*conn
,
800 struct smb_request
*req
,
807 /* As we are using a protocol > LANMAN1 then the max_send
808 variable must have been set in the sessetupX call.
809 This takes precedence over the max_xmit field in the
810 global struct. These different max_xmit variables should
811 be merged as this is now too confusing */
813 int data_to_send
= datasize
;
814 int params_to_send
= paramsize
;
816 const char *pp
= params
;
817 const char *pd
= pdata
;
818 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
819 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
820 int data_alignment_offset
= 0;
821 bool overflow
= False
;
822 struct smbd_server_connection
*sconn
= req
->sconn
;
823 int max_send
= sconn
->smb1
.sessions
.max_send
;
825 /* Modify the data_to_send and datasize and set the error if
826 we're trying to send more than max_data_bytes. We still send
827 the part of the packet(s) that fit. Strange, but needed
830 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
831 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
832 max_data_bytes
, datasize
));
833 datasize
= data_to_send
= max_data_bytes
;
837 /* If there genuinely are no parameters or data to send just send the empty packet */
839 if(params_to_send
== 0 && data_to_send
== 0) {
840 reply_outbuf(req
, 10, 0);
841 show_msg((char *)req
->outbuf
);
842 if (!srv_send_smb(sconn
,
845 IS_CONN_ENCRYPTED(conn
),
847 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
849 TALLOC_FREE(req
->outbuf
);
853 /* When sending params and data ensure that both are nicely aligned */
854 /* Only do this alignment when there is also data to send - else
855 can cause NT redirector problems. */
857 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
858 data_alignment_offset
= 4 - (params_to_send
% 4);
860 /* Space is bufsize minus Netbios over TCP header minus SMB header */
861 /* The alignment_offset is to align the param bytes on an even byte
862 boundary. NT 4.0 Beta needs this to work correctly. */
864 useable_space
= max_send
- (smb_size
867 + data_alignment_offset
);
869 if (useable_space
< 0) {
870 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
871 "= %d!!!", useable_space
));
872 exit_server_cleanly("send_trans2_replies: Not enough space");
875 while (params_to_send
|| data_to_send
) {
876 /* Calculate whether we will totally or partially fill this packet */
878 total_sent_thistime
= params_to_send
+ data_to_send
;
880 /* We can never send more than useable_space */
882 * Note that 'useable_space' does not include the alignment offsets,
883 * but we must include the alignment offsets in the calculation of
884 * the length of the data we send over the wire, as the alignment offsets
885 * are sent here. Fix from Marc_Jacobsen@hp.com.
888 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
890 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
891 + data_alignment_offset
);
893 /* Set total params and data to be sent */
894 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
895 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
897 /* Calculate how many parameters and data we can fit into
898 * this packet. Parameters get precedence
901 params_sent_thistime
= MIN(params_to_send
,useable_space
);
902 data_sent_thistime
= useable_space
- params_sent_thistime
;
903 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
905 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
907 /* smb_proff is the offset from the start of the SMB header to the
908 parameter bytes, however the first 4 bytes of outbuf are
909 the Netbios over TCP header. Thus use smb_base() to subtract
910 them from the calculation */
912 SSVAL(req
->outbuf
,smb_proff
,
913 ((smb_buf(req
->outbuf
)+alignment_offset
)
914 - smb_base(req
->outbuf
)));
916 if(params_sent_thistime
== 0)
917 SSVAL(req
->outbuf
,smb_prdisp
,0);
919 /* Absolute displacement of param bytes sent in this packet */
920 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
922 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
923 if(data_sent_thistime
== 0) {
924 SSVAL(req
->outbuf
,smb_droff
,0);
925 SSVAL(req
->outbuf
,smb_drdisp
, 0);
927 /* The offset of the data bytes is the offset of the
928 parameter bytes plus the number of parameters being sent this time */
929 SSVAL(req
->outbuf
, smb_droff
,
930 ((smb_buf(req
->outbuf
)+alignment_offset
)
931 - smb_base(req
->outbuf
))
932 + params_sent_thistime
+ data_alignment_offset
);
933 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
936 /* Initialize the padding for alignment */
938 if (alignment_offset
!= 0) {
939 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
942 /* Copy the param bytes into the packet */
944 if(params_sent_thistime
) {
945 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
946 params_sent_thistime
);
949 /* Copy in the data bytes */
950 if(data_sent_thistime
) {
951 if (data_alignment_offset
!= 0) {
952 memset((smb_buf(req
->outbuf
)+alignment_offset
+
953 params_sent_thistime
), 0,
954 data_alignment_offset
);
956 memcpy(smb_buf(req
->outbuf
)+alignment_offset
957 +params_sent_thistime
+data_alignment_offset
,
958 pd
,data_sent_thistime
);
961 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
962 params_sent_thistime
, data_sent_thistime
, useable_space
));
963 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
964 params_to_send
, data_to_send
, paramsize
, datasize
));
967 error_packet_set((char *)req
->outbuf
,
968 ERRDOS
,ERRbufferoverflow
,
969 STATUS_BUFFER_OVERFLOW
,
973 /* Send the packet */
974 show_msg((char *)req
->outbuf
);
975 if (!srv_send_smb(sconn
,
978 IS_CONN_ENCRYPTED(conn
),
980 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
982 TALLOC_FREE(req
->outbuf
);
984 pp
+= params_sent_thistime
;
985 pd
+= data_sent_thistime
;
987 params_to_send
-= params_sent_thistime
;
988 data_to_send
-= data_sent_thistime
;
991 if(params_to_send
< 0 || data_to_send
< 0) {
992 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
993 params_to_send
, data_to_send
));
1001 /****************************************************************************
1002 Reply to a TRANSACT2_OPEN.
1003 ****************************************************************************/
1005 static void call_trans2open(connection_struct
*conn
,
1006 struct smb_request
*req
,
1007 char **pparams
, int total_params
,
1008 char **ppdata
, int total_data
,
1009 unsigned int max_data_bytes
)
1011 struct smb_filename
*smb_fname
= NULL
;
1012 char *params
= *pparams
;
1013 char *pdata
= *ppdata
;
1016 bool oplock_request
;
1018 bool return_additional_info
;
1027 int fattr
=0,mtime
=0;
1028 SMB_INO_T inode
= 0;
1031 struct ea_list
*ea_list
= NULL
;
1036 uint32 create_disposition
;
1037 uint32 create_options
= 0;
1038 uint32_t private_flags
= 0;
1039 TALLOC_CTX
*ctx
= talloc_tos();
1042 * Ensure we have enough parameters to perform the operation.
1045 if (total_params
< 29) {
1046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1050 flags
= SVAL(params
, 0);
1051 deny_mode
= SVAL(params
, 2);
1052 open_attr
= SVAL(params
,6);
1053 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1054 if (oplock_request
) {
1055 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1059 return_additional_info
= BITSETW(params
,0);
1060 open_sattr
= SVAL(params
, 4);
1061 open_time
= make_unix_date3(params
+8);
1063 open_ofun
= SVAL(params
,12);
1064 open_size
= IVAL(params
,14);
1065 pname
= ¶ms
[28];
1068 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1072 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1073 total_params
- 28, STR_TERMINATE
,
1075 if (!NT_STATUS_IS_OK(status
)) {
1076 reply_nterror(req
, status
);
1080 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1081 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1082 (unsigned int)open_ofun
, open_size
));
1084 status
= filename_convert(ctx
,
1086 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1091 if (!NT_STATUS_IS_OK(status
)) {
1092 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1093 reply_botherror(req
,
1094 NT_STATUS_PATH_NOT_COVERED
,
1095 ERRSRV
, ERRbadpath
);
1098 reply_nterror(req
, status
);
1102 if (open_ofun
== 0) {
1103 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1107 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1109 &access_mask
, &share_mode
,
1110 &create_disposition
,
1113 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1117 /* Any data in this call is an EA list. */
1118 if (total_data
&& (total_data
!= 4)) {
1119 if (total_data
< 10) {
1120 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1124 if (IVAL(pdata
,0) > total_data
) {
1125 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1126 IVAL(pdata
,0), (unsigned int)total_data
));
1127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1131 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1134 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1138 if (!lp_ea_support(SNUM(conn
))) {
1139 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1144 status
= SMB_VFS_CREATE_FILE(
1147 0, /* root_dir_fid */
1148 smb_fname
, /* fname */
1149 access_mask
, /* access_mask */
1150 share_mode
, /* share_access */
1151 create_disposition
, /* create_disposition*/
1152 create_options
, /* create_options */
1153 open_attr
, /* file_attributes */
1154 oplock_request
, /* oplock_request */
1155 open_size
, /* allocation_size */
1158 ea_list
, /* ea_list */
1160 &smb_action
); /* psbuf */
1162 if (!NT_STATUS_IS_OK(status
)) {
1163 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1164 /* We have re-scheduled this call. */
1167 reply_openerror(req
, status
);
1171 size
= get_file_size_stat(&smb_fname
->st
);
1172 fattr
= dos_mode(conn
, smb_fname
);
1173 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1174 inode
= smb_fname
->st
.st_ex_ino
;
1175 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1176 close_file(req
, fsp
, ERROR_CLOSE
);
1177 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1181 /* Realloc the size of parameters and data we will return */
1182 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1183 if(*pparams
== NULL
) {
1184 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1189 SSVAL(params
,0,fsp
->fnum
);
1190 SSVAL(params
,2,fattr
);
1191 srv_put_dos_date2(params
,4, mtime
);
1192 SIVAL(params
,8, (uint32
)size
);
1193 SSVAL(params
,12,deny_mode
);
1194 SSVAL(params
,14,0); /* open_type - file or directory. */
1195 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1197 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1198 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1201 SSVAL(params
,18,smb_action
);
1204 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1206 SIVAL(params
,20,inode
);
1207 SSVAL(params
,24,0); /* Padding. */
1209 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1210 fsp
->fsp_name
->base_name
);
1211 SIVAL(params
, 26, ea_size
);
1213 SIVAL(params
, 26, 0);
1216 /* Send the required number of replies */
1217 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1219 TALLOC_FREE(smb_fname
);
1222 /*********************************************************
1223 Routine to check if a given string matches exactly.
1224 as a special case a mask of "." does NOT match. That
1225 is required for correct wildcard semantics
1226 Case can be significant or not.
1227 **********************************************************/
1229 static bool exact_match(bool has_wild
,
1230 bool case_sensitive
,
1234 if (mask
[0] == '.' && mask
[1] == 0) {
1242 if (case_sensitive
) {
1243 return strcmp(str
,mask
)==0;
1245 return strcasecmp_m(str
,mask
) == 0;
1249 /****************************************************************************
1250 Return the filetype for UNIX extensions.
1251 ****************************************************************************/
1253 static uint32
unix_filetype(mode_t mode
)
1256 return UNIX_TYPE_FILE
;
1257 else if(S_ISDIR(mode
))
1258 return UNIX_TYPE_DIR
;
1260 else if(S_ISLNK(mode
))
1261 return UNIX_TYPE_SYMLINK
;
1264 else if(S_ISCHR(mode
))
1265 return UNIX_TYPE_CHARDEV
;
1268 else if(S_ISBLK(mode
))
1269 return UNIX_TYPE_BLKDEV
;
1272 else if(S_ISFIFO(mode
))
1273 return UNIX_TYPE_FIFO
;
1276 else if(S_ISSOCK(mode
))
1277 return UNIX_TYPE_SOCKET
;
1280 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1281 return UNIX_TYPE_UNKNOWN
;
1284 /****************************************************************************
1285 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1286 ****************************************************************************/
1288 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1290 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1291 const SMB_STRUCT_STAT
*psbuf
,
1293 enum perm_type ptype
,
1298 if (perms
== SMB_MODE_NO_CHANGE
) {
1299 if (!VALID_STAT(*psbuf
)) {
1300 return NT_STATUS_INVALID_PARAMETER
;
1302 *ret_perms
= psbuf
->st_ex_mode
;
1303 return NT_STATUS_OK
;
1307 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1308 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1309 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1310 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1311 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1312 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1313 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1314 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1315 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1317 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1320 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1323 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1328 /* Apply mode mask */
1329 ret
&= lp_create_mask(SNUM(conn
));
1330 /* Add in force bits */
1331 ret
|= lp_force_create_mode(SNUM(conn
));
1334 ret
&= lp_dir_mask(SNUM(conn
));
1335 /* Add in force bits */
1336 ret
|= lp_force_dir_mode(SNUM(conn
));
1338 case PERM_EXISTING_FILE
:
1339 /* Apply mode mask */
1340 ret
&= lp_security_mask(SNUM(conn
));
1341 /* Add in force bits */
1342 ret
|= lp_force_security_mode(SNUM(conn
));
1344 case PERM_EXISTING_DIR
:
1345 /* Apply mode mask */
1346 ret
&= lp_dir_security_mask(SNUM(conn
));
1347 /* Add in force bits */
1348 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1353 return NT_STATUS_OK
;
1356 /****************************************************************************
1357 Needed to show the msdfs symlinks as directories. Modifies psbuf
1358 to be a directory if it's a msdfs link.
1359 ****************************************************************************/
1361 static bool check_msdfs_link(connection_struct
*conn
,
1362 const char *pathname
,
1363 SMB_STRUCT_STAT
*psbuf
)
1365 int saved_errno
= errno
;
1366 if(lp_host_msdfs() &&
1367 lp_msdfs_root(SNUM(conn
)) &&
1368 is_msdfs_link(conn
, pathname
, psbuf
)) {
1370 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1373 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1374 errno
= saved_errno
;
1377 errno
= saved_errno
;
1382 /****************************************************************************
1383 Get a level dependent lanman2 dir entry.
1384 ****************************************************************************/
1386 struct smbd_dirptr_lanman2_state
{
1387 connection_struct
*conn
;
1388 uint32_t info_level
;
1389 bool check_mangled_names
;
1391 bool got_exact_match
;
1394 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1400 struct smbd_dirptr_lanman2_state
*state
=
1401 (struct smbd_dirptr_lanman2_state
*)private_data
;
1403 char mangled_name
[13]; /* mangled 8.3 name. */
1407 /* Mangle fname if it's an illegal name. */
1408 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1409 ok
= name_to_8_3(dname
, mangled_name
,
1410 true, state
->conn
->params
);
1414 fname
= mangled_name
;
1419 got_match
= exact_match(state
->has_wild
,
1420 state
->conn
->case_sensitive
,
1422 state
->got_exact_match
= got_match
;
1424 got_match
= mask_match(fname
, mask
,
1425 state
->conn
->case_sensitive
);
1428 if(!got_match
&& state
->check_mangled_names
&&
1429 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1431 * It turns out that NT matches wildcards against
1432 * both long *and* short names. This may explain some
1433 * of the wildcard wierdness from old DOS clients
1434 * that some people have been seeing.... JRA.
1436 /* Force the mangling into 8.3. */
1437 ok
= name_to_8_3(fname
, mangled_name
,
1438 false, state
->conn
->params
);
1443 got_match
= exact_match(state
->has_wild
,
1444 state
->conn
->case_sensitive
,
1445 mangled_name
, mask
);
1446 state
->got_exact_match
= got_match
;
1448 got_match
= mask_match(mangled_name
, mask
,
1449 state
->conn
->case_sensitive
);
1457 *_fname
= talloc_strdup(ctx
, fname
);
1458 if (*_fname
== NULL
) {
1465 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1467 struct smb_filename
*smb_fname
,
1470 struct smbd_dirptr_lanman2_state
*state
=
1471 (struct smbd_dirptr_lanman2_state
*)private_data
;
1472 bool ms_dfs_link
= false;
1475 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1476 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1477 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1478 "Couldn't lstat [%s] (%s)\n",
1479 smb_fname_str_dbg(smb_fname
),
1483 } else if (!VALID_STAT(smb_fname
->st
) &&
1484 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1485 /* Needed to show the msdfs symlinks as
1488 ms_dfs_link
= check_msdfs_link(state
->conn
,
1489 smb_fname
->base_name
,
1492 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1493 "Couldn't stat [%s] (%s)\n",
1494 smb_fname_str_dbg(smb_fname
),
1501 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1503 mode
= dos_mode(state
->conn
, smb_fname
);
1510 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1511 connection_struct
*conn
,
1513 uint32_t info_level
,
1514 struct ea_list
*name_list
,
1515 bool check_mangled_names
,
1516 bool requires_resume_key
,
1519 const struct smb_filename
*smb_fname
,
1520 int space_remaining
,
1527 uint64_t *last_entry_off
)
1529 char *p
, *q
, *pdata
= *ppdata
;
1531 uint64_t file_size
= 0;
1532 uint64_t allocation_size
= 0;
1533 uint64_t file_index
= 0;
1535 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1536 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1538 char *last_entry_ptr
;
1543 *out_of_space
= false;
1545 ZERO_STRUCT(mdate_ts
);
1546 ZERO_STRUCT(adate_ts
);
1547 ZERO_STRUCT(create_date_ts
);
1548 ZERO_STRUCT(cdate_ts
);
1550 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1551 file_size
= get_file_size_stat(&smb_fname
->st
);
1553 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1555 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1557 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1558 adate_ts
= smb_fname
->st
.st_ex_atime
;
1559 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1560 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1562 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1563 dos_filetime_timespec(&create_date_ts
);
1564 dos_filetime_timespec(&mdate_ts
);
1565 dos_filetime_timespec(&adate_ts
);
1566 dos_filetime_timespec(&cdate_ts
);
1569 create_date
= convert_timespec_to_time_t(create_date_ts
);
1570 mdate
= convert_timespec_to_time_t(mdate_ts
);
1571 adate
= convert_timespec_to_time_t(adate_ts
);
1573 /* align the record */
1574 SMB_ASSERT(align
>= 1);
1576 off
= (int)PTR_DIFF(pdata
, base_data
);
1577 pad
= (off
+ (align
-1)) & ~(align
-1);
1580 if (pad
&& pad
> space_remaining
) {
1581 *out_of_space
= true;
1582 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1583 "for padding (wanted %u, had %d)\n",
1586 return false; /* Not finished - just out of space */
1590 /* initialize padding to 0 */
1592 memset(pdata
, 0, pad
);
1594 space_remaining
-= pad
;
1596 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1606 switch (info_level
) {
1607 case SMB_FIND_INFO_STANDARD
:
1608 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1609 if(requires_resume_key
) {
1613 srv_put_dos_date2(p
,0,create_date
);
1614 srv_put_dos_date2(p
,4,adate
);
1615 srv_put_dos_date2(p
,8,mdate
);
1616 SIVAL(p
,12,(uint32
)file_size
);
1617 SIVAL(p
,16,(uint32
)allocation_size
);
1621 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1622 p
+= ucs2_align(base_data
, p
, 0);
1624 len
= srvstr_push(base_data
, flags2
, p
,
1625 fname
, PTR_DIFF(end_data
, p
),
1627 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1629 SCVAL(nameptr
, -1, len
- 2);
1631 SCVAL(nameptr
, -1, 0);
1635 SCVAL(nameptr
, -1, len
- 1);
1637 SCVAL(nameptr
, -1, 0);
1643 case SMB_FIND_EA_SIZE
:
1644 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1645 if (requires_resume_key
) {
1649 srv_put_dos_date2(p
,0,create_date
);
1650 srv_put_dos_date2(p
,4,adate
);
1651 srv_put_dos_date2(p
,8,mdate
);
1652 SIVAL(p
,12,(uint32
)file_size
);
1653 SIVAL(p
,16,(uint32
)allocation_size
);
1656 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1657 smb_fname
->base_name
);
1658 SIVAL(p
,22,ea_size
); /* Extended attributes */
1662 len
= srvstr_push(base_data
, flags2
,
1663 p
, fname
, PTR_DIFF(end_data
, p
),
1664 STR_TERMINATE
| STR_NOALIGN
);
1665 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1678 SCVAL(nameptr
,0,len
);
1680 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1683 case SMB_FIND_EA_LIST
:
1685 struct ea_list
*file_list
= NULL
;
1688 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1692 if (requires_resume_key
) {
1696 srv_put_dos_date2(p
,0,create_date
);
1697 srv_put_dos_date2(p
,4,adate
);
1698 srv_put_dos_date2(p
,8,mdate
);
1699 SIVAL(p
,12,(uint32
)file_size
);
1700 SIVAL(p
,16,(uint32
)allocation_size
);
1702 p
+= 22; /* p now points to the EA area. */
1704 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1705 smb_fname
->base_name
,
1707 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1709 /* We need to determine if this entry will fit in the space available. */
1710 /* Max string size is 255 bytes. */
1711 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1712 *out_of_space
= true;
1713 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1714 "(wanted %u, had %d)\n",
1715 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1717 return False
; /* Not finished - just out of space */
1720 /* Push the ea_data followed by the name. */
1721 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1723 len
= srvstr_push(base_data
, flags2
,
1724 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1725 STR_TERMINATE
| STR_NOALIGN
);
1726 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1739 SCVAL(nameptr
,0,len
);
1741 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1745 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1746 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1747 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1749 SIVAL(p
,0,reskey
); p
+= 4;
1750 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1751 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1752 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1753 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1754 SOFF_T(p
,0,file_size
); p
+= 8;
1755 SOFF_T(p
,0,allocation_size
); p
+= 8;
1756 SIVAL(p
,0,mode
); p
+= 4;
1757 q
= p
; p
+= 4; /* q is placeholder for name length. */
1759 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1760 smb_fname
->base_name
);
1761 SIVAL(p
,0,ea_size
); /* Extended attributes */
1764 /* Clear the short name buffer. This is
1765 * IMPORTANT as not doing so will trigger
1766 * a Win2k client bug. JRA.
1768 if (!was_8_3
&& check_mangled_names
) {
1769 char mangled_name
[13]; /* mangled 8.3 name. */
1770 if (!name_to_8_3(fname
,mangled_name
,True
,
1772 /* Error - mangle failed ! */
1773 memset(mangled_name
,'\0',12);
1775 mangled_name
[12] = 0;
1776 len
= srvstr_push(base_data
, flags2
,
1777 p
+2, mangled_name
, 24,
1778 STR_UPPER
|STR_UNICODE
);
1780 memset(p
+ 2 + len
,'\0',24 - len
);
1787 len
= srvstr_push(base_data
, flags2
, p
,
1788 fname
, PTR_DIFF(end_data
, p
),
1789 STR_TERMINATE_ASCII
);
1793 len
= PTR_DIFF(p
, pdata
);
1794 pad
= (len
+ (align
-1)) & ~(align
-1);
1796 * offset to the next entry, the caller
1797 * will overwrite it for the last entry
1798 * that's why we always include the padding
1802 * set padding to zero
1805 memset(p
, 0, pad
- len
);
1812 case SMB_FIND_FILE_DIRECTORY_INFO
:
1813 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1815 SIVAL(p
,0,reskey
); p
+= 4;
1816 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1817 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1818 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1819 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1820 SOFF_T(p
,0,file_size
); p
+= 8;
1821 SOFF_T(p
,0,allocation_size
); p
+= 8;
1822 SIVAL(p
,0,mode
); p
+= 4;
1823 len
= srvstr_push(base_data
, flags2
,
1824 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1825 STR_TERMINATE_ASCII
);
1829 len
= PTR_DIFF(p
, pdata
);
1830 pad
= (len
+ (align
-1)) & ~(align
-1);
1832 * offset to the next entry, the caller
1833 * will overwrite it for the last entry
1834 * that's why we always include the padding
1838 * set padding to zero
1841 memset(p
, 0, pad
- len
);
1848 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1851 SIVAL(p
,0,reskey
); p
+= 4;
1852 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1853 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1854 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1855 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1856 SOFF_T(p
,0,file_size
); p
+= 8;
1857 SOFF_T(p
,0,allocation_size
); p
+= 8;
1858 SIVAL(p
,0,mode
); p
+= 4;
1859 q
= p
; p
+= 4; /* q is placeholder for name length. */
1861 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1862 smb_fname
->base_name
);
1863 SIVAL(p
,0,ea_size
); /* Extended attributes */
1866 len
= srvstr_push(base_data
, flags2
, p
,
1867 fname
, PTR_DIFF(end_data
, p
),
1868 STR_TERMINATE_ASCII
);
1872 len
= PTR_DIFF(p
, pdata
);
1873 pad
= (len
+ (align
-1)) & ~(align
-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1881 * set padding to zero
1884 memset(p
, 0, pad
- len
);
1891 case SMB_FIND_FILE_NAMES_INFO
:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1894 SIVAL(p
,0,reskey
); p
+= 4;
1896 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1897 acl on a dir (tridge) */
1898 len
= srvstr_push(base_data
, flags2
, p
,
1899 fname
, PTR_DIFF(end_data
, p
),
1900 STR_TERMINATE_ASCII
);
1904 len
= PTR_DIFF(p
, pdata
);
1905 pad
= (len
+ (align
-1)) & ~(align
-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1913 * set padding to zero
1916 memset(p
, 0, pad
- len
);
1923 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1926 SIVAL(p
,0,reskey
); p
+= 4;
1927 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1928 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1929 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1930 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1931 SOFF_T(p
,0,file_size
); p
+= 8;
1932 SOFF_T(p
,0,allocation_size
); p
+= 8;
1933 SIVAL(p
,0,mode
); p
+= 4;
1934 q
= p
; p
+= 4; /* q is placeholder for name length. */
1936 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1937 smb_fname
->base_name
);
1938 SIVAL(p
,0,ea_size
); /* Extended attributes */
1941 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1942 SBVAL(p
,0,file_index
); p
+= 8;
1943 len
= srvstr_push(base_data
, flags2
, p
,
1944 fname
, PTR_DIFF(end_data
, p
),
1945 STR_TERMINATE_ASCII
);
1949 len
= PTR_DIFF(p
, pdata
);
1950 pad
= (len
+ (align
-1)) & ~(align
-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1958 * set padding to zero
1961 memset(p
, 0, pad
- len
);
1968 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1969 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1970 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1972 SIVAL(p
,0,reskey
); p
+= 4;
1973 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1974 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1975 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1976 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1977 SOFF_T(p
,0,file_size
); p
+= 8;
1978 SOFF_T(p
,0,allocation_size
); p
+= 8;
1979 SIVAL(p
,0,mode
); p
+= 4;
1980 q
= p
; p
+= 4; /* q is placeholder for name length */
1982 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1983 smb_fname
->base_name
);
1984 SIVAL(p
,0,ea_size
); /* Extended attributes */
1987 /* Clear the short name buffer. This is
1988 * IMPORTANT as not doing so will trigger
1989 * a Win2k client bug. JRA.
1991 if (!was_8_3
&& check_mangled_names
) {
1992 char mangled_name
[13]; /* mangled 8.3 name. */
1993 if (!name_to_8_3(fname
,mangled_name
,True
,
1995 /* Error - mangle failed ! */
1996 memset(mangled_name
,'\0',12);
1998 mangled_name
[12] = 0;
1999 len
= srvstr_push(base_data
, flags2
,
2000 p
+2, mangled_name
, 24,
2001 STR_UPPER
|STR_UNICODE
);
2004 memset(p
+ 2 + len
,'\0',24 - len
);
2011 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2012 SBVAL(p
,0,file_index
); p
+= 8;
2013 len
= srvstr_push(base_data
, flags2
, p
,
2014 fname
, PTR_DIFF(end_data
, p
),
2015 STR_TERMINATE_ASCII
);
2019 len
= PTR_DIFF(p
, pdata
);
2020 pad
= (len
+ (align
-1)) & ~(align
-1);
2022 * offset to the next entry, the caller
2023 * will overwrite it for the last entry
2024 * that's why we always include the padding
2028 * set padding to zero
2031 memset(p
, 0, pad
- len
);
2038 /* CIFS UNIX Extension. */
2040 case SMB_FIND_FILE_UNIX
:
2041 case SMB_FIND_FILE_UNIX_INFO2
:
2043 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2045 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2047 if (info_level
== SMB_FIND_FILE_UNIX
) {
2048 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2049 p
= store_file_unix_basic(conn
, p
,
2050 NULL
, &smb_fname
->st
);
2051 len
= srvstr_push(base_data
, flags2
, p
,
2052 fname
, PTR_DIFF(end_data
, p
),
2055 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2056 p
= store_file_unix_basic_info2(conn
, p
,
2057 NULL
, &smb_fname
->st
);
2060 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2061 PTR_DIFF(end_data
, p
), 0);
2062 SIVAL(nameptr
, 0, len
);
2067 len
= PTR_DIFF(p
, pdata
);
2068 pad
= (len
+ (align
-1)) & ~(align
-1);
2070 * offset to the next entry, the caller
2071 * will overwrite it for the last entry
2072 * that's why we always include the padding
2076 * set padding to zero
2079 memset(p
, 0, pad
- len
);
2084 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2092 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2093 *out_of_space
= true;
2094 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2095 "(wanted %u, had %d)\n",
2096 (unsigned int)PTR_DIFF(p
,pdata
),
2098 return false; /* Not finished - just out of space */
2101 /* Setup the last entry pointer, as an offset from base_data */
2102 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2103 /* Advance the data pointer to the next slot */
2109 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2110 connection_struct
*conn
,
2111 struct dptr_struct
*dirptr
,
2113 const char *path_mask
,
2116 int requires_resume_key
,
2124 int space_remaining
,
2126 bool *got_exact_match
,
2127 int *_last_entry_off
,
2128 struct ea_list
*name_list
)
2131 const char *mask
= NULL
;
2132 long prev_dirpos
= 0;
2135 struct smb_filename
*smb_fname
= NULL
;
2136 struct smbd_dirptr_lanman2_state state
;
2138 uint64_t last_entry_off
= 0;
2142 state
.info_level
= info_level
;
2143 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2144 state
.has_wild
= dptr_has_wild(dirptr
);
2145 state
.got_exact_match
= false;
2147 *out_of_space
= false;
2148 *got_exact_match
= false;
2150 p
= strrchr_m(path_mask
,'/');
2161 ok
= smbd_dirptr_get_entry(ctx
,
2167 smbd_dirptr_lanman2_match_fn
,
2168 smbd_dirptr_lanman2_mode_fn
,
2178 *got_exact_match
= state
.got_exact_match
;
2180 ok
= smbd_marshall_dir_entry(ctx
,
2185 state
.check_mangled_names
,
2186 requires_resume_key
,
2199 TALLOC_FREE(smb_fname
);
2200 if (*out_of_space
) {
2201 dptr_SeekDir(dirptr
, prev_dirpos
);
2208 *_last_entry_off
= last_entry_off
;
2212 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2213 connection_struct
*conn
,
2214 struct dptr_struct
*dirptr
,
2216 const char *path_mask
,
2219 bool requires_resume_key
,
2225 int space_remaining
,
2227 bool *got_exact_match
,
2228 int *last_entry_off
,
2229 struct ea_list
*name_list
)
2232 const bool do_pad
= true;
2234 if (info_level
>= 1 && info_level
<= 3) {
2235 /* No alignment on earlier info levels. */
2239 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2240 path_mask
, dirtype
, info_level
,
2241 requires_resume_key
, dont_descend
, ask_sharemode
,
2243 ppdata
, base_data
, end_data
,
2245 out_of_space
, got_exact_match
,
2246 last_entry_off
, name_list
);
2249 /****************************************************************************
2250 Reply to a TRANS2_FINDFIRST.
2251 ****************************************************************************/
2253 static void call_trans2findfirst(connection_struct
*conn
,
2254 struct smb_request
*req
,
2255 char **pparams
, int total_params
,
2256 char **ppdata
, int total_data
,
2257 unsigned int max_data_bytes
)
2259 /* We must be careful here that we don't return more than the
2260 allowed number of data bytes. If this means returning fewer than
2261 maxentries then so be it. We assume that the redirector has
2262 enough room for the fixed number of parameter bytes it has
2264 struct smb_filename
*smb_dname
= NULL
;
2265 char *params
= *pparams
;
2266 char *pdata
= *ppdata
;
2270 uint16 findfirst_flags
;
2271 bool close_after_first
;
2273 bool requires_resume_key
;
2275 char *directory
= NULL
;
2278 int last_entry_off
=0;
2282 bool finished
= False
;
2283 bool dont_descend
= False
;
2284 bool out_of_space
= False
;
2285 int space_remaining
;
2286 bool mask_contains_wcard
= False
;
2287 struct ea_list
*ea_list
= NULL
;
2288 NTSTATUS ntstatus
= NT_STATUS_OK
;
2289 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2290 TALLOC_CTX
*ctx
= talloc_tos();
2291 struct dptr_struct
*dirptr
= NULL
;
2292 struct smbd_server_connection
*sconn
= req
->sconn
;
2293 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2294 bool backup_priv
= false;
2296 if (total_params
< 13) {
2297 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2301 dirtype
= SVAL(params
,0);
2302 maxentries
= SVAL(params
,2);
2303 findfirst_flags
= SVAL(params
,4);
2304 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2305 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2306 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2307 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2308 security_token_has_privilege(get_current_nttok(conn
),
2311 info_level
= SVAL(params
,6);
2313 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2314 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2315 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2317 info_level
, max_data_bytes
));
2320 /* W2K3 seems to treat zero as 1. */
2324 switch (info_level
) {
2325 case SMB_FIND_INFO_STANDARD
:
2326 case SMB_FIND_EA_SIZE
:
2327 case SMB_FIND_EA_LIST
:
2328 case SMB_FIND_FILE_DIRECTORY_INFO
:
2329 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2330 case SMB_FIND_FILE_NAMES_INFO
:
2331 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2332 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2333 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2335 case SMB_FIND_FILE_UNIX
:
2336 case SMB_FIND_FILE_UNIX_INFO2
:
2337 /* Always use filesystem for UNIX mtime query. */
2338 ask_sharemode
= false;
2339 if (!lp_unix_extensions()) {
2340 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2343 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2346 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2350 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2351 params
+12, total_params
- 12,
2352 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2353 if (!NT_STATUS_IS_OK(ntstatus
)) {
2354 reply_nterror(req
, ntstatus
);
2360 ntstatus
= filename_convert_with_privilege(ctx
,
2365 &mask_contains_wcard
,
2368 ntstatus
= filename_convert(ctx
, conn
,
2369 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2372 &mask_contains_wcard
,
2376 if (!NT_STATUS_IS_OK(ntstatus
)) {
2377 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2378 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2379 ERRSRV
, ERRbadpath
);
2382 reply_nterror(req
, ntstatus
);
2386 mask
= smb_dname
->original_lcomp
;
2388 directory
= smb_dname
->base_name
;
2390 p
= strrchr_m(directory
,'/');
2392 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2393 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2394 mask
= talloc_strdup(ctx
,"*");
2396 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2399 mask_contains_wcard
= True
;
2405 if (p
== NULL
|| p
== directory
) {
2406 /* Ensure we don't have a directory name of "". */
2407 directory
= talloc_strdup(talloc_tos(), ".");
2409 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2414 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2416 if (info_level
== SMB_FIND_EA_LIST
) {
2419 if (total_data
< 4) {
2420 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2424 ea_size
= IVAL(pdata
,0);
2425 if (ea_size
!= total_data
) {
2426 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2427 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2428 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2432 if (!lp_ea_support(SNUM(conn
))) {
2433 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2437 /* Pull out the list of names. */
2438 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2440 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2445 *ppdata
= (char *)SMB_REALLOC(
2446 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2447 if(*ppdata
== NULL
) {
2448 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2452 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2454 /* Realloc the params space */
2455 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2456 if (*pparams
== NULL
) {
2457 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2462 /* Save the wildcard match and attribs we are using on this directory -
2463 needed as lanman2 assumes these are being saved between calls */
2465 ntstatus
= dptr_create(conn
,
2473 mask_contains_wcard
,
2477 if (!NT_STATUS_IS_OK(ntstatus
)) {
2478 reply_nterror(req
, ntstatus
);
2483 /* Remember this in case we have
2484 to do a findnext. */
2485 dptr_set_priv(dirptr
);
2488 dptr_num
= dptr_dnum(dirptr
);
2489 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2491 /* Initialize per TRANS2_FIND_FIRST operation data */
2492 dptr_init_search_op(dirptr
);
2494 /* We don't need to check for VOL here as this is returned by
2495 a different TRANS2 call. */
2497 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2498 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2499 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2500 dont_descend
= True
;
2503 space_remaining
= max_data_bytes
;
2504 out_of_space
= False
;
2506 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2507 bool got_exact_match
= False
;
2509 /* this is a heuristic to avoid seeking the dirptr except when
2510 absolutely necessary. It allows for a filename of about 40 chars */
2511 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2512 out_of_space
= True
;
2515 finished
= !get_lanman2_dir_entry(ctx
,
2519 mask
,dirtype
,info_level
,
2520 requires_resume_key
,dont_descend
,
2523 space_remaining
, &out_of_space
,
2525 &last_entry_off
, ea_list
);
2528 if (finished
&& out_of_space
)
2531 if (!finished
&& !out_of_space
)
2535 * As an optimisation if we know we aren't looking
2536 * for a wildcard name (ie. the name matches the wildcard exactly)
2537 * then we can finish on any (first) match.
2538 * This speeds up large directory searches. JRA.
2544 /* Ensure space_remaining never goes -ve. */
2545 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2546 space_remaining
= 0;
2547 out_of_space
= true;
2549 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2553 /* Check if we can close the dirptr */
2554 if(close_after_first
|| (finished
&& close_if_end
)) {
2555 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2556 dptr_close(sconn
, &dptr_num
);
2560 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2561 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2562 * the protocol level is less than NT1. Tested with smbclient. JRA.
2563 * This should fix the OS/2 client bug #2335.
2566 if(numentries
== 0) {
2567 dptr_close(sconn
, &dptr_num
);
2568 if (get_Protocol() < PROTOCOL_NT1
) {
2569 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2572 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2573 ERRDOS
, ERRbadfile
);
2578 /* At this point pdata points to numentries directory entries. */
2580 /* Set up the return parameter block */
2581 SSVAL(params
,0,dptr_num
);
2582 SSVAL(params
,2,numentries
);
2583 SSVAL(params
,4,finished
);
2584 SSVAL(params
,6,0); /* Never an EA error */
2585 SSVAL(params
,8,last_entry_off
);
2587 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2590 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2591 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2593 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2597 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2598 smb_fn_name(req
->cmd
),
2599 mask
, directory
, dirtype
, numentries
) );
2602 * Force a name mangle here to ensure that the
2603 * mask as an 8.3 name is top of the mangled cache.
2604 * The reasons for this are subtle. Don't remove
2605 * this code unless you know what you are doing
2606 * (see PR#13758). JRA.
2609 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2610 char mangled_name
[13];
2611 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2619 TALLOC_FREE(smb_dname
);
2623 /****************************************************************************
2624 Reply to a TRANS2_FINDNEXT.
2625 ****************************************************************************/
2627 static void call_trans2findnext(connection_struct
*conn
,
2628 struct smb_request
*req
,
2629 char **pparams
, int total_params
,
2630 char **ppdata
, int total_data
,
2631 unsigned int max_data_bytes
)
2633 /* We must be careful here that we don't return more than the
2634 allowed number of data bytes. If this means returning fewer than
2635 maxentries then so be it. We assume that the redirector has
2636 enough room for the fixed number of parameter bytes it has
2638 char *params
= *pparams
;
2639 char *pdata
= *ppdata
;
2645 uint16 findnext_flags
;
2646 bool close_after_request
;
2648 bool requires_resume_key
;
2650 bool mask_contains_wcard
= False
;
2651 char *resume_name
= NULL
;
2652 const char *mask
= NULL
;
2653 const char *directory
= NULL
;
2657 int i
, last_entry_off
=0;
2658 bool finished
= False
;
2659 bool dont_descend
= False
;
2660 bool out_of_space
= False
;
2661 int space_remaining
;
2662 struct ea_list
*ea_list
= NULL
;
2663 NTSTATUS ntstatus
= NT_STATUS_OK
;
2664 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2665 TALLOC_CTX
*ctx
= talloc_tos();
2666 struct dptr_struct
*dirptr
;
2667 struct smbd_server_connection
*sconn
= req
->sconn
;
2668 bool backup_priv
= false;
2670 if (total_params
< 13) {
2671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2675 dptr_num
= SVAL(params
,0);
2676 maxentries
= SVAL(params
,2);
2677 info_level
= SVAL(params
,4);
2678 resume_key
= IVAL(params
,6);
2679 findnext_flags
= SVAL(params
,10);
2680 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2681 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2682 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2683 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2685 if (!continue_bit
) {
2686 /* We only need resume_name if continue_bit is zero. */
2687 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2689 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2690 &mask_contains_wcard
);
2691 if (!NT_STATUS_IS_OK(ntstatus
)) {
2692 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2693 complain (it thinks we're asking for the directory above the shared
2694 path or an invalid name). Catch this as the resume name is only compared, never used in
2695 a file access. JRA. */
2696 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2697 &resume_name
, params
+12,
2701 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2702 reply_nterror(req
, ntstatus
);
2708 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2709 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2710 resume_key = %d resume name = %s continue=%d level = %d\n",
2711 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2712 requires_resume_key
, resume_key
,
2713 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2716 /* W2K3 seems to treat zero as 1. */
2720 switch (info_level
) {
2721 case SMB_FIND_INFO_STANDARD
:
2722 case SMB_FIND_EA_SIZE
:
2723 case SMB_FIND_EA_LIST
:
2724 case SMB_FIND_FILE_DIRECTORY_INFO
:
2725 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2726 case SMB_FIND_FILE_NAMES_INFO
:
2727 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2728 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2729 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2731 case SMB_FIND_FILE_UNIX
:
2732 case SMB_FIND_FILE_UNIX_INFO2
:
2733 /* Always use filesystem for UNIX mtime query. */
2734 ask_sharemode
= false;
2735 if (!lp_unix_extensions()) {
2736 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2741 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2745 if (info_level
== SMB_FIND_EA_LIST
) {
2748 if (total_data
< 4) {
2749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2753 ea_size
= IVAL(pdata
,0);
2754 if (ea_size
!= total_data
) {
2755 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2756 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2757 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2761 if (!lp_ea_support(SNUM(conn
))) {
2762 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2766 /* Pull out the list of names. */
2767 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2774 *ppdata
= (char *)SMB_REALLOC(
2775 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2776 if(*ppdata
== NULL
) {
2777 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2782 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2784 /* Realloc the params space */
2785 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2786 if(*pparams
== NULL
) {
2787 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2793 /* Check that the dptr is valid */
2794 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2795 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2799 directory
= dptr_path(sconn
, dptr_num
);
2801 /* Get the wildcard mask from the dptr */
2802 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2803 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2804 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2808 /* Get the attr mask from the dptr */
2809 dirtype
= dptr_attr(sconn
, dptr_num
);
2811 backup_priv
= dptr_get_priv(dirptr
);
2813 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2814 "backup_priv = %d\n",
2815 dptr_num
, mask
, dirtype
,
2817 dptr_TellDir(dirptr
),
2820 /* Initialize per TRANS2_FIND_NEXT operation data */
2821 dptr_init_search_op(dirptr
);
2823 /* We don't need to check for VOL here as this is returned by
2824 a different TRANS2 call. */
2826 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2827 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2828 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2829 dont_descend
= True
;
2832 space_remaining
= max_data_bytes
;
2833 out_of_space
= False
;
2840 * Seek to the correct position. We no longer use the resume key but
2841 * depend on the last file name instead.
2844 if(!continue_bit
&& resume_name
&& *resume_name
) {
2847 long current_pos
= 0;
2849 * Remember, name_to_8_3 is called by
2850 * get_lanman2_dir_entry(), so the resume name
2851 * could be mangled. Ensure we check the unmangled name.
2854 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2855 char *new_resume_name
= NULL
;
2856 mangle_lookup_name_from_8_3(ctx
,
2860 if (new_resume_name
) {
2861 resume_name
= new_resume_name
;
2866 * Fix for NT redirector problem triggered by resume key indexes
2867 * changing between directory scans. We now return a resume key of 0
2868 * and instead look for the filename to continue from (also given
2869 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2870 * findfirst/findnext (as is usual) then the directory pointer
2871 * should already be at the correct place.
2874 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2875 } /* end if resume_name && !continue_bit */
2877 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2878 bool got_exact_match
= False
;
2880 /* this is a heuristic to avoid seeking the dirptr except when
2881 absolutely necessary. It allows for a filename of about 40 chars */
2882 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2883 out_of_space
= True
;
2886 finished
= !get_lanman2_dir_entry(ctx
,
2890 mask
,dirtype
,info_level
,
2891 requires_resume_key
,dont_descend
,
2894 space_remaining
, &out_of_space
,
2896 &last_entry_off
, ea_list
);
2899 if (finished
&& out_of_space
)
2902 if (!finished
&& !out_of_space
)
2906 * As an optimisation if we know we aren't looking
2907 * for a wildcard name (ie. the name matches the wildcard exactly)
2908 * then we can finish on any (first) match.
2909 * This speeds up large directory searches. JRA.
2915 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2918 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2919 smb_fn_name(req
->cmd
),
2920 mask
, directory
, dirtype
, numentries
) );
2922 /* Check if we can close the dirptr */
2923 if(close_after_request
|| (finished
&& close_if_end
)) {
2924 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2925 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2932 /* Set up the return parameter block */
2933 SSVAL(params
,0,numentries
);
2934 SSVAL(params
,2,finished
);
2935 SSVAL(params
,4,0); /* Never an EA error */
2936 SSVAL(params
,6,last_entry_off
);
2938 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2944 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2946 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2950 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2952 SMB_ASSERT(extended_info
!= NULL
);
2954 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2955 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2956 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2957 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2958 #ifdef SAMBA_VERSION_REVISION
2959 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2961 extended_info
->samba_subversion
= 0;
2962 #ifdef SAMBA_VERSION_RC_RELEASE
2963 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2965 #ifdef SAMBA_VERSION_PRE_RELEASE
2966 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2969 #ifdef SAMBA_VERSION_VENDOR_PATCH
2970 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2972 extended_info
->samba_gitcommitdate
= 0;
2973 #ifdef SAMBA_VERSION_COMMIT_TIME
2974 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2977 memset(extended_info
->samba_version_string
, 0,
2978 sizeof(extended_info
->samba_version_string
));
2980 snprintf (extended_info
->samba_version_string
,
2981 sizeof(extended_info
->samba_version_string
),
2982 "%s", samba_version_string());
2985 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2986 TALLOC_CTX
*mem_ctx
,
2987 uint16_t info_level
,
2989 unsigned int max_data_bytes
,
2993 char *pdata
, *end_data
;
2994 int data_len
= 0, len
;
2995 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2996 int snum
= SNUM(conn
);
2997 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
2998 uint32 additional_flags
= 0;
2999 struct smb_filename smb_fname_dot
;
3003 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3004 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3005 "info level (0x%x) on IPC$.\n",
3006 (unsigned int)info_level
));
3007 return NT_STATUS_ACCESS_DENIED
;
3011 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3013 ZERO_STRUCT(smb_fname_dot
);
3014 smb_fname_dot
.base_name
= discard_const_p(char, ".");
3016 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
3017 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3018 return map_nt_error_from_unix(errno
);
3021 st
= smb_fname_dot
.st
;
3023 *ppdata
= (char *)SMB_REALLOC(
3024 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3025 if (*ppdata
== NULL
) {
3026 return NT_STATUS_NO_MEMORY
;
3030 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3031 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3033 switch (info_level
) {
3034 case SMB_INFO_ALLOCATION
:
3036 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3038 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3039 return map_nt_error_from_unix(errno
);
3042 block_size
= lp_block_size(snum
);
3043 if (bsize
< block_size
) {
3044 uint64_t factor
= block_size
/bsize
;
3049 if (bsize
> block_size
) {
3050 uint64_t factor
= bsize
/block_size
;
3055 bytes_per_sector
= 512;
3056 sectors_per_unit
= bsize
/bytes_per_sector
;
3058 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3059 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3060 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3062 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3063 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3064 SIVAL(pdata
,l1_cUnit
,dsize
);
3065 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3066 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3070 case SMB_INFO_VOLUME
:
3071 /* Return volume name */
3073 * Add volume serial number - hash of a combination of
3074 * the called hostname and the service name.
3076 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3078 * Win2k3 and previous mess this up by sending a name length
3079 * one byte short. I believe only older clients (OS/2 Win9x) use
3080 * this call so try fixing this by adding a terminating null to
3081 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3085 pdata
+l2_vol_szVolLabel
, vname
,
3086 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3087 STR_NOALIGN
|STR_TERMINATE
);
3088 SCVAL(pdata
,l2_vol_cch
,len
);
3089 data_len
= l2_vol_szVolLabel
+ len
;
3090 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3091 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3095 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3096 case SMB_FS_ATTRIBUTE_INFORMATION
:
3098 additional_flags
= 0;
3099 #if defined(HAVE_SYS_QUOTAS)
3100 additional_flags
|= FILE_VOLUME_QUOTAS
;
3103 if(lp_nt_acl_support(SNUM(conn
))) {
3104 additional_flags
|= FILE_PERSISTENT_ACLS
;
3107 /* Capabilities are filled in at connection time through STATVFS call */
3108 additional_flags
|= conn
->fs_capabilities
;
3109 additional_flags
|= lp_parm_int(conn
->params
->service
,
3110 "share", "fake_fscaps",
3113 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3114 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3115 additional_flags
); /* FS ATTRIBUTES */
3117 SIVAL(pdata
,4,255); /* Max filename component length */
3118 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3119 and will think we can't do long filenames */
3120 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3121 PTR_DIFF(end_data
, pdata
+12),
3124 data_len
= 12 + len
;
3127 case SMB_QUERY_FS_LABEL_INFO
:
3128 case SMB_FS_LABEL_INFORMATION
:
3129 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3130 PTR_DIFF(end_data
, pdata
+4), 0);
3135 case SMB_QUERY_FS_VOLUME_INFO
:
3136 case SMB_FS_VOLUME_INFORMATION
:
3139 * Add volume serial number - hash of a combination of
3140 * the called hostname and the service name.
3142 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3143 (str_checksum(get_local_machine_name())<<16));
3145 /* Max label len is 32 characters. */
3146 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3147 PTR_DIFF(end_data
, pdata
+18),
3149 SIVAL(pdata
,12,len
);
3152 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3153 (int)strlen(vname
),vname
,
3154 lp_servicename(talloc_tos(), snum
)));
3157 case SMB_QUERY_FS_SIZE_INFO
:
3158 case SMB_FS_SIZE_INFORMATION
:
3160 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3162 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3163 return map_nt_error_from_unix(errno
);
3165 block_size
= lp_block_size(snum
);
3166 if (bsize
< block_size
) {
3167 uint64_t factor
= block_size
/bsize
;
3172 if (bsize
> block_size
) {
3173 uint64_t factor
= bsize
/block_size
;
3178 bytes_per_sector
= 512;
3179 sectors_per_unit
= bsize
/bytes_per_sector
;
3180 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3181 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3182 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3183 SBIG_UINT(pdata
,0,dsize
);
3184 SBIG_UINT(pdata
,8,dfree
);
3185 SIVAL(pdata
,16,sectors_per_unit
);
3186 SIVAL(pdata
,20,bytes_per_sector
);
3190 case SMB_FS_FULL_SIZE_INFORMATION
:
3192 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3194 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3195 return map_nt_error_from_unix(errno
);
3197 block_size
= lp_block_size(snum
);
3198 if (bsize
< block_size
) {
3199 uint64_t factor
= block_size
/bsize
;
3204 if (bsize
> block_size
) {
3205 uint64_t factor
= bsize
/block_size
;
3210 bytes_per_sector
= 512;
3211 sectors_per_unit
= bsize
/bytes_per_sector
;
3212 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3213 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3214 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3215 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3216 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3217 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3218 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3219 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3223 case SMB_QUERY_FS_DEVICE_INFO
:
3224 case SMB_FS_DEVICE_INFORMATION
:
3226 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3228 if (!CAN_WRITE(conn
)) {
3229 characteristics
|= FILE_READ_ONLY_DEVICE
;
3232 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3233 SIVAL(pdata
,4,characteristics
);
3237 #ifdef HAVE_SYS_QUOTAS
3238 case SMB_FS_QUOTA_INFORMATION
:
3240 * what we have to send --metze:
3242 * Unknown1: 24 NULL bytes
3243 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3244 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3245 * Quota Flags: 2 byte :
3246 * Unknown3: 6 NULL bytes
3250 * details for Quota Flags:
3252 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3253 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3254 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3255 * 0x0001 Enable Quotas: enable quota for this fs
3259 /* we need to fake up a fsp here,
3260 * because its not send in this call
3263 SMB_NTQUOTA_STRUCT quotas
;
3266 ZERO_STRUCT(quotas
);
3269 fsp
.fnum
= FNUM_FIELD_INVALID
;
3272 if (get_current_uid(conn
) != 0) {
3273 DEBUG(0,("set_user_quota: access_denied "
3274 "service [%s] user [%s]\n",
3275 lp_servicename(talloc_tos(), SNUM(conn
)),
3276 conn
->session_info
->unix_info
->unix_name
));
3277 return NT_STATUS_ACCESS_DENIED
;
3280 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3281 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3282 return map_nt_error_from_unix(errno
);
3287 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3288 lp_servicename(talloc_tos(), SNUM(conn
))));
3290 /* Unknown1 24 NULL bytes*/
3291 SBIG_UINT(pdata
,0,(uint64_t)0);
3292 SBIG_UINT(pdata
,8,(uint64_t)0);
3293 SBIG_UINT(pdata
,16,(uint64_t)0);
3295 /* Default Soft Quota 8 bytes */
3296 SBIG_UINT(pdata
,24,quotas
.softlim
);
3298 /* Default Hard Quota 8 bytes */
3299 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3301 /* Quota flag 2 bytes */
3302 SSVAL(pdata
,40,quotas
.qflags
);
3304 /* Unknown3 6 NULL bytes */
3310 #endif /* HAVE_SYS_QUOTAS */
3311 case SMB_FS_OBJECTID_INFORMATION
:
3313 unsigned char objid
[16];
3314 struct smb_extended_info extended_info
;
3315 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3316 samba_extended_info_version (&extended_info
);
3317 SIVAL(pdata
,16,extended_info
.samba_magic
);
3318 SIVAL(pdata
,20,extended_info
.samba_version
);
3319 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3320 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3321 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3327 * Query the version and capabilities of the CIFS UNIX extensions
3331 case SMB_QUERY_CIFS_UNIX_INFO
:
3333 bool large_write
= lp_min_receive_file_size() &&
3334 !srv_is_signing_active(conn
->sconn
);
3335 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3336 int encrypt_caps
= 0;
3338 if (!lp_unix_extensions()) {
3339 return NT_STATUS_INVALID_LEVEL
;
3342 switch (conn
->encrypt_level
) {
3348 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3351 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3352 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3353 large_write
= false;
3359 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3360 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3362 /* We have POSIX ACLs, pathname, encryption,
3363 * large read/write, and locking capability. */
3365 SBIG_UINT(pdata
,4,((uint64_t)(
3366 CIFS_UNIX_POSIX_ACLS_CAP
|
3367 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3368 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3369 CIFS_UNIX_EXTATTR_CAP
|
3370 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3372 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3374 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3378 case SMB_QUERY_POSIX_FS_INFO
:
3381 vfs_statvfs_struct svfs
;
3383 if (!lp_unix_extensions()) {
3384 return NT_STATUS_INVALID_LEVEL
;
3387 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3391 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3392 SIVAL(pdata
,4,svfs
.BlockSize
);
3393 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3394 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3395 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3396 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3397 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3398 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3399 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3401 } else if (rc
== EOPNOTSUPP
) {
3402 return NT_STATUS_INVALID_LEVEL
;
3403 #endif /* EOPNOTSUPP */
3405 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3406 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3411 case SMB_QUERY_POSIX_WHOAMI
:
3417 if (!lp_unix_extensions()) {
3418 return NT_STATUS_INVALID_LEVEL
;
3421 if (max_data_bytes
< 40) {
3422 return NT_STATUS_BUFFER_TOO_SMALL
;
3425 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3426 flags
|= SMB_WHOAMI_GUEST
;
3429 /* NOTE: 8 bytes for UID/GID, irrespective of native
3430 * platform size. This matches
3431 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3433 data_len
= 4 /* flags */
3440 + 4 /* pad/reserved */
3441 + (conn
->session_info
->unix_token
->ngroups
* 8)
3443 + (conn
->session_info
->security_token
->num_sids
*
3447 SIVAL(pdata
, 0, flags
);
3448 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3450 (uint64_t)conn
->session_info
->unix_token
->uid
);
3451 SBIG_UINT(pdata
, 16,
3452 (uint64_t)conn
->session_info
->unix_token
->gid
);
3455 if (data_len
>= max_data_bytes
) {
3456 /* Potential overflow, skip the GIDs and SIDs. */
3458 SIVAL(pdata
, 24, 0); /* num_groups */
3459 SIVAL(pdata
, 28, 0); /* num_sids */
3460 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3461 SIVAL(pdata
, 36, 0); /* reserved */
3467 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3468 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3470 /* We walk the SID list twice, but this call is fairly
3471 * infrequent, and I don't expect that it's performance
3472 * sensitive -- jpeach
3474 for (i
= 0, sid_bytes
= 0;
3475 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3476 sid_bytes
+= ndr_size_dom_sid(
3477 &conn
->session_info
->security_token
->sids
[i
],
3481 /* SID list byte count */
3482 SIVAL(pdata
, 32, sid_bytes
);
3484 /* 4 bytes pad/reserved - must be zero */
3485 SIVAL(pdata
, 36, 0);
3489 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3490 SBIG_UINT(pdata
, data_len
,
3491 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3497 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3498 int sid_len
= ndr_size_dom_sid(
3499 &conn
->session_info
->security_token
->sids
[i
],
3502 sid_linearize(pdata
+ data_len
, sid_len
,
3503 &conn
->session_info
->security_token
->sids
[i
]);
3504 data_len
+= sid_len
;
3510 case SMB_MAC_QUERY_FS_INFO
:
3512 * Thursby MAC extension... ONLY on NTFS filesystems
3513 * once we do streams then we don't need this
3515 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3517 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3522 return NT_STATUS_INVALID_LEVEL
;
3525 *ret_data_len
= data_len
;
3526 return NT_STATUS_OK
;
3529 /****************************************************************************
3530 Reply to a TRANS2_QFSINFO (query filesystem info).
3531 ****************************************************************************/
3533 static void call_trans2qfsinfo(connection_struct
*conn
,
3534 struct smb_request
*req
,
3535 char **pparams
, int total_params
,
3536 char **ppdata
, int total_data
,
3537 unsigned int max_data_bytes
)
3539 char *params
= *pparams
;
3540 uint16_t info_level
;
3544 if (total_params
< 2) {
3545 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3549 info_level
= SVAL(params
,0);
3551 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3552 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3553 DEBUG(0,("call_trans2qfsinfo: encryption required "
3554 "and info level 0x%x sent.\n",
3555 (unsigned int)info_level
));
3556 exit_server_cleanly("encryption required "
3562 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3564 status
= smbd_do_qfsinfo(conn
, req
,
3569 if (!NT_STATUS_IS_OK(status
)) {
3570 reply_nterror(req
, status
);
3574 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3577 DEBUG( 4, ( "%s info_level = %d\n",
3578 smb_fn_name(req
->cmd
), info_level
) );
3583 /****************************************************************************
3584 Reply to a TRANS2_SETFSINFO (set filesystem info).
3585 ****************************************************************************/
3587 static void call_trans2setfsinfo(connection_struct
*conn
,
3588 struct smb_request
*req
,
3589 char **pparams
, int total_params
,
3590 char **ppdata
, int total_data
,
3591 unsigned int max_data_bytes
)
3593 struct smbd_server_connection
*sconn
= req
->sconn
;
3594 char *pdata
= *ppdata
;
3595 char *params
= *pparams
;
3598 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3599 lp_servicename(talloc_tos(), SNUM(conn
))));
3602 if (total_params
< 4) {
3603 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3605 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3609 info_level
= SVAL(params
,2);
3612 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3613 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3614 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3615 "info level (0x%x) on IPC$.\n",
3616 (unsigned int)info_level
));
3617 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3622 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3623 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3624 DEBUG(0,("call_trans2setfsinfo: encryption required "
3625 "and info level 0x%x sent.\n",
3626 (unsigned int)info_level
));
3627 exit_server_cleanly("encryption required "
3633 switch(info_level
) {
3634 case SMB_SET_CIFS_UNIX_INFO
:
3635 if (!lp_unix_extensions()) {
3636 DEBUG(2,("call_trans2setfsinfo: "
3637 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3638 "unix extensions off\n"));
3640 NT_STATUS_INVALID_LEVEL
);
3644 /* There should be 12 bytes of capabilities set. */
3645 if (total_data
< 12) {
3648 NT_STATUS_INVALID_PARAMETER
);
3651 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3652 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3653 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3654 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3655 /* Just print these values for now. */
3656 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3657 "major = %u, minor = %u cap_low = 0x%x, "
3659 (unsigned int)sconn
->
3660 smb1
.unix_info
.client_major
,
3661 (unsigned int)sconn
->
3662 smb1
.unix_info
.client_minor
,
3663 (unsigned int)sconn
->
3664 smb1
.unix_info
.client_cap_low
,
3665 (unsigned int)sconn
->
3666 smb1
.unix_info
.client_cap_high
));
3668 /* Here is where we must switch to posix pathname processing... */
3669 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3670 lp_set_posix_pathnames();
3671 mangle_change_to_posix();
3674 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3675 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3676 /* Client that knows how to do posix locks,
3677 * but not posix open/mkdir operations. Set a
3678 * default type for read/write checks. */
3680 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3685 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3688 size_t param_len
= 0;
3689 size_t data_len
= total_data
;
3691 if (!lp_unix_extensions()) {
3694 NT_STATUS_INVALID_LEVEL
);
3698 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3701 NT_STATUS_NOT_SUPPORTED
);
3705 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3706 DEBUG( 2,("call_trans2setfsinfo: "
3707 "request transport encryption disabled"
3708 "with 'fork echo handler = yes'\n"));
3711 NT_STATUS_NOT_SUPPORTED
);
3715 DEBUG( 4,("call_trans2setfsinfo: "
3716 "request transport encryption.\n"));
3718 status
= srv_request_encryption_setup(conn
,
3719 (unsigned char **)ppdata
,
3721 (unsigned char **)pparams
,
3724 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3725 !NT_STATUS_IS_OK(status
)) {
3726 reply_nterror(req
, status
);
3730 send_trans2_replies(conn
, req
,
3737 if (NT_STATUS_IS_OK(status
)) {
3738 /* Server-side transport
3739 * encryption is now *on*. */
3740 status
= srv_encryption_start(conn
);
3741 if (!NT_STATUS_IS_OK(status
)) {
3742 char *reason
= talloc_asprintf(talloc_tos(),
3743 "Failure in setting "
3744 "up encrypted transport: %s",
3746 exit_server_cleanly(reason
);
3752 case SMB_FS_QUOTA_INFORMATION
:
3754 files_struct
*fsp
= NULL
;
3755 SMB_NTQUOTA_STRUCT quotas
;
3757 ZERO_STRUCT(quotas
);
3760 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3761 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3762 lp_servicename(talloc_tos(), SNUM(conn
)),
3763 conn
->session_info
->unix_info
->unix_name
));
3764 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3768 /* note: normaly there're 48 bytes,
3769 * but we didn't use the last 6 bytes for now
3772 fsp
= file_fsp(req
, SVAL(params
,0));
3774 if (!check_fsp_ntquota_handle(conn
, req
,
3776 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3778 req
, NT_STATUS_INVALID_HANDLE
);
3782 if (total_data
< 42) {
3783 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3787 NT_STATUS_INVALID_PARAMETER
);
3791 /* unknown_1 24 NULL bytes in pdata*/
3793 /* the soft quotas 8 bytes (uint64_t)*/
3794 quotas
.softlim
= BVAL(pdata
,24);
3796 /* the hard quotas 8 bytes (uint64_t)*/
3797 quotas
.hardlim
= BVAL(pdata
,32);
3799 /* quota_flags 2 bytes **/
3800 quotas
.qflags
= SVAL(pdata
,40);
3802 /* unknown_2 6 NULL bytes follow*/
3804 /* now set the quotas */
3805 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3806 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3807 reply_nterror(req
, map_nt_error_from_unix(errno
));
3814 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3816 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3822 * sending this reply works fine,
3823 * but I'm not sure it's the same
3824 * like windows do...
3827 reply_outbuf(req
, 10, 0);
3830 #if defined(HAVE_POSIX_ACLS)
3831 /****************************************************************************
3832 Utility function to count the number of entries in a POSIX acl.
3833 ****************************************************************************/
3835 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3837 unsigned int ace_count
= 0;
3838 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3839 SMB_ACL_ENTRY_T entry
;
3841 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3843 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3844 entry_id
= SMB_ACL_NEXT_ENTRY
;
3851 /****************************************************************************
3852 Utility function to marshall a POSIX acl into wire format.
3853 ****************************************************************************/
3855 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3857 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3858 SMB_ACL_ENTRY_T entry
;
3860 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3861 SMB_ACL_TAG_T tagtype
;
3862 SMB_ACL_PERMSET_T permset
;
3863 unsigned char perms
= 0;
3864 unsigned int own_grp
;
3867 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3868 entry_id
= SMB_ACL_NEXT_ENTRY
;
3871 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3876 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3877 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3881 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3882 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3883 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3885 SCVAL(pdata
,1,perms
);
3888 case SMB_ACL_USER_OBJ
:
3889 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3890 own_grp
= (unsigned int)pst
->st_ex_uid
;
3891 SIVAL(pdata
,2,own_grp
);
3896 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3898 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3901 own_grp
= (unsigned int)*puid
;
3902 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3903 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3904 SIVAL(pdata
,2,own_grp
);
3908 case SMB_ACL_GROUP_OBJ
:
3909 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3910 own_grp
= (unsigned int)pst
->st_ex_gid
;
3911 SIVAL(pdata
,2,own_grp
);
3916 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3921 own_grp
= (unsigned int)*pgid
;
3922 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3923 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3924 SIVAL(pdata
,2,own_grp
);
3929 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3930 SIVAL(pdata
,2,0xFFFFFFFF);
3931 SIVAL(pdata
,6,0xFFFFFFFF);
3934 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3935 SIVAL(pdata
,2,0xFFFFFFFF);
3936 SIVAL(pdata
,6,0xFFFFFFFF);
3939 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3942 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3949 /****************************************************************************
3950 Store the FILE_UNIX_BASIC info.
3951 ****************************************************************************/
3953 static char *store_file_unix_basic(connection_struct
*conn
,
3956 const SMB_STRUCT_STAT
*psbuf
)
3958 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3961 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3962 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3964 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3967 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3970 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3971 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3972 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3975 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3979 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3983 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3986 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
3987 devno
= psbuf
->st_ex_rdev
;
3989 devno
= psbuf
->st_ex_dev
;
3992 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
3996 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4000 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4003 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4007 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4014 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4015 * the chflags(2) (or equivalent) flags.
4017 * XXX: this really should be behind the VFS interface. To do this, we would
4018 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4019 * Each VFS module could then implement its own mapping as appropriate for the
4020 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4022 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4026 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4030 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4034 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4038 { UF_HIDDEN
, EXT_HIDDEN
},
4041 /* Do not remove. We need to guarantee that this array has at least one
4042 * entry to build on HP-UX.
4048 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4049 uint32
*smb_fflags
, uint32
*smb_fmask
)
4053 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4054 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4055 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4056 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4061 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4062 const uint32 smb_fflags
,
4063 const uint32 smb_fmask
,
4066 uint32 max_fmask
= 0;
4069 *stat_fflags
= psbuf
->st_ex_flags
;
4071 /* For each flags requested in smb_fmask, check the state of the
4072 * corresponding flag in smb_fflags and set or clear the matching
4076 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4077 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4078 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4079 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4080 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4082 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4087 /* If smb_fmask is asking to set any bits that are not supported by
4088 * our flag mappings, we should fail.
4090 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4098 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4099 * of file flags and birth (create) time.
4101 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4104 const SMB_STRUCT_STAT
*psbuf
)
4106 uint32 file_flags
= 0;
4107 uint32 flags_mask
= 0;
4109 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4111 /* Create (birth) time 64 bit */
4112 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4115 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4116 SIVAL(pdata
, 0, file_flags
); /* flags */
4117 SIVAL(pdata
, 4, flags_mask
); /* mask */
4123 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4124 const struct stream_struct
*streams
,
4126 unsigned int max_data_bytes
,
4127 unsigned int *data_size
)
4130 unsigned int ofs
= 0;
4132 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4133 unsigned int next_offset
;
4135 smb_ucs2_t
*namebuf
;
4137 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4138 streams
[i
].name
, &namelen
) ||
4141 return NT_STATUS_INVALID_PARAMETER
;
4145 * name_buf is now null-terminated, we need to marshall as not
4151 SIVAL(data
, ofs
+4, namelen
);
4152 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4153 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4154 memcpy(data
+ofs
+24, namebuf
, namelen
);
4155 TALLOC_FREE(namebuf
);
4157 next_offset
= ofs
+ 24 + namelen
;
4159 if (i
== num_streams
-1) {
4160 SIVAL(data
, ofs
, 0);
4163 unsigned int align
= ndr_align_size(next_offset
, 8);
4165 memset(data
+next_offset
, 0, align
);
4166 next_offset
+= align
;
4168 SIVAL(data
, ofs
, next_offset
- ofs
);
4177 return NT_STATUS_OK
;
4180 /****************************************************************************
4181 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4182 ****************************************************************************/
4184 static void call_trans2qpipeinfo(connection_struct
*conn
,
4185 struct smb_request
*req
,
4186 unsigned int tran_call
,
4187 char **pparams
, int total_params
,
4188 char **ppdata
, int total_data
,
4189 unsigned int max_data_bytes
)
4191 char *params
= *pparams
;
4192 char *pdata
= *ppdata
;
4193 unsigned int data_size
= 0;
4194 unsigned int param_size
= 2;
4199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4203 if (total_params
< 4) {
4204 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4208 fsp
= file_fsp(req
, SVAL(params
,0));
4209 if (!fsp_is_np(fsp
)) {
4210 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4214 info_level
= SVAL(params
,2);
4216 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4217 if (*pparams
== NULL
) {
4218 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4223 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4224 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4225 if (*ppdata
== NULL
) {
4226 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4231 switch (info_level
) {
4232 case SMB_FILE_STANDARD_INFORMATION
:
4234 SOFF_T(pdata
,0,4096LL);
4241 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4245 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4251 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4252 TALLOC_CTX
*mem_ctx
,
4253 uint16_t info_level
,
4255 struct smb_filename
*smb_fname
,
4256 bool delete_pending
,
4257 struct timespec write_time_ts
,
4258 struct ea_list
*ea_list
,
4259 int lock_data_count
,
4262 unsigned int max_data_bytes
,
4264 unsigned int *pdata_size
)
4266 char *pdata
= *ppdata
;
4267 char *dstart
, *dend
;
4268 unsigned int data_size
;
4269 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4270 time_t create_time
, mtime
, atime
, c_time
;
4271 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4278 uint64_t file_size
= 0;
4280 uint64_t allocation_size
= 0;
4281 uint64_t file_index
= 0;
4282 uint32_t access_mask
= 0;
4284 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4285 return NT_STATUS_INVALID_LEVEL
;
4288 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4289 smb_fname_str_dbg(smb_fname
),
4291 info_level
, max_data_bytes
));
4293 mode
= dos_mode(conn
, smb_fname
);
4294 nlink
= psbuf
->st_ex_nlink
;
4296 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4300 if ((nlink
> 0) && delete_pending
) {
4304 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4305 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4306 if (*ppdata
== NULL
) {
4307 return NT_STATUS_NO_MEMORY
;
4311 dend
= dstart
+ data_size
- 1;
4313 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4314 update_stat_ex_mtime(psbuf
, write_time_ts
);
4317 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4318 mtime_ts
= psbuf
->st_ex_mtime
;
4319 atime_ts
= psbuf
->st_ex_atime
;
4320 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4322 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4323 dos_filetime_timespec(&create_time_ts
);
4324 dos_filetime_timespec(&mtime_ts
);
4325 dos_filetime_timespec(&atime_ts
);
4326 dos_filetime_timespec(&ctime_ts
);
4329 create_time
= convert_timespec_to_time_t(create_time_ts
);
4330 mtime
= convert_timespec_to_time_t(mtime_ts
);
4331 atime
= convert_timespec_to_time_t(atime_ts
);
4332 c_time
= convert_timespec_to_time_t(ctime_ts
);
4334 p
= strrchr_m(smb_fname
->base_name
,'/');
4336 base_name
= smb_fname
->base_name
;
4340 /* NT expects the name to be in an exact form of the *full*
4341 filename. See the trans2 torture test */
4342 if (ISDOT(base_name
)) {
4343 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4345 return NT_STATUS_NO_MEMORY
;
4348 dos_fname
= talloc_asprintf(mem_ctx
,
4350 smb_fname
->base_name
);
4352 return NT_STATUS_NO_MEMORY
;
4354 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4355 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4356 smb_fname
->stream_name
);
4358 return NT_STATUS_NO_MEMORY
;
4362 string_replace(dos_fname
, '/', '\\');
4365 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4368 /* Do we have this path open ? */
4370 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4371 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4372 if (fsp1
&& fsp1
->initial_allocation_size
) {
4373 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4377 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4378 file_size
= get_file_size_stat(psbuf
);
4382 pos
= fsp
->fh
->position_information
;
4386 access_mask
= fsp
->access_mask
;
4388 /* GENERIC_EXECUTE mapping from Windows */
4389 access_mask
= 0x12019F;
4392 /* This should be an index number - looks like
4395 I think this causes us to fail the IFSKIT
4396 BasicFileInformationTest. -tpot */
4397 file_index
= get_FileIndex(conn
, psbuf
);
4399 switch (info_level
) {
4400 case SMB_INFO_STANDARD
:
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4403 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4404 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4405 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4406 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4407 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4408 SSVAL(pdata
,l1_attrFile
,mode
);
4411 case SMB_INFO_QUERY_EA_SIZE
:
4413 unsigned int ea_size
=
4414 estimate_ea_size(conn
, fsp
,
4415 smb_fname
->base_name
);
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4418 srv_put_dos_date2(pdata
,0,create_time
);
4419 srv_put_dos_date2(pdata
,4,atime
);
4420 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4421 SIVAL(pdata
,12,(uint32
)file_size
);
4422 SIVAL(pdata
,16,(uint32
)allocation_size
);
4423 SSVAL(pdata
,20,mode
);
4424 SIVAL(pdata
,22,ea_size
);
4428 case SMB_INFO_IS_NAME_VALID
:
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4431 /* os/2 needs this ? really ?*/
4432 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4434 /* This is only reached for qpathinfo */
4438 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4440 size_t total_ea_len
= 0;
4441 struct ea_list
*ea_file_list
= NULL
;
4443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4446 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4447 smb_fname
->base_name
,
4449 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4451 if (!ea_list
|| (total_ea_len
> data_size
)) {
4453 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4457 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4461 case SMB_INFO_QUERY_ALL_EAS
:
4463 /* We have data_size bytes to put EA's into. */
4464 size_t total_ea_len
= 0;
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4468 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4469 smb_fname
->base_name
,
4471 if (!ea_list
|| (total_ea_len
> data_size
)) {
4473 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4477 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4481 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4483 /* This is FileFullEaInformation - 0xF which maps to
4484 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4486 /* We have data_size bytes to put EA's into. */
4487 size_t total_ea_len
= 0;
4488 struct ea_list
*ea_file_list
= NULL
;
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4492 /*TODO: add filtering and index handling */
4495 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4496 smb_fname
->base_name
,
4498 if (!ea_file_list
) {
4499 return NT_STATUS_NO_EAS_ON_FILE
;
4502 status
= fill_ea_chained_buffer(mem_ctx
,
4506 conn
, ea_file_list
);
4507 if (!NT_STATUS_IS_OK(status
)) {
4513 case SMB_FILE_BASIC_INFORMATION
:
4514 case SMB_QUERY_FILE_BASIC_INFO
:
4516 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4518 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4524 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4525 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4526 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4527 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4528 SIVAL(pdata
,32,mode
);
4530 DEBUG(5,("SMB_QFBI - "));
4531 DEBUG(5,("create: %s ", ctime(&create_time
)));
4532 DEBUG(5,("access: %s ", ctime(&atime
)));
4533 DEBUG(5,("write: %s ", ctime(&mtime
)));
4534 DEBUG(5,("change: %s ", ctime(&c_time
)));
4535 DEBUG(5,("mode: %x\n", mode
));
4538 case SMB_FILE_STANDARD_INFORMATION
:
4539 case SMB_QUERY_FILE_STANDARD_INFO
:
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4543 SOFF_T(pdata
,0,allocation_size
);
4544 SOFF_T(pdata
,8,file_size
);
4545 SIVAL(pdata
,16,nlink
);
4546 SCVAL(pdata
,20,delete_pending
?1:0);
4547 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4548 SSVAL(pdata
,22,0); /* Padding. */
4551 case SMB_FILE_EA_INFORMATION
:
4552 case SMB_QUERY_FILE_EA_INFO
:
4554 unsigned int ea_size
=
4555 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4558 SIVAL(pdata
,0,ea_size
);
4562 /* Get the 8.3 name - used if NT SMB was negotiated. */
4563 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4564 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4567 char mangled_name
[13];
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4569 if (!name_to_8_3(base_name
,mangled_name
,
4570 True
,conn
->params
)) {
4571 return NT_STATUS_NO_MEMORY
;
4573 len
= srvstr_push(dstart
, flags2
,
4574 pdata
+4, mangled_name
,
4575 PTR_DIFF(dend
, pdata
+4),
4577 data_size
= 4 + len
;
4582 case SMB_QUERY_FILE_NAME_INFO
:
4586 this must be *exactly* right for ACLs on mapped drives to work
4588 len
= srvstr_push(dstart
, flags2
,
4590 PTR_DIFF(dend
, pdata
+4),
4592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4593 data_size
= 4 + len
;
4598 case SMB_FILE_ALLOCATION_INFORMATION
:
4599 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4602 SOFF_T(pdata
,0,allocation_size
);
4605 case SMB_FILE_END_OF_FILE_INFORMATION
:
4606 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4609 SOFF_T(pdata
,0,file_size
);
4612 case SMB_QUERY_FILE_ALL_INFO
:
4613 case SMB_FILE_ALL_INFORMATION
:
4616 unsigned int ea_size
=
4617 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4619 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4620 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4621 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4622 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4623 SIVAL(pdata
,32,mode
);
4624 SIVAL(pdata
,36,0); /* padding. */
4626 SOFF_T(pdata
,0,allocation_size
);
4627 SOFF_T(pdata
,8,file_size
);
4628 SIVAL(pdata
,16,nlink
);
4629 SCVAL(pdata
,20,delete_pending
);
4630 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4633 SIVAL(pdata
,0,ea_size
);
4634 pdata
+= 4; /* EA info */
4635 len
= srvstr_push(dstart
, flags2
,
4637 PTR_DIFF(dend
, pdata
+4),
4641 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4645 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4648 unsigned int ea_size
=
4649 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4651 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4652 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4653 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4654 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4655 SIVAL(pdata
, 0x20, mode
);
4656 SIVAL(pdata
, 0x24, 0); /* padding. */
4657 SBVAL(pdata
, 0x28, allocation_size
);
4658 SBVAL(pdata
, 0x30, file_size
);
4659 SIVAL(pdata
, 0x38, nlink
);
4660 SCVAL(pdata
, 0x3C, delete_pending
);
4661 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4662 SSVAL(pdata
, 0x3E, 0); /* padding */
4663 SBVAL(pdata
, 0x40, file_index
);
4664 SIVAL(pdata
, 0x48, ea_size
);
4665 SIVAL(pdata
, 0x4C, access_mask
);
4666 SBVAL(pdata
, 0x50, pos
);
4667 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4668 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4672 len
= srvstr_push(dstart
, flags2
,
4674 PTR_DIFF(dend
, pdata
+4),
4678 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4681 case SMB_FILE_INTERNAL_INFORMATION
:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4684 SBVAL(pdata
, 0, file_index
);
4688 case SMB_FILE_ACCESS_INFORMATION
:
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4690 SIVAL(pdata
, 0, access_mask
);
4694 case SMB_FILE_NAME_INFORMATION
:
4695 /* Pathname with leading '\'. */
4698 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4700 SIVAL(pdata
,0,byte_len
);
4701 data_size
= 4 + byte_len
;
4705 case SMB_FILE_DISPOSITION_INFORMATION
:
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4708 SCVAL(pdata
,0,delete_pending
);
4711 case SMB_FILE_POSITION_INFORMATION
:
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4714 SOFF_T(pdata
,0,pos
);
4717 case SMB_FILE_MODE_INFORMATION
:
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4719 SIVAL(pdata
,0,mode
);
4723 case SMB_FILE_ALIGNMENT_INFORMATION
:
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4725 SIVAL(pdata
,0,0); /* No alignment needed. */
4730 * NT4 server just returns "invalid query" to this - if we try
4731 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4734 /* The first statement above is false - verified using Thursby
4735 * client against NT4 -- gcolley.
4737 case SMB_QUERY_FILE_STREAM_INFO
:
4738 case SMB_FILE_STREAM_INFORMATION
: {
4739 unsigned int num_streams
= 0;
4740 struct stream_struct
*streams
= NULL
;
4742 DEBUG(10,("smbd_do_qfilepathinfo: "
4743 "SMB_FILE_STREAM_INFORMATION\n"));
4745 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4746 return NT_STATUS_INVALID_PARAMETER
;
4749 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4750 talloc_tos(), &num_streams
, &streams
);
4752 if (!NT_STATUS_IS_OK(status
)) {
4753 DEBUG(10, ("could not get stream info: %s\n",
4754 nt_errstr(status
)));
4758 status
= marshall_stream_info(num_streams
, streams
,
4759 pdata
, max_data_bytes
,
4762 if (!NT_STATUS_IS_OK(status
)) {
4763 DEBUG(10, ("marshall_stream_info failed: %s\n",
4764 nt_errstr(status
)));
4768 TALLOC_FREE(streams
);
4772 case SMB_QUERY_COMPRESSION_INFO
:
4773 case SMB_FILE_COMPRESSION_INFORMATION
:
4774 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4775 SOFF_T(pdata
,0,file_size
);
4776 SIVAL(pdata
,8,0); /* ??? */
4777 SIVAL(pdata
,12,0); /* ??? */
4781 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4782 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4783 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4784 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4785 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4786 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4787 SOFF_T(pdata
,32,allocation_size
);
4788 SOFF_T(pdata
,40,file_size
);
4789 SIVAL(pdata
,48,mode
);
4790 SIVAL(pdata
,52,0); /* ??? */
4794 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4795 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4796 SIVAL(pdata
,0,mode
);
4802 * CIFS UNIX Extensions.
4805 case SMB_QUERY_FILE_UNIX_BASIC
:
4807 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4808 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4810 DEBUG(4,("smbd_do_qfilepathinfo: "
4811 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4812 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4816 case SMB_QUERY_FILE_UNIX_INFO2
:
4818 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4819 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4823 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4825 for (i
=0; i
<100; i
++)
4826 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4832 case SMB_QUERY_FILE_UNIX_LINK
:
4835 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4838 return NT_STATUS_NO_MEMORY
;
4841 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4843 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4844 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4847 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4849 len
= SMB_VFS_READLINK(conn
,
4850 smb_fname
->base_name
,
4853 return map_nt_error_from_unix(errno
);
4856 len
= srvstr_push(dstart
, flags2
,
4858 PTR_DIFF(dend
, pdata
),
4861 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4866 #if defined(HAVE_POSIX_ACLS)
4867 case SMB_QUERY_POSIX_ACL
:
4869 SMB_ACL_T file_acl
= NULL
;
4870 SMB_ACL_T def_acl
= NULL
;
4871 uint16 num_file_acls
= 0;
4872 uint16 num_def_acls
= 0;
4874 if (fsp
&& fsp
->fh
->fd
!= -1) {
4875 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4878 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4879 smb_fname
->base_name
,
4880 SMB_ACL_TYPE_ACCESS
);
4883 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4884 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4885 "not implemented on "
4886 "filesystem containing %s\n",
4887 smb_fname
->base_name
));
4888 return NT_STATUS_NOT_IMPLEMENTED
;
4891 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4892 if (fsp
&& fsp
->is_directory
) {
4894 SMB_VFS_SYS_ACL_GET_FILE(
4896 fsp
->fsp_name
->base_name
,
4897 SMB_ACL_TYPE_DEFAULT
);
4900 SMB_VFS_SYS_ACL_GET_FILE(
4902 smb_fname
->base_name
,
4903 SMB_ACL_TYPE_DEFAULT
);
4905 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4908 num_file_acls
= count_acl_entries(conn
, file_acl
);
4909 num_def_acls
= count_acl_entries(conn
, def_acl
);
4911 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4912 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4914 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4915 SMB_POSIX_ACL_HEADER_SIZE
) ));
4917 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4920 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4922 return NT_STATUS_BUFFER_TOO_SMALL
;
4925 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4926 SSVAL(pdata
,2,num_file_acls
);
4927 SSVAL(pdata
,4,num_def_acls
);
4928 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4930 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4933 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4935 return NT_STATUS_INTERNAL_ERROR
;
4937 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4939 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4942 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4944 return NT_STATUS_INTERNAL_ERROR
;
4948 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4951 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4953 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4959 case SMB_QUERY_POSIX_LOCK
:
4964 enum brl_type lock_type
;
4966 /* We need an open file with a real fd for this. */
4967 if (!fsp
|| fsp
->fh
->fd
== -1) {
4968 return NT_STATUS_INVALID_LEVEL
;
4971 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4972 return NT_STATUS_INVALID_PARAMETER
;
4975 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4976 case POSIX_LOCK_TYPE_READ
:
4977 lock_type
= READ_LOCK
;
4979 case POSIX_LOCK_TYPE_WRITE
:
4980 lock_type
= WRITE_LOCK
;
4982 case POSIX_LOCK_TYPE_UNLOCK
:
4984 /* There's no point in asking for an unlock... */
4985 return NT_STATUS_INVALID_PARAMETER
;
4988 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4989 #if defined(HAVE_LONGLONG)
4990 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4991 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4992 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4993 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4994 #else /* HAVE_LONGLONG */
4995 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4996 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4997 #endif /* HAVE_LONGLONG */
4999 status
= query_lock(fsp
,
5006 if (ERROR_WAS_LOCK_DENIED(status
)) {
5007 /* Here we need to report who has it locked... */
5008 data_size
= POSIX_LOCK_DATA_SIZE
;
5010 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5011 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5012 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5013 #if defined(HAVE_LONGLONG)
5014 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5015 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5016 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5017 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5018 #else /* HAVE_LONGLONG */
5019 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5020 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5021 #endif /* HAVE_LONGLONG */
5023 } else if (NT_STATUS_IS_OK(status
)) {
5024 /* For success we just return a copy of what we sent
5025 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5026 data_size
= POSIX_LOCK_DATA_SIZE
;
5027 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5028 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5036 return NT_STATUS_INVALID_LEVEL
;
5039 *pdata_size
= data_size
;
5040 return NT_STATUS_OK
;
5043 /****************************************************************************
5044 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5045 file name or file id).
5046 ****************************************************************************/
5048 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5049 struct smb_request
*req
,
5050 unsigned int tran_call
,
5051 char **pparams
, int total_params
,
5052 char **ppdata
, int total_data
,
5053 unsigned int max_data_bytes
)
5055 char *params
= *pparams
;
5056 char *pdata
= *ppdata
;
5058 unsigned int data_size
= 0;
5059 unsigned int param_size
= 2;
5060 struct smb_filename
*smb_fname
= NULL
;
5061 bool delete_pending
= False
;
5062 struct timespec write_time_ts
;
5063 files_struct
*fsp
= NULL
;
5064 struct file_id fileid
;
5065 struct ea_list
*ea_list
= NULL
;
5066 int lock_data_count
= 0;
5067 char *lock_data
= NULL
;
5068 NTSTATUS status
= NT_STATUS_OK
;
5071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5075 ZERO_STRUCT(write_time_ts
);
5077 if (tran_call
== TRANSACT2_QFILEINFO
) {
5078 if (total_params
< 4) {
5079 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5084 call_trans2qpipeinfo(conn
, req
, tran_call
,
5085 pparams
, total_params
,
5091 fsp
= file_fsp(req
, SVAL(params
,0));
5092 info_level
= SVAL(params
,2);
5094 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5096 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5097 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5101 /* Initial check for valid fsp ptr. */
5102 if (!check_fsp_open(conn
, req
, fsp
)) {
5106 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5108 if (!NT_STATUS_IS_OK(status
)) {
5109 reply_nterror(req
, status
);
5113 if(fsp
->fake_file_handle
) {
5115 * This is actually for the QUOTA_FAKE_FILE --metze
5118 /* We know this name is ok, it's already passed the checks. */
5120 } else if(fsp
->fh
->fd
== -1) {
5122 * This is actually a QFILEINFO on a directory
5123 * handle (returned from an NT SMB). NT5.0 seems
5124 * to do this call. JRA.
5127 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5128 /* Always do lstat for UNIX calls. */
5129 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5130 DEBUG(3,("call_trans2qfilepathinfo: "
5131 "SMB_VFS_LSTAT of %s failed "
5133 smb_fname_str_dbg(smb_fname
),
5136 map_nt_error_from_unix(errno
));
5139 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5140 DEBUG(3,("call_trans2qfilepathinfo: "
5141 "SMB_VFS_STAT of %s failed (%s)\n",
5142 smb_fname_str_dbg(smb_fname
),
5145 map_nt_error_from_unix(errno
));
5149 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5150 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5153 * Original code - this is an open file.
5155 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5156 DEBUG(3, ("fstat of %s failed (%s)\n",
5157 fsp_fnum_dbg(fsp
), strerror(errno
)));
5159 map_nt_error_from_unix(errno
));
5162 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5163 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5169 uint32_t ucf_flags
= 0;
5172 if (total_params
< 7) {
5173 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5177 info_level
= SVAL(params
,0);
5179 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5181 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5182 if (!lp_unix_extensions()) {
5183 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5186 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5187 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5188 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5189 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5193 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5195 STR_TERMINATE
, &status
);
5196 if (!NT_STATUS_IS_OK(status
)) {
5197 reply_nterror(req
, status
);
5201 status
= filename_convert(req
,
5203 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5208 if (!NT_STATUS_IS_OK(status
)) {
5209 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5210 reply_botherror(req
,
5211 NT_STATUS_PATH_NOT_COVERED
,
5212 ERRSRV
, ERRbadpath
);
5215 reply_nterror(req
, status
);
5219 /* If this is a stream, check if there is a delete_pending. */
5220 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5221 && is_ntfs_stream_smb_fname(smb_fname
)) {
5222 struct smb_filename
*smb_fname_base
= NULL
;
5224 /* Create an smb_filename with stream_name == NULL. */
5226 create_synthetic_smb_fname(talloc_tos(),
5227 smb_fname
->base_name
,
5230 if (!NT_STATUS_IS_OK(status
)) {
5231 reply_nterror(req
, status
);
5235 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5236 /* Always do lstat for UNIX calls. */
5237 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5238 DEBUG(3,("call_trans2qfilepathinfo: "
5239 "SMB_VFS_LSTAT of %s failed "
5241 smb_fname_str_dbg(smb_fname_base
),
5243 TALLOC_FREE(smb_fname_base
);
5245 map_nt_error_from_unix(errno
));
5249 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5250 DEBUG(3,("call_trans2qfilepathinfo: "
5251 "fileinfo of %s failed "
5253 smb_fname_str_dbg(smb_fname_base
),
5255 TALLOC_FREE(smb_fname_base
);
5257 map_nt_error_from_unix(errno
));
5262 status
= file_name_hash(conn
,
5263 smb_fname_str_dbg(smb_fname_base
),
5265 if (!NT_STATUS_IS_OK(status
)) {
5266 TALLOC_FREE(smb_fname_base
);
5267 reply_nterror(req
, status
);
5271 fileid
= vfs_file_id_from_sbuf(conn
,
5272 &smb_fname_base
->st
);
5273 TALLOC_FREE(smb_fname_base
);
5274 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5275 if (delete_pending
) {
5276 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5281 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5282 /* Always do lstat for UNIX calls. */
5283 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5284 DEBUG(3,("call_trans2qfilepathinfo: "
5285 "SMB_VFS_LSTAT of %s failed (%s)\n",
5286 smb_fname_str_dbg(smb_fname
),
5289 map_nt_error_from_unix(errno
));
5294 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5295 DEBUG(3,("call_trans2qfilepathinfo: "
5296 "SMB_VFS_STAT of %s failed (%s)\n",
5297 smb_fname_str_dbg(smb_fname
),
5300 map_nt_error_from_unix(errno
));
5305 status
= file_name_hash(conn
,
5306 smb_fname_str_dbg(smb_fname
),
5308 if (!NT_STATUS_IS_OK(status
)) {
5309 reply_nterror(req
, status
);
5313 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5314 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5315 if (delete_pending
) {
5316 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5321 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5322 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5324 info_level
,tran_call
,total_data
));
5326 /* Pull out any data sent here before we realloc. */
5327 switch (info_level
) {
5328 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5330 /* Pull any EA list from the data portion. */
5333 if (total_data
< 4) {
5335 req
, NT_STATUS_INVALID_PARAMETER
);
5338 ea_size
= IVAL(pdata
,0);
5340 if (total_data
> 0 && ea_size
!= total_data
) {
5341 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5342 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5344 req
, NT_STATUS_INVALID_PARAMETER
);
5348 if (!lp_ea_support(SNUM(conn
))) {
5349 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5353 /* Pull out the list of names. */
5354 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5357 req
, NT_STATUS_INVALID_PARAMETER
);
5363 case SMB_QUERY_POSIX_LOCK
:
5365 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5366 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5370 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5372 req
, NT_STATUS_INVALID_PARAMETER
);
5376 /* Copy the lock range data. */
5377 lock_data
= (char *)talloc_memdup(
5378 req
, pdata
, total_data
);
5380 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5383 lock_data_count
= total_data
;
5389 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5390 if (*pparams
== NULL
) {
5391 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5398 * draft-leach-cifs-v1-spec-02.txt
5399 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5402 * The requested information is placed in the Data portion of the
5403 * transaction response. For the information levels greater than 0x100,
5404 * the transaction response has 1 parameter word which should be
5405 * ignored by the client.
5407 * However Windows only follows this rule for the IS_NAME_VALID call.
5409 switch (info_level
) {
5410 case SMB_INFO_IS_NAME_VALID
:
5415 if ((info_level
& 0xFF00) == 0xFF00) {
5417 * We use levels that start with 0xFF00
5418 * internally to represent SMB2 specific levels
5420 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5424 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5426 delete_pending
, write_time_ts
,
5428 lock_data_count
, lock_data
,
5429 req
->flags2
, max_data_bytes
,
5430 ppdata
, &data_size
);
5431 if (!NT_STATUS_IS_OK(status
)) {
5432 reply_nterror(req
, status
);
5436 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5442 /****************************************************************************
5443 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5445 ****************************************************************************/
5447 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5448 connection_struct
*conn
,
5449 struct smb_request
*req
,
5450 bool overwrite_if_exists
,
5451 const struct smb_filename
*smb_fname_old
,
5452 struct smb_filename
*smb_fname_new
)
5454 NTSTATUS status
= NT_STATUS_OK
;
5456 /* source must already exist. */
5457 if (!VALID_STAT(smb_fname_old
->st
)) {
5458 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5461 if (VALID_STAT(smb_fname_new
->st
)) {
5462 if (overwrite_if_exists
) {
5463 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5464 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5466 status
= unlink_internals(conn
,
5468 FILE_ATTRIBUTE_NORMAL
,
5471 if (!NT_STATUS_IS_OK(status
)) {
5475 /* Disallow if newname already exists. */
5476 return NT_STATUS_OBJECT_NAME_COLLISION
;
5480 /* No links from a directory. */
5481 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5482 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5485 /* Setting a hardlink to/from a stream isn't currently supported. */
5486 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5487 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5488 return NT_STATUS_INVALID_PARAMETER
;
5491 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5492 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5494 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5495 smb_fname_new
->base_name
) != 0) {
5496 status
= map_nt_error_from_unix(errno
);
5497 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5498 nt_errstr(status
), smb_fname_old
->base_name
,
5499 smb_fname_new
->base_name
));
5504 /****************************************************************************
5505 Deal with setting the time from any of the setfilepathinfo functions.
5506 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5507 calling this function.
5508 ****************************************************************************/
5510 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5512 const struct smb_filename
*smb_fname
,
5513 struct smb_file_time
*ft
,
5514 bool setting_write_time
)
5516 struct smb_filename smb_fname_base
;
5518 FILE_NOTIFY_CHANGE_LAST_ACCESS
5519 |FILE_NOTIFY_CHANGE_LAST_WRITE
5520 |FILE_NOTIFY_CHANGE_CREATION
;
5522 if (!VALID_STAT(smb_fname
->st
)) {
5523 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5526 /* get some defaults (no modifications) if any info is zero or -1. */
5527 if (null_timespec(ft
->create_time
)) {
5528 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5531 if (null_timespec(ft
->atime
)) {
5532 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5535 if (null_timespec(ft
->mtime
)) {
5536 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5539 if (!setting_write_time
) {
5540 /* ft->mtime comes from change time, not write time. */
5541 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5544 /* Ensure the resolution is the correct for
5545 * what we can store on this filesystem. */
5547 round_timespec(conn
->ts_res
, &ft
->create_time
);
5548 round_timespec(conn
->ts_res
, &ft
->ctime
);
5549 round_timespec(conn
->ts_res
, &ft
->atime
);
5550 round_timespec(conn
->ts_res
, &ft
->mtime
);
5552 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5553 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5554 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5555 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5556 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5557 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5558 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5561 if (setting_write_time
) {
5563 * This was a Windows setfileinfo on an open file.
5564 * NT does this a lot. We also need to
5565 * set the time here, as it can be read by
5566 * FindFirst/FindNext and with the patch for bug #2045
5567 * in smbd/fileio.c it ensures that this timestamp is
5568 * kept sticky even after a write. We save the request
5569 * away and will set it on file close and after a write. JRA.
5572 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5573 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5576 if (fsp
->base_fsp
) {
5577 set_sticky_write_time_fsp(fsp
->base_fsp
,
5580 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5583 set_sticky_write_time_path(
5584 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5589 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5591 /* Always call ntimes on the base, even if a stream was passed in. */
5592 smb_fname_base
= *smb_fname
;
5593 smb_fname_base
.stream_name
= NULL
;
5595 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5596 return map_nt_error_from_unix(errno
);
5599 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5600 smb_fname
->base_name
);
5601 return NT_STATUS_OK
;
5604 /****************************************************************************
5605 Deal with setting the dosmode from any of the setfilepathinfo functions.
5606 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5607 done before calling this function.
5608 ****************************************************************************/
5610 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5611 const struct smb_filename
*smb_fname
,
5614 struct smb_filename
*smb_fname_base
= NULL
;
5617 if (!VALID_STAT(smb_fname
->st
)) {
5618 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5621 /* Always operate on the base_name, even if a stream was passed in. */
5622 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5623 NULL
, &smb_fname
->st
,
5625 if (!NT_STATUS_IS_OK(status
)) {
5630 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5631 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5633 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5637 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5639 /* check the mode isn't different, before changing it */
5640 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5641 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5642 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5643 (unsigned int)dosmode
));
5645 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5647 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5649 smb_fname_str_dbg(smb_fname_base
),
5651 status
= map_nt_error_from_unix(errno
);
5655 status
= NT_STATUS_OK
;
5657 TALLOC_FREE(smb_fname_base
);
5661 /****************************************************************************
5662 Deal with setting the size from any of the setfilepathinfo functions.
5663 ****************************************************************************/
5665 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5666 struct smb_request
*req
,
5668 const struct smb_filename
*smb_fname
,
5669 const SMB_STRUCT_STAT
*psbuf
,
5671 bool fail_after_createfile
)
5673 NTSTATUS status
= NT_STATUS_OK
;
5674 struct smb_filename
*smb_fname_tmp
= NULL
;
5675 files_struct
*new_fsp
= NULL
;
5677 if (!VALID_STAT(*psbuf
)) {
5678 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5681 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5683 if (size
== get_file_size_stat(psbuf
)) {
5684 return NT_STATUS_OK
;
5687 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5688 smb_fname_str_dbg(smb_fname
), (double)size
));
5690 if (fsp
&& fsp
->fh
->fd
!= -1) {
5691 /* Handle based call. */
5692 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5693 return NT_STATUS_ACCESS_DENIED
;
5696 if (vfs_set_filelen(fsp
, size
) == -1) {
5697 return map_nt_error_from_unix(errno
);
5699 trigger_write_time_update_immediate(fsp
);
5700 return NT_STATUS_OK
;
5703 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5704 if (!NT_STATUS_IS_OK(status
)) {
5708 smb_fname_tmp
->st
= *psbuf
;
5710 status
= SMB_VFS_CREATE_FILE(
5713 0, /* root_dir_fid */
5714 smb_fname_tmp
, /* fname */
5715 FILE_WRITE_DATA
, /* access_mask */
5716 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5718 FILE_OPEN
, /* create_disposition*/
5719 0, /* create_options */
5720 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5721 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5722 0, /* allocation_size */
5723 0, /* private_flags */
5726 &new_fsp
, /* result */
5729 TALLOC_FREE(smb_fname_tmp
);
5731 if (!NT_STATUS_IS_OK(status
)) {
5732 /* NB. We check for open_was_deferred in the caller. */
5736 /* See RAW-SFILEINFO-END-OF-FILE */
5737 if (fail_after_createfile
) {
5738 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5739 return NT_STATUS_INVALID_LEVEL
;
5742 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5743 status
= map_nt_error_from_unix(errno
);
5744 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5748 trigger_write_time_update_immediate(new_fsp
);
5749 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5750 return NT_STATUS_OK
;
5753 /****************************************************************************
5754 Deal with SMB_INFO_SET_EA.
5755 ****************************************************************************/
5757 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5761 const struct smb_filename
*smb_fname
)
5763 struct ea_list
*ea_list
= NULL
;
5764 TALLOC_CTX
*ctx
= NULL
;
5765 NTSTATUS status
= NT_STATUS_OK
;
5767 if (total_data
< 10) {
5769 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5770 length. They seem to have no effect. Bug #3212. JRA */
5772 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5773 /* We're done. We only get EA info in this call. */
5774 return NT_STATUS_OK
;
5777 return NT_STATUS_INVALID_PARAMETER
;
5780 if (IVAL(pdata
,0) > total_data
) {
5781 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5782 IVAL(pdata
,0), (unsigned int)total_data
));
5783 return NT_STATUS_INVALID_PARAMETER
;
5787 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5789 return NT_STATUS_INVALID_PARAMETER
;
5792 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5797 /****************************************************************************
5798 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5799 ****************************************************************************/
5801 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5806 struct ea_list
*ea_list
= NULL
;
5810 return NT_STATUS_INVALID_HANDLE
;
5813 if (!lp_ea_support(SNUM(conn
))) {
5814 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5815 "EA's not supported.\n",
5816 (unsigned int)total_data
));
5817 return NT_STATUS_EAS_NOT_SUPPORTED
;
5820 if (total_data
< 10) {
5821 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5823 (unsigned int)total_data
));
5824 return NT_STATUS_INVALID_PARAMETER
;
5827 ea_list
= read_nttrans_ea_list(talloc_tos(),
5832 return NT_STATUS_INVALID_PARAMETER
;
5835 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5837 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5838 smb_fname_str_dbg(fsp
->fsp_name
),
5839 nt_errstr(status
) ));
5845 /****************************************************************************
5846 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5847 ****************************************************************************/
5849 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5853 struct smb_filename
*smb_fname
)
5855 NTSTATUS status
= NT_STATUS_OK
;
5856 bool delete_on_close
;
5859 if (total_data
< 1) {
5860 return NT_STATUS_INVALID_PARAMETER
;
5864 return NT_STATUS_INVALID_HANDLE
;
5867 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5868 dosmode
= dos_mode(conn
, smb_fname
);
5870 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5871 "delete_on_close = %u\n",
5872 smb_fname_str_dbg(smb_fname
),
5873 (unsigned int)dosmode
,
5874 (unsigned int)delete_on_close
));
5876 if (delete_on_close
) {
5877 status
= can_set_delete_on_close(fsp
, dosmode
);
5878 if (!NT_STATUS_IS_OK(status
)) {
5883 /* The set is across all open files on this dev/inode pair. */
5884 if (!set_delete_on_close(fsp
, delete_on_close
,
5885 conn
->session_info
->security_token
,
5886 conn
->session_info
->unix_token
)) {
5887 return NT_STATUS_ACCESS_DENIED
;
5889 return NT_STATUS_OK
;
5892 /****************************************************************************
5893 Deal with SMB_FILE_POSITION_INFORMATION.
5894 ****************************************************************************/
5896 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5901 uint64_t position_information
;
5903 if (total_data
< 8) {
5904 return NT_STATUS_INVALID_PARAMETER
;
5908 /* Ignore on pathname based set. */
5909 return NT_STATUS_OK
;
5912 position_information
= (uint64_t)IVAL(pdata
,0);
5913 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5915 DEBUG(10,("smb_file_position_information: Set file position "
5916 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5917 (double)position_information
));
5918 fsp
->fh
->position_information
= position_information
;
5919 return NT_STATUS_OK
;
5922 /****************************************************************************
5923 Deal with SMB_FILE_MODE_INFORMATION.
5924 ****************************************************************************/
5926 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5932 if (total_data
< 4) {
5933 return NT_STATUS_INVALID_PARAMETER
;
5935 mode
= IVAL(pdata
,0);
5936 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5937 return NT_STATUS_INVALID_PARAMETER
;
5939 return NT_STATUS_OK
;
5942 /****************************************************************************
5943 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5944 ****************************************************************************/
5946 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5947 struct smb_request
*req
,
5950 const struct smb_filename
*smb_fname
)
5952 char *link_target
= NULL
;
5953 const char *newname
= smb_fname
->base_name
;
5954 TALLOC_CTX
*ctx
= talloc_tos();
5956 /* Set a symbolic link. */
5957 /* Don't allow this if follow links is false. */
5959 if (total_data
== 0) {
5960 return NT_STATUS_INVALID_PARAMETER
;
5963 if (!lp_symlinks(SNUM(conn
))) {
5964 return NT_STATUS_ACCESS_DENIED
;
5967 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5968 total_data
, STR_TERMINATE
);
5971 return NT_STATUS_INVALID_PARAMETER
;
5974 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5975 newname
, link_target
));
5977 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5978 return map_nt_error_from_unix(errno
);
5981 return NT_STATUS_OK
;
5984 /****************************************************************************
5985 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5986 ****************************************************************************/
5988 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5989 struct smb_request
*req
,
5990 const char *pdata
, int total_data
,
5991 struct smb_filename
*smb_fname_new
)
5993 char *oldname
= NULL
;
5994 struct smb_filename
*smb_fname_old
= NULL
;
5995 TALLOC_CTX
*ctx
= talloc_tos();
5996 NTSTATUS status
= NT_STATUS_OK
;
5998 /* Set a hard link. */
5999 if (total_data
== 0) {
6000 return NT_STATUS_INVALID_PARAMETER
;
6003 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6004 total_data
, STR_TERMINATE
, &status
);
6005 if (!NT_STATUS_IS_OK(status
)) {
6009 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6010 smb_fname_str_dbg(smb_fname_new
), oldname
));
6012 status
= filename_convert(ctx
,
6014 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6019 if (!NT_STATUS_IS_OK(status
)) {
6023 return hardlink_internals(ctx
, conn
, req
, false,
6024 smb_fname_old
, smb_fname_new
);
6027 /****************************************************************************
6028 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6029 ****************************************************************************/
6031 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6032 struct smb_request
*req
,
6036 struct smb_filename
*smb_fname_src
)
6040 char *newname
= NULL
;
6041 struct smb_filename
*smb_fname_dst
= NULL
;
6042 NTSTATUS status
= NT_STATUS_OK
;
6043 TALLOC_CTX
*ctx
= talloc_tos();
6046 return NT_STATUS_INVALID_HANDLE
;
6049 if (total_data
< 20) {
6050 return NT_STATUS_INVALID_PARAMETER
;
6053 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6054 len
= IVAL(pdata
,16);
6056 if (len
> (total_data
- 20) || (len
== 0)) {
6057 return NT_STATUS_INVALID_PARAMETER
;
6060 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6061 &pdata
[20], len
, STR_TERMINATE
,
6063 if (!NT_STATUS_IS_OK(status
)) {
6067 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6070 status
= filename_convert(ctx
,
6072 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6077 if (!NT_STATUS_IS_OK(status
)) {
6081 if (fsp
->base_fsp
) {
6082 /* newname must be a stream name. */
6083 if (newname
[0] != ':') {
6084 return NT_STATUS_NOT_SUPPORTED
;
6087 /* Create an smb_fname to call rename_internals_fsp() with. */
6088 status
= create_synthetic_smb_fname(talloc_tos(),
6089 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6091 if (!NT_STATUS_IS_OK(status
)) {
6096 * Set the original last component, since
6097 * rename_internals_fsp() requires it.
6099 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6101 if (smb_fname_dst
->original_lcomp
== NULL
) {
6102 status
= NT_STATUS_NO_MEMORY
;
6108 DEBUG(10,("smb2_file_rename_information: "
6109 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6110 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6111 smb_fname_str_dbg(smb_fname_dst
)));
6112 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6113 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6117 TALLOC_FREE(smb_fname_dst
);
6121 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6122 struct smb_request
*req
,
6126 struct smb_filename
*smb_fname_src
)
6130 char *newname
= NULL
;
6131 struct smb_filename
*smb_fname_dst
= NULL
;
6132 NTSTATUS status
= NT_STATUS_OK
;
6133 TALLOC_CTX
*ctx
= talloc_tos();
6136 return NT_STATUS_INVALID_HANDLE
;
6139 if (total_data
< 20) {
6140 return NT_STATUS_INVALID_PARAMETER
;
6143 overwrite
= (CVAL(pdata
,0) ? true : false);
6144 len
= IVAL(pdata
,16);
6146 if (len
> (total_data
- 20) || (len
== 0)) {
6147 return NT_STATUS_INVALID_PARAMETER
;
6150 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6151 &pdata
[20], len
, STR_TERMINATE
,
6153 if (!NT_STATUS_IS_OK(status
)) {
6157 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6160 status
= filename_convert(ctx
,
6162 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6167 if (!NT_STATUS_IS_OK(status
)) {
6171 if (fsp
->base_fsp
) {
6172 /* No stream names. */
6173 return NT_STATUS_NOT_SUPPORTED
;
6176 DEBUG(10,("smb_file_link_information: "
6177 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6178 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6179 smb_fname_str_dbg(smb_fname_dst
)));
6180 status
= hardlink_internals(ctx
,
6187 TALLOC_FREE(smb_fname_dst
);
6191 /****************************************************************************
6192 Deal with SMB_FILE_RENAME_INFORMATION.
6193 ****************************************************************************/
6195 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6196 struct smb_request
*req
,
6200 struct smb_filename
*smb_fname_src
)
6205 char *newname
= NULL
;
6206 struct smb_filename
*smb_fname_dst
= NULL
;
6207 bool dest_has_wcard
= False
;
6208 NTSTATUS status
= NT_STATUS_OK
;
6210 TALLOC_CTX
*ctx
= talloc_tos();
6212 if (total_data
< 13) {
6213 return NT_STATUS_INVALID_PARAMETER
;
6216 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6217 root_fid
= IVAL(pdata
,4);
6218 len
= IVAL(pdata
,8);
6220 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6221 return NT_STATUS_INVALID_PARAMETER
;
6224 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6227 if (!NT_STATUS_IS_OK(status
)) {
6231 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6234 status
= resolve_dfspath_wcard(ctx
, conn
,
6235 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6238 !conn
->sconn
->using_smb2
,
6241 if (!NT_STATUS_IS_OK(status
)) {
6245 /* Check the new name has no '/' characters. */
6246 if (strchr_m(newname
, '/')) {
6247 return NT_STATUS_NOT_SUPPORTED
;
6250 if (fsp
&& fsp
->base_fsp
) {
6251 /* newname must be a stream name. */
6252 if (newname
[0] != ':') {
6253 return NT_STATUS_NOT_SUPPORTED
;
6256 /* Create an smb_fname to call rename_internals_fsp() with. */
6257 status
= create_synthetic_smb_fname(talloc_tos(),
6258 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6260 if (!NT_STATUS_IS_OK(status
)) {
6265 * Set the original last component, since
6266 * rename_internals_fsp() requires it.
6268 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6270 if (smb_fname_dst
->original_lcomp
== NULL
) {
6271 status
= NT_STATUS_NO_MEMORY
;
6277 * Build up an smb_fname_dst based on the filename passed in.
6278 * We basically just strip off the last component, and put on
6279 * the newname instead.
6281 char *base_name
= NULL
;
6283 /* newname must *not* be a stream name. */
6284 if (newname
[0] == ':') {
6285 return NT_STATUS_NOT_SUPPORTED
;
6289 * Strip off the last component (filename) of the path passed
6292 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6294 return NT_STATUS_NO_MEMORY
;
6296 p
= strrchr_m(base_name
, '/');
6300 base_name
= talloc_strdup(ctx
, "");
6302 return NT_STATUS_NO_MEMORY
;
6305 /* Append the new name. */
6306 base_name
= talloc_asprintf_append(base_name
,
6310 return NT_STATUS_NO_MEMORY
;
6313 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6316 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6319 /* If an error we expect this to be
6320 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6322 if (!NT_STATUS_IS_OK(status
)) {
6323 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6327 /* Create an smb_fname to call rename_internals_fsp() */
6328 status
= create_synthetic_smb_fname(ctx
,
6332 if (!NT_STATUS_IS_OK(status
)) {
6339 DEBUG(10,("smb_file_rename_information: "
6340 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6341 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6342 smb_fname_str_dbg(smb_fname_dst
)));
6343 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6346 DEBUG(10,("smb_file_rename_information: "
6347 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6348 smb_fname_str_dbg(smb_fname_src
),
6349 smb_fname_str_dbg(smb_fname_dst
)));
6350 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6351 smb_fname_dst
, 0, overwrite
, false,
6353 FILE_WRITE_ATTRIBUTES
);
6356 TALLOC_FREE(smb_fname_dst
);
6360 /****************************************************************************
6361 Deal with SMB_SET_POSIX_ACL.
6362 ****************************************************************************/
6364 #if defined(HAVE_POSIX_ACLS)
6365 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6369 const struct smb_filename
*smb_fname
)
6371 uint16 posix_acl_version
;
6372 uint16 num_file_acls
;
6373 uint16 num_def_acls
;
6374 bool valid_file_acls
= True
;
6375 bool valid_def_acls
= True
;
6377 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6378 return NT_STATUS_INVALID_PARAMETER
;
6380 posix_acl_version
= SVAL(pdata
,0);
6381 num_file_acls
= SVAL(pdata
,2);
6382 num_def_acls
= SVAL(pdata
,4);
6384 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6385 valid_file_acls
= False
;
6389 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6390 valid_def_acls
= False
;
6394 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6395 return NT_STATUS_INVALID_PARAMETER
;
6398 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6399 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6400 return NT_STATUS_INVALID_PARAMETER
;
6403 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6404 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6405 (unsigned int)num_file_acls
,
6406 (unsigned int)num_def_acls
));
6408 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6409 smb_fname
->base_name
, num_file_acls
,
6410 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6411 return map_nt_error_from_unix(errno
);
6414 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6415 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6416 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6417 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6418 return map_nt_error_from_unix(errno
);
6420 return NT_STATUS_OK
;
6424 /****************************************************************************
6425 Deal with SMB_SET_POSIX_LOCK.
6426 ****************************************************************************/
6428 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6429 struct smb_request
*req
,
6437 bool blocking_lock
= False
;
6438 enum brl_type lock_type
;
6440 NTSTATUS status
= NT_STATUS_OK
;
6442 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6443 return NT_STATUS_INVALID_HANDLE
;
6446 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6447 return NT_STATUS_INVALID_PARAMETER
;
6450 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6451 case POSIX_LOCK_TYPE_READ
:
6452 lock_type
= READ_LOCK
;
6454 case POSIX_LOCK_TYPE_WRITE
:
6455 /* Return the right POSIX-mappable error code for files opened read-only. */
6456 if (!fsp
->can_write
) {
6457 return NT_STATUS_INVALID_HANDLE
;
6459 lock_type
= WRITE_LOCK
;
6461 case POSIX_LOCK_TYPE_UNLOCK
:
6462 lock_type
= UNLOCK_LOCK
;
6465 return NT_STATUS_INVALID_PARAMETER
;
6468 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6469 blocking_lock
= False
;
6470 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6471 blocking_lock
= True
;
6473 return NT_STATUS_INVALID_PARAMETER
;
6476 if (!lp_blocking_locks(SNUM(conn
))) {
6477 blocking_lock
= False
;
6480 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6481 #if defined(HAVE_LONGLONG)
6482 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6483 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6484 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6485 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6486 #else /* HAVE_LONGLONG */
6487 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6488 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6489 #endif /* HAVE_LONGLONG */
6491 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6492 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6494 (unsigned int)lock_type
,
6495 (unsigned long long)smblctx
,
6499 if (lock_type
== UNLOCK_LOCK
) {
6500 status
= do_unlock(req
->sconn
->msg_ctx
,
6507 uint64_t block_smblctx
;
6509 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6521 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6523 * A blocking lock was requested. Package up
6524 * this smb into a queued request and push it
6525 * onto the blocking lock queue.
6527 if(push_blocking_lock_request(br_lck
,
6530 -1, /* infinite timeout. */
6538 TALLOC_FREE(br_lck
);
6542 TALLOC_FREE(br_lck
);
6548 /****************************************************************************
6549 Deal with SMB_SET_FILE_BASIC_INFO.
6550 ****************************************************************************/
6552 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6556 const struct smb_filename
*smb_fname
)
6558 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6559 struct smb_file_time ft
;
6561 NTSTATUS status
= NT_STATUS_OK
;
6565 if (total_data
< 36) {
6566 return NT_STATUS_INVALID_PARAMETER
;
6569 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6570 if (!NT_STATUS_IS_OK(status
)) {
6574 /* Set the attributes */
6575 dosmode
= IVAL(pdata
,32);
6576 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6577 if (!NT_STATUS_IS_OK(status
)) {
6582 ft
.create_time
= interpret_long_date(pdata
);
6585 ft
.atime
= interpret_long_date(pdata
+8);
6588 ft
.mtime
= interpret_long_date(pdata
+16);
6591 ft
.ctime
= interpret_long_date(pdata
+24);
6593 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6594 smb_fname_str_dbg(smb_fname
)));
6596 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6600 /****************************************************************************
6601 Deal with SMB_INFO_STANDARD.
6602 ****************************************************************************/
6604 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6608 const struct smb_filename
*smb_fname
)
6611 struct smb_file_time ft
;
6615 if (total_data
< 12) {
6616 return NT_STATUS_INVALID_PARAMETER
;
6620 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6622 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6624 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6626 DEBUG(10,("smb_set_info_standard: file %s\n",
6627 smb_fname_str_dbg(smb_fname
)));
6629 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6630 if (!NT_STATUS_IS_OK(status
)) {
6634 return smb_set_file_time(conn
,
6641 /****************************************************************************
6642 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6643 ****************************************************************************/
6645 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6646 struct smb_request
*req
,
6650 struct smb_filename
*smb_fname
)
6652 uint64_t allocation_size
= 0;
6653 NTSTATUS status
= NT_STATUS_OK
;
6654 files_struct
*new_fsp
= NULL
;
6656 if (!VALID_STAT(smb_fname
->st
)) {
6657 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6660 if (total_data
< 8) {
6661 return NT_STATUS_INVALID_PARAMETER
;
6664 allocation_size
= (uint64_t)IVAL(pdata
,0);
6665 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6666 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6667 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6668 (double)allocation_size
));
6670 if (allocation_size
) {
6671 allocation_size
= smb_roundup(conn
, allocation_size
);
6674 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6675 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6676 (double)allocation_size
));
6678 if (fsp
&& fsp
->fh
->fd
!= -1) {
6679 /* Open file handle. */
6680 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6681 return NT_STATUS_ACCESS_DENIED
;
6684 /* Only change if needed. */
6685 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6686 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6687 return map_nt_error_from_unix(errno
);
6690 /* But always update the time. */
6692 * This is equivalent to a write. Ensure it's seen immediately
6693 * if there are no pending writes.
6695 trigger_write_time_update_immediate(fsp
);
6696 return NT_STATUS_OK
;
6699 /* Pathname or stat or directory file. */
6700 status
= SMB_VFS_CREATE_FILE(
6703 0, /* root_dir_fid */
6704 smb_fname
, /* fname */
6705 FILE_WRITE_DATA
, /* access_mask */
6706 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6708 FILE_OPEN
, /* create_disposition*/
6709 0, /* create_options */
6710 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6711 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6712 0, /* allocation_size */
6713 0, /* private_flags */
6716 &new_fsp
, /* result */
6719 if (!NT_STATUS_IS_OK(status
)) {
6720 /* NB. We check for open_was_deferred in the caller. */
6724 /* Only change if needed. */
6725 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6726 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6727 status
= map_nt_error_from_unix(errno
);
6728 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6733 /* Changing the allocation size should set the last mod time. */
6735 * This is equivalent to a write. Ensure it's seen immediately
6736 * if there are no pending writes.
6738 trigger_write_time_update_immediate(new_fsp
);
6740 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6741 return NT_STATUS_OK
;
6744 /****************************************************************************
6745 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6746 ****************************************************************************/
6748 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6749 struct smb_request
*req
,
6753 const struct smb_filename
*smb_fname
,
6754 bool fail_after_createfile
)
6758 if (total_data
< 8) {
6759 return NT_STATUS_INVALID_PARAMETER
;
6762 size
= IVAL(pdata
,0);
6763 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6764 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6765 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6768 return smb_set_file_size(conn
, req
,
6773 fail_after_createfile
);
6776 /****************************************************************************
6777 Allow a UNIX info mknod.
6778 ****************************************************************************/
6780 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6783 const struct smb_filename
*smb_fname
)
6785 uint32 file_type
= IVAL(pdata
,56);
6786 #if defined(HAVE_MAKEDEV)
6787 uint32 dev_major
= IVAL(pdata
,60);
6788 uint32 dev_minor
= IVAL(pdata
,68);
6790 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6791 uint32 raw_unixmode
= IVAL(pdata
,84);
6795 if (total_data
< 100) {
6796 return NT_STATUS_INVALID_PARAMETER
;
6799 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6800 PERM_NEW_FILE
, &unixmode
);
6801 if (!NT_STATUS_IS_OK(status
)) {
6805 #if defined(HAVE_MAKEDEV)
6806 dev
= makedev(dev_major
, dev_minor
);
6809 switch (file_type
) {
6810 #if defined(S_IFIFO)
6811 case UNIX_TYPE_FIFO
:
6812 unixmode
|= S_IFIFO
;
6815 #if defined(S_IFSOCK)
6816 case UNIX_TYPE_SOCKET
:
6817 unixmode
|= S_IFSOCK
;
6820 #if defined(S_IFCHR)
6821 case UNIX_TYPE_CHARDEV
:
6822 unixmode
|= S_IFCHR
;
6825 #if defined(S_IFBLK)
6826 case UNIX_TYPE_BLKDEV
:
6827 unixmode
|= S_IFBLK
;
6831 return NT_STATUS_INVALID_PARAMETER
;
6834 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6835 "%.0f mode 0%o for file %s\n", (double)dev
,
6836 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6838 /* Ok - do the mknod. */
6839 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6840 return map_nt_error_from_unix(errno
);
6843 /* If any of the other "set" calls fail we
6844 * don't want to end up with a half-constructed mknod.
6847 if (lp_inherit_perms(SNUM(conn
))) {
6849 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6851 return NT_STATUS_NO_MEMORY
;
6853 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6855 TALLOC_FREE(parent
);
6858 return NT_STATUS_OK
;
6861 /****************************************************************************
6862 Deal with SMB_SET_FILE_UNIX_BASIC.
6863 ****************************************************************************/
6865 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6866 struct smb_request
*req
,
6870 const struct smb_filename
*smb_fname
)
6872 struct smb_file_time ft
;
6873 uint32 raw_unixmode
;
6876 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6877 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6878 NTSTATUS status
= NT_STATUS_OK
;
6879 bool delete_on_fail
= False
;
6880 enum perm_type ptype
;
6881 files_struct
*all_fsps
= NULL
;
6882 bool modify_mtime
= true;
6884 struct smb_filename
*smb_fname_tmp
= NULL
;
6885 SMB_STRUCT_STAT sbuf
;
6889 if (total_data
< 100) {
6890 return NT_STATUS_INVALID_PARAMETER
;
6893 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6894 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6895 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6896 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6899 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6900 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6901 set_owner
= (uid_t
)IVAL(pdata
,40);
6902 set_grp
= (gid_t
)IVAL(pdata
,48);
6903 raw_unixmode
= IVAL(pdata
,84);
6905 if (VALID_STAT(smb_fname
->st
)) {
6906 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6907 ptype
= PERM_EXISTING_DIR
;
6909 ptype
= PERM_EXISTING_FILE
;
6912 ptype
= PERM_NEW_FILE
;
6915 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6917 if (!NT_STATUS_IS_OK(status
)) {
6921 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6922 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6923 smb_fname_str_dbg(smb_fname
), (double)size
,
6924 (unsigned int)set_owner
, (unsigned int)set_grp
,
6925 (int)raw_unixmode
));
6927 sbuf
= smb_fname
->st
;
6929 if (!VALID_STAT(sbuf
)) {
6931 * The only valid use of this is to create character and block
6932 * devices, and named pipes. This is deprecated (IMHO) and
6933 * a new info level should be used for mknod. JRA.
6936 status
= smb_unix_mknod(conn
,
6940 if (!NT_STATUS_IS_OK(status
)) {
6944 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6946 if (!NT_STATUS_IS_OK(status
)) {
6950 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6951 status
= map_nt_error_from_unix(errno
);
6952 TALLOC_FREE(smb_fname_tmp
);
6953 SMB_VFS_UNLINK(conn
, smb_fname
);
6957 sbuf
= smb_fname_tmp
->st
;
6958 smb_fname
= smb_fname_tmp
;
6960 /* Ensure we don't try and change anything else. */
6961 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6962 size
= get_file_size_stat(&sbuf
);
6963 ft
.atime
= sbuf
.st_ex_atime
;
6964 ft
.mtime
= sbuf
.st_ex_mtime
;
6966 * We continue here as we might want to change the
6969 delete_on_fail
= True
;
6973 /* Horrible backwards compatibility hack as an old server bug
6974 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6978 size
= get_file_size_stat(&sbuf
);
6983 * Deal with the UNIX specific mode set.
6986 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6987 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6988 "setting mode 0%o for file %s\n",
6989 (unsigned int)unixmode
,
6990 smb_fname_str_dbg(smb_fname
)));
6991 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6992 return map_nt_error_from_unix(errno
);
6997 * Deal with the UNIX specific uid set.
7000 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7001 (sbuf
.st_ex_uid
!= set_owner
)) {
7004 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7005 "changing owner %u for path %s\n",
7006 (unsigned int)set_owner
,
7007 smb_fname_str_dbg(smb_fname
)));
7009 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7010 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7011 set_owner
, (gid_t
)-1);
7013 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7014 set_owner
, (gid_t
)-1);
7018 status
= map_nt_error_from_unix(errno
);
7019 if (delete_on_fail
) {
7020 SMB_VFS_UNLINK(conn
, smb_fname
);
7027 * Deal with the UNIX specific gid set.
7030 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7031 (sbuf
.st_ex_gid
!= set_grp
)) {
7032 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7033 "changing group %u for file %s\n",
7034 (unsigned int)set_owner
,
7035 smb_fname_str_dbg(smb_fname
)));
7036 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7038 status
= map_nt_error_from_unix(errno
);
7039 if (delete_on_fail
) {
7040 SMB_VFS_UNLINK(conn
, smb_fname
);
7046 /* Deal with any size changes. */
7048 status
= smb_set_file_size(conn
, req
,
7054 if (!NT_STATUS_IS_OK(status
)) {
7058 /* Deal with any time changes. */
7059 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7060 /* No change, don't cancel anything. */
7064 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7065 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7066 all_fsps
= file_find_di_next(all_fsps
)) {
7068 * We're setting the time explicitly for UNIX.
7069 * Cancel any pending changes over all handles.
7071 all_fsps
->update_write_time_on_close
= false;
7072 TALLOC_FREE(all_fsps
->update_write_time_event
);
7076 * Override the "setting_write_time"
7077 * parameter here as it almost does what
7078 * we need. Just remember if we modified
7079 * mtime and send the notify ourselves.
7081 if (null_timespec(ft
.mtime
)) {
7082 modify_mtime
= false;
7085 status
= smb_set_file_time(conn
,
7091 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7092 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7097 /****************************************************************************
7098 Deal with SMB_SET_FILE_UNIX_INFO2.
7099 ****************************************************************************/
7101 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7102 struct smb_request
*req
,
7106 const struct smb_filename
*smb_fname
)
7112 if (total_data
< 116) {
7113 return NT_STATUS_INVALID_PARAMETER
;
7116 /* Start by setting all the fields that are common between UNIX_BASIC
7119 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7121 if (!NT_STATUS_IS_OK(status
)) {
7125 smb_fflags
= IVAL(pdata
, 108);
7126 smb_fmask
= IVAL(pdata
, 112);
7128 /* NB: We should only attempt to alter the file flags if the client
7129 * sends a non-zero mask.
7131 if (smb_fmask
!= 0) {
7132 int stat_fflags
= 0;
7134 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7135 smb_fmask
, &stat_fflags
)) {
7136 /* Client asked to alter a flag we don't understand. */
7137 return NT_STATUS_INVALID_PARAMETER
;
7140 if (fsp
&& fsp
->fh
->fd
!= -1) {
7141 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7142 return NT_STATUS_NOT_SUPPORTED
;
7144 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7145 stat_fflags
) != 0) {
7146 return map_nt_error_from_unix(errno
);
7151 /* XXX: need to add support for changing the create_time here. You
7152 * can do this for paths on Darwin with setattrlist(2). The right way
7153 * to hook this up is probably by extending the VFS utimes interface.
7156 return NT_STATUS_OK
;
7159 /****************************************************************************
7160 Create a directory with POSIX semantics.
7161 ****************************************************************************/
7163 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7164 struct smb_request
*req
,
7167 struct smb_filename
*smb_fname
,
7168 int *pdata_return_size
)
7170 NTSTATUS status
= NT_STATUS_OK
;
7171 uint32 raw_unixmode
= 0;
7172 uint32 mod_unixmode
= 0;
7173 mode_t unixmode
= (mode_t
)0;
7174 files_struct
*fsp
= NULL
;
7175 uint16 info_level_return
= 0;
7177 char *pdata
= *ppdata
;
7179 if (total_data
< 18) {
7180 return NT_STATUS_INVALID_PARAMETER
;
7183 raw_unixmode
= IVAL(pdata
,8);
7184 /* Next 4 bytes are not yet defined. */
7186 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7187 PERM_NEW_DIR
, &unixmode
);
7188 if (!NT_STATUS_IS_OK(status
)) {
7192 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7194 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7195 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7197 status
= SMB_VFS_CREATE_FILE(
7200 0, /* root_dir_fid */
7201 smb_fname
, /* fname */
7202 FILE_READ_ATTRIBUTES
, /* access_mask */
7203 FILE_SHARE_NONE
, /* share_access */
7204 FILE_CREATE
, /* create_disposition*/
7205 FILE_DIRECTORY_FILE
, /* create_options */
7206 mod_unixmode
, /* file_attributes */
7207 0, /* oplock_request */
7208 0, /* allocation_size */
7209 0, /* private_flags */
7215 if (NT_STATUS_IS_OK(status
)) {
7216 close_file(req
, fsp
, NORMAL_CLOSE
);
7219 info_level_return
= SVAL(pdata
,16);
7221 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7222 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7223 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7224 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7226 *pdata_return_size
= 12;
7229 /* Realloc the data size */
7230 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7231 if (*ppdata
== NULL
) {
7232 *pdata_return_size
= 0;
7233 return NT_STATUS_NO_MEMORY
;
7237 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7238 SSVAL(pdata
,2,0); /* No fnum. */
7239 SIVAL(pdata
,4,info
); /* Was directory created. */
7241 switch (info_level_return
) {
7242 case SMB_QUERY_FILE_UNIX_BASIC
:
7243 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7244 SSVAL(pdata
,10,0); /* Padding. */
7245 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7248 case SMB_QUERY_FILE_UNIX_INFO2
:
7249 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7250 SSVAL(pdata
,10,0); /* Padding. */
7251 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7255 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7256 SSVAL(pdata
,10,0); /* Padding. */
7263 /****************************************************************************
7264 Open/Create a file with POSIX semantics.
7265 ****************************************************************************/
7267 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7268 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7270 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7271 struct smb_request
*req
,
7274 struct smb_filename
*smb_fname
,
7275 int *pdata_return_size
)
7277 bool extended_oplock_granted
= False
;
7278 char *pdata
= *ppdata
;
7280 uint32 wire_open_mode
= 0;
7281 uint32 raw_unixmode
= 0;
7282 uint32 mod_unixmode
= 0;
7283 uint32 create_disp
= 0;
7284 uint32 access_mask
= 0;
7285 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7286 NTSTATUS status
= NT_STATUS_OK
;
7287 mode_t unixmode
= (mode_t
)0;
7288 files_struct
*fsp
= NULL
;
7289 int oplock_request
= 0;
7291 uint16 info_level_return
= 0;
7293 if (total_data
< 18) {
7294 return NT_STATUS_INVALID_PARAMETER
;
7297 flags
= IVAL(pdata
,0);
7298 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7299 if (oplock_request
) {
7300 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7303 wire_open_mode
= IVAL(pdata
,4);
7305 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7306 return smb_posix_mkdir(conn
, req
,
7313 switch (wire_open_mode
& SMB_ACCMODE
) {
7315 access_mask
= SMB_O_RDONLY_MAPPING
;
7318 access_mask
= SMB_O_WRONLY_MAPPING
;
7321 access_mask
= (SMB_O_RDONLY_MAPPING
|
7322 SMB_O_WRONLY_MAPPING
);
7325 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7326 (unsigned int)wire_open_mode
));
7327 return NT_STATUS_INVALID_PARAMETER
;
7330 wire_open_mode
&= ~SMB_ACCMODE
;
7332 /* First take care of O_CREAT|O_EXCL interactions. */
7333 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7334 case (SMB_O_CREAT
| SMB_O_EXCL
):
7335 /* File exists fail. File not exist create. */
7336 create_disp
= FILE_CREATE
;
7339 /* File exists open. File not exist create. */
7340 create_disp
= FILE_OPEN_IF
;
7343 /* File exists open. File not exist fail. */
7344 create_disp
= FILE_OPEN
;
7347 /* O_EXCL on its own without O_CREAT is undefined. */
7349 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7350 (unsigned int)wire_open_mode
));
7351 return NT_STATUS_INVALID_PARAMETER
;
7354 /* Next factor in the effects of O_TRUNC. */
7355 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7357 if (wire_open_mode
& SMB_O_TRUNC
) {
7358 switch (create_disp
) {
7360 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7361 /* Leave create_disp alone as
7362 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7364 /* File exists fail. File not exist create. */
7367 /* SMB_O_CREAT | SMB_O_TRUNC */
7368 /* File exists overwrite. File not exist create. */
7369 create_disp
= FILE_OVERWRITE_IF
;
7373 /* File exists overwrite. File not exist fail. */
7374 create_disp
= FILE_OVERWRITE
;
7377 /* Cannot get here. */
7378 smb_panic("smb_posix_open: logic error");
7379 return NT_STATUS_INVALID_PARAMETER
;
7383 raw_unixmode
= IVAL(pdata
,8);
7384 /* Next 4 bytes are not yet defined. */
7386 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7387 (VALID_STAT(smb_fname
->st
) ?
7388 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7391 if (!NT_STATUS_IS_OK(status
)) {
7395 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7397 if (wire_open_mode
& SMB_O_SYNC
) {
7398 create_options
|= FILE_WRITE_THROUGH
;
7400 if (wire_open_mode
& SMB_O_APPEND
) {
7401 access_mask
|= FILE_APPEND_DATA
;
7403 if (wire_open_mode
& SMB_O_DIRECT
) {
7404 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7407 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7408 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7409 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7410 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7412 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7413 create_options
|= FILE_DIRECTORY_FILE
;
7416 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7417 smb_fname_str_dbg(smb_fname
),
7418 (unsigned int)wire_open_mode
,
7419 (unsigned int)unixmode
));
7421 status
= SMB_VFS_CREATE_FILE(
7424 0, /* root_dir_fid */
7425 smb_fname
, /* fname */
7426 access_mask
, /* access_mask */
7427 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7429 create_disp
, /* create_disposition*/
7430 create_options
, /* create_options */
7431 mod_unixmode
, /* file_attributes */
7432 oplock_request
, /* oplock_request */
7433 0, /* allocation_size */
7434 0, /* private_flags */
7440 if (!NT_STATUS_IS_OK(status
)) {
7444 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7445 extended_oplock_granted
= True
;
7448 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7449 extended_oplock_granted
= True
;
7452 info_level_return
= SVAL(pdata
,16);
7454 /* Allocate the correct return size. */
7456 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7457 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7458 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7459 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7461 *pdata_return_size
= 12;
7464 /* Realloc the data size */
7465 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7466 if (*ppdata
== NULL
) {
7467 close_file(req
, fsp
, ERROR_CLOSE
);
7468 *pdata_return_size
= 0;
7469 return NT_STATUS_NO_MEMORY
;
7473 if (extended_oplock_granted
) {
7474 if (flags
& REQUEST_BATCH_OPLOCK
) {
7475 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7477 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7479 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7480 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7482 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7485 SSVAL(pdata
,2,fsp
->fnum
);
7486 SIVAL(pdata
,4,info
); /* Was file created etc. */
7488 switch (info_level_return
) {
7489 case SMB_QUERY_FILE_UNIX_BASIC
:
7490 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7491 SSVAL(pdata
,10,0); /* padding. */
7492 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7495 case SMB_QUERY_FILE_UNIX_INFO2
:
7496 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7497 SSVAL(pdata
,10,0); /* padding. */
7498 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7502 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7503 SSVAL(pdata
,10,0); /* padding. */
7506 return NT_STATUS_OK
;
7509 /****************************************************************************
7510 Delete a file with POSIX semantics.
7511 ****************************************************************************/
7513 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7514 struct smb_request
*req
,
7517 struct smb_filename
*smb_fname
)
7519 NTSTATUS status
= NT_STATUS_OK
;
7520 files_struct
*fsp
= NULL
;
7524 int create_options
= 0;
7526 struct share_mode_lock
*lck
= NULL
;
7528 if (total_data
< 2) {
7529 return NT_STATUS_INVALID_PARAMETER
;
7532 flags
= SVAL(pdata
,0);
7534 if (!VALID_STAT(smb_fname
->st
)) {
7535 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7538 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7539 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7540 return NT_STATUS_NOT_A_DIRECTORY
;
7543 DEBUG(10,("smb_posix_unlink: %s %s\n",
7544 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7545 smb_fname_str_dbg(smb_fname
)));
7547 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7548 create_options
|= FILE_DIRECTORY_FILE
;
7551 status
= SMB_VFS_CREATE_FILE(
7554 0, /* root_dir_fid */
7555 smb_fname
, /* fname */
7556 DELETE_ACCESS
, /* access_mask */
7557 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7559 FILE_OPEN
, /* create_disposition*/
7560 create_options
, /* create_options */
7561 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7562 0, /* oplock_request */
7563 0, /* allocation_size */
7564 0, /* private_flags */
7570 if (!NT_STATUS_IS_OK(status
)) {
7575 * Don't lie to client. If we can't really delete due to
7576 * non-POSIX opens return SHARING_VIOLATION.
7579 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7581 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7582 "lock for file %s\n", fsp_str_dbg(fsp
)));
7583 close_file(req
, fsp
, NORMAL_CLOSE
);
7584 return NT_STATUS_INVALID_PARAMETER
;
7588 * See if others still have the file open. If this is the case, then
7589 * don't delete. If all opens are POSIX delete we can set the delete
7590 * on close disposition.
7592 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7593 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7594 if (is_valid_share_mode_entry(e
)) {
7595 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7598 if (share_mode_stale_pid(lck
->data
, i
)) {
7601 /* Fail with sharing violation. */
7602 close_file(req
, fsp
, NORMAL_CLOSE
);
7604 return NT_STATUS_SHARING_VIOLATION
;
7609 * Set the delete on close.
7611 status
= smb_set_file_disposition_info(conn
,
7617 if (!NT_STATUS_IS_OK(status
)) {
7618 close_file(req
, fsp
, NORMAL_CLOSE
);
7623 return close_file(req
, fsp
, NORMAL_CLOSE
);
7626 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7627 struct smb_request
*req
,
7628 TALLOC_CTX
*mem_ctx
,
7629 uint16_t info_level
,
7631 struct smb_filename
*smb_fname
,
7632 char **ppdata
, int total_data
,
7635 char *pdata
= *ppdata
;
7636 NTSTATUS status
= NT_STATUS_OK
;
7637 int data_return_size
= 0;
7641 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7642 return NT_STATUS_INVALID_LEVEL
;
7645 if (!CAN_WRITE(conn
)) {
7646 /* Allow POSIX opens. The open path will deny
7647 * any non-readonly opens. */
7648 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7649 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7653 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7654 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7656 info_level
, total_data
));
7658 switch (info_level
) {
7660 case SMB_INFO_STANDARD
:
7662 status
= smb_set_info_standard(conn
,
7670 case SMB_INFO_SET_EA
:
7672 status
= smb_info_set_ea(conn
,
7680 case SMB_SET_FILE_BASIC_INFO
:
7681 case SMB_FILE_BASIC_INFORMATION
:
7683 status
= smb_set_file_basic_info(conn
,
7691 case SMB_FILE_ALLOCATION_INFORMATION
:
7692 case SMB_SET_FILE_ALLOCATION_INFO
:
7694 status
= smb_set_file_allocation_info(conn
, req
,
7702 case SMB_FILE_END_OF_FILE_INFORMATION
:
7703 case SMB_SET_FILE_END_OF_FILE_INFO
:
7706 * XP/Win7 both fail after the createfile with
7707 * SMB_SET_FILE_END_OF_FILE_INFO but not
7708 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7709 * The level is known here, so pass it down
7713 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7715 status
= smb_set_file_end_of_file_info(conn
, req
,
7724 case SMB_FILE_DISPOSITION_INFORMATION
:
7725 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7728 /* JRA - We used to just ignore this on a path ?
7729 * Shouldn't this be invalid level on a pathname
7732 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7733 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7736 status
= smb_set_file_disposition_info(conn
,
7744 case SMB_FILE_POSITION_INFORMATION
:
7746 status
= smb_file_position_information(conn
,
7753 case SMB_FILE_FULL_EA_INFORMATION
:
7755 status
= smb_set_file_full_ea_info(conn
,
7762 /* From tridge Samba4 :
7763 * MODE_INFORMATION in setfileinfo (I have no
7764 * idea what "mode information" on a file is - it takes a value of 0,
7765 * 2, 4 or 6. What could it be?).
7768 case SMB_FILE_MODE_INFORMATION
:
7770 status
= smb_file_mode_information(conn
,
7777 * CIFS UNIX extensions.
7780 case SMB_SET_FILE_UNIX_BASIC
:
7782 status
= smb_set_file_unix_basic(conn
, req
,
7790 case SMB_SET_FILE_UNIX_INFO2
:
7792 status
= smb_set_file_unix_info2(conn
, req
,
7800 case SMB_SET_FILE_UNIX_LINK
:
7803 /* We must have a pathname for this. */
7804 return NT_STATUS_INVALID_LEVEL
;
7806 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7807 total_data
, smb_fname
);
7811 case SMB_SET_FILE_UNIX_HLINK
:
7814 /* We must have a pathname for this. */
7815 return NT_STATUS_INVALID_LEVEL
;
7817 status
= smb_set_file_unix_hlink(conn
, req
,
7823 case SMB_FILE_RENAME_INFORMATION
:
7825 status
= smb_file_rename_information(conn
, req
,
7831 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7833 /* SMB2 rename information. */
7834 status
= smb2_file_rename_information(conn
, req
,
7840 case SMB_FILE_LINK_INFORMATION
:
7842 status
= smb_file_link_information(conn
, req
,
7848 #if defined(HAVE_POSIX_ACLS)
7849 case SMB_SET_POSIX_ACL
:
7851 status
= smb_set_posix_acl(conn
,
7860 case SMB_SET_POSIX_LOCK
:
7863 return NT_STATUS_INVALID_LEVEL
;
7865 status
= smb_set_posix_lock(conn
, req
,
7866 pdata
, total_data
, fsp
);
7870 case SMB_POSIX_PATH_OPEN
:
7873 /* We must have a pathname for this. */
7874 return NT_STATUS_INVALID_LEVEL
;
7877 status
= smb_posix_open(conn
, req
,
7885 case SMB_POSIX_PATH_UNLINK
:
7888 /* We must have a pathname for this. */
7889 return NT_STATUS_INVALID_LEVEL
;
7892 status
= smb_posix_unlink(conn
, req
,
7900 return NT_STATUS_INVALID_LEVEL
;
7903 if (!NT_STATUS_IS_OK(status
)) {
7907 *ret_data_size
= data_return_size
;
7908 return NT_STATUS_OK
;
7911 /****************************************************************************
7912 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7913 ****************************************************************************/
7915 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7916 struct smb_request
*req
,
7917 unsigned int tran_call
,
7918 char **pparams
, int total_params
,
7919 char **ppdata
, int total_data
,
7920 unsigned int max_data_bytes
)
7922 char *params
= *pparams
;
7923 char *pdata
= *ppdata
;
7925 struct smb_filename
*smb_fname
= NULL
;
7926 files_struct
*fsp
= NULL
;
7927 NTSTATUS status
= NT_STATUS_OK
;
7928 int data_return_size
= 0;
7931 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7935 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7936 if (total_params
< 4) {
7937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7941 fsp
= file_fsp(req
, SVAL(params
,0));
7942 /* Basic check for non-null fsp. */
7943 if (!check_fsp_open(conn
, req
, fsp
)) {
7946 info_level
= SVAL(params
,2);
7948 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7950 if (!NT_STATUS_IS_OK(status
)) {
7951 reply_nterror(req
, status
);
7955 if(fsp
->fh
->fd
== -1) {
7957 * This is actually a SETFILEINFO on a directory
7958 * handle (returned from an NT SMB). NT5.0 seems
7959 * to do this call. JRA.
7961 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7962 /* Always do lstat for UNIX calls. */
7963 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7964 DEBUG(3,("call_trans2setfilepathinfo: "
7965 "SMB_VFS_LSTAT of %s failed "
7967 smb_fname_str_dbg(smb_fname
),
7969 reply_nterror(req
, map_nt_error_from_unix(errno
));
7973 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7974 DEBUG(3,("call_trans2setfilepathinfo: "
7975 "fileinfo of %s failed (%s)\n",
7976 smb_fname_str_dbg(smb_fname
),
7978 reply_nterror(req
, map_nt_error_from_unix(errno
));
7982 } else if (fsp
->print_file
) {
7984 * Doing a DELETE_ON_CLOSE should cancel a print job.
7986 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7987 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7989 DEBUG(3,("call_trans2setfilepathinfo: "
7990 "Cancelling print job (%s)\n",
7994 send_trans2_replies(conn
, req
, params
, 2,
8000 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8005 * Original code - this is an open file.
8007 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8008 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8009 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8011 reply_nterror(req
, map_nt_error_from_unix(errno
));
8017 uint32_t ucf_flags
= 0;
8020 if (total_params
< 7) {
8021 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8025 info_level
= SVAL(params
,0);
8026 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8027 total_params
- 6, STR_TERMINATE
,
8029 if (!NT_STATUS_IS_OK(status
)) {
8030 reply_nterror(req
, status
);
8034 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8035 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8036 info_level
== SMB_FILE_RENAME_INFORMATION
||
8037 info_level
== SMB_POSIX_PATH_UNLINK
) {
8038 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8041 status
= filename_convert(req
, conn
,
8042 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8047 if (!NT_STATUS_IS_OK(status
)) {
8048 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8049 reply_botherror(req
,
8050 NT_STATUS_PATH_NOT_COVERED
,
8051 ERRSRV
, ERRbadpath
);
8054 reply_nterror(req
, status
);
8058 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8060 * For CIFS UNIX extensions the target name may not exist.
8063 /* Always do lstat for UNIX calls. */
8064 SMB_VFS_LSTAT(conn
, smb_fname
);
8066 } else if (!VALID_STAT(smb_fname
->st
) &&
8067 SMB_VFS_STAT(conn
, smb_fname
)) {
8068 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8070 smb_fname_str_dbg(smb_fname
),
8072 reply_nterror(req
, map_nt_error_from_unix(errno
));
8077 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8078 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8080 info_level
,total_data
));
8082 /* Realloc the parameter size */
8083 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8084 if (*pparams
== NULL
) {
8085 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8092 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8098 if (!NT_STATUS_IS_OK(status
)) {
8099 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8100 /* We have re-scheduled this call. */
8103 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8104 /* We have re-scheduled this call. */
8107 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8108 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8109 ERRSRV
, ERRbadpath
);
8112 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8113 reply_openerror(req
, status
);
8117 reply_nterror(req
, status
);
8121 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8127 /****************************************************************************
8128 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8129 ****************************************************************************/
8131 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8132 char **pparams
, int total_params
,
8133 char **ppdata
, int total_data
,
8134 unsigned int max_data_bytes
)
8136 struct smb_filename
*smb_dname
= NULL
;
8137 char *params
= *pparams
;
8138 char *pdata
= *ppdata
;
8139 char *directory
= NULL
;
8140 NTSTATUS status
= NT_STATUS_OK
;
8141 struct ea_list
*ea_list
= NULL
;
8142 TALLOC_CTX
*ctx
= talloc_tos();
8144 if (!CAN_WRITE(conn
)) {
8145 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8149 if (total_params
< 5) {
8150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8154 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8155 total_params
- 4, STR_TERMINATE
,
8157 if (!NT_STATUS_IS_OK(status
)) {
8158 reply_nterror(req
, status
);
8162 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8164 status
= filename_convert(ctx
,
8166 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8172 if (!NT_STATUS_IS_OK(status
)) {
8173 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8174 reply_botherror(req
,
8175 NT_STATUS_PATH_NOT_COVERED
,
8176 ERRSRV
, ERRbadpath
);
8179 reply_nterror(req
, status
);
8184 * OS/2 workplace shell seems to send SET_EA requests of "null"
8185 * length (4 bytes containing IVAL 4).
8186 * They seem to have no effect. Bug #3212. JRA.
8189 if (total_data
&& (total_data
!= 4)) {
8190 /* Any data in this call is an EA list. */
8191 if (total_data
< 10) {
8192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8196 if (IVAL(pdata
,0) > total_data
) {
8197 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8198 IVAL(pdata
,0), (unsigned int)total_data
));
8199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8203 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8206 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8210 if (!lp_ea_support(SNUM(conn
))) {
8211 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8215 /* If total_data == 4 Windows doesn't care what values
8216 * are placed in that field, it just ignores them.
8217 * The System i QNTC IBM SMB client puts bad values here,
8218 * so ignore them. */
8220 status
= create_directory(conn
, req
, smb_dname
);
8222 if (!NT_STATUS_IS_OK(status
)) {
8223 reply_nterror(req
, status
);
8227 /* Try and set any given EA. */
8229 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8230 if (!NT_STATUS_IS_OK(status
)) {
8231 reply_nterror(req
, status
);
8236 /* Realloc the parameter and data sizes */
8237 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8238 if(*pparams
== NULL
) {
8239 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8246 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8249 TALLOC_FREE(smb_dname
);
8253 /****************************************************************************
8254 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8255 We don't actually do this - we just send a null response.
8256 ****************************************************************************/
8258 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8259 struct smb_request
*req
,
8260 char **pparams
, int total_params
,
8261 char **ppdata
, int total_data
,
8262 unsigned int max_data_bytes
)
8264 char *params
= *pparams
;
8267 if (total_params
< 6) {
8268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8272 info_level
= SVAL(params
,4);
8273 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8275 switch (info_level
) {
8280 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8284 /* Realloc the parameter and data sizes */
8285 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8286 if (*pparams
== NULL
) {
8287 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8292 SSVAL(params
,0,fnf_handle
);
8293 SSVAL(params
,2,0); /* No changes */
8294 SSVAL(params
,4,0); /* No EA errors */
8301 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8306 /****************************************************************************
8307 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8308 changes). Currently this does nothing.
8309 ****************************************************************************/
8311 static void call_trans2findnotifynext(connection_struct
*conn
,
8312 struct smb_request
*req
,
8313 char **pparams
, int total_params
,
8314 char **ppdata
, int total_data
,
8315 unsigned int max_data_bytes
)
8317 char *params
= *pparams
;
8319 DEBUG(3,("call_trans2findnotifynext\n"));
8321 /* Realloc the parameter and data sizes */
8322 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8323 if (*pparams
== NULL
) {
8324 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8329 SSVAL(params
,0,0); /* No changes */
8330 SSVAL(params
,2,0); /* No EA errors */
8332 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8337 /****************************************************************************
8338 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8339 ****************************************************************************/
8341 static void call_trans2getdfsreferral(connection_struct
*conn
,
8342 struct smb_request
*req
,
8343 char **pparams
, int total_params
,
8344 char **ppdata
, int total_data
,
8345 unsigned int max_data_bytes
)
8347 char *params
= *pparams
;
8348 char *pathname
= NULL
;
8350 int max_referral_level
;
8351 NTSTATUS status
= NT_STATUS_OK
;
8352 TALLOC_CTX
*ctx
= talloc_tos();
8354 DEBUG(10,("call_trans2getdfsreferral\n"));
8356 if (total_params
< 3) {
8357 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8361 max_referral_level
= SVAL(params
,0);
8363 if(!lp_host_msdfs()) {
8364 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8368 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8369 total_params
- 2, STR_TERMINATE
);
8371 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8374 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8375 ppdata
,&status
)) < 0) {
8376 reply_nterror(req
, status
);
8380 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8381 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8382 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8387 #define LMCAT_SPL 0x53
8388 #define LMFUNC_GETJOBID 0x60
8390 /****************************************************************************
8391 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8392 ****************************************************************************/
8394 static void call_trans2ioctl(connection_struct
*conn
,
8395 struct smb_request
*req
,
8396 char **pparams
, int total_params
,
8397 char **ppdata
, int total_data
,
8398 unsigned int max_data_bytes
)
8400 char *pdata
= *ppdata
;
8401 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8403 /* check for an invalid fid before proceeding */
8406 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8410 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8411 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8412 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8413 if (*ppdata
== NULL
) {
8414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8419 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8420 CAN ACCEPT THIS IN UNICODE. JRA. */
8423 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8425 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8426 lp_netbios_name(), 15,
8427 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8428 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8429 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8430 STR_ASCII
|STR_TERMINATE
); /* Service name */
8431 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8436 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8437 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8440 /****************************************************************************
8441 Reply to a SMBfindclose (stop trans2 directory search).
8442 ****************************************************************************/
8444 void reply_findclose(struct smb_request
*req
)
8447 struct smbd_server_connection
*sconn
= req
->sconn
;
8449 START_PROFILE(SMBfindclose
);
8452 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8453 END_PROFILE(SMBfindclose
);
8457 dptr_num
= SVALS(req
->vwv
+0, 0);
8459 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8461 dptr_close(sconn
, &dptr_num
);
8463 reply_outbuf(req
, 0, 0);
8465 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8467 END_PROFILE(SMBfindclose
);
8471 /****************************************************************************
8472 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8473 ****************************************************************************/
8475 void reply_findnclose(struct smb_request
*req
)
8479 START_PROFILE(SMBfindnclose
);
8482 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8483 END_PROFILE(SMBfindnclose
);
8487 dptr_num
= SVAL(req
->vwv
+0, 0);
8489 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8491 /* We never give out valid handles for a
8492 findnotifyfirst - so any dptr_num is ok here.
8495 reply_outbuf(req
, 0, 0);
8497 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8499 END_PROFILE(SMBfindnclose
);
8503 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8504 struct trans_state
*state
)
8506 if (get_Protocol() >= PROTOCOL_NT1
) {
8507 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8508 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8511 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8512 if (state
->call
!= TRANSACT2_QFSINFO
&&
8513 state
->call
!= TRANSACT2_SETFSINFO
) {
8514 DEBUG(0,("handle_trans2: encryption required "
8516 (unsigned int)state
->call
));
8517 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8522 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8524 /* Now we must call the relevant TRANS2 function */
8525 switch(state
->call
) {
8526 case TRANSACT2_OPEN
:
8528 START_PROFILE(Trans2_open
);
8529 call_trans2open(conn
, req
,
8530 &state
->param
, state
->total_param
,
8531 &state
->data
, state
->total_data
,
8532 state
->max_data_return
);
8533 END_PROFILE(Trans2_open
);
8537 case TRANSACT2_FINDFIRST
:
8539 START_PROFILE(Trans2_findfirst
);
8540 call_trans2findfirst(conn
, req
,
8541 &state
->param
, state
->total_param
,
8542 &state
->data
, state
->total_data
,
8543 state
->max_data_return
);
8544 END_PROFILE(Trans2_findfirst
);
8548 case TRANSACT2_FINDNEXT
:
8550 START_PROFILE(Trans2_findnext
);
8551 call_trans2findnext(conn
, req
,
8552 &state
->param
, state
->total_param
,
8553 &state
->data
, state
->total_data
,
8554 state
->max_data_return
);
8555 END_PROFILE(Trans2_findnext
);
8559 case TRANSACT2_QFSINFO
:
8561 START_PROFILE(Trans2_qfsinfo
);
8562 call_trans2qfsinfo(conn
, req
,
8563 &state
->param
, state
->total_param
,
8564 &state
->data
, state
->total_data
,
8565 state
->max_data_return
);
8566 END_PROFILE(Trans2_qfsinfo
);
8570 case TRANSACT2_SETFSINFO
:
8572 START_PROFILE(Trans2_setfsinfo
);
8573 call_trans2setfsinfo(conn
, req
,
8574 &state
->param
, state
->total_param
,
8575 &state
->data
, state
->total_data
,
8576 state
->max_data_return
);
8577 END_PROFILE(Trans2_setfsinfo
);
8581 case TRANSACT2_QPATHINFO
:
8582 case TRANSACT2_QFILEINFO
:
8584 START_PROFILE(Trans2_qpathinfo
);
8585 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8586 &state
->param
, state
->total_param
,
8587 &state
->data
, state
->total_data
,
8588 state
->max_data_return
);
8589 END_PROFILE(Trans2_qpathinfo
);
8593 case TRANSACT2_SETPATHINFO
:
8594 case TRANSACT2_SETFILEINFO
:
8596 START_PROFILE(Trans2_setpathinfo
);
8597 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8598 &state
->param
, state
->total_param
,
8599 &state
->data
, state
->total_data
,
8600 state
->max_data_return
);
8601 END_PROFILE(Trans2_setpathinfo
);
8605 case TRANSACT2_FINDNOTIFYFIRST
:
8607 START_PROFILE(Trans2_findnotifyfirst
);
8608 call_trans2findnotifyfirst(conn
, req
,
8609 &state
->param
, state
->total_param
,
8610 &state
->data
, state
->total_data
,
8611 state
->max_data_return
);
8612 END_PROFILE(Trans2_findnotifyfirst
);
8616 case TRANSACT2_FINDNOTIFYNEXT
:
8618 START_PROFILE(Trans2_findnotifynext
);
8619 call_trans2findnotifynext(conn
, req
,
8620 &state
->param
, state
->total_param
,
8621 &state
->data
, state
->total_data
,
8622 state
->max_data_return
);
8623 END_PROFILE(Trans2_findnotifynext
);
8627 case TRANSACT2_MKDIR
:
8629 START_PROFILE(Trans2_mkdir
);
8630 call_trans2mkdir(conn
, req
,
8631 &state
->param
, state
->total_param
,
8632 &state
->data
, state
->total_data
,
8633 state
->max_data_return
);
8634 END_PROFILE(Trans2_mkdir
);
8638 case TRANSACT2_GET_DFS_REFERRAL
:
8640 START_PROFILE(Trans2_get_dfs_referral
);
8641 call_trans2getdfsreferral(conn
, req
,
8642 &state
->param
, state
->total_param
,
8643 &state
->data
, state
->total_data
,
8644 state
->max_data_return
);
8645 END_PROFILE(Trans2_get_dfs_referral
);
8649 case TRANSACT2_IOCTL
:
8651 START_PROFILE(Trans2_ioctl
);
8652 call_trans2ioctl(conn
, req
,
8653 &state
->param
, state
->total_param
,
8654 &state
->data
, state
->total_data
,
8655 state
->max_data_return
);
8656 END_PROFILE(Trans2_ioctl
);
8661 /* Error in request */
8662 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8663 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8667 /****************************************************************************
8668 Reply to a SMBtrans2.
8669 ****************************************************************************/
8671 void reply_trans2(struct smb_request
*req
)
8673 connection_struct
*conn
= req
->conn
;
8678 unsigned int tran_call
;
8679 struct trans_state
*state
;
8682 START_PROFILE(SMBtrans2
);
8684 if (req
->wct
< 14) {
8685 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8686 END_PROFILE(SMBtrans2
);
8690 dsoff
= SVAL(req
->vwv
+12, 0);
8691 dscnt
= SVAL(req
->vwv
+11, 0);
8692 psoff
= SVAL(req
->vwv
+10, 0);
8693 pscnt
= SVAL(req
->vwv
+9, 0);
8694 tran_call
= SVAL(req
->vwv
+14, 0);
8696 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8697 if (!NT_STATUS_IS_OK(result
)) {
8698 DEBUG(2, ("Got invalid trans2 request: %s\n",
8699 nt_errstr(result
)));
8700 reply_nterror(req
, result
);
8701 END_PROFILE(SMBtrans2
);
8706 switch (tran_call
) {
8707 /* List the allowed trans2 calls on IPC$ */
8708 case TRANSACT2_OPEN
:
8709 case TRANSACT2_GET_DFS_REFERRAL
:
8710 case TRANSACT2_QFILEINFO
:
8711 case TRANSACT2_QFSINFO
:
8712 case TRANSACT2_SETFSINFO
:
8715 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8716 END_PROFILE(SMBtrans2
);
8721 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8722 DEBUG(0, ("talloc failed\n"));
8723 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8724 END_PROFILE(SMBtrans2
);
8728 state
->cmd
= SMBtrans2
;
8730 state
->mid
= req
->mid
;
8731 state
->vuid
= req
->vuid
;
8732 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8733 state
->setup
= NULL
;
8734 state
->total_param
= SVAL(req
->vwv
+0, 0);
8735 state
->param
= NULL
;
8736 state
->total_data
= SVAL(req
->vwv
+1, 0);
8738 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8739 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8740 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8741 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8742 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8744 state
->call
= tran_call
;
8746 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8747 is so as a sanity check */
8748 if (state
->setup_count
!= 1) {
8750 * Need to have rc=0 for ioctl to get job id for OS/2.
8751 * Network printing will fail if function is not successful.
8752 * Similar function in reply.c will be used if protocol
8753 * is LANMAN1.0 instead of LM1.2X002.
8754 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8755 * outbuf doesn't have to be set(only job id is used).
8757 if ( (state
->setup_count
== 4)
8758 && (tran_call
== TRANSACT2_IOCTL
)
8759 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8760 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8761 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8763 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8764 DEBUG(2,("Transaction is %d\n",tran_call
));
8766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8767 END_PROFILE(SMBtrans2
);
8772 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8775 if (state
->total_data
) {
8777 if (trans_oob(state
->total_data
, 0, dscnt
)
8778 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8782 /* Can't use talloc here, the core routines do realloc on the
8783 * params and data. */
8784 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8785 if (state
->data
== NULL
) {
8786 DEBUG(0,("reply_trans2: data malloc fail for %u "
8787 "bytes !\n", (unsigned int)state
->total_data
));
8789 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8790 END_PROFILE(SMBtrans2
);
8794 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8797 if (state
->total_param
) {
8799 if (trans_oob(state
->total_param
, 0, pscnt
)
8800 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8804 /* Can't use talloc here, the core routines do realloc on the
8805 * params and data. */
8806 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8807 if (state
->param
== NULL
) {
8808 DEBUG(0,("reply_trans: param malloc fail for %u "
8809 "bytes !\n", (unsigned int)state
->total_param
));
8810 SAFE_FREE(state
->data
);
8812 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8813 END_PROFILE(SMBtrans2
);
8817 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8820 state
->received_data
= dscnt
;
8821 state
->received_param
= pscnt
;
8823 if ((state
->received_param
== state
->total_param
) &&
8824 (state
->received_data
== state
->total_data
)) {
8826 handle_trans2(conn
, req
, state
);
8828 SAFE_FREE(state
->data
);
8829 SAFE_FREE(state
->param
);
8831 END_PROFILE(SMBtrans2
);
8835 DLIST_ADD(conn
->pending_trans
, state
);
8837 /* We need to send an interim response then receive the rest
8838 of the parameter/data bytes */
8839 reply_outbuf(req
, 0, 0);
8840 show_msg((char *)req
->outbuf
);
8841 END_PROFILE(SMBtrans2
);
8846 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8847 SAFE_FREE(state
->data
);
8848 SAFE_FREE(state
->param
);
8850 END_PROFILE(SMBtrans2
);
8851 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8855 /****************************************************************************
8856 Reply to a SMBtranss2
8857 ****************************************************************************/
8859 void reply_transs2(struct smb_request
*req
)
8861 connection_struct
*conn
= req
->conn
;
8862 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8863 struct trans_state
*state
;
8865 START_PROFILE(SMBtranss2
);
8867 show_msg((const char *)req
->inbuf
);
8869 /* Windows clients expect all replies to
8870 a transact secondary (SMBtranss2 0x33)
8871 to have a command code of transact
8872 (SMBtrans2 0x32). See bug #8989
8873 and also [MS-CIFS] section 2.2.4.47.2
8876 req
->cmd
= SMBtrans2
;
8879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8880 END_PROFILE(SMBtranss2
);
8884 for (state
= conn
->pending_trans
; state
!= NULL
;
8885 state
= state
->next
) {
8886 if (state
->mid
== req
->mid
) {
8891 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8892 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8893 END_PROFILE(SMBtranss2
);
8897 /* Revise state->total_param and state->total_data in case they have
8898 changed downwards */
8900 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8901 state
->total_param
= SVAL(req
->vwv
+0, 0);
8902 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8903 state
->total_data
= SVAL(req
->vwv
+1, 0);
8905 pcnt
= SVAL(req
->vwv
+2, 0);
8906 poff
= SVAL(req
->vwv
+3, 0);
8907 pdisp
= SVAL(req
->vwv
+4, 0);
8909 dcnt
= SVAL(req
->vwv
+5, 0);
8910 doff
= SVAL(req
->vwv
+6, 0);
8911 ddisp
= SVAL(req
->vwv
+7, 0);
8913 state
->received_param
+= pcnt
;
8914 state
->received_data
+= dcnt
;
8916 if ((state
->received_data
> state
->total_data
) ||
8917 (state
->received_param
> state
->total_param
))
8921 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8922 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8925 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8929 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8930 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8933 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8936 if ((state
->received_param
< state
->total_param
) ||
8937 (state
->received_data
< state
->total_data
)) {
8938 END_PROFILE(SMBtranss2
);
8942 handle_trans2(conn
, req
, state
);
8944 DLIST_REMOVE(conn
->pending_trans
, state
);
8945 SAFE_FREE(state
->data
);
8946 SAFE_FREE(state
->param
);
8949 END_PROFILE(SMBtranss2
);
8954 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8955 DLIST_REMOVE(conn
->pending_trans
, state
);
8956 SAFE_FREE(state
->data
);
8957 SAFE_FREE(state
->param
);
8959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8960 END_PROFILE(SMBtranss2
);