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"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct
*conn
,
46 const SMB_STRUCT_STAT
*psbuf
);
48 static char *store_file_unix_basic_info2(connection_struct
*conn
,
51 const SMB_STRUCT_STAT
*psbuf
);
53 /********************************************************************
54 The canonical "check access" based on object handle or path function.
55 ********************************************************************/
57 NTSTATUS
check_access(connection_struct
*conn
,
59 const struct smb_filename
*smb_fname
,
63 if (!(fsp
->access_mask
& access_mask
)) {
64 return NT_STATUS_ACCESS_DENIED
;
67 NTSTATUS status
= smbd_check_access_rights(conn
,
70 if (!NT_STATUS_IS_OK(status
)) {
77 /********************************************************************
78 Roundup a value to the nearest allocation roundup size boundary.
79 Only do this for Windows clients.
80 ********************************************************************/
82 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
84 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
86 /* Only roundup for Windows clients. */
87 enum remote_arch_types ra_type
= get_remote_arch();
88 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
89 val
= SMB_ROUNDUP(val
,rval
);
94 /********************************************************************
95 Create a 64 bit FileIndex. If the file is on the same device as
96 the root of the share, just return the 64-bit inode. If it isn't,
97 mangle as we used to do.
98 ********************************************************************/
100 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
103 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
104 return (uint64_t)psbuf
->st_ex_ino
;
106 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
107 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
111 /****************************************************************************
112 Utility functions for dealing with extended attributes.
113 ****************************************************************************/
115 /****************************************************************************
116 Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
119 static bool samba_private_attr_name(const char *unix_ea_name
)
121 static const char * const prohibited_ea_names
[] = {
122 SAMBA_POSIX_INHERITANCE_EA_NAME
,
123 SAMBA_XATTR_DOS_ATTRIB
,
131 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
132 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
135 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
136 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
142 /****************************************************************************
143 Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
146 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
147 files_struct
*fsp
, const char *fname
,
148 const char *ea_name
, struct ea_struct
*pea
)
150 /* Get the value of this xattr. Max size is 64k. */
151 size_t attr_size
= 256;
157 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
159 return NT_STATUS_NO_MEMORY
;
162 if (fsp
&& fsp
->fh
->fd
!= -1) {
163 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
165 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
168 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
174 return map_nt_error_from_unix(errno
);
177 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
178 dump_data(10, (uint8
*)val
, sizeret
);
181 if (strnequal(ea_name
, "user.", 5)) {
182 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
184 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
186 if (pea
->name
== NULL
) {
188 return NT_STATUS_NO_MEMORY
;
190 pea
->value
.data
= (unsigned char *)val
;
191 pea
->value
.length
= (size_t)sizeret
;
195 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
196 files_struct
*fsp
, const char *fname
,
197 char ***pnames
, size_t *pnum_names
)
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size
= 1024;
201 char *ea_namelist
= NULL
;
206 ssize_t sizeret
= -1;
208 if (!lp_ea_support(SNUM(conn
))) {
217 * TALLOC the result early to get the talloc hierarchy right.
220 names
= talloc_array(mem_ctx
, char *, 1);
222 DEBUG(0, ("talloc failed\n"));
223 return NT_STATUS_NO_MEMORY
;
226 while (ea_namelist_size
<= 65536) {
228 ea_namelist
= talloc_realloc(
229 names
, ea_namelist
, char, ea_namelist_size
);
230 if (ea_namelist
== NULL
) {
231 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY
;
236 if (fsp
&& fsp
->fh
->fd
!= -1) {
237 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
240 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
244 if ((sizeret
== -1) && (errno
== ERANGE
)) {
245 ea_namelist_size
*= 2;
254 return map_nt_error_from_unix(errno
);
257 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258 (unsigned int)sizeret
));
270 * Ensure the result is 0-terminated
273 if (ea_namelist
[sizeret
-1] != '\0') {
275 return NT_STATUS_INTERNAL_ERROR
;
283 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
287 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
289 DEBUG(0, ("talloc failed\n"));
291 return NT_STATUS_NO_MEMORY
;
297 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
298 names
[num_names
++] = p
;
306 *pnum_names
= num_names
;
310 /****************************************************************************
311 Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
314 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
315 const char *fname
, size_t *pea_total_len
)
317 /* Get a list of all xattrs. Max namesize is 64k. */
320 struct ea_list
*ea_list_head
= NULL
;
325 if (!lp_ea_support(SNUM(conn
))) {
329 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
332 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
336 for (i
=0; i
<num_names
; i
++) {
337 struct ea_list
*listp
;
340 if (strnequal(names
[i
], "system.", 7)
341 || samba_private_attr_name(names
[i
]))
344 listp
= talloc(mem_ctx
, struct ea_list
);
349 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
355 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
358 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
360 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
362 (unsigned int)listp
->ea
.value
.length
));
364 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
368 /* Add on 4 for total length. */
369 if (*pea_total_len
) {
373 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374 (unsigned int)*pea_total_len
));
379 /****************************************************************************
380 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
382 ****************************************************************************/
384 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
385 connection_struct
*conn
, struct ea_list
*ea_list
)
387 unsigned int ret_data_size
= 4;
390 SMB_ASSERT(total_data_size
>= 4);
392 if (!lp_ea_support(SNUM(conn
))) {
397 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
400 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
401 dos_namelen
= strlen(dos_ea_name
);
402 if (dos_namelen
> 255 || dos_namelen
== 0) {
405 if (ea_list
->ea
.value
.length
> 65535) {
408 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
412 /* We know we have room. */
413 SCVAL(p
,0,ea_list
->ea
.flags
);
414 SCVAL(p
,1,dos_namelen
);
415 SSVAL(p
,2,ea_list
->ea
.value
.length
);
416 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
417 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
419 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
420 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
423 ret_data_size
= PTR_DIFF(p
, pdata
);
424 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
425 SIVAL(pdata
,0,ret_data_size
);
426 return ret_data_size
;
429 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
431 unsigned int total_data_size
,
432 unsigned int *ret_data_size
,
433 connection_struct
*conn
,
434 struct ea_list
*ea_list
)
436 uint8_t *p
= (uint8_t *)pdata
;
437 uint8_t *last_start
= NULL
;
441 if (!lp_ea_support(SNUM(conn
))) {
442 return NT_STATUS_NO_EAS_ON_FILE
;
445 for (; ea_list
; ea_list
= ea_list
->next
) {
451 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
455 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
456 dos_namelen
= strlen(dos_ea_name
);
457 if (dos_namelen
> 255 || dos_namelen
== 0) {
458 return NT_STATUS_INTERNAL_ERROR
;
460 if (ea_list
->ea
.value
.length
> 65535) {
461 return NT_STATUS_INTERNAL_ERROR
;
464 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
467 size_t pad
= 4 - (this_size
% 4);
471 if (this_size
> total_data_size
) {
472 return NT_STATUS_INFO_LENGTH_MISMATCH
;
475 /* We know we have room. */
476 SIVAL(p
, 0x00, 0); /* next offset */
477 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
478 SCVAL(p
, 0x05, dos_namelen
);
479 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
480 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
481 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
483 total_data_size
-= this_size
;
487 *ret_data_size
= PTR_DIFF(p
, pdata
);
488 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
492 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
494 size_t total_ea_len
= 0;
495 TALLOC_CTX
*mem_ctx
= NULL
;
497 if (!lp_ea_support(SNUM(conn
))) {
500 mem_ctx
= talloc_tos();
501 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
505 /****************************************************************************
506 Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
509 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
512 TALLOC_CTX
*mem_ctx
= talloc_tos();
513 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
515 for (; ea_list
; ea_list
= ea_list
->next
) {
516 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
517 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518 &unix_ea_name
[5], ea_list
->ea
.name
));
519 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
525 /****************************************************************************
526 Set or delete an extended attribute.
527 ****************************************************************************/
529 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
530 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
535 if (!lp_ea_support(SNUM(conn
))) {
536 return NT_STATUS_EAS_NOT_SUPPORTED
;
539 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
540 if (!NT_STATUS_IS_OK(status
)) {
544 /* For now setting EAs on streams isn't supported. */
545 fname
= smb_fname
->base_name
;
547 for (;ea_list
; ea_list
= ea_list
->next
) {
549 fstring unix_ea_name
;
551 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
552 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
554 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
556 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
558 if (samba_private_attr_name(unix_ea_name
)) {
559 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
560 return NT_STATUS_ACCESS_DENIED
;
563 if (ea_list
->ea
.value
.length
== 0) {
564 /* Remove the attribute. */
565 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
566 DEBUG(10,("set_ea: deleting ea name %s on "
567 "file %s by file descriptor.\n",
568 unix_ea_name
, fsp_str_dbg(fsp
)));
569 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
571 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572 unix_ea_name
, fname
));
573 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
576 /* Removing a non existent attribute always succeeds. */
577 if (ret
== -1 && errno
== ENOATTR
) {
578 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
584 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
585 DEBUG(10,("set_ea: setting ea name %s on file "
586 "%s by file descriptor.\n",
587 unix_ea_name
, fsp_str_dbg(fsp
)));
588 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
589 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
591 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592 unix_ea_name
, fname
));
593 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
594 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
600 if (errno
== ENOTSUP
) {
601 return NT_STATUS_EAS_NOT_SUPPORTED
;
604 return map_nt_error_from_unix(errno
);
610 /****************************************************************************
611 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
614 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
616 struct ea_list
*ea_list_head
= NULL
;
617 size_t converted_size
, offset
= 0;
619 while (offset
+ 2 < data_size
) {
620 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
621 unsigned int namelen
= CVAL(pdata
,offset
);
623 offset
++; /* Go past the namelen byte. */
625 /* integer wrap paranioa. */
626 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
627 (offset
> data_size
) || (namelen
> data_size
) ||
628 (offset
+ namelen
>= data_size
)) {
631 /* Ensure the name is null terminated. */
632 if (pdata
[offset
+ namelen
] != '\0') {
635 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
637 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638 "failed: %s", strerror(errno
)));
644 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
645 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
646 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
652 /****************************************************************************
653 Read one EA list entry from the buffer.
654 ****************************************************************************/
656 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
658 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
660 unsigned int namelen
;
661 size_t converted_size
;
671 eal
->ea
.flags
= CVAL(pdata
,0);
672 namelen
= CVAL(pdata
,1);
673 val_len
= SVAL(pdata
,2);
675 if (4 + namelen
+ 1 + val_len
> data_size
) {
679 /* Ensure the name is null terminated. */
680 if (pdata
[namelen
+ 4] != '\0') {
683 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
684 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
691 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
692 if (!eal
->ea
.value
.data
) {
696 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
698 /* Ensure we're null terminated just in case we print the value. */
699 eal
->ea
.value
.data
[val_len
] = '\0';
700 /* But don't count the null. */
701 eal
->ea
.value
.length
--;
704 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
707 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
708 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
713 /****************************************************************************
714 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
717 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
719 struct ea_list
*ea_list_head
= NULL
;
721 size_t bytes_used
= 0;
723 while (offset
< data_size
) {
724 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
730 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
731 offset
+= bytes_used
;
737 /****************************************************************************
738 Count the total EA size needed.
739 ****************************************************************************/
741 static size_t ea_list_size(struct ea_list
*ealist
)
744 struct ea_list
*listp
;
747 for (listp
= ealist
; listp
; listp
= listp
->next
) {
748 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
749 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
751 /* Add on 4 for total length. */
759 /****************************************************************************
760 Return a union of EA's from a file list and a list of names.
761 The TALLOC context for the two lists *MUST* be identical as we steal
762 memory from one list to add to another. JRA.
763 ****************************************************************************/
765 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
767 struct ea_list
*nlistp
, *flistp
;
769 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
770 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
771 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
777 /* Copy the data from this entry. */
778 nlistp
->ea
.flags
= flistp
->ea
.flags
;
779 nlistp
->ea
.value
= flistp
->ea
.value
;
782 nlistp
->ea
.flags
= 0;
783 ZERO_STRUCT(nlistp
->ea
.value
);
787 *total_ea_len
= ea_list_size(name_list
);
791 /****************************************************************************
792 Send the required number of replies back.
793 We assume all fields other than the data fields are
794 set correctly for the type of call.
795 HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
798 void send_trans2_replies(connection_struct
*conn
,
799 struct smb_request
*req
,
806 /* As we are using a protocol > LANMAN1 then the max_send
807 variable must have been set in the sessetupX call.
808 This takes precedence over the max_xmit field in the
809 global struct. These different max_xmit variables should
810 be merged as this is now too confusing */
812 int data_to_send
= datasize
;
813 int params_to_send
= paramsize
;
815 const char *pp
= params
;
816 const char *pd
= pdata
;
817 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
818 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819 int data_alignment_offset
= 0;
820 bool overflow
= False
;
821 struct smbd_server_connection
*sconn
= req
->sconn
;
822 int max_send
= sconn
->smb1
.sessions
.max_send
;
824 /* Modify the data_to_send and datasize and set the error if
825 we're trying to send more than max_data_bytes. We still send
826 the part of the packet(s) that fit. Strange, but needed
829 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
830 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831 max_data_bytes
, datasize
));
832 datasize
= data_to_send
= max_data_bytes
;
836 /* If there genuinely are no parameters or data to send just send the empty packet */
838 if(params_to_send
== 0 && data_to_send
== 0) {
839 reply_outbuf(req
, 10, 0);
840 show_msg((char *)req
->outbuf
);
841 if (!srv_send_smb(sconn
,
844 IS_CONN_ENCRYPTED(conn
),
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req
->outbuf
);
852 /* When sending params and data ensure that both are nicely aligned */
853 /* Only do this alignment when there is also data to send - else
854 can cause NT redirector problems. */
856 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
857 data_alignment_offset
= 4 - (params_to_send
% 4);
859 /* Space is bufsize minus Netbios over TCP header minus SMB header */
860 /* The alignment_offset is to align the param bytes on an even byte
861 boundary. NT 4.0 Beta needs this to work correctly. */
863 useable_space
= max_send
- (smb_size
866 + data_alignment_offset
);
868 if (useable_space
< 0) {
869 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870 "= %d!!!", useable_space
));
871 exit_server_cleanly("send_trans2_replies: Not enough space");
874 while (params_to_send
|| data_to_send
) {
875 /* Calculate whether we will totally or partially fill this packet */
877 total_sent_thistime
= params_to_send
+ data_to_send
;
879 /* We can never send more than useable_space */
881 * Note that 'useable_space' does not include the alignment offsets,
882 * but we must include the alignment offsets in the calculation of
883 * the length of the data we send over the wire, as the alignment offsets
884 * are sent here. Fix from Marc_Jacobsen@hp.com.
887 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
889 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
890 + data_alignment_offset
);
893 * We might have SMBtrans2s in req which was transferred to
894 * the outbuf, fix that.
896 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
898 /* Set total params and data to be sent */
899 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
900 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
902 /* Calculate how many parameters and data we can fit into
903 * this packet. Parameters get precedence
906 params_sent_thistime
= MIN(params_to_send
,useable_space
);
907 data_sent_thistime
= useable_space
- params_sent_thistime
;
908 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
910 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
912 /* smb_proff is the offset from the start of the SMB header to the
913 parameter bytes, however the first 4 bytes of outbuf are
914 the Netbios over TCP header. Thus use smb_base() to subtract
915 them from the calculation */
917 SSVAL(req
->outbuf
,smb_proff
,
918 ((smb_buf(req
->outbuf
)+alignment_offset
)
919 - smb_base(req
->outbuf
)));
921 if(params_sent_thistime
== 0)
922 SSVAL(req
->outbuf
,smb_prdisp
,0);
924 /* Absolute displacement of param bytes sent in this packet */
925 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
927 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
928 if(data_sent_thistime
== 0) {
929 SSVAL(req
->outbuf
,smb_droff
,0);
930 SSVAL(req
->outbuf
,smb_drdisp
, 0);
932 /* The offset of the data bytes is the offset of the
933 parameter bytes plus the number of parameters being sent this time */
934 SSVAL(req
->outbuf
, smb_droff
,
935 ((smb_buf(req
->outbuf
)+alignment_offset
)
936 - smb_base(req
->outbuf
))
937 + params_sent_thistime
+ data_alignment_offset
);
938 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
941 /* Initialize the padding for alignment */
943 if (alignment_offset
!= 0) {
944 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
947 /* Copy the param bytes into the packet */
949 if(params_sent_thistime
) {
950 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
951 params_sent_thistime
);
954 /* Copy in the data bytes */
955 if(data_sent_thistime
) {
956 if (data_alignment_offset
!= 0) {
957 memset((smb_buf(req
->outbuf
)+alignment_offset
+
958 params_sent_thistime
), 0,
959 data_alignment_offset
);
961 memcpy(smb_buf(req
->outbuf
)+alignment_offset
962 +params_sent_thistime
+data_alignment_offset
,
963 pd
,data_sent_thistime
);
966 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967 params_sent_thistime
, data_sent_thistime
, useable_space
));
968 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969 params_to_send
, data_to_send
, paramsize
, datasize
));
972 error_packet_set((char *)req
->outbuf
,
973 ERRDOS
,ERRbufferoverflow
,
974 STATUS_BUFFER_OVERFLOW
,
978 /* Send the packet */
979 show_msg((char *)req
->outbuf
);
980 if (!srv_send_smb(sconn
,
983 IS_CONN_ENCRYPTED(conn
),
985 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
987 TALLOC_FREE(req
->outbuf
);
989 pp
+= params_sent_thistime
;
990 pd
+= data_sent_thistime
;
992 params_to_send
-= params_sent_thistime
;
993 data_to_send
-= data_sent_thistime
;
996 if(params_to_send
< 0 || data_to_send
< 0) {
997 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998 params_to_send
, data_to_send
));
1006 /****************************************************************************
1007 Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1010 static void call_trans2open(connection_struct
*conn
,
1011 struct smb_request
*req
,
1012 char **pparams
, int total_params
,
1013 char **ppdata
, int total_data
,
1014 unsigned int max_data_bytes
)
1016 struct smb_filename
*smb_fname
= NULL
;
1017 char *params
= *pparams
;
1018 char *pdata
= *ppdata
;
1021 bool oplock_request
;
1023 bool return_additional_info
;
1032 int fattr
=0,mtime
=0;
1033 SMB_INO_T inode
= 0;
1036 struct ea_list
*ea_list
= NULL
;
1041 uint32 create_disposition
;
1042 uint32 create_options
= 0;
1043 uint32_t private_flags
= 0;
1044 TALLOC_CTX
*ctx
= talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params
< 29) {
1051 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1055 flags
= SVAL(params
, 0);
1056 deny_mode
= SVAL(params
, 2);
1057 open_attr
= SVAL(params
,6);
1058 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1059 if (oplock_request
) {
1060 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1064 return_additional_info
= BITSETW(params
,0);
1065 open_sattr
= SVAL(params
, 4);
1066 open_time
= make_unix_date3(params
+8);
1068 open_ofun
= SVAL(params
,12);
1069 open_size
= IVAL(params
,14);
1070 pname
= ¶ms
[28];
1073 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1077 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1078 total_params
- 28, STR_TERMINATE
,
1080 if (!NT_STATUS_IS_OK(status
)) {
1081 reply_nterror(req
, status
);
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1087 (unsigned int)open_ofun
, open_size
));
1089 status
= filename_convert(ctx
,
1091 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1096 if (!NT_STATUS_IS_OK(status
)) {
1097 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1098 reply_botherror(req
,
1099 NT_STATUS_PATH_NOT_COVERED
,
1100 ERRSRV
, ERRbadpath
);
1103 reply_nterror(req
, status
);
1107 if (open_ofun
== 0) {
1108 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1112 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1114 &access_mask
, &share_mode
,
1115 &create_disposition
,
1118 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1122 /* Any data in this call is an EA list. */
1123 if (total_data
&& (total_data
!= 4)) {
1124 if (total_data
< 10) {
1125 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1129 if (IVAL(pdata
,0) > total_data
) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata
,0), (unsigned int)total_data
));
1132 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1136 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1139 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1143 if (!lp_ea_support(SNUM(conn
))) {
1144 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1149 status
= SMB_VFS_CREATE_FILE(
1152 0, /* root_dir_fid */
1153 smb_fname
, /* fname */
1154 access_mask
, /* access_mask */
1155 share_mode
, /* share_access */
1156 create_disposition
, /* create_disposition*/
1157 create_options
, /* create_options */
1158 open_attr
, /* file_attributes */
1159 oplock_request
, /* oplock_request */
1160 open_size
, /* allocation_size */
1163 ea_list
, /* ea_list */
1165 &smb_action
); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status
)) {
1168 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1169 /* We have re-scheduled this call. */
1172 reply_openerror(req
, status
);
1176 size
= get_file_size_stat(&smb_fname
->st
);
1177 fattr
= dos_mode(conn
, smb_fname
);
1178 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1179 inode
= smb_fname
->st
.st_ex_ino
;
1180 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1181 close_file(req
, fsp
, ERROR_CLOSE
);
1182 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1188 if(*pparams
== NULL
) {
1189 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1194 SSVAL(params
,0,fsp
->fnum
);
1195 SSVAL(params
,2,fattr
);
1196 srv_put_dos_date2(params
,4, mtime
);
1197 SIVAL(params
,8, (uint32
)size
);
1198 SSVAL(params
,12,deny_mode
);
1199 SSVAL(params
,14,0); /* open_type - file or directory. */
1200 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1203 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1206 SSVAL(params
,18,smb_action
);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params
,20,inode
);
1212 SSVAL(params
,24,0); /* Padding. */
1214 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1215 fsp
->fsp_name
->base_name
);
1216 SIVAL(params
, 26, ea_size
);
1218 SIVAL(params
, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1224 TALLOC_FREE(smb_fname
);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild
,
1235 bool case_sensitive
,
1239 if (mask
[0] == '.' && mask
[1] == 0) {
1247 if (case_sensitive
) {
1248 return strcmp(str
,mask
)==0;
1250 return strcasecmp_m(str
,mask
) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32
unix_filetype(mode_t mode
)
1261 return UNIX_TYPE_FILE
;
1262 else if(S_ISDIR(mode
))
1263 return UNIX_TYPE_DIR
;
1265 else if(S_ISLNK(mode
))
1266 return UNIX_TYPE_SYMLINK
;
1269 else if(S_ISCHR(mode
))
1270 return UNIX_TYPE_CHARDEV
;
1273 else if(S_ISBLK(mode
))
1274 return UNIX_TYPE_BLKDEV
;
1277 else if(S_ISFIFO(mode
))
1278 return UNIX_TYPE_FIFO
;
1281 else if(S_ISSOCK(mode
))
1282 return UNIX_TYPE_SOCKET
;
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1286 return UNIX_TYPE_UNKNOWN
;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1295 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1296 const SMB_STRUCT_STAT
*psbuf
,
1298 enum perm_type ptype
,
1303 if (perms
== SMB_MODE_NO_CHANGE
) {
1304 if (!VALID_STAT(*psbuf
)) {
1305 return NT_STATUS_INVALID_PARAMETER
;
1307 *ret_perms
= psbuf
->st_ex_mode
;
1308 return NT_STATUS_OK
;
1312 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1313 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1314 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1315 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1316 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1317 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1318 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1319 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1320 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1322 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1325 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1328 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1333 /* Apply mode mask */
1334 ret
&= lp_create_mask(SNUM(conn
));
1335 /* Add in force bits */
1336 ret
|= lp_force_create_mode(SNUM(conn
));
1339 ret
&= lp_dir_mask(SNUM(conn
));
1340 /* Add in force bits */
1341 ret
|= lp_force_dir_mode(SNUM(conn
));
1343 case PERM_EXISTING_FILE
:
1344 /* Apply mode mask */
1345 ret
&= lp_security_mask(SNUM(conn
));
1346 /* Add in force bits */
1347 ret
|= lp_force_security_mode(SNUM(conn
));
1349 case PERM_EXISTING_DIR
:
1350 /* Apply mode mask */
1351 ret
&= lp_dir_security_mask(SNUM(conn
));
1352 /* Add in force bits */
1353 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1358 return NT_STATUS_OK
;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct
*conn
,
1367 const char *pathname
,
1368 SMB_STRUCT_STAT
*psbuf
)
1370 int saved_errno
= errno
;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn
)) &&
1373 is_msdfs_link(conn
, pathname
, psbuf
)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1378 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1379 errno
= saved_errno
;
1382 errno
= saved_errno
;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state
{
1392 connection_struct
*conn
;
1393 uint32_t info_level
;
1394 bool check_mangled_names
;
1396 bool got_exact_match
;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1405 struct smbd_dirptr_lanman2_state
*state
=
1406 (struct smbd_dirptr_lanman2_state
*)private_data
;
1408 char mangled_name
[13]; /* mangled 8.3 name. */
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1414 ok
= name_to_8_3(dname
, mangled_name
,
1415 true, state
->conn
->params
);
1419 fname
= mangled_name
;
1424 got_match
= exact_match(state
->has_wild
,
1425 state
->conn
->case_sensitive
,
1427 state
->got_exact_match
= got_match
;
1429 got_match
= mask_match(fname
, mask
,
1430 state
->conn
->case_sensitive
);
1433 if(!got_match
&& state
->check_mangled_names
&&
1434 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok
= name_to_8_3(fname
, mangled_name
,
1443 false, state
->conn
->params
);
1448 got_match
= exact_match(state
->has_wild
,
1449 state
->conn
->case_sensitive
,
1450 mangled_name
, mask
);
1451 state
->got_exact_match
= got_match
;
1453 got_match
= mask_match(mangled_name
, mask
,
1454 state
->conn
->case_sensitive
);
1462 *_fname
= talloc_strdup(ctx
, fname
);
1463 if (*_fname
== NULL
) {
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1472 struct smb_filename
*smb_fname
,
1475 struct smbd_dirptr_lanman2_state
*state
=
1476 (struct smbd_dirptr_lanman2_state
*)private_data
;
1477 bool ms_dfs_link
= false;
1480 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1481 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname
),
1488 } else if (!VALID_STAT(smb_fname
->st
) &&
1489 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1490 /* Needed to show the msdfs symlinks as
1493 ms_dfs_link
= check_msdfs_link(state
->conn
,
1494 smb_fname
->base_name
,
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname
),
1506 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1508 mode
= dos_mode(state
->conn
, smb_fname
);
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1516 connection_struct
*conn
,
1518 uint32_t info_level
,
1519 struct ea_list
*name_list
,
1520 bool check_mangled_names
,
1521 bool requires_resume_key
,
1524 const struct smb_filename
*smb_fname
,
1525 int space_remaining
,
1532 uint64_t *last_entry_off
)
1534 char *p
, *q
, *pdata
= *ppdata
;
1536 uint64_t file_size
= 0;
1537 uint64_t allocation_size
= 0;
1538 uint64_t file_index
= 0;
1540 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1541 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1543 char *last_entry_ptr
;
1548 *out_of_space
= false;
1550 ZERO_STRUCT(mdate_ts
);
1551 ZERO_STRUCT(adate_ts
);
1552 ZERO_STRUCT(create_date_ts
);
1553 ZERO_STRUCT(cdate_ts
);
1555 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1556 file_size
= get_file_size_stat(&smb_fname
->st
);
1558 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1560 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1562 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1563 adate_ts
= smb_fname
->st
.st_ex_atime
;
1564 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1565 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1567 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1568 dos_filetime_timespec(&create_date_ts
);
1569 dos_filetime_timespec(&mdate_ts
);
1570 dos_filetime_timespec(&adate_ts
);
1571 dos_filetime_timespec(&cdate_ts
);
1574 create_date
= convert_timespec_to_time_t(create_date_ts
);
1575 mdate
= convert_timespec_to_time_t(mdate_ts
);
1576 adate
= convert_timespec_to_time_t(adate_ts
);
1578 /* align the record */
1579 SMB_ASSERT(align
>= 1);
1581 off
= (int)PTR_DIFF(pdata
, base_data
);
1582 pad
= (off
+ (align
-1)) & ~(align
-1);
1585 if (pad
&& pad
> space_remaining
) {
1586 *out_of_space
= true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1591 return false; /* Not finished - just out of space */
1595 /* initialize padding to 0 */
1597 memset(pdata
, 0, pad
);
1599 space_remaining
-= pad
;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1611 switch (info_level
) {
1612 case SMB_FIND_INFO_STANDARD
:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1614 if(requires_resume_key
) {
1618 srv_put_dos_date2(p
,0,create_date
);
1619 srv_put_dos_date2(p
,4,adate
);
1620 srv_put_dos_date2(p
,8,mdate
);
1621 SIVAL(p
,12,(uint32
)file_size
);
1622 SIVAL(p
,16,(uint32
)allocation_size
);
1626 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1627 p
+= ucs2_align(base_data
, p
, 0);
1629 len
= srvstr_push(base_data
, flags2
, p
,
1630 fname
, PTR_DIFF(end_data
, p
),
1632 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1634 SCVAL(nameptr
, -1, len
- 2);
1636 SCVAL(nameptr
, -1, 0);
1640 SCVAL(nameptr
, -1, len
- 1);
1642 SCVAL(nameptr
, -1, 0);
1648 case SMB_FIND_EA_SIZE
:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key
) {
1654 srv_put_dos_date2(p
,0,create_date
);
1655 srv_put_dos_date2(p
,4,adate
);
1656 srv_put_dos_date2(p
,8,mdate
);
1657 SIVAL(p
,12,(uint32
)file_size
);
1658 SIVAL(p
,16,(uint32
)allocation_size
);
1661 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1662 smb_fname
->base_name
);
1663 SIVAL(p
,22,ea_size
); /* Extended attributes */
1667 len
= srvstr_push(base_data
, flags2
,
1668 p
, fname
, PTR_DIFF(end_data
, p
),
1669 STR_TERMINATE
| STR_NOALIGN
);
1670 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1683 SCVAL(nameptr
,0,len
);
1685 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1688 case SMB_FIND_EA_LIST
:
1690 struct ea_list
*file_list
= NULL
;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1697 if (requires_resume_key
) {
1701 srv_put_dos_date2(p
,0,create_date
);
1702 srv_put_dos_date2(p
,4,adate
);
1703 srv_put_dos_date2(p
,8,mdate
);
1704 SIVAL(p
,12,(uint32
)file_size
);
1705 SIVAL(p
,16,(uint32
)allocation_size
);
1707 p
+= 22; /* p now points to the EA area. */
1709 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1710 smb_fname
->base_name
,
1712 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1717 *out_of_space
= true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1722 return False
; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1728 len
= srvstr_push(base_data
, flags2
,
1729 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1730 STR_TERMINATE
| STR_NOALIGN
);
1731 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1744 SCVAL(nameptr
,0,len
);
1746 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1754 SIVAL(p
,0,reskey
); p
+= 4;
1755 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1756 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1757 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1758 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1759 SOFF_T(p
,0,file_size
); p
+= 8;
1760 SOFF_T(p
,0,allocation_size
); p
+= 8;
1761 SIVAL(p
,0,mode
); p
+= 4;
1762 q
= p
; p
+= 4; /* q is placeholder for name length. */
1764 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1765 smb_fname
->base_name
);
1766 SIVAL(p
,0,ea_size
); /* Extended attributes */
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3
&& check_mangled_names
) {
1774 char mangled_name
[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname
,mangled_name
,True
,
1777 /* Error - mangle failed ! */
1778 memset(mangled_name
,'\0',12);
1780 mangled_name
[12] = 0;
1781 len
= srvstr_push(base_data
, flags2
,
1782 p
+2, mangled_name
, 24,
1783 STR_UPPER
|STR_UNICODE
);
1785 memset(p
+ 2 + len
,'\0',24 - len
);
1792 len
= srvstr_push(base_data
, flags2
, p
,
1793 fname
, PTR_DIFF(end_data
, p
),
1794 STR_TERMINATE_ASCII
);
1798 len
= PTR_DIFF(p
, pdata
);
1799 pad
= (len
+ (align
-1)) & ~(align
-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1807 * set padding to zero
1810 memset(p
, 0, pad
- len
);
1817 case SMB_FIND_FILE_DIRECTORY_INFO
:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1820 SIVAL(p
,0,reskey
); p
+= 4;
1821 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1822 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1823 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1824 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1825 SOFF_T(p
,0,file_size
); p
+= 8;
1826 SOFF_T(p
,0,allocation_size
); p
+= 8;
1827 SIVAL(p
,0,mode
); p
+= 4;
1828 len
= srvstr_push(base_data
, flags2
,
1829 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1830 STR_TERMINATE_ASCII
);
1834 len
= PTR_DIFF(p
, pdata
);
1835 pad
= (len
+ (align
-1)) & ~(align
-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1843 * set padding to zero
1846 memset(p
, 0, pad
- len
);
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1856 SIVAL(p
,0,reskey
); p
+= 4;
1857 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1858 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1859 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1861 SOFF_T(p
,0,file_size
); p
+= 8;
1862 SOFF_T(p
,0,allocation_size
); p
+= 8;
1863 SIVAL(p
,0,mode
); p
+= 4;
1864 q
= p
; p
+= 4; /* q is placeholder for name length. */
1866 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1867 smb_fname
->base_name
);
1868 SIVAL(p
,0,ea_size
); /* Extended attributes */
1871 len
= srvstr_push(base_data
, flags2
, p
,
1872 fname
, PTR_DIFF(end_data
, p
),
1873 STR_TERMINATE_ASCII
);
1877 len
= PTR_DIFF(p
, pdata
);
1878 pad
= (len
+ (align
-1)) & ~(align
-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1886 * set padding to zero
1889 memset(p
, 0, pad
- len
);
1896 case SMB_FIND_FILE_NAMES_INFO
:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1899 SIVAL(p
,0,reskey
); p
+= 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len
= srvstr_push(base_data
, flags2
, p
,
1904 fname
, PTR_DIFF(end_data
, p
),
1905 STR_TERMINATE_ASCII
);
1909 len
= PTR_DIFF(p
, pdata
);
1910 pad
= (len
+ (align
-1)) & ~(align
-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1918 * set padding to zero
1921 memset(p
, 0, pad
- len
);
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1931 SIVAL(p
,0,reskey
); p
+= 4;
1932 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1933 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1934 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1935 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1936 SOFF_T(p
,0,file_size
); p
+= 8;
1937 SOFF_T(p
,0,allocation_size
); p
+= 8;
1938 SIVAL(p
,0,mode
); p
+= 4;
1939 q
= p
; p
+= 4; /* q is placeholder for name length. */
1941 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1942 smb_fname
->base_name
);
1943 SIVAL(p
,0,ea_size
); /* Extended attributes */
1946 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1947 SBVAL(p
,0,file_index
); p
+= 8;
1948 len
= srvstr_push(base_data
, flags2
, p
,
1949 fname
, PTR_DIFF(end_data
, p
),
1950 STR_TERMINATE_ASCII
);
1954 len
= PTR_DIFF(p
, pdata
);
1955 pad
= (len
+ (align
-1)) & ~(align
-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1963 * set padding to zero
1966 memset(p
, 0, pad
- len
);
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1977 SIVAL(p
,0,reskey
); p
+= 4;
1978 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1979 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1980 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1981 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1982 SOFF_T(p
,0,file_size
); p
+= 8;
1983 SOFF_T(p
,0,allocation_size
); p
+= 8;
1984 SIVAL(p
,0,mode
); p
+= 4;
1985 q
= p
; p
+= 4; /* q is placeholder for name length */
1987 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1988 smb_fname
->base_name
);
1989 SIVAL(p
,0,ea_size
); /* Extended attributes */
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3
&& check_mangled_names
) {
1997 char mangled_name
[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname
,mangled_name
,True
,
2000 /* Error - mangle failed ! */
2001 memset(mangled_name
,'\0',12);
2003 mangled_name
[12] = 0;
2004 len
= srvstr_push(base_data
, flags2
,
2005 p
+2, mangled_name
, 24,
2006 STR_UPPER
|STR_UNICODE
);
2009 memset(p
+ 2 + len
,'\0',24 - len
);
2016 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2017 SBVAL(p
,0,file_index
); p
+= 8;
2018 len
= srvstr_push(base_data
, flags2
, p
,
2019 fname
, PTR_DIFF(end_data
, p
),
2020 STR_TERMINATE_ASCII
);
2024 len
= PTR_DIFF(p
, pdata
);
2025 pad
= (len
+ (align
-1)) & ~(align
-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2033 * set padding to zero
2036 memset(p
, 0, pad
- len
);
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX
:
2046 case SMB_FIND_FILE_UNIX_INFO2
:
2048 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level
== SMB_FIND_FILE_UNIX
) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p
= store_file_unix_basic(conn
, p
,
2055 NULL
, &smb_fname
->st
);
2056 len
= srvstr_push(base_data
, flags2
, p
,
2057 fname
, PTR_DIFF(end_data
, p
),
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p
= store_file_unix_basic_info2(conn
, p
,
2062 NULL
, &smb_fname
->st
);
2065 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2066 PTR_DIFF(end_data
, p
), 0);
2067 SIVAL(nameptr
, 0, len
);
2072 len
= PTR_DIFF(p
, pdata
);
2073 pad
= (len
+ (align
-1)) & ~(align
-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2081 * set padding to zero
2084 memset(p
, 0, pad
- len
);
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2097 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2098 *out_of_space
= true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p
,pdata
),
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2108 /* Advance the data pointer to the next slot */
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2115 connection_struct
*conn
,
2116 struct dptr_struct
*dirptr
,
2118 const char *path_mask
,
2121 int requires_resume_key
,
2129 int space_remaining
,
2131 bool *got_exact_match
,
2132 int *_last_entry_off
,
2133 struct ea_list
*name_list
)
2136 const char *mask
= NULL
;
2137 long prev_dirpos
= 0;
2140 struct smb_filename
*smb_fname
= NULL
;
2141 struct smbd_dirptr_lanman2_state state
;
2143 uint64_t last_entry_off
= 0;
2147 state
.info_level
= info_level
;
2148 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2149 state
.has_wild
= dptr_has_wild(dirptr
);
2150 state
.got_exact_match
= false;
2152 *out_of_space
= false;
2153 *got_exact_match
= false;
2155 p
= strrchr_m(path_mask
,'/');
2166 ok
= smbd_dirptr_get_entry(ctx
,
2172 smbd_dirptr_lanman2_match_fn
,
2173 smbd_dirptr_lanman2_mode_fn
,
2183 *got_exact_match
= state
.got_exact_match
;
2185 ok
= smbd_marshall_dir_entry(ctx
,
2190 state
.check_mangled_names
,
2191 requires_resume_key
,
2204 TALLOC_FREE(smb_fname
);
2205 if (*out_of_space
) {
2206 dptr_SeekDir(dirptr
, prev_dirpos
);
2213 *_last_entry_off
= last_entry_off
;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2218 connection_struct
*conn
,
2219 struct dptr_struct
*dirptr
,
2221 const char *path_mask
,
2224 bool requires_resume_key
,
2230 int space_remaining
,
2232 bool *got_exact_match
,
2233 int *last_entry_off
,
2234 struct ea_list
*name_list
)
2237 const bool do_pad
= true;
2239 if (info_level
>= 1 && info_level
<= 3) {
2240 /* No alignment on earlier info levels. */
2244 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2245 path_mask
, dirtype
, info_level
,
2246 requires_resume_key
, dont_descend
, ask_sharemode
,
2248 ppdata
, base_data
, end_data
,
2250 out_of_space
, got_exact_match
,
2251 last_entry_off
, name_list
);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct
*conn
,
2259 struct smb_request
*req
,
2260 char **pparams
, int total_params
,
2261 char **ppdata
, int total_data
,
2262 unsigned int max_data_bytes
)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2269 struct smb_filename
*smb_dname
= NULL
;
2270 char *params
= *pparams
;
2271 char *pdata
= *ppdata
;
2275 uint16 findfirst_flags
;
2276 bool close_after_first
;
2278 bool requires_resume_key
;
2280 char *directory
= NULL
;
2283 int last_entry_off
=0;
2287 bool finished
= False
;
2288 bool dont_descend
= False
;
2289 bool out_of_space
= False
;
2290 int space_remaining
;
2291 bool mask_contains_wcard
= False
;
2292 struct ea_list
*ea_list
= NULL
;
2293 NTSTATUS ntstatus
= NT_STATUS_OK
;
2294 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX
*ctx
= talloc_tos();
2296 struct dptr_struct
*dirptr
= NULL
;
2297 struct smbd_server_connection
*sconn
= req
->sconn
;
2298 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2299 bool backup_priv
= false;
2301 if (total_params
< 13) {
2302 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2306 dirtype
= SVAL(params
,0);
2307 maxentries
= SVAL(params
,2);
2308 findfirst_flags
= SVAL(params
,4);
2309 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2310 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2311 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2312 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2313 security_token_has_privilege(get_current_nttok(conn
),
2316 info_level
= SVAL(params
,6);
2318 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2319 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2320 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2322 info_level
, max_data_bytes
));
2325 /* W2K3 seems to treat zero as 1. */
2329 switch (info_level
) {
2330 case SMB_FIND_INFO_STANDARD
:
2331 case SMB_FIND_EA_SIZE
:
2332 case SMB_FIND_EA_LIST
:
2333 case SMB_FIND_FILE_DIRECTORY_INFO
:
2334 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2335 case SMB_FIND_FILE_NAMES_INFO
:
2336 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2337 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2338 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2340 case SMB_FIND_FILE_UNIX
:
2341 case SMB_FIND_FILE_UNIX_INFO2
:
2342 /* Always use filesystem for UNIX mtime query. */
2343 ask_sharemode
= false;
2344 if (!lp_unix_extensions()) {
2345 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2348 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2351 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2355 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2356 params
+12, total_params
- 12,
2357 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2358 if (!NT_STATUS_IS_OK(ntstatus
)) {
2359 reply_nterror(req
, ntstatus
);
2365 ntstatus
= filename_convert_with_privilege(ctx
,
2370 &mask_contains_wcard
,
2373 ntstatus
= filename_convert(ctx
, conn
,
2374 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2377 &mask_contains_wcard
,
2381 if (!NT_STATUS_IS_OK(ntstatus
)) {
2382 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2383 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2384 ERRSRV
, ERRbadpath
);
2387 reply_nterror(req
, ntstatus
);
2391 mask
= smb_dname
->original_lcomp
;
2393 directory
= smb_dname
->base_name
;
2395 p
= strrchr_m(directory
,'/');
2397 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2398 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2399 mask
= talloc_strdup(ctx
,"*");
2401 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2404 mask_contains_wcard
= True
;
2410 if (p
== NULL
|| p
== directory
) {
2411 /* Ensure we don't have a directory name of "". */
2412 directory
= talloc_strdup(talloc_tos(), ".");
2414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2419 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2421 if (info_level
== SMB_FIND_EA_LIST
) {
2424 if (total_data
< 4) {
2425 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2429 ea_size
= IVAL(pdata
,0);
2430 if (ea_size
!= total_data
) {
2431 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2432 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2433 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2437 if (!lp_ea_support(SNUM(conn
))) {
2438 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2442 /* Pull out the list of names. */
2443 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2445 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2450 *ppdata
= (char *)SMB_REALLOC(
2451 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2452 if(*ppdata
== NULL
) {
2453 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2457 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2459 /* Realloc the params space */
2460 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2461 if (*pparams
== NULL
) {
2462 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2467 /* Save the wildcard match and attribs we are using on this directory -
2468 needed as lanman2 assumes these are being saved between calls */
2470 ntstatus
= dptr_create(conn
,
2478 mask_contains_wcard
,
2482 if (!NT_STATUS_IS_OK(ntstatus
)) {
2483 reply_nterror(req
, ntstatus
);
2488 /* Remember this in case we have
2489 to do a findnext. */
2490 dptr_set_priv(dirptr
);
2493 dptr_num
= dptr_dnum(dirptr
);
2494 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2496 /* Initialize per TRANS2_FIND_FIRST operation data */
2497 dptr_init_search_op(dirptr
);
2499 /* We don't need to check for VOL here as this is returned by
2500 a different TRANS2 call. */
2502 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2503 directory
,lp_dontdescend(SNUM(conn
))));
2504 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2505 dont_descend
= True
;
2508 space_remaining
= max_data_bytes
;
2509 out_of_space
= False
;
2511 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2512 bool got_exact_match
= False
;
2514 /* this is a heuristic to avoid seeking the dirptr except when
2515 absolutely necessary. It allows for a filename of about 40 chars */
2516 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2517 out_of_space
= True
;
2520 finished
= !get_lanman2_dir_entry(ctx
,
2524 mask
,dirtype
,info_level
,
2525 requires_resume_key
,dont_descend
,
2528 space_remaining
, &out_of_space
,
2530 &last_entry_off
, ea_list
);
2533 if (finished
&& out_of_space
)
2536 if (!finished
&& !out_of_space
)
2540 * As an optimisation if we know we aren't looking
2541 * for a wildcard name (ie. the name matches the wildcard exactly)
2542 * then we can finish on any (first) match.
2543 * This speeds up large directory searches. JRA.
2549 /* Ensure space_remaining never goes -ve. */
2550 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2551 space_remaining
= 0;
2552 out_of_space
= true;
2554 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2558 /* Check if we can close the dirptr */
2559 if(close_after_first
|| (finished
&& close_if_end
)) {
2560 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2561 dptr_close(sconn
, &dptr_num
);
2565 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2566 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2567 * the protocol level is less than NT1. Tested with smbclient. JRA.
2568 * This should fix the OS/2 client bug #2335.
2571 if(numentries
== 0) {
2572 dptr_close(sconn
, &dptr_num
);
2573 if (get_Protocol() < PROTOCOL_NT1
) {
2574 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2577 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2578 ERRDOS
, ERRbadfile
);
2583 /* At this point pdata points to numentries directory entries. */
2585 /* Set up the return parameter block */
2586 SSVAL(params
,0,dptr_num
);
2587 SSVAL(params
,2,numentries
);
2588 SSVAL(params
,4,finished
);
2589 SSVAL(params
,6,0); /* Never an EA error */
2590 SSVAL(params
,8,last_entry_off
);
2592 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2595 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2596 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2598 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2602 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2603 smb_fn_name(req
->cmd
),
2604 mask
, directory
, dirtype
, numentries
) );
2607 * Force a name mangle here to ensure that the
2608 * mask as an 8.3 name is top of the mangled cache.
2609 * The reasons for this are subtle. Don't remove
2610 * this code unless you know what you are doing
2611 * (see PR#13758). JRA.
2614 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2615 char mangled_name
[13];
2616 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2624 TALLOC_FREE(smb_dname
);
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDNEXT.
2630 ****************************************************************************/
2632 static void call_trans2findnext(connection_struct
*conn
,
2633 struct smb_request
*req
,
2634 char **pparams
, int total_params
,
2635 char **ppdata
, int total_data
,
2636 unsigned int max_data_bytes
)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2643 char *params
= *pparams
;
2644 char *pdata
= *ppdata
;
2650 uint16 findnext_flags
;
2651 bool close_after_request
;
2653 bool requires_resume_key
;
2655 bool mask_contains_wcard
= False
;
2656 char *resume_name
= NULL
;
2657 const char *mask
= NULL
;
2658 const char *directory
= NULL
;
2662 int i
, last_entry_off
=0;
2663 bool finished
= False
;
2664 bool dont_descend
= False
;
2665 bool out_of_space
= False
;
2666 int space_remaining
;
2667 struct ea_list
*ea_list
= NULL
;
2668 NTSTATUS ntstatus
= NT_STATUS_OK
;
2669 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2670 TALLOC_CTX
*ctx
= talloc_tos();
2671 struct dptr_struct
*dirptr
;
2672 struct smbd_server_connection
*sconn
= req
->sconn
;
2673 bool backup_priv
= false;
2675 if (total_params
< 13) {
2676 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2680 dptr_num
= SVAL(params
,0);
2681 maxentries
= SVAL(params
,2);
2682 info_level
= SVAL(params
,4);
2683 resume_key
= IVAL(params
,6);
2684 findnext_flags
= SVAL(params
,10);
2685 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2686 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2687 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2688 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2690 if (!continue_bit
) {
2691 /* We only need resume_name if continue_bit is zero. */
2692 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2694 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2695 &mask_contains_wcard
);
2696 if (!NT_STATUS_IS_OK(ntstatus
)) {
2697 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2698 complain (it thinks we're asking for the directory above the shared
2699 path or an invalid name). Catch this as the resume name is only compared, never used in
2700 a file access. JRA. */
2701 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2702 &resume_name
, params
+12,
2706 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2707 reply_nterror(req
, ntstatus
);
2713 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2714 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2715 resume_key = %d resume name = %s continue=%d level = %d\n",
2716 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2717 requires_resume_key
, resume_key
,
2718 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2721 /* W2K3 seems to treat zero as 1. */
2725 switch (info_level
) {
2726 case SMB_FIND_INFO_STANDARD
:
2727 case SMB_FIND_EA_SIZE
:
2728 case SMB_FIND_EA_LIST
:
2729 case SMB_FIND_FILE_DIRECTORY_INFO
:
2730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2731 case SMB_FIND_FILE_NAMES_INFO
:
2732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2733 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2736 case SMB_FIND_FILE_UNIX
:
2737 case SMB_FIND_FILE_UNIX_INFO2
:
2738 /* Always use filesystem for UNIX mtime query. */
2739 ask_sharemode
= false;
2740 if (!lp_unix_extensions()) {
2741 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2746 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2750 if (info_level
== SMB_FIND_EA_LIST
) {
2753 if (total_data
< 4) {
2754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2758 ea_size
= IVAL(pdata
,0);
2759 if (ea_size
!= total_data
) {
2760 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2761 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2766 if (!lp_ea_support(SNUM(conn
))) {
2767 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2771 /* Pull out the list of names. */
2772 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2779 *ppdata
= (char *)SMB_REALLOC(
2780 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2781 if(*ppdata
== NULL
) {
2782 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2787 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2789 /* Realloc the params space */
2790 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2791 if(*pparams
== NULL
) {
2792 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2798 /* Check that the dptr is valid */
2799 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2800 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2804 directory
= dptr_path(sconn
, dptr_num
);
2806 /* Get the wildcard mask from the dptr */
2807 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2808 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2809 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2813 /* Get the attr mask from the dptr */
2814 dirtype
= dptr_attr(sconn
, dptr_num
);
2816 backup_priv
= dptr_get_priv(dirptr
);
2818 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2819 "backup_priv = %d\n",
2820 dptr_num
, mask
, dirtype
,
2822 dptr_TellDir(dirptr
),
2825 /* Initialize per TRANS2_FIND_NEXT operation data */
2826 dptr_init_search_op(dirptr
);
2828 /* We don't need to check for VOL here as this is returned by
2829 a different TRANS2 call. */
2831 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2832 directory
,lp_dontdescend(SNUM(conn
))));
2833 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2834 dont_descend
= True
;
2837 space_remaining
= max_data_bytes
;
2838 out_of_space
= False
;
2845 * Seek to the correct position. We no longer use the resume key but
2846 * depend on the last file name instead.
2849 if(!continue_bit
&& resume_name
&& *resume_name
) {
2852 long current_pos
= 0;
2854 * Remember, name_to_8_3 is called by
2855 * get_lanman2_dir_entry(), so the resume name
2856 * could be mangled. Ensure we check the unmangled name.
2859 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2860 char *new_resume_name
= NULL
;
2861 mangle_lookup_name_from_8_3(ctx
,
2865 if (new_resume_name
) {
2866 resume_name
= new_resume_name
;
2871 * Fix for NT redirector problem triggered by resume key indexes
2872 * changing between directory scans. We now return a resume key of 0
2873 * and instead look for the filename to continue from (also given
2874 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2875 * findfirst/findnext (as is usual) then the directory pointer
2876 * should already be at the correct place.
2879 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2880 } /* end if resume_name && !continue_bit */
2882 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2883 bool got_exact_match
= False
;
2885 /* this is a heuristic to avoid seeking the dirptr except when
2886 absolutely necessary. It allows for a filename of about 40 chars */
2887 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2888 out_of_space
= True
;
2891 finished
= !get_lanman2_dir_entry(ctx
,
2895 mask
,dirtype
,info_level
,
2896 requires_resume_key
,dont_descend
,
2899 space_remaining
, &out_of_space
,
2901 &last_entry_off
, ea_list
);
2904 if (finished
&& out_of_space
)
2907 if (!finished
&& !out_of_space
)
2911 * As an optimisation if we know we aren't looking
2912 * for a wildcard name (ie. the name matches the wildcard exactly)
2913 * then we can finish on any (first) match.
2914 * This speeds up large directory searches. JRA.
2920 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2923 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2924 smb_fn_name(req
->cmd
),
2925 mask
, directory
, dirtype
, numentries
) );
2927 /* Check if we can close the dirptr */
2928 if(close_after_request
|| (finished
&& close_if_end
)) {
2929 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2930 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2937 /* Set up the return parameter block */
2938 SSVAL(params
,0,numentries
);
2939 SSVAL(params
,2,finished
);
2940 SSVAL(params
,4,0); /* Never an EA error */
2941 SSVAL(params
,6,last_entry_off
);
2943 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2949 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2951 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2955 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2957 SMB_ASSERT(extended_info
!= NULL
);
2959 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2960 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2961 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2962 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2963 #ifdef SAMBA_VERSION_REVISION
2964 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2966 extended_info
->samba_subversion
= 0;
2967 #ifdef SAMBA_VERSION_RC_RELEASE
2968 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2970 #ifdef SAMBA_VERSION_PRE_RELEASE
2971 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2974 #ifdef SAMBA_VERSION_VENDOR_PATCH
2975 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2977 extended_info
->samba_gitcommitdate
= 0;
2978 #ifdef SAMBA_VERSION_COMMIT_TIME
2979 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2982 memset(extended_info
->samba_version_string
, 0,
2983 sizeof(extended_info
->samba_version_string
));
2985 snprintf (extended_info
->samba_version_string
,
2986 sizeof(extended_info
->samba_version_string
),
2987 "%s", samba_version_string());
2990 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2991 TALLOC_CTX
*mem_ctx
,
2992 uint16_t info_level
,
2994 unsigned int max_data_bytes
,
2998 char *pdata
, *end_data
;
2999 int data_len
= 0, len
;
3000 const char *vname
= volume_label(SNUM(conn
));
3001 int snum
= SNUM(conn
);
3002 char *fstype
= lp_fstype(SNUM(conn
));
3003 uint32 additional_flags
= 0;
3004 struct smb_filename smb_fname_dot
;
3008 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3009 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3010 "info level (0x%x) on IPC$.\n",
3011 (unsigned int)info_level
));
3012 return NT_STATUS_ACCESS_DENIED
;
3016 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3018 ZERO_STRUCT(smb_fname_dot
);
3019 smb_fname_dot
.base_name
= discard_const_p(char, ".");
3021 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
3022 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3023 return map_nt_error_from_unix(errno
);
3026 st
= smb_fname_dot
.st
;
3028 *ppdata
= (char *)SMB_REALLOC(
3029 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3030 if (*ppdata
== NULL
) {
3031 return NT_STATUS_NO_MEMORY
;
3035 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3036 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3038 switch (info_level
) {
3039 case SMB_INFO_ALLOCATION
:
3041 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3043 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno
);
3047 block_size
= lp_block_size(snum
);
3048 if (bsize
< block_size
) {
3049 uint64_t factor
= block_size
/bsize
;
3054 if (bsize
> block_size
) {
3055 uint64_t factor
= bsize
/block_size
;
3060 bytes_per_sector
= 512;
3061 sectors_per_unit
= bsize
/bytes_per_sector
;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3065 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3067 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3068 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3069 SIVAL(pdata
,l1_cUnit
,dsize
);
3070 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3071 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3075 case SMB_INFO_VOLUME
:
3076 /* Return volume name */
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3083 * Win2k3 and previous mess this up by sending a name length
3084 * one byte short. I believe only older clients (OS/2 Win9x) use
3085 * this call so try fixing this by adding a terminating null to
3086 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3090 pdata
+l2_vol_szVolLabel
, vname
,
3091 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3092 STR_NOALIGN
|STR_TERMINATE
);
3093 SCVAL(pdata
,l2_vol_cch
,len
);
3094 data_len
= l2_vol_szVolLabel
+ len
;
3095 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3096 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3100 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3101 case SMB_FS_ATTRIBUTE_INFORMATION
:
3103 additional_flags
= 0;
3104 #if defined(HAVE_SYS_QUOTAS)
3105 additional_flags
|= FILE_VOLUME_QUOTAS
;
3108 if(lp_nt_acl_support(SNUM(conn
))) {
3109 additional_flags
|= FILE_PERSISTENT_ACLS
;
3112 /* Capabilities are filled in at connection time through STATVFS call */
3113 additional_flags
|= conn
->fs_capabilities
;
3114 additional_flags
|= lp_parm_int(conn
->params
->service
,
3115 "share", "fake_fscaps",
3118 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3119 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3120 additional_flags
); /* FS ATTRIBUTES */
3122 SIVAL(pdata
,4,255); /* Max filename component length */
3123 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3124 and will think we can't do long filenames */
3125 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3126 PTR_DIFF(end_data
, pdata
+12),
3129 data_len
= 12 + len
;
3132 case SMB_QUERY_FS_LABEL_INFO
:
3133 case SMB_FS_LABEL_INFORMATION
:
3134 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3135 PTR_DIFF(end_data
, pdata
+4), 0);
3140 case SMB_QUERY_FS_VOLUME_INFO
:
3141 case SMB_FS_VOLUME_INFORMATION
:
3144 * Add volume serial number - hash of a combination of
3145 * the called hostname and the service name.
3147 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3148 (str_checksum(get_local_machine_name())<<16));
3150 /* Max label len is 32 characters. */
3151 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3152 PTR_DIFF(end_data
, pdata
+18),
3154 SIVAL(pdata
,12,len
);
3157 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3158 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3161 case SMB_QUERY_FS_SIZE_INFO
:
3162 case SMB_FS_SIZE_INFORMATION
:
3164 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3166 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3167 return map_nt_error_from_unix(errno
);
3169 block_size
= lp_block_size(snum
);
3170 if (bsize
< block_size
) {
3171 uint64_t factor
= block_size
/bsize
;
3176 if (bsize
> block_size
) {
3177 uint64_t factor
= bsize
/block_size
;
3182 bytes_per_sector
= 512;
3183 sectors_per_unit
= bsize
/bytes_per_sector
;
3184 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3185 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3186 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3187 SBIG_UINT(pdata
,0,dsize
);
3188 SBIG_UINT(pdata
,8,dfree
);
3189 SIVAL(pdata
,16,sectors_per_unit
);
3190 SIVAL(pdata
,20,bytes_per_sector
);
3194 case SMB_FS_FULL_SIZE_INFORMATION
:
3196 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3198 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3199 return map_nt_error_from_unix(errno
);
3201 block_size
= lp_block_size(snum
);
3202 if (bsize
< block_size
) {
3203 uint64_t factor
= block_size
/bsize
;
3208 if (bsize
> block_size
) {
3209 uint64_t factor
= bsize
/block_size
;
3214 bytes_per_sector
= 512;
3215 sectors_per_unit
= bsize
/bytes_per_sector
;
3216 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3217 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3218 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3219 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3220 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3221 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3222 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3223 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3227 case SMB_QUERY_FS_DEVICE_INFO
:
3228 case SMB_FS_DEVICE_INFORMATION
:
3230 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3232 if (!CAN_WRITE(conn
)) {
3233 characteristics
|= FILE_READ_ONLY_DEVICE
;
3236 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3237 SIVAL(pdata
,4,characteristics
);
3241 #ifdef HAVE_SYS_QUOTAS
3242 case SMB_FS_QUOTA_INFORMATION
:
3244 * what we have to send --metze:
3246 * Unknown1: 24 NULL bytes
3247 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3248 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3249 * Quota Flags: 2 byte :
3250 * Unknown3: 6 NULL bytes
3254 * details for Quota Flags:
3256 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3257 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3258 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3259 * 0x0001 Enable Quotas: enable quota for this fs
3263 /* we need to fake up a fsp here,
3264 * because its not send in this call
3267 SMB_NTQUOTA_STRUCT quotas
;
3270 ZERO_STRUCT(quotas
);
3276 if (get_current_uid(conn
) != 0) {
3277 DEBUG(0,("set_user_quota: access_denied "
3278 "service [%s] user [%s]\n",
3279 lp_servicename(SNUM(conn
)),
3280 conn
->session_info
->unix_info
->unix_name
));
3281 return NT_STATUS_ACCESS_DENIED
;
3284 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3285 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3286 return map_nt_error_from_unix(errno
);
3291 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3292 lp_servicename(SNUM(conn
))));
3294 /* Unknown1 24 NULL bytes*/
3295 SBIG_UINT(pdata
,0,(uint64_t)0);
3296 SBIG_UINT(pdata
,8,(uint64_t)0);
3297 SBIG_UINT(pdata
,16,(uint64_t)0);
3299 /* Default Soft Quota 8 bytes */
3300 SBIG_UINT(pdata
,24,quotas
.softlim
);
3302 /* Default Hard Quota 8 bytes */
3303 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3305 /* Quota flag 2 bytes */
3306 SSVAL(pdata
,40,quotas
.qflags
);
3308 /* Unknown3 6 NULL bytes */
3314 #endif /* HAVE_SYS_QUOTAS */
3315 case SMB_FS_OBJECTID_INFORMATION
:
3317 unsigned char objid
[16];
3318 struct smb_extended_info extended_info
;
3319 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3320 samba_extended_info_version (&extended_info
);
3321 SIVAL(pdata
,16,extended_info
.samba_magic
);
3322 SIVAL(pdata
,20,extended_info
.samba_version
);
3323 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3324 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3325 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3331 * Query the version and capabilities of the CIFS UNIX extensions
3335 case SMB_QUERY_CIFS_UNIX_INFO
:
3337 bool large_write
= lp_min_receive_file_size() &&
3338 !srv_is_signing_active(conn
->sconn
);
3339 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3340 int encrypt_caps
= 0;
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL
;
3346 switch (conn
->encrypt_level
) {
3352 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3355 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3356 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3357 large_write
= false;
3363 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3364 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3366 /* We have POSIX ACLs, pathname, encryption,
3367 * large read/write, and locking capability. */
3369 SBIG_UINT(pdata
,4,((uint64_t)(
3370 CIFS_UNIX_POSIX_ACLS_CAP
|
3371 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3372 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3373 CIFS_UNIX_EXTATTR_CAP
|
3374 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3376 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3378 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3382 case SMB_QUERY_POSIX_FS_INFO
:
3385 vfs_statvfs_struct svfs
;
3387 if (!lp_unix_extensions()) {
3388 return NT_STATUS_INVALID_LEVEL
;
3391 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3395 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3396 SIVAL(pdata
,4,svfs
.BlockSize
);
3397 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3398 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3399 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3400 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3401 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3402 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3403 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3405 } else if (rc
== EOPNOTSUPP
) {
3406 return NT_STATUS_INVALID_LEVEL
;
3407 #endif /* EOPNOTSUPP */
3409 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3410 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3415 case SMB_QUERY_POSIX_WHOAMI
:
3421 if (!lp_unix_extensions()) {
3422 return NT_STATUS_INVALID_LEVEL
;
3425 if (max_data_bytes
< 40) {
3426 return NT_STATUS_BUFFER_TOO_SMALL
;
3429 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3430 flags
|= SMB_WHOAMI_GUEST
;
3433 /* NOTE: 8 bytes for UID/GID, irrespective of native
3434 * platform size. This matches
3435 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3437 data_len
= 4 /* flags */
3444 + 4 /* pad/reserved */
3445 + (conn
->session_info
->unix_token
->ngroups
* 8)
3447 + (conn
->session_info
->security_token
->num_sids
*
3451 SIVAL(pdata
, 0, flags
);
3452 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3454 (uint64_t)conn
->session_info
->unix_token
->uid
);
3455 SBIG_UINT(pdata
, 16,
3456 (uint64_t)conn
->session_info
->unix_token
->gid
);
3459 if (data_len
>= max_data_bytes
) {
3460 /* Potential overflow, skip the GIDs and SIDs. */
3462 SIVAL(pdata
, 24, 0); /* num_groups */
3463 SIVAL(pdata
, 28, 0); /* num_sids */
3464 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3465 SIVAL(pdata
, 36, 0); /* reserved */
3471 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3472 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3474 /* We walk the SID list twice, but this call is fairly
3475 * infrequent, and I don't expect that it's performance
3476 * sensitive -- jpeach
3478 for (i
= 0, sid_bytes
= 0;
3479 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3480 sid_bytes
+= ndr_size_dom_sid(
3481 &conn
->session_info
->security_token
->sids
[i
],
3485 /* SID list byte count */
3486 SIVAL(pdata
, 32, sid_bytes
);
3488 /* 4 bytes pad/reserved - must be zero */
3489 SIVAL(pdata
, 36, 0);
3493 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3494 SBIG_UINT(pdata
, data_len
,
3495 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3501 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3502 int sid_len
= ndr_size_dom_sid(
3503 &conn
->session_info
->security_token
->sids
[i
],
3506 sid_linearize(pdata
+ data_len
, sid_len
,
3507 &conn
->session_info
->security_token
->sids
[i
]);
3508 data_len
+= sid_len
;
3514 case SMB_MAC_QUERY_FS_INFO
:
3516 * Thursby MAC extension... ONLY on NTFS filesystems
3517 * once we do streams then we don't need this
3519 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3521 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3526 return NT_STATUS_INVALID_LEVEL
;
3529 *ret_data_len
= data_len
;
3530 return NT_STATUS_OK
;
3533 /****************************************************************************
3534 Reply to a TRANS2_QFSINFO (query filesystem info).
3535 ****************************************************************************/
3537 static void call_trans2qfsinfo(connection_struct
*conn
,
3538 struct smb_request
*req
,
3539 char **pparams
, int total_params
,
3540 char **ppdata
, int total_data
,
3541 unsigned int max_data_bytes
)
3543 char *params
= *pparams
;
3544 uint16_t info_level
;
3548 if (total_params
< 2) {
3549 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3553 info_level
= SVAL(params
,0);
3555 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3556 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3557 DEBUG(0,("call_trans2qfsinfo: encryption required "
3558 "and info level 0x%x sent.\n",
3559 (unsigned int)info_level
));
3560 exit_server_cleanly("encryption required "
3566 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3568 status
= smbd_do_qfsinfo(conn
, req
,
3573 if (!NT_STATUS_IS_OK(status
)) {
3574 reply_nterror(req
, status
);
3578 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3581 DEBUG( 4, ( "%s info_level = %d\n",
3582 smb_fn_name(req
->cmd
), info_level
) );
3587 /****************************************************************************
3588 Reply to a TRANS2_SETFSINFO (set filesystem info).
3589 ****************************************************************************/
3591 static void call_trans2setfsinfo(connection_struct
*conn
,
3592 struct smb_request
*req
,
3593 char **pparams
, int total_params
,
3594 char **ppdata
, int total_data
,
3595 unsigned int max_data_bytes
)
3597 struct smbd_server_connection
*sconn
= req
->sconn
;
3598 char *pdata
= *ppdata
;
3599 char *params
= *pparams
;
3602 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3605 if (total_params
< 4) {
3606 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3608 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3612 info_level
= SVAL(params
,2);
3615 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3616 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3617 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3618 "info level (0x%x) on IPC$.\n",
3619 (unsigned int)info_level
));
3620 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3625 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3626 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3627 DEBUG(0,("call_trans2setfsinfo: encryption required "
3628 "and info level 0x%x sent.\n",
3629 (unsigned int)info_level
));
3630 exit_server_cleanly("encryption required "
3636 switch(info_level
) {
3637 case SMB_SET_CIFS_UNIX_INFO
:
3638 if (!lp_unix_extensions()) {
3639 DEBUG(2,("call_trans2setfsinfo: "
3640 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3641 "unix extensions off\n"));
3643 NT_STATUS_INVALID_LEVEL
);
3647 /* There should be 12 bytes of capabilities set. */
3648 if (total_data
< 12) {
3651 NT_STATUS_INVALID_PARAMETER
);
3654 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3655 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3656 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3657 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3658 /* Just print these values for now. */
3659 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3660 "major = %u, minor = %u cap_low = 0x%x, "
3662 (unsigned int)sconn
->
3663 smb1
.unix_info
.client_major
,
3664 (unsigned int)sconn
->
3665 smb1
.unix_info
.client_minor
,
3666 (unsigned int)sconn
->
3667 smb1
.unix_info
.client_cap_low
,
3668 (unsigned int)sconn
->
3669 smb1
.unix_info
.client_cap_high
));
3671 /* Here is where we must switch to posix pathname processing... */
3672 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3673 lp_set_posix_pathnames();
3674 mangle_change_to_posix();
3677 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3678 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3679 /* Client that knows how to do posix locks,
3680 * but not posix open/mkdir operations. Set a
3681 * default type for read/write checks. */
3683 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3688 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3691 size_t param_len
= 0;
3692 size_t data_len
= total_data
;
3694 if (!lp_unix_extensions()) {
3697 NT_STATUS_INVALID_LEVEL
);
3701 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3704 NT_STATUS_NOT_SUPPORTED
);
3708 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3709 DEBUG( 2,("call_trans2setfsinfo: "
3710 "request transport encryption disabled"
3711 "with 'fork echo handler = yes'\n"));
3714 NT_STATUS_NOT_SUPPORTED
);
3718 DEBUG( 4,("call_trans2setfsinfo: "
3719 "request transport encryption.\n"));
3721 status
= srv_request_encryption_setup(conn
,
3722 (unsigned char **)ppdata
,
3724 (unsigned char **)pparams
,
3727 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3728 !NT_STATUS_IS_OK(status
)) {
3729 reply_nterror(req
, status
);
3733 send_trans2_replies(conn
, req
,
3740 if (NT_STATUS_IS_OK(status
)) {
3741 /* Server-side transport
3742 * encryption is now *on*. */
3743 status
= srv_encryption_start(conn
);
3744 if (!NT_STATUS_IS_OK(status
)) {
3745 char *reason
= talloc_asprintf(talloc_tos(),
3746 "Failure in setting "
3747 "up encrypted transport: %s",
3749 exit_server_cleanly(reason
);
3755 case SMB_FS_QUOTA_INFORMATION
:
3757 files_struct
*fsp
= NULL
;
3758 SMB_NTQUOTA_STRUCT quotas
;
3760 ZERO_STRUCT(quotas
);
3763 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3764 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3765 lp_servicename(SNUM(conn
)),
3766 conn
->session_info
->unix_info
->unix_name
));
3767 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3771 /* note: normaly there're 48 bytes,
3772 * but we didn't use the last 6 bytes for now
3775 fsp
= file_fsp(req
, SVAL(params
,0));
3777 if (!check_fsp_ntquota_handle(conn
, req
,
3779 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3781 req
, NT_STATUS_INVALID_HANDLE
);
3785 if (total_data
< 42) {
3786 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3790 NT_STATUS_INVALID_PARAMETER
);
3794 /* unknown_1 24 NULL bytes in pdata*/
3796 /* the soft quotas 8 bytes (uint64_t)*/
3797 quotas
.softlim
= BVAL(pdata
,24);
3799 /* the hard quotas 8 bytes (uint64_t)*/
3800 quotas
.hardlim
= BVAL(pdata
,32);
3802 /* quota_flags 2 bytes **/
3803 quotas
.qflags
= SVAL(pdata
,40);
3805 /* unknown_2 6 NULL bytes follow*/
3807 /* now set the quotas */
3808 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3809 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3810 reply_nterror(req
, map_nt_error_from_unix(errno
));
3817 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3819 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3825 * sending this reply works fine,
3826 * but I'm not sure it's the same
3827 * like windows do...
3830 reply_outbuf(req
, 10, 0);
3833 #if defined(HAVE_POSIX_ACLS)
3834 /****************************************************************************
3835 Utility function to count the number of entries in a POSIX acl.
3836 ****************************************************************************/
3838 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3840 unsigned int ace_count
= 0;
3841 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3842 SMB_ACL_ENTRY_T entry
;
3844 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3846 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3847 entry_id
= SMB_ACL_NEXT_ENTRY
;
3854 /****************************************************************************
3855 Utility function to marshall a POSIX acl into wire format.
3856 ****************************************************************************/
3858 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3860 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3861 SMB_ACL_ENTRY_T entry
;
3863 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3864 SMB_ACL_TAG_T tagtype
;
3865 SMB_ACL_PERMSET_T permset
;
3866 unsigned char perms
= 0;
3867 unsigned int own_grp
;
3870 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3871 entry_id
= SMB_ACL_NEXT_ENTRY
;
3874 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3875 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3879 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3880 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3884 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3885 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3886 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3888 SCVAL(pdata
,1,perms
);
3891 case SMB_ACL_USER_OBJ
:
3892 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3893 own_grp
= (unsigned int)pst
->st_ex_uid
;
3894 SIVAL(pdata
,2,own_grp
);
3899 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3901 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3904 own_grp
= (unsigned int)*puid
;
3905 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3906 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3907 SIVAL(pdata
,2,own_grp
);
3911 case SMB_ACL_GROUP_OBJ
:
3912 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3913 own_grp
= (unsigned int)pst
->st_ex_gid
;
3914 SIVAL(pdata
,2,own_grp
);
3919 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3924 own_grp
= (unsigned int)*pgid
;
3925 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3926 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3927 SIVAL(pdata
,2,own_grp
);
3932 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3933 SIVAL(pdata
,2,0xFFFFFFFF);
3934 SIVAL(pdata
,6,0xFFFFFFFF);
3937 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3938 SIVAL(pdata
,2,0xFFFFFFFF);
3939 SIVAL(pdata
,6,0xFFFFFFFF);
3942 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3945 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3952 /****************************************************************************
3953 Store the FILE_UNIX_BASIC info.
3954 ****************************************************************************/
3956 static char *store_file_unix_basic(connection_struct
*conn
,
3959 const SMB_STRUCT_STAT
*psbuf
)
3961 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3964 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3965 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3967 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3970 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3973 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3974 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3975 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3978 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3982 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3986 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3989 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
3990 devno
= psbuf
->st_ex_rdev
;
3992 devno
= psbuf
->st_ex_dev
;
3995 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
3999 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4003 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4006 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4010 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4017 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4018 * the chflags(2) (or equivalent) flags.
4020 * XXX: this really should be behind the VFS interface. To do this, we would
4021 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4022 * Each VFS module could then implement its own mapping as appropriate for the
4023 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4025 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4029 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4033 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4037 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4041 { UF_HIDDEN
, EXT_HIDDEN
},
4044 /* Do not remove. We need to guarantee that this array has at least one
4045 * entry to build on HP-UX.
4051 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4052 uint32
*smb_fflags
, uint32
*smb_fmask
)
4056 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4057 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4058 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4059 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4064 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4065 const uint32 smb_fflags
,
4066 const uint32 smb_fmask
,
4069 uint32 max_fmask
= 0;
4072 *stat_fflags
= psbuf
->st_ex_flags
;
4074 /* For each flags requested in smb_fmask, check the state of the
4075 * corresponding flag in smb_fflags and set or clear the matching
4079 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4080 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4081 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4082 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4083 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4085 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4090 /* If smb_fmask is asking to set any bits that are not supported by
4091 * our flag mappings, we should fail.
4093 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4101 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4102 * of file flags and birth (create) time.
4104 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4107 const SMB_STRUCT_STAT
*psbuf
)
4109 uint32 file_flags
= 0;
4110 uint32 flags_mask
= 0;
4112 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4114 /* Create (birth) time 64 bit */
4115 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4118 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4119 SIVAL(pdata
, 0, file_flags
); /* flags */
4120 SIVAL(pdata
, 4, flags_mask
); /* mask */
4126 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4127 const struct stream_struct
*streams
,
4129 unsigned int max_data_bytes
,
4130 unsigned int *data_size
)
4133 unsigned int ofs
= 0;
4135 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4136 unsigned int next_offset
;
4138 smb_ucs2_t
*namebuf
;
4140 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4141 streams
[i
].name
, &namelen
) ||
4144 return NT_STATUS_INVALID_PARAMETER
;
4148 * name_buf is now null-terminated, we need to marshall as not
4154 SIVAL(data
, ofs
+4, namelen
);
4155 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4156 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4157 memcpy(data
+ofs
+24, namebuf
, namelen
);
4158 TALLOC_FREE(namebuf
);
4160 next_offset
= ofs
+ 24 + namelen
;
4162 if (i
== num_streams
-1) {
4163 SIVAL(data
, ofs
, 0);
4166 unsigned int align
= ndr_align_size(next_offset
, 8);
4168 memset(data
+next_offset
, 0, align
);
4169 next_offset
+= align
;
4171 SIVAL(data
, ofs
, next_offset
- ofs
);
4180 return NT_STATUS_OK
;
4183 /****************************************************************************
4184 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4185 ****************************************************************************/
4187 static void call_trans2qpipeinfo(connection_struct
*conn
,
4188 struct smb_request
*req
,
4189 unsigned int tran_call
,
4190 char **pparams
, int total_params
,
4191 char **ppdata
, int total_data
,
4192 unsigned int max_data_bytes
)
4194 char *params
= *pparams
;
4195 char *pdata
= *ppdata
;
4196 unsigned int data_size
= 0;
4197 unsigned int param_size
= 2;
4202 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4206 if (total_params
< 4) {
4207 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4211 fsp
= file_fsp(req
, SVAL(params
,0));
4212 if (!fsp_is_np(fsp
)) {
4213 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4217 info_level
= SVAL(params
,2);
4219 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4220 if (*pparams
== NULL
) {
4221 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4226 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4227 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4228 if (*ppdata
== NULL
) {
4229 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4234 switch (info_level
) {
4235 case SMB_FILE_STANDARD_INFORMATION
:
4237 SOFF_T(pdata
,0,4096LL);
4244 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4248 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4254 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4255 TALLOC_CTX
*mem_ctx
,
4256 uint16_t info_level
,
4258 struct smb_filename
*smb_fname
,
4259 bool delete_pending
,
4260 struct timespec write_time_ts
,
4261 struct ea_list
*ea_list
,
4262 int lock_data_count
,
4265 unsigned int max_data_bytes
,
4267 unsigned int *pdata_size
)
4269 char *pdata
= *ppdata
;
4270 char *dstart
, *dend
;
4271 unsigned int data_size
;
4272 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4273 time_t create_time
, mtime
, atime
, c_time
;
4274 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4281 uint64_t file_size
= 0;
4283 uint64_t allocation_size
= 0;
4284 uint64_t file_index
= 0;
4285 uint32_t access_mask
= 0;
4287 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4288 return NT_STATUS_INVALID_LEVEL
;
4291 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4292 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4293 info_level
, max_data_bytes
));
4295 mode
= dos_mode(conn
, smb_fname
);
4296 nlink
= psbuf
->st_ex_nlink
;
4298 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4302 if ((nlink
> 0) && delete_pending
) {
4306 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4307 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4308 if (*ppdata
== NULL
) {
4309 return NT_STATUS_NO_MEMORY
;
4313 dend
= dstart
+ data_size
- 1;
4315 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4316 update_stat_ex_mtime(psbuf
, write_time_ts
);
4319 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4320 mtime_ts
= psbuf
->st_ex_mtime
;
4321 atime_ts
= psbuf
->st_ex_atime
;
4322 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4324 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4325 dos_filetime_timespec(&create_time_ts
);
4326 dos_filetime_timespec(&mtime_ts
);
4327 dos_filetime_timespec(&atime_ts
);
4328 dos_filetime_timespec(&ctime_ts
);
4331 create_time
= convert_timespec_to_time_t(create_time_ts
);
4332 mtime
= convert_timespec_to_time_t(mtime_ts
);
4333 atime
= convert_timespec_to_time_t(atime_ts
);
4334 c_time
= convert_timespec_to_time_t(ctime_ts
);
4336 p
= strrchr_m(smb_fname
->base_name
,'/');
4338 base_name
= smb_fname
->base_name
;
4342 /* NT expects the name to be in an exact form of the *full*
4343 filename. See the trans2 torture test */
4344 if (ISDOT(base_name
)) {
4345 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4347 return NT_STATUS_NO_MEMORY
;
4350 dos_fname
= talloc_asprintf(mem_ctx
,
4352 smb_fname
->base_name
);
4354 return NT_STATUS_NO_MEMORY
;
4356 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4357 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4358 smb_fname
->stream_name
);
4360 return NT_STATUS_NO_MEMORY
;
4364 string_replace(dos_fname
, '/', '\\');
4367 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4370 /* Do we have this path open ? */
4372 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4373 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4374 if (fsp1
&& fsp1
->initial_allocation_size
) {
4375 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4379 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4380 file_size
= get_file_size_stat(psbuf
);
4384 pos
= fsp
->fh
->position_information
;
4388 access_mask
= fsp
->access_mask
;
4390 /* GENERIC_EXECUTE mapping from Windows */
4391 access_mask
= 0x12019F;
4394 /* This should be an index number - looks like
4397 I think this causes us to fail the IFSKIT
4398 BasicFileInformationTest. -tpot */
4399 file_index
= get_FileIndex(conn
, psbuf
);
4401 switch (info_level
) {
4402 case SMB_INFO_STANDARD
:
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4405 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4406 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4407 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4408 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4409 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4410 SSVAL(pdata
,l1_attrFile
,mode
);
4413 case SMB_INFO_QUERY_EA_SIZE
:
4415 unsigned int ea_size
=
4416 estimate_ea_size(conn
, fsp
,
4417 smb_fname
->base_name
);
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4420 srv_put_dos_date2(pdata
,0,create_time
);
4421 srv_put_dos_date2(pdata
,4,atime
);
4422 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4423 SIVAL(pdata
,12,(uint32
)file_size
);
4424 SIVAL(pdata
,16,(uint32
)allocation_size
);
4425 SSVAL(pdata
,20,mode
);
4426 SIVAL(pdata
,22,ea_size
);
4430 case SMB_INFO_IS_NAME_VALID
:
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4433 /* os/2 needs this ? really ?*/
4434 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4436 /* This is only reached for qpathinfo */
4440 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4442 size_t total_ea_len
= 0;
4443 struct ea_list
*ea_file_list
= NULL
;
4445 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4448 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4449 smb_fname
->base_name
,
4451 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4453 if (!ea_list
|| (total_ea_len
> data_size
)) {
4455 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4459 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4463 case SMB_INFO_QUERY_ALL_EAS
:
4465 /* We have data_size bytes to put EA's into. */
4466 size_t total_ea_len
= 0;
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4470 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4471 smb_fname
->base_name
,
4473 if (!ea_list
|| (total_ea_len
> data_size
)) {
4475 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4479 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4483 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4485 /* This is FileFullEaInformation - 0xF which maps to
4486 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4488 /* We have data_size bytes to put EA's into. */
4489 size_t total_ea_len
= 0;
4490 struct ea_list
*ea_file_list
= NULL
;
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4494 /*TODO: add filtering and index handling */
4497 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4498 smb_fname
->base_name
,
4500 if (!ea_file_list
) {
4501 return NT_STATUS_NO_EAS_ON_FILE
;
4504 status
= fill_ea_chained_buffer(mem_ctx
,
4508 conn
, ea_file_list
);
4509 if (!NT_STATUS_IS_OK(status
)) {
4515 case SMB_FILE_BASIC_INFORMATION
:
4516 case SMB_QUERY_FILE_BASIC_INFO
:
4518 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4520 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4522 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4526 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4527 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4528 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4529 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4530 SIVAL(pdata
,32,mode
);
4532 DEBUG(5,("SMB_QFBI - "));
4533 DEBUG(5,("create: %s ", ctime(&create_time
)));
4534 DEBUG(5,("access: %s ", ctime(&atime
)));
4535 DEBUG(5,("write: %s ", ctime(&mtime
)));
4536 DEBUG(5,("change: %s ", ctime(&c_time
)));
4537 DEBUG(5,("mode: %x\n", mode
));
4540 case SMB_FILE_STANDARD_INFORMATION
:
4541 case SMB_QUERY_FILE_STANDARD_INFO
:
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4545 SOFF_T(pdata
,0,allocation_size
);
4546 SOFF_T(pdata
,8,file_size
);
4547 SIVAL(pdata
,16,nlink
);
4548 SCVAL(pdata
,20,delete_pending
?1:0);
4549 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4550 SSVAL(pdata
,22,0); /* Padding. */
4553 case SMB_FILE_EA_INFORMATION
:
4554 case SMB_QUERY_FILE_EA_INFO
:
4556 unsigned int ea_size
=
4557 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4560 SIVAL(pdata
,0,ea_size
);
4564 /* Get the 8.3 name - used if NT SMB was negotiated. */
4565 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4566 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4569 char mangled_name
[13];
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4571 if (!name_to_8_3(base_name
,mangled_name
,
4572 True
,conn
->params
)) {
4573 return NT_STATUS_NO_MEMORY
;
4575 len
= srvstr_push(dstart
, flags2
,
4576 pdata
+4, mangled_name
,
4577 PTR_DIFF(dend
, pdata
+4),
4579 data_size
= 4 + len
;
4584 case SMB_QUERY_FILE_NAME_INFO
:
4588 this must be *exactly* right for ACLs on mapped drives to work
4590 len
= srvstr_push(dstart
, flags2
,
4592 PTR_DIFF(dend
, pdata
+4),
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4595 data_size
= 4 + len
;
4600 case SMB_FILE_ALLOCATION_INFORMATION
:
4601 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4604 SOFF_T(pdata
,0,allocation_size
);
4607 case SMB_FILE_END_OF_FILE_INFORMATION
:
4608 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4611 SOFF_T(pdata
,0,file_size
);
4614 case SMB_QUERY_FILE_ALL_INFO
:
4615 case SMB_FILE_ALL_INFORMATION
:
4618 unsigned int ea_size
=
4619 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4621 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4622 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4623 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4624 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4625 SIVAL(pdata
,32,mode
);
4626 SIVAL(pdata
,36,0); /* padding. */
4628 SOFF_T(pdata
,0,allocation_size
);
4629 SOFF_T(pdata
,8,file_size
);
4630 SIVAL(pdata
,16,nlink
);
4631 SCVAL(pdata
,20,delete_pending
);
4632 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4635 SIVAL(pdata
,0,ea_size
);
4636 pdata
+= 4; /* EA info */
4637 len
= srvstr_push(dstart
, flags2
,
4639 PTR_DIFF(dend
, pdata
+4),
4643 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4647 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4650 unsigned int ea_size
=
4651 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4653 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4654 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4655 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4656 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4657 SIVAL(pdata
, 0x20, mode
);
4658 SIVAL(pdata
, 0x24, 0); /* padding. */
4659 SBVAL(pdata
, 0x28, allocation_size
);
4660 SBVAL(pdata
, 0x30, file_size
);
4661 SIVAL(pdata
, 0x38, nlink
);
4662 SCVAL(pdata
, 0x3C, delete_pending
);
4663 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4664 SSVAL(pdata
, 0x3E, 0); /* padding */
4665 SBVAL(pdata
, 0x40, file_index
);
4666 SIVAL(pdata
, 0x48, ea_size
);
4667 SIVAL(pdata
, 0x4C, access_mask
);
4668 SBVAL(pdata
, 0x50, pos
);
4669 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4670 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4674 len
= srvstr_push(dstart
, flags2
,
4676 PTR_DIFF(dend
, pdata
+4),
4680 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4683 case SMB_FILE_INTERNAL_INFORMATION
:
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4686 SBVAL(pdata
, 0, file_index
);
4690 case SMB_FILE_ACCESS_INFORMATION
:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4692 SIVAL(pdata
, 0, access_mask
);
4696 case SMB_FILE_NAME_INFORMATION
:
4697 /* Pathname with leading '\'. */
4700 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4702 SIVAL(pdata
,0,byte_len
);
4703 data_size
= 4 + byte_len
;
4707 case SMB_FILE_DISPOSITION_INFORMATION
:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4710 SCVAL(pdata
,0,delete_pending
);
4713 case SMB_FILE_POSITION_INFORMATION
:
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4716 SOFF_T(pdata
,0,pos
);
4719 case SMB_FILE_MODE_INFORMATION
:
4720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4721 SIVAL(pdata
,0,mode
);
4725 case SMB_FILE_ALIGNMENT_INFORMATION
:
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4727 SIVAL(pdata
,0,0); /* No alignment needed. */
4732 * NT4 server just returns "invalid query" to this - if we try
4733 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4736 /* The first statement above is false - verified using Thursby
4737 * client against NT4 -- gcolley.
4739 case SMB_QUERY_FILE_STREAM_INFO
:
4740 case SMB_FILE_STREAM_INFORMATION
: {
4741 unsigned int num_streams
= 0;
4742 struct stream_struct
*streams
= NULL
;
4744 DEBUG(10,("smbd_do_qfilepathinfo: "
4745 "SMB_FILE_STREAM_INFORMATION\n"));
4747 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4748 return NT_STATUS_INVALID_PARAMETER
;
4751 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4752 talloc_tos(), &num_streams
, &streams
);
4754 if (!NT_STATUS_IS_OK(status
)) {
4755 DEBUG(10, ("could not get stream info: %s\n",
4756 nt_errstr(status
)));
4760 status
= marshall_stream_info(num_streams
, streams
,
4761 pdata
, max_data_bytes
,
4764 if (!NT_STATUS_IS_OK(status
)) {
4765 DEBUG(10, ("marshall_stream_info failed: %s\n",
4766 nt_errstr(status
)));
4770 TALLOC_FREE(streams
);
4774 case SMB_QUERY_COMPRESSION_INFO
:
4775 case SMB_FILE_COMPRESSION_INFORMATION
:
4776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4777 SOFF_T(pdata
,0,file_size
);
4778 SIVAL(pdata
,8,0); /* ??? */
4779 SIVAL(pdata
,12,0); /* ??? */
4783 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4785 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4786 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4787 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4788 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4789 SOFF_T(pdata
,32,allocation_size
);
4790 SOFF_T(pdata
,40,file_size
);
4791 SIVAL(pdata
,48,mode
);
4792 SIVAL(pdata
,52,0); /* ??? */
4796 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4797 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4798 SIVAL(pdata
,0,mode
);
4804 * CIFS UNIX Extensions.
4807 case SMB_QUERY_FILE_UNIX_BASIC
:
4809 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4810 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4812 DEBUG(4,("smbd_do_qfilepathinfo: "
4813 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4814 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4818 case SMB_QUERY_FILE_UNIX_INFO2
:
4820 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4821 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4825 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4827 for (i
=0; i
<100; i
++)
4828 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4834 case SMB_QUERY_FILE_UNIX_LINK
:
4837 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4840 return NT_STATUS_NO_MEMORY
;
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4845 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4846 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4849 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4851 len
= SMB_VFS_READLINK(conn
,
4852 smb_fname
->base_name
,
4855 return map_nt_error_from_unix(errno
);
4858 len
= srvstr_push(dstart
, flags2
,
4860 PTR_DIFF(dend
, pdata
),
4863 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4868 #if defined(HAVE_POSIX_ACLS)
4869 case SMB_QUERY_POSIX_ACL
:
4871 SMB_ACL_T file_acl
= NULL
;
4872 SMB_ACL_T def_acl
= NULL
;
4873 uint16 num_file_acls
= 0;
4874 uint16 num_def_acls
= 0;
4876 if (fsp
&& fsp
->fh
->fd
!= -1) {
4877 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4880 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4881 smb_fname
->base_name
,
4882 SMB_ACL_TYPE_ACCESS
);
4885 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4886 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4887 "not implemented on "
4888 "filesystem containing %s\n",
4889 smb_fname
->base_name
));
4890 return NT_STATUS_NOT_IMPLEMENTED
;
4893 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4894 if (fsp
&& fsp
->is_directory
) {
4896 SMB_VFS_SYS_ACL_GET_FILE(
4898 fsp
->fsp_name
->base_name
,
4899 SMB_ACL_TYPE_DEFAULT
);
4902 SMB_VFS_SYS_ACL_GET_FILE(
4904 smb_fname
->base_name
,
4905 SMB_ACL_TYPE_DEFAULT
);
4907 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4910 num_file_acls
= count_acl_entries(conn
, file_acl
);
4911 num_def_acls
= count_acl_entries(conn
, def_acl
);
4913 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4914 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4916 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4917 SMB_POSIX_ACL_HEADER_SIZE
) ));
4919 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4922 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4924 return NT_STATUS_BUFFER_TOO_SMALL
;
4927 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4928 SSVAL(pdata
,2,num_file_acls
);
4929 SSVAL(pdata
,4,num_def_acls
);
4930 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4932 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4935 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4937 return NT_STATUS_INTERNAL_ERROR
;
4939 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4941 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4944 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4946 return NT_STATUS_INTERNAL_ERROR
;
4950 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4953 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4955 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4961 case SMB_QUERY_POSIX_LOCK
:
4966 enum brl_type lock_type
;
4968 /* We need an open file with a real fd for this. */
4969 if (!fsp
|| fsp
->fh
->fd
== -1) {
4970 return NT_STATUS_INVALID_LEVEL
;
4973 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4974 return NT_STATUS_INVALID_PARAMETER
;
4977 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4978 case POSIX_LOCK_TYPE_READ
:
4979 lock_type
= READ_LOCK
;
4981 case POSIX_LOCK_TYPE_WRITE
:
4982 lock_type
= WRITE_LOCK
;
4984 case POSIX_LOCK_TYPE_UNLOCK
:
4986 /* There's no point in asking for an unlock... */
4987 return NT_STATUS_INVALID_PARAMETER
;
4990 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4991 #if defined(HAVE_LONGLONG)
4992 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4993 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4994 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4995 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4996 #else /* HAVE_LONGLONG */
4997 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4998 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4999 #endif /* HAVE_LONGLONG */
5001 status
= query_lock(fsp
,
5008 if (ERROR_WAS_LOCK_DENIED(status
)) {
5009 /* Here we need to report who has it locked... */
5010 data_size
= POSIX_LOCK_DATA_SIZE
;
5012 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5013 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5014 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5015 #if defined(HAVE_LONGLONG)
5016 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5017 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5018 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5019 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5020 #else /* HAVE_LONGLONG */
5021 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5022 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5023 #endif /* HAVE_LONGLONG */
5025 } else if (NT_STATUS_IS_OK(status
)) {
5026 /* For success we just return a copy of what we sent
5027 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5028 data_size
= POSIX_LOCK_DATA_SIZE
;
5029 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5030 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5038 return NT_STATUS_INVALID_LEVEL
;
5041 *pdata_size
= data_size
;
5042 return NT_STATUS_OK
;
5045 /****************************************************************************
5046 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5047 file name or file id).
5048 ****************************************************************************/
5050 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5051 struct smb_request
*req
,
5052 unsigned int tran_call
,
5053 char **pparams
, int total_params
,
5054 char **ppdata
, int total_data
,
5055 unsigned int max_data_bytes
)
5057 char *params
= *pparams
;
5058 char *pdata
= *ppdata
;
5060 unsigned int data_size
= 0;
5061 unsigned int param_size
= 2;
5062 struct smb_filename
*smb_fname
= NULL
;
5063 bool delete_pending
= False
;
5064 struct timespec write_time_ts
;
5065 files_struct
*fsp
= NULL
;
5066 struct file_id fileid
;
5067 struct ea_list
*ea_list
= NULL
;
5068 int lock_data_count
= 0;
5069 char *lock_data
= NULL
;
5070 NTSTATUS status
= NT_STATUS_OK
;
5073 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5077 ZERO_STRUCT(write_time_ts
);
5079 if (tran_call
== TRANSACT2_QFILEINFO
) {
5080 if (total_params
< 4) {
5081 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5086 call_trans2qpipeinfo(conn
, req
, tran_call
,
5087 pparams
, total_params
,
5093 fsp
= file_fsp(req
, SVAL(params
,0));
5094 info_level
= SVAL(params
,2);
5096 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5098 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5099 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5103 /* Initial check for valid fsp ptr. */
5104 if (!check_fsp_open(conn
, req
, fsp
)) {
5108 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5110 if (!NT_STATUS_IS_OK(status
)) {
5111 reply_nterror(req
, status
);
5115 if(fsp
->fake_file_handle
) {
5117 * This is actually for the QUOTA_FAKE_FILE --metze
5120 /* We know this name is ok, it's already passed the checks. */
5122 } else if(fsp
->fh
->fd
== -1) {
5124 * This is actually a QFILEINFO on a directory
5125 * handle (returned from an NT SMB). NT5.0 seems
5126 * to do this call. JRA.
5129 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5130 /* Always do lstat for UNIX calls. */
5131 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5132 DEBUG(3,("call_trans2qfilepathinfo: "
5133 "SMB_VFS_LSTAT of %s failed "
5135 smb_fname_str_dbg(smb_fname
),
5138 map_nt_error_from_unix(errno
));
5141 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5142 DEBUG(3,("call_trans2qfilepathinfo: "
5143 "SMB_VFS_STAT of %s failed (%s)\n",
5144 smb_fname_str_dbg(smb_fname
),
5147 map_nt_error_from_unix(errno
));
5151 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5152 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5155 * Original code - this is an open file.
5157 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5158 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5159 fsp
->fnum
, strerror(errno
)));
5161 map_nt_error_from_unix(errno
));
5164 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5165 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5171 uint32_t ucf_flags
= 0;
5174 if (total_params
< 7) {
5175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5179 info_level
= SVAL(params
,0);
5181 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5183 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5184 if (!lp_unix_extensions()) {
5185 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5188 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5189 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5190 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5191 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5195 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5197 STR_TERMINATE
, &status
);
5198 if (!NT_STATUS_IS_OK(status
)) {
5199 reply_nterror(req
, status
);
5203 status
= filename_convert(req
,
5205 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5210 if (!NT_STATUS_IS_OK(status
)) {
5211 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5212 reply_botherror(req
,
5213 NT_STATUS_PATH_NOT_COVERED
,
5214 ERRSRV
, ERRbadpath
);
5217 reply_nterror(req
, status
);
5221 /* If this is a stream, check if there is a delete_pending. */
5222 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5223 && is_ntfs_stream_smb_fname(smb_fname
)) {
5224 struct smb_filename
*smb_fname_base
= NULL
;
5226 /* Create an smb_filename with stream_name == NULL. */
5228 create_synthetic_smb_fname(talloc_tos(),
5229 smb_fname
->base_name
,
5232 if (!NT_STATUS_IS_OK(status
)) {
5233 reply_nterror(req
, status
);
5237 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5238 /* Always do lstat for UNIX calls. */
5239 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5240 DEBUG(3,("call_trans2qfilepathinfo: "
5241 "SMB_VFS_LSTAT of %s failed "
5243 smb_fname_str_dbg(smb_fname_base
),
5245 TALLOC_FREE(smb_fname_base
);
5247 map_nt_error_from_unix(errno
));
5251 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5252 DEBUG(3,("call_trans2qfilepathinfo: "
5253 "fileinfo of %s failed "
5255 smb_fname_str_dbg(smb_fname_base
),
5257 TALLOC_FREE(smb_fname_base
);
5259 map_nt_error_from_unix(errno
));
5264 status
= file_name_hash(conn
,
5265 smb_fname_str_dbg(smb_fname_base
),
5267 if (!NT_STATUS_IS_OK(status
)) {
5268 TALLOC_FREE(smb_fname_base
);
5269 reply_nterror(req
, status
);
5273 fileid
= vfs_file_id_from_sbuf(conn
,
5274 &smb_fname_base
->st
);
5275 TALLOC_FREE(smb_fname_base
);
5276 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5277 if (delete_pending
) {
5278 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5283 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5284 /* Always do lstat for UNIX calls. */
5285 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5286 DEBUG(3,("call_trans2qfilepathinfo: "
5287 "SMB_VFS_LSTAT of %s failed (%s)\n",
5288 smb_fname_str_dbg(smb_fname
),
5291 map_nt_error_from_unix(errno
));
5296 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5297 DEBUG(3,("call_trans2qfilepathinfo: "
5298 "SMB_VFS_STAT of %s failed (%s)\n",
5299 smb_fname_str_dbg(smb_fname
),
5302 map_nt_error_from_unix(errno
));
5307 status
= file_name_hash(conn
,
5308 smb_fname_str_dbg(smb_fname
),
5310 if (!NT_STATUS_IS_OK(status
)) {
5311 reply_nterror(req
, status
);
5315 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5316 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5317 if (delete_pending
) {
5318 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5323 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5324 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5325 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5327 /* Pull out any data sent here before we realloc. */
5328 switch (info_level
) {
5329 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5331 /* Pull any EA list from the data portion. */
5334 if (total_data
< 4) {
5336 req
, NT_STATUS_INVALID_PARAMETER
);
5339 ea_size
= IVAL(pdata
,0);
5341 if (total_data
> 0 && ea_size
!= total_data
) {
5342 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5343 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5345 req
, NT_STATUS_INVALID_PARAMETER
);
5349 if (!lp_ea_support(SNUM(conn
))) {
5350 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5354 /* Pull out the list of names. */
5355 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5358 req
, NT_STATUS_INVALID_PARAMETER
);
5364 case SMB_QUERY_POSIX_LOCK
:
5366 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5367 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5371 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5373 req
, NT_STATUS_INVALID_PARAMETER
);
5377 /* Copy the lock range data. */
5378 lock_data
= (char *)talloc_memdup(
5379 req
, pdata
, total_data
);
5381 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5384 lock_data_count
= total_data
;
5390 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5391 if (*pparams
== NULL
) {
5392 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5399 * draft-leach-cifs-v1-spec-02.txt
5400 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5403 * The requested information is placed in the Data portion of the
5404 * transaction response. For the information levels greater than 0x100,
5405 * the transaction response has 1 parameter word which should be
5406 * ignored by the client.
5408 * However Windows only follows this rule for the IS_NAME_VALID call.
5410 switch (info_level
) {
5411 case SMB_INFO_IS_NAME_VALID
:
5416 if ((info_level
& 0xFF00) == 0xFF00) {
5418 * We use levels that start with 0xFF00
5419 * internally to represent SMB2 specific levels
5421 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5425 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5427 delete_pending
, write_time_ts
,
5429 lock_data_count
, lock_data
,
5430 req
->flags2
, max_data_bytes
,
5431 ppdata
, &data_size
);
5432 if (!NT_STATUS_IS_OK(status
)) {
5433 reply_nterror(req
, status
);
5437 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5443 /****************************************************************************
5444 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5446 ****************************************************************************/
5448 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5449 connection_struct
*conn
,
5450 struct smb_request
*req
,
5451 bool overwrite_if_exists
,
5452 const struct smb_filename
*smb_fname_old
,
5453 struct smb_filename
*smb_fname_new
)
5455 NTSTATUS status
= NT_STATUS_OK
;
5457 /* source must already exist. */
5458 if (!VALID_STAT(smb_fname_old
->st
)) {
5459 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5462 if (VALID_STAT(smb_fname_new
->st
)) {
5463 if (overwrite_if_exists
) {
5464 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5465 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5467 status
= unlink_internals(conn
,
5469 FILE_ATTRIBUTE_NORMAL
,
5472 if (!NT_STATUS_IS_OK(status
)) {
5476 /* Disallow if newname already exists. */
5477 return NT_STATUS_OBJECT_NAME_COLLISION
;
5481 /* No links from a directory. */
5482 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5483 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5486 /* Setting a hardlink to/from a stream isn't currently supported. */
5487 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5488 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5489 return NT_STATUS_INVALID_PARAMETER
;
5492 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5493 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5495 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5496 smb_fname_new
->base_name
) != 0) {
5497 status
= map_nt_error_from_unix(errno
);
5498 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5499 nt_errstr(status
), smb_fname_old
->base_name
,
5500 smb_fname_new
->base_name
));
5505 /****************************************************************************
5506 Deal with setting the time from any of the setfilepathinfo functions.
5507 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5508 calling this function.
5509 ****************************************************************************/
5511 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5513 const struct smb_filename
*smb_fname
,
5514 struct smb_file_time
*ft
,
5515 bool setting_write_time
)
5517 struct smb_filename smb_fname_base
;
5519 FILE_NOTIFY_CHANGE_LAST_ACCESS
5520 |FILE_NOTIFY_CHANGE_LAST_WRITE
5521 |FILE_NOTIFY_CHANGE_CREATION
;
5523 if (!VALID_STAT(smb_fname
->st
)) {
5524 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5527 /* get some defaults (no modifications) if any info is zero or -1. */
5528 if (null_timespec(ft
->create_time
)) {
5529 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5532 if (null_timespec(ft
->atime
)) {
5533 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5536 if (null_timespec(ft
->mtime
)) {
5537 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5540 if (!setting_write_time
) {
5541 /* ft->mtime comes from change time, not write time. */
5542 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5545 /* Ensure the resolution is the correct for
5546 * what we can store on this filesystem. */
5548 round_timespec(conn
->ts_res
, &ft
->create_time
);
5549 round_timespec(conn
->ts_res
, &ft
->ctime
);
5550 round_timespec(conn
->ts_res
, &ft
->atime
);
5551 round_timespec(conn
->ts_res
, &ft
->mtime
);
5553 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5554 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5555 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5556 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5557 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5558 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5559 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5560 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5562 if (setting_write_time
) {
5564 * This was a Windows setfileinfo on an open file.
5565 * NT does this a lot. We also need to
5566 * set the time here, as it can be read by
5567 * FindFirst/FindNext and with the patch for bug #2045
5568 * in smbd/fileio.c it ensures that this timestamp is
5569 * kept sticky even after a write. We save the request
5570 * away and will set it on file close and after a write. JRA.
5573 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5574 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5577 if (fsp
->base_fsp
) {
5578 set_sticky_write_time_fsp(fsp
->base_fsp
,
5581 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5584 set_sticky_write_time_path(
5585 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5590 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5592 /* Always call ntimes on the base, even if a stream was passed in. */
5593 smb_fname_base
= *smb_fname
;
5594 smb_fname_base
.stream_name
= NULL
;
5596 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5597 return map_nt_error_from_unix(errno
);
5600 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5601 smb_fname
->base_name
);
5602 return NT_STATUS_OK
;
5605 /****************************************************************************
5606 Deal with setting the dosmode from any of the setfilepathinfo functions.
5607 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5608 done before calling this function.
5609 ****************************************************************************/
5611 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5612 const struct smb_filename
*smb_fname
,
5615 struct smb_filename
*smb_fname_base
= NULL
;
5618 if (!VALID_STAT(smb_fname
->st
)) {
5619 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5622 /* Always operate on the base_name, even if a stream was passed in. */
5623 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5624 NULL
, &smb_fname
->st
,
5626 if (!NT_STATUS_IS_OK(status
)) {
5631 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5632 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5634 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5638 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5640 /* check the mode isn't different, before changing it */
5641 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5642 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5643 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5644 (unsigned int)dosmode
));
5646 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5648 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5650 smb_fname_str_dbg(smb_fname_base
),
5652 status
= map_nt_error_from_unix(errno
);
5656 status
= NT_STATUS_OK
;
5658 TALLOC_FREE(smb_fname_base
);
5662 /****************************************************************************
5663 Deal with setting the size from any of the setfilepathinfo functions.
5664 ****************************************************************************/
5666 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5667 struct smb_request
*req
,
5669 const struct smb_filename
*smb_fname
,
5670 const SMB_STRUCT_STAT
*psbuf
,
5672 bool fail_after_createfile
)
5674 NTSTATUS status
= NT_STATUS_OK
;
5675 struct smb_filename
*smb_fname_tmp
= NULL
;
5676 files_struct
*new_fsp
= NULL
;
5678 if (!VALID_STAT(*psbuf
)) {
5679 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5682 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5684 if (size
== get_file_size_stat(psbuf
)) {
5685 return NT_STATUS_OK
;
5688 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5689 smb_fname_str_dbg(smb_fname
), (double)size
));
5691 if (fsp
&& fsp
->fh
->fd
!= -1) {
5692 /* Handle based call. */
5693 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5694 return NT_STATUS_ACCESS_DENIED
;
5697 if (vfs_set_filelen(fsp
, size
) == -1) {
5698 return map_nt_error_from_unix(errno
);
5700 trigger_write_time_update_immediate(fsp
);
5701 return NT_STATUS_OK
;
5704 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5705 if (!NT_STATUS_IS_OK(status
)) {
5709 smb_fname_tmp
->st
= *psbuf
;
5711 status
= SMB_VFS_CREATE_FILE(
5714 0, /* root_dir_fid */
5715 smb_fname_tmp
, /* fname */
5716 FILE_WRITE_DATA
, /* access_mask */
5717 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5719 FILE_OPEN
, /* create_disposition*/
5720 0, /* create_options */
5721 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5722 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5723 0, /* allocation_size */
5724 0, /* private_flags */
5727 &new_fsp
, /* result */
5730 TALLOC_FREE(smb_fname_tmp
);
5732 if (!NT_STATUS_IS_OK(status
)) {
5733 /* NB. We check for open_was_deferred in the caller. */
5737 /* See RAW-SFILEINFO-END-OF-FILE */
5738 if (fail_after_createfile
) {
5739 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5740 return NT_STATUS_INVALID_LEVEL
;
5743 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5744 status
= map_nt_error_from_unix(errno
);
5745 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5749 trigger_write_time_update_immediate(new_fsp
);
5750 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5751 return NT_STATUS_OK
;
5754 /****************************************************************************
5755 Deal with SMB_INFO_SET_EA.
5756 ****************************************************************************/
5758 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5762 const struct smb_filename
*smb_fname
)
5764 struct ea_list
*ea_list
= NULL
;
5765 TALLOC_CTX
*ctx
= NULL
;
5766 NTSTATUS status
= NT_STATUS_OK
;
5768 if (total_data
< 10) {
5770 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5771 length. They seem to have no effect. Bug #3212. JRA */
5773 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5774 /* We're done. We only get EA info in this call. */
5775 return NT_STATUS_OK
;
5778 return NT_STATUS_INVALID_PARAMETER
;
5781 if (IVAL(pdata
,0) > total_data
) {
5782 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5783 IVAL(pdata
,0), (unsigned int)total_data
));
5784 return NT_STATUS_INVALID_PARAMETER
;
5788 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5790 return NT_STATUS_INVALID_PARAMETER
;
5793 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5798 /****************************************************************************
5799 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5800 ****************************************************************************/
5802 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5807 struct ea_list
*ea_list
= NULL
;
5811 return NT_STATUS_INVALID_HANDLE
;
5814 if (!lp_ea_support(SNUM(conn
))) {
5815 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5816 "EA's not supported.\n",
5817 (unsigned int)total_data
));
5818 return NT_STATUS_EAS_NOT_SUPPORTED
;
5821 if (total_data
< 10) {
5822 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5824 (unsigned int)total_data
));
5825 return NT_STATUS_INVALID_PARAMETER
;
5828 ea_list
= read_nttrans_ea_list(talloc_tos(),
5833 return NT_STATUS_INVALID_PARAMETER
;
5836 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5838 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5839 smb_fname_str_dbg(fsp
->fsp_name
),
5840 nt_errstr(status
) ));
5846 /****************************************************************************
5847 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5848 ****************************************************************************/
5850 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5854 struct smb_filename
*smb_fname
)
5856 NTSTATUS status
= NT_STATUS_OK
;
5857 bool delete_on_close
;
5860 if (total_data
< 1) {
5861 return NT_STATUS_INVALID_PARAMETER
;
5865 return NT_STATUS_INVALID_HANDLE
;
5868 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5869 dosmode
= dos_mode(conn
, smb_fname
);
5871 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5872 "delete_on_close = %u\n",
5873 smb_fname_str_dbg(smb_fname
),
5874 (unsigned int)dosmode
,
5875 (unsigned int)delete_on_close
));
5877 if (delete_on_close
) {
5878 status
= can_set_delete_on_close(fsp
, dosmode
);
5879 if (!NT_STATUS_IS_OK(status
)) {
5884 /* The set is across all open files on this dev/inode pair. */
5885 if (!set_delete_on_close(fsp
, delete_on_close
,
5886 conn
->session_info
->security_token
,
5887 conn
->session_info
->unix_token
)) {
5888 return NT_STATUS_ACCESS_DENIED
;
5890 return NT_STATUS_OK
;
5893 /****************************************************************************
5894 Deal with SMB_FILE_POSITION_INFORMATION.
5895 ****************************************************************************/
5897 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5902 uint64_t position_information
;
5904 if (total_data
< 8) {
5905 return NT_STATUS_INVALID_PARAMETER
;
5909 /* Ignore on pathname based set. */
5910 return NT_STATUS_OK
;
5913 position_information
= (uint64_t)IVAL(pdata
,0);
5914 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5916 DEBUG(10,("smb_file_position_information: Set file position "
5917 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5918 (double)position_information
));
5919 fsp
->fh
->position_information
= position_information
;
5920 return NT_STATUS_OK
;
5923 /****************************************************************************
5924 Deal with SMB_FILE_MODE_INFORMATION.
5925 ****************************************************************************/
5927 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5933 if (total_data
< 4) {
5934 return NT_STATUS_INVALID_PARAMETER
;
5936 mode
= IVAL(pdata
,0);
5937 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5938 return NT_STATUS_INVALID_PARAMETER
;
5940 return NT_STATUS_OK
;
5943 /****************************************************************************
5944 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5945 ****************************************************************************/
5947 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5948 struct smb_request
*req
,
5951 const struct smb_filename
*smb_fname
)
5953 char *link_target
= NULL
;
5954 const char *newname
= smb_fname
->base_name
;
5955 TALLOC_CTX
*ctx
= talloc_tos();
5957 /* Set a symbolic link. */
5958 /* Don't allow this if follow links is false. */
5960 if (total_data
== 0) {
5961 return NT_STATUS_INVALID_PARAMETER
;
5964 if (!lp_symlinks(SNUM(conn
))) {
5965 return NT_STATUS_ACCESS_DENIED
;
5968 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5969 total_data
, STR_TERMINATE
);
5972 return NT_STATUS_INVALID_PARAMETER
;
5975 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5976 newname
, link_target
));
5978 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5979 return map_nt_error_from_unix(errno
);
5982 return NT_STATUS_OK
;
5985 /****************************************************************************
5986 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5987 ****************************************************************************/
5989 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5990 struct smb_request
*req
,
5991 const char *pdata
, int total_data
,
5992 struct smb_filename
*smb_fname_new
)
5994 char *oldname
= NULL
;
5995 struct smb_filename
*smb_fname_old
= NULL
;
5996 TALLOC_CTX
*ctx
= talloc_tos();
5997 NTSTATUS status
= NT_STATUS_OK
;
5999 /* Set a hard link. */
6000 if (total_data
== 0) {
6001 return NT_STATUS_INVALID_PARAMETER
;
6004 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6005 total_data
, STR_TERMINATE
, &status
);
6006 if (!NT_STATUS_IS_OK(status
)) {
6010 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6011 smb_fname_str_dbg(smb_fname_new
), oldname
));
6013 status
= filename_convert(ctx
,
6015 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6020 if (!NT_STATUS_IS_OK(status
)) {
6024 return hardlink_internals(ctx
, conn
, req
, false,
6025 smb_fname_old
, smb_fname_new
);
6028 /****************************************************************************
6029 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6030 ****************************************************************************/
6032 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6033 struct smb_request
*req
,
6037 struct smb_filename
*smb_fname_src
)
6041 char *newname
= NULL
;
6042 struct smb_filename
*smb_fname_dst
= NULL
;
6043 NTSTATUS status
= NT_STATUS_OK
;
6044 TALLOC_CTX
*ctx
= talloc_tos();
6047 return NT_STATUS_INVALID_HANDLE
;
6050 if (total_data
< 20) {
6051 return NT_STATUS_INVALID_PARAMETER
;
6054 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6055 len
= IVAL(pdata
,16);
6057 if (len
> (total_data
- 20) || (len
== 0)) {
6058 return NT_STATUS_INVALID_PARAMETER
;
6061 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6062 &pdata
[20], len
, STR_TERMINATE
,
6064 if (!NT_STATUS_IS_OK(status
)) {
6068 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6071 status
= filename_convert(ctx
,
6073 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6078 if (!NT_STATUS_IS_OK(status
)) {
6082 if (fsp
->base_fsp
) {
6083 /* newname must be a stream name. */
6084 if (newname
[0] != ':') {
6085 return NT_STATUS_NOT_SUPPORTED
;
6088 /* Create an smb_fname to call rename_internals_fsp() with. */
6089 status
= create_synthetic_smb_fname(talloc_tos(),
6090 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6092 if (!NT_STATUS_IS_OK(status
)) {
6097 * Set the original last component, since
6098 * rename_internals_fsp() requires it.
6100 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6102 if (smb_fname_dst
->original_lcomp
== NULL
) {
6103 status
= NT_STATUS_NO_MEMORY
;
6109 DEBUG(10,("smb2_file_rename_information: "
6110 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6111 fsp
->fnum
, fsp_str_dbg(fsp
),
6112 smb_fname_str_dbg(smb_fname_dst
)));
6113 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6114 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6118 TALLOC_FREE(smb_fname_dst
);
6122 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6123 struct smb_request
*req
,
6127 struct smb_filename
*smb_fname_src
)
6131 char *newname
= NULL
;
6132 struct smb_filename
*smb_fname_dst
= NULL
;
6133 NTSTATUS status
= NT_STATUS_OK
;
6134 TALLOC_CTX
*ctx
= talloc_tos();
6137 return NT_STATUS_INVALID_HANDLE
;
6140 if (total_data
< 20) {
6141 return NT_STATUS_INVALID_PARAMETER
;
6144 overwrite
= (CVAL(pdata
,0) ? true : false);
6145 len
= IVAL(pdata
,16);
6147 if (len
> (total_data
- 20) || (len
== 0)) {
6148 return NT_STATUS_INVALID_PARAMETER
;
6151 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6152 &pdata
[20], len
, STR_TERMINATE
,
6154 if (!NT_STATUS_IS_OK(status
)) {
6158 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6161 status
= filename_convert(ctx
,
6163 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6168 if (!NT_STATUS_IS_OK(status
)) {
6172 if (fsp
->base_fsp
) {
6173 /* No stream names. */
6174 return NT_STATUS_NOT_SUPPORTED
;
6177 DEBUG(10,("smb_file_link_information: "
6178 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6179 fsp
->fnum
, fsp_str_dbg(fsp
),
6180 smb_fname_str_dbg(smb_fname_dst
)));
6181 status
= hardlink_internals(ctx
,
6188 TALLOC_FREE(smb_fname_dst
);
6192 /****************************************************************************
6193 Deal with SMB_FILE_RENAME_INFORMATION.
6194 ****************************************************************************/
6196 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6197 struct smb_request
*req
,
6201 struct smb_filename
*smb_fname_src
)
6206 char *newname
= NULL
;
6207 struct smb_filename
*smb_fname_dst
= NULL
;
6208 bool dest_has_wcard
= False
;
6209 NTSTATUS status
= NT_STATUS_OK
;
6211 TALLOC_CTX
*ctx
= talloc_tos();
6213 if (total_data
< 13) {
6214 return NT_STATUS_INVALID_PARAMETER
;
6217 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6218 root_fid
= IVAL(pdata
,4);
6219 len
= IVAL(pdata
,8);
6221 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6222 return NT_STATUS_INVALID_PARAMETER
;
6225 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6228 if (!NT_STATUS_IS_OK(status
)) {
6232 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6235 status
= resolve_dfspath_wcard(ctx
, conn
,
6236 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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 (fnum %d) %s -> %s\n",
6341 fsp
->fnum
, 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 /* Fail with sharing violation. */
7599 close_file(req
, fsp
, NORMAL_CLOSE
);
7601 return NT_STATUS_SHARING_VIOLATION
;
7606 * Set the delete on close.
7608 status
= smb_set_file_disposition_info(conn
,
7614 if (!NT_STATUS_IS_OK(status
)) {
7615 close_file(req
, fsp
, NORMAL_CLOSE
);
7620 return close_file(req
, fsp
, NORMAL_CLOSE
);
7623 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7624 struct smb_request
*req
,
7625 TALLOC_CTX
*mem_ctx
,
7626 uint16_t info_level
,
7628 struct smb_filename
*smb_fname
,
7629 char **ppdata
, int total_data
,
7632 char *pdata
= *ppdata
;
7633 NTSTATUS status
= NT_STATUS_OK
;
7634 int data_return_size
= 0;
7638 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7639 return NT_STATUS_INVALID_LEVEL
;
7642 if (!CAN_WRITE(conn
)) {
7643 /* Allow POSIX opens. The open path will deny
7644 * any non-readonly opens. */
7645 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7646 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7650 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7651 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7652 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7654 switch (info_level
) {
7656 case SMB_INFO_STANDARD
:
7658 status
= smb_set_info_standard(conn
,
7666 case SMB_INFO_SET_EA
:
7668 status
= smb_info_set_ea(conn
,
7676 case SMB_SET_FILE_BASIC_INFO
:
7677 case SMB_FILE_BASIC_INFORMATION
:
7679 status
= smb_set_file_basic_info(conn
,
7687 case SMB_FILE_ALLOCATION_INFORMATION
:
7688 case SMB_SET_FILE_ALLOCATION_INFO
:
7690 status
= smb_set_file_allocation_info(conn
, req
,
7698 case SMB_FILE_END_OF_FILE_INFORMATION
:
7699 case SMB_SET_FILE_END_OF_FILE_INFO
:
7702 * XP/Win7 both fail after the createfile with
7703 * SMB_SET_FILE_END_OF_FILE_INFO but not
7704 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7705 * The level is known here, so pass it down
7709 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7711 status
= smb_set_file_end_of_file_info(conn
, req
,
7720 case SMB_FILE_DISPOSITION_INFORMATION
:
7721 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7724 /* JRA - We used to just ignore this on a path ?
7725 * Shouldn't this be invalid level on a pathname
7728 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7729 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7732 status
= smb_set_file_disposition_info(conn
,
7740 case SMB_FILE_POSITION_INFORMATION
:
7742 status
= smb_file_position_information(conn
,
7749 case SMB_FILE_FULL_EA_INFORMATION
:
7751 status
= smb_set_file_full_ea_info(conn
,
7758 /* From tridge Samba4 :
7759 * MODE_INFORMATION in setfileinfo (I have no
7760 * idea what "mode information" on a file is - it takes a value of 0,
7761 * 2, 4 or 6. What could it be?).
7764 case SMB_FILE_MODE_INFORMATION
:
7766 status
= smb_file_mode_information(conn
,
7773 * CIFS UNIX extensions.
7776 case SMB_SET_FILE_UNIX_BASIC
:
7778 status
= smb_set_file_unix_basic(conn
, req
,
7786 case SMB_SET_FILE_UNIX_INFO2
:
7788 status
= smb_set_file_unix_info2(conn
, req
,
7796 case SMB_SET_FILE_UNIX_LINK
:
7799 /* We must have a pathname for this. */
7800 return NT_STATUS_INVALID_LEVEL
;
7802 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7803 total_data
, smb_fname
);
7807 case SMB_SET_FILE_UNIX_HLINK
:
7810 /* We must have a pathname for this. */
7811 return NT_STATUS_INVALID_LEVEL
;
7813 status
= smb_set_file_unix_hlink(conn
, req
,
7819 case SMB_FILE_RENAME_INFORMATION
:
7821 status
= smb_file_rename_information(conn
, req
,
7827 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7829 /* SMB2 rename information. */
7830 status
= smb2_file_rename_information(conn
, req
,
7836 case SMB_FILE_LINK_INFORMATION
:
7838 status
= smb_file_link_information(conn
, req
,
7844 #if defined(HAVE_POSIX_ACLS)
7845 case SMB_SET_POSIX_ACL
:
7847 status
= smb_set_posix_acl(conn
,
7856 case SMB_SET_POSIX_LOCK
:
7859 return NT_STATUS_INVALID_LEVEL
;
7861 status
= smb_set_posix_lock(conn
, req
,
7862 pdata
, total_data
, fsp
);
7866 case SMB_POSIX_PATH_OPEN
:
7869 /* We must have a pathname for this. */
7870 return NT_STATUS_INVALID_LEVEL
;
7873 status
= smb_posix_open(conn
, req
,
7881 case SMB_POSIX_PATH_UNLINK
:
7884 /* We must have a pathname for this. */
7885 return NT_STATUS_INVALID_LEVEL
;
7888 status
= smb_posix_unlink(conn
, req
,
7896 return NT_STATUS_INVALID_LEVEL
;
7899 if (!NT_STATUS_IS_OK(status
)) {
7903 *ret_data_size
= data_return_size
;
7904 return NT_STATUS_OK
;
7907 /****************************************************************************
7908 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7909 ****************************************************************************/
7911 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7912 struct smb_request
*req
,
7913 unsigned int tran_call
,
7914 char **pparams
, int total_params
,
7915 char **ppdata
, int total_data
,
7916 unsigned int max_data_bytes
)
7918 char *params
= *pparams
;
7919 char *pdata
= *ppdata
;
7921 struct smb_filename
*smb_fname
= NULL
;
7922 files_struct
*fsp
= NULL
;
7923 NTSTATUS status
= NT_STATUS_OK
;
7924 int data_return_size
= 0;
7927 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7931 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7932 if (total_params
< 4) {
7933 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7937 fsp
= file_fsp(req
, SVAL(params
,0));
7938 /* Basic check for non-null fsp. */
7939 if (!check_fsp_open(conn
, req
, fsp
)) {
7942 info_level
= SVAL(params
,2);
7944 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7946 if (!NT_STATUS_IS_OK(status
)) {
7947 reply_nterror(req
, status
);
7951 if(fsp
->fh
->fd
== -1) {
7953 * This is actually a SETFILEINFO on a directory
7954 * handle (returned from an NT SMB). NT5.0 seems
7955 * to do this call. JRA.
7957 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7958 /* Always do lstat for UNIX calls. */
7959 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7960 DEBUG(3,("call_trans2setfilepathinfo: "
7961 "SMB_VFS_LSTAT of %s failed "
7963 smb_fname_str_dbg(smb_fname
),
7965 reply_nterror(req
, map_nt_error_from_unix(errno
));
7969 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7970 DEBUG(3,("call_trans2setfilepathinfo: "
7971 "fileinfo of %s failed (%s)\n",
7972 smb_fname_str_dbg(smb_fname
),
7974 reply_nterror(req
, map_nt_error_from_unix(errno
));
7978 } else if (fsp
->print_file
) {
7980 * Doing a DELETE_ON_CLOSE should cancel a print job.
7982 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7983 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7985 DEBUG(3,("call_trans2setfilepathinfo: "
7986 "Cancelling print job (%s)\n",
7990 send_trans2_replies(conn
, req
, params
, 2,
7996 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8001 * Original code - this is an open file.
8003 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8004 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8005 "of fnum %d failed (%s)\n", fsp
->fnum
,
8007 reply_nterror(req
, map_nt_error_from_unix(errno
));
8013 uint32_t ucf_flags
= 0;
8016 if (total_params
< 7) {
8017 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8021 info_level
= SVAL(params
,0);
8022 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8023 total_params
- 6, STR_TERMINATE
,
8025 if (!NT_STATUS_IS_OK(status
)) {
8026 reply_nterror(req
, status
);
8030 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8031 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8032 info_level
== SMB_FILE_RENAME_INFORMATION
||
8033 info_level
== SMB_POSIX_PATH_UNLINK
) {
8034 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8037 status
= filename_convert(req
, conn
,
8038 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8043 if (!NT_STATUS_IS_OK(status
)) {
8044 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8045 reply_botherror(req
,
8046 NT_STATUS_PATH_NOT_COVERED
,
8047 ERRSRV
, ERRbadpath
);
8050 reply_nterror(req
, status
);
8054 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8056 * For CIFS UNIX extensions the target name may not exist.
8059 /* Always do lstat for UNIX calls. */
8060 SMB_VFS_LSTAT(conn
, smb_fname
);
8062 } else if (!VALID_STAT(smb_fname
->st
) &&
8063 SMB_VFS_STAT(conn
, smb_fname
)) {
8064 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8066 smb_fname_str_dbg(smb_fname
),
8068 reply_nterror(req
, map_nt_error_from_unix(errno
));
8073 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8074 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8075 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8077 /* Realloc the parameter size */
8078 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8079 if (*pparams
== NULL
) {
8080 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8087 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8093 if (!NT_STATUS_IS_OK(status
)) {
8094 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8095 /* We have re-scheduled this call. */
8098 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8099 /* We have re-scheduled this call. */
8102 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8103 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8104 ERRSRV
, ERRbadpath
);
8107 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8108 reply_openerror(req
, status
);
8112 reply_nterror(req
, status
);
8116 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8122 /****************************************************************************
8123 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8124 ****************************************************************************/
8126 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8127 char **pparams
, int total_params
,
8128 char **ppdata
, int total_data
,
8129 unsigned int max_data_bytes
)
8131 struct smb_filename
*smb_dname
= NULL
;
8132 char *params
= *pparams
;
8133 char *pdata
= *ppdata
;
8134 char *directory
= NULL
;
8135 NTSTATUS status
= NT_STATUS_OK
;
8136 struct ea_list
*ea_list
= NULL
;
8137 TALLOC_CTX
*ctx
= talloc_tos();
8139 if (!CAN_WRITE(conn
)) {
8140 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8144 if (total_params
< 5) {
8145 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8149 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8150 total_params
- 4, STR_TERMINATE
,
8152 if (!NT_STATUS_IS_OK(status
)) {
8153 reply_nterror(req
, status
);
8157 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8159 status
= filename_convert(ctx
,
8161 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8167 if (!NT_STATUS_IS_OK(status
)) {
8168 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8169 reply_botherror(req
,
8170 NT_STATUS_PATH_NOT_COVERED
,
8171 ERRSRV
, ERRbadpath
);
8174 reply_nterror(req
, status
);
8179 * OS/2 workplace shell seems to send SET_EA requests of "null"
8180 * length (4 bytes containing IVAL 4).
8181 * They seem to have no effect. Bug #3212. JRA.
8184 if (total_data
&& (total_data
!= 4)) {
8185 /* Any data in this call is an EA list. */
8186 if (total_data
< 10) {
8187 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8191 if (IVAL(pdata
,0) > total_data
) {
8192 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8193 IVAL(pdata
,0), (unsigned int)total_data
));
8194 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8198 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8201 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8205 if (!lp_ea_support(SNUM(conn
))) {
8206 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8210 /* If total_data == 4 Windows doesn't care what values
8211 * are placed in that field, it just ignores them.
8212 * The System i QNTC IBM SMB client puts bad values here,
8213 * so ignore them. */
8215 status
= create_directory(conn
, req
, smb_dname
);
8217 if (!NT_STATUS_IS_OK(status
)) {
8218 reply_nterror(req
, status
);
8222 /* Try and set any given EA. */
8224 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8225 if (!NT_STATUS_IS_OK(status
)) {
8226 reply_nterror(req
, status
);
8231 /* Realloc the parameter and data sizes */
8232 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8233 if(*pparams
== NULL
) {
8234 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8241 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8244 TALLOC_FREE(smb_dname
);
8248 /****************************************************************************
8249 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8250 We don't actually do this - we just send a null response.
8251 ****************************************************************************/
8253 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8254 struct smb_request
*req
,
8255 char **pparams
, int total_params
,
8256 char **ppdata
, int total_data
,
8257 unsigned int max_data_bytes
)
8259 char *params
= *pparams
;
8262 if (total_params
< 6) {
8263 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8267 info_level
= SVAL(params
,4);
8268 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8270 switch (info_level
) {
8275 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8279 /* Realloc the parameter and data sizes */
8280 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8281 if (*pparams
== NULL
) {
8282 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8287 SSVAL(params
,0,fnf_handle
);
8288 SSVAL(params
,2,0); /* No changes */
8289 SSVAL(params
,4,0); /* No EA errors */
8296 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8301 /****************************************************************************
8302 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8303 changes). Currently this does nothing.
8304 ****************************************************************************/
8306 static void call_trans2findnotifynext(connection_struct
*conn
,
8307 struct smb_request
*req
,
8308 char **pparams
, int total_params
,
8309 char **ppdata
, int total_data
,
8310 unsigned int max_data_bytes
)
8312 char *params
= *pparams
;
8314 DEBUG(3,("call_trans2findnotifynext\n"));
8316 /* Realloc the parameter and data sizes */
8317 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8318 if (*pparams
== NULL
) {
8319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8324 SSVAL(params
,0,0); /* No changes */
8325 SSVAL(params
,2,0); /* No EA errors */
8327 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8332 /****************************************************************************
8333 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8334 ****************************************************************************/
8336 static void call_trans2getdfsreferral(connection_struct
*conn
,
8337 struct smb_request
*req
,
8338 char **pparams
, int total_params
,
8339 char **ppdata
, int total_data
,
8340 unsigned int max_data_bytes
)
8342 char *params
= *pparams
;
8343 char *pathname
= NULL
;
8345 int max_referral_level
;
8346 NTSTATUS status
= NT_STATUS_OK
;
8347 TALLOC_CTX
*ctx
= talloc_tos();
8349 DEBUG(10,("call_trans2getdfsreferral\n"));
8351 if (total_params
< 3) {
8352 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8356 max_referral_level
= SVAL(params
,0);
8358 if(!lp_host_msdfs()) {
8359 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8363 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8364 total_params
- 2, STR_TERMINATE
);
8366 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8369 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8370 ppdata
,&status
)) < 0) {
8371 reply_nterror(req
, status
);
8375 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8376 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8377 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8382 #define LMCAT_SPL 0x53
8383 #define LMFUNC_GETJOBID 0x60
8385 /****************************************************************************
8386 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8387 ****************************************************************************/
8389 static void call_trans2ioctl(connection_struct
*conn
,
8390 struct smb_request
*req
,
8391 char **pparams
, int total_params
,
8392 char **ppdata
, int total_data
,
8393 unsigned int max_data_bytes
)
8395 char *pdata
= *ppdata
;
8396 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8398 /* check for an invalid fid before proceeding */
8401 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8405 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8406 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8407 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8408 if (*ppdata
== NULL
) {
8409 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8414 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8415 CAN ACCEPT THIS IN UNICODE. JRA. */
8418 if (fsp
->print_file
) {
8419 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8423 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8424 lp_netbios_name(), 15,
8425 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8426 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8427 lp_servicename(SNUM(conn
)), 13,
8428 STR_ASCII
|STR_TERMINATE
); /* Service name */
8429 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8434 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8435 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8438 /****************************************************************************
8439 Reply to a SMBfindclose (stop trans2 directory search).
8440 ****************************************************************************/
8442 void reply_findclose(struct smb_request
*req
)
8445 struct smbd_server_connection
*sconn
= req
->sconn
;
8447 START_PROFILE(SMBfindclose
);
8450 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8451 END_PROFILE(SMBfindclose
);
8455 dptr_num
= SVALS(req
->vwv
+0, 0);
8457 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8459 dptr_close(sconn
, &dptr_num
);
8461 reply_outbuf(req
, 0, 0);
8463 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8465 END_PROFILE(SMBfindclose
);
8469 /****************************************************************************
8470 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8471 ****************************************************************************/
8473 void reply_findnclose(struct smb_request
*req
)
8477 START_PROFILE(SMBfindnclose
);
8480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8481 END_PROFILE(SMBfindnclose
);
8485 dptr_num
= SVAL(req
->vwv
+0, 0);
8487 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8489 /* We never give out valid handles for a
8490 findnotifyfirst - so any dptr_num is ok here.
8493 reply_outbuf(req
, 0, 0);
8495 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8497 END_PROFILE(SMBfindnclose
);
8501 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8502 struct trans_state
*state
)
8504 if (get_Protocol() >= PROTOCOL_NT1
) {
8505 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8506 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8509 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8510 if (state
->call
!= TRANSACT2_QFSINFO
&&
8511 state
->call
!= TRANSACT2_SETFSINFO
) {
8512 DEBUG(0,("handle_trans2: encryption required "
8514 (unsigned int)state
->call
));
8515 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8520 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8522 /* Now we must call the relevant TRANS2 function */
8523 switch(state
->call
) {
8524 case TRANSACT2_OPEN
:
8526 START_PROFILE(Trans2_open
);
8527 call_trans2open(conn
, req
,
8528 &state
->param
, state
->total_param
,
8529 &state
->data
, state
->total_data
,
8530 state
->max_data_return
);
8531 END_PROFILE(Trans2_open
);
8535 case TRANSACT2_FINDFIRST
:
8537 START_PROFILE(Trans2_findfirst
);
8538 call_trans2findfirst(conn
, req
,
8539 &state
->param
, state
->total_param
,
8540 &state
->data
, state
->total_data
,
8541 state
->max_data_return
);
8542 END_PROFILE(Trans2_findfirst
);
8546 case TRANSACT2_FINDNEXT
:
8548 START_PROFILE(Trans2_findnext
);
8549 call_trans2findnext(conn
, req
,
8550 &state
->param
, state
->total_param
,
8551 &state
->data
, state
->total_data
,
8552 state
->max_data_return
);
8553 END_PROFILE(Trans2_findnext
);
8557 case TRANSACT2_QFSINFO
:
8559 START_PROFILE(Trans2_qfsinfo
);
8560 call_trans2qfsinfo(conn
, req
,
8561 &state
->param
, state
->total_param
,
8562 &state
->data
, state
->total_data
,
8563 state
->max_data_return
);
8564 END_PROFILE(Trans2_qfsinfo
);
8568 case TRANSACT2_SETFSINFO
:
8570 START_PROFILE(Trans2_setfsinfo
);
8571 call_trans2setfsinfo(conn
, req
,
8572 &state
->param
, state
->total_param
,
8573 &state
->data
, state
->total_data
,
8574 state
->max_data_return
);
8575 END_PROFILE(Trans2_setfsinfo
);
8579 case TRANSACT2_QPATHINFO
:
8580 case TRANSACT2_QFILEINFO
:
8582 START_PROFILE(Trans2_qpathinfo
);
8583 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8584 &state
->param
, state
->total_param
,
8585 &state
->data
, state
->total_data
,
8586 state
->max_data_return
);
8587 END_PROFILE(Trans2_qpathinfo
);
8591 case TRANSACT2_SETPATHINFO
:
8592 case TRANSACT2_SETFILEINFO
:
8594 START_PROFILE(Trans2_setpathinfo
);
8595 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8596 &state
->param
, state
->total_param
,
8597 &state
->data
, state
->total_data
,
8598 state
->max_data_return
);
8599 END_PROFILE(Trans2_setpathinfo
);
8603 case TRANSACT2_FINDNOTIFYFIRST
:
8605 START_PROFILE(Trans2_findnotifyfirst
);
8606 call_trans2findnotifyfirst(conn
, req
,
8607 &state
->param
, state
->total_param
,
8608 &state
->data
, state
->total_data
,
8609 state
->max_data_return
);
8610 END_PROFILE(Trans2_findnotifyfirst
);
8614 case TRANSACT2_FINDNOTIFYNEXT
:
8616 START_PROFILE(Trans2_findnotifynext
);
8617 call_trans2findnotifynext(conn
, req
,
8618 &state
->param
, state
->total_param
,
8619 &state
->data
, state
->total_data
,
8620 state
->max_data_return
);
8621 END_PROFILE(Trans2_findnotifynext
);
8625 case TRANSACT2_MKDIR
:
8627 START_PROFILE(Trans2_mkdir
);
8628 call_trans2mkdir(conn
, req
,
8629 &state
->param
, state
->total_param
,
8630 &state
->data
, state
->total_data
,
8631 state
->max_data_return
);
8632 END_PROFILE(Trans2_mkdir
);
8636 case TRANSACT2_GET_DFS_REFERRAL
:
8638 START_PROFILE(Trans2_get_dfs_referral
);
8639 call_trans2getdfsreferral(conn
, req
,
8640 &state
->param
, state
->total_param
,
8641 &state
->data
, state
->total_data
,
8642 state
->max_data_return
);
8643 END_PROFILE(Trans2_get_dfs_referral
);
8647 case TRANSACT2_IOCTL
:
8649 START_PROFILE(Trans2_ioctl
);
8650 call_trans2ioctl(conn
, req
,
8651 &state
->param
, state
->total_param
,
8652 &state
->data
, state
->total_data
,
8653 state
->max_data_return
);
8654 END_PROFILE(Trans2_ioctl
);
8659 /* Error in request */
8660 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8661 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8665 /****************************************************************************
8666 Reply to a SMBtrans2.
8667 ****************************************************************************/
8669 void reply_trans2(struct smb_request
*req
)
8671 connection_struct
*conn
= req
->conn
;
8676 unsigned int tran_call
;
8677 struct trans_state
*state
;
8680 START_PROFILE(SMBtrans2
);
8682 if (req
->wct
< 14) {
8683 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8684 END_PROFILE(SMBtrans2
);
8688 dsoff
= SVAL(req
->vwv
+12, 0);
8689 dscnt
= SVAL(req
->vwv
+11, 0);
8690 psoff
= SVAL(req
->vwv
+10, 0);
8691 pscnt
= SVAL(req
->vwv
+9, 0);
8692 tran_call
= SVAL(req
->vwv
+14, 0);
8694 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8695 if (!NT_STATUS_IS_OK(result
)) {
8696 DEBUG(2, ("Got invalid trans2 request: %s\n",
8697 nt_errstr(result
)));
8698 reply_nterror(req
, result
);
8699 END_PROFILE(SMBtrans2
);
8704 switch (tran_call
) {
8705 /* List the allowed trans2 calls on IPC$ */
8706 case TRANSACT2_OPEN
:
8707 case TRANSACT2_GET_DFS_REFERRAL
:
8708 case TRANSACT2_QFILEINFO
:
8709 case TRANSACT2_QFSINFO
:
8710 case TRANSACT2_SETFSINFO
:
8713 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8714 END_PROFILE(SMBtrans2
);
8719 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8720 DEBUG(0, ("talloc failed\n"));
8721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8722 END_PROFILE(SMBtrans2
);
8726 state
->cmd
= SMBtrans2
;
8728 state
->mid
= req
->mid
;
8729 state
->vuid
= req
->vuid
;
8730 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8731 state
->setup
= NULL
;
8732 state
->total_param
= SVAL(req
->vwv
+0, 0);
8733 state
->param
= NULL
;
8734 state
->total_data
= SVAL(req
->vwv
+1, 0);
8736 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8737 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8738 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8739 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8740 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8742 state
->call
= tran_call
;
8744 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8745 is so as a sanity check */
8746 if (state
->setup_count
!= 1) {
8748 * Need to have rc=0 for ioctl to get job id for OS/2.
8749 * Network printing will fail if function is not successful.
8750 * Similar function in reply.c will be used if protocol
8751 * is LANMAN1.0 instead of LM1.2X002.
8752 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8753 * outbuf doesn't have to be set(only job id is used).
8755 if ( (state
->setup_count
== 4)
8756 && (tran_call
== TRANSACT2_IOCTL
)
8757 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8758 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8759 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8761 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8762 DEBUG(2,("Transaction is %d\n",tran_call
));
8764 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8765 END_PROFILE(SMBtrans2
);
8770 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8773 if (state
->total_data
) {
8775 if (trans_oob(state
->total_data
, 0, dscnt
)
8776 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8780 /* Can't use talloc here, the core routines do realloc on the
8781 * params and data. */
8782 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8783 if (state
->data
== NULL
) {
8784 DEBUG(0,("reply_trans2: data malloc fail for %u "
8785 "bytes !\n", (unsigned int)state
->total_data
));
8787 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8788 END_PROFILE(SMBtrans2
);
8792 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8795 if (state
->total_param
) {
8797 if (trans_oob(state
->total_param
, 0, pscnt
)
8798 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8802 /* Can't use talloc here, the core routines do realloc on the
8803 * params and data. */
8804 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8805 if (state
->param
== NULL
) {
8806 DEBUG(0,("reply_trans: param malloc fail for %u "
8807 "bytes !\n", (unsigned int)state
->total_param
));
8808 SAFE_FREE(state
->data
);
8810 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8811 END_PROFILE(SMBtrans2
);
8815 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8818 state
->received_data
= dscnt
;
8819 state
->received_param
= pscnt
;
8821 if ((state
->received_param
== state
->total_param
) &&
8822 (state
->received_data
== state
->total_data
)) {
8824 handle_trans2(conn
, req
, state
);
8826 SAFE_FREE(state
->data
);
8827 SAFE_FREE(state
->param
);
8829 END_PROFILE(SMBtrans2
);
8833 DLIST_ADD(conn
->pending_trans
, state
);
8835 /* We need to send an interim response then receive the rest
8836 of the parameter/data bytes */
8837 reply_outbuf(req
, 0, 0);
8838 show_msg((char *)req
->outbuf
);
8839 END_PROFILE(SMBtrans2
);
8844 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8845 SAFE_FREE(state
->data
);
8846 SAFE_FREE(state
->param
);
8848 END_PROFILE(SMBtrans2
);
8849 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8853 /****************************************************************************
8854 Reply to a SMBtranss2
8855 ****************************************************************************/
8857 void reply_transs2(struct smb_request
*req
)
8859 connection_struct
*conn
= req
->conn
;
8860 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8861 struct trans_state
*state
;
8863 START_PROFILE(SMBtranss2
);
8865 show_msg((const char *)req
->inbuf
);
8868 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8869 END_PROFILE(SMBtranss2
);
8873 for (state
= conn
->pending_trans
; state
!= NULL
;
8874 state
= state
->next
) {
8875 if (state
->mid
== req
->mid
) {
8880 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8881 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8882 END_PROFILE(SMBtranss2
);
8886 /* Revise state->total_param and state->total_data in case they have
8887 changed downwards */
8889 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8890 state
->total_param
= SVAL(req
->vwv
+0, 0);
8891 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8892 state
->total_data
= SVAL(req
->vwv
+1, 0);
8894 pcnt
= SVAL(req
->vwv
+2, 0);
8895 poff
= SVAL(req
->vwv
+3, 0);
8896 pdisp
= SVAL(req
->vwv
+4, 0);
8898 dcnt
= SVAL(req
->vwv
+5, 0);
8899 doff
= SVAL(req
->vwv
+6, 0);
8900 ddisp
= SVAL(req
->vwv
+7, 0);
8902 state
->received_param
+= pcnt
;
8903 state
->received_data
+= dcnt
;
8905 if ((state
->received_data
> state
->total_data
) ||
8906 (state
->received_param
> state
->total_param
))
8910 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8911 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8914 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8918 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8919 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8922 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8925 if ((state
->received_param
< state
->total_param
) ||
8926 (state
->received_data
< state
->total_data
)) {
8927 END_PROFILE(SMBtranss2
);
8931 handle_trans2(conn
, req
, state
);
8933 DLIST_REMOVE(conn
->pending_trans
, state
);
8934 SAFE_FREE(state
->data
);
8935 SAFE_FREE(state
->param
);
8938 END_PROFILE(SMBtranss2
);
8943 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8944 DLIST_REMOVE(conn
->pending_trans
, state
);
8945 SAFE_FREE(state
->data
);
8946 SAFE_FREE(state
->param
);
8948 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8949 END_PROFILE(SMBtranss2
);