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 "libcli/security/security.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct
*conn
,
45 const SMB_STRUCT_STAT
*psbuf
);
47 static char *store_file_unix_basic_info2(connection_struct
*conn
,
50 const SMB_STRUCT_STAT
*psbuf
);
52 /********************************************************************
53 The canonical "check access" based on object handle or path function.
54 ********************************************************************/
56 NTSTATUS
check_access(connection_struct
*conn
,
58 const struct smb_filename
*smb_fname
,
62 if (!(fsp
->access_mask
& access_mask
)) {
63 return NT_STATUS_ACCESS_DENIED
;
66 NTSTATUS status
= smbd_check_access_rights(conn
,
69 if (!NT_STATUS_IS_OK(status
)) {
76 /********************************************************************
77 Roundup a value to the nearest allocation roundup size boundary.
78 Only do this for Windows clients.
79 ********************************************************************/
81 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
83 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
85 /* Only roundup for Windows clients. */
86 enum remote_arch_types ra_type
= get_remote_arch();
87 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
88 val
= SMB_ROUNDUP(val
,rval
);
93 /********************************************************************
94 Create a 64 bit FileIndex. If the file is on the same device as
95 the root of the share, just return the 64-bit inode. If it isn't,
96 mangle as we used to do.
97 ********************************************************************/
99 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
102 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
103 return (uint64_t)psbuf
->st_ex_ino
;
105 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
106 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
110 /****************************************************************************
111 Utility functions for dealing with extended attributes.
112 ****************************************************************************/
114 /****************************************************************************
115 Refuse to allow clients to overwrite our private xattrs.
116 ****************************************************************************/
118 static bool samba_private_attr_name(const char *unix_ea_name
)
120 static const char * const prohibited_ea_names
[] = {
121 SAMBA_POSIX_INHERITANCE_EA_NAME
,
122 SAMBA_XATTR_DOS_ATTRIB
,
130 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
131 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
134 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
135 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
141 /****************************************************************************
142 Get one EA value. Fill in a struct ea_struct.
143 ****************************************************************************/
145 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
146 files_struct
*fsp
, const char *fname
,
147 const char *ea_name
, struct ea_struct
*pea
)
149 /* Get the value of this xattr. Max size is 64k. */
150 size_t attr_size
= 256;
156 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
158 return NT_STATUS_NO_MEMORY
;
161 if (fsp
&& fsp
->fh
->fd
!= -1) {
162 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
164 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
167 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
173 return map_nt_error_from_unix(errno
);
176 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
177 dump_data(10, (uint8
*)val
, sizeret
);
180 if (strnequal(ea_name
, "user.", 5)) {
181 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
183 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
185 if (pea
->name
== NULL
) {
187 return NT_STATUS_NO_MEMORY
;
189 pea
->value
.data
= (unsigned char *)val
;
190 pea
->value
.length
= (size_t)sizeret
;
194 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
195 files_struct
*fsp
, const char *fname
,
196 char ***pnames
, size_t *pnum_names
)
198 /* Get a list of all xattrs. Max namesize is 64k. */
199 size_t ea_namelist_size
= 1024;
200 char *ea_namelist
= NULL
;
205 ssize_t sizeret
= -1;
207 if (!lp_ea_support(SNUM(conn
))) {
216 * TALLOC the result early to get the talloc hierarchy right.
219 names
= talloc_array(mem_ctx
, char *, 1);
221 DEBUG(0, ("talloc failed\n"));
222 return NT_STATUS_NO_MEMORY
;
225 while (ea_namelist_size
<= 65536) {
227 ea_namelist
= talloc_realloc(
228 names
, ea_namelist
, char, ea_namelist_size
);
229 if (ea_namelist
== NULL
) {
230 DEBUG(0, ("talloc failed\n"));
232 return NT_STATUS_NO_MEMORY
;
235 if (fsp
&& fsp
->fh
->fd
!= -1) {
236 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
239 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
243 if ((sizeret
== -1) && (errno
== ERANGE
)) {
244 ea_namelist_size
*= 2;
253 return map_nt_error_from_unix(errno
);
256 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
257 (unsigned int)sizeret
));
269 * Ensure the result is 0-terminated
272 if (ea_namelist
[sizeret
-1] != '\0') {
274 return NT_STATUS_INTERNAL_ERROR
;
282 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
286 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
288 DEBUG(0, ("talloc failed\n"));
290 return NT_STATUS_NO_MEMORY
;
296 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
297 names
[num_names
++] = p
;
305 *pnum_names
= num_names
;
309 /****************************************************************************
310 Return a linked list of the total EA's. Plus the total size
311 ****************************************************************************/
313 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
314 const char *fname
, size_t *pea_total_len
)
316 /* Get a list of all xattrs. Max namesize is 64k. */
319 struct ea_list
*ea_list_head
= NULL
;
324 if (!lp_ea_support(SNUM(conn
))) {
328 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
331 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
335 for (i
=0; i
<num_names
; i
++) {
336 struct ea_list
*listp
;
339 if (strnequal(names
[i
], "system.", 7)
340 || samba_private_attr_name(names
[i
]))
343 listp
= talloc(mem_ctx
, struct ea_list
);
348 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
354 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
357 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
359 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
360 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
361 (unsigned int)listp
->ea
.value
.length
));
363 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
367 /* Add on 4 for total length. */
368 if (*pea_total_len
) {
372 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
373 (unsigned int)*pea_total_len
));
378 /****************************************************************************
379 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
381 ****************************************************************************/
383 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
384 connection_struct
*conn
, struct ea_list
*ea_list
)
386 unsigned int ret_data_size
= 4;
389 SMB_ASSERT(total_data_size
>= 4);
391 if (!lp_ea_support(SNUM(conn
))) {
396 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
399 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
400 dos_namelen
= strlen(dos_ea_name
);
401 if (dos_namelen
> 255 || dos_namelen
== 0) {
404 if (ea_list
->ea
.value
.length
> 65535) {
407 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
411 /* We know we have room. */
412 SCVAL(p
,0,ea_list
->ea
.flags
);
413 SCVAL(p
,1,dos_namelen
);
414 SSVAL(p
,2,ea_list
->ea
.value
.length
);
415 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
416 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
418 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
419 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
422 ret_data_size
= PTR_DIFF(p
, pdata
);
423 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
424 SIVAL(pdata
,0,ret_data_size
);
425 return ret_data_size
;
428 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
430 unsigned int total_data_size
,
431 unsigned int *ret_data_size
,
432 connection_struct
*conn
,
433 struct ea_list
*ea_list
)
435 uint8_t *p
= (uint8_t *)pdata
;
436 uint8_t *last_start
= NULL
;
440 if (!lp_ea_support(SNUM(conn
))) {
441 return NT_STATUS_NO_EAS_ON_FILE
;
444 for (; ea_list
; ea_list
= ea_list
->next
) {
450 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
454 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
455 dos_namelen
= strlen(dos_ea_name
);
456 if (dos_namelen
> 255 || dos_namelen
== 0) {
457 return NT_STATUS_INTERNAL_ERROR
;
459 if (ea_list
->ea
.value
.length
> 65535) {
460 return NT_STATUS_INTERNAL_ERROR
;
463 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
466 size_t pad
= 4 - (this_size
% 4);
470 if (this_size
> total_data_size
) {
471 return NT_STATUS_INFO_LENGTH_MISMATCH
;
474 /* We know we have room. */
475 SIVAL(p
, 0x00, 0); /* next offset */
476 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
477 SCVAL(p
, 0x05, dos_namelen
);
478 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
479 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
480 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
482 total_data_size
-= this_size
;
486 *ret_data_size
= PTR_DIFF(p
, pdata
);
487 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
491 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
493 size_t total_ea_len
= 0;
494 TALLOC_CTX
*mem_ctx
= NULL
;
496 if (!lp_ea_support(SNUM(conn
))) {
499 mem_ctx
= talloc_tos();
500 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
504 /****************************************************************************
505 Ensure the EA name is case insensitive by matching any existing EA name.
506 ****************************************************************************/
508 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
511 TALLOC_CTX
*mem_ctx
= talloc_tos();
512 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
514 for (; ea_list
; ea_list
= ea_list
->next
) {
515 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
516 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
517 &unix_ea_name
[5], ea_list
->ea
.name
));
518 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
524 /****************************************************************************
525 Set or delete an extended attribute.
526 ****************************************************************************/
528 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
529 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
534 if (!lp_ea_support(SNUM(conn
))) {
535 return NT_STATUS_EAS_NOT_SUPPORTED
;
538 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
539 if (!NT_STATUS_IS_OK(status
)) {
543 /* For now setting EAs on streams isn't supported. */
544 fname
= smb_fname
->base_name
;
546 for (;ea_list
; ea_list
= ea_list
->next
) {
548 fstring unix_ea_name
;
550 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
551 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
553 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
555 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
557 if (samba_private_attr_name(unix_ea_name
)) {
558 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
559 return NT_STATUS_ACCESS_DENIED
;
562 if (ea_list
->ea
.value
.length
== 0) {
563 /* Remove the attribute. */
564 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
565 DEBUG(10,("set_ea: deleting ea name %s on "
566 "file %s by file descriptor.\n",
567 unix_ea_name
, fsp_str_dbg(fsp
)));
568 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
570 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
571 unix_ea_name
, fname
));
572 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
575 /* Removing a non existent attribute always succeeds. */
576 if (ret
== -1 && errno
== ENOATTR
) {
577 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
583 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
584 DEBUG(10,("set_ea: setting ea name %s on file "
585 "%s by file descriptor.\n",
586 unix_ea_name
, fsp_str_dbg(fsp
)));
587 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
588 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
590 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
591 unix_ea_name
, fname
));
592 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
593 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
599 if (errno
== ENOTSUP
) {
600 return NT_STATUS_EAS_NOT_SUPPORTED
;
603 return map_nt_error_from_unix(errno
);
609 /****************************************************************************
610 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
611 ****************************************************************************/
613 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
615 struct ea_list
*ea_list_head
= NULL
;
616 size_t converted_size
, offset
= 0;
618 while (offset
+ 2 < data_size
) {
619 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
620 unsigned int namelen
= CVAL(pdata
,offset
);
622 offset
++; /* Go past the namelen byte. */
624 /* integer wrap paranioa. */
625 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
626 (offset
> data_size
) || (namelen
> data_size
) ||
627 (offset
+ namelen
>= data_size
)) {
630 /* Ensure the name is null terminated. */
631 if (pdata
[offset
+ namelen
] != '\0') {
634 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
636 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
637 "failed: %s", strerror(errno
)));
643 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
644 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
645 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
651 /****************************************************************************
652 Read one EA list entry from the buffer.
653 ****************************************************************************/
655 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
657 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
659 unsigned int namelen
;
660 size_t converted_size
;
670 eal
->ea
.flags
= CVAL(pdata
,0);
671 namelen
= CVAL(pdata
,1);
672 val_len
= SVAL(pdata
,2);
674 if (4 + namelen
+ 1 + val_len
> data_size
) {
678 /* Ensure the name is null terminated. */
679 if (pdata
[namelen
+ 4] != '\0') {
682 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
683 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
690 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
691 if (!eal
->ea
.value
.data
) {
695 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
697 /* Ensure we're null terminated just in case we print the value. */
698 eal
->ea
.value
.data
[val_len
] = '\0';
699 /* But don't count the null. */
700 eal
->ea
.value
.length
--;
703 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
706 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
707 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
712 /****************************************************************************
713 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
718 struct ea_list
*ea_list_head
= NULL
;
720 size_t bytes_used
= 0;
722 while (offset
< data_size
) {
723 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
729 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
730 offset
+= bytes_used
;
736 /****************************************************************************
737 Count the total EA size needed.
738 ****************************************************************************/
740 static size_t ea_list_size(struct ea_list
*ealist
)
743 struct ea_list
*listp
;
746 for (listp
= ealist
; listp
; listp
= listp
->next
) {
747 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
748 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
750 /* Add on 4 for total length. */
758 /****************************************************************************
759 Return a union of EA's from a file list and a list of names.
760 The TALLOC context for the two lists *MUST* be identical as we steal
761 memory from one list to add to another. JRA.
762 ****************************************************************************/
764 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
766 struct ea_list
*nlistp
, *flistp
;
768 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
769 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
770 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
776 /* Copy the data from this entry. */
777 nlistp
->ea
.flags
= flistp
->ea
.flags
;
778 nlistp
->ea
.value
= flistp
->ea
.value
;
781 nlistp
->ea
.flags
= 0;
782 ZERO_STRUCT(nlistp
->ea
.value
);
786 *total_ea_len
= ea_list_size(name_list
);
790 /****************************************************************************
791 Send the required number of replies back.
792 We assume all fields other than the data fields are
793 set correctly for the type of call.
794 HACK ! Always assumes smb_setup field is zero.
795 ****************************************************************************/
797 void send_trans2_replies(connection_struct
*conn
,
798 struct smb_request
*req
,
805 /* As we are using a protocol > LANMAN1 then the max_send
806 variable must have been set in the sessetupX call.
807 This takes precedence over the max_xmit field in the
808 global struct. These different max_xmit variables should
809 be merged as this is now too confusing */
811 int data_to_send
= datasize
;
812 int params_to_send
= paramsize
;
814 const char *pp
= params
;
815 const char *pd
= pdata
;
816 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
817 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
818 int data_alignment_offset
= 0;
819 bool overflow
= False
;
820 struct smbd_server_connection
*sconn
= req
->sconn
;
821 int max_send
= sconn
->smb1
.sessions
.max_send
;
823 /* Modify the data_to_send and datasize and set the error if
824 we're trying to send more than max_data_bytes. We still send
825 the part of the packet(s) that fit. Strange, but needed
828 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
829 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
830 max_data_bytes
, datasize
));
831 datasize
= data_to_send
= max_data_bytes
;
835 /* If there genuinely are no parameters or data to send just send the empty packet */
837 if(params_to_send
== 0 && data_to_send
== 0) {
838 reply_outbuf(req
, 10, 0);
839 show_msg((char *)req
->outbuf
);
840 if (!srv_send_smb(sconn
,
843 IS_CONN_ENCRYPTED(conn
),
845 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
847 TALLOC_FREE(req
->outbuf
);
851 /* When sending params and data ensure that both are nicely aligned */
852 /* Only do this alignment when there is also data to send - else
853 can cause NT redirector problems. */
855 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
856 data_alignment_offset
= 4 - (params_to_send
% 4);
858 /* Space is bufsize minus Netbios over TCP header minus SMB header */
859 /* The alignment_offset is to align the param bytes on an even byte
860 boundary. NT 4.0 Beta needs this to work correctly. */
862 useable_space
= max_send
- (smb_size
865 + data_alignment_offset
);
867 if (useable_space
< 0) {
868 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
869 "= %d!!!", useable_space
));
870 exit_server_cleanly("send_trans2_replies: Not enough space");
873 while (params_to_send
|| data_to_send
) {
874 /* Calculate whether we will totally or partially fill this packet */
876 total_sent_thistime
= params_to_send
+ data_to_send
;
878 /* We can never send more than useable_space */
880 * Note that 'useable_space' does not include the alignment offsets,
881 * but we must include the alignment offsets in the calculation of
882 * the length of the data we send over the wire, as the alignment offsets
883 * are sent here. Fix from Marc_Jacobsen@hp.com.
886 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
888 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
889 + data_alignment_offset
);
892 * We might have SMBtrans2s in req which was transferred to
893 * the outbuf, fix that.
895 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
897 /* Set total params and data to be sent */
898 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
899 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
901 /* Calculate how many parameters and data we can fit into
902 * this packet. Parameters get precedence
905 params_sent_thistime
= MIN(params_to_send
,useable_space
);
906 data_sent_thistime
= useable_space
- params_sent_thistime
;
907 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
909 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
911 /* smb_proff is the offset from the start of the SMB header to the
912 parameter bytes, however the first 4 bytes of outbuf are
913 the Netbios over TCP header. Thus use smb_base() to subtract
914 them from the calculation */
916 SSVAL(req
->outbuf
,smb_proff
,
917 ((smb_buf(req
->outbuf
)+alignment_offset
)
918 - smb_base(req
->outbuf
)));
920 if(params_sent_thistime
== 0)
921 SSVAL(req
->outbuf
,smb_prdisp
,0);
923 /* Absolute displacement of param bytes sent in this packet */
924 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
926 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
927 if(data_sent_thistime
== 0) {
928 SSVAL(req
->outbuf
,smb_droff
,0);
929 SSVAL(req
->outbuf
,smb_drdisp
, 0);
931 /* The offset of the data bytes is the offset of the
932 parameter bytes plus the number of parameters being sent this time */
933 SSVAL(req
->outbuf
, smb_droff
,
934 ((smb_buf(req
->outbuf
)+alignment_offset
)
935 - smb_base(req
->outbuf
))
936 + params_sent_thistime
+ data_alignment_offset
);
937 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
940 /* Initialize the padding for alignment */
942 if (alignment_offset
!= 0) {
943 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
946 /* Copy the param bytes into the packet */
948 if(params_sent_thistime
) {
949 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
950 params_sent_thistime
);
953 /* Copy in the data bytes */
954 if(data_sent_thistime
) {
955 if (data_alignment_offset
!= 0) {
956 memset((smb_buf(req
->outbuf
)+alignment_offset
+
957 params_sent_thistime
), 0,
958 data_alignment_offset
);
960 memcpy(smb_buf(req
->outbuf
)+alignment_offset
961 +params_sent_thistime
+data_alignment_offset
,
962 pd
,data_sent_thistime
);
965 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
966 params_sent_thistime
, data_sent_thistime
, useable_space
));
967 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
968 params_to_send
, data_to_send
, paramsize
, datasize
));
971 error_packet_set((char *)req
->outbuf
,
972 ERRDOS
,ERRbufferoverflow
,
973 STATUS_BUFFER_OVERFLOW
,
977 /* Send the packet */
978 show_msg((char *)req
->outbuf
);
979 if (!srv_send_smb(sconn
,
982 IS_CONN_ENCRYPTED(conn
),
984 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
986 TALLOC_FREE(req
->outbuf
);
988 pp
+= params_sent_thistime
;
989 pd
+= data_sent_thistime
;
991 params_to_send
-= params_sent_thistime
;
992 data_to_send
-= data_sent_thistime
;
995 if(params_to_send
< 0 || data_to_send
< 0) {
996 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
997 params_to_send
, data_to_send
));
1005 /****************************************************************************
1006 Reply to a TRANSACT2_OPEN.
1007 ****************************************************************************/
1009 static void call_trans2open(connection_struct
*conn
,
1010 struct smb_request
*req
,
1011 char **pparams
, int total_params
,
1012 char **ppdata
, int total_data
,
1013 unsigned int max_data_bytes
)
1015 struct smb_filename
*smb_fname
= NULL
;
1016 char *params
= *pparams
;
1017 char *pdata
= *ppdata
;
1020 bool oplock_request
;
1022 bool return_additional_info
;
1031 int fattr
=0,mtime
=0;
1032 SMB_INO_T inode
= 0;
1035 struct ea_list
*ea_list
= NULL
;
1040 uint32 create_disposition
;
1041 uint32 create_options
= 0;
1042 uint32_t private_flags
= 0;
1043 TALLOC_CTX
*ctx
= talloc_tos();
1046 * Ensure we have enough parameters to perform the operation.
1049 if (total_params
< 29) {
1050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1054 flags
= SVAL(params
, 0);
1055 deny_mode
= SVAL(params
, 2);
1056 open_attr
= SVAL(params
,6);
1057 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1058 if (oplock_request
) {
1059 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1063 return_additional_info
= BITSETW(params
,0);
1064 open_sattr
= SVAL(params
, 4);
1065 open_time
= make_unix_date3(params
+8);
1067 open_ofun
= SVAL(params
,12);
1068 open_size
= IVAL(params
,14);
1069 pname
= ¶ms
[28];
1072 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1076 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1077 total_params
- 28, STR_TERMINATE
,
1079 if (!NT_STATUS_IS_OK(status
)) {
1080 reply_nterror(req
, status
);
1084 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1085 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1086 (unsigned int)open_ofun
, open_size
));
1088 status
= filename_convert(ctx
,
1090 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1095 if (!NT_STATUS_IS_OK(status
)) {
1096 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1097 reply_botherror(req
,
1098 NT_STATUS_PATH_NOT_COVERED
,
1099 ERRSRV
, ERRbadpath
);
1102 reply_nterror(req
, status
);
1106 if (open_ofun
== 0) {
1107 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1111 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1113 &access_mask
, &share_mode
,
1114 &create_disposition
,
1117 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1121 /* Any data in this call is an EA list. */
1122 if (total_data
&& (total_data
!= 4)) {
1123 if (total_data
< 10) {
1124 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1128 if (IVAL(pdata
,0) > total_data
) {
1129 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1130 IVAL(pdata
,0), (unsigned int)total_data
));
1131 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1135 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1138 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1142 if (!lp_ea_support(SNUM(conn
))) {
1143 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1148 status
= SMB_VFS_CREATE_FILE(
1151 0, /* root_dir_fid */
1152 smb_fname
, /* fname */
1153 access_mask
, /* access_mask */
1154 share_mode
, /* share_access */
1155 create_disposition
, /* create_disposition*/
1156 create_options
, /* create_options */
1157 open_attr
, /* file_attributes */
1158 oplock_request
, /* oplock_request */
1159 open_size
, /* allocation_size */
1162 ea_list
, /* ea_list */
1164 &smb_action
); /* psbuf */
1166 if (!NT_STATUS_IS_OK(status
)) {
1167 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1168 /* We have re-scheduled this call. */
1171 reply_openerror(req
, status
);
1175 size
= get_file_size_stat(&smb_fname
->st
);
1176 fattr
= dos_mode(conn
, smb_fname
);
1177 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1178 inode
= smb_fname
->st
.st_ex_ino
;
1179 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1180 close_file(req
, fsp
, ERROR_CLOSE
);
1181 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1185 /* Realloc the size of parameters and data we will return */
1186 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1187 if(*pparams
== NULL
) {
1188 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1193 SSVAL(params
,0,fsp
->fnum
);
1194 SSVAL(params
,2,fattr
);
1195 srv_put_dos_date2(params
,4, mtime
);
1196 SIVAL(params
,8, (uint32
)size
);
1197 SSVAL(params
,12,deny_mode
);
1198 SSVAL(params
,14,0); /* open_type - file or directory. */
1199 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1201 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1202 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1205 SSVAL(params
,18,smb_action
);
1208 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1210 SIVAL(params
,20,inode
);
1211 SSVAL(params
,24,0); /* Padding. */
1213 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1214 fsp
->fsp_name
->base_name
);
1215 SIVAL(params
, 26, ea_size
);
1217 SIVAL(params
, 26, 0);
1220 /* Send the required number of replies */
1221 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1223 TALLOC_FREE(smb_fname
);
1226 /*********************************************************
1227 Routine to check if a given string matches exactly.
1228 as a special case a mask of "." does NOT match. That
1229 is required for correct wildcard semantics
1230 Case can be significant or not.
1231 **********************************************************/
1233 static bool exact_match(bool has_wild
,
1234 bool case_sensitive
,
1238 if (mask
[0] == '.' && mask
[1] == 0) {
1246 if (case_sensitive
) {
1247 return strcmp(str
,mask
)==0;
1249 return strcasecmp_m(str
,mask
) == 0;
1253 /****************************************************************************
1254 Return the filetype for UNIX extensions.
1255 ****************************************************************************/
1257 static uint32
unix_filetype(mode_t mode
)
1260 return UNIX_TYPE_FILE
;
1261 else if(S_ISDIR(mode
))
1262 return UNIX_TYPE_DIR
;
1264 else if(S_ISLNK(mode
))
1265 return UNIX_TYPE_SYMLINK
;
1268 else if(S_ISCHR(mode
))
1269 return UNIX_TYPE_CHARDEV
;
1272 else if(S_ISBLK(mode
))
1273 return UNIX_TYPE_BLKDEV
;
1276 else if(S_ISFIFO(mode
))
1277 return UNIX_TYPE_FIFO
;
1280 else if(S_ISSOCK(mode
))
1281 return UNIX_TYPE_SOCKET
;
1284 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1285 return UNIX_TYPE_UNKNOWN
;
1288 /****************************************************************************
1289 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1290 ****************************************************************************/
1292 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1294 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1295 const SMB_STRUCT_STAT
*psbuf
,
1297 enum perm_type ptype
,
1302 if (perms
== SMB_MODE_NO_CHANGE
) {
1303 if (!VALID_STAT(*psbuf
)) {
1304 return NT_STATUS_INVALID_PARAMETER
;
1306 *ret_perms
= psbuf
->st_ex_mode
;
1307 return NT_STATUS_OK
;
1311 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1312 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1313 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1314 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1315 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1316 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1317 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1318 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1319 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1321 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1324 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1327 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1332 /* Apply mode mask */
1333 ret
&= lp_create_mask(SNUM(conn
));
1334 /* Add in force bits */
1335 ret
|= lp_force_create_mode(SNUM(conn
));
1338 ret
&= lp_dir_mask(SNUM(conn
));
1339 /* Add in force bits */
1340 ret
|= lp_force_dir_mode(SNUM(conn
));
1342 case PERM_EXISTING_FILE
:
1343 /* Apply mode mask */
1344 ret
&= lp_security_mask(SNUM(conn
));
1345 /* Add in force bits */
1346 ret
|= lp_force_security_mode(SNUM(conn
));
1348 case PERM_EXISTING_DIR
:
1349 /* Apply mode mask */
1350 ret
&= lp_dir_security_mask(SNUM(conn
));
1351 /* Add in force bits */
1352 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1357 return NT_STATUS_OK
;
1360 /****************************************************************************
1361 Needed to show the msdfs symlinks as directories. Modifies psbuf
1362 to be a directory if it's a msdfs link.
1363 ****************************************************************************/
1365 static bool check_msdfs_link(connection_struct
*conn
,
1366 const char *pathname
,
1367 SMB_STRUCT_STAT
*psbuf
)
1369 int saved_errno
= errno
;
1370 if(lp_host_msdfs() &&
1371 lp_msdfs_root(SNUM(conn
)) &&
1372 is_msdfs_link(conn
, pathname
, psbuf
)) {
1374 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1377 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1378 errno
= saved_errno
;
1381 errno
= saved_errno
;
1386 /****************************************************************************
1387 Get a level dependent lanman2 dir entry.
1388 ****************************************************************************/
1390 struct smbd_dirptr_lanman2_state
{
1391 connection_struct
*conn
;
1392 uint32_t info_level
;
1393 bool check_mangled_names
;
1395 bool got_exact_match
;
1398 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1404 struct smbd_dirptr_lanman2_state
*state
=
1405 (struct smbd_dirptr_lanman2_state
*)private_data
;
1407 char mangled_name
[13]; /* mangled 8.3 name. */
1411 /* Mangle fname if it's an illegal name. */
1412 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1413 ok
= name_to_8_3(dname
, mangled_name
,
1414 true, state
->conn
->params
);
1418 fname
= mangled_name
;
1423 got_match
= exact_match(state
->has_wild
,
1424 state
->conn
->case_sensitive
,
1426 state
->got_exact_match
= got_match
;
1428 got_match
= mask_match(fname
, mask
,
1429 state
->conn
->case_sensitive
);
1432 if(!got_match
&& state
->check_mangled_names
&&
1433 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1435 * It turns out that NT matches wildcards against
1436 * both long *and* short names. This may explain some
1437 * of the wildcard wierdness from old DOS clients
1438 * that some people have been seeing.... JRA.
1440 /* Force the mangling into 8.3. */
1441 ok
= name_to_8_3(fname
, mangled_name
,
1442 false, state
->conn
->params
);
1447 got_match
= exact_match(state
->has_wild
,
1448 state
->conn
->case_sensitive
,
1449 mangled_name
, mask
);
1450 state
->got_exact_match
= got_match
;
1452 got_match
= mask_match(mangled_name
, mask
,
1453 state
->conn
->case_sensitive
);
1461 *_fname
= talloc_strdup(ctx
, fname
);
1462 if (*_fname
== NULL
) {
1469 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1471 struct smb_filename
*smb_fname
,
1474 struct smbd_dirptr_lanman2_state
*state
=
1475 (struct smbd_dirptr_lanman2_state
*)private_data
;
1476 bool ms_dfs_link
= false;
1479 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1480 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1481 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1482 "Couldn't lstat [%s] (%s)\n",
1483 smb_fname_str_dbg(smb_fname
),
1487 } else if (!VALID_STAT(smb_fname
->st
) &&
1488 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1489 /* Needed to show the msdfs symlinks as
1492 ms_dfs_link
= check_msdfs_link(state
->conn
,
1493 smb_fname
->base_name
,
1496 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1497 "Couldn't stat [%s] (%s)\n",
1498 smb_fname_str_dbg(smb_fname
),
1505 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1507 mode
= dos_mode(state
->conn
, smb_fname
);
1514 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1515 connection_struct
*conn
,
1517 uint32_t info_level
,
1518 struct ea_list
*name_list
,
1519 bool check_mangled_names
,
1520 bool requires_resume_key
,
1523 const struct smb_filename
*smb_fname
,
1524 int space_remaining
,
1531 uint64_t *last_entry_off
)
1533 char *p
, *q
, *pdata
= *ppdata
;
1535 uint64_t file_size
= 0;
1536 uint64_t allocation_size
= 0;
1537 uint64_t file_index
= 0;
1539 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1540 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1541 time_t c_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
);
1577 c_date
= convert_timespec_to_time_t(cdate_ts
);
1579 /* align the record */
1580 SMB_ASSERT(align
>= 1);
1582 off
= (int)PTR_DIFF(pdata
, base_data
);
1583 pad
= (off
+ (align
-1)) & ~(align
-1);
1586 if (pad
&& pad
> space_remaining
) {
1587 *out_of_space
= true;
1588 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1589 "for padding (wanted %u, had %d)\n",
1592 return false; /* Not finished - just out of space */
1596 /* initialize padding to 0 */
1598 memset(pdata
, 0, pad
);
1600 space_remaining
-= pad
;
1602 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1612 switch (info_level
) {
1613 case SMB_FIND_INFO_STANDARD
:
1614 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1615 if(requires_resume_key
) {
1619 srv_put_dos_date2(p
,0,create_date
);
1620 srv_put_dos_date2(p
,4,adate
);
1621 srv_put_dos_date2(p
,8,mdate
);
1622 SIVAL(p
,12,(uint32
)file_size
);
1623 SIVAL(p
,16,(uint32
)allocation_size
);
1627 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1628 p
+= ucs2_align(base_data
, p
, 0);
1630 len
= srvstr_push(base_data
, flags2
, p
,
1631 fname
, PTR_DIFF(end_data
, p
),
1633 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1635 SCVAL(nameptr
, -1, len
- 2);
1637 SCVAL(nameptr
, -1, 0);
1641 SCVAL(nameptr
, -1, len
- 1);
1643 SCVAL(nameptr
, -1, 0);
1649 case SMB_FIND_EA_SIZE
:
1650 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1651 if (requires_resume_key
) {
1655 srv_put_dos_date2(p
,0,create_date
);
1656 srv_put_dos_date2(p
,4,adate
);
1657 srv_put_dos_date2(p
,8,mdate
);
1658 SIVAL(p
,12,(uint32
)file_size
);
1659 SIVAL(p
,16,(uint32
)allocation_size
);
1662 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1663 smb_fname
->base_name
);
1664 SIVAL(p
,22,ea_size
); /* Extended attributes */
1668 len
= srvstr_push(base_data
, flags2
,
1669 p
, fname
, PTR_DIFF(end_data
, p
),
1670 STR_TERMINATE
| STR_NOALIGN
);
1671 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1684 SCVAL(nameptr
,0,len
);
1686 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1689 case SMB_FIND_EA_LIST
:
1691 struct ea_list
*file_list
= NULL
;
1694 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1698 if (requires_resume_key
) {
1702 srv_put_dos_date2(p
,0,create_date
);
1703 srv_put_dos_date2(p
,4,adate
);
1704 srv_put_dos_date2(p
,8,mdate
);
1705 SIVAL(p
,12,(uint32
)file_size
);
1706 SIVAL(p
,16,(uint32
)allocation_size
);
1708 p
+= 22; /* p now points to the EA area. */
1710 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1711 smb_fname
->base_name
,
1713 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1715 /* We need to determine if this entry will fit in the space available. */
1716 /* Max string size is 255 bytes. */
1717 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1718 *out_of_space
= true;
1719 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1720 "(wanted %u, had %d)\n",
1721 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1723 return False
; /* Not finished - just out of space */
1726 /* Push the ea_data followed by the name. */
1727 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1729 len
= srvstr_push(base_data
, flags2
,
1730 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1731 STR_TERMINATE
| STR_NOALIGN
);
1732 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1745 SCVAL(nameptr
,0,len
);
1747 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1751 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1753 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1755 SIVAL(p
,0,reskey
); p
+= 4;
1756 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1757 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1758 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1759 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1760 SOFF_T(p
,0,file_size
); p
+= 8;
1761 SOFF_T(p
,0,allocation_size
); p
+= 8;
1762 SIVAL(p
,0,mode
); p
+= 4;
1763 q
= p
; p
+= 4; /* q is placeholder for name length. */
1765 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1766 smb_fname
->base_name
);
1767 SIVAL(p
,0,ea_size
); /* Extended attributes */
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3
&& check_mangled_names
) {
1775 char mangled_name
[13]; /* mangled 8.3 name. */
1776 if (!name_to_8_3(fname
,mangled_name
,True
,
1778 /* Error - mangle failed ! */
1779 memset(mangled_name
,'\0',12);
1781 mangled_name
[12] = 0;
1782 len
= srvstr_push(base_data
, flags2
,
1783 p
+2, mangled_name
, 24,
1784 STR_UPPER
|STR_UNICODE
);
1786 memset(p
+ 2 + len
,'\0',24 - len
);
1793 len
= srvstr_push(base_data
, flags2
, p
,
1794 fname
, PTR_DIFF(end_data
, p
),
1795 STR_TERMINATE_ASCII
);
1799 len
= PTR_DIFF(p
, pdata
);
1800 pad
= (len
+ (align
-1)) & ~(align
-1);
1802 * offset to the next entry, the caller
1803 * will overwrite it for the last entry
1804 * that's why we always include the padding
1808 * set padding to zero
1811 memset(p
, 0, pad
- len
);
1818 case SMB_FIND_FILE_DIRECTORY_INFO
:
1819 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1821 SIVAL(p
,0,reskey
); p
+= 4;
1822 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1823 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1824 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1825 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1826 SOFF_T(p
,0,file_size
); p
+= 8;
1827 SOFF_T(p
,0,allocation_size
); p
+= 8;
1828 SIVAL(p
,0,mode
); p
+= 4;
1829 len
= srvstr_push(base_data
, flags2
,
1830 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1831 STR_TERMINATE_ASCII
);
1835 len
= PTR_DIFF(p
, pdata
);
1836 pad
= (len
+ (align
-1)) & ~(align
-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1844 * set padding to zero
1847 memset(p
, 0, pad
- len
);
1854 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1857 SIVAL(p
,0,reskey
); p
+= 4;
1858 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1859 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1862 SOFF_T(p
,0,file_size
); p
+= 8;
1863 SOFF_T(p
,0,allocation_size
); p
+= 8;
1864 SIVAL(p
,0,mode
); p
+= 4;
1865 q
= p
; p
+= 4; /* q is placeholder for name length. */
1867 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1868 smb_fname
->base_name
);
1869 SIVAL(p
,0,ea_size
); /* Extended attributes */
1872 len
= srvstr_push(base_data
, flags2
, p
,
1873 fname
, PTR_DIFF(end_data
, p
),
1874 STR_TERMINATE_ASCII
);
1878 len
= PTR_DIFF(p
, pdata
);
1879 pad
= (len
+ (align
-1)) & ~(align
-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1887 * set padding to zero
1890 memset(p
, 0, pad
- len
);
1897 case SMB_FIND_FILE_NAMES_INFO
:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1900 SIVAL(p
,0,reskey
); p
+= 4;
1902 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1903 acl on a dir (tridge) */
1904 len
= srvstr_push(base_data
, flags2
, p
,
1905 fname
, PTR_DIFF(end_data
, p
),
1906 STR_TERMINATE_ASCII
);
1910 len
= PTR_DIFF(p
, pdata
);
1911 pad
= (len
+ (align
-1)) & ~(align
-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1919 * set padding to zero
1922 memset(p
, 0, pad
- len
);
1929 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1932 SIVAL(p
,0,reskey
); p
+= 4;
1933 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1934 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1935 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1936 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1937 SOFF_T(p
,0,file_size
); p
+= 8;
1938 SOFF_T(p
,0,allocation_size
); p
+= 8;
1939 SIVAL(p
,0,mode
); p
+= 4;
1940 q
= p
; p
+= 4; /* q is placeholder for name length. */
1942 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1943 smb_fname
->base_name
);
1944 SIVAL(p
,0,ea_size
); /* Extended attributes */
1947 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1948 SBVAL(p
,0,file_index
); p
+= 8;
1949 len
= srvstr_push(base_data
, flags2
, p
,
1950 fname
, PTR_DIFF(end_data
, p
),
1951 STR_TERMINATE_ASCII
);
1955 len
= PTR_DIFF(p
, pdata
);
1956 pad
= (len
+ (align
-1)) & ~(align
-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1964 * set padding to zero
1967 memset(p
, 0, pad
- len
);
1974 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1976 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1978 SIVAL(p
,0,reskey
); p
+= 4;
1979 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1980 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1981 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1982 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1983 SOFF_T(p
,0,file_size
); p
+= 8;
1984 SOFF_T(p
,0,allocation_size
); p
+= 8;
1985 SIVAL(p
,0,mode
); p
+= 4;
1986 q
= p
; p
+= 4; /* q is placeholder for name length */
1988 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1989 smb_fname
->base_name
);
1990 SIVAL(p
,0,ea_size
); /* Extended attributes */
1993 /* Clear the short name buffer. This is
1994 * IMPORTANT as not doing so will trigger
1995 * a Win2k client bug. JRA.
1997 if (!was_8_3
&& check_mangled_names
) {
1998 char mangled_name
[13]; /* mangled 8.3 name. */
1999 if (!name_to_8_3(fname
,mangled_name
,True
,
2001 /* Error - mangle failed ! */
2002 memset(mangled_name
,'\0',12);
2004 mangled_name
[12] = 0;
2005 len
= srvstr_push(base_data
, flags2
,
2006 p
+2, mangled_name
, 24,
2007 STR_UPPER
|STR_UNICODE
);
2010 memset(p
+ 2 + len
,'\0',24 - len
);
2017 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2018 SBVAL(p
,0,file_index
); p
+= 8;
2019 len
= srvstr_push(base_data
, flags2
, p
,
2020 fname
, PTR_DIFF(end_data
, p
),
2021 STR_TERMINATE_ASCII
);
2025 len
= PTR_DIFF(p
, pdata
);
2026 pad
= (len
+ (align
-1)) & ~(align
-1);
2028 * offset to the next entry, the caller
2029 * will overwrite it for the last entry
2030 * that's why we always include the padding
2034 * set padding to zero
2037 memset(p
, 0, pad
- len
);
2044 /* CIFS UNIX Extension. */
2046 case SMB_FIND_FILE_UNIX
:
2047 case SMB_FIND_FILE_UNIX_INFO2
:
2049 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2051 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2053 if (info_level
== SMB_FIND_FILE_UNIX
) {
2054 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2055 p
= store_file_unix_basic(conn
, p
,
2056 NULL
, &smb_fname
->st
);
2057 len
= srvstr_push(base_data
, flags2
, p
,
2058 fname
, PTR_DIFF(end_data
, p
),
2061 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2062 p
= store_file_unix_basic_info2(conn
, p
,
2063 NULL
, &smb_fname
->st
);
2066 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2067 PTR_DIFF(end_data
, p
), 0);
2068 SIVAL(nameptr
, 0, len
);
2073 len
= PTR_DIFF(p
, pdata
);
2074 pad
= (len
+ (align
-1)) & ~(align
-1);
2076 * offset to the next entry, the caller
2077 * will overwrite it for the last entry
2078 * that's why we always include the padding
2082 * set padding to zero
2085 memset(p
, 0, pad
- len
);
2090 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2098 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2099 *out_of_space
= true;
2100 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2101 "(wanted %u, had %d)\n",
2102 (unsigned int)PTR_DIFF(p
,pdata
),
2104 return false; /* Not finished - just out of space */
2107 /* Setup the last entry pointer, as an offset from base_data */
2108 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2109 /* Advance the data pointer to the next slot */
2115 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2116 connection_struct
*conn
,
2117 struct dptr_struct
*dirptr
,
2119 const char *path_mask
,
2122 int requires_resume_key
,
2130 int space_remaining
,
2132 bool *got_exact_match
,
2133 int *_last_entry_off
,
2134 struct ea_list
*name_list
)
2137 const char *mask
= NULL
;
2138 long prev_dirpos
= 0;
2141 struct smb_filename
*smb_fname
= NULL
;
2142 struct smbd_dirptr_lanman2_state state
;
2144 uint64_t last_entry_off
= 0;
2148 state
.info_level
= info_level
;
2149 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2150 state
.has_wild
= dptr_has_wild(dirptr
);
2151 state
.got_exact_match
= false;
2153 *out_of_space
= false;
2154 *got_exact_match
= false;
2156 p
= strrchr_m(path_mask
,'/');
2167 ok
= smbd_dirptr_get_entry(ctx
,
2173 smbd_dirptr_lanman2_match_fn
,
2174 smbd_dirptr_lanman2_mode_fn
,
2184 *got_exact_match
= state
.got_exact_match
;
2186 ok
= smbd_marshall_dir_entry(ctx
,
2191 state
.check_mangled_names
,
2192 requires_resume_key
,
2205 TALLOC_FREE(smb_fname
);
2206 if (*out_of_space
) {
2207 dptr_SeekDir(dirptr
, prev_dirpos
);
2214 *_last_entry_off
= last_entry_off
;
2218 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2219 connection_struct
*conn
,
2220 struct dptr_struct
*dirptr
,
2222 const char *path_mask
,
2225 bool requires_resume_key
,
2231 int space_remaining
,
2233 bool *got_exact_match
,
2234 int *last_entry_off
,
2235 struct ea_list
*name_list
)
2238 const bool do_pad
= true;
2240 if (info_level
>= 1 && info_level
<= 3) {
2241 /* No alignment on earlier info levels. */
2245 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2246 path_mask
, dirtype
, info_level
,
2247 requires_resume_key
, dont_descend
, ask_sharemode
,
2249 ppdata
, base_data
, end_data
,
2251 out_of_space
, got_exact_match
,
2252 last_entry_off
, name_list
);
2255 /****************************************************************************
2256 Reply to a TRANS2_FINDFIRST.
2257 ****************************************************************************/
2259 static void call_trans2findfirst(connection_struct
*conn
,
2260 struct smb_request
*req
,
2261 char **pparams
, int total_params
,
2262 char **ppdata
, int total_data
,
2263 unsigned int max_data_bytes
)
2265 /* We must be careful here that we don't return more than the
2266 allowed number of data bytes. If this means returning fewer than
2267 maxentries then so be it. We assume that the redirector has
2268 enough room for the fixed number of parameter bytes it has
2270 struct smb_filename
*smb_dname
= NULL
;
2271 char *params
= *pparams
;
2272 char *pdata
= *ppdata
;
2276 uint16 findfirst_flags
;
2277 bool close_after_first
;
2279 bool requires_resume_key
;
2281 char *directory
= NULL
;
2284 int last_entry_off
=0;
2288 bool finished
= False
;
2289 bool dont_descend
= False
;
2290 bool out_of_space
= False
;
2291 int space_remaining
;
2292 bool mask_contains_wcard
= False
;
2293 struct ea_list
*ea_list
= NULL
;
2294 NTSTATUS ntstatus
= NT_STATUS_OK
;
2295 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2296 TALLOC_CTX
*ctx
= talloc_tos();
2297 struct dptr_struct
*dirptr
= NULL
;
2298 struct smbd_server_connection
*sconn
= req
->sconn
;
2299 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
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 info_level
= SVAL(params
,6);
2314 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2315 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2316 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2317 info_level
, max_data_bytes
));
2320 /* W2K3 seems to treat zero as 1. */
2324 switch (info_level
) {
2325 case SMB_FIND_INFO_STANDARD
:
2326 case SMB_FIND_EA_SIZE
:
2327 case SMB_FIND_EA_LIST
:
2328 case SMB_FIND_FILE_DIRECTORY_INFO
:
2329 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2330 case SMB_FIND_FILE_NAMES_INFO
:
2331 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2332 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2333 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2335 case SMB_FIND_FILE_UNIX
:
2336 case SMB_FIND_FILE_UNIX_INFO2
:
2337 /* Always use filesystem for UNIX mtime query. */
2338 ask_sharemode
= false;
2339 if (!lp_unix_extensions()) {
2340 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2343 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2346 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2350 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2351 params
+12, total_params
- 12,
2352 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2353 if (!NT_STATUS_IS_OK(ntstatus
)) {
2354 reply_nterror(req
, ntstatus
);
2358 ntstatus
= filename_convert(ctx
, conn
,
2359 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2362 &mask_contains_wcard
,
2364 if (!NT_STATUS_IS_OK(ntstatus
)) {
2365 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2366 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2367 ERRSRV
, ERRbadpath
);
2370 reply_nterror(req
, ntstatus
);
2374 mask
= smb_dname
->original_lcomp
;
2376 directory
= smb_dname
->base_name
;
2378 p
= strrchr_m(directory
,'/');
2380 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2381 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2382 mask
= talloc_strdup(ctx
,"*");
2384 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2387 mask_contains_wcard
= True
;
2393 if (p
== NULL
|| p
== directory
) {
2394 /* Ensure we don't have a directory name of "". */
2395 directory
= talloc_strdup(talloc_tos(), ".");
2397 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2402 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2404 if (info_level
== SMB_FIND_EA_LIST
) {
2407 if (total_data
< 4) {
2408 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2412 ea_size
= IVAL(pdata
,0);
2413 if (ea_size
!= total_data
) {
2414 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2415 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2416 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2420 if (!lp_ea_support(SNUM(conn
))) {
2421 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2425 /* Pull out the list of names. */
2426 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2428 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2433 *ppdata
= (char *)SMB_REALLOC(
2434 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2435 if(*ppdata
== NULL
) {
2436 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2440 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2442 /* Realloc the params space */
2443 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2444 if (*pparams
== NULL
) {
2445 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2450 /* Save the wildcard match and attribs we are using on this directory -
2451 needed as lanman2 assumes these are being saved between calls */
2453 ntstatus
= dptr_create(conn
,
2460 mask_contains_wcard
,
2464 if (!NT_STATUS_IS_OK(ntstatus
)) {
2465 reply_nterror(req
, ntstatus
);
2469 dptr_num
= dptr_dnum(dirptr
);
2470 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2472 /* Initialize per TRANS2_FIND_FIRST operation data */
2473 dptr_init_search_op(dirptr
);
2475 /* We don't need to check for VOL here as this is returned by
2476 a different TRANS2 call. */
2478 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2479 directory
,lp_dontdescend(SNUM(conn
))));
2480 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2481 dont_descend
= True
;
2484 space_remaining
= max_data_bytes
;
2485 out_of_space
= False
;
2487 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2488 bool got_exact_match
= False
;
2490 /* this is a heuristic to avoid seeking the dirptr except when
2491 absolutely necessary. It allows for a filename of about 40 chars */
2492 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2493 out_of_space
= True
;
2496 finished
= !get_lanman2_dir_entry(ctx
,
2500 mask
,dirtype
,info_level
,
2501 requires_resume_key
,dont_descend
,
2504 space_remaining
, &out_of_space
,
2506 &last_entry_off
, ea_list
);
2509 if (finished
&& out_of_space
)
2512 if (!finished
&& !out_of_space
)
2516 * As an optimisation if we know we aren't looking
2517 * for a wildcard name (ie. the name matches the wildcard exactly)
2518 * then we can finish on any (first) match.
2519 * This speeds up large directory searches. JRA.
2525 /* Ensure space_remaining never goes -ve. */
2526 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2527 space_remaining
= 0;
2528 out_of_space
= true;
2530 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2534 /* Check if we can close the dirptr */
2535 if(close_after_first
|| (finished
&& close_if_end
)) {
2536 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2537 dptr_close(sconn
, &dptr_num
);
2541 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2542 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2543 * the protocol level is less than NT1. Tested with smbclient. JRA.
2544 * This should fix the OS/2 client bug #2335.
2547 if(numentries
== 0) {
2548 dptr_close(sconn
, &dptr_num
);
2549 if (get_Protocol() < PROTOCOL_NT1
) {
2550 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2553 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2554 ERRDOS
, ERRbadfile
);
2559 /* At this point pdata points to numentries directory entries. */
2561 /* Set up the return parameter block */
2562 SSVAL(params
,0,dptr_num
);
2563 SSVAL(params
,2,numentries
);
2564 SSVAL(params
,4,finished
);
2565 SSVAL(params
,6,0); /* Never an EA error */
2566 SSVAL(params
,8,last_entry_off
);
2568 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2571 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2572 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2574 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2578 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2579 smb_fn_name(req
->cmd
),
2580 mask
, directory
, dirtype
, numentries
) );
2583 * Force a name mangle here to ensure that the
2584 * mask as an 8.3 name is top of the mangled cache.
2585 * The reasons for this are subtle. Don't remove
2586 * this code unless you know what you are doing
2587 * (see PR#13758). JRA.
2590 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2591 char mangled_name
[13];
2592 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2595 TALLOC_FREE(smb_dname
);
2599 /****************************************************************************
2600 Reply to a TRANS2_FINDNEXT.
2601 ****************************************************************************/
2603 static void call_trans2findnext(connection_struct
*conn
,
2604 struct smb_request
*req
,
2605 char **pparams
, int total_params
,
2606 char **ppdata
, int total_data
,
2607 unsigned int max_data_bytes
)
2609 /* We must be careful here that we don't return more than the
2610 allowed number of data bytes. If this means returning fewer than
2611 maxentries then so be it. We assume that the redirector has
2612 enough room for the fixed number of parameter bytes it has
2614 char *params
= *pparams
;
2615 char *pdata
= *ppdata
;
2621 uint16 findnext_flags
;
2622 bool close_after_request
;
2624 bool requires_resume_key
;
2626 bool mask_contains_wcard
= False
;
2627 char *resume_name
= NULL
;
2628 const char *mask
= NULL
;
2629 const char *directory
= NULL
;
2633 int i
, last_entry_off
=0;
2634 bool finished
= False
;
2635 bool dont_descend
= False
;
2636 bool out_of_space
= False
;
2637 int space_remaining
;
2638 struct ea_list
*ea_list
= NULL
;
2639 NTSTATUS ntstatus
= NT_STATUS_OK
;
2640 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2641 TALLOC_CTX
*ctx
= talloc_tos();
2642 struct dptr_struct
*dirptr
;
2643 struct smbd_server_connection
*sconn
= req
->sconn
;
2645 if (total_params
< 13) {
2646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2650 dptr_num
= SVAL(params
,0);
2651 maxentries
= SVAL(params
,2);
2652 info_level
= SVAL(params
,4);
2653 resume_key
= IVAL(params
,6);
2654 findnext_flags
= SVAL(params
,10);
2655 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2656 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2657 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2658 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2660 if (!continue_bit
) {
2661 /* We only need resume_name if continue_bit is zero. */
2662 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2664 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2665 &mask_contains_wcard
);
2666 if (!NT_STATUS_IS_OK(ntstatus
)) {
2667 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2668 complain (it thinks we're asking for the directory above the shared
2669 path or an invalid name). Catch this as the resume name is only compared, never used in
2670 a file access. JRA. */
2671 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2672 &resume_name
, params
+12,
2676 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2677 reply_nterror(req
, ntstatus
);
2683 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2684 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2685 resume_key = %d resume name = %s continue=%d level = %d\n",
2686 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2687 requires_resume_key
, resume_key
,
2688 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2691 /* W2K3 seems to treat zero as 1. */
2695 switch (info_level
) {
2696 case SMB_FIND_INFO_STANDARD
:
2697 case SMB_FIND_EA_SIZE
:
2698 case SMB_FIND_EA_LIST
:
2699 case SMB_FIND_FILE_DIRECTORY_INFO
:
2700 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2701 case SMB_FIND_FILE_NAMES_INFO
:
2702 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2703 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2704 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2706 case SMB_FIND_FILE_UNIX
:
2707 case SMB_FIND_FILE_UNIX_INFO2
:
2708 /* Always use filesystem for UNIX mtime query. */
2709 ask_sharemode
= false;
2710 if (!lp_unix_extensions()) {
2711 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2716 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2720 if (info_level
== SMB_FIND_EA_LIST
) {
2723 if (total_data
< 4) {
2724 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2728 ea_size
= IVAL(pdata
,0);
2729 if (ea_size
!= total_data
) {
2730 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2731 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2732 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2736 if (!lp_ea_support(SNUM(conn
))) {
2737 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2741 /* Pull out the list of names. */
2742 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2749 *ppdata
= (char *)SMB_REALLOC(
2750 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2751 if(*ppdata
== NULL
) {
2752 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2757 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2759 /* Realloc the params space */
2760 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2761 if(*pparams
== NULL
) {
2762 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2768 /* Check that the dptr is valid */
2769 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2770 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2774 directory
= dptr_path(sconn
, dptr_num
);
2776 /* Get the wildcard mask from the dptr */
2777 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2778 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2779 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2785 /* Get the attr mask from the dptr */
2786 dirtype
= dptr_attr(sconn
, dptr_num
);
2788 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2789 dptr_num
, mask
, dirtype
,
2791 dptr_TellDir(dirptr
)));
2793 /* Initialize per TRANS2_FIND_NEXT operation data */
2794 dptr_init_search_op(dirptr
);
2796 /* We don't need to check for VOL here as this is returned by
2797 a different TRANS2 call. */
2799 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2800 directory
,lp_dontdescend(SNUM(conn
))));
2801 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2802 dont_descend
= True
;
2805 space_remaining
= max_data_bytes
;
2806 out_of_space
= False
;
2809 * Seek to the correct position. We no longer use the resume key but
2810 * depend on the last file name instead.
2813 if(!continue_bit
&& resume_name
&& *resume_name
) {
2816 long current_pos
= 0;
2818 * Remember, name_to_8_3 is called by
2819 * get_lanman2_dir_entry(), so the resume name
2820 * could be mangled. Ensure we check the unmangled name.
2823 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2824 char *new_resume_name
= NULL
;
2825 mangle_lookup_name_from_8_3(ctx
,
2829 if (new_resume_name
) {
2830 resume_name
= new_resume_name
;
2835 * Fix for NT redirector problem triggered by resume key indexes
2836 * changing between directory scans. We now return a resume key of 0
2837 * and instead look for the filename to continue from (also given
2838 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2839 * findfirst/findnext (as is usual) then the directory pointer
2840 * should already be at the correct place.
2843 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2844 } /* end if resume_name && !continue_bit */
2846 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2847 bool got_exact_match
= False
;
2849 /* this is a heuristic to avoid seeking the dirptr except when
2850 absolutely necessary. It allows for a filename of about 40 chars */
2851 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2852 out_of_space
= True
;
2855 finished
= !get_lanman2_dir_entry(ctx
,
2859 mask
,dirtype
,info_level
,
2860 requires_resume_key
,dont_descend
,
2863 space_remaining
, &out_of_space
,
2865 &last_entry_off
, ea_list
);
2868 if (finished
&& out_of_space
)
2871 if (!finished
&& !out_of_space
)
2875 * As an optimisation if we know we aren't looking
2876 * for a wildcard name (ie. the name matches the wildcard exactly)
2877 * then we can finish on any (first) match.
2878 * This speeds up large directory searches. JRA.
2884 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2887 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2888 smb_fn_name(req
->cmd
),
2889 mask
, directory
, dirtype
, numentries
) );
2891 /* Check if we can close the dirptr */
2892 if(close_after_request
|| (finished
&& close_if_end
)) {
2893 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2894 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2897 /* Set up the return parameter block */
2898 SSVAL(params
,0,numentries
);
2899 SSVAL(params
,2,finished
);
2900 SSVAL(params
,4,0); /* Never an EA error */
2901 SSVAL(params
,6,last_entry_off
);
2903 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2909 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2911 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2915 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2917 SMB_ASSERT(extended_info
!= NULL
);
2919 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2920 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2921 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2922 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2923 #ifdef SAMBA_VERSION_REVISION
2924 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2926 extended_info
->samba_subversion
= 0;
2927 #ifdef SAMBA_VERSION_RC_RELEASE
2928 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2930 #ifdef SAMBA_VERSION_PRE_RELEASE
2931 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2934 #ifdef SAMBA_VERSION_VENDOR_PATCH
2935 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2937 extended_info
->samba_gitcommitdate
= 0;
2938 #ifdef SAMBA_VERSION_COMMIT_TIME
2939 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2942 memset(extended_info
->samba_version_string
, 0,
2943 sizeof(extended_info
->samba_version_string
));
2945 snprintf (extended_info
->samba_version_string
,
2946 sizeof(extended_info
->samba_version_string
),
2947 "%s", samba_version_string());
2950 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2951 TALLOC_CTX
*mem_ctx
,
2952 uint16_t info_level
,
2954 unsigned int max_data_bytes
,
2958 char *pdata
, *end_data
;
2959 int data_len
= 0, len
;
2960 const char *vname
= volume_label(SNUM(conn
));
2961 int snum
= SNUM(conn
);
2962 char *fstype
= lp_fstype(SNUM(conn
));
2963 uint32 additional_flags
= 0;
2964 struct smb_filename smb_fname_dot
;
2968 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2969 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2970 "info level (0x%x) on IPC$.\n",
2971 (unsigned int)info_level
));
2972 return NT_STATUS_ACCESS_DENIED
;
2976 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2978 ZERO_STRUCT(smb_fname_dot
);
2979 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2981 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2982 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2983 return map_nt_error_from_unix(errno
);
2986 st
= smb_fname_dot
.st
;
2988 *ppdata
= (char *)SMB_REALLOC(
2989 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2990 if (*ppdata
== NULL
) {
2991 return NT_STATUS_NO_MEMORY
;
2995 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2996 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2998 switch (info_level
) {
2999 case SMB_INFO_ALLOCATION
:
3001 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3003 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3004 return map_nt_error_from_unix(errno
);
3007 block_size
= lp_block_size(snum
);
3008 if (bsize
< block_size
) {
3009 uint64_t factor
= block_size
/bsize
;
3014 if (bsize
> block_size
) {
3015 uint64_t factor
= bsize
/block_size
;
3020 bytes_per_sector
= 512;
3021 sectors_per_unit
= bsize
/bytes_per_sector
;
3023 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3024 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3025 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3027 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3028 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3029 SIVAL(pdata
,l1_cUnit
,dsize
);
3030 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3031 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3035 case SMB_INFO_VOLUME
:
3036 /* Return volume name */
3038 * Add volume serial number - hash of a combination of
3039 * the called hostname and the service name.
3041 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3043 * Win2k3 and previous mess this up by sending a name length
3044 * one byte short. I believe only older clients (OS/2 Win9x) use
3045 * this call so try fixing this by adding a terminating null to
3046 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3050 pdata
+l2_vol_szVolLabel
, vname
,
3051 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3052 STR_NOALIGN
|STR_TERMINATE
);
3053 SCVAL(pdata
,l2_vol_cch
,len
);
3054 data_len
= l2_vol_szVolLabel
+ len
;
3055 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3056 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3060 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3061 case SMB_FS_ATTRIBUTE_INFORMATION
:
3063 additional_flags
= 0;
3064 #if defined(HAVE_SYS_QUOTAS)
3065 additional_flags
|= FILE_VOLUME_QUOTAS
;
3068 if(lp_nt_acl_support(SNUM(conn
))) {
3069 additional_flags
|= FILE_PERSISTENT_ACLS
;
3072 /* Capabilities are filled in at connection time through STATVFS call */
3073 additional_flags
|= conn
->fs_capabilities
;
3074 additional_flags
|= lp_parm_int(conn
->params
->service
,
3075 "share", "fake_fscaps",
3078 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3079 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3080 additional_flags
); /* FS ATTRIBUTES */
3082 SIVAL(pdata
,4,255); /* Max filename component length */
3083 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3084 and will think we can't do long filenames */
3085 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3086 PTR_DIFF(end_data
, pdata
+12),
3089 data_len
= 12 + len
;
3092 case SMB_QUERY_FS_LABEL_INFO
:
3093 case SMB_FS_LABEL_INFORMATION
:
3094 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3095 PTR_DIFF(end_data
, pdata
+4), 0);
3100 case SMB_QUERY_FS_VOLUME_INFO
:
3101 case SMB_FS_VOLUME_INFORMATION
:
3104 * Add volume serial number - hash of a combination of
3105 * the called hostname and the service name.
3107 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3108 (str_checksum(get_local_machine_name())<<16));
3110 /* Max label len is 32 characters. */
3111 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3112 PTR_DIFF(end_data
, pdata
+18),
3114 SIVAL(pdata
,12,len
);
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3118 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3121 case SMB_QUERY_FS_SIZE_INFO
:
3122 case SMB_FS_SIZE_INFORMATION
:
3124 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3126 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3127 return map_nt_error_from_unix(errno
);
3129 block_size
= lp_block_size(snum
);
3130 if (bsize
< block_size
) {
3131 uint64_t factor
= block_size
/bsize
;
3136 if (bsize
> block_size
) {
3137 uint64_t factor
= bsize
/block_size
;
3142 bytes_per_sector
= 512;
3143 sectors_per_unit
= bsize
/bytes_per_sector
;
3144 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3145 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3146 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3147 SBIG_UINT(pdata
,0,dsize
);
3148 SBIG_UINT(pdata
,8,dfree
);
3149 SIVAL(pdata
,16,sectors_per_unit
);
3150 SIVAL(pdata
,20,bytes_per_sector
);
3154 case SMB_FS_FULL_SIZE_INFORMATION
:
3156 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3158 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3159 return map_nt_error_from_unix(errno
);
3161 block_size
= lp_block_size(snum
);
3162 if (bsize
< block_size
) {
3163 uint64_t factor
= block_size
/bsize
;
3168 if (bsize
> block_size
) {
3169 uint64_t factor
= bsize
/block_size
;
3174 bytes_per_sector
= 512;
3175 sectors_per_unit
= bsize
/bytes_per_sector
;
3176 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3177 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3178 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3179 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3180 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3181 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3182 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3183 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3187 case SMB_QUERY_FS_DEVICE_INFO
:
3188 case SMB_FS_DEVICE_INFORMATION
:
3190 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3192 if (!CAN_WRITE(conn
)) {
3193 characteristics
|= FILE_READ_ONLY_DEVICE
;
3196 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3197 SIVAL(pdata
,4,characteristics
);
3201 #ifdef HAVE_SYS_QUOTAS
3202 case SMB_FS_QUOTA_INFORMATION
:
3204 * what we have to send --metze:
3206 * Unknown1: 24 NULL bytes
3207 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3208 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3209 * Quota Flags: 2 byte :
3210 * Unknown3: 6 NULL bytes
3214 * details for Quota Flags:
3216 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3217 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3218 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3219 * 0x0001 Enable Quotas: enable quota for this fs
3223 /* we need to fake up a fsp here,
3224 * because its not send in this call
3227 SMB_NTQUOTA_STRUCT quotas
;
3230 ZERO_STRUCT(quotas
);
3236 if (get_current_uid(conn
) != 0) {
3237 DEBUG(0,("set_user_quota: access_denied "
3238 "service [%s] user [%s]\n",
3239 lp_servicename(SNUM(conn
)),
3240 conn
->session_info
->unix_info
->unix_name
));
3241 return NT_STATUS_ACCESS_DENIED
;
3244 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3245 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3246 return map_nt_error_from_unix(errno
);
3251 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3252 lp_servicename(SNUM(conn
))));
3254 /* Unknown1 24 NULL bytes*/
3255 SBIG_UINT(pdata
,0,(uint64_t)0);
3256 SBIG_UINT(pdata
,8,(uint64_t)0);
3257 SBIG_UINT(pdata
,16,(uint64_t)0);
3259 /* Default Soft Quota 8 bytes */
3260 SBIG_UINT(pdata
,24,quotas
.softlim
);
3262 /* Default Hard Quota 8 bytes */
3263 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3265 /* Quota flag 2 bytes */
3266 SSVAL(pdata
,40,quotas
.qflags
);
3268 /* Unknown3 6 NULL bytes */
3274 #endif /* HAVE_SYS_QUOTAS */
3275 case SMB_FS_OBJECTID_INFORMATION
:
3277 unsigned char objid
[16];
3278 struct smb_extended_info extended_info
;
3279 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3280 samba_extended_info_version (&extended_info
);
3281 SIVAL(pdata
,16,extended_info
.samba_magic
);
3282 SIVAL(pdata
,20,extended_info
.samba_version
);
3283 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3284 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3285 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3291 * Query the version and capabilities of the CIFS UNIX extensions
3295 case SMB_QUERY_CIFS_UNIX_INFO
:
3297 bool large_write
= lp_min_receive_file_size() &&
3298 !srv_is_signing_active(conn
->sconn
);
3299 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3300 int encrypt_caps
= 0;
3302 if (!lp_unix_extensions()) {
3303 return NT_STATUS_INVALID_LEVEL
;
3306 switch (conn
->encrypt_level
) {
3312 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3315 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3316 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3317 large_write
= false;
3323 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3324 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3326 /* We have POSIX ACLs, pathname, encryption,
3327 * large read/write, and locking capability. */
3329 SBIG_UINT(pdata
,4,((uint64_t)(
3330 CIFS_UNIX_POSIX_ACLS_CAP
|
3331 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3332 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3333 CIFS_UNIX_EXTATTR_CAP
|
3334 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3336 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3338 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3342 case SMB_QUERY_POSIX_FS_INFO
:
3345 vfs_statvfs_struct svfs
;
3347 if (!lp_unix_extensions()) {
3348 return NT_STATUS_INVALID_LEVEL
;
3351 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3355 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3356 SIVAL(pdata
,4,svfs
.BlockSize
);
3357 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3358 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3359 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3360 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3361 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3362 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3363 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3365 } else if (rc
== EOPNOTSUPP
) {
3366 return NT_STATUS_INVALID_LEVEL
;
3367 #endif /* EOPNOTSUPP */
3369 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3370 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3375 case SMB_QUERY_POSIX_WHOAMI
:
3381 if (!lp_unix_extensions()) {
3382 return NT_STATUS_INVALID_LEVEL
;
3385 if (max_data_bytes
< 40) {
3386 return NT_STATUS_BUFFER_TOO_SMALL
;
3389 /* We ARE guest if global_sid_Builtin_Guests is
3390 * in our list of SIDs.
3392 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3393 conn
->session_info
->security_token
)) {
3394 flags
|= SMB_WHOAMI_GUEST
;
3397 /* We are NOT guest if global_sid_Authenticated_Users
3398 * is in our list of SIDs.
3400 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3401 conn
->session_info
->security_token
)) {
3402 flags
&= ~SMB_WHOAMI_GUEST
;
3405 /* NOTE: 8 bytes for UID/GID, irrespective of native
3406 * platform size. This matches
3407 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3409 data_len
= 4 /* flags */
3416 + 4 /* pad/reserved */
3417 + (conn
->session_info
->unix_token
->ngroups
* 8)
3419 + (conn
->session_info
->security_token
->num_sids
*
3423 SIVAL(pdata
, 0, flags
);
3424 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3426 (uint64_t)conn
->session_info
->unix_token
->uid
);
3427 SBIG_UINT(pdata
, 16,
3428 (uint64_t)conn
->session_info
->unix_token
->gid
);
3431 if (data_len
>= max_data_bytes
) {
3432 /* Potential overflow, skip the GIDs and SIDs. */
3434 SIVAL(pdata
, 24, 0); /* num_groups */
3435 SIVAL(pdata
, 28, 0); /* num_sids */
3436 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3437 SIVAL(pdata
, 36, 0); /* reserved */
3443 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3444 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3446 /* We walk the SID list twice, but this call is fairly
3447 * infrequent, and I don't expect that it's performance
3448 * sensitive -- jpeach
3450 for (i
= 0, sid_bytes
= 0;
3451 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3452 sid_bytes
+= ndr_size_dom_sid(
3453 &conn
->session_info
->security_token
->sids
[i
],
3457 /* SID list byte count */
3458 SIVAL(pdata
, 32, sid_bytes
);
3460 /* 4 bytes pad/reserved - must be zero */
3461 SIVAL(pdata
, 36, 0);
3465 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3466 SBIG_UINT(pdata
, data_len
,
3467 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3473 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3474 int sid_len
= ndr_size_dom_sid(
3475 &conn
->session_info
->security_token
->sids
[i
],
3478 sid_linearize(pdata
+ data_len
, sid_len
,
3479 &conn
->session_info
->security_token
->sids
[i
]);
3480 data_len
+= sid_len
;
3486 case SMB_MAC_QUERY_FS_INFO
:
3488 * Thursby MAC extension... ONLY on NTFS filesystems
3489 * once we do streams then we don't need this
3491 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3493 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3498 return NT_STATUS_INVALID_LEVEL
;
3501 *ret_data_len
= data_len
;
3502 return NT_STATUS_OK
;
3505 /****************************************************************************
3506 Reply to a TRANS2_QFSINFO (query filesystem info).
3507 ****************************************************************************/
3509 static void call_trans2qfsinfo(connection_struct
*conn
,
3510 struct smb_request
*req
,
3511 char **pparams
, int total_params
,
3512 char **ppdata
, int total_data
,
3513 unsigned int max_data_bytes
)
3515 char *params
= *pparams
;
3516 uint16_t info_level
;
3520 if (total_params
< 2) {
3521 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3525 info_level
= SVAL(params
,0);
3527 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3528 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3529 DEBUG(0,("call_trans2qfsinfo: encryption required "
3530 "and info level 0x%x sent.\n",
3531 (unsigned int)info_level
));
3532 exit_server_cleanly("encryption required "
3538 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3540 status
= smbd_do_qfsinfo(conn
, req
,
3545 if (!NT_STATUS_IS_OK(status
)) {
3546 reply_nterror(req
, status
);
3550 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3553 DEBUG( 4, ( "%s info_level = %d\n",
3554 smb_fn_name(req
->cmd
), info_level
) );
3559 /****************************************************************************
3560 Reply to a TRANS2_SETFSINFO (set filesystem info).
3561 ****************************************************************************/
3563 static void call_trans2setfsinfo(connection_struct
*conn
,
3564 struct smb_request
*req
,
3565 char **pparams
, int total_params
,
3566 char **ppdata
, int total_data
,
3567 unsigned int max_data_bytes
)
3569 struct smbd_server_connection
*sconn
= req
->sconn
;
3570 char *pdata
= *ppdata
;
3571 char *params
= *pparams
;
3574 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3577 if (total_params
< 4) {
3578 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3580 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3584 info_level
= SVAL(params
,2);
3587 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3588 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3589 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3590 "info level (0x%x) on IPC$.\n",
3591 (unsigned int)info_level
));
3592 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3597 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3598 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3599 DEBUG(0,("call_trans2setfsinfo: encryption required "
3600 "and info level 0x%x sent.\n",
3601 (unsigned int)info_level
));
3602 exit_server_cleanly("encryption required "
3608 switch(info_level
) {
3609 case SMB_SET_CIFS_UNIX_INFO
:
3610 if (!lp_unix_extensions()) {
3612 NT_STATUS_INVALID_LEVEL
);
3616 /* There should be 12 bytes of capabilities set. */
3617 if (total_data
< 8) {
3620 NT_STATUS_INVALID_PARAMETER
);
3623 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3624 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3625 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3626 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3627 /* Just print these values for now. */
3628 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3629 "major = %u, minor = %u cap_low = 0x%x, "
3631 (unsigned int)sconn
->
3632 smb1
.unix_info
.client_major
,
3633 (unsigned int)sconn
->
3634 smb1
.unix_info
.client_minor
,
3635 (unsigned int)sconn
->
3636 smb1
.unix_info
.client_cap_low
,
3637 (unsigned int)sconn
->
3638 smb1
.unix_info
.client_cap_high
));
3640 /* Here is where we must switch to posix pathname processing... */
3641 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3642 lp_set_posix_pathnames();
3643 mangle_change_to_posix();
3646 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3647 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3648 /* Client that knows how to do posix locks,
3649 * but not posix open/mkdir operations. Set a
3650 * default type for read/write checks. */
3652 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3657 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3660 size_t param_len
= 0;
3661 size_t data_len
= total_data
;
3663 if (!lp_unix_extensions()) {
3666 NT_STATUS_INVALID_LEVEL
);
3670 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3673 NT_STATUS_NOT_SUPPORTED
);
3677 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3678 DEBUG( 2,("call_trans2setfsinfo: "
3679 "request transport encryption disabled"
3680 "with 'fork echo handler = yes'\n"));
3683 NT_STATUS_NOT_SUPPORTED
);
3687 DEBUG( 4,("call_trans2setfsinfo: "
3688 "request transport encryption.\n"));
3690 status
= srv_request_encryption_setup(conn
,
3691 (unsigned char **)ppdata
,
3693 (unsigned char **)pparams
,
3696 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3697 !NT_STATUS_IS_OK(status
)) {
3698 reply_nterror(req
, status
);
3702 send_trans2_replies(conn
, req
,
3709 if (NT_STATUS_IS_OK(status
)) {
3710 /* Server-side transport
3711 * encryption is now *on*. */
3712 status
= srv_encryption_start(conn
);
3713 if (!NT_STATUS_IS_OK(status
)) {
3714 char *reason
= talloc_asprintf(talloc_tos(),
3715 "Failure in setting "
3716 "up encrypted transport: %s",
3718 exit_server_cleanly(reason
);
3724 case SMB_FS_QUOTA_INFORMATION
:
3726 files_struct
*fsp
= NULL
;
3727 SMB_NTQUOTA_STRUCT quotas
;
3729 ZERO_STRUCT(quotas
);
3732 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3733 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3734 lp_servicename(SNUM(conn
)),
3735 conn
->session_info
->unix_info
->unix_name
));
3736 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3740 /* note: normaly there're 48 bytes,
3741 * but we didn't use the last 6 bytes for now
3744 fsp
= file_fsp(req
, SVAL(params
,0));
3746 if (!check_fsp_ntquota_handle(conn
, req
,
3748 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3750 req
, NT_STATUS_INVALID_HANDLE
);
3754 if (total_data
< 42) {
3755 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3759 NT_STATUS_INVALID_PARAMETER
);
3763 /* unknown_1 24 NULL bytes in pdata*/
3765 /* the soft quotas 8 bytes (uint64_t)*/
3766 quotas
.softlim
= BVAL(pdata
,24);
3768 /* the hard quotas 8 bytes (uint64_t)*/
3769 quotas
.hardlim
= BVAL(pdata
,32);
3771 /* quota_flags 2 bytes **/
3772 quotas
.qflags
= SVAL(pdata
,40);
3774 /* unknown_2 6 NULL bytes follow*/
3776 /* now set the quotas */
3777 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3778 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3779 reply_nterror(req
, map_nt_error_from_unix(errno
));
3786 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3788 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3794 * sending this reply works fine,
3795 * but I'm not sure it's the same
3796 * like windows do...
3799 reply_outbuf(req
, 10, 0);
3802 #if defined(HAVE_POSIX_ACLS)
3803 /****************************************************************************
3804 Utility function to count the number of entries in a POSIX acl.
3805 ****************************************************************************/
3807 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3809 unsigned int ace_count
= 0;
3810 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3811 SMB_ACL_ENTRY_T entry
;
3813 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3815 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3816 entry_id
= SMB_ACL_NEXT_ENTRY
;
3823 /****************************************************************************
3824 Utility function to marshall a POSIX acl into wire format.
3825 ****************************************************************************/
3827 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3829 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3830 SMB_ACL_ENTRY_T entry
;
3832 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3833 SMB_ACL_TAG_T tagtype
;
3834 SMB_ACL_PERMSET_T permset
;
3835 unsigned char perms
= 0;
3836 unsigned int own_grp
;
3839 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3840 entry_id
= SMB_ACL_NEXT_ENTRY
;
3843 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3844 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3848 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3849 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3853 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3854 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3855 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3857 SCVAL(pdata
,1,perms
);
3860 case SMB_ACL_USER_OBJ
:
3861 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3862 own_grp
= (unsigned int)pst
->st_ex_uid
;
3863 SIVAL(pdata
,2,own_grp
);
3868 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3870 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3873 own_grp
= (unsigned int)*puid
;
3874 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3875 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3876 SIVAL(pdata
,2,own_grp
);
3880 case SMB_ACL_GROUP_OBJ
:
3881 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3882 own_grp
= (unsigned int)pst
->st_ex_gid
;
3883 SIVAL(pdata
,2,own_grp
);
3888 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3893 own_grp
= (unsigned int)*pgid
;
3894 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3895 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3896 SIVAL(pdata
,2,own_grp
);
3901 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3902 SIVAL(pdata
,2,0xFFFFFFFF);
3903 SIVAL(pdata
,6,0xFFFFFFFF);
3906 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3907 SIVAL(pdata
,2,0xFFFFFFFF);
3908 SIVAL(pdata
,6,0xFFFFFFFF);
3911 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3914 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3921 /****************************************************************************
3922 Store the FILE_UNIX_BASIC info.
3923 ****************************************************************************/
3925 static char *store_file_unix_basic(connection_struct
*conn
,
3928 const SMB_STRUCT_STAT
*psbuf
)
3930 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3932 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3933 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3935 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3938 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3941 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3942 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3943 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3946 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3950 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3954 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3957 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3961 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3965 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3968 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3972 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3979 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3980 * the chflags(2) (or equivalent) flags.
3982 * XXX: this really should be behind the VFS interface. To do this, we would
3983 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3984 * Each VFS module could then implement its own mapping as appropriate for the
3985 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3987 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3991 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3995 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3999 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4003 { UF_HIDDEN
, EXT_HIDDEN
},
4006 /* Do not remove. We need to guarantee that this array has at least one
4007 * entry to build on HP-UX.
4013 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4014 uint32
*smb_fflags
, uint32
*smb_fmask
)
4018 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4019 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4020 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4021 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4026 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4027 const uint32 smb_fflags
,
4028 const uint32 smb_fmask
,
4031 uint32 max_fmask
= 0;
4034 *stat_fflags
= psbuf
->st_ex_flags
;
4036 /* For each flags requested in smb_fmask, check the state of the
4037 * corresponding flag in smb_fflags and set or clear the matching
4041 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4042 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4043 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4044 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4045 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4047 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4052 /* If smb_fmask is asking to set any bits that are not supported by
4053 * our flag mappings, we should fail.
4055 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4063 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4064 * of file flags and birth (create) time.
4066 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4069 const SMB_STRUCT_STAT
*psbuf
)
4071 uint32 file_flags
= 0;
4072 uint32 flags_mask
= 0;
4074 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4076 /* Create (birth) time 64 bit */
4077 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4080 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4081 SIVAL(pdata
, 0, file_flags
); /* flags */
4082 SIVAL(pdata
, 4, flags_mask
); /* mask */
4088 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4089 const struct stream_struct
*streams
,
4091 unsigned int max_data_bytes
,
4092 unsigned int *data_size
)
4095 unsigned int ofs
= 0;
4097 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4098 unsigned int next_offset
;
4100 smb_ucs2_t
*namebuf
;
4102 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4103 streams
[i
].name
, &namelen
) ||
4106 return NT_STATUS_INVALID_PARAMETER
;
4110 * name_buf is now null-terminated, we need to marshall as not
4116 SIVAL(data
, ofs
+4, namelen
);
4117 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4118 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4119 memcpy(data
+ofs
+24, namebuf
, namelen
);
4120 TALLOC_FREE(namebuf
);
4122 next_offset
= ofs
+ 24 + namelen
;
4124 if (i
== num_streams
-1) {
4125 SIVAL(data
, ofs
, 0);
4128 unsigned int align
= ndr_align_size(next_offset
, 8);
4130 memset(data
+next_offset
, 0, align
);
4131 next_offset
+= align
;
4133 SIVAL(data
, ofs
, next_offset
- ofs
);
4142 return NT_STATUS_OK
;
4145 /****************************************************************************
4146 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4147 ****************************************************************************/
4149 static void call_trans2qpipeinfo(connection_struct
*conn
,
4150 struct smb_request
*req
,
4151 unsigned int tran_call
,
4152 char **pparams
, int total_params
,
4153 char **ppdata
, int total_data
,
4154 unsigned int max_data_bytes
)
4156 char *params
= *pparams
;
4157 char *pdata
= *ppdata
;
4158 unsigned int data_size
= 0;
4159 unsigned int param_size
= 2;
4164 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4168 if (total_params
< 4) {
4169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4173 fsp
= file_fsp(req
, SVAL(params
,0));
4174 if (!fsp_is_np(fsp
)) {
4175 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4179 info_level
= SVAL(params
,2);
4181 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4182 if (*pparams
== NULL
) {
4183 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4188 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4189 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4190 if (*ppdata
== NULL
) {
4191 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4196 switch (info_level
) {
4197 case SMB_FILE_STANDARD_INFORMATION
:
4199 SOFF_T(pdata
,0,4096LL);
4206 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4210 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4216 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4217 TALLOC_CTX
*mem_ctx
,
4218 uint16_t info_level
,
4220 struct smb_filename
*smb_fname
,
4221 bool delete_pending
,
4222 struct timespec write_time_ts
,
4223 struct ea_list
*ea_list
,
4224 int lock_data_count
,
4227 unsigned int max_data_bytes
,
4229 unsigned int *pdata_size
)
4231 char *pdata
= *ppdata
;
4232 char *dstart
, *dend
;
4233 unsigned int data_size
;
4234 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4235 time_t create_time
, mtime
, atime
, c_time
;
4236 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4243 uint64_t file_size
= 0;
4245 uint64_t allocation_size
= 0;
4246 uint64_t file_index
= 0;
4247 uint32_t access_mask
= 0;
4249 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4250 return NT_STATUS_INVALID_LEVEL
;
4253 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4254 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4255 info_level
, max_data_bytes
));
4257 mode
= dos_mode(conn
, smb_fname
);
4258 nlink
= psbuf
->st_ex_nlink
;
4260 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4264 if ((nlink
> 0) && delete_pending
) {
4268 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4269 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4270 if (*ppdata
== NULL
) {
4271 return NT_STATUS_NO_MEMORY
;
4275 dend
= dstart
+ data_size
- 1;
4277 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4278 update_stat_ex_mtime(psbuf
, write_time_ts
);
4281 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4282 mtime_ts
= psbuf
->st_ex_mtime
;
4283 atime_ts
= psbuf
->st_ex_atime
;
4284 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4286 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4287 dos_filetime_timespec(&create_time_ts
);
4288 dos_filetime_timespec(&mtime_ts
);
4289 dos_filetime_timespec(&atime_ts
);
4290 dos_filetime_timespec(&ctime_ts
);
4293 create_time
= convert_timespec_to_time_t(create_time_ts
);
4294 mtime
= convert_timespec_to_time_t(mtime_ts
);
4295 atime
= convert_timespec_to_time_t(atime_ts
);
4296 c_time
= convert_timespec_to_time_t(ctime_ts
);
4298 p
= strrchr_m(smb_fname
->base_name
,'/');
4300 base_name
= smb_fname
->base_name
;
4304 /* NT expects the name to be in an exact form of the *full*
4305 filename. See the trans2 torture test */
4306 if (ISDOT(base_name
)) {
4307 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4309 return NT_STATUS_NO_MEMORY
;
4312 dos_fname
= talloc_asprintf(mem_ctx
,
4314 smb_fname
->base_name
);
4316 return NT_STATUS_NO_MEMORY
;
4318 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4319 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4320 smb_fname
->stream_name
);
4322 return NT_STATUS_NO_MEMORY
;
4326 string_replace(dos_fname
, '/', '\\');
4329 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4332 /* Do we have this path open ? */
4334 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4335 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4336 if (fsp1
&& fsp1
->initial_allocation_size
) {
4337 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4341 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4342 file_size
= get_file_size_stat(psbuf
);
4346 pos
= fsp
->fh
->position_information
;
4350 access_mask
= fsp
->access_mask
;
4352 /* GENERIC_EXECUTE mapping from Windows */
4353 access_mask
= 0x12019F;
4356 /* This should be an index number - looks like
4359 I think this causes us to fail the IFSKIT
4360 BasicFileInformationTest. -tpot */
4361 file_index
= get_FileIndex(conn
, psbuf
);
4363 switch (info_level
) {
4364 case SMB_INFO_STANDARD
:
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4367 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4368 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4369 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4370 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4371 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4372 SSVAL(pdata
,l1_attrFile
,mode
);
4375 case SMB_INFO_QUERY_EA_SIZE
:
4377 unsigned int ea_size
=
4378 estimate_ea_size(conn
, fsp
,
4379 smb_fname
->base_name
);
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4382 srv_put_dos_date2(pdata
,0,create_time
);
4383 srv_put_dos_date2(pdata
,4,atime
);
4384 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4385 SIVAL(pdata
,12,(uint32
)file_size
);
4386 SIVAL(pdata
,16,(uint32
)allocation_size
);
4387 SSVAL(pdata
,20,mode
);
4388 SIVAL(pdata
,22,ea_size
);
4392 case SMB_INFO_IS_NAME_VALID
:
4393 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4395 /* os/2 needs this ? really ?*/
4396 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4398 /* This is only reached for qpathinfo */
4402 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4404 size_t total_ea_len
= 0;
4405 struct ea_list
*ea_file_list
= NULL
;
4407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4410 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4411 smb_fname
->base_name
,
4413 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4415 if (!ea_list
|| (total_ea_len
> data_size
)) {
4417 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4421 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4425 case SMB_INFO_QUERY_ALL_EAS
:
4427 /* We have data_size bytes to put EA's into. */
4428 size_t total_ea_len
= 0;
4430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4432 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4433 smb_fname
->base_name
,
4435 if (!ea_list
|| (total_ea_len
> data_size
)) {
4437 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4441 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4445 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4447 /* This is FileFullEaInformation - 0xF which maps to
4448 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4450 /* We have data_size bytes to put EA's into. */
4451 size_t total_ea_len
= 0;
4452 struct ea_list
*ea_file_list
= NULL
;
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4456 /*TODO: add filtering and index handling */
4459 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4460 smb_fname
->base_name
,
4462 if (!ea_file_list
) {
4463 return NT_STATUS_NO_EAS_ON_FILE
;
4466 status
= fill_ea_chained_buffer(mem_ctx
,
4470 conn
, ea_file_list
);
4471 if (!NT_STATUS_IS_OK(status
)) {
4477 case SMB_FILE_BASIC_INFORMATION
:
4478 case SMB_QUERY_FILE_BASIC_INFO
:
4480 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4482 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4488 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4489 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4490 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4491 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4492 SIVAL(pdata
,32,mode
);
4494 DEBUG(5,("SMB_QFBI - "));
4495 DEBUG(5,("create: %s ", ctime(&create_time
)));
4496 DEBUG(5,("access: %s ", ctime(&atime
)));
4497 DEBUG(5,("write: %s ", ctime(&mtime
)));
4498 DEBUG(5,("change: %s ", ctime(&c_time
)));
4499 DEBUG(5,("mode: %x\n", mode
));
4502 case SMB_FILE_STANDARD_INFORMATION
:
4503 case SMB_QUERY_FILE_STANDARD_INFO
:
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4507 SOFF_T(pdata
,0,allocation_size
);
4508 SOFF_T(pdata
,8,file_size
);
4509 SIVAL(pdata
,16,nlink
);
4510 SCVAL(pdata
,20,delete_pending
?1:0);
4511 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4512 SSVAL(pdata
,22,0); /* Padding. */
4515 case SMB_FILE_EA_INFORMATION
:
4516 case SMB_QUERY_FILE_EA_INFO
:
4518 unsigned int ea_size
=
4519 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4522 SIVAL(pdata
,0,ea_size
);
4526 /* Get the 8.3 name - used if NT SMB was negotiated. */
4527 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4528 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4531 char mangled_name
[13];
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4533 if (!name_to_8_3(base_name
,mangled_name
,
4534 True
,conn
->params
)) {
4535 return NT_STATUS_NO_MEMORY
;
4537 len
= srvstr_push(dstart
, flags2
,
4538 pdata
+4, mangled_name
,
4539 PTR_DIFF(dend
, pdata
+4),
4541 data_size
= 4 + len
;
4546 case SMB_QUERY_FILE_NAME_INFO
:
4550 this must be *exactly* right for ACLs on mapped drives to work
4552 len
= srvstr_push(dstart
, flags2
,
4554 PTR_DIFF(dend
, pdata
+4),
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4557 data_size
= 4 + len
;
4562 case SMB_FILE_ALLOCATION_INFORMATION
:
4563 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4566 SOFF_T(pdata
,0,allocation_size
);
4569 case SMB_FILE_END_OF_FILE_INFORMATION
:
4570 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4571 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4573 SOFF_T(pdata
,0,file_size
);
4576 case SMB_QUERY_FILE_ALL_INFO
:
4577 case SMB_FILE_ALL_INFORMATION
:
4580 unsigned int ea_size
=
4581 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4582 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4583 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4584 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4585 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4586 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4587 SIVAL(pdata
,32,mode
);
4588 SIVAL(pdata
,36,0); /* padding. */
4590 SOFF_T(pdata
,0,allocation_size
);
4591 SOFF_T(pdata
,8,file_size
);
4592 SIVAL(pdata
,16,nlink
);
4593 SCVAL(pdata
,20,delete_pending
);
4594 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4597 SIVAL(pdata
,0,ea_size
);
4598 pdata
+= 4; /* EA info */
4599 len
= srvstr_push(dstart
, flags2
,
4601 PTR_DIFF(dend
, pdata
+4),
4605 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4609 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4612 unsigned int ea_size
=
4613 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4615 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4616 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4617 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4618 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4619 SIVAL(pdata
, 0x20, mode
);
4620 SIVAL(pdata
, 0x24, 0); /* padding. */
4621 SBVAL(pdata
, 0x28, allocation_size
);
4622 SBVAL(pdata
, 0x30, file_size
);
4623 SIVAL(pdata
, 0x38, nlink
);
4624 SCVAL(pdata
, 0x3C, delete_pending
);
4625 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4626 SSVAL(pdata
, 0x3E, 0); /* padding */
4627 SBVAL(pdata
, 0x40, file_index
);
4628 SIVAL(pdata
, 0x48, ea_size
);
4629 SIVAL(pdata
, 0x4C, access_mask
);
4630 SBVAL(pdata
, 0x50, pos
);
4631 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4632 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4636 len
= srvstr_push(dstart
, flags2
,
4638 PTR_DIFF(dend
, pdata
+4),
4642 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4645 case SMB_FILE_INTERNAL_INFORMATION
:
4647 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4648 SBVAL(pdata
, 0, file_index
);
4652 case SMB_FILE_ACCESS_INFORMATION
:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4654 SIVAL(pdata
, 0, access_mask
);
4658 case SMB_FILE_NAME_INFORMATION
:
4659 /* Pathname with leading '\'. */
4662 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4664 SIVAL(pdata
,0,byte_len
);
4665 data_size
= 4 + byte_len
;
4669 case SMB_FILE_DISPOSITION_INFORMATION
:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4672 SCVAL(pdata
,0,delete_pending
);
4675 case SMB_FILE_POSITION_INFORMATION
:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4678 SOFF_T(pdata
,0,pos
);
4681 case SMB_FILE_MODE_INFORMATION
:
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4683 SIVAL(pdata
,0,mode
);
4687 case SMB_FILE_ALIGNMENT_INFORMATION
:
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4689 SIVAL(pdata
,0,0); /* No alignment needed. */
4694 * NT4 server just returns "invalid query" to this - if we try
4695 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4698 /* The first statement above is false - verified using Thursby
4699 * client against NT4 -- gcolley.
4701 case SMB_QUERY_FILE_STREAM_INFO
:
4702 case SMB_FILE_STREAM_INFORMATION
: {
4703 unsigned int num_streams
= 0;
4704 struct stream_struct
*streams
= NULL
;
4706 DEBUG(10,("smbd_do_qfilepathinfo: "
4707 "SMB_FILE_STREAM_INFORMATION\n"));
4709 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4710 return NT_STATUS_INVALID_PARAMETER
;
4713 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4714 talloc_tos(), &num_streams
, &streams
);
4716 if (!NT_STATUS_IS_OK(status
)) {
4717 DEBUG(10, ("could not get stream info: %s\n",
4718 nt_errstr(status
)));
4722 status
= marshall_stream_info(num_streams
, streams
,
4723 pdata
, max_data_bytes
,
4726 if (!NT_STATUS_IS_OK(status
)) {
4727 DEBUG(10, ("marshall_stream_info failed: %s\n",
4728 nt_errstr(status
)));
4732 TALLOC_FREE(streams
);
4736 case SMB_QUERY_COMPRESSION_INFO
:
4737 case SMB_FILE_COMPRESSION_INFORMATION
:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4739 SOFF_T(pdata
,0,file_size
);
4740 SIVAL(pdata
,8,0); /* ??? */
4741 SIVAL(pdata
,12,0); /* ??? */
4745 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4746 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4747 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4748 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4749 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4750 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4751 SOFF_T(pdata
,32,allocation_size
);
4752 SOFF_T(pdata
,40,file_size
);
4753 SIVAL(pdata
,48,mode
);
4754 SIVAL(pdata
,52,0); /* ??? */
4758 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4760 SIVAL(pdata
,0,mode
);
4766 * CIFS UNIX Extensions.
4769 case SMB_QUERY_FILE_UNIX_BASIC
:
4771 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4772 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4774 DEBUG(4,("smbd_do_qfilepathinfo: "
4775 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4776 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4780 case SMB_QUERY_FILE_UNIX_INFO2
:
4782 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4783 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4787 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4789 for (i
=0; i
<100; i
++)
4790 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4796 case SMB_QUERY_FILE_UNIX_LINK
:
4799 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4802 return NT_STATUS_NO_MEMORY
;
4805 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4807 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4808 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4811 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4813 len
= SMB_VFS_READLINK(conn
,
4814 smb_fname
->base_name
,
4817 return map_nt_error_from_unix(errno
);
4820 len
= srvstr_push(dstart
, flags2
,
4822 PTR_DIFF(dend
, pdata
),
4825 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4830 #if defined(HAVE_POSIX_ACLS)
4831 case SMB_QUERY_POSIX_ACL
:
4833 SMB_ACL_T file_acl
= NULL
;
4834 SMB_ACL_T def_acl
= NULL
;
4835 uint16 num_file_acls
= 0;
4836 uint16 num_def_acls
= 0;
4838 if (fsp
&& fsp
->fh
->fd
!= -1) {
4839 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4842 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4843 smb_fname
->base_name
,
4844 SMB_ACL_TYPE_ACCESS
);
4847 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4848 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4849 "not implemented on "
4850 "filesystem containing %s\n",
4851 smb_fname
->base_name
));
4852 return NT_STATUS_NOT_IMPLEMENTED
;
4855 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4856 if (fsp
&& fsp
->is_directory
) {
4858 SMB_VFS_SYS_ACL_GET_FILE(
4860 fsp
->fsp_name
->base_name
,
4861 SMB_ACL_TYPE_DEFAULT
);
4864 SMB_VFS_SYS_ACL_GET_FILE(
4866 smb_fname
->base_name
,
4867 SMB_ACL_TYPE_DEFAULT
);
4869 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4872 num_file_acls
= count_acl_entries(conn
, file_acl
);
4873 num_def_acls
= count_acl_entries(conn
, def_acl
);
4875 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4876 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4878 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4879 SMB_POSIX_ACL_HEADER_SIZE
) ));
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4886 return NT_STATUS_BUFFER_TOO_SMALL
;
4889 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4890 SSVAL(pdata
,2,num_file_acls
);
4891 SSVAL(pdata
,4,num_def_acls
);
4892 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4897 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4899 return NT_STATUS_INTERNAL_ERROR
;
4901 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4906 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4908 return NT_STATUS_INTERNAL_ERROR
;
4912 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4915 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4917 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4923 case SMB_QUERY_POSIX_LOCK
:
4928 enum brl_type lock_type
;
4930 /* We need an open file with a real fd for this. */
4931 if (!fsp
|| fsp
->fh
->fd
== -1) {
4932 return NT_STATUS_INVALID_LEVEL
;
4935 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4936 return NT_STATUS_INVALID_PARAMETER
;
4939 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4940 case POSIX_LOCK_TYPE_READ
:
4941 lock_type
= READ_LOCK
;
4943 case POSIX_LOCK_TYPE_WRITE
:
4944 lock_type
= WRITE_LOCK
;
4946 case POSIX_LOCK_TYPE_UNLOCK
:
4948 /* There's no point in asking for an unlock... */
4949 return NT_STATUS_INVALID_PARAMETER
;
4952 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4953 #if defined(HAVE_LONGLONG)
4954 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4955 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4956 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4957 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4958 #else /* HAVE_LONGLONG */
4959 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4960 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4961 #endif /* HAVE_LONGLONG */
4963 status
= query_lock(fsp
,
4970 if (ERROR_WAS_LOCK_DENIED(status
)) {
4971 /* Here we need to report who has it locked... */
4972 data_size
= POSIX_LOCK_DATA_SIZE
;
4974 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4975 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4976 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4977 #if defined(HAVE_LONGLONG)
4978 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4979 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4980 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4981 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4982 #else /* HAVE_LONGLONG */
4983 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4984 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4985 #endif /* HAVE_LONGLONG */
4987 } else if (NT_STATUS_IS_OK(status
)) {
4988 /* For success we just return a copy of what we sent
4989 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4990 data_size
= POSIX_LOCK_DATA_SIZE
;
4991 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4992 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5000 return NT_STATUS_INVALID_LEVEL
;
5003 *pdata_size
= data_size
;
5004 return NT_STATUS_OK
;
5007 /****************************************************************************
5008 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5009 file name or file id).
5010 ****************************************************************************/
5012 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5013 struct smb_request
*req
,
5014 unsigned int tran_call
,
5015 char **pparams
, int total_params
,
5016 char **ppdata
, int total_data
,
5017 unsigned int max_data_bytes
)
5019 char *params
= *pparams
;
5020 char *pdata
= *ppdata
;
5022 unsigned int data_size
= 0;
5023 unsigned int param_size
= 2;
5024 struct smb_filename
*smb_fname
= NULL
;
5025 bool delete_pending
= False
;
5026 struct timespec write_time_ts
;
5027 files_struct
*fsp
= NULL
;
5028 struct file_id fileid
;
5029 struct ea_list
*ea_list
= NULL
;
5030 int lock_data_count
= 0;
5031 char *lock_data
= NULL
;
5032 NTSTATUS status
= NT_STATUS_OK
;
5035 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5039 ZERO_STRUCT(write_time_ts
);
5041 if (tran_call
== TRANSACT2_QFILEINFO
) {
5042 if (total_params
< 4) {
5043 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5048 call_trans2qpipeinfo(conn
, req
, tran_call
,
5049 pparams
, total_params
,
5055 fsp
= file_fsp(req
, SVAL(params
,0));
5056 info_level
= SVAL(params
,2);
5058 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5060 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5061 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5065 /* Initial check for valid fsp ptr. */
5066 if (!check_fsp_open(conn
, req
, fsp
)) {
5070 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5072 if (!NT_STATUS_IS_OK(status
)) {
5073 reply_nterror(req
, status
);
5077 if(fsp
->fake_file_handle
) {
5079 * This is actually for the QUOTA_FAKE_FILE --metze
5082 /* We know this name is ok, it's already passed the checks. */
5084 } else if(fsp
->fh
->fd
== -1) {
5086 * This is actually a QFILEINFO on a directory
5087 * handle (returned from an NT SMB). NT5.0 seems
5088 * to do this call. JRA.
5091 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5092 /* Always do lstat for UNIX calls. */
5093 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5094 DEBUG(3,("call_trans2qfilepathinfo: "
5095 "SMB_VFS_LSTAT of %s failed "
5097 smb_fname_str_dbg(smb_fname
),
5100 map_nt_error_from_unix(errno
));
5103 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5104 DEBUG(3,("call_trans2qfilepathinfo: "
5105 "SMB_VFS_STAT of %s failed (%s)\n",
5106 smb_fname_str_dbg(smb_fname
),
5109 map_nt_error_from_unix(errno
));
5113 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5114 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5117 * Original code - this is an open file.
5119 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5120 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5121 fsp
->fnum
, strerror(errno
)));
5123 map_nt_error_from_unix(errno
));
5126 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5127 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5133 uint32_t ucf_flags
= 0;
5136 if (total_params
< 7) {
5137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5141 info_level
= SVAL(params
,0);
5143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5145 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5146 if (!lp_unix_extensions()) {
5147 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5150 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5151 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5152 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5153 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5157 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5159 STR_TERMINATE
, &status
);
5160 if (!NT_STATUS_IS_OK(status
)) {
5161 reply_nterror(req
, status
);
5165 status
= filename_convert(req
,
5167 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5172 if (!NT_STATUS_IS_OK(status
)) {
5173 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5174 reply_botherror(req
,
5175 NT_STATUS_PATH_NOT_COVERED
,
5176 ERRSRV
, ERRbadpath
);
5179 reply_nterror(req
, status
);
5183 /* If this is a stream, check if there is a delete_pending. */
5184 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5185 && is_ntfs_stream_smb_fname(smb_fname
)) {
5186 struct smb_filename
*smb_fname_base
= NULL
;
5188 /* Create an smb_filename with stream_name == NULL. */
5190 create_synthetic_smb_fname(talloc_tos(),
5191 smb_fname
->base_name
,
5194 if (!NT_STATUS_IS_OK(status
)) {
5195 reply_nterror(req
, status
);
5199 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5200 /* Always do lstat for UNIX calls. */
5201 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "SMB_VFS_LSTAT of %s failed "
5205 smb_fname_str_dbg(smb_fname_base
),
5207 TALLOC_FREE(smb_fname_base
);
5209 map_nt_error_from_unix(errno
));
5213 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5214 DEBUG(3,("call_trans2qfilepathinfo: "
5215 "fileinfo of %s failed "
5217 smb_fname_str_dbg(smb_fname_base
),
5219 TALLOC_FREE(smb_fname_base
);
5221 map_nt_error_from_unix(errno
));
5226 status
= file_name_hash(conn
,
5227 smb_fname_str_dbg(smb_fname_base
),
5229 if (!NT_STATUS_IS_OK(status
)) {
5230 TALLOC_FREE(smb_fname_base
);
5231 reply_nterror(req
, status
);
5235 fileid
= vfs_file_id_from_sbuf(conn
,
5236 &smb_fname_base
->st
);
5237 TALLOC_FREE(smb_fname_base
);
5238 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5239 if (delete_pending
) {
5240 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5245 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5246 /* Always do lstat for UNIX calls. */
5247 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "SMB_VFS_LSTAT of %s failed (%s)\n",
5250 smb_fname_str_dbg(smb_fname
),
5253 map_nt_error_from_unix(errno
));
5258 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5259 DEBUG(3,("call_trans2qfilepathinfo: "
5260 "SMB_VFS_STAT of %s failed (%s)\n",
5261 smb_fname_str_dbg(smb_fname
),
5264 map_nt_error_from_unix(errno
));
5269 status
= file_name_hash(conn
,
5270 smb_fname_str_dbg(smb_fname
),
5272 if (!NT_STATUS_IS_OK(status
)) {
5273 reply_nterror(req
, status
);
5277 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5278 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5279 if (delete_pending
) {
5280 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5285 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5286 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5287 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5289 /* Pull out any data sent here before we realloc. */
5290 switch (info_level
) {
5291 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5293 /* Pull any EA list from the data portion. */
5296 if (total_data
< 4) {
5298 req
, NT_STATUS_INVALID_PARAMETER
);
5301 ea_size
= IVAL(pdata
,0);
5303 if (total_data
> 0 && ea_size
!= total_data
) {
5304 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5305 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5307 req
, NT_STATUS_INVALID_PARAMETER
);
5311 if (!lp_ea_support(SNUM(conn
))) {
5312 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5316 /* Pull out the list of names. */
5317 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5320 req
, NT_STATUS_INVALID_PARAMETER
);
5326 case SMB_QUERY_POSIX_LOCK
:
5328 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5329 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5333 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5335 req
, NT_STATUS_INVALID_PARAMETER
);
5339 /* Copy the lock range data. */
5340 lock_data
= (char *)talloc_memdup(
5341 req
, pdata
, total_data
);
5343 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5346 lock_data_count
= total_data
;
5352 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5353 if (*pparams
== NULL
) {
5354 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5361 * draft-leach-cifs-v1-spec-02.txt
5362 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5365 * The requested information is placed in the Data portion of the
5366 * transaction response. For the information levels greater than 0x100,
5367 * the transaction response has 1 parameter word which should be
5368 * ignored by the client.
5370 * However Windows only follows this rule for the IS_NAME_VALID call.
5372 switch (info_level
) {
5373 case SMB_INFO_IS_NAME_VALID
:
5378 if ((info_level
& 0xFF00) == 0xFF00) {
5380 * We use levels that start with 0xFF00
5381 * internally to represent SMB2 specific levels
5383 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5387 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5389 delete_pending
, write_time_ts
,
5391 lock_data_count
, lock_data
,
5392 req
->flags2
, max_data_bytes
,
5393 ppdata
, &data_size
);
5394 if (!NT_STATUS_IS_OK(status
)) {
5395 reply_nterror(req
, status
);
5399 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5405 /****************************************************************************
5406 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5408 ****************************************************************************/
5410 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5411 connection_struct
*conn
,
5412 struct smb_request
*req
,
5413 bool overwrite_if_exists
,
5414 const struct smb_filename
*smb_fname_old
,
5415 struct smb_filename
*smb_fname_new
)
5417 NTSTATUS status
= NT_STATUS_OK
;
5419 /* source must already exist. */
5420 if (!VALID_STAT(smb_fname_old
->st
)) {
5421 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5424 if (VALID_STAT(smb_fname_new
->st
)) {
5425 if (overwrite_if_exists
) {
5426 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5427 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5429 status
= unlink_internals(conn
,
5431 FILE_ATTRIBUTE_NORMAL
,
5434 if (!NT_STATUS_IS_OK(status
)) {
5438 /* Disallow if newname already exists. */
5439 return NT_STATUS_OBJECT_NAME_COLLISION
;
5443 /* No links from a directory. */
5444 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5445 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5448 /* Setting a hardlink to/from a stream isn't currently supported. */
5449 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5450 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5451 return NT_STATUS_INVALID_PARAMETER
;
5454 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5455 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5457 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5458 smb_fname_new
->base_name
) != 0) {
5459 status
= map_nt_error_from_unix(errno
);
5460 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5461 nt_errstr(status
), smb_fname_old
->base_name
,
5462 smb_fname_new
->base_name
));
5467 /****************************************************************************
5468 Deal with setting the time from any of the setfilepathinfo functions.
5469 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5470 calling this function.
5471 ****************************************************************************/
5473 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5475 const struct smb_filename
*smb_fname
,
5476 struct smb_file_time
*ft
,
5477 bool setting_write_time
)
5479 struct smb_filename smb_fname_base
;
5481 FILE_NOTIFY_CHANGE_LAST_ACCESS
5482 |FILE_NOTIFY_CHANGE_LAST_WRITE
5483 |FILE_NOTIFY_CHANGE_CREATION
;
5485 if (!VALID_STAT(smb_fname
->st
)) {
5486 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5489 /* get some defaults (no modifications) if any info is zero or -1. */
5490 if (null_timespec(ft
->create_time
)) {
5491 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5494 if (null_timespec(ft
->atime
)) {
5495 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5498 if (null_timespec(ft
->mtime
)) {
5499 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5502 if (!setting_write_time
) {
5503 /* ft->mtime comes from change time, not write time. */
5504 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5507 /* Ensure the resolution is the correct for
5508 * what we can store on this filesystem. */
5510 round_timespec(conn
->ts_res
, &ft
->create_time
);
5511 round_timespec(conn
->ts_res
, &ft
->ctime
);
5512 round_timespec(conn
->ts_res
, &ft
->atime
);
5513 round_timespec(conn
->ts_res
, &ft
->mtime
);
5515 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5516 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5517 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5518 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5519 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5520 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5521 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5522 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5524 if (setting_write_time
) {
5526 * This was a Windows setfileinfo on an open file.
5527 * NT does this a lot. We also need to
5528 * set the time here, as it can be read by
5529 * FindFirst/FindNext and with the patch for bug #2045
5530 * in smbd/fileio.c it ensures that this timestamp is
5531 * kept sticky even after a write. We save the request
5532 * away and will set it on file close and after a write. JRA.
5535 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5536 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5539 if (fsp
->base_fsp
) {
5540 set_sticky_write_time_fsp(fsp
->base_fsp
,
5543 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5546 set_sticky_write_time_path(
5547 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5552 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5554 /* Always call ntimes on the base, even if a stream was passed in. */
5555 smb_fname_base
= *smb_fname
;
5556 smb_fname_base
.stream_name
= NULL
;
5558 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5559 return map_nt_error_from_unix(errno
);
5562 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5563 smb_fname
->base_name
);
5564 return NT_STATUS_OK
;
5567 /****************************************************************************
5568 Deal with setting the dosmode from any of the setfilepathinfo functions.
5569 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5570 done before calling this function.
5571 ****************************************************************************/
5573 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5574 const struct smb_filename
*smb_fname
,
5577 struct smb_filename
*smb_fname_base
= NULL
;
5580 if (!VALID_STAT(smb_fname
->st
)) {
5581 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5584 /* Always operate on the base_name, even if a stream was passed in. */
5585 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5586 NULL
, &smb_fname
->st
,
5588 if (!NT_STATUS_IS_OK(status
)) {
5593 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5594 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5596 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5600 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5602 /* check the mode isn't different, before changing it */
5603 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5604 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5605 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5606 (unsigned int)dosmode
));
5608 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5610 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5612 smb_fname_str_dbg(smb_fname_base
),
5614 status
= map_nt_error_from_unix(errno
);
5618 status
= NT_STATUS_OK
;
5620 TALLOC_FREE(smb_fname_base
);
5624 /****************************************************************************
5625 Deal with setting the size from any of the setfilepathinfo functions.
5626 ****************************************************************************/
5628 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5629 struct smb_request
*req
,
5631 const struct smb_filename
*smb_fname
,
5632 const SMB_STRUCT_STAT
*psbuf
,
5634 bool fail_after_createfile
)
5636 NTSTATUS status
= NT_STATUS_OK
;
5637 struct smb_filename
*smb_fname_tmp
= NULL
;
5638 files_struct
*new_fsp
= NULL
;
5640 if (!VALID_STAT(*psbuf
)) {
5641 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5644 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5646 if (size
== get_file_size_stat(psbuf
)) {
5647 return NT_STATUS_OK
;
5650 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5651 smb_fname_str_dbg(smb_fname
), (double)size
));
5653 if (fsp
&& fsp
->fh
->fd
!= -1) {
5654 /* Handle based call. */
5655 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5656 return NT_STATUS_ACCESS_DENIED
;
5659 if (vfs_set_filelen(fsp
, size
) == -1) {
5660 return map_nt_error_from_unix(errno
);
5662 trigger_write_time_update_immediate(fsp
);
5663 return NT_STATUS_OK
;
5666 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5667 if (!NT_STATUS_IS_OK(status
)) {
5671 smb_fname_tmp
->st
= *psbuf
;
5673 status
= SMB_VFS_CREATE_FILE(
5676 0, /* root_dir_fid */
5677 smb_fname_tmp
, /* fname */
5678 FILE_WRITE_DATA
, /* access_mask */
5679 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5681 FILE_OPEN
, /* create_disposition*/
5682 0, /* create_options */
5683 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5684 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5685 0, /* allocation_size */
5686 0, /* private_flags */
5689 &new_fsp
, /* result */
5692 TALLOC_FREE(smb_fname_tmp
);
5694 if (!NT_STATUS_IS_OK(status
)) {
5695 /* NB. We check for open_was_deferred in the caller. */
5699 /* See RAW-SFILEINFO-END-OF-FILE */
5700 if (fail_after_createfile
) {
5701 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5702 return NT_STATUS_INVALID_LEVEL
;
5705 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5706 status
= map_nt_error_from_unix(errno
);
5707 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5711 trigger_write_time_update_immediate(new_fsp
);
5712 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5713 return NT_STATUS_OK
;
5716 /****************************************************************************
5717 Deal with SMB_INFO_SET_EA.
5718 ****************************************************************************/
5720 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5724 const struct smb_filename
*smb_fname
)
5726 struct ea_list
*ea_list
= NULL
;
5727 TALLOC_CTX
*ctx
= NULL
;
5728 NTSTATUS status
= NT_STATUS_OK
;
5730 if (total_data
< 10) {
5732 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5733 length. They seem to have no effect. Bug #3212. JRA */
5735 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5736 /* We're done. We only get EA info in this call. */
5737 return NT_STATUS_OK
;
5740 return NT_STATUS_INVALID_PARAMETER
;
5743 if (IVAL(pdata
,0) > total_data
) {
5744 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5745 IVAL(pdata
,0), (unsigned int)total_data
));
5746 return NT_STATUS_INVALID_PARAMETER
;
5750 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5752 return NT_STATUS_INVALID_PARAMETER
;
5755 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5760 /****************************************************************************
5761 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5762 ****************************************************************************/
5764 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5769 struct ea_list
*ea_list
= NULL
;
5773 return NT_STATUS_INVALID_HANDLE
;
5776 if (!lp_ea_support(SNUM(conn
))) {
5777 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5778 "EA's not supported.\n",
5779 (unsigned int)total_data
));
5780 return NT_STATUS_EAS_NOT_SUPPORTED
;
5783 if (total_data
< 10) {
5784 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5786 (unsigned int)total_data
));
5787 return NT_STATUS_INVALID_PARAMETER
;
5790 ea_list
= read_nttrans_ea_list(talloc_tos(),
5795 return NT_STATUS_INVALID_PARAMETER
;
5798 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5800 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5801 smb_fname_str_dbg(fsp
->fsp_name
),
5802 nt_errstr(status
) ));
5808 /****************************************************************************
5809 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5810 ****************************************************************************/
5812 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5816 struct smb_filename
*smb_fname
)
5818 NTSTATUS status
= NT_STATUS_OK
;
5819 bool delete_on_close
;
5822 if (total_data
< 1) {
5823 return NT_STATUS_INVALID_PARAMETER
;
5827 return NT_STATUS_INVALID_HANDLE
;
5830 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5831 dosmode
= dos_mode(conn
, smb_fname
);
5833 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5834 "delete_on_close = %u\n",
5835 smb_fname_str_dbg(smb_fname
),
5836 (unsigned int)dosmode
,
5837 (unsigned int)delete_on_close
));
5839 if (delete_on_close
) {
5840 status
= can_set_delete_on_close(fsp
, dosmode
);
5841 if (!NT_STATUS_IS_OK(status
)) {
5846 /* The set is across all open files on this dev/inode pair. */
5847 if (!set_delete_on_close(fsp
, delete_on_close
,
5848 conn
->session_info
->unix_token
)) {
5849 return NT_STATUS_ACCESS_DENIED
;
5851 return NT_STATUS_OK
;
5854 /****************************************************************************
5855 Deal with SMB_FILE_POSITION_INFORMATION.
5856 ****************************************************************************/
5858 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5863 uint64_t position_information
;
5865 if (total_data
< 8) {
5866 return NT_STATUS_INVALID_PARAMETER
;
5870 /* Ignore on pathname based set. */
5871 return NT_STATUS_OK
;
5874 position_information
= (uint64_t)IVAL(pdata
,0);
5875 #ifdef LARGE_SMB_OFF_T
5876 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5877 #else /* LARGE_SMB_OFF_T */
5878 if (IVAL(pdata
,4) != 0) {
5879 /* more than 32 bits? */
5880 return NT_STATUS_INVALID_PARAMETER
;
5882 #endif /* LARGE_SMB_OFF_T */
5884 DEBUG(10,("smb_file_position_information: Set file position "
5885 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5886 (double)position_information
));
5887 fsp
->fh
->position_information
= position_information
;
5888 return NT_STATUS_OK
;
5891 /****************************************************************************
5892 Deal with SMB_FILE_MODE_INFORMATION.
5893 ****************************************************************************/
5895 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5901 if (total_data
< 4) {
5902 return NT_STATUS_INVALID_PARAMETER
;
5904 mode
= IVAL(pdata
,0);
5905 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5906 return NT_STATUS_INVALID_PARAMETER
;
5908 return NT_STATUS_OK
;
5911 /****************************************************************************
5912 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5913 ****************************************************************************/
5915 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5916 struct smb_request
*req
,
5919 const struct smb_filename
*smb_fname
)
5921 char *link_target
= NULL
;
5922 const char *newname
= smb_fname
->base_name
;
5923 TALLOC_CTX
*ctx
= talloc_tos();
5925 /* Set a symbolic link. */
5926 /* Don't allow this if follow links is false. */
5928 if (total_data
== 0) {
5929 return NT_STATUS_INVALID_PARAMETER
;
5932 if (!lp_symlinks(SNUM(conn
))) {
5933 return NT_STATUS_ACCESS_DENIED
;
5936 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5937 total_data
, STR_TERMINATE
);
5940 return NT_STATUS_INVALID_PARAMETER
;
5943 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5944 newname
, link_target
));
5946 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5947 return map_nt_error_from_unix(errno
);
5950 return NT_STATUS_OK
;
5953 /****************************************************************************
5954 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5955 ****************************************************************************/
5957 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5958 struct smb_request
*req
,
5959 const char *pdata
, int total_data
,
5960 struct smb_filename
*smb_fname_new
)
5962 char *oldname
= NULL
;
5963 struct smb_filename
*smb_fname_old
= NULL
;
5964 TALLOC_CTX
*ctx
= talloc_tos();
5965 NTSTATUS status
= NT_STATUS_OK
;
5967 /* Set a hard link. */
5968 if (total_data
== 0) {
5969 return NT_STATUS_INVALID_PARAMETER
;
5972 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5973 total_data
, STR_TERMINATE
, &status
);
5974 if (!NT_STATUS_IS_OK(status
)) {
5978 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5979 smb_fname_str_dbg(smb_fname_new
), oldname
));
5981 status
= filename_convert(ctx
,
5983 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5988 if (!NT_STATUS_IS_OK(status
)) {
5992 return hardlink_internals(ctx
, conn
, req
, false,
5993 smb_fname_old
, smb_fname_new
);
5996 /****************************************************************************
5997 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5998 ****************************************************************************/
6000 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6001 struct smb_request
*req
,
6005 struct smb_filename
*smb_fname_src
)
6009 char *newname
= NULL
;
6010 struct smb_filename
*smb_fname_dst
= NULL
;
6011 NTSTATUS status
= NT_STATUS_OK
;
6012 TALLOC_CTX
*ctx
= talloc_tos();
6015 return NT_STATUS_INVALID_HANDLE
;
6018 if (total_data
< 20) {
6019 return NT_STATUS_INVALID_PARAMETER
;
6022 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6023 len
= IVAL(pdata
,16);
6025 if (len
> (total_data
- 20) || (len
== 0)) {
6026 return NT_STATUS_INVALID_PARAMETER
;
6029 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6030 &pdata
[20], len
, STR_TERMINATE
,
6032 if (!NT_STATUS_IS_OK(status
)) {
6036 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6039 status
= filename_convert(ctx
,
6041 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6046 if (!NT_STATUS_IS_OK(status
)) {
6050 if (fsp
->base_fsp
) {
6051 /* newname must be a stream name. */
6052 if (newname
[0] != ':') {
6053 return NT_STATUS_NOT_SUPPORTED
;
6056 /* Create an smb_fname to call rename_internals_fsp() with. */
6057 status
= create_synthetic_smb_fname(talloc_tos(),
6058 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6060 if (!NT_STATUS_IS_OK(status
)) {
6065 * Set the original last component, since
6066 * rename_internals_fsp() requires it.
6068 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6070 if (smb_fname_dst
->original_lcomp
== NULL
) {
6071 status
= NT_STATUS_NO_MEMORY
;
6077 DEBUG(10,("smb2_file_rename_information: "
6078 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6079 fsp
->fnum
, fsp_str_dbg(fsp
),
6080 smb_fname_str_dbg(smb_fname_dst
)));
6081 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6082 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6086 TALLOC_FREE(smb_fname_dst
);
6090 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6091 struct smb_request
*req
,
6095 struct smb_filename
*smb_fname_src
)
6099 char *newname
= NULL
;
6100 struct smb_filename
*smb_fname_dst
= NULL
;
6101 NTSTATUS status
= NT_STATUS_OK
;
6102 TALLOC_CTX
*ctx
= talloc_tos();
6105 return NT_STATUS_INVALID_HANDLE
;
6108 if (total_data
< 20) {
6109 return NT_STATUS_INVALID_PARAMETER
;
6112 overwrite
= (CVAL(pdata
,0) ? true : false);
6113 len
= IVAL(pdata
,16);
6115 if (len
> (total_data
- 20) || (len
== 0)) {
6116 return NT_STATUS_INVALID_PARAMETER
;
6119 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6120 &pdata
[20], len
, STR_TERMINATE
,
6122 if (!NT_STATUS_IS_OK(status
)) {
6126 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6129 status
= filename_convert(ctx
,
6131 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6136 if (!NT_STATUS_IS_OK(status
)) {
6140 if (fsp
->base_fsp
) {
6141 /* No stream names. */
6142 return NT_STATUS_NOT_SUPPORTED
;
6145 DEBUG(10,("smb_file_link_information: "
6146 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6147 fsp
->fnum
, fsp_str_dbg(fsp
),
6148 smb_fname_str_dbg(smb_fname_dst
)));
6149 status
= hardlink_internals(ctx
,
6156 TALLOC_FREE(smb_fname_dst
);
6160 /****************************************************************************
6161 Deal with SMB_FILE_RENAME_INFORMATION.
6162 ****************************************************************************/
6164 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6165 struct smb_request
*req
,
6169 struct smb_filename
*smb_fname_src
)
6174 char *newname
= NULL
;
6175 struct smb_filename
*smb_fname_dst
= NULL
;
6176 bool dest_has_wcard
= False
;
6177 NTSTATUS status
= NT_STATUS_OK
;
6179 TALLOC_CTX
*ctx
= talloc_tos();
6181 if (total_data
< 13) {
6182 return NT_STATUS_INVALID_PARAMETER
;
6185 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6186 root_fid
= IVAL(pdata
,4);
6187 len
= IVAL(pdata
,8);
6189 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6190 return NT_STATUS_INVALID_PARAMETER
;
6193 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6196 if (!NT_STATUS_IS_OK(status
)) {
6200 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6203 status
= resolve_dfspath_wcard(ctx
, conn
,
6204 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6209 if (!NT_STATUS_IS_OK(status
)) {
6213 /* Check the new name has no '/' characters. */
6214 if (strchr_m(newname
, '/')) {
6215 return NT_STATUS_NOT_SUPPORTED
;
6218 if (fsp
&& fsp
->base_fsp
) {
6219 /* newname must be a stream name. */
6220 if (newname
[0] != ':') {
6221 return NT_STATUS_NOT_SUPPORTED
;
6224 /* Create an smb_fname to call rename_internals_fsp() with. */
6225 status
= create_synthetic_smb_fname(talloc_tos(),
6226 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6228 if (!NT_STATUS_IS_OK(status
)) {
6233 * Set the original last component, since
6234 * rename_internals_fsp() requires it.
6236 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6238 if (smb_fname_dst
->original_lcomp
== NULL
) {
6239 status
= NT_STATUS_NO_MEMORY
;
6245 * Build up an smb_fname_dst based on the filename passed in.
6246 * We basically just strip off the last component, and put on
6247 * the newname instead.
6249 char *base_name
= NULL
;
6251 /* newname must *not* be a stream name. */
6252 if (newname
[0] == ':') {
6253 return NT_STATUS_NOT_SUPPORTED
;
6257 * Strip off the last component (filename) of the path passed
6260 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6262 return NT_STATUS_NO_MEMORY
;
6264 p
= strrchr_m(base_name
, '/');
6268 base_name
= talloc_strdup(ctx
, "");
6270 return NT_STATUS_NO_MEMORY
;
6273 /* Append the new name. */
6274 base_name
= talloc_asprintf_append(base_name
,
6278 return NT_STATUS_NO_MEMORY
;
6281 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6284 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6287 /* If an error we expect this to be
6288 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6290 if (!NT_STATUS_IS_OK(status
)) {
6291 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6295 /* Create an smb_fname to call rename_internals_fsp() */
6296 status
= create_synthetic_smb_fname(ctx
,
6300 if (!NT_STATUS_IS_OK(status
)) {
6307 DEBUG(10,("smb_file_rename_information: "
6308 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6309 fsp
->fnum
, fsp_str_dbg(fsp
),
6310 smb_fname_str_dbg(smb_fname_dst
)));
6311 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6314 DEBUG(10,("smb_file_rename_information: "
6315 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6316 smb_fname_str_dbg(smb_fname_src
),
6317 smb_fname_str_dbg(smb_fname_dst
)));
6318 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6319 smb_fname_dst
, 0, overwrite
, false,
6321 FILE_WRITE_ATTRIBUTES
);
6324 TALLOC_FREE(smb_fname_dst
);
6328 /****************************************************************************
6329 Deal with SMB_SET_POSIX_ACL.
6330 ****************************************************************************/
6332 #if defined(HAVE_POSIX_ACLS)
6333 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6337 const struct smb_filename
*smb_fname
)
6339 uint16 posix_acl_version
;
6340 uint16 num_file_acls
;
6341 uint16 num_def_acls
;
6342 bool valid_file_acls
= True
;
6343 bool valid_def_acls
= True
;
6345 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6346 return NT_STATUS_INVALID_PARAMETER
;
6348 posix_acl_version
= SVAL(pdata
,0);
6349 num_file_acls
= SVAL(pdata
,2);
6350 num_def_acls
= SVAL(pdata
,4);
6352 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6353 valid_file_acls
= False
;
6357 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6358 valid_def_acls
= False
;
6362 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6363 return NT_STATUS_INVALID_PARAMETER
;
6366 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6367 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6368 return NT_STATUS_INVALID_PARAMETER
;
6371 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6372 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6373 (unsigned int)num_file_acls
,
6374 (unsigned int)num_def_acls
));
6376 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6377 smb_fname
->base_name
, num_file_acls
,
6378 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6379 return map_nt_error_from_unix(errno
);
6382 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6383 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6384 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6385 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6386 return map_nt_error_from_unix(errno
);
6388 return NT_STATUS_OK
;
6392 /****************************************************************************
6393 Deal with SMB_SET_POSIX_LOCK.
6394 ****************************************************************************/
6396 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6397 struct smb_request
*req
,
6405 bool blocking_lock
= False
;
6406 enum brl_type lock_type
;
6408 NTSTATUS status
= NT_STATUS_OK
;
6410 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6411 return NT_STATUS_INVALID_HANDLE
;
6414 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6419 case POSIX_LOCK_TYPE_READ
:
6420 lock_type
= READ_LOCK
;
6422 case POSIX_LOCK_TYPE_WRITE
:
6423 /* Return the right POSIX-mappable error code for files opened read-only. */
6424 if (!fsp
->can_write
) {
6425 return NT_STATUS_INVALID_HANDLE
;
6427 lock_type
= WRITE_LOCK
;
6429 case POSIX_LOCK_TYPE_UNLOCK
:
6430 lock_type
= UNLOCK_LOCK
;
6433 return NT_STATUS_INVALID_PARAMETER
;
6436 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6437 blocking_lock
= False
;
6438 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6439 blocking_lock
= True
;
6441 return NT_STATUS_INVALID_PARAMETER
;
6444 if (!lp_blocking_locks(SNUM(conn
))) {
6445 blocking_lock
= False
;
6448 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6449 #if defined(HAVE_LONGLONG)
6450 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6451 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6452 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6453 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6454 #else /* HAVE_LONGLONG */
6455 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6456 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6457 #endif /* HAVE_LONGLONG */
6459 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6460 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6462 (unsigned int)lock_type
,
6463 (unsigned long long)smblctx
,
6467 if (lock_type
== UNLOCK_LOCK
) {
6468 status
= do_unlock(req
->sconn
->msg_ctx
,
6475 uint64_t block_smblctx
;
6477 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6489 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6491 * A blocking lock was requested. Package up
6492 * this smb into a queued request and push it
6493 * onto the blocking lock queue.
6495 if(push_blocking_lock_request(br_lck
,
6498 -1, /* infinite timeout. */
6506 TALLOC_FREE(br_lck
);
6510 TALLOC_FREE(br_lck
);
6516 /****************************************************************************
6517 Deal with SMB_SET_FILE_BASIC_INFO.
6518 ****************************************************************************/
6520 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6524 const struct smb_filename
*smb_fname
)
6526 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6527 struct smb_file_time ft
;
6529 NTSTATUS status
= NT_STATUS_OK
;
6533 if (total_data
< 36) {
6534 return NT_STATUS_INVALID_PARAMETER
;
6537 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6538 if (!NT_STATUS_IS_OK(status
)) {
6542 /* Set the attributes */
6543 dosmode
= IVAL(pdata
,32);
6544 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6545 if (!NT_STATUS_IS_OK(status
)) {
6550 ft
.create_time
= interpret_long_date(pdata
);
6553 ft
.atime
= interpret_long_date(pdata
+8);
6556 ft
.mtime
= interpret_long_date(pdata
+16);
6559 ft
.ctime
= interpret_long_date(pdata
+24);
6561 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6562 smb_fname_str_dbg(smb_fname
)));
6564 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6568 /****************************************************************************
6569 Deal with SMB_INFO_STANDARD.
6570 ****************************************************************************/
6572 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6576 const struct smb_filename
*smb_fname
)
6579 struct smb_file_time ft
;
6583 if (total_data
< 12) {
6584 return NT_STATUS_INVALID_PARAMETER
;
6588 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6590 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6592 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6594 DEBUG(10,("smb_set_info_standard: file %s\n",
6595 smb_fname_str_dbg(smb_fname
)));
6597 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6598 if (!NT_STATUS_IS_OK(status
)) {
6602 return smb_set_file_time(conn
,
6609 /****************************************************************************
6610 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6611 ****************************************************************************/
6613 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6614 struct smb_request
*req
,
6618 struct smb_filename
*smb_fname
)
6620 uint64_t allocation_size
= 0;
6621 NTSTATUS status
= NT_STATUS_OK
;
6622 files_struct
*new_fsp
= NULL
;
6624 if (!VALID_STAT(smb_fname
->st
)) {
6625 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6628 if (total_data
< 8) {
6629 return NT_STATUS_INVALID_PARAMETER
;
6632 allocation_size
= (uint64_t)IVAL(pdata
,0);
6633 #ifdef LARGE_SMB_OFF_T
6634 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6635 #else /* LARGE_SMB_OFF_T */
6636 if (IVAL(pdata
,4) != 0) {
6637 /* more than 32 bits? */
6638 return NT_STATUS_INVALID_PARAMETER
;
6640 #endif /* LARGE_SMB_OFF_T */
6642 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6643 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6644 (double)allocation_size
));
6646 if (allocation_size
) {
6647 allocation_size
= smb_roundup(conn
, allocation_size
);
6650 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6651 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6652 (double)allocation_size
));
6654 if (fsp
&& fsp
->fh
->fd
!= -1) {
6655 /* Open file handle. */
6656 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6657 return NT_STATUS_ACCESS_DENIED
;
6660 /* Only change if needed. */
6661 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6662 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6663 return map_nt_error_from_unix(errno
);
6666 /* But always update the time. */
6668 * This is equivalent to a write. Ensure it's seen immediately
6669 * if there are no pending writes.
6671 trigger_write_time_update_immediate(fsp
);
6672 return NT_STATUS_OK
;
6675 /* Pathname or stat or directory file. */
6676 status
= SMB_VFS_CREATE_FILE(
6679 0, /* root_dir_fid */
6680 smb_fname
, /* fname */
6681 FILE_WRITE_DATA
, /* access_mask */
6682 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6684 FILE_OPEN
, /* create_disposition*/
6685 0, /* create_options */
6686 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6687 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6688 0, /* allocation_size */
6689 0, /* private_flags */
6692 &new_fsp
, /* result */
6695 if (!NT_STATUS_IS_OK(status
)) {
6696 /* NB. We check for open_was_deferred in the caller. */
6700 /* Only change if needed. */
6701 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6702 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6703 status
= map_nt_error_from_unix(errno
);
6704 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6709 /* Changing the allocation size should set the last mod time. */
6711 * This is equivalent to a write. Ensure it's seen immediately
6712 * if there are no pending writes.
6714 trigger_write_time_update_immediate(new_fsp
);
6716 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6717 return NT_STATUS_OK
;
6720 /****************************************************************************
6721 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6722 ****************************************************************************/
6724 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6725 struct smb_request
*req
,
6729 const struct smb_filename
*smb_fname
,
6730 bool fail_after_createfile
)
6734 if (total_data
< 8) {
6735 return NT_STATUS_INVALID_PARAMETER
;
6738 size
= IVAL(pdata
,0);
6739 #ifdef LARGE_SMB_OFF_T
6740 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6741 #else /* LARGE_SMB_OFF_T */
6742 if (IVAL(pdata
,4) != 0) {
6743 /* more than 32 bits? */
6744 return NT_STATUS_INVALID_PARAMETER
;
6746 #endif /* LARGE_SMB_OFF_T */
6747 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6748 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6751 return smb_set_file_size(conn
, req
,
6756 fail_after_createfile
);
6759 /****************************************************************************
6760 Allow a UNIX info mknod.
6761 ****************************************************************************/
6763 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6766 const struct smb_filename
*smb_fname
)
6768 uint32 file_type
= IVAL(pdata
,56);
6769 #if defined(HAVE_MAKEDEV)
6770 uint32 dev_major
= IVAL(pdata
,60);
6771 uint32 dev_minor
= IVAL(pdata
,68);
6773 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6774 uint32 raw_unixmode
= IVAL(pdata
,84);
6778 if (total_data
< 100) {
6779 return NT_STATUS_INVALID_PARAMETER
;
6782 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6783 PERM_NEW_FILE
, &unixmode
);
6784 if (!NT_STATUS_IS_OK(status
)) {
6788 #if defined(HAVE_MAKEDEV)
6789 dev
= makedev(dev_major
, dev_minor
);
6792 switch (file_type
) {
6793 #if defined(S_IFIFO)
6794 case UNIX_TYPE_FIFO
:
6795 unixmode
|= S_IFIFO
;
6798 #if defined(S_IFSOCK)
6799 case UNIX_TYPE_SOCKET
:
6800 unixmode
|= S_IFSOCK
;
6803 #if defined(S_IFCHR)
6804 case UNIX_TYPE_CHARDEV
:
6805 unixmode
|= S_IFCHR
;
6808 #if defined(S_IFBLK)
6809 case UNIX_TYPE_BLKDEV
:
6810 unixmode
|= S_IFBLK
;
6814 return NT_STATUS_INVALID_PARAMETER
;
6817 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6818 "%.0f mode 0%o for file %s\n", (double)dev
,
6819 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6821 /* Ok - do the mknod. */
6822 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6823 return map_nt_error_from_unix(errno
);
6826 /* If any of the other "set" calls fail we
6827 * don't want to end up with a half-constructed mknod.
6830 if (lp_inherit_perms(SNUM(conn
))) {
6832 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6834 return NT_STATUS_NO_MEMORY
;
6836 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6838 TALLOC_FREE(parent
);
6841 return NT_STATUS_OK
;
6844 /****************************************************************************
6845 Deal with SMB_SET_FILE_UNIX_BASIC.
6846 ****************************************************************************/
6848 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6849 struct smb_request
*req
,
6853 const struct smb_filename
*smb_fname
)
6855 struct smb_file_time ft
;
6856 uint32 raw_unixmode
;
6859 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6860 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6861 NTSTATUS status
= NT_STATUS_OK
;
6862 bool delete_on_fail
= False
;
6863 enum perm_type ptype
;
6864 files_struct
*all_fsps
= NULL
;
6865 bool modify_mtime
= true;
6867 struct smb_filename
*smb_fname_tmp
= NULL
;
6868 SMB_STRUCT_STAT sbuf
;
6872 if (total_data
< 100) {
6873 return NT_STATUS_INVALID_PARAMETER
;
6876 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6877 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6878 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6879 #ifdef LARGE_SMB_OFF_T
6880 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6881 #else /* LARGE_SMB_OFF_T */
6882 if (IVAL(pdata
,4) != 0) {
6883 /* more than 32 bits? */
6884 return NT_STATUS_INVALID_PARAMETER
;
6886 #endif /* LARGE_SMB_OFF_T */
6889 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6890 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6891 set_owner
= (uid_t
)IVAL(pdata
,40);
6892 set_grp
= (gid_t
)IVAL(pdata
,48);
6893 raw_unixmode
= IVAL(pdata
,84);
6895 if (VALID_STAT(smb_fname
->st
)) {
6896 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6897 ptype
= PERM_EXISTING_DIR
;
6899 ptype
= PERM_EXISTING_FILE
;
6902 ptype
= PERM_NEW_FILE
;
6905 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6907 if (!NT_STATUS_IS_OK(status
)) {
6911 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6912 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6913 smb_fname_str_dbg(smb_fname
), (double)size
,
6914 (unsigned int)set_owner
, (unsigned int)set_grp
,
6915 (int)raw_unixmode
));
6917 sbuf
= smb_fname
->st
;
6919 if (!VALID_STAT(sbuf
)) {
6921 * The only valid use of this is to create character and block
6922 * devices, and named pipes. This is deprecated (IMHO) and
6923 * a new info level should be used for mknod. JRA.
6926 status
= smb_unix_mknod(conn
,
6930 if (!NT_STATUS_IS_OK(status
)) {
6934 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6936 if (!NT_STATUS_IS_OK(status
)) {
6940 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6941 status
= map_nt_error_from_unix(errno
);
6942 TALLOC_FREE(smb_fname_tmp
);
6943 SMB_VFS_UNLINK(conn
, smb_fname
);
6947 sbuf
= smb_fname_tmp
->st
;
6948 smb_fname
= smb_fname_tmp
;
6950 /* Ensure we don't try and change anything else. */
6951 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6952 size
= get_file_size_stat(&sbuf
);
6953 ft
.atime
= sbuf
.st_ex_atime
;
6954 ft
.mtime
= sbuf
.st_ex_mtime
;
6956 * We continue here as we might want to change the
6959 delete_on_fail
= True
;
6963 /* Horrible backwards compatibility hack as an old server bug
6964 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6968 size
= get_file_size_stat(&sbuf
);
6972 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6973 if (!NT_STATUS_IS_OK(status
)) {
6978 * Deal with the UNIX specific mode set.
6981 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6983 "setting mode 0%o for file %s\n",
6984 (unsigned int)unixmode
,
6985 smb_fname_str_dbg(smb_fname
)));
6986 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6987 return map_nt_error_from_unix(errno
);
6992 * Deal with the UNIX specific uid set.
6995 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6996 (sbuf
.st_ex_uid
!= set_owner
)) {
6999 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7000 "changing owner %u for path %s\n",
7001 (unsigned int)set_owner
,
7002 smb_fname_str_dbg(smb_fname
)));
7004 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7005 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7006 set_owner
, (gid_t
)-1);
7008 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7009 set_owner
, (gid_t
)-1);
7013 status
= map_nt_error_from_unix(errno
);
7014 if (delete_on_fail
) {
7015 SMB_VFS_UNLINK(conn
, smb_fname
);
7022 * Deal with the UNIX specific gid set.
7025 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7026 (sbuf
.st_ex_gid
!= set_grp
)) {
7027 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7028 "changing group %u for file %s\n",
7029 (unsigned int)set_owner
,
7030 smb_fname_str_dbg(smb_fname
)));
7031 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7033 status
= map_nt_error_from_unix(errno
);
7034 if (delete_on_fail
) {
7035 SMB_VFS_UNLINK(conn
, smb_fname
);
7041 /* Deal with any size changes. */
7043 status
= smb_set_file_size(conn
, req
,
7049 if (!NT_STATUS_IS_OK(status
)) {
7053 /* Deal with any time changes. */
7054 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7055 /* No change, don't cancel anything. */
7059 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7060 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7061 all_fsps
= file_find_di_next(all_fsps
)) {
7063 * We're setting the time explicitly for UNIX.
7064 * Cancel any pending changes over all handles.
7066 all_fsps
->update_write_time_on_close
= false;
7067 TALLOC_FREE(all_fsps
->update_write_time_event
);
7071 * Override the "setting_write_time"
7072 * parameter here as it almost does what
7073 * we need. Just remember if we modified
7074 * mtime and send the notify ourselves.
7076 if (null_timespec(ft
.mtime
)) {
7077 modify_mtime
= false;
7080 status
= smb_set_file_time(conn
,
7086 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7087 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7092 /****************************************************************************
7093 Deal with SMB_SET_FILE_UNIX_INFO2.
7094 ****************************************************************************/
7096 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7097 struct smb_request
*req
,
7101 const struct smb_filename
*smb_fname
)
7107 if (total_data
< 116) {
7108 return NT_STATUS_INVALID_PARAMETER
;
7111 /* Start by setting all the fields that are common between UNIX_BASIC
7114 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7116 if (!NT_STATUS_IS_OK(status
)) {
7120 smb_fflags
= IVAL(pdata
, 108);
7121 smb_fmask
= IVAL(pdata
, 112);
7123 /* NB: We should only attempt to alter the file flags if the client
7124 * sends a non-zero mask.
7126 if (smb_fmask
!= 0) {
7127 int stat_fflags
= 0;
7129 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7130 smb_fmask
, &stat_fflags
)) {
7131 /* Client asked to alter a flag we don't understand. */
7132 return NT_STATUS_INVALID_PARAMETER
;
7135 if (fsp
&& fsp
->fh
->fd
!= -1) {
7136 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7137 return NT_STATUS_NOT_SUPPORTED
;
7139 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7140 stat_fflags
) != 0) {
7141 return map_nt_error_from_unix(errno
);
7146 /* XXX: need to add support for changing the create_time here. You
7147 * can do this for paths on Darwin with setattrlist(2). The right way
7148 * to hook this up is probably by extending the VFS utimes interface.
7151 return NT_STATUS_OK
;
7154 /****************************************************************************
7155 Create a directory with POSIX semantics.
7156 ****************************************************************************/
7158 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7159 struct smb_request
*req
,
7162 struct smb_filename
*smb_fname
,
7163 int *pdata_return_size
)
7165 NTSTATUS status
= NT_STATUS_OK
;
7166 uint32 raw_unixmode
= 0;
7167 uint32 mod_unixmode
= 0;
7168 mode_t unixmode
= (mode_t
)0;
7169 files_struct
*fsp
= NULL
;
7170 uint16 info_level_return
= 0;
7172 char *pdata
= *ppdata
;
7174 if (total_data
< 18) {
7175 return NT_STATUS_INVALID_PARAMETER
;
7178 raw_unixmode
= IVAL(pdata
,8);
7179 /* Next 4 bytes are not yet defined. */
7181 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7182 PERM_NEW_DIR
, &unixmode
);
7183 if (!NT_STATUS_IS_OK(status
)) {
7187 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7189 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7190 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7192 status
= SMB_VFS_CREATE_FILE(
7195 0, /* root_dir_fid */
7196 smb_fname
, /* fname */
7197 FILE_READ_ATTRIBUTES
, /* access_mask */
7198 FILE_SHARE_NONE
, /* share_access */
7199 FILE_CREATE
, /* create_disposition*/
7200 FILE_DIRECTORY_FILE
, /* create_options */
7201 mod_unixmode
, /* file_attributes */
7202 0, /* oplock_request */
7203 0, /* allocation_size */
7204 0, /* private_flags */
7210 if (NT_STATUS_IS_OK(status
)) {
7211 close_file(req
, fsp
, NORMAL_CLOSE
);
7214 info_level_return
= SVAL(pdata
,16);
7216 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7217 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7218 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7219 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7221 *pdata_return_size
= 12;
7224 /* Realloc the data size */
7225 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7226 if (*ppdata
== NULL
) {
7227 *pdata_return_size
= 0;
7228 return NT_STATUS_NO_MEMORY
;
7232 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7233 SSVAL(pdata
,2,0); /* No fnum. */
7234 SIVAL(pdata
,4,info
); /* Was directory created. */
7236 switch (info_level_return
) {
7237 case SMB_QUERY_FILE_UNIX_BASIC
:
7238 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7239 SSVAL(pdata
,10,0); /* Padding. */
7240 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7243 case SMB_QUERY_FILE_UNIX_INFO2
:
7244 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7245 SSVAL(pdata
,10,0); /* Padding. */
7246 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7250 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7251 SSVAL(pdata
,10,0); /* Padding. */
7258 /****************************************************************************
7259 Open/Create a file with POSIX semantics.
7260 ****************************************************************************/
7262 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7263 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7265 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7266 struct smb_request
*req
,
7269 struct smb_filename
*smb_fname
,
7270 int *pdata_return_size
)
7272 bool extended_oplock_granted
= False
;
7273 char *pdata
= *ppdata
;
7275 uint32 wire_open_mode
= 0;
7276 uint32 raw_unixmode
= 0;
7277 uint32 mod_unixmode
= 0;
7278 uint32 create_disp
= 0;
7279 uint32 access_mask
= 0;
7280 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7281 NTSTATUS status
= NT_STATUS_OK
;
7282 mode_t unixmode
= (mode_t
)0;
7283 files_struct
*fsp
= NULL
;
7284 int oplock_request
= 0;
7286 uint16 info_level_return
= 0;
7288 if (total_data
< 18) {
7289 return NT_STATUS_INVALID_PARAMETER
;
7292 flags
= IVAL(pdata
,0);
7293 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7294 if (oplock_request
) {
7295 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7298 wire_open_mode
= IVAL(pdata
,4);
7300 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7301 return smb_posix_mkdir(conn
, req
,
7308 switch (wire_open_mode
& SMB_ACCMODE
) {
7310 access_mask
= SMB_O_RDONLY_MAPPING
;
7313 access_mask
= SMB_O_WRONLY_MAPPING
;
7316 access_mask
= (SMB_O_RDONLY_MAPPING
|
7317 SMB_O_WRONLY_MAPPING
);
7320 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7321 (unsigned int)wire_open_mode
));
7322 return NT_STATUS_INVALID_PARAMETER
;
7325 wire_open_mode
&= ~SMB_ACCMODE
;
7327 /* First take care of O_CREAT|O_EXCL interactions. */
7328 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7329 case (SMB_O_CREAT
| SMB_O_EXCL
):
7330 /* File exists fail. File not exist create. */
7331 create_disp
= FILE_CREATE
;
7334 /* File exists open. File not exist create. */
7335 create_disp
= FILE_OPEN_IF
;
7338 /* File exists open. File not exist fail. */
7339 create_disp
= FILE_OPEN
;
7342 /* O_EXCL on its own without O_CREAT is undefined. */
7344 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7345 (unsigned int)wire_open_mode
));
7346 return NT_STATUS_INVALID_PARAMETER
;
7349 /* Next factor in the effects of O_TRUNC. */
7350 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7352 if (wire_open_mode
& SMB_O_TRUNC
) {
7353 switch (create_disp
) {
7355 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7356 /* Leave create_disp alone as
7357 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7359 /* File exists fail. File not exist create. */
7362 /* SMB_O_CREAT | SMB_O_TRUNC */
7363 /* File exists overwrite. File not exist create. */
7364 create_disp
= FILE_OVERWRITE_IF
;
7368 /* File exists overwrite. File not exist fail. */
7369 create_disp
= FILE_OVERWRITE
;
7372 /* Cannot get here. */
7373 smb_panic("smb_posix_open: logic error");
7374 return NT_STATUS_INVALID_PARAMETER
;
7378 raw_unixmode
= IVAL(pdata
,8);
7379 /* Next 4 bytes are not yet defined. */
7381 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7382 (VALID_STAT(smb_fname
->st
) ?
7383 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7386 if (!NT_STATUS_IS_OK(status
)) {
7390 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7392 if (wire_open_mode
& SMB_O_SYNC
) {
7393 create_options
|= FILE_WRITE_THROUGH
;
7395 if (wire_open_mode
& SMB_O_APPEND
) {
7396 access_mask
|= FILE_APPEND_DATA
;
7398 if (wire_open_mode
& SMB_O_DIRECT
) {
7399 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7402 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7403 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7404 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7405 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7407 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7408 create_options
|= FILE_DIRECTORY_FILE
;
7411 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7412 smb_fname_str_dbg(smb_fname
),
7413 (unsigned int)wire_open_mode
,
7414 (unsigned int)unixmode
));
7416 status
= SMB_VFS_CREATE_FILE(
7419 0, /* root_dir_fid */
7420 smb_fname
, /* fname */
7421 access_mask
, /* access_mask */
7422 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7424 create_disp
, /* create_disposition*/
7425 create_options
, /* create_options */
7426 mod_unixmode
, /* file_attributes */
7427 oplock_request
, /* oplock_request */
7428 0, /* allocation_size */
7429 0, /* private_flags */
7435 if (!NT_STATUS_IS_OK(status
)) {
7439 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7440 extended_oplock_granted
= True
;
7443 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7444 extended_oplock_granted
= True
;
7447 info_level_return
= SVAL(pdata
,16);
7449 /* Allocate the correct return size. */
7451 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7452 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7453 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7454 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7456 *pdata_return_size
= 12;
7459 /* Realloc the data size */
7460 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7461 if (*ppdata
== NULL
) {
7462 close_file(req
, fsp
, ERROR_CLOSE
);
7463 *pdata_return_size
= 0;
7464 return NT_STATUS_NO_MEMORY
;
7468 if (extended_oplock_granted
) {
7469 if (flags
& REQUEST_BATCH_OPLOCK
) {
7470 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7472 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7474 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7475 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7477 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7480 SSVAL(pdata
,2,fsp
->fnum
);
7481 SIVAL(pdata
,4,info
); /* Was file created etc. */
7483 switch (info_level_return
) {
7484 case SMB_QUERY_FILE_UNIX_BASIC
:
7485 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7486 SSVAL(pdata
,10,0); /* padding. */
7487 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7490 case SMB_QUERY_FILE_UNIX_INFO2
:
7491 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7492 SSVAL(pdata
,10,0); /* padding. */
7493 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7497 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7498 SSVAL(pdata
,10,0); /* padding. */
7501 return NT_STATUS_OK
;
7504 /****************************************************************************
7505 Delete a file with POSIX semantics.
7506 ****************************************************************************/
7508 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7509 struct smb_request
*req
,
7512 struct smb_filename
*smb_fname
)
7514 NTSTATUS status
= NT_STATUS_OK
;
7515 files_struct
*fsp
= NULL
;
7519 int create_options
= 0;
7521 struct share_mode_lock
*lck
= NULL
;
7523 if (total_data
< 2) {
7524 return NT_STATUS_INVALID_PARAMETER
;
7527 flags
= SVAL(pdata
,0);
7529 if (!VALID_STAT(smb_fname
->st
)) {
7530 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7533 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7534 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7535 return NT_STATUS_NOT_A_DIRECTORY
;
7538 DEBUG(10,("smb_posix_unlink: %s %s\n",
7539 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7540 smb_fname_str_dbg(smb_fname
)));
7542 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7543 create_options
|= FILE_DIRECTORY_FILE
;
7546 status
= SMB_VFS_CREATE_FILE(
7549 0, /* root_dir_fid */
7550 smb_fname
, /* fname */
7551 DELETE_ACCESS
, /* access_mask */
7552 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7554 FILE_OPEN
, /* create_disposition*/
7555 create_options
, /* create_options */
7556 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7557 0, /* oplock_request */
7558 0, /* allocation_size */
7559 0, /* private_flags */
7565 if (!NT_STATUS_IS_OK(status
)) {
7570 * Don't lie to client. If we can't really delete due to
7571 * non-POSIX opens return SHARING_VIOLATION.
7574 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7577 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7578 "lock for file %s\n", fsp_str_dbg(fsp
)));
7579 close_file(req
, fsp
, NORMAL_CLOSE
);
7580 return NT_STATUS_INVALID_PARAMETER
;
7584 * See if others still have the file open. If this is the case, then
7585 * don't delete. If all opens are POSIX delete we can set the delete
7586 * on close disposition.
7588 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7589 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7590 if (is_valid_share_mode_entry(e
)) {
7591 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7594 /* Fail with sharing violation. */
7595 close_file(req
, fsp
, NORMAL_CLOSE
);
7597 return NT_STATUS_SHARING_VIOLATION
;
7602 * Set the delete on close.
7604 status
= smb_set_file_disposition_info(conn
,
7610 if (!NT_STATUS_IS_OK(status
)) {
7611 close_file(req
, fsp
, NORMAL_CLOSE
);
7616 return close_file(req
, fsp
, NORMAL_CLOSE
);
7619 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7620 struct smb_request
*req
,
7621 TALLOC_CTX
*mem_ctx
,
7622 uint16_t info_level
,
7624 struct smb_filename
*smb_fname
,
7625 char **ppdata
, int total_data
,
7628 char *pdata
= *ppdata
;
7629 NTSTATUS status
= NT_STATUS_OK
;
7630 int data_return_size
= 0;
7634 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7635 return NT_STATUS_INVALID_LEVEL
;
7638 if (!CAN_WRITE(conn
)) {
7639 /* Allow POSIX opens. The open path will deny
7640 * any non-readonly opens. */
7641 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7642 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7646 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7647 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7648 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7650 switch (info_level
) {
7652 case SMB_INFO_STANDARD
:
7654 status
= smb_set_info_standard(conn
,
7662 case SMB_INFO_SET_EA
:
7664 status
= smb_info_set_ea(conn
,
7672 case SMB_SET_FILE_BASIC_INFO
:
7673 case SMB_FILE_BASIC_INFORMATION
:
7675 status
= smb_set_file_basic_info(conn
,
7683 case SMB_FILE_ALLOCATION_INFORMATION
:
7684 case SMB_SET_FILE_ALLOCATION_INFO
:
7686 status
= smb_set_file_allocation_info(conn
, req
,
7694 case SMB_FILE_END_OF_FILE_INFORMATION
:
7695 case SMB_SET_FILE_END_OF_FILE_INFO
:
7698 * XP/Win7 both fail after the createfile with
7699 * SMB_SET_FILE_END_OF_FILE_INFO but not
7700 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7701 * The level is known here, so pass it down
7705 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7707 status
= smb_set_file_end_of_file_info(conn
, req
,
7716 case SMB_FILE_DISPOSITION_INFORMATION
:
7717 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7720 /* JRA - We used to just ignore this on a path ?
7721 * Shouldn't this be invalid level on a pathname
7724 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7725 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7728 status
= smb_set_file_disposition_info(conn
,
7736 case SMB_FILE_POSITION_INFORMATION
:
7738 status
= smb_file_position_information(conn
,
7745 case SMB_FILE_FULL_EA_INFORMATION
:
7747 status
= smb_set_file_full_ea_info(conn
,
7754 /* From tridge Samba4 :
7755 * MODE_INFORMATION in setfileinfo (I have no
7756 * idea what "mode information" on a file is - it takes a value of 0,
7757 * 2, 4 or 6. What could it be?).
7760 case SMB_FILE_MODE_INFORMATION
:
7762 status
= smb_file_mode_information(conn
,
7769 * CIFS UNIX extensions.
7772 case SMB_SET_FILE_UNIX_BASIC
:
7774 status
= smb_set_file_unix_basic(conn
, req
,
7782 case SMB_SET_FILE_UNIX_INFO2
:
7784 status
= smb_set_file_unix_info2(conn
, req
,
7792 case SMB_SET_FILE_UNIX_LINK
:
7795 /* We must have a pathname for this. */
7796 return NT_STATUS_INVALID_LEVEL
;
7798 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7799 total_data
, smb_fname
);
7803 case SMB_SET_FILE_UNIX_HLINK
:
7806 /* We must have a pathname for this. */
7807 return NT_STATUS_INVALID_LEVEL
;
7809 status
= smb_set_file_unix_hlink(conn
, req
,
7815 case SMB_FILE_RENAME_INFORMATION
:
7817 status
= smb_file_rename_information(conn
, req
,
7823 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7825 /* SMB2 rename information. */
7826 status
= smb2_file_rename_information(conn
, req
,
7832 case SMB_FILE_LINK_INFORMATION
:
7834 status
= smb_file_link_information(conn
, req
,
7840 #if defined(HAVE_POSIX_ACLS)
7841 case SMB_SET_POSIX_ACL
:
7843 status
= smb_set_posix_acl(conn
,
7852 case SMB_SET_POSIX_LOCK
:
7855 return NT_STATUS_INVALID_LEVEL
;
7857 status
= smb_set_posix_lock(conn
, req
,
7858 pdata
, total_data
, fsp
);
7862 case SMB_POSIX_PATH_OPEN
:
7865 /* We must have a pathname for this. */
7866 return NT_STATUS_INVALID_LEVEL
;
7869 status
= smb_posix_open(conn
, req
,
7877 case SMB_POSIX_PATH_UNLINK
:
7880 /* We must have a pathname for this. */
7881 return NT_STATUS_INVALID_LEVEL
;
7884 status
= smb_posix_unlink(conn
, req
,
7892 return NT_STATUS_INVALID_LEVEL
;
7895 if (!NT_STATUS_IS_OK(status
)) {
7899 *ret_data_size
= data_return_size
;
7900 return NT_STATUS_OK
;
7903 /****************************************************************************
7904 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7905 ****************************************************************************/
7907 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7908 struct smb_request
*req
,
7909 unsigned int tran_call
,
7910 char **pparams
, int total_params
,
7911 char **ppdata
, int total_data
,
7912 unsigned int max_data_bytes
)
7914 char *params
= *pparams
;
7915 char *pdata
= *ppdata
;
7917 struct smb_filename
*smb_fname
= NULL
;
7918 files_struct
*fsp
= NULL
;
7919 NTSTATUS status
= NT_STATUS_OK
;
7920 int data_return_size
= 0;
7923 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7927 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7928 if (total_params
< 4) {
7929 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7933 fsp
= file_fsp(req
, SVAL(params
,0));
7934 /* Basic check for non-null fsp. */
7935 if (!check_fsp_open(conn
, req
, fsp
)) {
7938 info_level
= SVAL(params
,2);
7940 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7942 if (!NT_STATUS_IS_OK(status
)) {
7943 reply_nterror(req
, status
);
7947 if(fsp
->fh
->fd
== -1) {
7949 * This is actually a SETFILEINFO on a directory
7950 * handle (returned from an NT SMB). NT5.0 seems
7951 * to do this call. JRA.
7953 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7954 /* Always do lstat for UNIX calls. */
7955 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7956 DEBUG(3,("call_trans2setfilepathinfo: "
7957 "SMB_VFS_LSTAT of %s failed "
7959 smb_fname_str_dbg(smb_fname
),
7961 reply_nterror(req
, map_nt_error_from_unix(errno
));
7965 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7966 DEBUG(3,("call_trans2setfilepathinfo: "
7967 "fileinfo of %s failed (%s)\n",
7968 smb_fname_str_dbg(smb_fname
),
7970 reply_nterror(req
, map_nt_error_from_unix(errno
));
7974 } else if (fsp
->print_file
) {
7976 * Doing a DELETE_ON_CLOSE should cancel a print job.
7978 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7979 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7981 DEBUG(3,("call_trans2setfilepathinfo: "
7982 "Cancelling print job (%s)\n",
7986 send_trans2_replies(conn
, req
, params
, 2,
7992 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7997 * Original code - this is an open file.
7999 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8000 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8001 "of fnum %d failed (%s)\n", fsp
->fnum
,
8003 reply_nterror(req
, map_nt_error_from_unix(errno
));
8011 if (total_params
< 7) {
8012 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8016 info_level
= SVAL(params
,0);
8017 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8018 total_params
- 6, STR_TERMINATE
,
8020 if (!NT_STATUS_IS_OK(status
)) {
8021 reply_nterror(req
, status
);
8025 status
= filename_convert(req
, conn
,
8026 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8031 if (!NT_STATUS_IS_OK(status
)) {
8032 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8033 reply_botherror(req
,
8034 NT_STATUS_PATH_NOT_COVERED
,
8035 ERRSRV
, ERRbadpath
);
8038 reply_nterror(req
, status
);
8042 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8044 * For CIFS UNIX extensions the target name may not exist.
8047 /* Always do lstat for UNIX calls. */
8048 SMB_VFS_LSTAT(conn
, smb_fname
);
8050 } else if (!VALID_STAT(smb_fname
->st
) &&
8051 SMB_VFS_STAT(conn
, smb_fname
)) {
8052 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8054 smb_fname_str_dbg(smb_fname
),
8056 reply_nterror(req
, map_nt_error_from_unix(errno
));
8061 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8062 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8063 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8065 /* Realloc the parameter size */
8066 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8067 if (*pparams
== NULL
) {
8068 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8075 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8081 if (!NT_STATUS_IS_OK(status
)) {
8082 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8083 /* We have re-scheduled this call. */
8086 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8087 /* We have re-scheduled this call. */
8090 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8091 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8092 ERRSRV
, ERRbadpath
);
8095 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8096 reply_openerror(req
, status
);
8100 reply_nterror(req
, status
);
8104 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8110 /****************************************************************************
8111 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8112 ****************************************************************************/
8114 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8115 char **pparams
, int total_params
,
8116 char **ppdata
, int total_data
,
8117 unsigned int max_data_bytes
)
8119 struct smb_filename
*smb_dname
= NULL
;
8120 char *params
= *pparams
;
8121 char *pdata
= *ppdata
;
8122 char *directory
= NULL
;
8123 NTSTATUS status
= NT_STATUS_OK
;
8124 struct ea_list
*ea_list
= NULL
;
8125 TALLOC_CTX
*ctx
= talloc_tos();
8127 if (!CAN_WRITE(conn
)) {
8128 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8132 if (total_params
< 5) {
8133 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8137 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8138 total_params
- 4, STR_TERMINATE
,
8140 if (!NT_STATUS_IS_OK(status
)) {
8141 reply_nterror(req
, status
);
8145 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8147 status
= filename_convert(ctx
,
8149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8155 if (!NT_STATUS_IS_OK(status
)) {
8156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8157 reply_botherror(req
,
8158 NT_STATUS_PATH_NOT_COVERED
,
8159 ERRSRV
, ERRbadpath
);
8162 reply_nterror(req
, status
);
8167 * OS/2 workplace shell seems to send SET_EA requests of "null"
8168 * length (4 bytes containing IVAL 4).
8169 * They seem to have no effect. Bug #3212. JRA.
8172 if (total_data
&& (total_data
!= 4)) {
8173 /* Any data in this call is an EA list. */
8174 if (total_data
< 10) {
8175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8179 if (IVAL(pdata
,0) > total_data
) {
8180 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8181 IVAL(pdata
,0), (unsigned int)total_data
));
8182 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8186 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8189 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8193 if (!lp_ea_support(SNUM(conn
))) {
8194 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8198 /* If total_data == 4 Windows doesn't care what values
8199 * are placed in that field, it just ignores them.
8200 * The System i QNTC IBM SMB client puts bad values here,
8201 * so ignore them. */
8203 status
= create_directory(conn
, req
, smb_dname
);
8205 if (!NT_STATUS_IS_OK(status
)) {
8206 reply_nterror(req
, status
);
8210 /* Try and set any given EA. */
8212 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8213 if (!NT_STATUS_IS_OK(status
)) {
8214 reply_nterror(req
, status
);
8219 /* Realloc the parameter and data sizes */
8220 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8221 if(*pparams
== NULL
) {
8222 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8229 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8232 TALLOC_FREE(smb_dname
);
8236 /****************************************************************************
8237 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8238 We don't actually do this - we just send a null response.
8239 ****************************************************************************/
8241 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8242 struct smb_request
*req
,
8243 char **pparams
, int total_params
,
8244 char **ppdata
, int total_data
,
8245 unsigned int max_data_bytes
)
8247 char *params
= *pparams
;
8250 if (total_params
< 6) {
8251 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8255 info_level
= SVAL(params
,4);
8256 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8258 switch (info_level
) {
8263 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8267 /* Realloc the parameter and data sizes */
8268 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8269 if (*pparams
== NULL
) {
8270 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8275 SSVAL(params
,0,fnf_handle
);
8276 SSVAL(params
,2,0); /* No changes */
8277 SSVAL(params
,4,0); /* No EA errors */
8284 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8289 /****************************************************************************
8290 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8291 changes). Currently this does nothing.
8292 ****************************************************************************/
8294 static void call_trans2findnotifynext(connection_struct
*conn
,
8295 struct smb_request
*req
,
8296 char **pparams
, int total_params
,
8297 char **ppdata
, int total_data
,
8298 unsigned int max_data_bytes
)
8300 char *params
= *pparams
;
8302 DEBUG(3,("call_trans2findnotifynext\n"));
8304 /* Realloc the parameter and data sizes */
8305 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8306 if (*pparams
== NULL
) {
8307 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8312 SSVAL(params
,0,0); /* No changes */
8313 SSVAL(params
,2,0); /* No EA errors */
8315 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8320 /****************************************************************************
8321 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8322 ****************************************************************************/
8324 static void call_trans2getdfsreferral(connection_struct
*conn
,
8325 struct smb_request
*req
,
8326 char **pparams
, int total_params
,
8327 char **ppdata
, int total_data
,
8328 unsigned int max_data_bytes
)
8330 char *params
= *pparams
;
8331 char *pathname
= NULL
;
8333 int max_referral_level
;
8334 NTSTATUS status
= NT_STATUS_OK
;
8335 TALLOC_CTX
*ctx
= talloc_tos();
8337 DEBUG(10,("call_trans2getdfsreferral\n"));
8339 if (total_params
< 3) {
8340 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8344 max_referral_level
= SVAL(params
,0);
8346 if(!lp_host_msdfs()) {
8347 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8351 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8352 total_params
- 2, STR_TERMINATE
);
8354 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8357 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8358 ppdata
,&status
)) < 0) {
8359 reply_nterror(req
, status
);
8363 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8364 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8365 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8370 #define LMCAT_SPL 0x53
8371 #define LMFUNC_GETJOBID 0x60
8373 /****************************************************************************
8374 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8375 ****************************************************************************/
8377 static void call_trans2ioctl(connection_struct
*conn
,
8378 struct smb_request
*req
,
8379 char **pparams
, int total_params
,
8380 char **ppdata
, int total_data
,
8381 unsigned int max_data_bytes
)
8383 char *pdata
= *ppdata
;
8384 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8386 /* check for an invalid fid before proceeding */
8389 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8393 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8394 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8395 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8396 if (*ppdata
== NULL
) {
8397 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8402 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8403 CAN ACCEPT THIS IN UNICODE. JRA. */
8406 if (fsp
->print_file
) {
8407 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8411 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8412 lp_netbios_name(), 15,
8413 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8414 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8415 lp_servicename(SNUM(conn
)), 13,
8416 STR_ASCII
|STR_TERMINATE
); /* Service name */
8417 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8422 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8423 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8426 /****************************************************************************
8427 Reply to a SMBfindclose (stop trans2 directory search).
8428 ****************************************************************************/
8430 void reply_findclose(struct smb_request
*req
)
8433 struct smbd_server_connection
*sconn
= req
->sconn
;
8435 START_PROFILE(SMBfindclose
);
8438 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8439 END_PROFILE(SMBfindclose
);
8443 dptr_num
= SVALS(req
->vwv
+0, 0);
8445 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8447 dptr_close(sconn
, &dptr_num
);
8449 reply_outbuf(req
, 0, 0);
8451 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8453 END_PROFILE(SMBfindclose
);
8457 /****************************************************************************
8458 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8459 ****************************************************************************/
8461 void reply_findnclose(struct smb_request
*req
)
8465 START_PROFILE(SMBfindnclose
);
8468 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8469 END_PROFILE(SMBfindnclose
);
8473 dptr_num
= SVAL(req
->vwv
+0, 0);
8475 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8477 /* We never give out valid handles for a
8478 findnotifyfirst - so any dptr_num is ok here.
8481 reply_outbuf(req
, 0, 0);
8483 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8485 END_PROFILE(SMBfindnclose
);
8489 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8490 struct trans_state
*state
)
8492 if (get_Protocol() >= PROTOCOL_NT1
) {
8493 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8494 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8497 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8498 if (state
->call
!= TRANSACT2_QFSINFO
&&
8499 state
->call
!= TRANSACT2_SETFSINFO
) {
8500 DEBUG(0,("handle_trans2: encryption required "
8502 (unsigned int)state
->call
));
8503 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8508 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8510 /* Now we must call the relevant TRANS2 function */
8511 switch(state
->call
) {
8512 case TRANSACT2_OPEN
:
8514 START_PROFILE(Trans2_open
);
8515 call_trans2open(conn
, req
,
8516 &state
->param
, state
->total_param
,
8517 &state
->data
, state
->total_data
,
8518 state
->max_data_return
);
8519 END_PROFILE(Trans2_open
);
8523 case TRANSACT2_FINDFIRST
:
8525 START_PROFILE(Trans2_findfirst
);
8526 call_trans2findfirst(conn
, req
,
8527 &state
->param
, state
->total_param
,
8528 &state
->data
, state
->total_data
,
8529 state
->max_data_return
);
8530 END_PROFILE(Trans2_findfirst
);
8534 case TRANSACT2_FINDNEXT
:
8536 START_PROFILE(Trans2_findnext
);
8537 call_trans2findnext(conn
, req
,
8538 &state
->param
, state
->total_param
,
8539 &state
->data
, state
->total_data
,
8540 state
->max_data_return
);
8541 END_PROFILE(Trans2_findnext
);
8545 case TRANSACT2_QFSINFO
:
8547 START_PROFILE(Trans2_qfsinfo
);
8548 call_trans2qfsinfo(conn
, req
,
8549 &state
->param
, state
->total_param
,
8550 &state
->data
, state
->total_data
,
8551 state
->max_data_return
);
8552 END_PROFILE(Trans2_qfsinfo
);
8556 case TRANSACT2_SETFSINFO
:
8558 START_PROFILE(Trans2_setfsinfo
);
8559 call_trans2setfsinfo(conn
, req
,
8560 &state
->param
, state
->total_param
,
8561 &state
->data
, state
->total_data
,
8562 state
->max_data_return
);
8563 END_PROFILE(Trans2_setfsinfo
);
8567 case TRANSACT2_QPATHINFO
:
8568 case TRANSACT2_QFILEINFO
:
8570 START_PROFILE(Trans2_qpathinfo
);
8571 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8572 &state
->param
, state
->total_param
,
8573 &state
->data
, state
->total_data
,
8574 state
->max_data_return
);
8575 END_PROFILE(Trans2_qpathinfo
);
8579 case TRANSACT2_SETPATHINFO
:
8580 case TRANSACT2_SETFILEINFO
:
8582 START_PROFILE(Trans2_setpathinfo
);
8583 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8584 &state
->param
, state
->total_param
,
8585 &state
->data
, state
->total_data
,
8586 state
->max_data_return
);
8587 END_PROFILE(Trans2_setpathinfo
);
8591 case TRANSACT2_FINDNOTIFYFIRST
:
8593 START_PROFILE(Trans2_findnotifyfirst
);
8594 call_trans2findnotifyfirst(conn
, req
,
8595 &state
->param
, state
->total_param
,
8596 &state
->data
, state
->total_data
,
8597 state
->max_data_return
);
8598 END_PROFILE(Trans2_findnotifyfirst
);
8602 case TRANSACT2_FINDNOTIFYNEXT
:
8604 START_PROFILE(Trans2_findnotifynext
);
8605 call_trans2findnotifynext(conn
, req
,
8606 &state
->param
, state
->total_param
,
8607 &state
->data
, state
->total_data
,
8608 state
->max_data_return
);
8609 END_PROFILE(Trans2_findnotifynext
);
8613 case TRANSACT2_MKDIR
:
8615 START_PROFILE(Trans2_mkdir
);
8616 call_trans2mkdir(conn
, req
,
8617 &state
->param
, state
->total_param
,
8618 &state
->data
, state
->total_data
,
8619 state
->max_data_return
);
8620 END_PROFILE(Trans2_mkdir
);
8624 case TRANSACT2_GET_DFS_REFERRAL
:
8626 START_PROFILE(Trans2_get_dfs_referral
);
8627 call_trans2getdfsreferral(conn
, req
,
8628 &state
->param
, state
->total_param
,
8629 &state
->data
, state
->total_data
,
8630 state
->max_data_return
);
8631 END_PROFILE(Trans2_get_dfs_referral
);
8635 case TRANSACT2_IOCTL
:
8637 START_PROFILE(Trans2_ioctl
);
8638 call_trans2ioctl(conn
, req
,
8639 &state
->param
, state
->total_param
,
8640 &state
->data
, state
->total_data
,
8641 state
->max_data_return
);
8642 END_PROFILE(Trans2_ioctl
);
8647 /* Error in request */
8648 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8649 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8653 /****************************************************************************
8654 Reply to a SMBtrans2.
8655 ****************************************************************************/
8657 void reply_trans2(struct smb_request
*req
)
8659 connection_struct
*conn
= req
->conn
;
8664 unsigned int tran_call
;
8665 struct trans_state
*state
;
8668 START_PROFILE(SMBtrans2
);
8670 if (req
->wct
< 14) {
8671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8672 END_PROFILE(SMBtrans2
);
8676 dsoff
= SVAL(req
->vwv
+12, 0);
8677 dscnt
= SVAL(req
->vwv
+11, 0);
8678 psoff
= SVAL(req
->vwv
+10, 0);
8679 pscnt
= SVAL(req
->vwv
+9, 0);
8680 tran_call
= SVAL(req
->vwv
+14, 0);
8682 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8683 if (!NT_STATUS_IS_OK(result
)) {
8684 DEBUG(2, ("Got invalid trans2 request: %s\n",
8685 nt_errstr(result
)));
8686 reply_nterror(req
, result
);
8687 END_PROFILE(SMBtrans2
);
8692 switch (tran_call
) {
8693 /* List the allowed trans2 calls on IPC$ */
8694 case TRANSACT2_OPEN
:
8695 case TRANSACT2_GET_DFS_REFERRAL
:
8696 case TRANSACT2_QFILEINFO
:
8697 case TRANSACT2_QFSINFO
:
8698 case TRANSACT2_SETFSINFO
:
8701 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8702 END_PROFILE(SMBtrans2
);
8707 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8708 DEBUG(0, ("talloc failed\n"));
8709 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8710 END_PROFILE(SMBtrans2
);
8714 state
->cmd
= SMBtrans2
;
8716 state
->mid
= req
->mid
;
8717 state
->vuid
= req
->vuid
;
8718 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8719 state
->setup
= NULL
;
8720 state
->total_param
= SVAL(req
->vwv
+0, 0);
8721 state
->param
= NULL
;
8722 state
->total_data
= SVAL(req
->vwv
+1, 0);
8724 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8725 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8726 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8727 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8728 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8730 state
->call
= tran_call
;
8732 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8733 is so as a sanity check */
8734 if (state
->setup_count
!= 1) {
8736 * Need to have rc=0 for ioctl to get job id for OS/2.
8737 * Network printing will fail if function is not successful.
8738 * Similar function in reply.c will be used if protocol
8739 * is LANMAN1.0 instead of LM1.2X002.
8740 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8741 * outbuf doesn't have to be set(only job id is used).
8743 if ( (state
->setup_count
== 4)
8744 && (tran_call
== TRANSACT2_IOCTL
)
8745 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8746 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8747 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8749 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8750 DEBUG(2,("Transaction is %d\n",tran_call
));
8752 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8753 END_PROFILE(SMBtrans2
);
8758 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8761 if (state
->total_data
) {
8763 if (trans_oob(state
->total_data
, 0, dscnt
)
8764 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8768 /* Can't use talloc here, the core routines do realloc on the
8769 * params and data. */
8770 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8771 if (state
->data
== NULL
) {
8772 DEBUG(0,("reply_trans2: data malloc fail for %u "
8773 "bytes !\n", (unsigned int)state
->total_data
));
8775 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8776 END_PROFILE(SMBtrans2
);
8780 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8783 if (state
->total_param
) {
8785 if (trans_oob(state
->total_param
, 0, pscnt
)
8786 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8790 /* Can't use talloc here, the core routines do realloc on the
8791 * params and data. */
8792 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8793 if (state
->param
== NULL
) {
8794 DEBUG(0,("reply_trans: param malloc fail for %u "
8795 "bytes !\n", (unsigned int)state
->total_param
));
8796 SAFE_FREE(state
->data
);
8798 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8799 END_PROFILE(SMBtrans2
);
8803 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8806 state
->received_data
= dscnt
;
8807 state
->received_param
= pscnt
;
8809 if ((state
->received_param
== state
->total_param
) &&
8810 (state
->received_data
== state
->total_data
)) {
8812 handle_trans2(conn
, req
, state
);
8814 SAFE_FREE(state
->data
);
8815 SAFE_FREE(state
->param
);
8817 END_PROFILE(SMBtrans2
);
8821 DLIST_ADD(conn
->pending_trans
, state
);
8823 /* We need to send an interim response then receive the rest
8824 of the parameter/data bytes */
8825 reply_outbuf(req
, 0, 0);
8826 show_msg((char *)req
->outbuf
);
8827 END_PROFILE(SMBtrans2
);
8832 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8833 SAFE_FREE(state
->data
);
8834 SAFE_FREE(state
->param
);
8836 END_PROFILE(SMBtrans2
);
8837 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8841 /****************************************************************************
8842 Reply to a SMBtranss2
8843 ****************************************************************************/
8845 void reply_transs2(struct smb_request
*req
)
8847 connection_struct
*conn
= req
->conn
;
8848 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8849 struct trans_state
*state
;
8851 START_PROFILE(SMBtranss2
);
8853 show_msg((const char *)req
->inbuf
);
8856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8857 END_PROFILE(SMBtranss2
);
8861 for (state
= conn
->pending_trans
; state
!= NULL
;
8862 state
= state
->next
) {
8863 if (state
->mid
== req
->mid
) {
8868 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8869 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8870 END_PROFILE(SMBtranss2
);
8874 /* Revise state->total_param and state->total_data in case they have
8875 changed downwards */
8877 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8878 state
->total_param
= SVAL(req
->vwv
+0, 0);
8879 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8880 state
->total_data
= SVAL(req
->vwv
+1, 0);
8882 pcnt
= SVAL(req
->vwv
+2, 0);
8883 poff
= SVAL(req
->vwv
+3, 0);
8884 pdisp
= SVAL(req
->vwv
+4, 0);
8886 dcnt
= SVAL(req
->vwv
+5, 0);
8887 doff
= SVAL(req
->vwv
+6, 0);
8888 ddisp
= SVAL(req
->vwv
+7, 0);
8890 state
->received_param
+= pcnt
;
8891 state
->received_data
+= dcnt
;
8893 if ((state
->received_data
> state
->total_data
) ||
8894 (state
->received_param
> state
->total_param
))
8898 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8899 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8902 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8906 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8907 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8910 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8913 if ((state
->received_param
< state
->total_param
) ||
8914 (state
->received_data
< state
->total_data
)) {
8915 END_PROFILE(SMBtranss2
);
8919 handle_trans2(conn
, req
, state
);
8921 DLIST_REMOVE(conn
->pending_trans
, state
);
8922 SAFE_FREE(state
->data
);
8923 SAFE_FREE(state
->param
);
8926 END_PROFILE(SMBtranss2
);
8931 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8932 DLIST_REMOVE(conn
->pending_trans
, state
);
8933 SAFE_FREE(state
->data
);
8934 SAFE_FREE(state
->param
);
8936 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8937 END_PROFILE(SMBtranss2
);