2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct
*conn
,
37 const SMB_STRUCT_STAT
*psbuf
);
39 static char *store_file_unix_basic_info2(connection_struct
*conn
,
42 const SMB_STRUCT_STAT
*psbuf
);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
51 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type
= get_remote_arch();
55 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
56 val
= SMB_ROUNDUP(val
,rval
);
61 /********************************************************************
62 Create a 64 bit FileIndex. If the file is on the same device as
63 the root of the share, just return the 64-bit inode. If it isn't,
64 mangle as we used to do.
65 ********************************************************************/
67 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
70 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
71 return (uint64_t)psbuf
->st_ex_ino
;
73 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
74 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
78 /****************************************************************************
79 Utility functions for dealing with extended attributes.
80 ****************************************************************************/
82 /****************************************************************************
83 Refuse to allow clients to overwrite our private xattrs.
84 ****************************************************************************/
86 static bool samba_private_attr_name(const char *unix_ea_name
)
88 static const char * const prohibited_ea_names
[] = {
89 SAMBA_POSIX_INHERITANCE_EA_NAME
,
90 SAMBA_XATTR_DOS_ATTRIB
,
98 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
99 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
102 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
103 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
109 /****************************************************************************
110 Get one EA value. Fill in a struct ea_struct.
111 ****************************************************************************/
113 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
114 files_struct
*fsp
, const char *fname
,
115 const char *ea_name
, struct ea_struct
*pea
)
117 /* Get the value of this xattr. Max size is 64k. */
118 size_t attr_size
= 256;
124 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
126 return NT_STATUS_NO_MEMORY
;
129 if (fsp
&& fsp
->fh
->fd
!= -1) {
130 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
132 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
135 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
141 return map_nt_error_from_unix(errno
);
144 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
145 dump_data(10, (uint8
*)val
, sizeret
);
148 if (strnequal(ea_name
, "user.", 5)) {
149 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
151 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
153 if (pea
->name
== NULL
) {
155 return NT_STATUS_NO_MEMORY
;
157 pea
->value
.data
= (unsigned char *)val
;
158 pea
->value
.length
= (size_t)sizeret
;
162 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
163 files_struct
*fsp
, const char *fname
,
164 char ***pnames
, size_t *pnum_names
)
166 /* Get a list of all xattrs. Max namesize is 64k. */
167 size_t ea_namelist_size
= 1024;
168 char *ea_namelist
= NULL
;
173 ssize_t sizeret
= -1;
175 if (!lp_ea_support(SNUM(conn
))) {
184 * TALLOC the result early to get the talloc hierarchy right.
187 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
189 DEBUG(0, ("talloc failed\n"));
190 return NT_STATUS_NO_MEMORY
;
193 while (ea_namelist_size
<= 65536) {
195 ea_namelist
= TALLOC_REALLOC_ARRAY(
196 names
, ea_namelist
, char, ea_namelist_size
);
197 if (ea_namelist
== NULL
) {
198 DEBUG(0, ("talloc failed\n"));
200 return NT_STATUS_NO_MEMORY
;
203 if (fsp
&& fsp
->fh
->fd
!= -1) {
204 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
207 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
211 if ((sizeret
== -1) && (errno
== ERANGE
)) {
212 ea_namelist_size
*= 2;
221 return map_nt_error_from_unix(errno
);
224 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
225 (unsigned int)sizeret
));
237 * Ensure the result is 0-terminated
240 if (ea_namelist
[sizeret
-1] != '\0') {
242 return NT_STATUS_INTERNAL_ERROR
;
250 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
254 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
256 DEBUG(0, ("talloc failed\n"));
258 return NT_STATUS_NO_MEMORY
;
264 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
265 names
[num_names
++] = p
;
273 *pnum_names
= num_names
;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
282 const char *fname
, size_t *pea_total_len
)
284 /* Get a list of all xattrs. Max namesize is 64k. */
287 struct ea_list
*ea_list_head
= NULL
;
292 if (!lp_ea_support(SNUM(conn
))) {
296 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
299 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
303 for (i
=0; i
<num_names
; i
++) {
304 struct ea_list
*listp
;
307 if (strnequal(names
[i
], "system.", 7)
308 || samba_private_attr_name(names
[i
]))
311 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
322 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
325 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
329 (unsigned int)listp
->ea
.value
.length
));
331 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
335 /* Add on 4 for total length. */
336 if (*pea_total_len
) {
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len
));
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
352 connection_struct
*conn
, struct ea_list
*ea_list
)
354 unsigned int ret_data_size
= 4;
357 SMB_ASSERT(total_data_size
>= 4);
359 if (!lp_ea_support(SNUM(conn
))) {
364 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
367 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
368 dos_namelen
= strlen(dos_ea_name
);
369 if (dos_namelen
> 255 || dos_namelen
== 0) {
372 if (ea_list
->ea
.value
.length
> 65535) {
375 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
379 /* We know we have room. */
380 SCVAL(p
,0,ea_list
->ea
.flags
);
381 SCVAL(p
,1,dos_namelen
);
382 SSVAL(p
,2,ea_list
->ea
.value
.length
);
383 fstrcpy(p
+4, dos_ea_name
);
384 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
386 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
387 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
390 ret_data_size
= PTR_DIFF(p
, pdata
);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
392 SIVAL(pdata
,0,ret_data_size
);
393 return ret_data_size
;
396 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
398 unsigned int total_data_size
,
399 unsigned int *ret_data_size
,
400 connection_struct
*conn
,
401 struct ea_list
*ea_list
)
403 uint8_t *p
= (uint8_t *)pdata
;
404 uint8_t *last_start
= NULL
;
408 if (!lp_ea_support(SNUM(conn
))) {
409 return NT_STATUS_NO_EAS_ON_FILE
;
412 for (; ea_list
; ea_list
= ea_list
->next
) {
418 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
422 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
423 dos_namelen
= strlen(dos_ea_name
);
424 if (dos_namelen
> 255 || dos_namelen
== 0) {
425 return NT_STATUS_INTERNAL_ERROR
;
427 if (ea_list
->ea
.value
.length
> 65535) {
428 return NT_STATUS_INTERNAL_ERROR
;
431 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
434 size_t pad
= 4 - (this_size
% 4);
438 if (this_size
> total_data_size
) {
439 return NT_STATUS_INFO_LENGTH_MISMATCH
;
442 /* We know we have room. */
443 SIVAL(p
, 0x00, 0); /* next offset */
444 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
445 SCVAL(p
, 0x05, dos_namelen
);
446 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
447 fstrcpy((char *)(p
+0x08), dos_ea_name
);
448 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
450 total_data_size
-= this_size
;
454 *ret_data_size
= PTR_DIFF(p
, pdata
);
455 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
459 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
461 size_t total_ea_len
= 0;
462 TALLOC_CTX
*mem_ctx
= NULL
;
464 if (!lp_ea_support(SNUM(conn
))) {
467 mem_ctx
= talloc_tos();
468 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
472 /****************************************************************************
473 Ensure the EA name is case insensitive by matching any existing EA name.
474 ****************************************************************************/
476 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
479 TALLOC_CTX
*mem_ctx
= talloc_tos();
480 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
482 for (; ea_list
; ea_list
= ea_list
->next
) {
483 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
484 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
485 &unix_ea_name
[5], ea_list
->ea
.name
));
486 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
492 /****************************************************************************
493 Set or delete an extended attribute.
494 ****************************************************************************/
496 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
497 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
501 if (!lp_ea_support(SNUM(conn
))) {
502 return NT_STATUS_EAS_NOT_SUPPORTED
;
505 /* For now setting EAs on streams isn't supported. */
506 fname
= smb_fname
->base_name
;
508 for (;ea_list
; ea_list
= ea_list
->next
) {
510 fstring unix_ea_name
;
512 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
513 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
515 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
517 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
519 if (samba_private_attr_name(unix_ea_name
)) {
520 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
521 return NT_STATUS_ACCESS_DENIED
;
524 if (ea_list
->ea
.value
.length
== 0) {
525 /* Remove the attribute. */
526 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
527 DEBUG(10,("set_ea: deleting ea name %s on "
528 "file %s by file descriptor.\n",
529 unix_ea_name
, fsp_str_dbg(fsp
)));
530 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
532 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
533 unix_ea_name
, fname
));
534 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
537 /* Removing a non existent attribute always succeeds. */
538 if (ret
== -1 && errno
== ENOATTR
) {
539 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
545 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
546 DEBUG(10,("set_ea: setting ea name %s on file "
547 "%s by file descriptor.\n",
548 unix_ea_name
, fsp_str_dbg(fsp
)));
549 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
550 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
552 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
553 unix_ea_name
, fname
));
554 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
555 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
561 if (errno
== ENOTSUP
) {
562 return NT_STATUS_EAS_NOT_SUPPORTED
;
565 return map_nt_error_from_unix(errno
);
571 /****************************************************************************
572 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
573 ****************************************************************************/
575 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
577 struct ea_list
*ea_list_head
= NULL
;
578 size_t converted_size
, offset
= 0;
580 while (offset
+ 2 < data_size
) {
581 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
582 unsigned int namelen
= CVAL(pdata
,offset
);
584 offset
++; /* Go past the namelen byte. */
586 /* integer wrap paranioa. */
587 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
588 (offset
> data_size
) || (namelen
> data_size
) ||
589 (offset
+ namelen
>= data_size
)) {
592 /* Ensure the name is null terminated. */
593 if (pdata
[offset
+ namelen
] != '\0') {
596 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
598 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
599 "failed: %s", strerror(errno
)));
605 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
606 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
607 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
613 /****************************************************************************
614 Read one EA list entry from the buffer.
615 ****************************************************************************/
617 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
619 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
621 unsigned int namelen
;
622 size_t converted_size
;
632 eal
->ea
.flags
= CVAL(pdata
,0);
633 namelen
= CVAL(pdata
,1);
634 val_len
= SVAL(pdata
,2);
636 if (4 + namelen
+ 1 + val_len
> data_size
) {
640 /* Ensure the name is null terminated. */
641 if (pdata
[namelen
+ 4] != '\0') {
644 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
645 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
652 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
653 if (!eal
->ea
.value
.data
) {
657 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
659 /* Ensure we're null terminated just in case we print the value. */
660 eal
->ea
.value
.data
[val_len
] = '\0';
661 /* But don't count the null. */
662 eal
->ea
.value
.length
--;
665 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
668 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
669 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
674 /****************************************************************************
675 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
676 ****************************************************************************/
678 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
680 struct ea_list
*ea_list_head
= NULL
;
682 size_t bytes_used
= 0;
684 while (offset
< data_size
) {
685 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
691 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
692 offset
+= bytes_used
;
698 /****************************************************************************
699 Count the total EA size needed.
700 ****************************************************************************/
702 static size_t ea_list_size(struct ea_list
*ealist
)
705 struct ea_list
*listp
;
708 for (listp
= ealist
; listp
; listp
= listp
->next
) {
709 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
710 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
712 /* Add on 4 for total length. */
720 /****************************************************************************
721 Return a union of EA's from a file list and a list of names.
722 The TALLOC context for the two lists *MUST* be identical as we steal
723 memory from one list to add to another. JRA.
724 ****************************************************************************/
726 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
728 struct ea_list
*nlistp
, *flistp
;
730 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
731 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
732 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
738 /* Copy the data from this entry. */
739 nlistp
->ea
.flags
= flistp
->ea
.flags
;
740 nlistp
->ea
.value
= flistp
->ea
.value
;
743 nlistp
->ea
.flags
= 0;
744 ZERO_STRUCT(nlistp
->ea
.value
);
748 *total_ea_len
= ea_list_size(name_list
);
752 /****************************************************************************
753 Send the required number of replies back.
754 We assume all fields other than the data fields are
755 set correctly for the type of call.
756 HACK ! Always assumes smb_setup field is zero.
757 ****************************************************************************/
759 void send_trans2_replies(connection_struct
*conn
,
760 struct smb_request
*req
,
767 /* As we are using a protocol > LANMAN1 then the max_send
768 variable must have been set in the sessetupX call.
769 This takes precedence over the max_xmit field in the
770 global struct. These different max_xmit variables should
771 be merged as this is now too confusing */
773 int data_to_send
= datasize
;
774 int params_to_send
= paramsize
;
776 const char *pp
= params
;
777 const char *pd
= pdata
;
778 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
779 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
780 int data_alignment_offset
= 0;
781 bool overflow
= False
;
782 struct smbd_server_connection
*sconn
= smbd_server_conn
;
783 int max_send
= sconn
->smb1
.sessions
.max_send
;
785 /* Modify the data_to_send and datasize and set the error if
786 we're trying to send more than max_data_bytes. We still send
787 the part of the packet(s) that fit. Strange, but needed
790 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
791 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
792 max_data_bytes
, datasize
));
793 datasize
= data_to_send
= max_data_bytes
;
797 /* If there genuinely are no parameters or data to send just send the empty packet */
799 if(params_to_send
== 0 && data_to_send
== 0) {
800 reply_outbuf(req
, 10, 0);
801 show_msg((char *)req
->outbuf
);
802 if (!srv_send_smb(smbd_server_fd(),
805 IS_CONN_ENCRYPTED(conn
),
807 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
809 TALLOC_FREE(req
->outbuf
);
813 /* When sending params and data ensure that both are nicely aligned */
814 /* Only do this alignment when there is also data to send - else
815 can cause NT redirector problems. */
817 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
818 data_alignment_offset
= 4 - (params_to_send
% 4);
820 /* Space is bufsize minus Netbios over TCP header minus SMB header */
821 /* The alignment_offset is to align the param bytes on an even byte
822 boundary. NT 4.0 Beta needs this to work correctly. */
824 useable_space
= max_send
- (smb_size
827 + data_alignment_offset
);
829 if (useable_space
< 0) {
830 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
831 "= %d!!!", useable_space
));
832 exit_server_cleanly("send_trans2_replies: Not enough space");
835 while (params_to_send
|| data_to_send
) {
836 /* Calculate whether we will totally or partially fill this packet */
838 total_sent_thistime
= params_to_send
+ data_to_send
;
840 /* We can never send more than useable_space */
842 * Note that 'useable_space' does not include the alignment offsets,
843 * but we must include the alignment offsets in the calculation of
844 * the length of the data we send over the wire, as the alignment offsets
845 * are sent here. Fix from Marc_Jacobsen@hp.com.
848 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
850 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
851 + data_alignment_offset
);
854 * We might have SMBtrans2s in req which was transferred to
855 * the outbuf, fix that.
857 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
859 /* Set total params and data to be sent */
860 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
861 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
863 /* Calculate how many parameters and data we can fit into
864 * this packet. Parameters get precedence
867 params_sent_thistime
= MIN(params_to_send
,useable_space
);
868 data_sent_thistime
= useable_space
- params_sent_thistime
;
869 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
871 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
873 /* smb_proff is the offset from the start of the SMB header to the
874 parameter bytes, however the first 4 bytes of outbuf are
875 the Netbios over TCP header. Thus use smb_base() to subtract
876 them from the calculation */
878 SSVAL(req
->outbuf
,smb_proff
,
879 ((smb_buf(req
->outbuf
)+alignment_offset
)
880 - smb_base(req
->outbuf
)));
882 if(params_sent_thistime
== 0)
883 SSVAL(req
->outbuf
,smb_prdisp
,0);
885 /* Absolute displacement of param bytes sent in this packet */
886 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
888 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
889 if(data_sent_thistime
== 0) {
890 SSVAL(req
->outbuf
,smb_droff
,0);
891 SSVAL(req
->outbuf
,smb_drdisp
, 0);
893 /* The offset of the data bytes is the offset of the
894 parameter bytes plus the number of parameters being sent this time */
895 SSVAL(req
->outbuf
, smb_droff
,
896 ((smb_buf(req
->outbuf
)+alignment_offset
)
897 - smb_base(req
->outbuf
))
898 + params_sent_thistime
+ data_alignment_offset
);
899 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
902 /* Initialize the padding for alignment */
904 if (alignment_offset
!= 0) {
905 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
908 /* Copy the param bytes into the packet */
910 if(params_sent_thistime
) {
911 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
912 params_sent_thistime
);
915 /* Copy in the data bytes */
916 if(data_sent_thistime
) {
917 if (data_alignment_offset
!= 0) {
918 memset((smb_buf(req
->outbuf
)+alignment_offset
+
919 params_sent_thistime
), 0,
920 data_alignment_offset
);
922 memcpy(smb_buf(req
->outbuf
)+alignment_offset
923 +params_sent_thistime
+data_alignment_offset
,
924 pd
,data_sent_thistime
);
927 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
928 params_sent_thistime
, data_sent_thistime
, useable_space
));
929 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
930 params_to_send
, data_to_send
, paramsize
, datasize
));
933 error_packet_set((char *)req
->outbuf
,
934 ERRDOS
,ERRbufferoverflow
,
935 STATUS_BUFFER_OVERFLOW
,
939 /* Send the packet */
940 show_msg((char *)req
->outbuf
);
941 if (!srv_send_smb(smbd_server_fd(),
944 IS_CONN_ENCRYPTED(conn
),
946 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
948 TALLOC_FREE(req
->outbuf
);
950 pp
+= params_sent_thistime
;
951 pd
+= data_sent_thistime
;
953 params_to_send
-= params_sent_thistime
;
954 data_to_send
-= data_sent_thistime
;
957 if(params_to_send
< 0 || data_to_send
< 0) {
958 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
959 params_to_send
, data_to_send
));
967 /****************************************************************************
968 Reply to a TRANSACT2_OPEN.
969 ****************************************************************************/
971 static void call_trans2open(connection_struct
*conn
,
972 struct smb_request
*req
,
973 char **pparams
, int total_params
,
974 char **ppdata
, int total_data
,
975 unsigned int max_data_bytes
)
977 struct smb_filename
*smb_fname
= NULL
;
978 char *params
= *pparams
;
979 char *pdata
= *ppdata
;
984 bool return_additional_info
;
997 struct ea_list
*ea_list
= NULL
;
1002 uint32 create_disposition
;
1003 uint32 create_options
= 0;
1004 uint32_t private_flags
= 0;
1005 TALLOC_CTX
*ctx
= talloc_tos();
1008 * Ensure we have enough parameters to perform the operation.
1011 if (total_params
< 29) {
1012 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1016 flags
= SVAL(params
, 0);
1017 deny_mode
= SVAL(params
, 2);
1018 open_attr
= SVAL(params
,6);
1019 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1020 if (oplock_request
) {
1021 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1025 return_additional_info
= BITSETW(params
,0);
1026 open_sattr
= SVAL(params
, 4);
1027 open_time
= make_unix_date3(params
+8);
1029 open_ofun
= SVAL(params
,12);
1030 open_size
= IVAL(params
,14);
1031 pname
= ¶ms
[28];
1034 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1038 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1039 total_params
- 28, STR_TERMINATE
,
1041 if (!NT_STATUS_IS_OK(status
)) {
1042 reply_nterror(req
, status
);
1046 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1047 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1048 (unsigned int)open_ofun
, open_size
));
1050 status
= filename_convert(ctx
,
1052 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1057 if (!NT_STATUS_IS_OK(status
)) {
1058 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1059 reply_botherror(req
,
1060 NT_STATUS_PATH_NOT_COVERED
,
1061 ERRSRV
, ERRbadpath
);
1064 reply_nterror(req
, status
);
1068 if (open_ofun
== 0) {
1069 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1073 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1074 &access_mask
, &share_mode
,
1075 &create_disposition
,
1078 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1082 /* Any data in this call is an EA list. */
1083 if (total_data
&& (total_data
!= 4)) {
1084 if (total_data
< 10) {
1085 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1089 if (IVAL(pdata
,0) > total_data
) {
1090 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1091 IVAL(pdata
,0), (unsigned int)total_data
));
1092 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1096 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1099 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1103 if (!lp_ea_support(SNUM(conn
))) {
1104 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1109 status
= SMB_VFS_CREATE_FILE(
1112 0, /* root_dir_fid */
1113 smb_fname
, /* fname */
1114 access_mask
, /* access_mask */
1115 share_mode
, /* share_access */
1116 create_disposition
, /* create_disposition*/
1117 create_options
, /* create_options */
1118 open_attr
, /* file_attributes */
1119 oplock_request
, /* oplock_request */
1120 open_size
, /* allocation_size */
1123 ea_list
, /* ea_list */
1125 &smb_action
); /* psbuf */
1127 if (!NT_STATUS_IS_OK(status
)) {
1128 if (open_was_deferred(req
->mid
)) {
1129 /* We have re-scheduled this call. */
1132 reply_openerror(req
, status
);
1136 size
= get_file_size_stat(&smb_fname
->st
);
1137 fattr
= dos_mode(conn
, smb_fname
);
1138 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1139 inode
= smb_fname
->st
.st_ex_ino
;
1141 close_file(req
, fsp
, ERROR_CLOSE
);
1142 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1146 /* Realloc the size of parameters and data we will return */
1147 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1148 if(*pparams
== NULL
) {
1149 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1154 SSVAL(params
,0,fsp
->fnum
);
1155 SSVAL(params
,2,fattr
);
1156 srv_put_dos_date2(params
,4, mtime
);
1157 SIVAL(params
,8, (uint32
)size
);
1158 SSVAL(params
,12,deny_mode
);
1159 SSVAL(params
,14,0); /* open_type - file or directory. */
1160 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1162 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1163 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1166 SSVAL(params
,18,smb_action
);
1169 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1171 SIVAL(params
,20,inode
);
1172 SSVAL(params
,24,0); /* Padding. */
1174 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1175 fsp
->fsp_name
->base_name
);
1176 SIVAL(params
, 26, ea_size
);
1178 SIVAL(params
, 26, 0);
1181 /* Send the required number of replies */
1182 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1184 TALLOC_FREE(smb_fname
);
1187 /*********************************************************
1188 Routine to check if a given string matches exactly.
1189 as a special case a mask of "." does NOT match. That
1190 is required for correct wildcard semantics
1191 Case can be significant or not.
1192 **********************************************************/
1194 static bool exact_match(bool has_wild
,
1195 bool case_sensitive
,
1199 if (mask
[0] == '.' && mask
[1] == 0) {
1207 if (case_sensitive
) {
1208 return strcmp(str
,mask
)==0;
1210 return StrCaseCmp(str
,mask
) == 0;
1214 /****************************************************************************
1215 Return the filetype for UNIX extensions.
1216 ****************************************************************************/
1218 static uint32
unix_filetype(mode_t mode
)
1221 return UNIX_TYPE_FILE
;
1222 else if(S_ISDIR(mode
))
1223 return UNIX_TYPE_DIR
;
1225 else if(S_ISLNK(mode
))
1226 return UNIX_TYPE_SYMLINK
;
1229 else if(S_ISCHR(mode
))
1230 return UNIX_TYPE_CHARDEV
;
1233 else if(S_ISBLK(mode
))
1234 return UNIX_TYPE_BLKDEV
;
1237 else if(S_ISFIFO(mode
))
1238 return UNIX_TYPE_FIFO
;
1241 else if(S_ISSOCK(mode
))
1242 return UNIX_TYPE_SOCKET
;
1245 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1246 return UNIX_TYPE_UNKNOWN
;
1249 /****************************************************************************
1250 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1251 ****************************************************************************/
1253 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1255 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1256 const SMB_STRUCT_STAT
*psbuf
,
1258 enum perm_type ptype
,
1263 if (perms
== SMB_MODE_NO_CHANGE
) {
1264 if (!VALID_STAT(*psbuf
)) {
1265 return NT_STATUS_INVALID_PARAMETER
;
1267 *ret_perms
= psbuf
->st_ex_mode
;
1268 return NT_STATUS_OK
;
1272 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1273 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1274 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1275 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1276 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1277 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1278 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1279 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1280 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1282 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1285 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1288 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1293 /* Apply mode mask */
1294 ret
&= lp_create_mask(SNUM(conn
));
1295 /* Add in force bits */
1296 ret
|= lp_force_create_mode(SNUM(conn
));
1299 ret
&= lp_dir_mask(SNUM(conn
));
1300 /* Add in force bits */
1301 ret
|= lp_force_dir_mode(SNUM(conn
));
1303 case PERM_EXISTING_FILE
:
1304 /* Apply mode mask */
1305 ret
&= lp_security_mask(SNUM(conn
));
1306 /* Add in force bits */
1307 ret
|= lp_force_security_mode(SNUM(conn
));
1309 case PERM_EXISTING_DIR
:
1310 /* Apply mode mask */
1311 ret
&= lp_dir_security_mask(SNUM(conn
));
1312 /* Add in force bits */
1313 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1318 return NT_STATUS_OK
;
1321 /****************************************************************************
1322 Needed to show the msdfs symlinks as directories. Modifies psbuf
1323 to be a directory if it's a msdfs link.
1324 ****************************************************************************/
1326 static bool check_msdfs_link(connection_struct
*conn
,
1327 const char *pathname
,
1328 SMB_STRUCT_STAT
*psbuf
)
1330 int saved_errno
= errno
;
1331 if(lp_host_msdfs() &&
1332 lp_msdfs_root(SNUM(conn
)) &&
1333 is_msdfs_link(conn
, pathname
, psbuf
)) {
1335 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1338 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1339 errno
= saved_errno
;
1342 errno
= saved_errno
;
1347 /****************************************************************************
1348 Get a level dependent lanman2 dir entry.
1349 ****************************************************************************/
1351 struct smbd_dirptr_lanman2_state
{
1352 connection_struct
*conn
;
1353 uint32_t info_level
;
1354 bool check_mangled_names
;
1356 bool got_exact_match
;
1359 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1365 struct smbd_dirptr_lanman2_state
*state
=
1366 (struct smbd_dirptr_lanman2_state
*)private_data
;
1368 char mangled_name
[13]; /* mangled 8.3 name. */
1372 /* Mangle fname if it's an illegal name. */
1373 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1374 ok
= name_to_8_3(dname
, mangled_name
,
1375 true, state
->conn
->params
);
1379 fname
= mangled_name
;
1384 got_match
= exact_match(state
->has_wild
,
1385 state
->conn
->case_sensitive
,
1387 state
->got_exact_match
= got_match
;
1389 got_match
= mask_match(fname
, mask
,
1390 state
->conn
->case_sensitive
);
1393 if(!got_match
&& state
->check_mangled_names
&&
1394 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1396 * It turns out that NT matches wildcards against
1397 * both long *and* short names. This may explain some
1398 * of the wildcard wierdness from old DOS clients
1399 * that some people have been seeing.... JRA.
1401 /* Force the mangling into 8.3. */
1402 ok
= name_to_8_3(fname
, mangled_name
,
1403 false, state
->conn
->params
);
1408 got_match
= exact_match(state
->has_wild
,
1409 state
->conn
->case_sensitive
,
1410 mangled_name
, mask
);
1411 state
->got_exact_match
= got_match
;
1413 got_match
= mask_match(mangled_name
, mask
,
1414 state
->conn
->case_sensitive
);
1422 *_fname
= talloc_strdup(ctx
, fname
);
1423 if (*_fname
== NULL
) {
1430 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1432 struct smb_filename
*smb_fname
,
1435 struct smbd_dirptr_lanman2_state
*state
=
1436 (struct smbd_dirptr_lanman2_state
*)private_data
;
1437 bool ms_dfs_link
= false;
1440 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1441 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1442 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1443 "Couldn't lstat [%s] (%s)\n",
1444 smb_fname_str_dbg(smb_fname
),
1448 } else if (!VALID_STAT(smb_fname
->st
) &&
1449 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1450 /* Needed to show the msdfs symlinks as
1453 ms_dfs_link
= check_msdfs_link(state
->conn
,
1454 smb_fname
->base_name
,
1457 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1458 "Couldn't stat [%s] (%s)\n",
1459 smb_fname_str_dbg(smb_fname
),
1466 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1468 mode
= dos_mode(state
->conn
, smb_fname
);
1475 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1476 connection_struct
*conn
,
1478 uint32_t info_level
,
1479 struct ea_list
*name_list
,
1480 bool check_mangled_names
,
1481 bool requires_resume_key
,
1484 const struct smb_filename
*smb_fname
,
1485 int space_remaining
,
1492 uint64_t *last_entry_off
)
1494 char *p
, *q
, *pdata
= *ppdata
;
1496 uint64_t file_size
= 0;
1497 uint64_t allocation_size
= 0;
1498 uint64_t file_index
= 0;
1500 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1501 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1502 time_t c_date
= (time_t)0;
1504 char *last_entry_ptr
;
1509 *out_of_space
= false;
1511 ZERO_STRUCT(mdate_ts
);
1512 ZERO_STRUCT(adate_ts
);
1513 ZERO_STRUCT(create_date_ts
);
1514 ZERO_STRUCT(cdate_ts
);
1516 if (!(mode
& aDIR
)) {
1517 file_size
= get_file_size_stat(&smb_fname
->st
);
1519 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1521 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1523 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1524 adate_ts
= smb_fname
->st
.st_ex_atime
;
1525 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1526 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1528 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1529 dos_filetime_timespec(&create_date_ts
);
1530 dos_filetime_timespec(&mdate_ts
);
1531 dos_filetime_timespec(&adate_ts
);
1532 dos_filetime_timespec(&cdate_ts
);
1535 create_date
= convert_timespec_to_time_t(create_date_ts
);
1536 mdate
= convert_timespec_to_time_t(mdate_ts
);
1537 adate
= convert_timespec_to_time_t(adate_ts
);
1538 c_date
= convert_timespec_to_time_t(cdate_ts
);
1540 /* align the record */
1541 SMB_ASSERT(align
>= 1);
1543 off
= (int)PTR_DIFF(pdata
, base_data
);
1544 pad
= (off
+ (align
-1)) & ~(align
-1);
1547 if (pad
&& pad
> space_remaining
) {
1548 *out_of_space
= true;
1549 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1550 "for padding (wanted %u, had %d)\n",
1553 return false; /* Not finished - just out of space */
1557 /* initialize padding to 0 */
1559 memset(pdata
, 0, pad
);
1561 space_remaining
-= pad
;
1563 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1573 switch (info_level
) {
1574 case SMB_FIND_INFO_STANDARD
:
1575 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1576 if(requires_resume_key
) {
1580 srv_put_dos_date2(p
,0,create_date
);
1581 srv_put_dos_date2(p
,4,adate
);
1582 srv_put_dos_date2(p
,8,mdate
);
1583 SIVAL(p
,12,(uint32
)file_size
);
1584 SIVAL(p
,16,(uint32
)allocation_size
);
1588 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1589 p
+= ucs2_align(base_data
, p
, 0);
1591 len
= srvstr_push(base_data
, flags2
, p
,
1592 fname
, PTR_DIFF(end_data
, p
),
1594 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1596 SCVAL(nameptr
, -1, len
- 2);
1598 SCVAL(nameptr
, -1, 0);
1602 SCVAL(nameptr
, -1, len
- 1);
1604 SCVAL(nameptr
, -1, 0);
1610 case SMB_FIND_EA_SIZE
:
1611 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1612 if (requires_resume_key
) {
1616 srv_put_dos_date2(p
,0,create_date
);
1617 srv_put_dos_date2(p
,4,adate
);
1618 srv_put_dos_date2(p
,8,mdate
);
1619 SIVAL(p
,12,(uint32
)file_size
);
1620 SIVAL(p
,16,(uint32
)allocation_size
);
1623 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1624 smb_fname
->base_name
);
1625 SIVAL(p
,22,ea_size
); /* Extended attributes */
1629 len
= srvstr_push(base_data
, flags2
,
1630 p
, fname
, PTR_DIFF(end_data
, p
),
1631 STR_TERMINATE
| STR_NOALIGN
);
1632 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1645 SCVAL(nameptr
,0,len
);
1647 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1650 case SMB_FIND_EA_LIST
:
1652 struct ea_list
*file_list
= NULL
;
1655 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1659 if (requires_resume_key
) {
1663 srv_put_dos_date2(p
,0,create_date
);
1664 srv_put_dos_date2(p
,4,adate
);
1665 srv_put_dos_date2(p
,8,mdate
);
1666 SIVAL(p
,12,(uint32
)file_size
);
1667 SIVAL(p
,16,(uint32
)allocation_size
);
1669 p
+= 22; /* p now points to the EA area. */
1671 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1672 smb_fname
->base_name
,
1674 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1676 /* We need to determine if this entry will fit in the space available. */
1677 /* Max string size is 255 bytes. */
1678 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1679 *out_of_space
= true;
1680 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1681 "(wanted %u, had %d)\n",
1682 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1684 return False
; /* Not finished - just out of space */
1687 /* Push the ea_data followed by the name. */
1688 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1690 len
= srvstr_push(base_data
, flags2
,
1691 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1692 STR_TERMINATE
| STR_NOALIGN
);
1693 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1706 SCVAL(nameptr
,0,len
);
1708 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1712 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1713 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1714 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1716 SIVAL(p
,0,reskey
); p
+= 4;
1717 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1718 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1719 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1720 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1721 SOFF_T(p
,0,file_size
); p
+= 8;
1722 SOFF_T(p
,0,allocation_size
); p
+= 8;
1723 SIVAL(p
,0,mode
); p
+= 4;
1724 q
= p
; p
+= 4; /* q is placeholder for name length. */
1726 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1727 smb_fname
->base_name
);
1728 SIVAL(p
,0,ea_size
); /* Extended attributes */
1731 /* Clear the short name buffer. This is
1732 * IMPORTANT as not doing so will trigger
1733 * a Win2k client bug. JRA.
1735 if (!was_8_3
&& check_mangled_names
) {
1736 char mangled_name
[13]; /* mangled 8.3 name. */
1737 if (!name_to_8_3(fname
,mangled_name
,True
,
1739 /* Error - mangle failed ! */
1740 memset(mangled_name
,'\0',12);
1742 mangled_name
[12] = 0;
1743 len
= srvstr_push(base_data
, flags2
,
1744 p
+2, mangled_name
, 24,
1745 STR_UPPER
|STR_UNICODE
);
1747 memset(p
+ 2 + len
,'\0',24 - len
);
1754 len
= srvstr_push(base_data
, flags2
, p
,
1755 fname
, PTR_DIFF(end_data
, p
),
1756 STR_TERMINATE_ASCII
);
1760 len
= PTR_DIFF(p
, pdata
);
1761 pad
= (len
+ (align
-1)) & ~(align
-1);
1763 * offset to the next entry, the caller
1764 * will overwrite it for the last entry
1765 * that's why we always include the padding
1769 * set padding to zero
1772 memset(p
, 0, pad
- len
);
1779 case SMB_FIND_FILE_DIRECTORY_INFO
:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1782 SIVAL(p
,0,reskey
); p
+= 4;
1783 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1784 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1787 SOFF_T(p
,0,file_size
); p
+= 8;
1788 SOFF_T(p
,0,allocation_size
); p
+= 8;
1789 SIVAL(p
,0,mode
); p
+= 4;
1790 len
= srvstr_push(base_data
, flags2
,
1791 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1792 STR_TERMINATE_ASCII
);
1796 len
= PTR_DIFF(p
, pdata
);
1797 pad
= (len
+ (align
-1)) & ~(align
-1);
1799 * offset to the next entry, the caller
1800 * will overwrite it for the last entry
1801 * that's why we always include the padding
1805 * set padding to zero
1808 memset(p
, 0, pad
- len
);
1815 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1816 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1818 SIVAL(p
,0,reskey
); p
+= 4;
1819 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1820 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1821 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1822 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1823 SOFF_T(p
,0,file_size
); p
+= 8;
1824 SOFF_T(p
,0,allocation_size
); p
+= 8;
1825 SIVAL(p
,0,mode
); p
+= 4;
1826 q
= p
; p
+= 4; /* q is placeholder for name length. */
1828 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1829 smb_fname
->base_name
);
1830 SIVAL(p
,0,ea_size
); /* Extended attributes */
1833 len
= srvstr_push(base_data
, flags2
, p
,
1834 fname
, PTR_DIFF(end_data
, p
),
1835 STR_TERMINATE_ASCII
);
1839 len
= PTR_DIFF(p
, pdata
);
1840 pad
= (len
+ (align
-1)) & ~(align
-1);
1842 * offset to the next entry, the caller
1843 * will overwrite it for the last entry
1844 * that's why we always include the padding
1848 * set padding to zero
1851 memset(p
, 0, pad
- len
);
1858 case SMB_FIND_FILE_NAMES_INFO
:
1859 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1861 SIVAL(p
,0,reskey
); p
+= 4;
1863 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1864 acl on a dir (tridge) */
1865 len
= srvstr_push(base_data
, flags2
, p
,
1866 fname
, PTR_DIFF(end_data
, p
),
1867 STR_TERMINATE_ASCII
);
1871 len
= PTR_DIFF(p
, pdata
);
1872 pad
= (len
+ (align
-1)) & ~(align
-1);
1874 * offset to the next entry, the caller
1875 * will overwrite it for the last entry
1876 * that's why we always include the padding
1880 * set padding to zero
1883 memset(p
, 0, pad
- len
);
1890 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1891 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1893 SIVAL(p
,0,reskey
); p
+= 4;
1894 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1895 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1896 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1897 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1898 SOFF_T(p
,0,file_size
); p
+= 8;
1899 SOFF_T(p
,0,allocation_size
); p
+= 8;
1900 SIVAL(p
,0,mode
); p
+= 4;
1901 q
= p
; p
+= 4; /* q is placeholder for name length. */
1903 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1904 smb_fname
->base_name
);
1905 SIVAL(p
,0,ea_size
); /* Extended attributes */
1908 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1909 SBVAL(p
,0,file_index
); p
+= 8;
1910 len
= srvstr_push(base_data
, flags2
, p
,
1911 fname
, PTR_DIFF(end_data
, p
),
1912 STR_TERMINATE_ASCII
);
1916 len
= PTR_DIFF(p
, pdata
);
1917 pad
= (len
+ (align
-1)) & ~(align
-1);
1919 * offset to the next entry, the caller
1920 * will overwrite it for the last entry
1921 * that's why we always include the padding
1925 * set padding to zero
1928 memset(p
, 0, pad
- len
);
1935 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1937 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1939 SIVAL(p
,0,reskey
); p
+= 4;
1940 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1941 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1942 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1943 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1944 SOFF_T(p
,0,file_size
); p
+= 8;
1945 SOFF_T(p
,0,allocation_size
); p
+= 8;
1946 SIVAL(p
,0,mode
); p
+= 4;
1947 q
= p
; p
+= 4; /* q is placeholder for name length */
1949 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1950 smb_fname
->base_name
);
1951 SIVAL(p
,0,ea_size
); /* Extended attributes */
1954 /* Clear the short name buffer. This is
1955 * IMPORTANT as not doing so will trigger
1956 * a Win2k client bug. JRA.
1958 if (!was_8_3
&& check_mangled_names
) {
1959 char mangled_name
[13]; /* mangled 8.3 name. */
1960 if (!name_to_8_3(fname
,mangled_name
,True
,
1962 /* Error - mangle failed ! */
1963 memset(mangled_name
,'\0',12);
1965 mangled_name
[12] = 0;
1966 len
= srvstr_push(base_data
, flags2
,
1967 p
+2, mangled_name
, 24,
1968 STR_UPPER
|STR_UNICODE
);
1971 memset(p
+ 2 + len
,'\0',24 - len
);
1978 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1979 SBVAL(p
,0,file_index
); p
+= 8;
1980 len
= srvstr_push(base_data
, flags2
, p
,
1981 fname
, PTR_DIFF(end_data
, p
),
1982 STR_TERMINATE_ASCII
);
1986 len
= PTR_DIFF(p
, pdata
);
1987 pad
= (len
+ (align
-1)) & ~(align
-1);
1989 * offset to the next entry, the caller
1990 * will overwrite it for the last entry
1991 * that's why we always include the padding
1995 * set padding to zero
1998 memset(p
, 0, pad
- len
);
2005 /* CIFS UNIX Extension. */
2007 case SMB_FIND_FILE_UNIX
:
2008 case SMB_FIND_FILE_UNIX_INFO2
:
2010 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2012 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2014 if (info_level
== SMB_FIND_FILE_UNIX
) {
2015 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2016 p
= store_file_unix_basic(conn
, p
,
2017 NULL
, &smb_fname
->st
);
2018 len
= srvstr_push(base_data
, flags2
, p
,
2019 fname
, PTR_DIFF(end_data
, p
),
2022 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2023 p
= store_file_unix_basic_info2(conn
, p
,
2024 NULL
, &smb_fname
->st
);
2027 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2028 PTR_DIFF(end_data
, p
), 0);
2029 SIVAL(nameptr
, 0, len
);
2034 len
= PTR_DIFF(p
, pdata
);
2035 pad
= (len
+ (align
-1)) & ~(align
-1);
2037 * offset to the next entry, the caller
2038 * will overwrite it for the last entry
2039 * that's why we always include the padding
2043 * set padding to zero
2046 memset(p
, 0, pad
- len
);
2051 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2059 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2060 *out_of_space
= true;
2061 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2062 "(wanted %u, had %d)\n",
2063 (unsigned int)PTR_DIFF(p
,pdata
),
2065 return false; /* Not finished - just out of space */
2068 /* Setup the last entry pointer, as an offset from base_data */
2069 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2070 /* Advance the data pointer to the next slot */
2076 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2077 connection_struct
*conn
,
2078 struct dptr_struct
*dirptr
,
2080 const char *path_mask
,
2083 int requires_resume_key
,
2091 int space_remaining
,
2093 bool *got_exact_match
,
2094 int *_last_entry_off
,
2095 struct ea_list
*name_list
)
2098 const char *mask
= NULL
;
2099 long prev_dirpos
= 0;
2102 struct smb_filename
*smb_fname
= NULL
;
2103 struct smbd_dirptr_lanman2_state state
;
2105 uint64_t last_entry_off
= 0;
2109 state
.info_level
= info_level
;
2110 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2111 state
.has_wild
= dptr_has_wild(dirptr
);
2112 state
.got_exact_match
= false;
2114 *out_of_space
= false;
2115 *got_exact_match
= false;
2117 p
= strrchr_m(path_mask
,'/');
2128 ok
= smbd_dirptr_get_entry(ctx
,
2134 smbd_dirptr_lanman2_match_fn
,
2135 smbd_dirptr_lanman2_mode_fn
,
2145 *got_exact_match
= state
.got_exact_match
;
2147 ok
= smbd_marshall_dir_entry(ctx
,
2152 state
.check_mangled_names
,
2153 requires_resume_key
,
2166 TALLOC_FREE(smb_fname
);
2167 if (*out_of_space
) {
2168 dptr_SeekDir(dirptr
, prev_dirpos
);
2175 *_last_entry_off
= last_entry_off
;
2179 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2180 connection_struct
*conn
,
2181 struct dptr_struct
*dirptr
,
2183 const char *path_mask
,
2186 bool requires_resume_key
,
2192 int space_remaining
,
2194 bool *got_exact_match
,
2195 int *last_entry_off
,
2196 struct ea_list
*name_list
)
2199 const bool do_pad
= true;
2201 if (info_level
>= 1 && info_level
<= 3) {
2202 /* No alignment on earlier info levels. */
2206 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2207 path_mask
, dirtype
, info_level
,
2208 requires_resume_key
, dont_descend
, ask_sharemode
,
2210 ppdata
, base_data
, end_data
,
2212 out_of_space
, got_exact_match
,
2213 last_entry_off
, name_list
);
2216 /****************************************************************************
2217 Reply to a TRANS2_FINDFIRST.
2218 ****************************************************************************/
2220 static void call_trans2findfirst(connection_struct
*conn
,
2221 struct smb_request
*req
,
2222 char **pparams
, int total_params
,
2223 char **ppdata
, int total_data
,
2224 unsigned int max_data_bytes
)
2226 /* We must be careful here that we don't return more than the
2227 allowed number of data bytes. If this means returning fewer than
2228 maxentries then so be it. We assume that the redirector has
2229 enough room for the fixed number of parameter bytes it has
2231 struct smb_filename
*smb_dname
= NULL
;
2232 char *params
= *pparams
;
2233 char *pdata
= *ppdata
;
2237 uint16 findfirst_flags
;
2238 bool close_after_first
;
2240 bool requires_resume_key
;
2242 char *directory
= NULL
;
2245 int last_entry_off
=0;
2249 bool finished
= False
;
2250 bool dont_descend
= False
;
2251 bool out_of_space
= False
;
2252 int space_remaining
;
2253 bool mask_contains_wcard
= False
;
2254 struct ea_list
*ea_list
= NULL
;
2255 NTSTATUS ntstatus
= NT_STATUS_OK
;
2256 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2257 TALLOC_CTX
*ctx
= talloc_tos();
2258 struct dptr_struct
*dirptr
= NULL
;
2259 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2261 if (total_params
< 13) {
2262 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2266 dirtype
= SVAL(params
,0);
2267 maxentries
= SVAL(params
,2);
2268 findfirst_flags
= SVAL(params
,4);
2269 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2270 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2271 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2272 info_level
= SVAL(params
,6);
2274 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2275 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2276 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2277 info_level
, max_data_bytes
));
2280 /* W2K3 seems to treat zero as 1. */
2284 switch (info_level
) {
2285 case SMB_FIND_INFO_STANDARD
:
2286 case SMB_FIND_EA_SIZE
:
2287 case SMB_FIND_EA_LIST
:
2288 case SMB_FIND_FILE_DIRECTORY_INFO
:
2289 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2290 case SMB_FIND_FILE_NAMES_INFO
:
2291 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2292 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2293 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2295 case SMB_FIND_FILE_UNIX
:
2296 case SMB_FIND_FILE_UNIX_INFO2
:
2297 /* Always use filesystem for UNIX mtime query. */
2298 ask_sharemode
= false;
2299 if (!lp_unix_extensions()) {
2300 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2305 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2309 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2310 params
+12, total_params
- 12,
2311 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2312 if (!NT_STATUS_IS_OK(ntstatus
)) {
2313 reply_nterror(req
, ntstatus
);
2317 ntstatus
= filename_convert(ctx
, conn
,
2318 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2321 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2322 &mask_contains_wcard
,
2324 if (!NT_STATUS_IS_OK(ntstatus
)) {
2325 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2326 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2327 ERRSRV
, ERRbadpath
);
2330 reply_nterror(req
, ntstatus
);
2334 mask
= smb_dname
->original_lcomp
;
2336 directory
= smb_dname
->base_name
;
2338 p
= strrchr_m(directory
,'/');
2340 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2341 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2342 mask
= talloc_strdup(ctx
,"*");
2344 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2347 mask_contains_wcard
= True
;
2349 directory
= talloc_strdup(talloc_tos(), "./");
2351 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2358 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2360 if (info_level
== SMB_FIND_EA_LIST
) {
2363 if (total_data
< 4) {
2364 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2368 ea_size
= IVAL(pdata
,0);
2369 if (ea_size
!= total_data
) {
2370 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2371 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2372 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2376 if (!lp_ea_support(SNUM(conn
))) {
2377 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2381 /* Pull out the list of names. */
2382 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2384 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2389 *ppdata
= (char *)SMB_REALLOC(
2390 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2391 if(*ppdata
== NULL
) {
2392 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2396 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2398 /* Realloc the params space */
2399 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2400 if (*pparams
== NULL
) {
2401 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2406 /* Save the wildcard match and attribs we are using on this directory -
2407 needed as lanman2 assumes these are being saved between calls */
2409 ntstatus
= dptr_create(conn
,
2415 mask_contains_wcard
,
2419 if (!NT_STATUS_IS_OK(ntstatus
)) {
2420 reply_nterror(req
, ntstatus
);
2424 dptr_num
= dptr_dnum(dirptr
);
2425 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2427 /* Initialize per TRANS2_FIND_FIRST operation data */
2428 dptr_init_search_op(dirptr
);
2430 /* We don't need to check for VOL here as this is returned by
2431 a different TRANS2 call. */
2433 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2434 directory
,lp_dontdescend(SNUM(conn
))));
2435 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2436 dont_descend
= True
;
2439 space_remaining
= max_data_bytes
;
2440 out_of_space
= False
;
2442 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2443 bool got_exact_match
= False
;
2445 /* this is a heuristic to avoid seeking the dirptr except when
2446 absolutely necessary. It allows for a filename of about 40 chars */
2447 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2448 out_of_space
= True
;
2451 finished
= !get_lanman2_dir_entry(ctx
,
2455 mask
,dirtype
,info_level
,
2456 requires_resume_key
,dont_descend
,
2459 space_remaining
, &out_of_space
,
2461 &last_entry_off
, ea_list
);
2464 if (finished
&& out_of_space
)
2467 if (!finished
&& !out_of_space
)
2471 * As an optimisation if we know we aren't looking
2472 * for a wildcard name (ie. the name matches the wildcard exactly)
2473 * then we can finish on any (first) match.
2474 * This speeds up large directory searches. JRA.
2480 /* Ensure space_remaining never goes -ve. */
2481 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2482 space_remaining
= 0;
2483 out_of_space
= true;
2485 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2489 /* Check if we can close the dirptr */
2490 if(close_after_first
|| (finished
&& close_if_end
)) {
2491 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2492 dptr_close(sconn
, &dptr_num
);
2496 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2497 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2498 * the protocol level is less than NT1. Tested with smbclient. JRA.
2499 * This should fix the OS/2 client bug #2335.
2502 if(numentries
== 0) {
2503 dptr_close(sconn
, &dptr_num
);
2504 if (get_Protocol() < PROTOCOL_NT1
) {
2505 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2508 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2509 ERRDOS
, ERRbadfile
);
2514 /* At this point pdata points to numentries directory entries. */
2516 /* Set up the return parameter block */
2517 SSVAL(params
,0,dptr_num
);
2518 SSVAL(params
,2,numentries
);
2519 SSVAL(params
,4,finished
);
2520 SSVAL(params
,6,0); /* Never an EA error */
2521 SSVAL(params
,8,last_entry_off
);
2523 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2526 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2527 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2529 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2533 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2534 smb_fn_name(req
->cmd
),
2535 mask
, directory
, dirtype
, numentries
) );
2538 * Force a name mangle here to ensure that the
2539 * mask as an 8.3 name is top of the mangled cache.
2540 * The reasons for this are subtle. Don't remove
2541 * this code unless you know what you are doing
2542 * (see PR#13758). JRA.
2545 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2546 char mangled_name
[13];
2547 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2550 TALLOC_FREE(smb_dname
);
2554 /****************************************************************************
2555 Reply to a TRANS2_FINDNEXT.
2556 ****************************************************************************/
2558 static void call_trans2findnext(connection_struct
*conn
,
2559 struct smb_request
*req
,
2560 char **pparams
, int total_params
,
2561 char **ppdata
, int total_data
,
2562 unsigned int max_data_bytes
)
2564 /* We must be careful here that we don't return more than the
2565 allowed number of data bytes. If this means returning fewer than
2566 maxentries then so be it. We assume that the redirector has
2567 enough room for the fixed number of parameter bytes it has
2569 char *params
= *pparams
;
2570 char *pdata
= *ppdata
;
2576 uint16 findnext_flags
;
2577 bool close_after_request
;
2579 bool requires_resume_key
;
2581 bool mask_contains_wcard
= False
;
2582 char *resume_name
= NULL
;
2583 const char *mask
= NULL
;
2584 const char *directory
= NULL
;
2588 int i
, last_entry_off
=0;
2589 bool finished
= False
;
2590 bool dont_descend
= False
;
2591 bool out_of_space
= False
;
2592 int space_remaining
;
2593 struct ea_list
*ea_list
= NULL
;
2594 NTSTATUS ntstatus
= NT_STATUS_OK
;
2595 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2596 TALLOC_CTX
*ctx
= talloc_tos();
2597 struct dptr_struct
*dirptr
;
2598 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2600 if (total_params
< 13) {
2601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2605 dptr_num
= SVAL(params
,0);
2606 maxentries
= SVAL(params
,2);
2607 info_level
= SVAL(params
,4);
2608 resume_key
= IVAL(params
,6);
2609 findnext_flags
= SVAL(params
,10);
2610 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2611 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2612 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2613 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2615 if (!continue_bit
) {
2616 /* We only need resume_name if continue_bit is zero. */
2617 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2619 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2620 &mask_contains_wcard
);
2621 if (!NT_STATUS_IS_OK(ntstatus
)) {
2622 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2623 complain (it thinks we're asking for the directory above the shared
2624 path or an invalid name). Catch this as the resume name is only compared, never used in
2625 a file access. JRA. */
2626 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2627 &resume_name
, params
+12,
2631 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2632 reply_nterror(req
, ntstatus
);
2638 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2639 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2640 resume_key = %d resume name = %s continue=%d level = %d\n",
2641 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2642 requires_resume_key
, resume_key
,
2643 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2646 /* W2K3 seems to treat zero as 1. */
2650 switch (info_level
) {
2651 case SMB_FIND_INFO_STANDARD
:
2652 case SMB_FIND_EA_SIZE
:
2653 case SMB_FIND_EA_LIST
:
2654 case SMB_FIND_FILE_DIRECTORY_INFO
:
2655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2656 case SMB_FIND_FILE_NAMES_INFO
:
2657 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2658 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2659 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2661 case SMB_FIND_FILE_UNIX
:
2662 case SMB_FIND_FILE_UNIX_INFO2
:
2663 /* Always use filesystem for UNIX mtime query. */
2664 ask_sharemode
= false;
2665 if (!lp_unix_extensions()) {
2666 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2671 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2675 if (info_level
== SMB_FIND_EA_LIST
) {
2678 if (total_data
< 4) {
2679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2683 ea_size
= IVAL(pdata
,0);
2684 if (ea_size
!= total_data
) {
2685 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2686 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2691 if (!lp_ea_support(SNUM(conn
))) {
2692 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2696 /* Pull out the list of names. */
2697 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2704 *ppdata
= (char *)SMB_REALLOC(
2705 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2706 if(*ppdata
== NULL
) {
2707 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2712 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2714 /* Realloc the params space */
2715 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2716 if(*pparams
== NULL
) {
2717 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2723 /* Check that the dptr is valid */
2724 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2725 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2729 directory
= dptr_path(sconn
, dptr_num
);
2731 /* Get the wildcard mask from the dptr */
2732 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2733 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2734 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2740 /* Get the attr mask from the dptr */
2741 dirtype
= dptr_attr(sconn
, dptr_num
);
2743 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2744 dptr_num
, mask
, dirtype
,
2746 dptr_TellDir(dirptr
)));
2748 /* Initialize per TRANS2_FIND_NEXT operation data */
2749 dptr_init_search_op(dirptr
);
2751 /* We don't need to check for VOL here as this is returned by
2752 a different TRANS2 call. */
2754 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2755 directory
,lp_dontdescend(SNUM(conn
))));
2756 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2757 dont_descend
= True
;
2760 space_remaining
= max_data_bytes
;
2761 out_of_space
= False
;
2764 * Seek to the correct position. We no longer use the resume key but
2765 * depend on the last file name instead.
2768 if(!continue_bit
&& resume_name
&& *resume_name
) {
2771 long current_pos
= 0;
2773 * Remember, name_to_8_3 is called by
2774 * get_lanman2_dir_entry(), so the resume name
2775 * could be mangled. Ensure we check the unmangled name.
2778 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2779 char *new_resume_name
= NULL
;
2780 mangle_lookup_name_from_8_3(ctx
,
2784 if (new_resume_name
) {
2785 resume_name
= new_resume_name
;
2790 * Fix for NT redirector problem triggered by resume key indexes
2791 * changing between directory scans. We now return a resume key of 0
2792 * and instead look for the filename to continue from (also given
2793 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2794 * findfirst/findnext (as is usual) then the directory pointer
2795 * should already be at the correct place.
2798 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2799 } /* end if resume_name && !continue_bit */
2801 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2802 bool got_exact_match
= False
;
2804 /* this is a heuristic to avoid seeking the dirptr except when
2805 absolutely necessary. It allows for a filename of about 40 chars */
2806 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2807 out_of_space
= True
;
2810 finished
= !get_lanman2_dir_entry(ctx
,
2814 mask
,dirtype
,info_level
,
2815 requires_resume_key
,dont_descend
,
2818 space_remaining
, &out_of_space
,
2820 &last_entry_off
, ea_list
);
2823 if (finished
&& out_of_space
)
2826 if (!finished
&& !out_of_space
)
2830 * As an optimisation if we know we aren't looking
2831 * for a wildcard name (ie. the name matches the wildcard exactly)
2832 * then we can finish on any (first) match.
2833 * This speeds up large directory searches. JRA.
2839 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2842 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2843 smb_fn_name(req
->cmd
),
2844 mask
, directory
, dirtype
, numentries
) );
2846 /* Check if we can close the dirptr */
2847 if(close_after_request
|| (finished
&& close_if_end
)) {
2848 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2849 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2852 /* Set up the return parameter block */
2853 SSVAL(params
,0,numentries
);
2854 SSVAL(params
,2,finished
);
2855 SSVAL(params
,4,0); /* Never an EA error */
2856 SSVAL(params
,6,last_entry_off
);
2858 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2864 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2866 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2870 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2872 SMB_ASSERT(extended_info
!= NULL
);
2874 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2875 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2876 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2877 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2878 #ifdef SAMBA_VERSION_REVISION
2879 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2881 extended_info
->samba_subversion
= 0;
2882 #ifdef SAMBA_VERSION_RC_RELEASE
2883 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2885 #ifdef SAMBA_VERSION_PRE_RELEASE
2886 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2889 #ifdef SAMBA_VERSION_VENDOR_PATCH
2890 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2892 extended_info
->samba_gitcommitdate
= 0;
2893 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2894 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2897 memset(extended_info
->samba_version_string
, 0,
2898 sizeof(extended_info
->samba_version_string
));
2900 snprintf (extended_info
->samba_version_string
,
2901 sizeof(extended_info
->samba_version_string
),
2902 "%s", samba_version_string());
2905 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2906 TALLOC_CTX
*mem_ctx
,
2907 uint16_t info_level
,
2909 unsigned int max_data_bytes
,
2913 char *pdata
, *end_data
;
2914 int data_len
= 0, len
;
2915 const char *vname
= volume_label(SNUM(conn
));
2916 int snum
= SNUM(conn
);
2917 char *fstype
= lp_fstype(SNUM(conn
));
2918 uint32 additional_flags
= 0;
2919 struct smb_filename smb_fname_dot
;
2923 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2924 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2925 "info level (0x%x) on IPC$.\n",
2926 (unsigned int)info_level
));
2927 return NT_STATUS_ACCESS_DENIED
;
2931 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2933 ZERO_STRUCT(smb_fname_dot
);
2934 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2936 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2937 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2938 return map_nt_error_from_unix(errno
);
2941 st
= smb_fname_dot
.st
;
2943 *ppdata
= (char *)SMB_REALLOC(
2944 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2945 if (*ppdata
== NULL
) {
2946 return NT_STATUS_NO_MEMORY
;
2950 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2951 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2953 switch (info_level
) {
2954 case SMB_INFO_ALLOCATION
:
2956 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2958 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2959 return map_nt_error_from_unix(errno
);
2962 block_size
= lp_block_size(snum
);
2963 if (bsize
< block_size
) {
2964 uint64_t factor
= block_size
/bsize
;
2969 if (bsize
> block_size
) {
2970 uint64_t factor
= bsize
/block_size
;
2975 bytes_per_sector
= 512;
2976 sectors_per_unit
= bsize
/bytes_per_sector
;
2978 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2979 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2980 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2982 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2983 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2984 SIVAL(pdata
,l1_cUnit
,dsize
);
2985 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2986 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2990 case SMB_INFO_VOLUME
:
2991 /* Return volume name */
2993 * Add volume serial number - hash of a combination of
2994 * the called hostname and the service name.
2996 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2998 * Win2k3 and previous mess this up by sending a name length
2999 * one byte short. I believe only older clients (OS/2 Win9x) use
3000 * this call so try fixing this by adding a terminating null to
3001 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3005 pdata
+l2_vol_szVolLabel
, vname
,
3006 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3007 STR_NOALIGN
|STR_TERMINATE
);
3008 SCVAL(pdata
,l2_vol_cch
,len
);
3009 data_len
= l2_vol_szVolLabel
+ len
;
3010 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3011 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3015 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3016 case SMB_FS_ATTRIBUTE_INFORMATION
:
3018 additional_flags
= 0;
3019 #if defined(HAVE_SYS_QUOTAS)
3020 additional_flags
|= FILE_VOLUME_QUOTAS
;
3023 if(lp_nt_acl_support(SNUM(conn
))) {
3024 additional_flags
|= FILE_PERSISTENT_ACLS
;
3027 /* Capabilities are filled in at connection time through STATVFS call */
3028 additional_flags
|= conn
->fs_capabilities
;
3029 additional_flags
|= lp_parm_int(conn
->params
->service
,
3030 "share", "fake_fscaps",
3033 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3034 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3035 additional_flags
); /* FS ATTRIBUTES */
3037 SIVAL(pdata
,4,255); /* Max filename component length */
3038 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3039 and will think we can't do long filenames */
3040 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3041 PTR_DIFF(end_data
, pdata
+12),
3044 data_len
= 12 + len
;
3047 case SMB_QUERY_FS_LABEL_INFO
:
3048 case SMB_FS_LABEL_INFORMATION
:
3049 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3050 PTR_DIFF(end_data
, pdata
+4), 0);
3055 case SMB_QUERY_FS_VOLUME_INFO
:
3056 case SMB_FS_VOLUME_INFORMATION
:
3059 * Add volume serial number - hash of a combination of
3060 * the called hostname and the service name.
3062 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3063 (str_checksum(get_local_machine_name())<<16));
3065 /* Max label len is 32 characters. */
3066 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3067 PTR_DIFF(end_data
, pdata
+18),
3069 SIVAL(pdata
,12,len
);
3072 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3073 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3076 case SMB_QUERY_FS_SIZE_INFO
:
3077 case SMB_FS_SIZE_INFORMATION
:
3079 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3081 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3082 return map_nt_error_from_unix(errno
);
3084 block_size
= lp_block_size(snum
);
3085 if (bsize
< block_size
) {
3086 uint64_t factor
= block_size
/bsize
;
3091 if (bsize
> block_size
) {
3092 uint64_t factor
= bsize
/block_size
;
3097 bytes_per_sector
= 512;
3098 sectors_per_unit
= bsize
/bytes_per_sector
;
3099 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3100 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3101 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3102 SBIG_UINT(pdata
,0,dsize
);
3103 SBIG_UINT(pdata
,8,dfree
);
3104 SIVAL(pdata
,16,sectors_per_unit
);
3105 SIVAL(pdata
,20,bytes_per_sector
);
3109 case SMB_FS_FULL_SIZE_INFORMATION
:
3111 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3113 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3114 return map_nt_error_from_unix(errno
);
3116 block_size
= lp_block_size(snum
);
3117 if (bsize
< block_size
) {
3118 uint64_t factor
= block_size
/bsize
;
3123 if (bsize
> block_size
) {
3124 uint64_t factor
= bsize
/block_size
;
3129 bytes_per_sector
= 512;
3130 sectors_per_unit
= bsize
/bytes_per_sector
;
3131 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3132 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3133 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3134 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3135 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3136 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3137 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3138 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3142 case SMB_QUERY_FS_DEVICE_INFO
:
3143 case SMB_FS_DEVICE_INFORMATION
:
3145 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3147 if (!CAN_WRITE(conn
)) {
3148 characteristics
|= FILE_READ_ONLY_DEVICE
;
3151 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3152 SIVAL(pdata
,4,characteristics
);
3156 #ifdef HAVE_SYS_QUOTAS
3157 case SMB_FS_QUOTA_INFORMATION
:
3159 * what we have to send --metze:
3161 * Unknown1: 24 NULL bytes
3162 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3163 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3164 * Quota Flags: 2 byte :
3165 * Unknown3: 6 NULL bytes
3169 * details for Quota Flags:
3171 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3172 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3173 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3174 * 0x0001 Enable Quotas: enable quota for this fs
3178 /* we need to fake up a fsp here,
3179 * because its not send in this call
3182 SMB_NTQUOTA_STRUCT quotas
;
3185 ZERO_STRUCT(quotas
);
3191 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3192 DEBUG(0,("set_user_quota: access_denied "
3193 "service [%s] user [%s]\n",
3194 lp_servicename(SNUM(conn
)),
3195 conn
->server_info
->unix_name
));
3196 return NT_STATUS_ACCESS_DENIED
;
3199 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3200 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3201 return map_nt_error_from_unix(errno
);
3206 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3207 lp_servicename(SNUM(conn
))));
3209 /* Unknown1 24 NULL bytes*/
3210 SBIG_UINT(pdata
,0,(uint64_t)0);
3211 SBIG_UINT(pdata
,8,(uint64_t)0);
3212 SBIG_UINT(pdata
,16,(uint64_t)0);
3214 /* Default Soft Quota 8 bytes */
3215 SBIG_UINT(pdata
,24,quotas
.softlim
);
3217 /* Default Hard Quota 8 bytes */
3218 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3220 /* Quota flag 2 bytes */
3221 SSVAL(pdata
,40,quotas
.qflags
);
3223 /* Unknown3 6 NULL bytes */
3229 #endif /* HAVE_SYS_QUOTAS */
3230 case SMB_FS_OBJECTID_INFORMATION
:
3232 unsigned char objid
[16];
3233 struct smb_extended_info extended_info
;
3234 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3235 samba_extended_info_version (&extended_info
);
3236 SIVAL(pdata
,16,extended_info
.samba_magic
);
3237 SIVAL(pdata
,20,extended_info
.samba_version
);
3238 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3239 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3240 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3246 * Query the version and capabilities of the CIFS UNIX extensions
3250 case SMB_QUERY_CIFS_UNIX_INFO
:
3252 bool large_write
= lp_min_receive_file_size() &&
3253 !srv_is_signing_active(smbd_server_conn
);
3254 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3255 int encrypt_caps
= 0;
3257 if (!lp_unix_extensions()) {
3258 return NT_STATUS_INVALID_LEVEL
;
3261 switch (conn
->encrypt_level
) {
3267 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3270 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3271 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3272 large_write
= false;
3278 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3279 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3281 /* We have POSIX ACLs, pathname, encryption,
3282 * large read/write, and locking capability. */
3284 SBIG_UINT(pdata
,4,((uint64_t)(
3285 CIFS_UNIX_POSIX_ACLS_CAP
|
3286 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3287 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3288 CIFS_UNIX_EXTATTR_CAP
|
3289 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3291 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3293 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3297 case SMB_QUERY_POSIX_FS_INFO
:
3300 vfs_statvfs_struct svfs
;
3302 if (!lp_unix_extensions()) {
3303 return NT_STATUS_INVALID_LEVEL
;
3306 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3310 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3311 SIVAL(pdata
,4,svfs
.BlockSize
);
3312 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3313 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3314 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3315 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3316 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3317 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3318 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3320 } else if (rc
== EOPNOTSUPP
) {
3321 return NT_STATUS_INVALID_LEVEL
;
3322 #endif /* EOPNOTSUPP */
3324 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3325 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3330 case SMB_QUERY_POSIX_WHOAMI
:
3336 if (!lp_unix_extensions()) {
3337 return NT_STATUS_INVALID_LEVEL
;
3340 if (max_data_bytes
< 40) {
3341 return NT_STATUS_BUFFER_TOO_SMALL
;
3344 /* We ARE guest if global_sid_Builtin_Guests is
3345 * in our list of SIDs.
3347 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3348 conn
->server_info
->ptok
)) {
3349 flags
|= SMB_WHOAMI_GUEST
;
3352 /* We are NOT guest if global_sid_Authenticated_Users
3353 * is in our list of SIDs.
3355 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3356 conn
->server_info
->ptok
)) {
3357 flags
&= ~SMB_WHOAMI_GUEST
;
3360 /* NOTE: 8 bytes for UID/GID, irrespective of native
3361 * platform size. This matches
3362 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3364 data_len
= 4 /* flags */
3371 + 4 /* pad/reserved */
3372 + (conn
->server_info
->utok
.ngroups
* 8)
3374 + (conn
->server_info
->ptok
->num_sids
*
3378 SIVAL(pdata
, 0, flags
);
3379 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3381 (uint64_t)conn
->server_info
->utok
.uid
);
3382 SBIG_UINT(pdata
, 16,
3383 (uint64_t)conn
->server_info
->utok
.gid
);
3386 if (data_len
>= max_data_bytes
) {
3387 /* Potential overflow, skip the GIDs and SIDs. */
3389 SIVAL(pdata
, 24, 0); /* num_groups */
3390 SIVAL(pdata
, 28, 0); /* num_sids */
3391 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3392 SIVAL(pdata
, 36, 0); /* reserved */
3398 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3399 SIVAL(pdata
, 28, conn
->server_info
->ptok
->num_sids
);
3401 /* We walk the SID list twice, but this call is fairly
3402 * infrequent, and I don't expect that it's performance
3403 * sensitive -- jpeach
3405 for (i
= 0, sid_bytes
= 0;
3406 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3407 sid_bytes
+= ndr_size_dom_sid(
3408 &conn
->server_info
->ptok
->user_sids
[i
],
3412 /* SID list byte count */
3413 SIVAL(pdata
, 32, sid_bytes
);
3415 /* 4 bytes pad/reserved - must be zero */
3416 SIVAL(pdata
, 36, 0);
3420 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3421 SBIG_UINT(pdata
, data_len
,
3422 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3428 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3429 int sid_len
= ndr_size_dom_sid(
3430 &conn
->server_info
->ptok
->user_sids
[i
],
3433 sid_linearize(pdata
+ data_len
, sid_len
,
3434 &conn
->server_info
->ptok
->user_sids
[i
]);
3435 data_len
+= sid_len
;
3441 case SMB_MAC_QUERY_FS_INFO
:
3443 * Thursby MAC extension... ONLY on NTFS filesystems
3444 * once we do streams then we don't need this
3446 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3448 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3453 return NT_STATUS_INVALID_LEVEL
;
3456 *ret_data_len
= data_len
;
3457 return NT_STATUS_OK
;
3460 /****************************************************************************
3461 Reply to a TRANS2_QFSINFO (query filesystem info).
3462 ****************************************************************************/
3464 static void call_trans2qfsinfo(connection_struct
*conn
,
3465 struct smb_request
*req
,
3466 char **pparams
, int total_params
,
3467 char **ppdata
, int total_data
,
3468 unsigned int max_data_bytes
)
3470 char *params
= *pparams
;
3471 uint16_t info_level
;
3475 if (total_params
< 2) {
3476 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3480 info_level
= SVAL(params
,0);
3482 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3483 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3484 DEBUG(0,("call_trans2qfsinfo: encryption required "
3485 "and info level 0x%x sent.\n",
3486 (unsigned int)info_level
));
3487 exit_server_cleanly("encryption required "
3493 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3495 status
= smbd_do_qfsinfo(conn
, req
,
3500 if (!NT_STATUS_IS_OK(status
)) {
3501 reply_nterror(req
, status
);
3505 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3508 DEBUG( 4, ( "%s info_level = %d\n",
3509 smb_fn_name(req
->cmd
), info_level
) );
3514 /****************************************************************************
3515 Reply to a TRANS2_SETFSINFO (set filesystem info).
3516 ****************************************************************************/
3518 static void call_trans2setfsinfo(connection_struct
*conn
,
3519 struct smb_request
*req
,
3520 char **pparams
, int total_params
,
3521 char **ppdata
, int total_data
,
3522 unsigned int max_data_bytes
)
3524 char *pdata
= *ppdata
;
3525 char *params
= *pparams
;
3528 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3531 if (total_params
< 4) {
3532 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3538 info_level
= SVAL(params
,2);
3541 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3542 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3543 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3544 "info level (0x%x) on IPC$.\n",
3545 (unsigned int)info_level
));
3546 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3551 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3552 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3553 DEBUG(0,("call_trans2setfsinfo: encryption required "
3554 "and info level 0x%x sent.\n",
3555 (unsigned int)info_level
));
3556 exit_server_cleanly("encryption required "
3562 switch(info_level
) {
3563 case SMB_SET_CIFS_UNIX_INFO
:
3565 uint16 client_unix_major
;
3566 uint16 client_unix_minor
;
3567 uint32 client_unix_cap_low
;
3568 uint32 client_unix_cap_high
;
3570 if (!lp_unix_extensions()) {
3572 NT_STATUS_INVALID_LEVEL
);
3576 /* There should be 12 bytes of capabilities set. */
3577 if (total_data
< 8) {
3580 NT_STATUS_INVALID_PARAMETER
);
3583 client_unix_major
= SVAL(pdata
,0);
3584 client_unix_minor
= SVAL(pdata
,2);
3585 client_unix_cap_low
= IVAL(pdata
,4);
3586 client_unix_cap_high
= IVAL(pdata
,8);
3587 /* Just print these values for now. */
3588 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3589 cap_low = 0x%x, cap_high = 0x%x\n",
3590 (unsigned int)client_unix_major
,
3591 (unsigned int)client_unix_minor
,
3592 (unsigned int)client_unix_cap_low
,
3593 (unsigned int)client_unix_cap_high
));
3595 /* Here is where we must switch to posix pathname processing... */
3596 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3597 lp_set_posix_pathnames();
3598 mangle_change_to_posix();
3601 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3602 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3603 /* Client that knows how to do posix locks,
3604 * but not posix open/mkdir operations. Set a
3605 * default type for read/write checks. */
3607 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3613 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3616 size_t param_len
= 0;
3617 size_t data_len
= total_data
;
3619 if (!lp_unix_extensions()) {
3622 NT_STATUS_INVALID_LEVEL
);
3626 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3629 NT_STATUS_NOT_SUPPORTED
);
3633 if (smbd_server_conn
->smb1
.echo_handler
.trusted_fde
) {
3634 DEBUG( 2,("call_trans2setfsinfo: "
3635 "request transport encryption disabled"
3636 "with 'fork echo handler = yes'\n"));
3639 NT_STATUS_NOT_SUPPORTED
);
3643 DEBUG( 4,("call_trans2setfsinfo: "
3644 "request transport encryption.\n"));
3646 status
= srv_request_encryption_setup(conn
,
3647 (unsigned char **)ppdata
,
3649 (unsigned char **)pparams
,
3652 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3653 !NT_STATUS_IS_OK(status
)) {
3654 reply_nterror(req
, status
);
3658 send_trans2_replies(conn
, req
,
3665 if (NT_STATUS_IS_OK(status
)) {
3666 /* Server-side transport
3667 * encryption is now *on*. */
3668 status
= srv_encryption_start(conn
);
3669 if (!NT_STATUS_IS_OK(status
)) {
3670 exit_server_cleanly(
3671 "Failure in setting "
3672 "up encrypted transport");
3678 case SMB_FS_QUOTA_INFORMATION
:
3680 files_struct
*fsp
= NULL
;
3681 SMB_NTQUOTA_STRUCT quotas
;
3683 ZERO_STRUCT(quotas
);
3686 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3687 ||!CAN_WRITE(conn
)) {
3688 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3689 lp_servicename(SNUM(conn
)),
3690 conn
->server_info
->unix_name
));
3691 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3695 /* note: normaly there're 48 bytes,
3696 * but we didn't use the last 6 bytes for now
3699 fsp
= file_fsp(req
, SVAL(params
,0));
3701 if (!check_fsp_ntquota_handle(conn
, req
,
3703 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3705 req
, NT_STATUS_INVALID_HANDLE
);
3709 if (total_data
< 42) {
3710 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3714 NT_STATUS_INVALID_PARAMETER
);
3718 /* unknown_1 24 NULL bytes in pdata*/
3720 /* the soft quotas 8 bytes (uint64_t)*/
3721 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3722 #ifdef LARGE_SMB_OFF_T
3723 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3724 #else /* LARGE_SMB_OFF_T */
3725 if ((IVAL(pdata
,28) != 0)&&
3726 ((quotas
.softlim
!= 0xFFFFFFFF)||
3727 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3728 /* more than 32 bits? */
3731 NT_STATUS_INVALID_PARAMETER
);
3734 #endif /* LARGE_SMB_OFF_T */
3736 /* the hard quotas 8 bytes (uint64_t)*/
3737 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3738 #ifdef LARGE_SMB_OFF_T
3739 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3740 #else /* LARGE_SMB_OFF_T */
3741 if ((IVAL(pdata
,36) != 0)&&
3742 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3743 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3744 /* more than 32 bits? */
3747 NT_STATUS_INVALID_PARAMETER
);
3750 #endif /* LARGE_SMB_OFF_T */
3752 /* quota_flags 2 bytes **/
3753 quotas
.qflags
= SVAL(pdata
,40);
3755 /* unknown_2 6 NULL bytes follow*/
3757 /* now set the quotas */
3758 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3759 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3760 reply_nterror(req
, map_nt_error_from_unix(errno
));
3767 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3769 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3775 * sending this reply works fine,
3776 * but I'm not sure it's the same
3777 * like windows do...
3780 reply_outbuf(req
, 10, 0);
3783 #if defined(HAVE_POSIX_ACLS)
3784 /****************************************************************************
3785 Utility function to count the number of entries in a POSIX acl.
3786 ****************************************************************************/
3788 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3790 unsigned int ace_count
= 0;
3791 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3792 SMB_ACL_ENTRY_T entry
;
3794 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3796 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3797 entry_id
= SMB_ACL_NEXT_ENTRY
;
3804 /****************************************************************************
3805 Utility function to marshall a POSIX acl into wire format.
3806 ****************************************************************************/
3808 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
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)) {
3814 SMB_ACL_TAG_T tagtype
;
3815 SMB_ACL_PERMSET_T permset
;
3816 unsigned char perms
= 0;
3817 unsigned int own_grp
;
3820 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3821 entry_id
= SMB_ACL_NEXT_ENTRY
;
3824 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3825 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3829 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3830 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3834 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3835 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3836 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3838 SCVAL(pdata
,1,perms
);
3841 case SMB_ACL_USER_OBJ
:
3842 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3843 own_grp
= (unsigned int)pst
->st_ex_uid
;
3844 SIVAL(pdata
,2,own_grp
);
3849 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3851 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3854 own_grp
= (unsigned int)*puid
;
3855 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3856 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3857 SIVAL(pdata
,2,own_grp
);
3861 case SMB_ACL_GROUP_OBJ
:
3862 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3863 own_grp
= (unsigned int)pst
->st_ex_gid
;
3864 SIVAL(pdata
,2,own_grp
);
3869 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3871 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3874 own_grp
= (unsigned int)*pgid
;
3875 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3876 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3877 SIVAL(pdata
,2,own_grp
);
3882 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3883 SIVAL(pdata
,2,0xFFFFFFFF);
3884 SIVAL(pdata
,6,0xFFFFFFFF);
3887 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3888 SIVAL(pdata
,2,0xFFFFFFFF);
3889 SIVAL(pdata
,6,0xFFFFFFFF);
3892 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3895 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3902 /****************************************************************************
3903 Store the FILE_UNIX_BASIC info.
3904 ****************************************************************************/
3906 static char *store_file_unix_basic(connection_struct
*conn
,
3909 const SMB_STRUCT_STAT
*psbuf
)
3911 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3913 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3914 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3916 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3919 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3922 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3923 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3927 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3931 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3935 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3938 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3942 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3946 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3949 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3953 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3960 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3961 * the chflags(2) (or equivalent) flags.
3963 * XXX: this really should be behind the VFS interface. To do this, we would
3964 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3965 * Each VFS module could then implement its own mapping as appropriate for the
3966 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3968 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3972 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3976 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3980 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3984 { UF_HIDDEN
, EXT_HIDDEN
},
3987 /* Do not remove. We need to guarantee that this array has at least one
3988 * entry to build on HP-UX.
3994 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3995 uint32
*smb_fflags
, uint32
*smb_fmask
)
3999 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4000 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4001 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4002 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4007 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4008 const uint32 smb_fflags
,
4009 const uint32 smb_fmask
,
4012 uint32 max_fmask
= 0;
4015 *stat_fflags
= psbuf
->st_ex_flags
;
4017 /* For each flags requested in smb_fmask, check the state of the
4018 * corresponding flag in smb_fflags and set or clear the matching
4022 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4023 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4024 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4025 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4026 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4028 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4033 /* If smb_fmask is asking to set any bits that are not supported by
4034 * our flag mappings, we should fail.
4036 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4044 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4045 * of file flags and birth (create) time.
4047 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4050 const SMB_STRUCT_STAT
*psbuf
)
4052 uint32 file_flags
= 0;
4053 uint32 flags_mask
= 0;
4055 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4057 /* Create (birth) time 64 bit */
4058 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4061 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4062 SIVAL(pdata
, 0, file_flags
); /* flags */
4063 SIVAL(pdata
, 4, flags_mask
); /* mask */
4069 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4070 const struct stream_struct
*streams
,
4072 unsigned int max_data_bytes
,
4073 unsigned int *data_size
)
4076 unsigned int ofs
= 0;
4078 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4079 unsigned int next_offset
;
4081 smb_ucs2_t
*namebuf
;
4083 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4084 streams
[i
].name
, &namelen
) ||
4087 return NT_STATUS_INVALID_PARAMETER
;
4091 * name_buf is now null-terminated, we need to marshall as not
4097 SIVAL(data
, ofs
+4, namelen
);
4098 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4099 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4100 memcpy(data
+ofs
+24, namebuf
, namelen
);
4101 TALLOC_FREE(namebuf
);
4103 next_offset
= ofs
+ 24 + namelen
;
4105 if (i
== num_streams
-1) {
4106 SIVAL(data
, ofs
, 0);
4109 unsigned int align
= ndr_align_size(next_offset
, 8);
4111 memset(data
+next_offset
, 0, align
);
4112 next_offset
+= align
;
4114 SIVAL(data
, ofs
, next_offset
- ofs
);
4123 return NT_STATUS_OK
;
4126 /****************************************************************************
4127 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4128 ****************************************************************************/
4130 static void call_trans2qpipeinfo(connection_struct
*conn
,
4131 struct smb_request
*req
,
4132 unsigned int tran_call
,
4133 char **pparams
, int total_params
,
4134 char **ppdata
, int total_data
,
4135 unsigned int max_data_bytes
)
4137 char *params
= *pparams
;
4138 char *pdata
= *ppdata
;
4139 unsigned int data_size
= 0;
4140 unsigned int param_size
= 2;
4145 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4149 if (total_params
< 4) {
4150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4154 fsp
= file_fsp(req
, SVAL(params
,0));
4155 if (!fsp_is_np(fsp
)) {
4156 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4160 info_level
= SVAL(params
,2);
4162 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4163 if (*pparams
== NULL
) {
4164 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4169 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4170 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4171 if (*ppdata
== NULL
) {
4172 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4177 switch (info_level
) {
4178 case SMB_FILE_STANDARD_INFORMATION
:
4180 SOFF_T(pdata
,0,4096LL);
4187 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4191 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4197 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4198 TALLOC_CTX
*mem_ctx
,
4199 uint16_t info_level
,
4201 struct smb_filename
*smb_fname
,
4202 bool delete_pending
,
4203 struct timespec write_time_ts
,
4204 struct ea_list
*ea_list
,
4205 int lock_data_count
,
4208 unsigned int max_data_bytes
,
4210 unsigned int *pdata_size
)
4212 char *pdata
= *ppdata
;
4213 char *dstart
, *dend
;
4214 unsigned int data_size
;
4215 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4216 time_t create_time
, mtime
, atime
, c_time
;
4217 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4224 uint64_t file_size
= 0;
4226 uint64_t allocation_size
= 0;
4227 uint64_t file_index
= 0;
4228 uint32_t access_mask
= 0;
4230 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4231 return NT_STATUS_INVALID_LEVEL
;
4234 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4235 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4236 info_level
, max_data_bytes
));
4238 mode
= dos_mode(conn
, smb_fname
);
4239 nlink
= psbuf
->st_ex_nlink
;
4241 if (nlink
&& (mode
&aDIR
)) {
4245 if ((nlink
> 0) && delete_pending
) {
4249 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4250 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4251 if (*ppdata
== NULL
) {
4252 return NT_STATUS_NO_MEMORY
;
4256 dend
= dstart
+ data_size
- 1;
4258 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4259 update_stat_ex_mtime(psbuf
, write_time_ts
);
4262 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4263 mtime_ts
= psbuf
->st_ex_mtime
;
4264 atime_ts
= psbuf
->st_ex_atime
;
4265 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4267 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4268 dos_filetime_timespec(&create_time_ts
);
4269 dos_filetime_timespec(&mtime_ts
);
4270 dos_filetime_timespec(&atime_ts
);
4271 dos_filetime_timespec(&ctime_ts
);
4274 create_time
= convert_timespec_to_time_t(create_time_ts
);
4275 mtime
= convert_timespec_to_time_t(mtime_ts
);
4276 atime
= convert_timespec_to_time_t(atime_ts
);
4277 c_time
= convert_timespec_to_time_t(ctime_ts
);
4279 p
= strrchr_m(smb_fname
->base_name
,'/');
4281 base_name
= smb_fname
->base_name
;
4285 /* NT expects the name to be in an exact form of the *full*
4286 filename. See the trans2 torture test */
4287 if (ISDOT(base_name
)) {
4288 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4290 return NT_STATUS_NO_MEMORY
;
4293 dos_fname
= talloc_asprintf(mem_ctx
,
4295 smb_fname
->base_name
);
4297 return NT_STATUS_NO_MEMORY
;
4299 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4300 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4301 smb_fname
->stream_name
);
4303 return NT_STATUS_NO_MEMORY
;
4307 string_replace(dos_fname
, '/', '\\');
4310 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4313 /* Do we have this path open ? */
4315 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4316 fsp1
= file_find_di_first(fileid
);
4317 if (fsp1
&& fsp1
->initial_allocation_size
) {
4318 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4322 if (!(mode
& aDIR
)) {
4323 file_size
= get_file_size_stat(psbuf
);
4327 pos
= fsp
->fh
->position_information
;
4331 access_mask
= fsp
->access_mask
;
4333 /* GENERIC_EXECUTE mapping from Windows */
4334 access_mask
= 0x12019F;
4337 /* This should be an index number - looks like
4340 I think this causes us to fail the IFSKIT
4341 BasicFileInformationTest. -tpot */
4342 file_index
= get_FileIndex(conn
, psbuf
);
4344 switch (info_level
) {
4345 case SMB_INFO_STANDARD
:
4346 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4348 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4349 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4350 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4351 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4352 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4353 SSVAL(pdata
,l1_attrFile
,mode
);
4356 case SMB_INFO_QUERY_EA_SIZE
:
4358 unsigned int ea_size
=
4359 estimate_ea_size(conn
, fsp
,
4360 smb_fname
->base_name
);
4361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4363 srv_put_dos_date2(pdata
,0,create_time
);
4364 srv_put_dos_date2(pdata
,4,atime
);
4365 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4366 SIVAL(pdata
,12,(uint32
)file_size
);
4367 SIVAL(pdata
,16,(uint32
)allocation_size
);
4368 SSVAL(pdata
,20,mode
);
4369 SIVAL(pdata
,22,ea_size
);
4373 case SMB_INFO_IS_NAME_VALID
:
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4376 /* os/2 needs this ? really ?*/
4377 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4379 /* This is only reached for qpathinfo */
4383 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4385 size_t total_ea_len
= 0;
4386 struct ea_list
*ea_file_list
= NULL
;
4388 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4391 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4392 smb_fname
->base_name
,
4394 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4396 if (!ea_list
|| (total_ea_len
> data_size
)) {
4398 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4402 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4406 case SMB_INFO_QUERY_ALL_EAS
:
4408 /* We have data_size bytes to put EA's into. */
4409 size_t total_ea_len
= 0;
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4413 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4414 smb_fname
->base_name
,
4416 if (!ea_list
|| (total_ea_len
> data_size
)) {
4418 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4422 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4426 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4428 /* This is FileFullEaInformation - 0xF which maps to
4429 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4431 /* We have data_size bytes to put EA's into. */
4432 size_t total_ea_len
= 0;
4433 struct ea_list
*ea_file_list
= NULL
;
4435 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4437 /*TODO: add filtering and index handling */
4440 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4441 smb_fname
->base_name
,
4443 if (!ea_file_list
) {
4444 return NT_STATUS_NO_EAS_ON_FILE
;
4447 status
= fill_ea_chained_buffer(mem_ctx
,
4451 conn
, ea_file_list
);
4452 if (!NT_STATUS_IS_OK(status
)) {
4458 case SMB_FILE_BASIC_INFORMATION
:
4459 case SMB_QUERY_FILE_BASIC_INFO
:
4461 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4463 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4465 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4469 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4470 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4471 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4472 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4473 SIVAL(pdata
,32,mode
);
4475 DEBUG(5,("SMB_QFBI - "));
4476 DEBUG(5,("create: %s ", ctime(&create_time
)));
4477 DEBUG(5,("access: %s ", ctime(&atime
)));
4478 DEBUG(5,("write: %s ", ctime(&mtime
)));
4479 DEBUG(5,("change: %s ", ctime(&c_time
)));
4480 DEBUG(5,("mode: %x\n", mode
));
4483 case SMB_FILE_STANDARD_INFORMATION
:
4484 case SMB_QUERY_FILE_STANDARD_INFO
:
4486 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4488 SOFF_T(pdata
,0,allocation_size
);
4489 SOFF_T(pdata
,8,file_size
);
4490 SIVAL(pdata
,16,nlink
);
4491 SCVAL(pdata
,20,delete_pending
?1:0);
4492 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4493 SSVAL(pdata
,22,0); /* Padding. */
4496 case SMB_FILE_EA_INFORMATION
:
4497 case SMB_QUERY_FILE_EA_INFO
:
4499 unsigned int ea_size
=
4500 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4503 SIVAL(pdata
,0,ea_size
);
4507 /* Get the 8.3 name - used if NT SMB was negotiated. */
4508 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4509 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4512 char mangled_name
[13];
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4514 if (!name_to_8_3(base_name
,mangled_name
,
4515 True
,conn
->params
)) {
4516 return NT_STATUS_NO_MEMORY
;
4518 len
= srvstr_push(dstart
, flags2
,
4519 pdata
+4, mangled_name
,
4520 PTR_DIFF(dend
, pdata
+4),
4522 data_size
= 4 + len
;
4527 case SMB_QUERY_FILE_NAME_INFO
:
4531 this must be *exactly* right for ACLs on mapped drives to work
4533 len
= srvstr_push(dstart
, flags2
,
4535 PTR_DIFF(dend
, pdata
+4),
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4538 data_size
= 4 + len
;
4543 case SMB_FILE_ALLOCATION_INFORMATION
:
4544 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4547 SOFF_T(pdata
,0,allocation_size
);
4550 case SMB_FILE_END_OF_FILE_INFORMATION
:
4551 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4554 SOFF_T(pdata
,0,file_size
);
4557 case SMB_QUERY_FILE_ALL_INFO
:
4558 case SMB_FILE_ALL_INFORMATION
:
4561 unsigned int ea_size
=
4562 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4564 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4565 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4566 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4567 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4568 SIVAL(pdata
,32,mode
);
4569 SIVAL(pdata
,36,0); /* padding. */
4571 SOFF_T(pdata
,0,allocation_size
);
4572 SOFF_T(pdata
,8,file_size
);
4573 SIVAL(pdata
,16,nlink
);
4574 SCVAL(pdata
,20,delete_pending
);
4575 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4578 SIVAL(pdata
,0,ea_size
);
4579 pdata
+= 4; /* EA info */
4580 len
= srvstr_push(dstart
, flags2
,
4582 PTR_DIFF(dend
, pdata
+4),
4586 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4590 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4593 unsigned int ea_size
=
4594 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4596 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4597 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4598 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4599 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4600 SIVAL(pdata
, 0x20, mode
);
4601 SIVAL(pdata
, 0x24, 0); /* padding. */
4602 SBVAL(pdata
, 0x28, allocation_size
);
4603 SBVAL(pdata
, 0x30, file_size
);
4604 SIVAL(pdata
, 0x38, nlink
);
4605 SCVAL(pdata
, 0x3C, delete_pending
);
4606 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4607 SSVAL(pdata
, 0x3E, 0); /* padding */
4608 SBVAL(pdata
, 0x40, file_index
);
4609 SIVAL(pdata
, 0x48, ea_size
);
4610 SIVAL(pdata
, 0x4C, access_mask
);
4611 SBVAL(pdata
, 0x50, pos
);
4612 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4613 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4617 len
= srvstr_push(dstart
, flags2
,
4619 PTR_DIFF(dend
, pdata
+4),
4623 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4626 case SMB_FILE_INTERNAL_INFORMATION
:
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4629 SBVAL(pdata
, 0, file_index
);
4633 case SMB_FILE_ACCESS_INFORMATION
:
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4635 SIVAL(pdata
, 0, access_mask
);
4639 case SMB_FILE_NAME_INFORMATION
:
4640 /* Pathname with leading '\'. */
4643 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4645 SIVAL(pdata
,0,byte_len
);
4646 data_size
= 4 + byte_len
;
4650 case SMB_FILE_DISPOSITION_INFORMATION
:
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4653 SCVAL(pdata
,0,delete_pending
);
4656 case SMB_FILE_POSITION_INFORMATION
:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4659 SOFF_T(pdata
,0,pos
);
4662 case SMB_FILE_MODE_INFORMATION
:
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4664 SIVAL(pdata
,0,mode
);
4668 case SMB_FILE_ALIGNMENT_INFORMATION
:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4670 SIVAL(pdata
,0,0); /* No alignment needed. */
4675 * NT4 server just returns "invalid query" to this - if we try
4676 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4679 /* The first statement above is false - verified using Thursby
4680 * client against NT4 -- gcolley.
4682 case SMB_QUERY_FILE_STREAM_INFO
:
4683 case SMB_FILE_STREAM_INFORMATION
: {
4684 unsigned int num_streams
;
4685 struct stream_struct
*streams
;
4687 DEBUG(10,("smbd_do_qfilepathinfo: "
4688 "SMB_FILE_STREAM_INFORMATION\n"));
4690 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4691 return NT_STATUS_INVALID_PARAMETER
;
4694 status
= SMB_VFS_STREAMINFO(
4695 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4696 &num_streams
, &streams
);
4698 if (!NT_STATUS_IS_OK(status
)) {
4699 DEBUG(10, ("could not get stream info: %s\n",
4700 nt_errstr(status
)));
4704 status
= marshall_stream_info(num_streams
, streams
,
4705 pdata
, max_data_bytes
,
4708 if (!NT_STATUS_IS_OK(status
)) {
4709 DEBUG(10, ("marshall_stream_info failed: %s\n",
4710 nt_errstr(status
)));
4714 TALLOC_FREE(streams
);
4718 case SMB_QUERY_COMPRESSION_INFO
:
4719 case SMB_FILE_COMPRESSION_INFORMATION
:
4720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4721 SOFF_T(pdata
,0,file_size
);
4722 SIVAL(pdata
,8,0); /* ??? */
4723 SIVAL(pdata
,12,0); /* ??? */
4727 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4728 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4729 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4730 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4731 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4732 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4733 SOFF_T(pdata
,32,allocation_size
);
4734 SOFF_T(pdata
,40,file_size
);
4735 SIVAL(pdata
,48,mode
);
4736 SIVAL(pdata
,52,0); /* ??? */
4740 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4742 SIVAL(pdata
,0,mode
);
4748 * CIFS UNIX Extensions.
4751 case SMB_QUERY_FILE_UNIX_BASIC
:
4753 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4754 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4758 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4760 for (i
=0; i
<100; i
++)
4761 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4767 case SMB_QUERY_FILE_UNIX_INFO2
:
4769 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4770 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4774 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4776 for (i
=0; i
<100; i
++)
4777 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4783 case SMB_QUERY_FILE_UNIX_LINK
:
4786 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4789 return NT_STATUS_NO_MEMORY
;
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4794 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4795 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4798 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4800 len
= SMB_VFS_READLINK(conn
,
4801 smb_fname
->base_name
,
4804 return map_nt_error_from_unix(errno
);
4807 len
= srvstr_push(dstart
, flags2
,
4809 PTR_DIFF(dend
, pdata
),
4812 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4817 #if defined(HAVE_POSIX_ACLS)
4818 case SMB_QUERY_POSIX_ACL
:
4820 SMB_ACL_T file_acl
= NULL
;
4821 SMB_ACL_T def_acl
= NULL
;
4822 uint16 num_file_acls
= 0;
4823 uint16 num_def_acls
= 0;
4825 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4826 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4829 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4830 smb_fname
->base_name
,
4831 SMB_ACL_TYPE_ACCESS
);
4834 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4835 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4836 "not implemented on "
4837 "filesystem containing %s\n",
4838 smb_fname
->base_name
));
4839 return NT_STATUS_NOT_IMPLEMENTED
;
4842 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4843 if (fsp
&& fsp
->is_directory
) {
4845 SMB_VFS_SYS_ACL_GET_FILE(
4847 fsp
->fsp_name
->base_name
,
4848 SMB_ACL_TYPE_DEFAULT
);
4851 SMB_VFS_SYS_ACL_GET_FILE(
4853 smb_fname
->base_name
,
4854 SMB_ACL_TYPE_DEFAULT
);
4856 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4859 num_file_acls
= count_acl_entries(conn
, file_acl
);
4860 num_def_acls
= count_acl_entries(conn
, def_acl
);
4862 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4863 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4865 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4866 SMB_POSIX_ACL_HEADER_SIZE
) ));
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4871 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4873 return NT_STATUS_BUFFER_TOO_SMALL
;
4876 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4877 SSVAL(pdata
,2,num_file_acls
);
4878 SSVAL(pdata
,4,num_def_acls
);
4879 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4886 return NT_STATUS_INTERNAL_ERROR
;
4888 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4893 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4895 return NT_STATUS_INTERNAL_ERROR
;
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4902 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4904 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4910 case SMB_QUERY_POSIX_LOCK
:
4915 enum brl_type lock_type
;
4917 /* We need an open file with a real fd for this. */
4918 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4919 return NT_STATUS_INVALID_LEVEL
;
4922 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4923 return NT_STATUS_INVALID_PARAMETER
;
4926 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4927 case POSIX_LOCK_TYPE_READ
:
4928 lock_type
= READ_LOCK
;
4930 case POSIX_LOCK_TYPE_WRITE
:
4931 lock_type
= WRITE_LOCK
;
4933 case POSIX_LOCK_TYPE_UNLOCK
:
4935 /* There's no point in asking for an unlock... */
4936 return NT_STATUS_INVALID_PARAMETER
;
4939 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4940 #if defined(HAVE_LONGLONG)
4941 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4942 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4943 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4944 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4945 #else /* HAVE_LONGLONG */
4946 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4947 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4948 #endif /* HAVE_LONGLONG */
4950 status
= query_lock(fsp
,
4957 if (ERROR_WAS_LOCK_DENIED(status
)) {
4958 /* Here we need to report who has it locked... */
4959 data_size
= POSIX_LOCK_DATA_SIZE
;
4961 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4962 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4963 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4964 #if defined(HAVE_LONGLONG)
4965 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4966 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4967 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4968 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4969 #else /* HAVE_LONGLONG */
4970 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4971 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4972 #endif /* HAVE_LONGLONG */
4974 } else if (NT_STATUS_IS_OK(status
)) {
4975 /* For success we just return a copy of what we sent
4976 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4977 data_size
= POSIX_LOCK_DATA_SIZE
;
4978 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4979 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4987 return NT_STATUS_INVALID_LEVEL
;
4990 *pdata_size
= data_size
;
4991 return NT_STATUS_OK
;
4994 /****************************************************************************
4995 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4996 file name or file id).
4997 ****************************************************************************/
4999 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5000 struct smb_request
*req
,
5001 unsigned int tran_call
,
5002 char **pparams
, int total_params
,
5003 char **ppdata
, int total_data
,
5004 unsigned int max_data_bytes
)
5006 char *params
= *pparams
;
5007 char *pdata
= *ppdata
;
5009 unsigned int data_size
= 0;
5010 unsigned int param_size
= 2;
5011 struct smb_filename
*smb_fname
= NULL
;
5012 bool delete_pending
= False
;
5013 struct timespec write_time_ts
;
5014 files_struct
*fsp
= NULL
;
5015 struct file_id fileid
;
5016 struct ea_list
*ea_list
= NULL
;
5017 int lock_data_count
= 0;
5018 char *lock_data
= NULL
;
5019 NTSTATUS status
= NT_STATUS_OK
;
5022 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5026 ZERO_STRUCT(write_time_ts
);
5028 if (tran_call
== TRANSACT2_QFILEINFO
) {
5029 if (total_params
< 4) {
5030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5035 call_trans2qpipeinfo(conn
, req
, tran_call
,
5036 pparams
, total_params
,
5042 fsp
= file_fsp(req
, SVAL(params
,0));
5043 info_level
= SVAL(params
,2);
5045 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5047 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5048 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5052 /* Initial check for valid fsp ptr. */
5053 if (!check_fsp_open(conn
, req
, fsp
)) {
5057 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5059 if (!NT_STATUS_IS_OK(status
)) {
5060 reply_nterror(req
, status
);
5064 if(fsp
->fake_file_handle
) {
5066 * This is actually for the QUOTA_FAKE_FILE --metze
5069 /* We know this name is ok, it's already passed the checks. */
5071 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5073 * This is actually a QFILEINFO on a directory
5074 * handle (returned from an NT SMB). NT5.0 seems
5075 * to do this call. JRA.
5078 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5079 /* Always do lstat for UNIX calls. */
5080 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5081 DEBUG(3,("call_trans2qfilepathinfo: "
5082 "SMB_VFS_LSTAT of %s failed "
5084 smb_fname_str_dbg(smb_fname
),
5087 map_nt_error_from_unix(errno
));
5090 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5091 DEBUG(3,("call_trans2qfilepathinfo: "
5092 "SMB_VFS_STAT of %s failed (%s)\n",
5093 smb_fname_str_dbg(smb_fname
),
5096 map_nt_error_from_unix(errno
));
5100 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5101 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5104 * Original code - this is an open file.
5106 if (!check_fsp(conn
, req
, fsp
)) {
5110 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5111 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5112 fsp
->fnum
, strerror(errno
)));
5114 map_nt_error_from_unix(errno
));
5117 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5118 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5125 if (total_params
< 7) {
5126 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5130 info_level
= SVAL(params
,0);
5132 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5134 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5135 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5139 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5141 STR_TERMINATE
, &status
);
5142 if (!NT_STATUS_IS_OK(status
)) {
5143 reply_nterror(req
, status
);
5147 status
= filename_convert(req
,
5149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5154 if (!NT_STATUS_IS_OK(status
)) {
5155 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5156 reply_botherror(req
,
5157 NT_STATUS_PATH_NOT_COVERED
,
5158 ERRSRV
, ERRbadpath
);
5161 reply_nterror(req
, status
);
5165 /* If this is a stream, check if there is a delete_pending. */
5166 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5167 && is_ntfs_stream_smb_fname(smb_fname
)) {
5168 struct smb_filename
*smb_fname_base
= NULL
;
5170 /* Create an smb_filename with stream_name == NULL. */
5172 create_synthetic_smb_fname(talloc_tos(),
5173 smb_fname
->base_name
,
5176 if (!NT_STATUS_IS_OK(status
)) {
5177 reply_nterror(req
, status
);
5181 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5182 /* Always do lstat for UNIX calls. */
5183 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5184 DEBUG(3,("call_trans2qfilepathinfo: "
5185 "SMB_VFS_LSTAT of %s failed "
5187 smb_fname_str_dbg(smb_fname_base
),
5189 TALLOC_FREE(smb_fname_base
);
5191 map_nt_error_from_unix(errno
));
5195 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5196 DEBUG(3,("call_trans2qfilepathinfo: "
5197 "fileinfo of %s failed "
5199 smb_fname_str_dbg(smb_fname_base
),
5201 TALLOC_FREE(smb_fname_base
);
5203 map_nt_error_from_unix(errno
));
5208 fileid
= vfs_file_id_from_sbuf(conn
,
5209 &smb_fname_base
->st
);
5210 TALLOC_FREE(smb_fname_base
);
5211 get_file_infos(fileid
, &delete_pending
, NULL
);
5212 if (delete_pending
) {
5213 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5218 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5219 /* Always do lstat for UNIX calls. */
5220 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5221 DEBUG(3,("call_trans2qfilepathinfo: "
5222 "SMB_VFS_LSTAT of %s failed (%s)\n",
5223 smb_fname_str_dbg(smb_fname
),
5226 map_nt_error_from_unix(errno
));
5231 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5232 DEBUG(3,("call_trans2qfilepathinfo: "
5233 "SMB_VFS_STAT of %s failed (%s)\n",
5234 smb_fname_str_dbg(smb_fname
),
5237 map_nt_error_from_unix(errno
));
5242 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5243 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5244 if (delete_pending
) {
5245 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5250 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5251 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5252 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5254 /* Pull out any data sent here before we realloc. */
5255 switch (info_level
) {
5256 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5258 /* Pull any EA list from the data portion. */
5261 if (total_data
< 4) {
5263 req
, NT_STATUS_INVALID_PARAMETER
);
5266 ea_size
= IVAL(pdata
,0);
5268 if (total_data
> 0 && ea_size
!= total_data
) {
5269 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5270 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5272 req
, NT_STATUS_INVALID_PARAMETER
);
5276 if (!lp_ea_support(SNUM(conn
))) {
5277 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5281 /* Pull out the list of names. */
5282 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5285 req
, NT_STATUS_INVALID_PARAMETER
);
5291 case SMB_QUERY_POSIX_LOCK
:
5293 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5294 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5298 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5300 req
, NT_STATUS_INVALID_PARAMETER
);
5304 /* Copy the lock range data. */
5305 lock_data
= (char *)TALLOC_MEMDUP(
5306 req
, pdata
, total_data
);
5308 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5311 lock_data_count
= total_data
;
5317 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5318 if (*pparams
== NULL
) {
5319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5326 * draft-leach-cifs-v1-spec-02.txt
5327 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5330 * The requested information is placed in the Data portion of the
5331 * transaction response. For the information levels greater than 0x100,
5332 * the transaction response has 1 parameter word which should be
5333 * ignored by the client.
5335 * However Windows only follows this rule for the IS_NAME_VALID call.
5337 switch (info_level
) {
5338 case SMB_INFO_IS_NAME_VALID
:
5343 if ((info_level
& 0xFF00) == 0xFF00) {
5345 * We use levels that start with 0xFF00
5346 * internally to represent SMB2 specific levels
5348 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5352 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5354 delete_pending
, write_time_ts
,
5356 lock_data_count
, lock_data
,
5357 req
->flags2
, max_data_bytes
,
5358 ppdata
, &data_size
);
5359 if (!NT_STATUS_IS_OK(status
)) {
5360 reply_nterror(req
, status
);
5364 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5370 /****************************************************************************
5371 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5373 ****************************************************************************/
5375 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5376 connection_struct
*conn
,
5377 struct smb_request
*req
,
5378 bool overwrite_if_exists
,
5379 const struct smb_filename
*smb_fname_old
,
5380 struct smb_filename
*smb_fname_new
)
5382 NTSTATUS status
= NT_STATUS_OK
;
5384 /* source must already exist. */
5385 if (!VALID_STAT(smb_fname_old
->st
)) {
5386 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5389 if (VALID_STAT(smb_fname_new
->st
)) {
5390 if (overwrite_if_exists
) {
5391 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5392 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5394 status
= unlink_internals(conn
,
5396 FILE_ATTRIBUTE_NORMAL
,
5399 if (!NT_STATUS_IS_OK(status
)) {
5403 /* Disallow if newname already exists. */
5404 return NT_STATUS_OBJECT_NAME_COLLISION
;
5408 /* No links from a directory. */
5409 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5410 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5413 /* Setting a hardlink to/from a stream isn't currently supported. */
5414 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5415 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5416 return NT_STATUS_INVALID_PARAMETER
;
5419 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5420 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5422 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5423 smb_fname_new
->base_name
) != 0) {
5424 status
= map_nt_error_from_unix(errno
);
5425 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5426 nt_errstr(status
), smb_fname_old
->base_name
,
5427 smb_fname_new
->base_name
));
5432 /****************************************************************************
5433 Deal with setting the time from any of the setfilepathinfo functions.
5434 ****************************************************************************/
5436 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5438 const struct smb_filename
*smb_fname
,
5439 struct smb_file_time
*ft
,
5440 bool setting_write_time
)
5442 struct smb_filename smb_fname_base
;
5444 FILE_NOTIFY_CHANGE_LAST_ACCESS
5445 |FILE_NOTIFY_CHANGE_LAST_WRITE
5446 |FILE_NOTIFY_CHANGE_CREATION
;
5448 if (!VALID_STAT(smb_fname
->st
)) {
5449 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5452 /* get some defaults (no modifications) if any info is zero or -1. */
5453 if (null_timespec(ft
->create_time
)) {
5454 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5457 if (null_timespec(ft
->atime
)) {
5458 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5461 if (null_timespec(ft
->mtime
)) {
5462 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5465 if (!setting_write_time
) {
5466 /* ft->mtime comes from change time, not write time. */
5467 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5470 /* Ensure the resolution is the correct for
5471 * what we can store on this filesystem. */
5473 round_timespec(conn
->ts_res
, &ft
->create_time
);
5474 round_timespec(conn
->ts_res
, &ft
->ctime
);
5475 round_timespec(conn
->ts_res
, &ft
->atime
);
5476 round_timespec(conn
->ts_res
, &ft
->mtime
);
5478 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5479 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5480 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5482 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5484 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5487 if (setting_write_time
) {
5489 * This was a Windows setfileinfo on an open file.
5490 * NT does this a lot. We also need to
5491 * set the time here, as it can be read by
5492 * FindFirst/FindNext and with the patch for bug #2045
5493 * in smbd/fileio.c it ensures that this timestamp is
5494 * kept sticky even after a write. We save the request
5495 * away and will set it on file close and after a write. JRA.
5498 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5499 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5502 if (fsp
->base_fsp
) {
5503 set_sticky_write_time_fsp(fsp
->base_fsp
,
5506 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5509 set_sticky_write_time_path(
5510 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5515 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5517 /* Always call ntimes on the base, even if a stream was passed in. */
5518 smb_fname_base
= *smb_fname
;
5519 smb_fname_base
.stream_name
= NULL
;
5521 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5522 return map_nt_error_from_unix(errno
);
5525 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5526 smb_fname
->base_name
);
5527 return NT_STATUS_OK
;
5530 /****************************************************************************
5531 Deal with setting the dosmode from any of the setfilepathinfo functions.
5532 ****************************************************************************/
5534 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5535 const struct smb_filename
*smb_fname
,
5538 struct smb_filename
*smb_fname_base
= NULL
;
5541 if (!VALID_STAT(smb_fname
->st
)) {
5542 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5545 /* Always operate on the base_name, even if a stream was passed in. */
5546 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5547 NULL
, &smb_fname
->st
,
5549 if (!NT_STATUS_IS_OK(status
)) {
5554 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5561 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5563 /* check the mode isn't different, before changing it */
5564 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5565 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5566 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5567 (unsigned int)dosmode
));
5569 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5571 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5573 smb_fname_str_dbg(smb_fname_base
),
5575 status
= map_nt_error_from_unix(errno
);
5579 status
= NT_STATUS_OK
;
5581 TALLOC_FREE(smb_fname_base
);
5585 /****************************************************************************
5586 Deal with setting the size from any of the setfilepathinfo functions.
5587 ****************************************************************************/
5589 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5590 struct smb_request
*req
,
5592 const struct smb_filename
*smb_fname
,
5593 const SMB_STRUCT_STAT
*psbuf
,
5595 bool fail_after_createfile
)
5597 NTSTATUS status
= NT_STATUS_OK
;
5598 struct smb_filename
*smb_fname_tmp
= NULL
;
5599 files_struct
*new_fsp
= NULL
;
5601 if (!VALID_STAT(*psbuf
)) {
5602 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5605 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5607 if (size
== get_file_size_stat(psbuf
)) {
5608 return NT_STATUS_OK
;
5611 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5612 smb_fname_str_dbg(smb_fname
), (double)size
));
5614 if (fsp
&& fsp
->fh
->fd
!= -1) {
5615 /* Handle based call. */
5616 if (vfs_set_filelen(fsp
, size
) == -1) {
5617 return map_nt_error_from_unix(errno
);
5619 trigger_write_time_update_immediate(fsp
);
5620 return NT_STATUS_OK
;
5623 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5624 if (!NT_STATUS_IS_OK(status
)) {
5628 smb_fname_tmp
->st
= *psbuf
;
5630 status
= SMB_VFS_CREATE_FILE(
5633 0, /* root_dir_fid */
5634 smb_fname_tmp
, /* fname */
5635 FILE_WRITE_DATA
, /* access_mask */
5636 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5638 FILE_OPEN
, /* create_disposition*/
5639 0, /* create_options */
5640 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5641 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5642 0, /* allocation_size */
5643 0, /* private_flags */
5646 &new_fsp
, /* result */
5649 TALLOC_FREE(smb_fname_tmp
);
5651 if (!NT_STATUS_IS_OK(status
)) {
5652 /* NB. We check for open_was_deferred in the caller. */
5656 /* See RAW-SFILEINFO-END-OF-FILE */
5657 if (fail_after_createfile
) {
5658 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5659 return NT_STATUS_INVALID_LEVEL
;
5662 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5663 status
= map_nt_error_from_unix(errno
);
5664 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5668 trigger_write_time_update_immediate(new_fsp
);
5669 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5670 return NT_STATUS_OK
;
5673 /****************************************************************************
5674 Deal with SMB_INFO_SET_EA.
5675 ****************************************************************************/
5677 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5681 const struct smb_filename
*smb_fname
)
5683 struct ea_list
*ea_list
= NULL
;
5684 TALLOC_CTX
*ctx
= NULL
;
5685 NTSTATUS status
= NT_STATUS_OK
;
5687 if (total_data
< 10) {
5689 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5690 length. They seem to have no effect. Bug #3212. JRA */
5692 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5693 /* We're done. We only get EA info in this call. */
5694 return NT_STATUS_OK
;
5697 return NT_STATUS_INVALID_PARAMETER
;
5700 if (IVAL(pdata
,0) > total_data
) {
5701 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5702 IVAL(pdata
,0), (unsigned int)total_data
));
5703 return NT_STATUS_INVALID_PARAMETER
;
5707 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5709 return NT_STATUS_INVALID_PARAMETER
;
5711 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5716 /****************************************************************************
5717 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5718 ****************************************************************************/
5720 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5725 struct ea_list
*ea_list
= NULL
;
5729 return NT_STATUS_INVALID_HANDLE
;
5732 if (!lp_ea_support(SNUM(conn
))) {
5733 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5734 "EA's not supported.\n",
5735 (unsigned int)total_data
));
5736 return NT_STATUS_EAS_NOT_SUPPORTED
;
5739 if (total_data
< 10) {
5740 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5742 (unsigned int)total_data
));
5743 return NT_STATUS_INVALID_PARAMETER
;
5746 ea_list
= read_nttrans_ea_list(talloc_tos(),
5751 return NT_STATUS_INVALID_PARAMETER
;
5753 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5755 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5756 smb_fname_str_dbg(fsp
->fsp_name
),
5757 nt_errstr(status
) ));
5763 /****************************************************************************
5764 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5765 ****************************************************************************/
5767 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5771 struct smb_filename
*smb_fname
)
5773 NTSTATUS status
= NT_STATUS_OK
;
5774 bool delete_on_close
;
5777 if (total_data
< 1) {
5778 return NT_STATUS_INVALID_PARAMETER
;
5782 return NT_STATUS_INVALID_HANDLE
;
5785 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5786 dosmode
= dos_mode(conn
, smb_fname
);
5788 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5789 "delete_on_close = %u\n",
5790 smb_fname_str_dbg(smb_fname
),
5791 (unsigned int)dosmode
,
5792 (unsigned int)delete_on_close
));
5794 if (delete_on_close
) {
5795 status
= can_set_delete_on_close(fsp
, dosmode
);
5796 if (!NT_STATUS_IS_OK(status
)) {
5801 /* The set is across all open files on this dev/inode pair. */
5802 if (!set_delete_on_close(fsp
, delete_on_close
,
5803 &conn
->server_info
->utok
)) {
5804 return NT_STATUS_ACCESS_DENIED
;
5806 return NT_STATUS_OK
;
5809 /****************************************************************************
5810 Deal with SMB_FILE_POSITION_INFORMATION.
5811 ****************************************************************************/
5813 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5818 uint64_t position_information
;
5820 if (total_data
< 8) {
5821 return NT_STATUS_INVALID_PARAMETER
;
5825 /* Ignore on pathname based set. */
5826 return NT_STATUS_OK
;
5829 position_information
= (uint64_t)IVAL(pdata
,0);
5830 #ifdef LARGE_SMB_OFF_T
5831 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5832 #else /* LARGE_SMB_OFF_T */
5833 if (IVAL(pdata
,4) != 0) {
5834 /* more than 32 bits? */
5835 return NT_STATUS_INVALID_PARAMETER
;
5837 #endif /* LARGE_SMB_OFF_T */
5839 DEBUG(10,("smb_file_position_information: Set file position "
5840 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5841 (double)position_information
));
5842 fsp
->fh
->position_information
= position_information
;
5843 return NT_STATUS_OK
;
5846 /****************************************************************************
5847 Deal with SMB_FILE_MODE_INFORMATION.
5848 ****************************************************************************/
5850 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5856 if (total_data
< 4) {
5857 return NT_STATUS_INVALID_PARAMETER
;
5859 mode
= IVAL(pdata
,0);
5860 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5861 return NT_STATUS_INVALID_PARAMETER
;
5863 return NT_STATUS_OK
;
5866 /****************************************************************************
5867 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5868 ****************************************************************************/
5870 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5871 struct smb_request
*req
,
5874 const struct smb_filename
*smb_fname
)
5876 char *link_target
= NULL
;
5877 const char *newname
= smb_fname
->base_name
;
5878 TALLOC_CTX
*ctx
= talloc_tos();
5880 /* Set a symbolic link. */
5881 /* Don't allow this if follow links is false. */
5883 if (total_data
== 0) {
5884 return NT_STATUS_INVALID_PARAMETER
;
5887 if (!lp_symlinks(SNUM(conn
))) {
5888 return NT_STATUS_ACCESS_DENIED
;
5891 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5892 total_data
, STR_TERMINATE
);
5895 return NT_STATUS_INVALID_PARAMETER
;
5898 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5899 newname
, link_target
));
5901 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5902 return map_nt_error_from_unix(errno
);
5905 return NT_STATUS_OK
;
5908 /****************************************************************************
5909 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5910 ****************************************************************************/
5912 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5913 struct smb_request
*req
,
5914 const char *pdata
, int total_data
,
5915 struct smb_filename
*smb_fname_new
)
5917 char *oldname
= NULL
;
5918 struct smb_filename
*smb_fname_old
= NULL
;
5919 TALLOC_CTX
*ctx
= talloc_tos();
5920 NTSTATUS status
= NT_STATUS_OK
;
5922 /* Set a hard link. */
5923 if (total_data
== 0) {
5924 return NT_STATUS_INVALID_PARAMETER
;
5927 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5928 total_data
, STR_TERMINATE
, &status
);
5929 if (!NT_STATUS_IS_OK(status
)) {
5933 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5934 smb_fname_str_dbg(smb_fname_new
), oldname
));
5936 status
= filename_convert(ctx
,
5938 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5943 if (!NT_STATUS_IS_OK(status
)) {
5947 return hardlink_internals(ctx
, conn
, req
, false,
5948 smb_fname_old
, smb_fname_new
);
5951 /****************************************************************************
5952 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5953 ****************************************************************************/
5955 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5956 struct smb_request
*req
,
5960 struct smb_filename
*smb_fname_src
)
5964 char *newname
= NULL
;
5965 struct smb_filename
*smb_fname_dst
= NULL
;
5966 NTSTATUS status
= NT_STATUS_OK
;
5967 TALLOC_CTX
*ctx
= talloc_tos();
5970 return NT_STATUS_INVALID_HANDLE
;
5973 if (total_data
< 20) {
5974 return NT_STATUS_INVALID_PARAMETER
;
5977 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5978 len
= IVAL(pdata
,16);
5980 if (len
> (total_data
- 20) || (len
== 0)) {
5981 return NT_STATUS_INVALID_PARAMETER
;
5984 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
5985 &pdata
[20], len
, STR_TERMINATE
,
5987 if (!NT_STATUS_IS_OK(status
)) {
5991 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5994 status
= filename_convert(ctx
,
5996 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6001 if (!NT_STATUS_IS_OK(status
)) {
6005 /* Ok, this looks wrong to me, but appears to
6006 * be how SMB2 renames work. CHECK WITH Microsoft !
6009 if (fsp
->oplock_type
!= NO_OPLOCK
) {
6010 return NT_STATUS_SHARING_VIOLATION
;
6013 if (fsp
->base_fsp
) {
6014 /* newname must be a stream name. */
6015 if (newname
[0] != ':') {
6016 return NT_STATUS_NOT_SUPPORTED
;
6019 /* Create an smb_fname to call rename_internals_fsp() with. */
6020 status
= create_synthetic_smb_fname(talloc_tos(),
6021 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6023 if (!NT_STATUS_IS_OK(status
)) {
6028 * Set the original last component, since
6029 * rename_internals_fsp() requires it.
6031 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6033 if (smb_fname_dst
->original_lcomp
== NULL
) {
6034 status
= NT_STATUS_NO_MEMORY
;
6040 DEBUG(10,("smb2_file_rename_information: "
6041 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6042 fsp
->fnum
, fsp_str_dbg(fsp
),
6043 smb_fname_str_dbg(smb_fname_dst
)));
6044 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6048 TALLOC_FREE(smb_fname_dst
);
6052 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6053 struct smb_request
*req
,
6057 struct smb_filename
*smb_fname_src
)
6061 char *newname
= NULL
;
6062 struct smb_filename
*smb_fname_dst
= NULL
;
6063 NTSTATUS status
= NT_STATUS_OK
;
6064 TALLOC_CTX
*ctx
= talloc_tos();
6067 return NT_STATUS_INVALID_HANDLE
;
6070 if (total_data
< 20) {
6071 return NT_STATUS_INVALID_PARAMETER
;
6074 overwrite
= (CVAL(pdata
,0) ? true : false);
6075 len
= IVAL(pdata
,16);
6077 if (len
> (total_data
- 20) || (len
== 0)) {
6078 return NT_STATUS_INVALID_PARAMETER
;
6081 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6082 &pdata
[20], len
, STR_TERMINATE
,
6084 if (!NT_STATUS_IS_OK(status
)) {
6088 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6091 status
= filename_convert(ctx
,
6093 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6098 if (!NT_STATUS_IS_OK(status
)) {
6102 if (fsp
->base_fsp
) {
6103 /* No stream names. */
6104 return NT_STATUS_NOT_SUPPORTED
;
6107 DEBUG(10,("smb_file_link_information: "
6108 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6109 fsp
->fnum
, fsp_str_dbg(fsp
),
6110 smb_fname_str_dbg(smb_fname_dst
)));
6111 status
= hardlink_internals(ctx
,
6118 TALLOC_FREE(smb_fname_dst
);
6122 /****************************************************************************
6123 Deal with SMB_FILE_RENAME_INFORMATION.
6124 ****************************************************************************/
6126 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6127 struct smb_request
*req
,
6131 struct smb_filename
*smb_fname_src
)
6136 char *newname
= NULL
;
6137 struct smb_filename
*smb_fname_dst
= NULL
;
6138 bool dest_has_wcard
= False
;
6139 NTSTATUS status
= NT_STATUS_OK
;
6141 TALLOC_CTX
*ctx
= talloc_tos();
6143 if (total_data
< 13) {
6144 return NT_STATUS_INVALID_PARAMETER
;
6147 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6148 root_fid
= IVAL(pdata
,4);
6149 len
= IVAL(pdata
,8);
6151 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6152 return NT_STATUS_INVALID_PARAMETER
;
6155 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6158 if (!NT_STATUS_IS_OK(status
)) {
6162 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6165 status
= resolve_dfspath_wcard(ctx
, conn
,
6166 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6171 if (!NT_STATUS_IS_OK(status
)) {
6175 /* Check the new name has no '/' characters. */
6176 if (strchr_m(newname
, '/')) {
6177 return NT_STATUS_NOT_SUPPORTED
;
6180 if (fsp
&& fsp
->base_fsp
) {
6181 /* newname must be a stream name. */
6182 if (newname
[0] != ':') {
6183 return NT_STATUS_NOT_SUPPORTED
;
6186 /* Create an smb_fname to call rename_internals_fsp() with. */
6187 status
= create_synthetic_smb_fname(talloc_tos(),
6188 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6190 if (!NT_STATUS_IS_OK(status
)) {
6195 * Set the original last component, since
6196 * rename_internals_fsp() requires it.
6198 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6200 if (smb_fname_dst
->original_lcomp
== NULL
) {
6201 status
= NT_STATUS_NO_MEMORY
;
6207 * Build up an smb_fname_dst based on the filename passed in.
6208 * We basically just strip off the last component, and put on
6209 * the newname instead.
6211 char *base_name
= NULL
;
6213 /* newname must *not* be a stream name. */
6214 if (newname
[0] == ':') {
6215 return NT_STATUS_NOT_SUPPORTED
;
6219 * Strip off the last component (filename) of the path passed
6222 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6224 return NT_STATUS_NO_MEMORY
;
6226 p
= strrchr_m(base_name
, '/');
6230 base_name
= talloc_strdup(ctx
, "./");
6232 return NT_STATUS_NO_MEMORY
;
6235 /* Append the new name. */
6236 base_name
= talloc_asprintf_append(base_name
,
6240 return NT_STATUS_NO_MEMORY
;
6243 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6246 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6249 /* If an error we expect this to be
6250 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6252 if (!NT_STATUS_IS_OK(status
)) {
6253 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6257 /* Create an smb_fname to call rename_internals_fsp() */
6258 status
= create_synthetic_smb_fname(ctx
,
6262 if (!NT_STATUS_IS_OK(status
)) {
6269 DEBUG(10,("smb_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6271 fsp
->fnum
, fsp_str_dbg(fsp
),
6272 smb_fname_str_dbg(smb_fname_dst
)));
6273 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6276 DEBUG(10,("smb_file_rename_information: "
6277 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6278 smb_fname_str_dbg(smb_fname_src
),
6279 smb_fname_str_dbg(smb_fname_dst
)));
6280 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6281 smb_fname_dst
, 0, overwrite
, false,
6283 FILE_WRITE_ATTRIBUTES
);
6286 TALLOC_FREE(smb_fname_dst
);
6290 /****************************************************************************
6291 Deal with SMB_SET_POSIX_ACL.
6292 ****************************************************************************/
6294 #if defined(HAVE_POSIX_ACLS)
6295 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6299 const struct smb_filename
*smb_fname
)
6301 uint16 posix_acl_version
;
6302 uint16 num_file_acls
;
6303 uint16 num_def_acls
;
6304 bool valid_file_acls
= True
;
6305 bool valid_def_acls
= True
;
6307 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6308 return NT_STATUS_INVALID_PARAMETER
;
6310 posix_acl_version
= SVAL(pdata
,0);
6311 num_file_acls
= SVAL(pdata
,2);
6312 num_def_acls
= SVAL(pdata
,4);
6314 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6315 valid_file_acls
= False
;
6319 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6320 valid_def_acls
= False
;
6324 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6325 return NT_STATUS_INVALID_PARAMETER
;
6328 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6329 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6330 return NT_STATUS_INVALID_PARAMETER
;
6333 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6334 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6335 (unsigned int)num_file_acls
,
6336 (unsigned int)num_def_acls
));
6338 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6339 smb_fname
->base_name
, num_file_acls
,
6340 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6341 return map_nt_error_from_unix(errno
);
6344 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6345 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6346 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6347 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6348 return map_nt_error_from_unix(errno
);
6350 return NT_STATUS_OK
;
6354 /****************************************************************************
6355 Deal with SMB_SET_POSIX_LOCK.
6356 ****************************************************************************/
6358 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6359 struct smb_request
*req
,
6367 bool blocking_lock
= False
;
6368 enum brl_type lock_type
;
6370 NTSTATUS status
= NT_STATUS_OK
;
6372 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6373 return NT_STATUS_INVALID_HANDLE
;
6376 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6377 return NT_STATUS_INVALID_PARAMETER
;
6380 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6381 case POSIX_LOCK_TYPE_READ
:
6382 lock_type
= READ_LOCK
;
6384 case POSIX_LOCK_TYPE_WRITE
:
6385 /* Return the right POSIX-mappable error code for files opened read-only. */
6386 if (!fsp
->can_write
) {
6387 return NT_STATUS_INVALID_HANDLE
;
6389 lock_type
= WRITE_LOCK
;
6391 case POSIX_LOCK_TYPE_UNLOCK
:
6392 lock_type
= UNLOCK_LOCK
;
6395 return NT_STATUS_INVALID_PARAMETER
;
6398 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6399 blocking_lock
= False
;
6400 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6401 blocking_lock
= True
;
6403 return NT_STATUS_INVALID_PARAMETER
;
6406 if (!lp_blocking_locks(SNUM(conn
))) {
6407 blocking_lock
= False
;
6410 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6411 #if defined(HAVE_LONGLONG)
6412 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6413 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6414 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6415 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6416 #else /* HAVE_LONGLONG */
6417 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6418 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6419 #endif /* HAVE_LONGLONG */
6421 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6422 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6424 (unsigned int)lock_type
,
6425 (unsigned long long)smblctx
,
6429 if (lock_type
== UNLOCK_LOCK
) {
6430 status
= do_unlock(smbd_messaging_context(),
6437 uint64_t block_smblctx
;
6439 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6451 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6453 * A blocking lock was requested. Package up
6454 * this smb into a queued request and push it
6455 * onto the blocking lock queue.
6457 if(push_blocking_lock_request(br_lck
,
6460 -1, /* infinite timeout. */
6468 TALLOC_FREE(br_lck
);
6472 TALLOC_FREE(br_lck
);
6478 /****************************************************************************
6479 Deal with SMB_SET_FILE_BASIC_INFO.
6480 ****************************************************************************/
6482 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6486 const struct smb_filename
*smb_fname
)
6488 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6489 struct smb_file_time ft
;
6491 NTSTATUS status
= NT_STATUS_OK
;
6495 if (total_data
< 36) {
6496 return NT_STATUS_INVALID_PARAMETER
;
6499 /* Set the attributes */
6500 dosmode
= IVAL(pdata
,32);
6501 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6502 if (!NT_STATUS_IS_OK(status
)) {
6507 ft
.create_time
= interpret_long_date(pdata
);
6510 ft
.atime
= interpret_long_date(pdata
+8);
6513 ft
.mtime
= interpret_long_date(pdata
+16);
6516 ft
.ctime
= interpret_long_date(pdata
+24);
6518 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6519 smb_fname_str_dbg(smb_fname
)));
6521 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6525 /****************************************************************************
6526 Deal with SMB_INFO_STANDARD.
6527 ****************************************************************************/
6529 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6533 const struct smb_filename
*smb_fname
)
6535 struct smb_file_time ft
;
6539 if (total_data
< 12) {
6540 return NT_STATUS_INVALID_PARAMETER
;
6544 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6546 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6548 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6550 DEBUG(10,("smb_set_info_standard: file %s\n",
6551 smb_fname_str_dbg(smb_fname
)));
6553 return smb_set_file_time(conn
,
6560 /****************************************************************************
6561 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6562 ****************************************************************************/
6564 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6565 struct smb_request
*req
,
6569 struct smb_filename
*smb_fname
)
6571 uint64_t allocation_size
= 0;
6572 NTSTATUS status
= NT_STATUS_OK
;
6573 files_struct
*new_fsp
= NULL
;
6575 if (!VALID_STAT(smb_fname
->st
)) {
6576 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6579 if (total_data
< 8) {
6580 return NT_STATUS_INVALID_PARAMETER
;
6583 allocation_size
= (uint64_t)IVAL(pdata
,0);
6584 #ifdef LARGE_SMB_OFF_T
6585 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6586 #else /* LARGE_SMB_OFF_T */
6587 if (IVAL(pdata
,4) != 0) {
6588 /* more than 32 bits? */
6589 return NT_STATUS_INVALID_PARAMETER
;
6591 #endif /* LARGE_SMB_OFF_T */
6593 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6594 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6595 (double)allocation_size
));
6597 if (allocation_size
) {
6598 allocation_size
= smb_roundup(conn
, allocation_size
);
6601 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6602 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6603 (double)allocation_size
));
6605 if (fsp
&& fsp
->fh
->fd
!= -1) {
6606 /* Open file handle. */
6607 /* Only change if needed. */
6608 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6609 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6610 return map_nt_error_from_unix(errno
);
6613 /* But always update the time. */
6615 * This is equivalent to a write. Ensure it's seen immediately
6616 * if there are no pending writes.
6618 trigger_write_time_update_immediate(fsp
);
6619 return NT_STATUS_OK
;
6622 /* Pathname or stat or directory file. */
6623 status
= SMB_VFS_CREATE_FILE(
6626 0, /* root_dir_fid */
6627 smb_fname
, /* fname */
6628 FILE_WRITE_DATA
, /* access_mask */
6629 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6631 FILE_OPEN
, /* create_disposition*/
6632 0, /* create_options */
6633 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6634 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6635 0, /* allocation_size */
6636 0, /* private_flags */
6639 &new_fsp
, /* result */
6642 if (!NT_STATUS_IS_OK(status
)) {
6643 /* NB. We check for open_was_deferred in the caller. */
6647 /* Only change if needed. */
6648 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6649 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6650 status
= map_nt_error_from_unix(errno
);
6651 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6656 /* Changing the allocation size should set the last mod time. */
6658 * This is equivalent to a write. Ensure it's seen immediately
6659 * if there are no pending writes.
6661 trigger_write_time_update_immediate(new_fsp
);
6663 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6664 return NT_STATUS_OK
;
6667 /****************************************************************************
6668 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6669 ****************************************************************************/
6671 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6672 struct smb_request
*req
,
6676 const struct smb_filename
*smb_fname
,
6677 bool fail_after_createfile
)
6681 if (total_data
< 8) {
6682 return NT_STATUS_INVALID_PARAMETER
;
6685 size
= IVAL(pdata
,0);
6686 #ifdef LARGE_SMB_OFF_T
6687 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6688 #else /* LARGE_SMB_OFF_T */
6689 if (IVAL(pdata
,4) != 0) {
6690 /* more than 32 bits? */
6691 return NT_STATUS_INVALID_PARAMETER
;
6693 #endif /* LARGE_SMB_OFF_T */
6694 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6695 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6698 return smb_set_file_size(conn
, req
,
6703 fail_after_createfile
);
6706 /****************************************************************************
6707 Allow a UNIX info mknod.
6708 ****************************************************************************/
6710 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6713 const struct smb_filename
*smb_fname
)
6715 uint32 file_type
= IVAL(pdata
,56);
6716 #if defined(HAVE_MAKEDEV)
6717 uint32 dev_major
= IVAL(pdata
,60);
6718 uint32 dev_minor
= IVAL(pdata
,68);
6720 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6721 uint32 raw_unixmode
= IVAL(pdata
,84);
6725 if (total_data
< 100) {
6726 return NT_STATUS_INVALID_PARAMETER
;
6729 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6730 PERM_NEW_FILE
, &unixmode
);
6731 if (!NT_STATUS_IS_OK(status
)) {
6735 #if defined(HAVE_MAKEDEV)
6736 dev
= makedev(dev_major
, dev_minor
);
6739 switch (file_type
) {
6740 #if defined(S_IFIFO)
6741 case UNIX_TYPE_FIFO
:
6742 unixmode
|= S_IFIFO
;
6745 #if defined(S_IFSOCK)
6746 case UNIX_TYPE_SOCKET
:
6747 unixmode
|= S_IFSOCK
;
6750 #if defined(S_IFCHR)
6751 case UNIX_TYPE_CHARDEV
:
6752 unixmode
|= S_IFCHR
;
6755 #if defined(S_IFBLK)
6756 case UNIX_TYPE_BLKDEV
:
6757 unixmode
|= S_IFBLK
;
6761 return NT_STATUS_INVALID_PARAMETER
;
6764 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6765 "%.0f mode 0%o for file %s\n", (double)dev
,
6766 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6768 /* Ok - do the mknod. */
6769 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6770 return map_nt_error_from_unix(errno
);
6773 /* If any of the other "set" calls fail we
6774 * don't want to end up with a half-constructed mknod.
6777 if (lp_inherit_perms(SNUM(conn
))) {
6779 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6781 return NT_STATUS_NO_MEMORY
;
6783 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6785 TALLOC_FREE(parent
);
6788 return NT_STATUS_OK
;
6791 /****************************************************************************
6792 Deal with SMB_SET_FILE_UNIX_BASIC.
6793 ****************************************************************************/
6795 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6796 struct smb_request
*req
,
6800 const struct smb_filename
*smb_fname
)
6802 struct smb_file_time ft
;
6803 uint32 raw_unixmode
;
6806 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6807 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6808 NTSTATUS status
= NT_STATUS_OK
;
6809 bool delete_on_fail
= False
;
6810 enum perm_type ptype
;
6811 files_struct
*all_fsps
= NULL
;
6812 bool modify_mtime
= true;
6814 SMB_STRUCT_STAT sbuf
;
6818 if (total_data
< 100) {
6819 return NT_STATUS_INVALID_PARAMETER
;
6822 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6823 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6824 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6825 #ifdef LARGE_SMB_OFF_T
6826 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6827 #else /* LARGE_SMB_OFF_T */
6828 if (IVAL(pdata
,4) != 0) {
6829 /* more than 32 bits? */
6830 return NT_STATUS_INVALID_PARAMETER
;
6832 #endif /* LARGE_SMB_OFF_T */
6835 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6836 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6837 set_owner
= (uid_t
)IVAL(pdata
,40);
6838 set_grp
= (gid_t
)IVAL(pdata
,48);
6839 raw_unixmode
= IVAL(pdata
,84);
6841 if (VALID_STAT(smb_fname
->st
)) {
6842 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6843 ptype
= PERM_EXISTING_DIR
;
6845 ptype
= PERM_EXISTING_FILE
;
6848 ptype
= PERM_NEW_FILE
;
6851 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6853 if (!NT_STATUS_IS_OK(status
)) {
6857 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6858 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6859 smb_fname_str_dbg(smb_fname
), (double)size
,
6860 (unsigned int)set_owner
, (unsigned int)set_grp
,
6861 (int)raw_unixmode
));
6863 sbuf
= smb_fname
->st
;
6865 if (!VALID_STAT(sbuf
)) {
6866 struct smb_filename
*smb_fname_tmp
= NULL
;
6868 * The only valid use of this is to create character and block
6869 * devices, and named pipes. This is deprecated (IMHO) and
6870 * a new info level should be used for mknod. JRA.
6873 status
= smb_unix_mknod(conn
,
6877 if (!NT_STATUS_IS_OK(status
)) {
6881 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6883 if (!NT_STATUS_IS_OK(status
)) {
6887 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6888 status
= map_nt_error_from_unix(errno
);
6889 TALLOC_FREE(smb_fname_tmp
);
6890 SMB_VFS_UNLINK(conn
, smb_fname
);
6894 sbuf
= smb_fname_tmp
->st
;
6895 TALLOC_FREE(smb_fname_tmp
);
6897 /* Ensure we don't try and change anything else. */
6898 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6899 size
= get_file_size_stat(&sbuf
);
6900 ft
.atime
= sbuf
.st_ex_atime
;
6901 ft
.mtime
= sbuf
.st_ex_mtime
;
6903 * We continue here as we might want to change the
6906 delete_on_fail
= True
;
6910 /* Horrible backwards compatibility hack as an old server bug
6911 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6915 size
= get_file_size_stat(&sbuf
);
6920 * Deal with the UNIX specific mode set.
6923 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6924 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6925 "setting mode 0%o for file %s\n",
6926 (unsigned int)unixmode
,
6927 smb_fname_str_dbg(smb_fname
)));
6928 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6929 return map_nt_error_from_unix(errno
);
6934 * Deal with the UNIX specific uid set.
6937 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6938 (sbuf
.st_ex_uid
!= set_owner
)) {
6941 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6942 "changing owner %u for path %s\n",
6943 (unsigned int)set_owner
,
6944 smb_fname_str_dbg(smb_fname
)));
6946 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6947 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6948 set_owner
, (gid_t
)-1);
6950 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6951 set_owner
, (gid_t
)-1);
6955 status
= map_nt_error_from_unix(errno
);
6956 if (delete_on_fail
) {
6957 SMB_VFS_UNLINK(conn
, smb_fname
);
6964 * Deal with the UNIX specific gid set.
6967 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6968 (sbuf
.st_ex_gid
!= set_grp
)) {
6969 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6970 "changing group %u for file %s\n",
6971 (unsigned int)set_owner
,
6972 smb_fname_str_dbg(smb_fname
)));
6973 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6975 status
= map_nt_error_from_unix(errno
);
6976 if (delete_on_fail
) {
6977 SMB_VFS_UNLINK(conn
, smb_fname
);
6983 /* Deal with any size changes. */
6985 status
= smb_set_file_size(conn
, req
,
6991 if (!NT_STATUS_IS_OK(status
)) {
6995 /* Deal with any time changes. */
6996 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6997 /* No change, don't cancel anything. */
7001 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7002 for(all_fsps
= file_find_di_first(id
); all_fsps
;
7003 all_fsps
= file_find_di_next(all_fsps
)) {
7005 * We're setting the time explicitly for UNIX.
7006 * Cancel any pending changes over all handles.
7008 all_fsps
->update_write_time_on_close
= false;
7009 TALLOC_FREE(all_fsps
->update_write_time_event
);
7013 * Override the "setting_write_time"
7014 * parameter here as it almost does what
7015 * we need. Just remember if we modified
7016 * mtime and send the notify ourselves.
7018 if (null_timespec(ft
.mtime
)) {
7019 modify_mtime
= false;
7022 status
= smb_set_file_time(conn
,
7028 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7029 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7034 /****************************************************************************
7035 Deal with SMB_SET_FILE_UNIX_INFO2.
7036 ****************************************************************************/
7038 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7039 struct smb_request
*req
,
7043 const struct smb_filename
*smb_fname
)
7049 if (total_data
< 116) {
7050 return NT_STATUS_INVALID_PARAMETER
;
7053 /* Start by setting all the fields that are common between UNIX_BASIC
7056 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7058 if (!NT_STATUS_IS_OK(status
)) {
7062 smb_fflags
= IVAL(pdata
, 108);
7063 smb_fmask
= IVAL(pdata
, 112);
7065 /* NB: We should only attempt to alter the file flags if the client
7066 * sends a non-zero mask.
7068 if (smb_fmask
!= 0) {
7069 int stat_fflags
= 0;
7071 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7072 smb_fmask
, &stat_fflags
)) {
7073 /* Client asked to alter a flag we don't understand. */
7074 return NT_STATUS_INVALID_PARAMETER
;
7077 if (fsp
&& fsp
->fh
->fd
!= -1) {
7078 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7079 return NT_STATUS_NOT_SUPPORTED
;
7081 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7082 stat_fflags
) != 0) {
7083 return map_nt_error_from_unix(errno
);
7088 /* XXX: need to add support for changing the create_time here. You
7089 * can do this for paths on Darwin with setattrlist(2). The right way
7090 * to hook this up is probably by extending the VFS utimes interface.
7093 return NT_STATUS_OK
;
7096 /****************************************************************************
7097 Create a directory with POSIX semantics.
7098 ****************************************************************************/
7100 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7101 struct smb_request
*req
,
7104 struct smb_filename
*smb_fname
,
7105 int *pdata_return_size
)
7107 NTSTATUS status
= NT_STATUS_OK
;
7108 uint32 raw_unixmode
= 0;
7109 uint32 mod_unixmode
= 0;
7110 mode_t unixmode
= (mode_t
)0;
7111 files_struct
*fsp
= NULL
;
7112 uint16 info_level_return
= 0;
7114 char *pdata
= *ppdata
;
7116 if (total_data
< 18) {
7117 return NT_STATUS_INVALID_PARAMETER
;
7120 raw_unixmode
= IVAL(pdata
,8);
7121 /* Next 4 bytes are not yet defined. */
7123 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7124 PERM_NEW_DIR
, &unixmode
);
7125 if (!NT_STATUS_IS_OK(status
)) {
7129 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7131 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7132 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7134 status
= SMB_VFS_CREATE_FILE(
7137 0, /* root_dir_fid */
7138 smb_fname
, /* fname */
7139 FILE_READ_ATTRIBUTES
, /* access_mask */
7140 FILE_SHARE_NONE
, /* share_access */
7141 FILE_CREATE
, /* create_disposition*/
7142 FILE_DIRECTORY_FILE
, /* create_options */
7143 mod_unixmode
, /* file_attributes */
7144 0, /* oplock_request */
7145 0, /* allocation_size */
7146 0, /* private_flags */
7152 if (NT_STATUS_IS_OK(status
)) {
7153 close_file(req
, fsp
, NORMAL_CLOSE
);
7156 info_level_return
= SVAL(pdata
,16);
7158 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7159 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7160 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7161 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7163 *pdata_return_size
= 12;
7166 /* Realloc the data size */
7167 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7168 if (*ppdata
== NULL
) {
7169 *pdata_return_size
= 0;
7170 return NT_STATUS_NO_MEMORY
;
7174 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7175 SSVAL(pdata
,2,0); /* No fnum. */
7176 SIVAL(pdata
,4,info
); /* Was directory created. */
7178 switch (info_level_return
) {
7179 case SMB_QUERY_FILE_UNIX_BASIC
:
7180 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7181 SSVAL(pdata
,10,0); /* Padding. */
7182 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7185 case SMB_QUERY_FILE_UNIX_INFO2
:
7186 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7187 SSVAL(pdata
,10,0); /* Padding. */
7188 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7192 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7193 SSVAL(pdata
,10,0); /* Padding. */
7200 /****************************************************************************
7201 Open/Create a file with POSIX semantics.
7202 ****************************************************************************/
7204 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7205 struct smb_request
*req
,
7208 struct smb_filename
*smb_fname
,
7209 int *pdata_return_size
)
7211 bool extended_oplock_granted
= False
;
7212 char *pdata
= *ppdata
;
7214 uint32 wire_open_mode
= 0;
7215 uint32 raw_unixmode
= 0;
7216 uint32 mod_unixmode
= 0;
7217 uint32 create_disp
= 0;
7218 uint32 access_mask
= 0;
7219 uint32 create_options
= 0;
7220 NTSTATUS status
= NT_STATUS_OK
;
7221 mode_t unixmode
= (mode_t
)0;
7222 files_struct
*fsp
= NULL
;
7223 int oplock_request
= 0;
7225 uint16 info_level_return
= 0;
7227 if (total_data
< 18) {
7228 return NT_STATUS_INVALID_PARAMETER
;
7231 flags
= IVAL(pdata
,0);
7232 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7233 if (oplock_request
) {
7234 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7237 wire_open_mode
= IVAL(pdata
,4);
7239 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7240 return smb_posix_mkdir(conn
, req
,
7247 switch (wire_open_mode
& SMB_ACCMODE
) {
7249 access_mask
= FILE_READ_DATA
;
7252 access_mask
= FILE_WRITE_DATA
;
7255 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7258 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7259 (unsigned int)wire_open_mode
));
7260 return NT_STATUS_INVALID_PARAMETER
;
7263 wire_open_mode
&= ~SMB_ACCMODE
;
7265 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7266 create_disp
= FILE_CREATE
;
7267 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7268 create_disp
= FILE_OVERWRITE_IF
;
7269 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7270 create_disp
= FILE_OPEN_IF
;
7271 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7272 create_disp
= FILE_OPEN
;
7274 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7275 (unsigned int)wire_open_mode
));
7276 return NT_STATUS_INVALID_PARAMETER
;
7279 raw_unixmode
= IVAL(pdata
,8);
7280 /* Next 4 bytes are not yet defined. */
7282 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7283 (VALID_STAT(smb_fname
->st
) ?
7284 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7287 if (!NT_STATUS_IS_OK(status
)) {
7291 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7293 if (wire_open_mode
& SMB_O_SYNC
) {
7294 create_options
|= FILE_WRITE_THROUGH
;
7296 if (wire_open_mode
& SMB_O_APPEND
) {
7297 access_mask
|= FILE_APPEND_DATA
;
7299 if (wire_open_mode
& SMB_O_DIRECT
) {
7300 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7303 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7304 smb_fname_str_dbg(smb_fname
),
7305 (unsigned int)wire_open_mode
,
7306 (unsigned int)unixmode
));
7308 status
= SMB_VFS_CREATE_FILE(
7311 0, /* root_dir_fid */
7312 smb_fname
, /* fname */
7313 access_mask
, /* access_mask */
7314 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7316 create_disp
, /* create_disposition*/
7317 FILE_NON_DIRECTORY_FILE
, /* create_options */
7318 mod_unixmode
, /* file_attributes */
7319 oplock_request
, /* oplock_request */
7320 0, /* allocation_size */
7321 0, /* private_flags */
7327 if (!NT_STATUS_IS_OK(status
)) {
7331 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7332 extended_oplock_granted
= True
;
7335 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7336 extended_oplock_granted
= True
;
7339 info_level_return
= SVAL(pdata
,16);
7341 /* Allocate the correct return size. */
7343 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7344 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7345 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7346 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7348 *pdata_return_size
= 12;
7351 /* Realloc the data size */
7352 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7353 if (*ppdata
== NULL
) {
7354 close_file(req
, fsp
, ERROR_CLOSE
);
7355 *pdata_return_size
= 0;
7356 return NT_STATUS_NO_MEMORY
;
7360 if (extended_oplock_granted
) {
7361 if (flags
& REQUEST_BATCH_OPLOCK
) {
7362 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7364 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7366 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7367 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7369 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7372 SSVAL(pdata
,2,fsp
->fnum
);
7373 SIVAL(pdata
,4,info
); /* Was file created etc. */
7375 switch (info_level_return
) {
7376 case SMB_QUERY_FILE_UNIX_BASIC
:
7377 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7378 SSVAL(pdata
,10,0); /* padding. */
7379 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7382 case SMB_QUERY_FILE_UNIX_INFO2
:
7383 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7384 SSVAL(pdata
,10,0); /* padding. */
7385 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7389 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7390 SSVAL(pdata
,10,0); /* padding. */
7393 return NT_STATUS_OK
;
7396 /****************************************************************************
7397 Delete a file with POSIX semantics.
7398 ****************************************************************************/
7400 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7401 struct smb_request
*req
,
7404 struct smb_filename
*smb_fname
)
7406 NTSTATUS status
= NT_STATUS_OK
;
7407 files_struct
*fsp
= NULL
;
7411 int create_options
= 0;
7413 struct share_mode_lock
*lck
= NULL
;
7415 if (total_data
< 2) {
7416 return NT_STATUS_INVALID_PARAMETER
;
7419 flags
= SVAL(pdata
,0);
7421 if (!VALID_STAT(smb_fname
->st
)) {
7422 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7425 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7426 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7427 return NT_STATUS_NOT_A_DIRECTORY
;
7430 DEBUG(10,("smb_posix_unlink: %s %s\n",
7431 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7432 smb_fname_str_dbg(smb_fname
)));
7434 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7435 create_options
|= FILE_DIRECTORY_FILE
;
7438 status
= SMB_VFS_CREATE_FILE(
7441 0, /* root_dir_fid */
7442 smb_fname
, /* fname */
7443 DELETE_ACCESS
, /* access_mask */
7444 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7446 FILE_OPEN
, /* create_disposition*/
7447 create_options
, /* create_options */
7448 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7449 0, /* oplock_request */
7450 0, /* allocation_size */
7451 0, /* private_flags */
7457 if (!NT_STATUS_IS_OK(status
)) {
7462 * Don't lie to client. If we can't really delete due to
7463 * non-POSIX opens return SHARING_VIOLATION.
7466 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7469 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7470 "lock for file %s\n", fsp_str_dbg(fsp
)));
7471 close_file(req
, fsp
, NORMAL_CLOSE
);
7472 return NT_STATUS_INVALID_PARAMETER
;
7476 * See if others still have the file open. If this is the case, then
7477 * don't delete. If all opens are POSIX delete we can set the delete
7478 * on close disposition.
7480 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7481 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7482 if (is_valid_share_mode_entry(e
)) {
7483 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7486 /* Fail with sharing violation. */
7487 close_file(req
, fsp
, NORMAL_CLOSE
);
7489 return NT_STATUS_SHARING_VIOLATION
;
7494 * Set the delete on close.
7496 status
= smb_set_file_disposition_info(conn
,
7502 if (!NT_STATUS_IS_OK(status
)) {
7503 close_file(req
, fsp
, NORMAL_CLOSE
);
7508 return close_file(req
, fsp
, NORMAL_CLOSE
);
7511 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7512 struct smb_request
*req
,
7513 TALLOC_CTX
*mem_ctx
,
7514 uint16_t info_level
,
7516 struct smb_filename
*smb_fname
,
7517 char **ppdata
, int total_data
,
7520 char *pdata
= *ppdata
;
7521 NTSTATUS status
= NT_STATUS_OK
;
7522 int data_return_size
= 0;
7526 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7527 return NT_STATUS_INVALID_LEVEL
;
7530 if (!CAN_WRITE(conn
)) {
7531 /* Allow POSIX opens. The open path will deny
7532 * any non-readonly opens. */
7533 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7534 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7538 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7539 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7540 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7542 switch (info_level
) {
7544 case SMB_INFO_STANDARD
:
7546 status
= smb_set_info_standard(conn
,
7554 case SMB_INFO_SET_EA
:
7556 status
= smb_info_set_ea(conn
,
7564 case SMB_SET_FILE_BASIC_INFO
:
7565 case SMB_FILE_BASIC_INFORMATION
:
7567 status
= smb_set_file_basic_info(conn
,
7575 case SMB_FILE_ALLOCATION_INFORMATION
:
7576 case SMB_SET_FILE_ALLOCATION_INFO
:
7578 status
= smb_set_file_allocation_info(conn
, req
,
7586 case SMB_FILE_END_OF_FILE_INFORMATION
:
7587 case SMB_SET_FILE_END_OF_FILE_INFO
:
7590 * XP/Win7 both fail after the createfile with
7591 * SMB_SET_FILE_END_OF_FILE_INFO but not
7592 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7593 * The level is known here, so pass it down
7597 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7599 status
= smb_set_file_end_of_file_info(conn
, req
,
7608 case SMB_FILE_DISPOSITION_INFORMATION
:
7609 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7612 /* JRA - We used to just ignore this on a path ?
7613 * Shouldn't this be invalid level on a pathname
7616 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7617 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7620 status
= smb_set_file_disposition_info(conn
,
7628 case SMB_FILE_POSITION_INFORMATION
:
7630 status
= smb_file_position_information(conn
,
7637 case SMB_FILE_FULL_EA_INFORMATION
:
7639 status
= smb_set_file_full_ea_info(conn
,
7646 /* From tridge Samba4 :
7647 * MODE_INFORMATION in setfileinfo (I have no
7648 * idea what "mode information" on a file is - it takes a value of 0,
7649 * 2, 4 or 6. What could it be?).
7652 case SMB_FILE_MODE_INFORMATION
:
7654 status
= smb_file_mode_information(conn
,
7661 * CIFS UNIX extensions.
7664 case SMB_SET_FILE_UNIX_BASIC
:
7666 status
= smb_set_file_unix_basic(conn
, req
,
7674 case SMB_SET_FILE_UNIX_INFO2
:
7676 status
= smb_set_file_unix_info2(conn
, req
,
7684 case SMB_SET_FILE_UNIX_LINK
:
7687 /* We must have a pathname for this. */
7688 return NT_STATUS_INVALID_LEVEL
;
7690 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7691 total_data
, smb_fname
);
7695 case SMB_SET_FILE_UNIX_HLINK
:
7698 /* We must have a pathname for this. */
7699 return NT_STATUS_INVALID_LEVEL
;
7701 status
= smb_set_file_unix_hlink(conn
, req
,
7707 case SMB_FILE_RENAME_INFORMATION
:
7709 status
= smb_file_rename_information(conn
, req
,
7715 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7717 /* SMB2 rename information. */
7718 status
= smb2_file_rename_information(conn
, req
,
7724 case SMB_FILE_LINK_INFORMATION
:
7726 status
= smb_file_link_information(conn
, req
,
7732 #if defined(HAVE_POSIX_ACLS)
7733 case SMB_SET_POSIX_ACL
:
7735 status
= smb_set_posix_acl(conn
,
7744 case SMB_SET_POSIX_LOCK
:
7747 return NT_STATUS_INVALID_LEVEL
;
7749 status
= smb_set_posix_lock(conn
, req
,
7750 pdata
, total_data
, fsp
);
7754 case SMB_POSIX_PATH_OPEN
:
7757 /* We must have a pathname for this. */
7758 return NT_STATUS_INVALID_LEVEL
;
7761 status
= smb_posix_open(conn
, req
,
7769 case SMB_POSIX_PATH_UNLINK
:
7772 /* We must have a pathname for this. */
7773 return NT_STATUS_INVALID_LEVEL
;
7776 status
= smb_posix_unlink(conn
, req
,
7784 return NT_STATUS_INVALID_LEVEL
;
7787 if (!NT_STATUS_IS_OK(status
)) {
7791 *ret_data_size
= data_return_size
;
7792 return NT_STATUS_OK
;
7795 /****************************************************************************
7796 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7797 ****************************************************************************/
7799 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7800 struct smb_request
*req
,
7801 unsigned int tran_call
,
7802 char **pparams
, int total_params
,
7803 char **ppdata
, int total_data
,
7804 unsigned int max_data_bytes
)
7806 char *params
= *pparams
;
7807 char *pdata
= *ppdata
;
7809 struct smb_filename
*smb_fname
= NULL
;
7810 files_struct
*fsp
= NULL
;
7811 NTSTATUS status
= NT_STATUS_OK
;
7812 int data_return_size
= 0;
7815 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7819 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7820 if (total_params
< 4) {
7821 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7825 fsp
= file_fsp(req
, SVAL(params
,0));
7826 /* Basic check for non-null fsp. */
7827 if (!check_fsp_open(conn
, req
, fsp
)) {
7830 info_level
= SVAL(params
,2);
7832 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7834 if (!NT_STATUS_IS_OK(status
)) {
7835 reply_nterror(req
, status
);
7839 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7841 * This is actually a SETFILEINFO on a directory
7842 * handle (returned from an NT SMB). NT5.0 seems
7843 * to do this call. JRA.
7845 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7846 /* Always do lstat for UNIX calls. */
7847 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7848 DEBUG(3,("call_trans2setfilepathinfo: "
7849 "SMB_VFS_LSTAT of %s failed "
7851 smb_fname_str_dbg(smb_fname
),
7853 reply_nterror(req
, map_nt_error_from_unix(errno
));
7857 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7858 DEBUG(3,("call_trans2setfilepathinfo: "
7859 "fileinfo of %s failed (%s)\n",
7860 smb_fname_str_dbg(smb_fname
),
7862 reply_nterror(req
, map_nt_error_from_unix(errno
));
7866 } else if (fsp
->print_file
) {
7868 * Doing a DELETE_ON_CLOSE should cancel a print job.
7870 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7871 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7873 DEBUG(3,("call_trans2setfilepathinfo: "
7874 "Cancelling print job (%s)\n",
7878 send_trans2_replies(conn
, req
, params
, 2,
7884 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7889 * Original code - this is an open file.
7891 if (!check_fsp(conn
, req
, fsp
)) {
7895 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7896 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7897 "of fnum %d failed (%s)\n", fsp
->fnum
,
7899 reply_nterror(req
, map_nt_error_from_unix(errno
));
7907 if (total_params
< 7) {
7908 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7912 info_level
= SVAL(params
,0);
7913 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7914 total_params
- 6, STR_TERMINATE
,
7916 if (!NT_STATUS_IS_OK(status
)) {
7917 reply_nterror(req
, status
);
7921 status
= filename_convert(req
, conn
,
7922 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7927 if (!NT_STATUS_IS_OK(status
)) {
7928 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7929 reply_botherror(req
,
7930 NT_STATUS_PATH_NOT_COVERED
,
7931 ERRSRV
, ERRbadpath
);
7934 reply_nterror(req
, status
);
7938 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7940 * For CIFS UNIX extensions the target name may not exist.
7943 /* Always do lstat for UNIX calls. */
7944 SMB_VFS_LSTAT(conn
, smb_fname
);
7946 } else if (!VALID_STAT(smb_fname
->st
) &&
7947 SMB_VFS_STAT(conn
, smb_fname
)) {
7948 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7950 smb_fname_str_dbg(smb_fname
),
7952 reply_nterror(req
, map_nt_error_from_unix(errno
));
7957 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7958 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7959 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7961 /* Realloc the parameter size */
7962 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7963 if (*pparams
== NULL
) {
7964 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7971 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7977 if (!NT_STATUS_IS_OK(status
)) {
7978 if (open_was_deferred(req
->mid
)) {
7979 /* We have re-scheduled this call. */
7982 if (blocking_lock_was_deferred_smb1(req
->mid
)) {
7983 /* We have re-scheduled this call. */
7986 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7987 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7988 ERRSRV
, ERRbadpath
);
7991 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7992 reply_openerror(req
, status
);
7996 reply_nterror(req
, status
);
8000 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8006 /****************************************************************************
8007 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8008 ****************************************************************************/
8010 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8011 char **pparams
, int total_params
,
8012 char **ppdata
, int total_data
,
8013 unsigned int max_data_bytes
)
8015 struct smb_filename
*smb_dname
= NULL
;
8016 char *params
= *pparams
;
8017 char *pdata
= *ppdata
;
8018 char *directory
= NULL
;
8019 NTSTATUS status
= NT_STATUS_OK
;
8020 struct ea_list
*ea_list
= NULL
;
8021 TALLOC_CTX
*ctx
= talloc_tos();
8023 if (!CAN_WRITE(conn
)) {
8024 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8028 if (total_params
< 5) {
8029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8033 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8034 total_params
- 4, STR_TERMINATE
,
8036 if (!NT_STATUS_IS_OK(status
)) {
8037 reply_nterror(req
, status
);
8041 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8043 status
= filename_convert(ctx
,
8045 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8051 if (!NT_STATUS_IS_OK(status
)) {
8052 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8053 reply_botherror(req
,
8054 NT_STATUS_PATH_NOT_COVERED
,
8055 ERRSRV
, ERRbadpath
);
8058 reply_nterror(req
, status
);
8063 * OS/2 workplace shell seems to send SET_EA requests of "null"
8064 * length (4 bytes containing IVAL 4).
8065 * They seem to have no effect. Bug #3212. JRA.
8068 if (total_data
&& (total_data
!= 4)) {
8069 /* Any data in this call is an EA list. */
8070 if (total_data
< 10) {
8071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8075 if (IVAL(pdata
,0) > total_data
) {
8076 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8077 IVAL(pdata
,0), (unsigned int)total_data
));
8078 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8082 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8085 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8089 if (!lp_ea_support(SNUM(conn
))) {
8090 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8094 /* If total_data == 4 Windows doesn't care what values
8095 * are placed in that field, it just ignores them.
8096 * The System i QNTC IBM SMB client puts bad values here,
8097 * so ignore them. */
8099 status
= create_directory(conn
, req
, smb_dname
);
8101 if (!NT_STATUS_IS_OK(status
)) {
8102 reply_nterror(req
, status
);
8106 /* Try and set any given EA. */
8108 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8109 if (!NT_STATUS_IS_OK(status
)) {
8110 reply_nterror(req
, status
);
8115 /* Realloc the parameter and data sizes */
8116 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8117 if(*pparams
== NULL
) {
8118 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8125 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8128 TALLOC_FREE(smb_dname
);
8132 /****************************************************************************
8133 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8134 We don't actually do this - we just send a null response.
8135 ****************************************************************************/
8137 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8138 struct smb_request
*req
,
8139 char **pparams
, int total_params
,
8140 char **ppdata
, int total_data
,
8141 unsigned int max_data_bytes
)
8143 char *params
= *pparams
;
8146 if (total_params
< 6) {
8147 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8151 info_level
= SVAL(params
,4);
8152 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8154 switch (info_level
) {
8159 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8163 /* Realloc the parameter and data sizes */
8164 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8165 if (*pparams
== NULL
) {
8166 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8171 SSVAL(params
,0,fnf_handle
);
8172 SSVAL(params
,2,0); /* No changes */
8173 SSVAL(params
,4,0); /* No EA errors */
8180 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8185 /****************************************************************************
8186 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8187 changes). Currently this does nothing.
8188 ****************************************************************************/
8190 static void call_trans2findnotifynext(connection_struct
*conn
,
8191 struct smb_request
*req
,
8192 char **pparams
, int total_params
,
8193 char **ppdata
, int total_data
,
8194 unsigned int max_data_bytes
)
8196 char *params
= *pparams
;
8198 DEBUG(3,("call_trans2findnotifynext\n"));
8200 /* Realloc the parameter and data sizes */
8201 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8202 if (*pparams
== NULL
) {
8203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8208 SSVAL(params
,0,0); /* No changes */
8209 SSVAL(params
,2,0); /* No EA errors */
8211 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8216 /****************************************************************************
8217 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8218 ****************************************************************************/
8220 static void call_trans2getdfsreferral(connection_struct
*conn
,
8221 struct smb_request
*req
,
8222 char **pparams
, int total_params
,
8223 char **ppdata
, int total_data
,
8224 unsigned int max_data_bytes
)
8226 char *params
= *pparams
;
8227 char *pathname
= NULL
;
8229 int max_referral_level
;
8230 NTSTATUS status
= NT_STATUS_OK
;
8231 TALLOC_CTX
*ctx
= talloc_tos();
8233 DEBUG(10,("call_trans2getdfsreferral\n"));
8235 if (total_params
< 3) {
8236 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8240 max_referral_level
= SVAL(params
,0);
8242 if(!lp_host_msdfs()) {
8243 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8247 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8248 total_params
- 2, STR_TERMINATE
);
8250 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8253 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8254 ppdata
,&status
)) < 0) {
8255 reply_nterror(req
, status
);
8259 SSVAL(req
->inbuf
, smb_flg2
,
8260 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8261 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8266 #define LMCAT_SPL 0x53
8267 #define LMFUNC_GETJOBID 0x60
8269 /****************************************************************************
8270 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8271 ****************************************************************************/
8273 static void call_trans2ioctl(connection_struct
*conn
,
8274 struct smb_request
*req
,
8275 char **pparams
, int total_params
,
8276 char **ppdata
, int total_data
,
8277 unsigned int max_data_bytes
)
8279 char *pdata
= *ppdata
;
8280 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8282 /* check for an invalid fid before proceeding */
8285 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8289 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8290 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8291 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8292 if (*ppdata
== NULL
) {
8293 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8298 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8299 CAN ACCEPT THIS IN UNICODE. JRA. */
8302 if (fsp
->print_file
) {
8303 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8307 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8308 global_myname(), 15,
8309 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8310 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8311 lp_servicename(SNUM(conn
)), 13,
8312 STR_ASCII
|STR_TERMINATE
); /* Service name */
8313 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8318 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8319 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8322 /****************************************************************************
8323 Reply to a SMBfindclose (stop trans2 directory search).
8324 ****************************************************************************/
8326 void reply_findclose(struct smb_request
*req
)
8329 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8331 START_PROFILE(SMBfindclose
);
8334 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8335 END_PROFILE(SMBfindclose
);
8339 dptr_num
= SVALS(req
->vwv
+0, 0);
8341 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8343 dptr_close(sconn
, &dptr_num
);
8345 reply_outbuf(req
, 0, 0);
8347 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8349 END_PROFILE(SMBfindclose
);
8353 /****************************************************************************
8354 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8355 ****************************************************************************/
8357 void reply_findnclose(struct smb_request
*req
)
8361 START_PROFILE(SMBfindnclose
);
8364 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8365 END_PROFILE(SMBfindnclose
);
8369 dptr_num
= SVAL(req
->vwv
+0, 0);
8371 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8373 /* We never give out valid handles for a
8374 findnotifyfirst - so any dptr_num is ok here.
8377 reply_outbuf(req
, 0, 0);
8379 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8381 END_PROFILE(SMBfindnclose
);
8385 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8386 struct trans_state
*state
)
8388 if (get_Protocol() >= PROTOCOL_NT1
) {
8389 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8390 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8393 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8394 if (state
->call
!= TRANSACT2_QFSINFO
&&
8395 state
->call
!= TRANSACT2_SETFSINFO
) {
8396 DEBUG(0,("handle_trans2: encryption required "
8398 (unsigned int)state
->call
));
8399 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8404 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8406 /* Now we must call the relevant TRANS2 function */
8407 switch(state
->call
) {
8408 case TRANSACT2_OPEN
:
8410 START_PROFILE(Trans2_open
);
8411 call_trans2open(conn
, req
,
8412 &state
->param
, state
->total_param
,
8413 &state
->data
, state
->total_data
,
8414 state
->max_data_return
);
8415 END_PROFILE(Trans2_open
);
8419 case TRANSACT2_FINDFIRST
:
8421 START_PROFILE(Trans2_findfirst
);
8422 call_trans2findfirst(conn
, req
,
8423 &state
->param
, state
->total_param
,
8424 &state
->data
, state
->total_data
,
8425 state
->max_data_return
);
8426 END_PROFILE(Trans2_findfirst
);
8430 case TRANSACT2_FINDNEXT
:
8432 START_PROFILE(Trans2_findnext
);
8433 call_trans2findnext(conn
, req
,
8434 &state
->param
, state
->total_param
,
8435 &state
->data
, state
->total_data
,
8436 state
->max_data_return
);
8437 END_PROFILE(Trans2_findnext
);
8441 case TRANSACT2_QFSINFO
:
8443 START_PROFILE(Trans2_qfsinfo
);
8444 call_trans2qfsinfo(conn
, req
,
8445 &state
->param
, state
->total_param
,
8446 &state
->data
, state
->total_data
,
8447 state
->max_data_return
);
8448 END_PROFILE(Trans2_qfsinfo
);
8452 case TRANSACT2_SETFSINFO
:
8454 START_PROFILE(Trans2_setfsinfo
);
8455 call_trans2setfsinfo(conn
, req
,
8456 &state
->param
, state
->total_param
,
8457 &state
->data
, state
->total_data
,
8458 state
->max_data_return
);
8459 END_PROFILE(Trans2_setfsinfo
);
8463 case TRANSACT2_QPATHINFO
:
8464 case TRANSACT2_QFILEINFO
:
8466 START_PROFILE(Trans2_qpathinfo
);
8467 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8468 &state
->param
, state
->total_param
,
8469 &state
->data
, state
->total_data
,
8470 state
->max_data_return
);
8471 END_PROFILE(Trans2_qpathinfo
);
8475 case TRANSACT2_SETPATHINFO
:
8476 case TRANSACT2_SETFILEINFO
:
8478 START_PROFILE(Trans2_setpathinfo
);
8479 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8480 &state
->param
, state
->total_param
,
8481 &state
->data
, state
->total_data
,
8482 state
->max_data_return
);
8483 END_PROFILE(Trans2_setpathinfo
);
8487 case TRANSACT2_FINDNOTIFYFIRST
:
8489 START_PROFILE(Trans2_findnotifyfirst
);
8490 call_trans2findnotifyfirst(conn
, req
,
8491 &state
->param
, state
->total_param
,
8492 &state
->data
, state
->total_data
,
8493 state
->max_data_return
);
8494 END_PROFILE(Trans2_findnotifyfirst
);
8498 case TRANSACT2_FINDNOTIFYNEXT
:
8500 START_PROFILE(Trans2_findnotifynext
);
8501 call_trans2findnotifynext(conn
, req
,
8502 &state
->param
, state
->total_param
,
8503 &state
->data
, state
->total_data
,
8504 state
->max_data_return
);
8505 END_PROFILE(Trans2_findnotifynext
);
8509 case TRANSACT2_MKDIR
:
8511 START_PROFILE(Trans2_mkdir
);
8512 call_trans2mkdir(conn
, req
,
8513 &state
->param
, state
->total_param
,
8514 &state
->data
, state
->total_data
,
8515 state
->max_data_return
);
8516 END_PROFILE(Trans2_mkdir
);
8520 case TRANSACT2_GET_DFS_REFERRAL
:
8522 START_PROFILE(Trans2_get_dfs_referral
);
8523 call_trans2getdfsreferral(conn
, req
,
8524 &state
->param
, state
->total_param
,
8525 &state
->data
, state
->total_data
,
8526 state
->max_data_return
);
8527 END_PROFILE(Trans2_get_dfs_referral
);
8531 case TRANSACT2_IOCTL
:
8533 START_PROFILE(Trans2_ioctl
);
8534 call_trans2ioctl(conn
, req
,
8535 &state
->param
, state
->total_param
,
8536 &state
->data
, state
->total_data
,
8537 state
->max_data_return
);
8538 END_PROFILE(Trans2_ioctl
);
8543 /* Error in request */
8544 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8545 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8549 /****************************************************************************
8550 Reply to a SMBtrans2.
8551 ****************************************************************************/
8553 void reply_trans2(struct smb_request
*req
)
8555 connection_struct
*conn
= req
->conn
;
8560 unsigned int tran_call
;
8561 struct trans_state
*state
;
8564 START_PROFILE(SMBtrans2
);
8566 if (req
->wct
< 14) {
8567 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8568 END_PROFILE(SMBtrans2
);
8572 dsoff
= SVAL(req
->vwv
+12, 0);
8573 dscnt
= SVAL(req
->vwv
+11, 0);
8574 psoff
= SVAL(req
->vwv
+10, 0);
8575 pscnt
= SVAL(req
->vwv
+9, 0);
8576 tran_call
= SVAL(req
->vwv
+14, 0);
8578 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8579 if (!NT_STATUS_IS_OK(result
)) {
8580 DEBUG(2, ("Got invalid trans2 request: %s\n",
8581 nt_errstr(result
)));
8582 reply_nterror(req
, result
);
8583 END_PROFILE(SMBtrans2
);
8588 switch (tran_call
) {
8589 /* List the allowed trans2 calls on IPC$ */
8590 case TRANSACT2_OPEN
:
8591 case TRANSACT2_GET_DFS_REFERRAL
:
8592 case TRANSACT2_QFILEINFO
:
8593 case TRANSACT2_QFSINFO
:
8594 case TRANSACT2_SETFSINFO
:
8597 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8598 END_PROFILE(SMBtrans2
);
8603 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8604 DEBUG(0, ("talloc failed\n"));
8605 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8606 END_PROFILE(SMBtrans2
);
8610 state
->cmd
= SMBtrans2
;
8612 state
->mid
= req
->mid
;
8613 state
->vuid
= req
->vuid
;
8614 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8615 state
->setup
= NULL
;
8616 state
->total_param
= SVAL(req
->vwv
+0, 0);
8617 state
->param
= NULL
;
8618 state
->total_data
= SVAL(req
->vwv
+1, 0);
8620 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8621 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8622 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8623 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8624 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8626 state
->call
= tran_call
;
8628 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8629 is so as a sanity check */
8630 if (state
->setup_count
!= 1) {
8632 * Need to have rc=0 for ioctl to get job id for OS/2.
8633 * Network printing will fail if function is not successful.
8634 * Similar function in reply.c will be used if protocol
8635 * is LANMAN1.0 instead of LM1.2X002.
8636 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8637 * outbuf doesn't have to be set(only job id is used).
8639 if ( (state
->setup_count
== 4)
8640 && (tran_call
== TRANSACT2_IOCTL
)
8641 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8642 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8643 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8645 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8646 DEBUG(2,("Transaction is %d\n",tran_call
));
8648 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8649 END_PROFILE(SMBtrans2
);
8654 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8657 if (state
->total_data
) {
8659 if (trans_oob(state
->total_data
, 0, dscnt
)
8660 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8664 /* Can't use talloc here, the core routines do realloc on the
8665 * params and data. */
8666 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8667 if (state
->data
== NULL
) {
8668 DEBUG(0,("reply_trans2: data malloc fail for %u "
8669 "bytes !\n", (unsigned int)state
->total_data
));
8671 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8672 END_PROFILE(SMBtrans2
);
8676 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8679 if (state
->total_param
) {
8681 if (trans_oob(state
->total_param
, 0, pscnt
)
8682 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8686 /* Can't use talloc here, the core routines do realloc on the
8687 * params and data. */
8688 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8689 if (state
->param
== NULL
) {
8690 DEBUG(0,("reply_trans: param malloc fail for %u "
8691 "bytes !\n", (unsigned int)state
->total_param
));
8692 SAFE_FREE(state
->data
);
8694 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8695 END_PROFILE(SMBtrans2
);
8699 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8702 state
->received_data
= dscnt
;
8703 state
->received_param
= pscnt
;
8705 if ((state
->received_param
== state
->total_param
) &&
8706 (state
->received_data
== state
->total_data
)) {
8708 handle_trans2(conn
, req
, state
);
8710 SAFE_FREE(state
->data
);
8711 SAFE_FREE(state
->param
);
8713 END_PROFILE(SMBtrans2
);
8717 DLIST_ADD(conn
->pending_trans
, state
);
8719 /* We need to send an interim response then receive the rest
8720 of the parameter/data bytes */
8721 reply_outbuf(req
, 0, 0);
8722 show_msg((char *)req
->outbuf
);
8723 END_PROFILE(SMBtrans2
);
8728 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8729 SAFE_FREE(state
->data
);
8730 SAFE_FREE(state
->param
);
8732 END_PROFILE(SMBtrans2
);
8733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8737 /****************************************************************************
8738 Reply to a SMBtranss2
8739 ****************************************************************************/
8741 void reply_transs2(struct smb_request
*req
)
8743 connection_struct
*conn
= req
->conn
;
8744 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8745 struct trans_state
*state
;
8747 START_PROFILE(SMBtranss2
);
8749 show_msg((char *)req
->inbuf
);
8752 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8753 END_PROFILE(SMBtranss2
);
8757 for (state
= conn
->pending_trans
; state
!= NULL
;
8758 state
= state
->next
) {
8759 if (state
->mid
== req
->mid
) {
8764 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8765 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8766 END_PROFILE(SMBtranss2
);
8770 /* Revise state->total_param and state->total_data in case they have
8771 changed downwards */
8773 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8774 state
->total_param
= SVAL(req
->vwv
+0, 0);
8775 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8776 state
->total_data
= SVAL(req
->vwv
+1, 0);
8778 pcnt
= SVAL(req
->vwv
+2, 0);
8779 poff
= SVAL(req
->vwv
+3, 0);
8780 pdisp
= SVAL(req
->vwv
+4, 0);
8782 dcnt
= SVAL(req
->vwv
+5, 0);
8783 doff
= SVAL(req
->vwv
+6, 0);
8784 ddisp
= SVAL(req
->vwv
+7, 0);
8786 state
->received_param
+= pcnt
;
8787 state
->received_data
+= dcnt
;
8789 if ((state
->received_data
> state
->total_data
) ||
8790 (state
->received_param
> state
->total_param
))
8794 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8795 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8798 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8802 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8803 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8806 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8809 if ((state
->received_param
< state
->total_param
) ||
8810 (state
->received_data
< state
->total_data
)) {
8811 END_PROFILE(SMBtranss2
);
8815 handle_trans2(conn
, req
, state
);
8817 DLIST_REMOVE(conn
->pending_trans
, state
);
8818 SAFE_FREE(state
->data
);
8819 SAFE_FREE(state
->param
);
8822 END_PROFILE(SMBtranss2
);
8827 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8828 DLIST_REMOVE(conn
->pending_trans
, state
);
8829 SAFE_FREE(state
->data
);
8830 SAFE_FREE(state
->param
);
8832 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8833 END_PROFILE(SMBtranss2
);