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 /* We ARE guest if global_sid_Builtin_Guests is
3430 * in our list of SIDs.
3432 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3433 conn
->session_info
->security_token
)) {
3434 flags
|= SMB_WHOAMI_GUEST
;
3437 /* We are NOT guest if global_sid_Authenticated_Users
3438 * is in our list of SIDs.
3440 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3441 conn
->session_info
->security_token
)) {
3442 flags
&= ~SMB_WHOAMI_GUEST
;
3445 /* NOTE: 8 bytes for UID/GID, irrespective of native
3446 * platform size. This matches
3447 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3449 data_len
= 4 /* flags */
3456 + 4 /* pad/reserved */
3457 + (conn
->session_info
->unix_token
->ngroups
* 8)
3459 + (conn
->session_info
->security_token
->num_sids
*
3463 SIVAL(pdata
, 0, flags
);
3464 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3466 (uint64_t)conn
->session_info
->unix_token
->uid
);
3467 SBIG_UINT(pdata
, 16,
3468 (uint64_t)conn
->session_info
->unix_token
->gid
);
3471 if (data_len
>= max_data_bytes
) {
3472 /* Potential overflow, skip the GIDs and SIDs. */
3474 SIVAL(pdata
, 24, 0); /* num_groups */
3475 SIVAL(pdata
, 28, 0); /* num_sids */
3476 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3477 SIVAL(pdata
, 36, 0); /* reserved */
3483 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3484 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3486 /* We walk the SID list twice, but this call is fairly
3487 * infrequent, and I don't expect that it's performance
3488 * sensitive -- jpeach
3490 for (i
= 0, sid_bytes
= 0;
3491 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3492 sid_bytes
+= ndr_size_dom_sid(
3493 &conn
->session_info
->security_token
->sids
[i
],
3497 /* SID list byte count */
3498 SIVAL(pdata
, 32, sid_bytes
);
3500 /* 4 bytes pad/reserved - must be zero */
3501 SIVAL(pdata
, 36, 0);
3505 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3506 SBIG_UINT(pdata
, data_len
,
3507 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3513 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3514 int sid_len
= ndr_size_dom_sid(
3515 &conn
->session_info
->security_token
->sids
[i
],
3518 sid_linearize(pdata
+ data_len
, sid_len
,
3519 &conn
->session_info
->security_token
->sids
[i
]);
3520 data_len
+= sid_len
;
3526 case SMB_MAC_QUERY_FS_INFO
:
3528 * Thursby MAC extension... ONLY on NTFS filesystems
3529 * once we do streams then we don't need this
3531 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3533 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3538 return NT_STATUS_INVALID_LEVEL
;
3541 *ret_data_len
= data_len
;
3542 return NT_STATUS_OK
;
3545 /****************************************************************************
3546 Reply to a TRANS2_QFSINFO (query filesystem info).
3547 ****************************************************************************/
3549 static void call_trans2qfsinfo(connection_struct
*conn
,
3550 struct smb_request
*req
,
3551 char **pparams
, int total_params
,
3552 char **ppdata
, int total_data
,
3553 unsigned int max_data_bytes
)
3555 char *params
= *pparams
;
3556 uint16_t info_level
;
3560 if (total_params
< 2) {
3561 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3565 info_level
= SVAL(params
,0);
3567 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3568 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3569 DEBUG(0,("call_trans2qfsinfo: encryption required "
3570 "and info level 0x%x sent.\n",
3571 (unsigned int)info_level
));
3572 exit_server_cleanly("encryption required "
3578 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3580 status
= smbd_do_qfsinfo(conn
, req
,
3585 if (!NT_STATUS_IS_OK(status
)) {
3586 reply_nterror(req
, status
);
3590 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3593 DEBUG( 4, ( "%s info_level = %d\n",
3594 smb_fn_name(req
->cmd
), info_level
) );
3599 /****************************************************************************
3600 Reply to a TRANS2_SETFSINFO (set filesystem info).
3601 ****************************************************************************/
3603 static void call_trans2setfsinfo(connection_struct
*conn
,
3604 struct smb_request
*req
,
3605 char **pparams
, int total_params
,
3606 char **ppdata
, int total_data
,
3607 unsigned int max_data_bytes
)
3609 struct smbd_server_connection
*sconn
= req
->sconn
;
3610 char *pdata
= *ppdata
;
3611 char *params
= *pparams
;
3614 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3617 if (total_params
< 4) {
3618 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3624 info_level
= SVAL(params
,2);
3627 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3628 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3629 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3630 "info level (0x%x) on IPC$.\n",
3631 (unsigned int)info_level
));
3632 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3637 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3638 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3639 DEBUG(0,("call_trans2setfsinfo: encryption required "
3640 "and info level 0x%x sent.\n",
3641 (unsigned int)info_level
));
3642 exit_server_cleanly("encryption required "
3648 switch(info_level
) {
3649 case SMB_SET_CIFS_UNIX_INFO
:
3650 if (!lp_unix_extensions()) {
3651 DEBUG(2,("call_trans2setfsinfo: "
3652 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3653 "unix extensions off\n"));
3655 NT_STATUS_INVALID_LEVEL
);
3659 /* There should be 12 bytes of capabilities set. */
3660 if (total_data
< 12) {
3663 NT_STATUS_INVALID_PARAMETER
);
3666 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3667 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3668 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3669 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3670 /* Just print these values for now. */
3671 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3672 "major = %u, minor = %u cap_low = 0x%x, "
3674 (unsigned int)sconn
->
3675 smb1
.unix_info
.client_major
,
3676 (unsigned int)sconn
->
3677 smb1
.unix_info
.client_minor
,
3678 (unsigned int)sconn
->
3679 smb1
.unix_info
.client_cap_low
,
3680 (unsigned int)sconn
->
3681 smb1
.unix_info
.client_cap_high
));
3683 /* Here is where we must switch to posix pathname processing... */
3684 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3685 lp_set_posix_pathnames();
3686 mangle_change_to_posix();
3689 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3690 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3691 /* Client that knows how to do posix locks,
3692 * but not posix open/mkdir operations. Set a
3693 * default type for read/write checks. */
3695 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3700 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3703 size_t param_len
= 0;
3704 size_t data_len
= total_data
;
3706 if (!lp_unix_extensions()) {
3709 NT_STATUS_INVALID_LEVEL
);
3713 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3716 NT_STATUS_NOT_SUPPORTED
);
3720 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3721 DEBUG( 2,("call_trans2setfsinfo: "
3722 "request transport encryption disabled"
3723 "with 'fork echo handler = yes'\n"));
3726 NT_STATUS_NOT_SUPPORTED
);
3730 DEBUG( 4,("call_trans2setfsinfo: "
3731 "request transport encryption.\n"));
3733 status
= srv_request_encryption_setup(conn
,
3734 (unsigned char **)ppdata
,
3736 (unsigned char **)pparams
,
3739 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3740 !NT_STATUS_IS_OK(status
)) {
3741 reply_nterror(req
, status
);
3745 send_trans2_replies(conn
, req
,
3752 if (NT_STATUS_IS_OK(status
)) {
3753 /* Server-side transport
3754 * encryption is now *on*. */
3755 status
= srv_encryption_start(conn
);
3756 if (!NT_STATUS_IS_OK(status
)) {
3757 char *reason
= talloc_asprintf(talloc_tos(),
3758 "Failure in setting "
3759 "up encrypted transport: %s",
3761 exit_server_cleanly(reason
);
3767 case SMB_FS_QUOTA_INFORMATION
:
3769 files_struct
*fsp
= NULL
;
3770 SMB_NTQUOTA_STRUCT quotas
;
3772 ZERO_STRUCT(quotas
);
3775 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3776 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3777 lp_servicename(SNUM(conn
)),
3778 conn
->session_info
->unix_info
->unix_name
));
3779 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3783 /* note: normaly there're 48 bytes,
3784 * but we didn't use the last 6 bytes for now
3787 fsp
= file_fsp(req
, SVAL(params
,0));
3789 if (!check_fsp_ntquota_handle(conn
, req
,
3791 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3793 req
, NT_STATUS_INVALID_HANDLE
);
3797 if (total_data
< 42) {
3798 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3802 NT_STATUS_INVALID_PARAMETER
);
3806 /* unknown_1 24 NULL bytes in pdata*/
3808 /* the soft quotas 8 bytes (uint64_t)*/
3809 quotas
.softlim
= BVAL(pdata
,24);
3811 /* the hard quotas 8 bytes (uint64_t)*/
3812 quotas
.hardlim
= BVAL(pdata
,32);
3814 /* quota_flags 2 bytes **/
3815 quotas
.qflags
= SVAL(pdata
,40);
3817 /* unknown_2 6 NULL bytes follow*/
3819 /* now set the quotas */
3820 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3821 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3822 reply_nterror(req
, map_nt_error_from_unix(errno
));
3829 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3831 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3837 * sending this reply works fine,
3838 * but I'm not sure it's the same
3839 * like windows do...
3842 reply_outbuf(req
, 10, 0);
3845 #if defined(HAVE_POSIX_ACLS)
3846 /****************************************************************************
3847 Utility function to count the number of entries in a POSIX acl.
3848 ****************************************************************************/
3850 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3852 unsigned int ace_count
= 0;
3853 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3854 SMB_ACL_ENTRY_T entry
;
3856 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3858 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3859 entry_id
= SMB_ACL_NEXT_ENTRY
;
3866 /****************************************************************************
3867 Utility function to marshall a POSIX acl into wire format.
3868 ****************************************************************************/
3870 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3872 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3873 SMB_ACL_ENTRY_T entry
;
3875 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3876 SMB_ACL_TAG_T tagtype
;
3877 SMB_ACL_PERMSET_T permset
;
3878 unsigned char perms
= 0;
3879 unsigned int own_grp
;
3882 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3883 entry_id
= SMB_ACL_NEXT_ENTRY
;
3886 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3887 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3891 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3892 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3896 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3897 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3898 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3900 SCVAL(pdata
,1,perms
);
3903 case SMB_ACL_USER_OBJ
:
3904 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3905 own_grp
= (unsigned int)pst
->st_ex_uid
;
3906 SIVAL(pdata
,2,own_grp
);
3911 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3916 own_grp
= (unsigned int)*puid
;
3917 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3918 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3919 SIVAL(pdata
,2,own_grp
);
3923 case SMB_ACL_GROUP_OBJ
:
3924 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3925 own_grp
= (unsigned int)pst
->st_ex_gid
;
3926 SIVAL(pdata
,2,own_grp
);
3931 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3933 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3936 own_grp
= (unsigned int)*pgid
;
3937 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3938 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3939 SIVAL(pdata
,2,own_grp
);
3944 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3945 SIVAL(pdata
,2,0xFFFFFFFF);
3946 SIVAL(pdata
,6,0xFFFFFFFF);
3949 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3950 SIVAL(pdata
,2,0xFFFFFFFF);
3951 SIVAL(pdata
,6,0xFFFFFFFF);
3954 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3957 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3964 /****************************************************************************
3965 Store the FILE_UNIX_BASIC info.
3966 ****************************************************************************/
3968 static char *store_file_unix_basic(connection_struct
*conn
,
3971 const SMB_STRUCT_STAT
*psbuf
)
3973 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3975 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3976 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3978 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3981 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3984 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3985 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3986 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3989 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3993 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3997 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4000 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
4004 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
4008 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4011 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4015 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4022 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4023 * the chflags(2) (or equivalent) flags.
4025 * XXX: this really should be behind the VFS interface. To do this, we would
4026 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4027 * Each VFS module could then implement its own mapping as appropriate for the
4028 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4030 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4034 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4038 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4042 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4046 { UF_HIDDEN
, EXT_HIDDEN
},
4049 /* Do not remove. We need to guarantee that this array has at least one
4050 * entry to build on HP-UX.
4056 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4057 uint32
*smb_fflags
, uint32
*smb_fmask
)
4061 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4062 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4063 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4064 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4069 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4070 const uint32 smb_fflags
,
4071 const uint32 smb_fmask
,
4074 uint32 max_fmask
= 0;
4077 *stat_fflags
= psbuf
->st_ex_flags
;
4079 /* For each flags requested in smb_fmask, check the state of the
4080 * corresponding flag in smb_fflags and set or clear the matching
4084 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4085 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4086 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4087 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4088 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4090 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4095 /* If smb_fmask is asking to set any bits that are not supported by
4096 * our flag mappings, we should fail.
4098 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4106 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4107 * of file flags and birth (create) time.
4109 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4112 const SMB_STRUCT_STAT
*psbuf
)
4114 uint32 file_flags
= 0;
4115 uint32 flags_mask
= 0;
4117 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4119 /* Create (birth) time 64 bit */
4120 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4123 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4124 SIVAL(pdata
, 0, file_flags
); /* flags */
4125 SIVAL(pdata
, 4, flags_mask
); /* mask */
4131 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4132 const struct stream_struct
*streams
,
4134 unsigned int max_data_bytes
,
4135 unsigned int *data_size
)
4138 unsigned int ofs
= 0;
4140 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4141 unsigned int next_offset
;
4143 smb_ucs2_t
*namebuf
;
4145 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4146 streams
[i
].name
, &namelen
) ||
4149 return NT_STATUS_INVALID_PARAMETER
;
4153 * name_buf is now null-terminated, we need to marshall as not
4159 SIVAL(data
, ofs
+4, namelen
);
4160 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4161 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4162 memcpy(data
+ofs
+24, namebuf
, namelen
);
4163 TALLOC_FREE(namebuf
);
4165 next_offset
= ofs
+ 24 + namelen
;
4167 if (i
== num_streams
-1) {
4168 SIVAL(data
, ofs
, 0);
4171 unsigned int align
= ndr_align_size(next_offset
, 8);
4173 memset(data
+next_offset
, 0, align
);
4174 next_offset
+= align
;
4176 SIVAL(data
, ofs
, next_offset
- ofs
);
4185 return NT_STATUS_OK
;
4188 /****************************************************************************
4189 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4190 ****************************************************************************/
4192 static void call_trans2qpipeinfo(connection_struct
*conn
,
4193 struct smb_request
*req
,
4194 unsigned int tran_call
,
4195 char **pparams
, int total_params
,
4196 char **ppdata
, int total_data
,
4197 unsigned int max_data_bytes
)
4199 char *params
= *pparams
;
4200 char *pdata
= *ppdata
;
4201 unsigned int data_size
= 0;
4202 unsigned int param_size
= 2;
4207 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4211 if (total_params
< 4) {
4212 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4216 fsp
= file_fsp(req
, SVAL(params
,0));
4217 if (!fsp_is_np(fsp
)) {
4218 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4222 info_level
= SVAL(params
,2);
4224 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4225 if (*pparams
== NULL
) {
4226 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4231 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4232 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4233 if (*ppdata
== NULL
) {
4234 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4239 switch (info_level
) {
4240 case SMB_FILE_STANDARD_INFORMATION
:
4242 SOFF_T(pdata
,0,4096LL);
4249 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4253 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4259 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4260 TALLOC_CTX
*mem_ctx
,
4261 uint16_t info_level
,
4263 struct smb_filename
*smb_fname
,
4264 bool delete_pending
,
4265 struct timespec write_time_ts
,
4266 struct ea_list
*ea_list
,
4267 int lock_data_count
,
4270 unsigned int max_data_bytes
,
4272 unsigned int *pdata_size
)
4274 char *pdata
= *ppdata
;
4275 char *dstart
, *dend
;
4276 unsigned int data_size
;
4277 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4278 time_t create_time
, mtime
, atime
, c_time
;
4279 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4286 uint64_t file_size
= 0;
4288 uint64_t allocation_size
= 0;
4289 uint64_t file_index
= 0;
4290 uint32_t access_mask
= 0;
4292 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4293 return NT_STATUS_INVALID_LEVEL
;
4296 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4297 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4298 info_level
, max_data_bytes
));
4300 mode
= dos_mode(conn
, smb_fname
);
4301 nlink
= psbuf
->st_ex_nlink
;
4303 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4307 if ((nlink
> 0) && delete_pending
) {
4311 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4312 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4313 if (*ppdata
== NULL
) {
4314 return NT_STATUS_NO_MEMORY
;
4318 dend
= dstart
+ data_size
- 1;
4320 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4321 update_stat_ex_mtime(psbuf
, write_time_ts
);
4324 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4325 mtime_ts
= psbuf
->st_ex_mtime
;
4326 atime_ts
= psbuf
->st_ex_atime
;
4327 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4329 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4330 dos_filetime_timespec(&create_time_ts
);
4331 dos_filetime_timespec(&mtime_ts
);
4332 dos_filetime_timespec(&atime_ts
);
4333 dos_filetime_timespec(&ctime_ts
);
4336 create_time
= convert_timespec_to_time_t(create_time_ts
);
4337 mtime
= convert_timespec_to_time_t(mtime_ts
);
4338 atime
= convert_timespec_to_time_t(atime_ts
);
4339 c_time
= convert_timespec_to_time_t(ctime_ts
);
4341 p
= strrchr_m(smb_fname
->base_name
,'/');
4343 base_name
= smb_fname
->base_name
;
4347 /* NT expects the name to be in an exact form of the *full*
4348 filename. See the trans2 torture test */
4349 if (ISDOT(base_name
)) {
4350 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4352 return NT_STATUS_NO_MEMORY
;
4355 dos_fname
= talloc_asprintf(mem_ctx
,
4357 smb_fname
->base_name
);
4359 return NT_STATUS_NO_MEMORY
;
4361 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4362 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4363 smb_fname
->stream_name
);
4365 return NT_STATUS_NO_MEMORY
;
4369 string_replace(dos_fname
, '/', '\\');
4372 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4375 /* Do we have this path open ? */
4377 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4378 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4379 if (fsp1
&& fsp1
->initial_allocation_size
) {
4380 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4384 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4385 file_size
= get_file_size_stat(psbuf
);
4389 pos
= fsp
->fh
->position_information
;
4393 access_mask
= fsp
->access_mask
;
4395 /* GENERIC_EXECUTE mapping from Windows */
4396 access_mask
= 0x12019F;
4399 /* This should be an index number - looks like
4402 I think this causes us to fail the IFSKIT
4403 BasicFileInformationTest. -tpot */
4404 file_index
= get_FileIndex(conn
, psbuf
);
4406 switch (info_level
) {
4407 case SMB_INFO_STANDARD
:
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4410 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4411 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4412 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4413 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4414 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4415 SSVAL(pdata
,l1_attrFile
,mode
);
4418 case SMB_INFO_QUERY_EA_SIZE
:
4420 unsigned int ea_size
=
4421 estimate_ea_size(conn
, fsp
,
4422 smb_fname
->base_name
);
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4425 srv_put_dos_date2(pdata
,0,create_time
);
4426 srv_put_dos_date2(pdata
,4,atime
);
4427 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4428 SIVAL(pdata
,12,(uint32
)file_size
);
4429 SIVAL(pdata
,16,(uint32
)allocation_size
);
4430 SSVAL(pdata
,20,mode
);
4431 SIVAL(pdata
,22,ea_size
);
4435 case SMB_INFO_IS_NAME_VALID
:
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4438 /* os/2 needs this ? really ?*/
4439 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4441 /* This is only reached for qpathinfo */
4445 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4447 size_t total_ea_len
= 0;
4448 struct ea_list
*ea_file_list
= NULL
;
4450 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4453 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4454 smb_fname
->base_name
,
4456 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4458 if (!ea_list
|| (total_ea_len
> data_size
)) {
4460 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4464 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4468 case SMB_INFO_QUERY_ALL_EAS
:
4470 /* We have data_size bytes to put EA's into. */
4471 size_t total_ea_len
= 0;
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4475 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4476 smb_fname
->base_name
,
4478 if (!ea_list
|| (total_ea_len
> data_size
)) {
4480 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4484 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4488 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4490 /* This is FileFullEaInformation - 0xF which maps to
4491 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4493 /* We have data_size bytes to put EA's into. */
4494 size_t total_ea_len
= 0;
4495 struct ea_list
*ea_file_list
= NULL
;
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4499 /*TODO: add filtering and index handling */
4502 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4503 smb_fname
->base_name
,
4505 if (!ea_file_list
) {
4506 return NT_STATUS_NO_EAS_ON_FILE
;
4509 status
= fill_ea_chained_buffer(mem_ctx
,
4513 conn
, ea_file_list
);
4514 if (!NT_STATUS_IS_OK(status
)) {
4520 case SMB_FILE_BASIC_INFORMATION
:
4521 case SMB_QUERY_FILE_BASIC_INFO
:
4523 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4525 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4531 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4532 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4533 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4534 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4535 SIVAL(pdata
,32,mode
);
4537 DEBUG(5,("SMB_QFBI - "));
4538 DEBUG(5,("create: %s ", ctime(&create_time
)));
4539 DEBUG(5,("access: %s ", ctime(&atime
)));
4540 DEBUG(5,("write: %s ", ctime(&mtime
)));
4541 DEBUG(5,("change: %s ", ctime(&c_time
)));
4542 DEBUG(5,("mode: %x\n", mode
));
4545 case SMB_FILE_STANDARD_INFORMATION
:
4546 case SMB_QUERY_FILE_STANDARD_INFO
:
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4550 SOFF_T(pdata
,0,allocation_size
);
4551 SOFF_T(pdata
,8,file_size
);
4552 SIVAL(pdata
,16,nlink
);
4553 SCVAL(pdata
,20,delete_pending
?1:0);
4554 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4555 SSVAL(pdata
,22,0); /* Padding. */
4558 case SMB_FILE_EA_INFORMATION
:
4559 case SMB_QUERY_FILE_EA_INFO
:
4561 unsigned int ea_size
=
4562 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4565 SIVAL(pdata
,0,ea_size
);
4569 /* Get the 8.3 name - used if NT SMB was negotiated. */
4570 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4571 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4574 char mangled_name
[13];
4575 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4576 if (!name_to_8_3(base_name
,mangled_name
,
4577 True
,conn
->params
)) {
4578 return NT_STATUS_NO_MEMORY
;
4580 len
= srvstr_push(dstart
, flags2
,
4581 pdata
+4, mangled_name
,
4582 PTR_DIFF(dend
, pdata
+4),
4584 data_size
= 4 + len
;
4589 case SMB_QUERY_FILE_NAME_INFO
:
4593 this must be *exactly* right for ACLs on mapped drives to work
4595 len
= srvstr_push(dstart
, flags2
,
4597 PTR_DIFF(dend
, pdata
+4),
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4600 data_size
= 4 + len
;
4605 case SMB_FILE_ALLOCATION_INFORMATION
:
4606 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4609 SOFF_T(pdata
,0,allocation_size
);
4612 case SMB_FILE_END_OF_FILE_INFORMATION
:
4613 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4616 SOFF_T(pdata
,0,file_size
);
4619 case SMB_QUERY_FILE_ALL_INFO
:
4620 case SMB_FILE_ALL_INFORMATION
:
4623 unsigned int ea_size
=
4624 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4626 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4627 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4628 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4629 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4630 SIVAL(pdata
,32,mode
);
4631 SIVAL(pdata
,36,0); /* padding. */
4633 SOFF_T(pdata
,0,allocation_size
);
4634 SOFF_T(pdata
,8,file_size
);
4635 SIVAL(pdata
,16,nlink
);
4636 SCVAL(pdata
,20,delete_pending
);
4637 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4640 SIVAL(pdata
,0,ea_size
);
4641 pdata
+= 4; /* EA info */
4642 len
= srvstr_push(dstart
, flags2
,
4644 PTR_DIFF(dend
, pdata
+4),
4648 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4652 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4655 unsigned int ea_size
=
4656 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4658 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4659 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4660 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4661 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4662 SIVAL(pdata
, 0x20, mode
);
4663 SIVAL(pdata
, 0x24, 0); /* padding. */
4664 SBVAL(pdata
, 0x28, allocation_size
);
4665 SBVAL(pdata
, 0x30, file_size
);
4666 SIVAL(pdata
, 0x38, nlink
);
4667 SCVAL(pdata
, 0x3C, delete_pending
);
4668 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4669 SSVAL(pdata
, 0x3E, 0); /* padding */
4670 SBVAL(pdata
, 0x40, file_index
);
4671 SIVAL(pdata
, 0x48, ea_size
);
4672 SIVAL(pdata
, 0x4C, access_mask
);
4673 SBVAL(pdata
, 0x50, pos
);
4674 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4675 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4679 len
= srvstr_push(dstart
, flags2
,
4681 PTR_DIFF(dend
, pdata
+4),
4685 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4688 case SMB_FILE_INTERNAL_INFORMATION
:
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4691 SBVAL(pdata
, 0, file_index
);
4695 case SMB_FILE_ACCESS_INFORMATION
:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4697 SIVAL(pdata
, 0, access_mask
);
4701 case SMB_FILE_NAME_INFORMATION
:
4702 /* Pathname with leading '\'. */
4705 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4707 SIVAL(pdata
,0,byte_len
);
4708 data_size
= 4 + byte_len
;
4712 case SMB_FILE_DISPOSITION_INFORMATION
:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4715 SCVAL(pdata
,0,delete_pending
);
4718 case SMB_FILE_POSITION_INFORMATION
:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4721 SOFF_T(pdata
,0,pos
);
4724 case SMB_FILE_MODE_INFORMATION
:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4726 SIVAL(pdata
,0,mode
);
4730 case SMB_FILE_ALIGNMENT_INFORMATION
:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4732 SIVAL(pdata
,0,0); /* No alignment needed. */
4737 * NT4 server just returns "invalid query" to this - if we try
4738 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4741 /* The first statement above is false - verified using Thursby
4742 * client against NT4 -- gcolley.
4744 case SMB_QUERY_FILE_STREAM_INFO
:
4745 case SMB_FILE_STREAM_INFORMATION
: {
4746 unsigned int num_streams
= 0;
4747 struct stream_struct
*streams
= NULL
;
4749 DEBUG(10,("smbd_do_qfilepathinfo: "
4750 "SMB_FILE_STREAM_INFORMATION\n"));
4752 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4753 return NT_STATUS_INVALID_PARAMETER
;
4756 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4757 talloc_tos(), &num_streams
, &streams
);
4759 if (!NT_STATUS_IS_OK(status
)) {
4760 DEBUG(10, ("could not get stream info: %s\n",
4761 nt_errstr(status
)));
4765 status
= marshall_stream_info(num_streams
, streams
,
4766 pdata
, max_data_bytes
,
4769 if (!NT_STATUS_IS_OK(status
)) {
4770 DEBUG(10, ("marshall_stream_info failed: %s\n",
4771 nt_errstr(status
)));
4775 TALLOC_FREE(streams
);
4779 case SMB_QUERY_COMPRESSION_INFO
:
4780 case SMB_FILE_COMPRESSION_INFORMATION
:
4781 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4782 SOFF_T(pdata
,0,file_size
);
4783 SIVAL(pdata
,8,0); /* ??? */
4784 SIVAL(pdata
,12,0); /* ??? */
4788 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4790 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4791 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4792 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4793 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4794 SOFF_T(pdata
,32,allocation_size
);
4795 SOFF_T(pdata
,40,file_size
);
4796 SIVAL(pdata
,48,mode
);
4797 SIVAL(pdata
,52,0); /* ??? */
4801 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4803 SIVAL(pdata
,0,mode
);
4809 * CIFS UNIX Extensions.
4812 case SMB_QUERY_FILE_UNIX_BASIC
:
4814 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4815 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4817 DEBUG(4,("smbd_do_qfilepathinfo: "
4818 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4819 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4823 case SMB_QUERY_FILE_UNIX_INFO2
:
4825 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4826 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4830 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4832 for (i
=0; i
<100; i
++)
4833 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4839 case SMB_QUERY_FILE_UNIX_LINK
:
4842 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4845 return NT_STATUS_NO_MEMORY
;
4848 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4850 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4851 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4854 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4856 len
= SMB_VFS_READLINK(conn
,
4857 smb_fname
->base_name
,
4860 return map_nt_error_from_unix(errno
);
4863 len
= srvstr_push(dstart
, flags2
,
4865 PTR_DIFF(dend
, pdata
),
4868 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4873 #if defined(HAVE_POSIX_ACLS)
4874 case SMB_QUERY_POSIX_ACL
:
4876 SMB_ACL_T file_acl
= NULL
;
4877 SMB_ACL_T def_acl
= NULL
;
4878 uint16 num_file_acls
= 0;
4879 uint16 num_def_acls
= 0;
4881 if (fsp
&& fsp
->fh
->fd
!= -1) {
4882 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4885 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4886 smb_fname
->base_name
,
4887 SMB_ACL_TYPE_ACCESS
);
4890 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4891 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4892 "not implemented on "
4893 "filesystem containing %s\n",
4894 smb_fname
->base_name
));
4895 return NT_STATUS_NOT_IMPLEMENTED
;
4898 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4899 if (fsp
&& fsp
->is_directory
) {
4901 SMB_VFS_SYS_ACL_GET_FILE(
4903 fsp
->fsp_name
->base_name
,
4904 SMB_ACL_TYPE_DEFAULT
);
4907 SMB_VFS_SYS_ACL_GET_FILE(
4909 smb_fname
->base_name
,
4910 SMB_ACL_TYPE_DEFAULT
);
4912 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4915 num_file_acls
= count_acl_entries(conn
, file_acl
);
4916 num_def_acls
= count_acl_entries(conn
, def_acl
);
4918 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4919 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4921 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4922 SMB_POSIX_ACL_HEADER_SIZE
) ));
4924 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4927 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4929 return NT_STATUS_BUFFER_TOO_SMALL
;
4932 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4933 SSVAL(pdata
,2,num_file_acls
);
4934 SSVAL(pdata
,4,num_def_acls
);
4935 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4940 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4942 return NT_STATUS_INTERNAL_ERROR
;
4944 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4949 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4951 return NT_STATUS_INTERNAL_ERROR
;
4955 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4958 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4960 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4966 case SMB_QUERY_POSIX_LOCK
:
4971 enum brl_type lock_type
;
4973 /* We need an open file with a real fd for this. */
4974 if (!fsp
|| fsp
->fh
->fd
== -1) {
4975 return NT_STATUS_INVALID_LEVEL
;
4978 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4979 return NT_STATUS_INVALID_PARAMETER
;
4982 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4983 case POSIX_LOCK_TYPE_READ
:
4984 lock_type
= READ_LOCK
;
4986 case POSIX_LOCK_TYPE_WRITE
:
4987 lock_type
= WRITE_LOCK
;
4989 case POSIX_LOCK_TYPE_UNLOCK
:
4991 /* There's no point in asking for an unlock... */
4992 return NT_STATUS_INVALID_PARAMETER
;
4995 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4996 #if defined(HAVE_LONGLONG)
4997 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4998 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4999 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5000 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5001 #else /* HAVE_LONGLONG */
5002 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5003 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5004 #endif /* HAVE_LONGLONG */
5006 status
= query_lock(fsp
,
5013 if (ERROR_WAS_LOCK_DENIED(status
)) {
5014 /* Here we need to report who has it locked... */
5015 data_size
= POSIX_LOCK_DATA_SIZE
;
5017 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5018 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5019 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5020 #if defined(HAVE_LONGLONG)
5021 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5022 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5023 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5024 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5025 #else /* HAVE_LONGLONG */
5026 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5027 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5028 #endif /* HAVE_LONGLONG */
5030 } else if (NT_STATUS_IS_OK(status
)) {
5031 /* For success we just return a copy of what we sent
5032 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5033 data_size
= POSIX_LOCK_DATA_SIZE
;
5034 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5035 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5043 return NT_STATUS_INVALID_LEVEL
;
5046 *pdata_size
= data_size
;
5047 return NT_STATUS_OK
;
5050 /****************************************************************************
5051 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5052 file name or file id).
5053 ****************************************************************************/
5055 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5056 struct smb_request
*req
,
5057 unsigned int tran_call
,
5058 char **pparams
, int total_params
,
5059 char **ppdata
, int total_data
,
5060 unsigned int max_data_bytes
)
5062 char *params
= *pparams
;
5063 char *pdata
= *ppdata
;
5065 unsigned int data_size
= 0;
5066 unsigned int param_size
= 2;
5067 struct smb_filename
*smb_fname
= NULL
;
5068 bool delete_pending
= False
;
5069 struct timespec write_time_ts
;
5070 files_struct
*fsp
= NULL
;
5071 struct file_id fileid
;
5072 struct ea_list
*ea_list
= NULL
;
5073 int lock_data_count
= 0;
5074 char *lock_data
= NULL
;
5075 NTSTATUS status
= NT_STATUS_OK
;
5078 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5082 ZERO_STRUCT(write_time_ts
);
5084 if (tran_call
== TRANSACT2_QFILEINFO
) {
5085 if (total_params
< 4) {
5086 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5091 call_trans2qpipeinfo(conn
, req
, tran_call
,
5092 pparams
, total_params
,
5098 fsp
= file_fsp(req
, SVAL(params
,0));
5099 info_level
= SVAL(params
,2);
5101 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5103 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5104 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5108 /* Initial check for valid fsp ptr. */
5109 if (!check_fsp_open(conn
, req
, fsp
)) {
5113 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5115 if (!NT_STATUS_IS_OK(status
)) {
5116 reply_nterror(req
, status
);
5120 if(fsp
->fake_file_handle
) {
5122 * This is actually for the QUOTA_FAKE_FILE --metze
5125 /* We know this name is ok, it's already passed the checks. */
5127 } else if(fsp
->fh
->fd
== -1) {
5129 * This is actually a QFILEINFO on a directory
5130 * handle (returned from an NT SMB). NT5.0 seems
5131 * to do this call. JRA.
5134 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5135 /* Always do lstat for UNIX calls. */
5136 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5137 DEBUG(3,("call_trans2qfilepathinfo: "
5138 "SMB_VFS_LSTAT of %s failed "
5140 smb_fname_str_dbg(smb_fname
),
5143 map_nt_error_from_unix(errno
));
5146 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5147 DEBUG(3,("call_trans2qfilepathinfo: "
5148 "SMB_VFS_STAT of %s failed (%s)\n",
5149 smb_fname_str_dbg(smb_fname
),
5152 map_nt_error_from_unix(errno
));
5156 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5157 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5160 * Original code - this is an open file.
5162 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5163 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5164 fsp
->fnum
, strerror(errno
)));
5166 map_nt_error_from_unix(errno
));
5169 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5170 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5176 uint32_t ucf_flags
= 0;
5179 if (total_params
< 7) {
5180 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5184 info_level
= SVAL(params
,0);
5186 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5188 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5189 if (!lp_unix_extensions()) {
5190 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5193 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5194 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5195 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5196 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5200 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5202 STR_TERMINATE
, &status
);
5203 if (!NT_STATUS_IS_OK(status
)) {
5204 reply_nterror(req
, status
);
5208 status
= filename_convert(req
,
5210 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5215 if (!NT_STATUS_IS_OK(status
)) {
5216 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5217 reply_botherror(req
,
5218 NT_STATUS_PATH_NOT_COVERED
,
5219 ERRSRV
, ERRbadpath
);
5222 reply_nterror(req
, status
);
5226 /* If this is a stream, check if there is a delete_pending. */
5227 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5228 && is_ntfs_stream_smb_fname(smb_fname
)) {
5229 struct smb_filename
*smb_fname_base
= NULL
;
5231 /* Create an smb_filename with stream_name == NULL. */
5233 create_synthetic_smb_fname(talloc_tos(),
5234 smb_fname
->base_name
,
5237 if (!NT_STATUS_IS_OK(status
)) {
5238 reply_nterror(req
, status
);
5242 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5243 /* Always do lstat for UNIX calls. */
5244 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5245 DEBUG(3,("call_trans2qfilepathinfo: "
5246 "SMB_VFS_LSTAT of %s failed "
5248 smb_fname_str_dbg(smb_fname_base
),
5250 TALLOC_FREE(smb_fname_base
);
5252 map_nt_error_from_unix(errno
));
5256 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5257 DEBUG(3,("call_trans2qfilepathinfo: "
5258 "fileinfo of %s failed "
5260 smb_fname_str_dbg(smb_fname_base
),
5262 TALLOC_FREE(smb_fname_base
);
5264 map_nt_error_from_unix(errno
));
5269 status
= file_name_hash(conn
,
5270 smb_fname_str_dbg(smb_fname_base
),
5272 if (!NT_STATUS_IS_OK(status
)) {
5273 TALLOC_FREE(smb_fname_base
);
5274 reply_nterror(req
, status
);
5278 fileid
= vfs_file_id_from_sbuf(conn
,
5279 &smb_fname_base
->st
);
5280 TALLOC_FREE(smb_fname_base
);
5281 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5282 if (delete_pending
) {
5283 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5288 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5289 /* Always do lstat for UNIX calls. */
5290 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5291 DEBUG(3,("call_trans2qfilepathinfo: "
5292 "SMB_VFS_LSTAT of %s failed (%s)\n",
5293 smb_fname_str_dbg(smb_fname
),
5296 map_nt_error_from_unix(errno
));
5301 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5302 DEBUG(3,("call_trans2qfilepathinfo: "
5303 "SMB_VFS_STAT of %s failed (%s)\n",
5304 smb_fname_str_dbg(smb_fname
),
5307 map_nt_error_from_unix(errno
));
5312 status
= file_name_hash(conn
,
5313 smb_fname_str_dbg(smb_fname
),
5315 if (!NT_STATUS_IS_OK(status
)) {
5316 reply_nterror(req
, status
);
5320 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5321 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5322 if (delete_pending
) {
5323 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5328 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5329 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5330 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5332 /* Pull out any data sent here before we realloc. */
5333 switch (info_level
) {
5334 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5336 /* Pull any EA list from the data portion. */
5339 if (total_data
< 4) {
5341 req
, NT_STATUS_INVALID_PARAMETER
);
5344 ea_size
= IVAL(pdata
,0);
5346 if (total_data
> 0 && ea_size
!= total_data
) {
5347 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5348 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5350 req
, NT_STATUS_INVALID_PARAMETER
);
5354 if (!lp_ea_support(SNUM(conn
))) {
5355 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5359 /* Pull out the list of names. */
5360 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5363 req
, NT_STATUS_INVALID_PARAMETER
);
5369 case SMB_QUERY_POSIX_LOCK
:
5371 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5372 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5376 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5378 req
, NT_STATUS_INVALID_PARAMETER
);
5382 /* Copy the lock range data. */
5383 lock_data
= (char *)talloc_memdup(
5384 req
, pdata
, total_data
);
5386 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5389 lock_data_count
= total_data
;
5395 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5396 if (*pparams
== NULL
) {
5397 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5404 * draft-leach-cifs-v1-spec-02.txt
5405 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5408 * The requested information is placed in the Data portion of the
5409 * transaction response. For the information levels greater than 0x100,
5410 * the transaction response has 1 parameter word which should be
5411 * ignored by the client.
5413 * However Windows only follows this rule for the IS_NAME_VALID call.
5415 switch (info_level
) {
5416 case SMB_INFO_IS_NAME_VALID
:
5421 if ((info_level
& 0xFF00) == 0xFF00) {
5423 * We use levels that start with 0xFF00
5424 * internally to represent SMB2 specific levels
5426 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5430 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5432 delete_pending
, write_time_ts
,
5434 lock_data_count
, lock_data
,
5435 req
->flags2
, max_data_bytes
,
5436 ppdata
, &data_size
);
5437 if (!NT_STATUS_IS_OK(status
)) {
5438 reply_nterror(req
, status
);
5442 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5448 /****************************************************************************
5449 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5451 ****************************************************************************/
5453 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5454 connection_struct
*conn
,
5455 struct smb_request
*req
,
5456 bool overwrite_if_exists
,
5457 const struct smb_filename
*smb_fname_old
,
5458 struct smb_filename
*smb_fname_new
)
5460 NTSTATUS status
= NT_STATUS_OK
;
5462 /* source must already exist. */
5463 if (!VALID_STAT(smb_fname_old
->st
)) {
5464 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5467 if (VALID_STAT(smb_fname_new
->st
)) {
5468 if (overwrite_if_exists
) {
5469 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5470 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5472 status
= unlink_internals(conn
,
5474 FILE_ATTRIBUTE_NORMAL
,
5477 if (!NT_STATUS_IS_OK(status
)) {
5481 /* Disallow if newname already exists. */
5482 return NT_STATUS_OBJECT_NAME_COLLISION
;
5486 /* No links from a directory. */
5487 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5488 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5491 /* Setting a hardlink to/from a stream isn't currently supported. */
5492 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5493 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5494 return NT_STATUS_INVALID_PARAMETER
;
5497 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5498 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5500 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5501 smb_fname_new
->base_name
) != 0) {
5502 status
= map_nt_error_from_unix(errno
);
5503 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5504 nt_errstr(status
), smb_fname_old
->base_name
,
5505 smb_fname_new
->base_name
));
5510 /****************************************************************************
5511 Deal with setting the time from any of the setfilepathinfo functions.
5512 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5513 calling this function.
5514 ****************************************************************************/
5516 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5518 const struct smb_filename
*smb_fname
,
5519 struct smb_file_time
*ft
,
5520 bool setting_write_time
)
5522 struct smb_filename smb_fname_base
;
5524 FILE_NOTIFY_CHANGE_LAST_ACCESS
5525 |FILE_NOTIFY_CHANGE_LAST_WRITE
5526 |FILE_NOTIFY_CHANGE_CREATION
;
5528 if (!VALID_STAT(smb_fname
->st
)) {
5529 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5532 /* get some defaults (no modifications) if any info is zero or -1. */
5533 if (null_timespec(ft
->create_time
)) {
5534 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5537 if (null_timespec(ft
->atime
)) {
5538 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5541 if (null_timespec(ft
->mtime
)) {
5542 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5545 if (!setting_write_time
) {
5546 /* ft->mtime comes from change time, not write time. */
5547 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5550 /* Ensure the resolution is the correct for
5551 * what we can store on this filesystem. */
5553 round_timespec(conn
->ts_res
, &ft
->create_time
);
5554 round_timespec(conn
->ts_res
, &ft
->ctime
);
5555 round_timespec(conn
->ts_res
, &ft
->atime
);
5556 round_timespec(conn
->ts_res
, &ft
->mtime
);
5558 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5560 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5561 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5562 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5563 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5564 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5565 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5567 if (setting_write_time
) {
5569 * This was a Windows setfileinfo on an open file.
5570 * NT does this a lot. We also need to
5571 * set the time here, as it can be read by
5572 * FindFirst/FindNext and with the patch for bug #2045
5573 * in smbd/fileio.c it ensures that this timestamp is
5574 * kept sticky even after a write. We save the request
5575 * away and will set it on file close and after a write. JRA.
5578 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5579 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5582 if (fsp
->base_fsp
) {
5583 set_sticky_write_time_fsp(fsp
->base_fsp
,
5586 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5589 set_sticky_write_time_path(
5590 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5595 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5597 /* Always call ntimes on the base, even if a stream was passed in. */
5598 smb_fname_base
= *smb_fname
;
5599 smb_fname_base
.stream_name
= NULL
;
5601 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5602 return map_nt_error_from_unix(errno
);
5605 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5606 smb_fname
->base_name
);
5607 return NT_STATUS_OK
;
5610 /****************************************************************************
5611 Deal with setting the dosmode from any of the setfilepathinfo functions.
5612 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5613 done before calling this function.
5614 ****************************************************************************/
5616 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5617 const struct smb_filename
*smb_fname
,
5620 struct smb_filename
*smb_fname_base
= NULL
;
5623 if (!VALID_STAT(smb_fname
->st
)) {
5624 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5627 /* Always operate on the base_name, even if a stream was passed in. */
5628 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5629 NULL
, &smb_fname
->st
,
5631 if (!NT_STATUS_IS_OK(status
)) {
5636 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5637 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5639 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5643 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5645 /* check the mode isn't different, before changing it */
5646 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5647 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5648 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5649 (unsigned int)dosmode
));
5651 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5653 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5655 smb_fname_str_dbg(smb_fname_base
),
5657 status
= map_nt_error_from_unix(errno
);
5661 status
= NT_STATUS_OK
;
5663 TALLOC_FREE(smb_fname_base
);
5667 /****************************************************************************
5668 Deal with setting the size from any of the setfilepathinfo functions.
5669 ****************************************************************************/
5671 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5672 struct smb_request
*req
,
5674 const struct smb_filename
*smb_fname
,
5675 const SMB_STRUCT_STAT
*psbuf
,
5677 bool fail_after_createfile
)
5679 NTSTATUS status
= NT_STATUS_OK
;
5680 struct smb_filename
*smb_fname_tmp
= NULL
;
5681 files_struct
*new_fsp
= NULL
;
5683 if (!VALID_STAT(*psbuf
)) {
5684 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5687 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5689 if (size
== get_file_size_stat(psbuf
)) {
5690 return NT_STATUS_OK
;
5693 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5694 smb_fname_str_dbg(smb_fname
), (double)size
));
5696 if (fsp
&& fsp
->fh
->fd
!= -1) {
5697 /* Handle based call. */
5698 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5699 return NT_STATUS_ACCESS_DENIED
;
5702 if (vfs_set_filelen(fsp
, size
) == -1) {
5703 return map_nt_error_from_unix(errno
);
5705 trigger_write_time_update_immediate(fsp
);
5706 return NT_STATUS_OK
;
5709 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5710 if (!NT_STATUS_IS_OK(status
)) {
5714 smb_fname_tmp
->st
= *psbuf
;
5716 status
= SMB_VFS_CREATE_FILE(
5719 0, /* root_dir_fid */
5720 smb_fname_tmp
, /* fname */
5721 FILE_WRITE_DATA
, /* access_mask */
5722 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5724 FILE_OPEN
, /* create_disposition*/
5725 0, /* create_options */
5726 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5727 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5728 0, /* allocation_size */
5729 0, /* private_flags */
5732 &new_fsp
, /* result */
5735 TALLOC_FREE(smb_fname_tmp
);
5737 if (!NT_STATUS_IS_OK(status
)) {
5738 /* NB. We check for open_was_deferred in the caller. */
5742 /* See RAW-SFILEINFO-END-OF-FILE */
5743 if (fail_after_createfile
) {
5744 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5745 return NT_STATUS_INVALID_LEVEL
;
5748 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5749 status
= map_nt_error_from_unix(errno
);
5750 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5754 trigger_write_time_update_immediate(new_fsp
);
5755 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5756 return NT_STATUS_OK
;
5759 /****************************************************************************
5760 Deal with SMB_INFO_SET_EA.
5761 ****************************************************************************/
5763 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5767 const struct smb_filename
*smb_fname
)
5769 struct ea_list
*ea_list
= NULL
;
5770 TALLOC_CTX
*ctx
= NULL
;
5771 NTSTATUS status
= NT_STATUS_OK
;
5773 if (total_data
< 10) {
5775 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5776 length. They seem to have no effect. Bug #3212. JRA */
5778 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5779 /* We're done. We only get EA info in this call. */
5780 return NT_STATUS_OK
;
5783 return NT_STATUS_INVALID_PARAMETER
;
5786 if (IVAL(pdata
,0) > total_data
) {
5787 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5788 IVAL(pdata
,0), (unsigned int)total_data
));
5789 return NT_STATUS_INVALID_PARAMETER
;
5793 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5795 return NT_STATUS_INVALID_PARAMETER
;
5798 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5803 /****************************************************************************
5804 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5805 ****************************************************************************/
5807 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5812 struct ea_list
*ea_list
= NULL
;
5816 return NT_STATUS_INVALID_HANDLE
;
5819 if (!lp_ea_support(SNUM(conn
))) {
5820 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5821 "EA's not supported.\n",
5822 (unsigned int)total_data
));
5823 return NT_STATUS_EAS_NOT_SUPPORTED
;
5826 if (total_data
< 10) {
5827 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5829 (unsigned int)total_data
));
5830 return NT_STATUS_INVALID_PARAMETER
;
5833 ea_list
= read_nttrans_ea_list(talloc_tos(),
5838 return NT_STATUS_INVALID_PARAMETER
;
5841 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5843 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5844 smb_fname_str_dbg(fsp
->fsp_name
),
5845 nt_errstr(status
) ));
5851 /****************************************************************************
5852 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5853 ****************************************************************************/
5855 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5859 struct smb_filename
*smb_fname
)
5861 NTSTATUS status
= NT_STATUS_OK
;
5862 bool delete_on_close
;
5865 if (total_data
< 1) {
5866 return NT_STATUS_INVALID_PARAMETER
;
5870 return NT_STATUS_INVALID_HANDLE
;
5873 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5874 dosmode
= dos_mode(conn
, smb_fname
);
5876 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5877 "delete_on_close = %u\n",
5878 smb_fname_str_dbg(smb_fname
),
5879 (unsigned int)dosmode
,
5880 (unsigned int)delete_on_close
));
5882 if (delete_on_close
) {
5883 status
= can_set_delete_on_close(fsp
, dosmode
);
5884 if (!NT_STATUS_IS_OK(status
)) {
5889 /* The set is across all open files on this dev/inode pair. */
5890 if (!set_delete_on_close(fsp
, delete_on_close
,
5891 conn
->session_info
->security_token
,
5892 conn
->session_info
->unix_token
)) {
5893 return NT_STATUS_ACCESS_DENIED
;
5895 return NT_STATUS_OK
;
5898 /****************************************************************************
5899 Deal with SMB_FILE_POSITION_INFORMATION.
5900 ****************************************************************************/
5902 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5907 uint64_t position_information
;
5909 if (total_data
< 8) {
5910 return NT_STATUS_INVALID_PARAMETER
;
5914 /* Ignore on pathname based set. */
5915 return NT_STATUS_OK
;
5918 position_information
= (uint64_t)IVAL(pdata
,0);
5919 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5921 DEBUG(10,("smb_file_position_information: Set file position "
5922 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5923 (double)position_information
));
5924 fsp
->fh
->position_information
= position_information
;
5925 return NT_STATUS_OK
;
5928 /****************************************************************************
5929 Deal with SMB_FILE_MODE_INFORMATION.
5930 ****************************************************************************/
5932 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5938 if (total_data
< 4) {
5939 return NT_STATUS_INVALID_PARAMETER
;
5941 mode
= IVAL(pdata
,0);
5942 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5943 return NT_STATUS_INVALID_PARAMETER
;
5945 return NT_STATUS_OK
;
5948 /****************************************************************************
5949 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5950 ****************************************************************************/
5952 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5953 struct smb_request
*req
,
5956 const struct smb_filename
*smb_fname
)
5958 char *link_target
= NULL
;
5959 const char *newname
= smb_fname
->base_name
;
5960 TALLOC_CTX
*ctx
= talloc_tos();
5962 /* Set a symbolic link. */
5963 /* Don't allow this if follow links is false. */
5965 if (total_data
== 0) {
5966 return NT_STATUS_INVALID_PARAMETER
;
5969 if (!lp_symlinks(SNUM(conn
))) {
5970 return NT_STATUS_ACCESS_DENIED
;
5973 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5974 total_data
, STR_TERMINATE
);
5977 return NT_STATUS_INVALID_PARAMETER
;
5980 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5981 newname
, link_target
));
5983 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5984 return map_nt_error_from_unix(errno
);
5987 return NT_STATUS_OK
;
5990 /****************************************************************************
5991 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5992 ****************************************************************************/
5994 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5995 struct smb_request
*req
,
5996 const char *pdata
, int total_data
,
5997 struct smb_filename
*smb_fname_new
)
5999 char *oldname
= NULL
;
6000 struct smb_filename
*smb_fname_old
= NULL
;
6001 TALLOC_CTX
*ctx
= talloc_tos();
6002 NTSTATUS status
= NT_STATUS_OK
;
6004 /* Set a hard link. */
6005 if (total_data
== 0) {
6006 return NT_STATUS_INVALID_PARAMETER
;
6009 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6010 total_data
, STR_TERMINATE
, &status
);
6011 if (!NT_STATUS_IS_OK(status
)) {
6015 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6016 smb_fname_str_dbg(smb_fname_new
), oldname
));
6018 status
= filename_convert(ctx
,
6020 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6025 if (!NT_STATUS_IS_OK(status
)) {
6029 return hardlink_internals(ctx
, conn
, req
, false,
6030 smb_fname_old
, smb_fname_new
);
6033 /****************************************************************************
6034 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6035 ****************************************************************************/
6037 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6038 struct smb_request
*req
,
6042 struct smb_filename
*smb_fname_src
)
6046 char *newname
= NULL
;
6047 struct smb_filename
*smb_fname_dst
= NULL
;
6048 NTSTATUS status
= NT_STATUS_OK
;
6049 TALLOC_CTX
*ctx
= talloc_tos();
6052 return NT_STATUS_INVALID_HANDLE
;
6055 if (total_data
< 20) {
6056 return NT_STATUS_INVALID_PARAMETER
;
6059 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6060 len
= IVAL(pdata
,16);
6062 if (len
> (total_data
- 20) || (len
== 0)) {
6063 return NT_STATUS_INVALID_PARAMETER
;
6066 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6067 &pdata
[20], len
, STR_TERMINATE
,
6069 if (!NT_STATUS_IS_OK(status
)) {
6073 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6076 status
= filename_convert(ctx
,
6078 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6083 if (!NT_STATUS_IS_OK(status
)) {
6087 if (fsp
->base_fsp
) {
6088 /* newname must be a stream name. */
6089 if (newname
[0] != ':') {
6090 return NT_STATUS_NOT_SUPPORTED
;
6093 /* Create an smb_fname to call rename_internals_fsp() with. */
6094 status
= create_synthetic_smb_fname(talloc_tos(),
6095 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6097 if (!NT_STATUS_IS_OK(status
)) {
6102 * Set the original last component, since
6103 * rename_internals_fsp() requires it.
6105 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6107 if (smb_fname_dst
->original_lcomp
== NULL
) {
6108 status
= NT_STATUS_NO_MEMORY
;
6114 DEBUG(10,("smb2_file_rename_information: "
6115 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6116 fsp
->fnum
, fsp_str_dbg(fsp
),
6117 smb_fname_str_dbg(smb_fname_dst
)));
6118 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6119 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6123 TALLOC_FREE(smb_fname_dst
);
6127 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6128 struct smb_request
*req
,
6132 struct smb_filename
*smb_fname_src
)
6136 char *newname
= NULL
;
6137 struct smb_filename
*smb_fname_dst
= NULL
;
6138 NTSTATUS status
= NT_STATUS_OK
;
6139 TALLOC_CTX
*ctx
= talloc_tos();
6142 return NT_STATUS_INVALID_HANDLE
;
6145 if (total_data
< 20) {
6146 return NT_STATUS_INVALID_PARAMETER
;
6149 overwrite
= (CVAL(pdata
,0) ? true : false);
6150 len
= IVAL(pdata
,16);
6152 if (len
> (total_data
- 20) || (len
== 0)) {
6153 return NT_STATUS_INVALID_PARAMETER
;
6156 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6157 &pdata
[20], len
, STR_TERMINATE
,
6159 if (!NT_STATUS_IS_OK(status
)) {
6163 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6166 status
= filename_convert(ctx
,
6168 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6173 if (!NT_STATUS_IS_OK(status
)) {
6177 if (fsp
->base_fsp
) {
6178 /* No stream names. */
6179 return NT_STATUS_NOT_SUPPORTED
;
6182 DEBUG(10,("smb_file_link_information: "
6183 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6184 fsp
->fnum
, fsp_str_dbg(fsp
),
6185 smb_fname_str_dbg(smb_fname_dst
)));
6186 status
= hardlink_internals(ctx
,
6193 TALLOC_FREE(smb_fname_dst
);
6197 /****************************************************************************
6198 Deal with SMB_FILE_RENAME_INFORMATION.
6199 ****************************************************************************/
6201 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6202 struct smb_request
*req
,
6206 struct smb_filename
*smb_fname_src
)
6211 char *newname
= NULL
;
6212 struct smb_filename
*smb_fname_dst
= NULL
;
6213 bool dest_has_wcard
= False
;
6214 NTSTATUS status
= NT_STATUS_OK
;
6216 TALLOC_CTX
*ctx
= talloc_tos();
6218 if (total_data
< 13) {
6219 return NT_STATUS_INVALID_PARAMETER
;
6222 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6223 root_fid
= IVAL(pdata
,4);
6224 len
= IVAL(pdata
,8);
6226 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6227 return NT_STATUS_INVALID_PARAMETER
;
6230 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6233 if (!NT_STATUS_IS_OK(status
)) {
6237 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6240 status
= resolve_dfspath_wcard(ctx
, conn
,
6241 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6246 if (!NT_STATUS_IS_OK(status
)) {
6250 /* Check the new name has no '/' characters. */
6251 if (strchr_m(newname
, '/')) {
6252 return NT_STATUS_NOT_SUPPORTED
;
6255 if (fsp
&& fsp
->base_fsp
) {
6256 /* newname must be a stream name. */
6257 if (newname
[0] != ':') {
6258 return NT_STATUS_NOT_SUPPORTED
;
6261 /* Create an smb_fname to call rename_internals_fsp() with. */
6262 status
= create_synthetic_smb_fname(talloc_tos(),
6263 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6265 if (!NT_STATUS_IS_OK(status
)) {
6270 * Set the original last component, since
6271 * rename_internals_fsp() requires it.
6273 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6275 if (smb_fname_dst
->original_lcomp
== NULL
) {
6276 status
= NT_STATUS_NO_MEMORY
;
6282 * Build up an smb_fname_dst based on the filename passed in.
6283 * We basically just strip off the last component, and put on
6284 * the newname instead.
6286 char *base_name
= NULL
;
6288 /* newname must *not* be a stream name. */
6289 if (newname
[0] == ':') {
6290 return NT_STATUS_NOT_SUPPORTED
;
6294 * Strip off the last component (filename) of the path passed
6297 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6299 return NT_STATUS_NO_MEMORY
;
6301 p
= strrchr_m(base_name
, '/');
6305 base_name
= talloc_strdup(ctx
, "");
6307 return NT_STATUS_NO_MEMORY
;
6310 /* Append the new name. */
6311 base_name
= talloc_asprintf_append(base_name
,
6315 return NT_STATUS_NO_MEMORY
;
6318 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6321 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6324 /* If an error we expect this to be
6325 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6327 if (!NT_STATUS_IS_OK(status
)) {
6328 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6332 /* Create an smb_fname to call rename_internals_fsp() */
6333 status
= create_synthetic_smb_fname(ctx
,
6337 if (!NT_STATUS_IS_OK(status
)) {
6344 DEBUG(10,("smb_file_rename_information: "
6345 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6346 fsp
->fnum
, fsp_str_dbg(fsp
),
6347 smb_fname_str_dbg(smb_fname_dst
)));
6348 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6351 DEBUG(10,("smb_file_rename_information: "
6352 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6353 smb_fname_str_dbg(smb_fname_src
),
6354 smb_fname_str_dbg(smb_fname_dst
)));
6355 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6356 smb_fname_dst
, 0, overwrite
, false,
6358 FILE_WRITE_ATTRIBUTES
);
6361 TALLOC_FREE(smb_fname_dst
);
6365 /****************************************************************************
6366 Deal with SMB_SET_POSIX_ACL.
6367 ****************************************************************************/
6369 #if defined(HAVE_POSIX_ACLS)
6370 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6374 const struct smb_filename
*smb_fname
)
6376 uint16 posix_acl_version
;
6377 uint16 num_file_acls
;
6378 uint16 num_def_acls
;
6379 bool valid_file_acls
= True
;
6380 bool valid_def_acls
= True
;
6382 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6383 return NT_STATUS_INVALID_PARAMETER
;
6385 posix_acl_version
= SVAL(pdata
,0);
6386 num_file_acls
= SVAL(pdata
,2);
6387 num_def_acls
= SVAL(pdata
,4);
6389 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6390 valid_file_acls
= False
;
6394 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6395 valid_def_acls
= False
;
6399 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6400 return NT_STATUS_INVALID_PARAMETER
;
6403 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6404 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6405 return NT_STATUS_INVALID_PARAMETER
;
6408 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6409 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6410 (unsigned int)num_file_acls
,
6411 (unsigned int)num_def_acls
));
6413 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6414 smb_fname
->base_name
, num_file_acls
,
6415 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6416 return map_nt_error_from_unix(errno
);
6419 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6420 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6421 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6422 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6423 return map_nt_error_from_unix(errno
);
6425 return NT_STATUS_OK
;
6429 /****************************************************************************
6430 Deal with SMB_SET_POSIX_LOCK.
6431 ****************************************************************************/
6433 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6434 struct smb_request
*req
,
6442 bool blocking_lock
= False
;
6443 enum brl_type lock_type
;
6445 NTSTATUS status
= NT_STATUS_OK
;
6447 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6448 return NT_STATUS_INVALID_HANDLE
;
6451 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6452 return NT_STATUS_INVALID_PARAMETER
;
6455 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6456 case POSIX_LOCK_TYPE_READ
:
6457 lock_type
= READ_LOCK
;
6459 case POSIX_LOCK_TYPE_WRITE
:
6460 /* Return the right POSIX-mappable error code for files opened read-only. */
6461 if (!fsp
->can_write
) {
6462 return NT_STATUS_INVALID_HANDLE
;
6464 lock_type
= WRITE_LOCK
;
6466 case POSIX_LOCK_TYPE_UNLOCK
:
6467 lock_type
= UNLOCK_LOCK
;
6470 return NT_STATUS_INVALID_PARAMETER
;
6473 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6474 blocking_lock
= False
;
6475 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6476 blocking_lock
= True
;
6478 return NT_STATUS_INVALID_PARAMETER
;
6481 if (!lp_blocking_locks(SNUM(conn
))) {
6482 blocking_lock
= False
;
6485 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6486 #if defined(HAVE_LONGLONG)
6487 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6488 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6489 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6490 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6491 #else /* HAVE_LONGLONG */
6492 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6493 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6494 #endif /* HAVE_LONGLONG */
6496 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6497 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6499 (unsigned int)lock_type
,
6500 (unsigned long long)smblctx
,
6504 if (lock_type
== UNLOCK_LOCK
) {
6505 status
= do_unlock(req
->sconn
->msg_ctx
,
6512 uint64_t block_smblctx
;
6514 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6526 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6528 * A blocking lock was requested. Package up
6529 * this smb into a queued request and push it
6530 * onto the blocking lock queue.
6532 if(push_blocking_lock_request(br_lck
,
6535 -1, /* infinite timeout. */
6543 TALLOC_FREE(br_lck
);
6547 TALLOC_FREE(br_lck
);
6553 /****************************************************************************
6554 Deal with SMB_SET_FILE_BASIC_INFO.
6555 ****************************************************************************/
6557 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6561 const struct smb_filename
*smb_fname
)
6563 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6564 struct smb_file_time ft
;
6566 NTSTATUS status
= NT_STATUS_OK
;
6570 if (total_data
< 36) {
6571 return NT_STATUS_INVALID_PARAMETER
;
6574 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6575 if (!NT_STATUS_IS_OK(status
)) {
6579 /* Set the attributes */
6580 dosmode
= IVAL(pdata
,32);
6581 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6582 if (!NT_STATUS_IS_OK(status
)) {
6587 ft
.create_time
= interpret_long_date(pdata
);
6590 ft
.atime
= interpret_long_date(pdata
+8);
6593 ft
.mtime
= interpret_long_date(pdata
+16);
6596 ft
.ctime
= interpret_long_date(pdata
+24);
6598 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6599 smb_fname_str_dbg(smb_fname
)));
6601 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6605 /****************************************************************************
6606 Deal with SMB_INFO_STANDARD.
6607 ****************************************************************************/
6609 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6613 const struct smb_filename
*smb_fname
)
6616 struct smb_file_time ft
;
6620 if (total_data
< 12) {
6621 return NT_STATUS_INVALID_PARAMETER
;
6625 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6627 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6629 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6631 DEBUG(10,("smb_set_info_standard: file %s\n",
6632 smb_fname_str_dbg(smb_fname
)));
6634 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6635 if (!NT_STATUS_IS_OK(status
)) {
6639 return smb_set_file_time(conn
,
6646 /****************************************************************************
6647 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6648 ****************************************************************************/
6650 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6651 struct smb_request
*req
,
6655 struct smb_filename
*smb_fname
)
6657 uint64_t allocation_size
= 0;
6658 NTSTATUS status
= NT_STATUS_OK
;
6659 files_struct
*new_fsp
= NULL
;
6661 if (!VALID_STAT(smb_fname
->st
)) {
6662 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6665 if (total_data
< 8) {
6666 return NT_STATUS_INVALID_PARAMETER
;
6669 allocation_size
= (uint64_t)IVAL(pdata
,0);
6670 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6671 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6672 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6673 (double)allocation_size
));
6675 if (allocation_size
) {
6676 allocation_size
= smb_roundup(conn
, allocation_size
);
6679 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6680 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6681 (double)allocation_size
));
6683 if (fsp
&& fsp
->fh
->fd
!= -1) {
6684 /* Open file handle. */
6685 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6686 return NT_STATUS_ACCESS_DENIED
;
6689 /* Only change if needed. */
6690 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6691 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6692 return map_nt_error_from_unix(errno
);
6695 /* But always update the time. */
6697 * This is equivalent to a write. Ensure it's seen immediately
6698 * if there are no pending writes.
6700 trigger_write_time_update_immediate(fsp
);
6701 return NT_STATUS_OK
;
6704 /* Pathname or stat or directory file. */
6705 status
= SMB_VFS_CREATE_FILE(
6708 0, /* root_dir_fid */
6709 smb_fname
, /* fname */
6710 FILE_WRITE_DATA
, /* access_mask */
6711 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6713 FILE_OPEN
, /* create_disposition*/
6714 0, /* create_options */
6715 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6716 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6717 0, /* allocation_size */
6718 0, /* private_flags */
6721 &new_fsp
, /* result */
6724 if (!NT_STATUS_IS_OK(status
)) {
6725 /* NB. We check for open_was_deferred in the caller. */
6729 /* Only change if needed. */
6730 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6731 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6732 status
= map_nt_error_from_unix(errno
);
6733 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6738 /* Changing the allocation size should set the last mod time. */
6740 * This is equivalent to a write. Ensure it's seen immediately
6741 * if there are no pending writes.
6743 trigger_write_time_update_immediate(new_fsp
);
6745 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6746 return NT_STATUS_OK
;
6749 /****************************************************************************
6750 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6751 ****************************************************************************/
6753 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6754 struct smb_request
*req
,
6758 const struct smb_filename
*smb_fname
,
6759 bool fail_after_createfile
)
6763 if (total_data
< 8) {
6764 return NT_STATUS_INVALID_PARAMETER
;
6767 size
= IVAL(pdata
,0);
6768 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6769 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6770 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6773 return smb_set_file_size(conn
, req
,
6778 fail_after_createfile
);
6781 /****************************************************************************
6782 Allow a UNIX info mknod.
6783 ****************************************************************************/
6785 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6788 const struct smb_filename
*smb_fname
)
6790 uint32 file_type
= IVAL(pdata
,56);
6791 #if defined(HAVE_MAKEDEV)
6792 uint32 dev_major
= IVAL(pdata
,60);
6793 uint32 dev_minor
= IVAL(pdata
,68);
6795 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6796 uint32 raw_unixmode
= IVAL(pdata
,84);
6800 if (total_data
< 100) {
6801 return NT_STATUS_INVALID_PARAMETER
;
6804 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6805 PERM_NEW_FILE
, &unixmode
);
6806 if (!NT_STATUS_IS_OK(status
)) {
6810 #if defined(HAVE_MAKEDEV)
6811 dev
= makedev(dev_major
, dev_minor
);
6814 switch (file_type
) {
6815 #if defined(S_IFIFO)
6816 case UNIX_TYPE_FIFO
:
6817 unixmode
|= S_IFIFO
;
6820 #if defined(S_IFSOCK)
6821 case UNIX_TYPE_SOCKET
:
6822 unixmode
|= S_IFSOCK
;
6825 #if defined(S_IFCHR)
6826 case UNIX_TYPE_CHARDEV
:
6827 unixmode
|= S_IFCHR
;
6830 #if defined(S_IFBLK)
6831 case UNIX_TYPE_BLKDEV
:
6832 unixmode
|= S_IFBLK
;
6836 return NT_STATUS_INVALID_PARAMETER
;
6839 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6840 "%.0f mode 0%o for file %s\n", (double)dev
,
6841 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6843 /* Ok - do the mknod. */
6844 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6845 return map_nt_error_from_unix(errno
);
6848 /* If any of the other "set" calls fail we
6849 * don't want to end up with a half-constructed mknod.
6852 if (lp_inherit_perms(SNUM(conn
))) {
6854 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6856 return NT_STATUS_NO_MEMORY
;
6858 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6860 TALLOC_FREE(parent
);
6863 return NT_STATUS_OK
;
6866 /****************************************************************************
6867 Deal with SMB_SET_FILE_UNIX_BASIC.
6868 ****************************************************************************/
6870 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6871 struct smb_request
*req
,
6875 const struct smb_filename
*smb_fname
)
6877 struct smb_file_time ft
;
6878 uint32 raw_unixmode
;
6881 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6882 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6883 NTSTATUS status
= NT_STATUS_OK
;
6884 bool delete_on_fail
= False
;
6885 enum perm_type ptype
;
6886 files_struct
*all_fsps
= NULL
;
6887 bool modify_mtime
= true;
6889 struct smb_filename
*smb_fname_tmp
= NULL
;
6890 SMB_STRUCT_STAT sbuf
;
6894 if (total_data
< 100) {
6895 return NT_STATUS_INVALID_PARAMETER
;
6898 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6899 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6900 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6901 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6904 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6905 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6906 set_owner
= (uid_t
)IVAL(pdata
,40);
6907 set_grp
= (gid_t
)IVAL(pdata
,48);
6908 raw_unixmode
= IVAL(pdata
,84);
6910 if (VALID_STAT(smb_fname
->st
)) {
6911 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6912 ptype
= PERM_EXISTING_DIR
;
6914 ptype
= PERM_EXISTING_FILE
;
6917 ptype
= PERM_NEW_FILE
;
6920 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6922 if (!NT_STATUS_IS_OK(status
)) {
6926 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6927 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6928 smb_fname_str_dbg(smb_fname
), (double)size
,
6929 (unsigned int)set_owner
, (unsigned int)set_grp
,
6930 (int)raw_unixmode
));
6932 sbuf
= smb_fname
->st
;
6934 if (!VALID_STAT(sbuf
)) {
6936 * The only valid use of this is to create character and block
6937 * devices, and named pipes. This is deprecated (IMHO) and
6938 * a new info level should be used for mknod. JRA.
6941 status
= smb_unix_mknod(conn
,
6945 if (!NT_STATUS_IS_OK(status
)) {
6949 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6951 if (!NT_STATUS_IS_OK(status
)) {
6955 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6956 status
= map_nt_error_from_unix(errno
);
6957 TALLOC_FREE(smb_fname_tmp
);
6958 SMB_VFS_UNLINK(conn
, smb_fname
);
6962 sbuf
= smb_fname_tmp
->st
;
6963 smb_fname
= smb_fname_tmp
;
6965 /* Ensure we don't try and change anything else. */
6966 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6967 size
= get_file_size_stat(&sbuf
);
6968 ft
.atime
= sbuf
.st_ex_atime
;
6969 ft
.mtime
= sbuf
.st_ex_mtime
;
6971 * We continue here as we might want to change the
6974 delete_on_fail
= True
;
6978 /* Horrible backwards compatibility hack as an old server bug
6979 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6983 size
= get_file_size_stat(&sbuf
);
6988 * Deal with the UNIX specific mode set.
6991 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6992 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6993 "setting mode 0%o for file %s\n",
6994 (unsigned int)unixmode
,
6995 smb_fname_str_dbg(smb_fname
)));
6996 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6997 return map_nt_error_from_unix(errno
);
7002 * Deal with the UNIX specific uid set.
7005 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7006 (sbuf
.st_ex_uid
!= set_owner
)) {
7009 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7010 "changing owner %u for path %s\n",
7011 (unsigned int)set_owner
,
7012 smb_fname_str_dbg(smb_fname
)));
7014 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7015 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7016 set_owner
, (gid_t
)-1);
7018 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7019 set_owner
, (gid_t
)-1);
7023 status
= map_nt_error_from_unix(errno
);
7024 if (delete_on_fail
) {
7025 SMB_VFS_UNLINK(conn
, smb_fname
);
7032 * Deal with the UNIX specific gid set.
7035 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7036 (sbuf
.st_ex_gid
!= set_grp
)) {
7037 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7038 "changing group %u for file %s\n",
7039 (unsigned int)set_owner
,
7040 smb_fname_str_dbg(smb_fname
)));
7041 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7043 status
= map_nt_error_from_unix(errno
);
7044 if (delete_on_fail
) {
7045 SMB_VFS_UNLINK(conn
, smb_fname
);
7051 /* Deal with any size changes. */
7053 status
= smb_set_file_size(conn
, req
,
7059 if (!NT_STATUS_IS_OK(status
)) {
7063 /* Deal with any time changes. */
7064 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7065 /* No change, don't cancel anything. */
7069 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7070 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7071 all_fsps
= file_find_di_next(all_fsps
)) {
7073 * We're setting the time explicitly for UNIX.
7074 * Cancel any pending changes over all handles.
7076 all_fsps
->update_write_time_on_close
= false;
7077 TALLOC_FREE(all_fsps
->update_write_time_event
);
7081 * Override the "setting_write_time"
7082 * parameter here as it almost does what
7083 * we need. Just remember if we modified
7084 * mtime and send the notify ourselves.
7086 if (null_timespec(ft
.mtime
)) {
7087 modify_mtime
= false;
7090 status
= smb_set_file_time(conn
,
7096 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7097 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7102 /****************************************************************************
7103 Deal with SMB_SET_FILE_UNIX_INFO2.
7104 ****************************************************************************/
7106 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7107 struct smb_request
*req
,
7111 const struct smb_filename
*smb_fname
)
7117 if (total_data
< 116) {
7118 return NT_STATUS_INVALID_PARAMETER
;
7121 /* Start by setting all the fields that are common between UNIX_BASIC
7124 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7126 if (!NT_STATUS_IS_OK(status
)) {
7130 smb_fflags
= IVAL(pdata
, 108);
7131 smb_fmask
= IVAL(pdata
, 112);
7133 /* NB: We should only attempt to alter the file flags if the client
7134 * sends a non-zero mask.
7136 if (smb_fmask
!= 0) {
7137 int stat_fflags
= 0;
7139 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7140 smb_fmask
, &stat_fflags
)) {
7141 /* Client asked to alter a flag we don't understand. */
7142 return NT_STATUS_INVALID_PARAMETER
;
7145 if (fsp
&& fsp
->fh
->fd
!= -1) {
7146 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7147 return NT_STATUS_NOT_SUPPORTED
;
7149 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7150 stat_fflags
) != 0) {
7151 return map_nt_error_from_unix(errno
);
7156 /* XXX: need to add support for changing the create_time here. You
7157 * can do this for paths on Darwin with setattrlist(2). The right way
7158 * to hook this up is probably by extending the VFS utimes interface.
7161 return NT_STATUS_OK
;
7164 /****************************************************************************
7165 Create a directory with POSIX semantics.
7166 ****************************************************************************/
7168 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7169 struct smb_request
*req
,
7172 struct smb_filename
*smb_fname
,
7173 int *pdata_return_size
)
7175 NTSTATUS status
= NT_STATUS_OK
;
7176 uint32 raw_unixmode
= 0;
7177 uint32 mod_unixmode
= 0;
7178 mode_t unixmode
= (mode_t
)0;
7179 files_struct
*fsp
= NULL
;
7180 uint16 info_level_return
= 0;
7182 char *pdata
= *ppdata
;
7184 if (total_data
< 18) {
7185 return NT_STATUS_INVALID_PARAMETER
;
7188 raw_unixmode
= IVAL(pdata
,8);
7189 /* Next 4 bytes are not yet defined. */
7191 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7192 PERM_NEW_DIR
, &unixmode
);
7193 if (!NT_STATUS_IS_OK(status
)) {
7197 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7199 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7200 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7202 status
= SMB_VFS_CREATE_FILE(
7205 0, /* root_dir_fid */
7206 smb_fname
, /* fname */
7207 FILE_READ_ATTRIBUTES
, /* access_mask */
7208 FILE_SHARE_NONE
, /* share_access */
7209 FILE_CREATE
, /* create_disposition*/
7210 FILE_DIRECTORY_FILE
, /* create_options */
7211 mod_unixmode
, /* file_attributes */
7212 0, /* oplock_request */
7213 0, /* allocation_size */
7214 0, /* private_flags */
7220 if (NT_STATUS_IS_OK(status
)) {
7221 close_file(req
, fsp
, NORMAL_CLOSE
);
7224 info_level_return
= SVAL(pdata
,16);
7226 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7227 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7228 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7229 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7231 *pdata_return_size
= 12;
7234 /* Realloc the data size */
7235 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7236 if (*ppdata
== NULL
) {
7237 *pdata_return_size
= 0;
7238 return NT_STATUS_NO_MEMORY
;
7242 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7243 SSVAL(pdata
,2,0); /* No fnum. */
7244 SIVAL(pdata
,4,info
); /* Was directory created. */
7246 switch (info_level_return
) {
7247 case SMB_QUERY_FILE_UNIX_BASIC
:
7248 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7249 SSVAL(pdata
,10,0); /* Padding. */
7250 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7253 case SMB_QUERY_FILE_UNIX_INFO2
:
7254 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7255 SSVAL(pdata
,10,0); /* Padding. */
7256 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7260 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7261 SSVAL(pdata
,10,0); /* Padding. */
7268 /****************************************************************************
7269 Open/Create a file with POSIX semantics.
7270 ****************************************************************************/
7272 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7273 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7275 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7276 struct smb_request
*req
,
7279 struct smb_filename
*smb_fname
,
7280 int *pdata_return_size
)
7282 bool extended_oplock_granted
= False
;
7283 char *pdata
= *ppdata
;
7285 uint32 wire_open_mode
= 0;
7286 uint32 raw_unixmode
= 0;
7287 uint32 mod_unixmode
= 0;
7288 uint32 create_disp
= 0;
7289 uint32 access_mask
= 0;
7290 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7291 NTSTATUS status
= NT_STATUS_OK
;
7292 mode_t unixmode
= (mode_t
)0;
7293 files_struct
*fsp
= NULL
;
7294 int oplock_request
= 0;
7296 uint16 info_level_return
= 0;
7298 if (total_data
< 18) {
7299 return NT_STATUS_INVALID_PARAMETER
;
7302 flags
= IVAL(pdata
,0);
7303 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7304 if (oplock_request
) {
7305 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7308 wire_open_mode
= IVAL(pdata
,4);
7310 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7311 return smb_posix_mkdir(conn
, req
,
7318 switch (wire_open_mode
& SMB_ACCMODE
) {
7320 access_mask
= SMB_O_RDONLY_MAPPING
;
7323 access_mask
= SMB_O_WRONLY_MAPPING
;
7326 access_mask
= (SMB_O_RDONLY_MAPPING
|
7327 SMB_O_WRONLY_MAPPING
);
7330 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7331 (unsigned int)wire_open_mode
));
7332 return NT_STATUS_INVALID_PARAMETER
;
7335 wire_open_mode
&= ~SMB_ACCMODE
;
7337 /* First take care of O_CREAT|O_EXCL interactions. */
7338 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7339 case (SMB_O_CREAT
| SMB_O_EXCL
):
7340 /* File exists fail. File not exist create. */
7341 create_disp
= FILE_CREATE
;
7344 /* File exists open. File not exist create. */
7345 create_disp
= FILE_OPEN_IF
;
7348 /* File exists open. File not exist fail. */
7349 create_disp
= FILE_OPEN
;
7352 /* O_EXCL on its own without O_CREAT is undefined. */
7354 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7355 (unsigned int)wire_open_mode
));
7356 return NT_STATUS_INVALID_PARAMETER
;
7359 /* Next factor in the effects of O_TRUNC. */
7360 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7362 if (wire_open_mode
& SMB_O_TRUNC
) {
7363 switch (create_disp
) {
7365 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7366 /* Leave create_disp alone as
7367 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7369 /* File exists fail. File not exist create. */
7372 /* SMB_O_CREAT | SMB_O_TRUNC */
7373 /* File exists overwrite. File not exist create. */
7374 create_disp
= FILE_OVERWRITE_IF
;
7378 /* File exists overwrite. File not exist fail. */
7379 create_disp
= FILE_OVERWRITE
;
7382 /* Cannot get here. */
7383 smb_panic("smb_posix_open: logic error");
7384 return NT_STATUS_INVALID_PARAMETER
;
7388 raw_unixmode
= IVAL(pdata
,8);
7389 /* Next 4 bytes are not yet defined. */
7391 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7392 (VALID_STAT(smb_fname
->st
) ?
7393 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7396 if (!NT_STATUS_IS_OK(status
)) {
7400 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7402 if (wire_open_mode
& SMB_O_SYNC
) {
7403 create_options
|= FILE_WRITE_THROUGH
;
7405 if (wire_open_mode
& SMB_O_APPEND
) {
7406 access_mask
|= FILE_APPEND_DATA
;
7408 if (wire_open_mode
& SMB_O_DIRECT
) {
7409 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7412 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7413 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7414 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7415 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7417 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7418 create_options
|= FILE_DIRECTORY_FILE
;
7421 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7422 smb_fname_str_dbg(smb_fname
),
7423 (unsigned int)wire_open_mode
,
7424 (unsigned int)unixmode
));
7426 status
= SMB_VFS_CREATE_FILE(
7429 0, /* root_dir_fid */
7430 smb_fname
, /* fname */
7431 access_mask
, /* access_mask */
7432 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7434 create_disp
, /* create_disposition*/
7435 create_options
, /* create_options */
7436 mod_unixmode
, /* file_attributes */
7437 oplock_request
, /* oplock_request */
7438 0, /* allocation_size */
7439 0, /* private_flags */
7445 if (!NT_STATUS_IS_OK(status
)) {
7449 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7450 extended_oplock_granted
= True
;
7453 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7454 extended_oplock_granted
= True
;
7457 info_level_return
= SVAL(pdata
,16);
7459 /* Allocate the correct return size. */
7461 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7462 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7463 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7464 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7466 *pdata_return_size
= 12;
7469 /* Realloc the data size */
7470 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7471 if (*ppdata
== NULL
) {
7472 close_file(req
, fsp
, ERROR_CLOSE
);
7473 *pdata_return_size
= 0;
7474 return NT_STATUS_NO_MEMORY
;
7478 if (extended_oplock_granted
) {
7479 if (flags
& REQUEST_BATCH_OPLOCK
) {
7480 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7482 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7484 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7485 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7487 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7490 SSVAL(pdata
,2,fsp
->fnum
);
7491 SIVAL(pdata
,4,info
); /* Was file created etc. */
7493 switch (info_level_return
) {
7494 case SMB_QUERY_FILE_UNIX_BASIC
:
7495 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7496 SSVAL(pdata
,10,0); /* padding. */
7497 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7500 case SMB_QUERY_FILE_UNIX_INFO2
:
7501 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7502 SSVAL(pdata
,10,0); /* padding. */
7503 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7507 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7508 SSVAL(pdata
,10,0); /* padding. */
7511 return NT_STATUS_OK
;
7514 /****************************************************************************
7515 Delete a file with POSIX semantics.
7516 ****************************************************************************/
7518 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7519 struct smb_request
*req
,
7522 struct smb_filename
*smb_fname
)
7524 NTSTATUS status
= NT_STATUS_OK
;
7525 files_struct
*fsp
= NULL
;
7529 int create_options
= 0;
7531 struct share_mode_lock
*lck
= NULL
;
7533 if (total_data
< 2) {
7534 return NT_STATUS_INVALID_PARAMETER
;
7537 flags
= SVAL(pdata
,0);
7539 if (!VALID_STAT(smb_fname
->st
)) {
7540 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7543 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7544 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7545 return NT_STATUS_NOT_A_DIRECTORY
;
7548 DEBUG(10,("smb_posix_unlink: %s %s\n",
7549 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7550 smb_fname_str_dbg(smb_fname
)));
7552 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7553 create_options
|= FILE_DIRECTORY_FILE
;
7556 status
= SMB_VFS_CREATE_FILE(
7559 0, /* root_dir_fid */
7560 smb_fname
, /* fname */
7561 DELETE_ACCESS
, /* access_mask */
7562 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7564 FILE_OPEN
, /* create_disposition*/
7565 create_options
, /* create_options */
7566 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7567 0, /* oplock_request */
7568 0, /* allocation_size */
7569 0, /* private_flags */
7575 if (!NT_STATUS_IS_OK(status
)) {
7580 * Don't lie to client. If we can't really delete due to
7581 * non-POSIX opens return SHARING_VIOLATION.
7584 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7586 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7587 "lock for file %s\n", fsp_str_dbg(fsp
)));
7588 close_file(req
, fsp
, NORMAL_CLOSE
);
7589 return NT_STATUS_INVALID_PARAMETER
;
7593 * See if others still have the file open. If this is the case, then
7594 * don't delete. If all opens are POSIX delete we can set the delete
7595 * on close disposition.
7597 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7598 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7599 if (is_valid_share_mode_entry(e
)) {
7600 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7603 /* Fail with sharing violation. */
7604 close_file(req
, fsp
, NORMAL_CLOSE
);
7606 return NT_STATUS_SHARING_VIOLATION
;
7611 * Set the delete on close.
7613 status
= smb_set_file_disposition_info(conn
,
7619 if (!NT_STATUS_IS_OK(status
)) {
7620 close_file(req
, fsp
, NORMAL_CLOSE
);
7625 return close_file(req
, fsp
, NORMAL_CLOSE
);
7628 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7629 struct smb_request
*req
,
7630 TALLOC_CTX
*mem_ctx
,
7631 uint16_t info_level
,
7633 struct smb_filename
*smb_fname
,
7634 char **ppdata
, int total_data
,
7637 char *pdata
= *ppdata
;
7638 NTSTATUS status
= NT_STATUS_OK
;
7639 int data_return_size
= 0;
7643 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7644 return NT_STATUS_INVALID_LEVEL
;
7647 if (!CAN_WRITE(conn
)) {
7648 /* Allow POSIX opens. The open path will deny
7649 * any non-readonly opens. */
7650 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7651 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7655 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7656 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7657 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7659 switch (info_level
) {
7661 case SMB_INFO_STANDARD
:
7663 status
= smb_set_info_standard(conn
,
7671 case SMB_INFO_SET_EA
:
7673 status
= smb_info_set_ea(conn
,
7681 case SMB_SET_FILE_BASIC_INFO
:
7682 case SMB_FILE_BASIC_INFORMATION
:
7684 status
= smb_set_file_basic_info(conn
,
7692 case SMB_FILE_ALLOCATION_INFORMATION
:
7693 case SMB_SET_FILE_ALLOCATION_INFO
:
7695 status
= smb_set_file_allocation_info(conn
, req
,
7703 case SMB_FILE_END_OF_FILE_INFORMATION
:
7704 case SMB_SET_FILE_END_OF_FILE_INFO
:
7707 * XP/Win7 both fail after the createfile with
7708 * SMB_SET_FILE_END_OF_FILE_INFO but not
7709 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7710 * The level is known here, so pass it down
7714 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7716 status
= smb_set_file_end_of_file_info(conn
, req
,
7725 case SMB_FILE_DISPOSITION_INFORMATION
:
7726 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7729 /* JRA - We used to just ignore this on a path ?
7730 * Shouldn't this be invalid level on a pathname
7733 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7734 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7737 status
= smb_set_file_disposition_info(conn
,
7745 case SMB_FILE_POSITION_INFORMATION
:
7747 status
= smb_file_position_information(conn
,
7754 case SMB_FILE_FULL_EA_INFORMATION
:
7756 status
= smb_set_file_full_ea_info(conn
,
7763 /* From tridge Samba4 :
7764 * MODE_INFORMATION in setfileinfo (I have no
7765 * idea what "mode information" on a file is - it takes a value of 0,
7766 * 2, 4 or 6. What could it be?).
7769 case SMB_FILE_MODE_INFORMATION
:
7771 status
= smb_file_mode_information(conn
,
7778 * CIFS UNIX extensions.
7781 case SMB_SET_FILE_UNIX_BASIC
:
7783 status
= smb_set_file_unix_basic(conn
, req
,
7791 case SMB_SET_FILE_UNIX_INFO2
:
7793 status
= smb_set_file_unix_info2(conn
, req
,
7801 case SMB_SET_FILE_UNIX_LINK
:
7804 /* We must have a pathname for this. */
7805 return NT_STATUS_INVALID_LEVEL
;
7807 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7808 total_data
, smb_fname
);
7812 case SMB_SET_FILE_UNIX_HLINK
:
7815 /* We must have a pathname for this. */
7816 return NT_STATUS_INVALID_LEVEL
;
7818 status
= smb_set_file_unix_hlink(conn
, req
,
7824 case SMB_FILE_RENAME_INFORMATION
:
7826 status
= smb_file_rename_information(conn
, req
,
7832 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7834 /* SMB2 rename information. */
7835 status
= smb2_file_rename_information(conn
, req
,
7841 case SMB_FILE_LINK_INFORMATION
:
7843 status
= smb_file_link_information(conn
, req
,
7849 #if defined(HAVE_POSIX_ACLS)
7850 case SMB_SET_POSIX_ACL
:
7852 status
= smb_set_posix_acl(conn
,
7861 case SMB_SET_POSIX_LOCK
:
7864 return NT_STATUS_INVALID_LEVEL
;
7866 status
= smb_set_posix_lock(conn
, req
,
7867 pdata
, total_data
, fsp
);
7871 case SMB_POSIX_PATH_OPEN
:
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL
;
7878 status
= smb_posix_open(conn
, req
,
7886 case SMB_POSIX_PATH_UNLINK
:
7889 /* We must have a pathname for this. */
7890 return NT_STATUS_INVALID_LEVEL
;
7893 status
= smb_posix_unlink(conn
, req
,
7901 return NT_STATUS_INVALID_LEVEL
;
7904 if (!NT_STATUS_IS_OK(status
)) {
7908 *ret_data_size
= data_return_size
;
7909 return NT_STATUS_OK
;
7912 /****************************************************************************
7913 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7914 ****************************************************************************/
7916 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7917 struct smb_request
*req
,
7918 unsigned int tran_call
,
7919 char **pparams
, int total_params
,
7920 char **ppdata
, int total_data
,
7921 unsigned int max_data_bytes
)
7923 char *params
= *pparams
;
7924 char *pdata
= *ppdata
;
7926 struct smb_filename
*smb_fname
= NULL
;
7927 files_struct
*fsp
= NULL
;
7928 NTSTATUS status
= NT_STATUS_OK
;
7929 int data_return_size
= 0;
7932 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7936 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7937 if (total_params
< 4) {
7938 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7942 fsp
= file_fsp(req
, SVAL(params
,0));
7943 /* Basic check for non-null fsp. */
7944 if (!check_fsp_open(conn
, req
, fsp
)) {
7947 info_level
= SVAL(params
,2);
7949 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7951 if (!NT_STATUS_IS_OK(status
)) {
7952 reply_nterror(req
, status
);
7956 if(fsp
->fh
->fd
== -1) {
7958 * This is actually a SETFILEINFO on a directory
7959 * handle (returned from an NT SMB). NT5.0 seems
7960 * to do this call. JRA.
7962 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7963 /* Always do lstat for UNIX calls. */
7964 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7965 DEBUG(3,("call_trans2setfilepathinfo: "
7966 "SMB_VFS_LSTAT of %s failed "
7968 smb_fname_str_dbg(smb_fname
),
7970 reply_nterror(req
, map_nt_error_from_unix(errno
));
7974 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7975 DEBUG(3,("call_trans2setfilepathinfo: "
7976 "fileinfo of %s failed (%s)\n",
7977 smb_fname_str_dbg(smb_fname
),
7979 reply_nterror(req
, map_nt_error_from_unix(errno
));
7983 } else if (fsp
->print_file
) {
7985 * Doing a DELETE_ON_CLOSE should cancel a print job.
7987 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7988 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7990 DEBUG(3,("call_trans2setfilepathinfo: "
7991 "Cancelling print job (%s)\n",
7995 send_trans2_replies(conn
, req
, params
, 2,
8001 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8006 * Original code - this is an open file.
8008 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8009 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8010 "of fnum %d failed (%s)\n", fsp
->fnum
,
8012 reply_nterror(req
, map_nt_error_from_unix(errno
));
8018 uint32_t ucf_flags
= 0;
8021 if (total_params
< 7) {
8022 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8026 info_level
= SVAL(params
,0);
8027 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8028 total_params
- 6, STR_TERMINATE
,
8030 if (!NT_STATUS_IS_OK(status
)) {
8031 reply_nterror(req
, status
);
8035 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8036 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8037 info_level
== SMB_FILE_RENAME_INFORMATION
||
8038 info_level
== SMB_POSIX_PATH_UNLINK
) {
8039 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8042 status
= filename_convert(req
, conn
,
8043 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8048 if (!NT_STATUS_IS_OK(status
)) {
8049 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8050 reply_botherror(req
,
8051 NT_STATUS_PATH_NOT_COVERED
,
8052 ERRSRV
, ERRbadpath
);
8055 reply_nterror(req
, status
);
8059 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8061 * For CIFS UNIX extensions the target name may not exist.
8064 /* Always do lstat for UNIX calls. */
8065 SMB_VFS_LSTAT(conn
, smb_fname
);
8067 } else if (!VALID_STAT(smb_fname
->st
) &&
8068 SMB_VFS_STAT(conn
, smb_fname
)) {
8069 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8071 smb_fname_str_dbg(smb_fname
),
8073 reply_nterror(req
, map_nt_error_from_unix(errno
));
8078 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8079 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8080 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8082 /* Realloc the parameter size */
8083 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8084 if (*pparams
== NULL
) {
8085 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8092 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8098 if (!NT_STATUS_IS_OK(status
)) {
8099 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8100 /* We have re-scheduled this call. */
8103 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8104 /* We have re-scheduled this call. */
8107 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8108 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8109 ERRSRV
, ERRbadpath
);
8112 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8113 reply_openerror(req
, status
);
8117 reply_nterror(req
, status
);
8121 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8127 /****************************************************************************
8128 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8129 ****************************************************************************/
8131 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8132 char **pparams
, int total_params
,
8133 char **ppdata
, int total_data
,
8134 unsigned int max_data_bytes
)
8136 struct smb_filename
*smb_dname
= NULL
;
8137 char *params
= *pparams
;
8138 char *pdata
= *ppdata
;
8139 char *directory
= NULL
;
8140 NTSTATUS status
= NT_STATUS_OK
;
8141 struct ea_list
*ea_list
= NULL
;
8142 TALLOC_CTX
*ctx
= talloc_tos();
8144 if (!CAN_WRITE(conn
)) {
8145 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8149 if (total_params
< 5) {
8150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8154 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8155 total_params
- 4, STR_TERMINATE
,
8157 if (!NT_STATUS_IS_OK(status
)) {
8158 reply_nterror(req
, status
);
8162 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8164 status
= filename_convert(ctx
,
8166 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8172 if (!NT_STATUS_IS_OK(status
)) {
8173 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8174 reply_botherror(req
,
8175 NT_STATUS_PATH_NOT_COVERED
,
8176 ERRSRV
, ERRbadpath
);
8179 reply_nterror(req
, status
);
8184 * OS/2 workplace shell seems to send SET_EA requests of "null"
8185 * length (4 bytes containing IVAL 4).
8186 * They seem to have no effect. Bug #3212. JRA.
8189 if (total_data
&& (total_data
!= 4)) {
8190 /* Any data in this call is an EA list. */
8191 if (total_data
< 10) {
8192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8196 if (IVAL(pdata
,0) > total_data
) {
8197 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8198 IVAL(pdata
,0), (unsigned int)total_data
));
8199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8203 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8206 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8210 if (!lp_ea_support(SNUM(conn
))) {
8211 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8215 /* If total_data == 4 Windows doesn't care what values
8216 * are placed in that field, it just ignores them.
8217 * The System i QNTC IBM SMB client puts bad values here,
8218 * so ignore them. */
8220 status
= create_directory(conn
, req
, smb_dname
);
8222 if (!NT_STATUS_IS_OK(status
)) {
8223 reply_nterror(req
, status
);
8227 /* Try and set any given EA. */
8229 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8230 if (!NT_STATUS_IS_OK(status
)) {
8231 reply_nterror(req
, status
);
8236 /* Realloc the parameter and data sizes */
8237 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8238 if(*pparams
== NULL
) {
8239 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8246 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8249 TALLOC_FREE(smb_dname
);
8253 /****************************************************************************
8254 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8255 We don't actually do this - we just send a null response.
8256 ****************************************************************************/
8258 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8259 struct smb_request
*req
,
8260 char **pparams
, int total_params
,
8261 char **ppdata
, int total_data
,
8262 unsigned int max_data_bytes
)
8264 char *params
= *pparams
;
8267 if (total_params
< 6) {
8268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8272 info_level
= SVAL(params
,4);
8273 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8275 switch (info_level
) {
8280 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8284 /* Realloc the parameter and data sizes */
8285 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8286 if (*pparams
== NULL
) {
8287 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8292 SSVAL(params
,0,fnf_handle
);
8293 SSVAL(params
,2,0); /* No changes */
8294 SSVAL(params
,4,0); /* No EA errors */
8301 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8306 /****************************************************************************
8307 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8308 changes). Currently this does nothing.
8309 ****************************************************************************/
8311 static void call_trans2findnotifynext(connection_struct
*conn
,
8312 struct smb_request
*req
,
8313 char **pparams
, int total_params
,
8314 char **ppdata
, int total_data
,
8315 unsigned int max_data_bytes
)
8317 char *params
= *pparams
;
8319 DEBUG(3,("call_trans2findnotifynext\n"));
8321 /* Realloc the parameter and data sizes */
8322 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8323 if (*pparams
== NULL
) {
8324 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8329 SSVAL(params
,0,0); /* No changes */
8330 SSVAL(params
,2,0); /* No EA errors */
8332 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8337 /****************************************************************************
8338 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8339 ****************************************************************************/
8341 static void call_trans2getdfsreferral(connection_struct
*conn
,
8342 struct smb_request
*req
,
8343 char **pparams
, int total_params
,
8344 char **ppdata
, int total_data
,
8345 unsigned int max_data_bytes
)
8347 char *params
= *pparams
;
8348 char *pathname
= NULL
;
8350 int max_referral_level
;
8351 NTSTATUS status
= NT_STATUS_OK
;
8352 TALLOC_CTX
*ctx
= talloc_tos();
8354 DEBUG(10,("call_trans2getdfsreferral\n"));
8356 if (total_params
< 3) {
8357 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8361 max_referral_level
= SVAL(params
,0);
8363 if(!lp_host_msdfs()) {
8364 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8368 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8369 total_params
- 2, STR_TERMINATE
);
8371 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8374 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8375 ppdata
,&status
)) < 0) {
8376 reply_nterror(req
, status
);
8380 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8381 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8382 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8387 #define LMCAT_SPL 0x53
8388 #define LMFUNC_GETJOBID 0x60
8390 /****************************************************************************
8391 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8392 ****************************************************************************/
8394 static void call_trans2ioctl(connection_struct
*conn
,
8395 struct smb_request
*req
,
8396 char **pparams
, int total_params
,
8397 char **ppdata
, int total_data
,
8398 unsigned int max_data_bytes
)
8400 char *pdata
= *ppdata
;
8401 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8403 /* check for an invalid fid before proceeding */
8406 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8410 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8411 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8412 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8413 if (*ppdata
== NULL
) {
8414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8419 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8420 CAN ACCEPT THIS IN UNICODE. JRA. */
8423 if (fsp
->print_file
) {
8424 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8428 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8429 lp_netbios_name(), 15,
8430 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8431 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8432 lp_servicename(SNUM(conn
)), 13,
8433 STR_ASCII
|STR_TERMINATE
); /* Service name */
8434 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8439 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8440 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8443 /****************************************************************************
8444 Reply to a SMBfindclose (stop trans2 directory search).
8445 ****************************************************************************/
8447 void reply_findclose(struct smb_request
*req
)
8450 struct smbd_server_connection
*sconn
= req
->sconn
;
8452 START_PROFILE(SMBfindclose
);
8455 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8456 END_PROFILE(SMBfindclose
);
8460 dptr_num
= SVALS(req
->vwv
+0, 0);
8462 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8464 dptr_close(sconn
, &dptr_num
);
8466 reply_outbuf(req
, 0, 0);
8468 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8470 END_PROFILE(SMBfindclose
);
8474 /****************************************************************************
8475 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8476 ****************************************************************************/
8478 void reply_findnclose(struct smb_request
*req
)
8482 START_PROFILE(SMBfindnclose
);
8485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8486 END_PROFILE(SMBfindnclose
);
8490 dptr_num
= SVAL(req
->vwv
+0, 0);
8492 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8494 /* We never give out valid handles for a
8495 findnotifyfirst - so any dptr_num is ok here.
8498 reply_outbuf(req
, 0, 0);
8500 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8502 END_PROFILE(SMBfindnclose
);
8506 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8507 struct trans_state
*state
)
8509 if (get_Protocol() >= PROTOCOL_NT1
) {
8510 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8511 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8514 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8515 if (state
->call
!= TRANSACT2_QFSINFO
&&
8516 state
->call
!= TRANSACT2_SETFSINFO
) {
8517 DEBUG(0,("handle_trans2: encryption required "
8519 (unsigned int)state
->call
));
8520 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8525 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8527 /* Now we must call the relevant TRANS2 function */
8528 switch(state
->call
) {
8529 case TRANSACT2_OPEN
:
8531 START_PROFILE(Trans2_open
);
8532 call_trans2open(conn
, req
,
8533 &state
->param
, state
->total_param
,
8534 &state
->data
, state
->total_data
,
8535 state
->max_data_return
);
8536 END_PROFILE(Trans2_open
);
8540 case TRANSACT2_FINDFIRST
:
8542 START_PROFILE(Trans2_findfirst
);
8543 call_trans2findfirst(conn
, req
,
8544 &state
->param
, state
->total_param
,
8545 &state
->data
, state
->total_data
,
8546 state
->max_data_return
);
8547 END_PROFILE(Trans2_findfirst
);
8551 case TRANSACT2_FINDNEXT
:
8553 START_PROFILE(Trans2_findnext
);
8554 call_trans2findnext(conn
, req
,
8555 &state
->param
, state
->total_param
,
8556 &state
->data
, state
->total_data
,
8557 state
->max_data_return
);
8558 END_PROFILE(Trans2_findnext
);
8562 case TRANSACT2_QFSINFO
:
8564 START_PROFILE(Trans2_qfsinfo
);
8565 call_trans2qfsinfo(conn
, req
,
8566 &state
->param
, state
->total_param
,
8567 &state
->data
, state
->total_data
,
8568 state
->max_data_return
);
8569 END_PROFILE(Trans2_qfsinfo
);
8573 case TRANSACT2_SETFSINFO
:
8575 START_PROFILE(Trans2_setfsinfo
);
8576 call_trans2setfsinfo(conn
, req
,
8577 &state
->param
, state
->total_param
,
8578 &state
->data
, state
->total_data
,
8579 state
->max_data_return
);
8580 END_PROFILE(Trans2_setfsinfo
);
8584 case TRANSACT2_QPATHINFO
:
8585 case TRANSACT2_QFILEINFO
:
8587 START_PROFILE(Trans2_qpathinfo
);
8588 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8589 &state
->param
, state
->total_param
,
8590 &state
->data
, state
->total_data
,
8591 state
->max_data_return
);
8592 END_PROFILE(Trans2_qpathinfo
);
8596 case TRANSACT2_SETPATHINFO
:
8597 case TRANSACT2_SETFILEINFO
:
8599 START_PROFILE(Trans2_setpathinfo
);
8600 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8601 &state
->param
, state
->total_param
,
8602 &state
->data
, state
->total_data
,
8603 state
->max_data_return
);
8604 END_PROFILE(Trans2_setpathinfo
);
8608 case TRANSACT2_FINDNOTIFYFIRST
:
8610 START_PROFILE(Trans2_findnotifyfirst
);
8611 call_trans2findnotifyfirst(conn
, req
,
8612 &state
->param
, state
->total_param
,
8613 &state
->data
, state
->total_data
,
8614 state
->max_data_return
);
8615 END_PROFILE(Trans2_findnotifyfirst
);
8619 case TRANSACT2_FINDNOTIFYNEXT
:
8621 START_PROFILE(Trans2_findnotifynext
);
8622 call_trans2findnotifynext(conn
, req
,
8623 &state
->param
, state
->total_param
,
8624 &state
->data
, state
->total_data
,
8625 state
->max_data_return
);
8626 END_PROFILE(Trans2_findnotifynext
);
8630 case TRANSACT2_MKDIR
:
8632 START_PROFILE(Trans2_mkdir
);
8633 call_trans2mkdir(conn
, req
,
8634 &state
->param
, state
->total_param
,
8635 &state
->data
, state
->total_data
,
8636 state
->max_data_return
);
8637 END_PROFILE(Trans2_mkdir
);
8641 case TRANSACT2_GET_DFS_REFERRAL
:
8643 START_PROFILE(Trans2_get_dfs_referral
);
8644 call_trans2getdfsreferral(conn
, req
,
8645 &state
->param
, state
->total_param
,
8646 &state
->data
, state
->total_data
,
8647 state
->max_data_return
);
8648 END_PROFILE(Trans2_get_dfs_referral
);
8652 case TRANSACT2_IOCTL
:
8654 START_PROFILE(Trans2_ioctl
);
8655 call_trans2ioctl(conn
, req
,
8656 &state
->param
, state
->total_param
,
8657 &state
->data
, state
->total_data
,
8658 state
->max_data_return
);
8659 END_PROFILE(Trans2_ioctl
);
8664 /* Error in request */
8665 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8666 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8670 /****************************************************************************
8671 Reply to a SMBtrans2.
8672 ****************************************************************************/
8674 void reply_trans2(struct smb_request
*req
)
8676 connection_struct
*conn
= req
->conn
;
8681 unsigned int tran_call
;
8682 struct trans_state
*state
;
8685 START_PROFILE(SMBtrans2
);
8687 if (req
->wct
< 14) {
8688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8689 END_PROFILE(SMBtrans2
);
8693 dsoff
= SVAL(req
->vwv
+12, 0);
8694 dscnt
= SVAL(req
->vwv
+11, 0);
8695 psoff
= SVAL(req
->vwv
+10, 0);
8696 pscnt
= SVAL(req
->vwv
+9, 0);
8697 tran_call
= SVAL(req
->vwv
+14, 0);
8699 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8700 if (!NT_STATUS_IS_OK(result
)) {
8701 DEBUG(2, ("Got invalid trans2 request: %s\n",
8702 nt_errstr(result
)));
8703 reply_nterror(req
, result
);
8704 END_PROFILE(SMBtrans2
);
8709 switch (tran_call
) {
8710 /* List the allowed trans2 calls on IPC$ */
8711 case TRANSACT2_OPEN
:
8712 case TRANSACT2_GET_DFS_REFERRAL
:
8713 case TRANSACT2_QFILEINFO
:
8714 case TRANSACT2_QFSINFO
:
8715 case TRANSACT2_SETFSINFO
:
8718 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8719 END_PROFILE(SMBtrans2
);
8724 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8725 DEBUG(0, ("talloc failed\n"));
8726 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8727 END_PROFILE(SMBtrans2
);
8731 state
->cmd
= SMBtrans2
;
8733 state
->mid
= req
->mid
;
8734 state
->vuid
= req
->vuid
;
8735 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8736 state
->setup
= NULL
;
8737 state
->total_param
= SVAL(req
->vwv
+0, 0);
8738 state
->param
= NULL
;
8739 state
->total_data
= SVAL(req
->vwv
+1, 0);
8741 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8742 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8743 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8744 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8745 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8747 state
->call
= tran_call
;
8749 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8750 is so as a sanity check */
8751 if (state
->setup_count
!= 1) {
8753 * Need to have rc=0 for ioctl to get job id for OS/2.
8754 * Network printing will fail if function is not successful.
8755 * Similar function in reply.c will be used if protocol
8756 * is LANMAN1.0 instead of LM1.2X002.
8757 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8758 * outbuf doesn't have to be set(only job id is used).
8760 if ( (state
->setup_count
== 4)
8761 && (tran_call
== TRANSACT2_IOCTL
)
8762 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8763 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8764 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8766 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8767 DEBUG(2,("Transaction is %d\n",tran_call
));
8769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8770 END_PROFILE(SMBtrans2
);
8775 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8778 if (state
->total_data
) {
8780 if (trans_oob(state
->total_data
, 0, dscnt
)
8781 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8785 /* Can't use talloc here, the core routines do realloc on the
8786 * params and data. */
8787 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8788 if (state
->data
== NULL
) {
8789 DEBUG(0,("reply_trans2: data malloc fail for %u "
8790 "bytes !\n", (unsigned int)state
->total_data
));
8792 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8793 END_PROFILE(SMBtrans2
);
8797 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8800 if (state
->total_param
) {
8802 if (trans_oob(state
->total_param
, 0, pscnt
)
8803 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8807 /* Can't use talloc here, the core routines do realloc on the
8808 * params and data. */
8809 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8810 if (state
->param
== NULL
) {
8811 DEBUG(0,("reply_trans: param malloc fail for %u "
8812 "bytes !\n", (unsigned int)state
->total_param
));
8813 SAFE_FREE(state
->data
);
8815 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8816 END_PROFILE(SMBtrans2
);
8820 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8823 state
->received_data
= dscnt
;
8824 state
->received_param
= pscnt
;
8826 if ((state
->received_param
== state
->total_param
) &&
8827 (state
->received_data
== state
->total_data
)) {
8829 handle_trans2(conn
, req
, state
);
8831 SAFE_FREE(state
->data
);
8832 SAFE_FREE(state
->param
);
8834 END_PROFILE(SMBtrans2
);
8838 DLIST_ADD(conn
->pending_trans
, state
);
8840 /* We need to send an interim response then receive the rest
8841 of the parameter/data bytes */
8842 reply_outbuf(req
, 0, 0);
8843 show_msg((char *)req
->outbuf
);
8844 END_PROFILE(SMBtrans2
);
8849 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8850 SAFE_FREE(state
->data
);
8851 SAFE_FREE(state
->param
);
8853 END_PROFILE(SMBtrans2
);
8854 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8858 /****************************************************************************
8859 Reply to a SMBtranss2
8860 ****************************************************************************/
8862 void reply_transs2(struct smb_request
*req
)
8864 connection_struct
*conn
= req
->conn
;
8865 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8866 struct trans_state
*state
;
8868 START_PROFILE(SMBtranss2
);
8870 show_msg((const char *)req
->inbuf
);
8873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8874 END_PROFILE(SMBtranss2
);
8878 for (state
= conn
->pending_trans
; state
!= NULL
;
8879 state
= state
->next
) {
8880 if (state
->mid
== req
->mid
) {
8885 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8886 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8887 END_PROFILE(SMBtranss2
);
8891 /* Revise state->total_param and state->total_data in case they have
8892 changed downwards */
8894 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8895 state
->total_param
= SVAL(req
->vwv
+0, 0);
8896 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8897 state
->total_data
= SVAL(req
->vwv
+1, 0);
8899 pcnt
= SVAL(req
->vwv
+2, 0);
8900 poff
= SVAL(req
->vwv
+3, 0);
8901 pdisp
= SVAL(req
->vwv
+4, 0);
8903 dcnt
= SVAL(req
->vwv
+5, 0);
8904 doff
= SVAL(req
->vwv
+6, 0);
8905 ddisp
= SVAL(req
->vwv
+7, 0);
8907 state
->received_param
+= pcnt
;
8908 state
->received_data
+= dcnt
;
8910 if ((state
->received_data
> state
->total_data
) ||
8911 (state
->received_param
> state
->total_param
))
8915 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8916 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8919 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8923 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8924 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8927 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8930 if ((state
->received_param
< state
->total_param
) ||
8931 (state
->received_data
< state
->total_data
)) {
8932 END_PROFILE(SMBtranss2
);
8936 handle_trans2(conn
, req
, state
);
8938 DLIST_REMOVE(conn
->pending_trans
, state
);
8939 SAFE_FREE(state
->data
);
8940 SAFE_FREE(state
->param
);
8943 END_PROFILE(SMBtranss2
);
8948 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8949 DLIST_REMOVE(conn
->pending_trans
, state
);
8950 SAFE_FREE(state
->data
);
8951 SAFE_FREE(state
->param
);
8953 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8954 END_PROFILE(SMBtranss2
);