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"
31 extern enum protocol_types Protocol
;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
52 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name
)
72 static const char * const prohibited_ea_names
[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME
,
74 SAMBA_XATTR_DOS_ATTRIB
,
80 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
81 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
84 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
96 files_struct
*fsp
, const char *fname
,
97 const char *ea_name
, struct ea_struct
*pea
)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size
= 256;
106 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
108 return NT_STATUS_NO_MEMORY
;
111 if (fsp
&& fsp
->fh
->fd
!= -1) {
112 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
114 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
117 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
123 return map_nt_error_from_unix(errno
);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
127 dump_data(10, (uint8
*)val
, sizeret
);
130 if (strnequal(ea_name
, "user.", 5)) {
131 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
133 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
135 if (pea
->name
== NULL
) {
137 return NT_STATUS_NO_MEMORY
;
139 pea
->value
.data
= (unsigned char *)val
;
140 pea
->value
.length
= (size_t)sizeret
;
144 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
145 files_struct
*fsp
, const char *fname
,
146 char ***pnames
, size_t *pnum_names
)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size
= 1024;
150 char *ea_namelist
= NULL
;
155 ssize_t sizeret
= -1;
157 if (!lp_ea_support(SNUM(conn
))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY
;
173 while (ea_namelist_size
<= 65536) {
175 ea_namelist
= TALLOC_REALLOC_ARRAY(
176 names
, ea_namelist
, char, ea_namelist_size
);
177 if (ea_namelist
== NULL
) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY
;
183 if (fsp
&& fsp
->fh
->fd
!= -1) {
184 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
187 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
191 if ((sizeret
== -1) && (errno
== ERANGE
)) {
192 ea_namelist_size
*= 2;
201 return map_nt_error_from_unix(errno
);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret
));
215 * Ensure the result is 0-terminated
218 if (ea_namelist
[sizeret
-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR
;
228 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
232 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY
;
242 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
243 names
[num_names
++] = p
;
247 *pnum_names
= num_names
;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
256 const char *fname
, size_t *pea_total_len
)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list
*ea_list_head
= NULL
;
266 if (!lp_ea_support(SNUM(conn
))) {
270 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
273 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
277 for (i
=0; i
<num_names
; i
++) {
278 struct ea_list
*listp
;
281 if (strnequal(names
[i
], "system.", 7)
282 || samba_private_attr_name(names
[i
]))
285 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
296 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
299 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
303 (unsigned int)listp
->ea
.value
.length
));
305 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
309 /* Add on 4 for total length. */
310 if (*pea_total_len
) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len
));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
326 connection_struct
*conn
, struct ea_list
*ea_list
)
328 unsigned int ret_data_size
= 4;
331 SMB_ASSERT(total_data_size
>= 4);
333 if (!lp_ea_support(SNUM(conn
))) {
338 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
341 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
342 dos_namelen
= strlen(dos_ea_name
);
343 if (dos_namelen
> 255 || dos_namelen
== 0) {
346 if (ea_list
->ea
.value
.length
> 65535) {
349 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
353 /* We know we have room. */
354 SCVAL(p
,0,ea_list
->ea
.flags
);
355 SCVAL(p
,1,dos_namelen
);
356 SSVAL(p
,2,ea_list
->ea
.value
.length
);
357 fstrcpy(p
+4, dos_ea_name
);
358 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
360 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
361 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
364 ret_data_size
= PTR_DIFF(p
, pdata
);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
366 SIVAL(pdata
,0,ret_data_size
);
367 return ret_data_size
;
370 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
372 size_t total_ea_len
= 0;
373 TALLOC_CTX
*mem_ctx
= NULL
;
375 if (!lp_ea_support(SNUM(conn
))) {
378 mem_ctx
= talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
390 TALLOC_CTX
*mem_ctx
= talloc_tos();
391 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
393 for (; ea_list
; ea_list
= ea_list
->next
) {
394 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name
[5], ea_list
->ea
.name
));
397 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
409 if (!lp_ea_support(SNUM(conn
))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED
;
413 for (;ea_list
; ea_list
= ea_list
->next
) {
415 fstring unix_ea_name
;
417 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
420 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
424 if (samba_private_attr_name(unix_ea_name
)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
426 return NT_STATUS_ACCESS_DENIED
;
429 if (ea_list
->ea
.value
.length
== 0) {
430 /* Remove the attribute. */
431 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name
, fsp
->fsp_name
));
434 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name
, fname
));
438 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret
== -1 && errno
== ENOATTR
) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name
, fsp
->fsp_name
));
452 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
453 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name
, fname
));
457 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
458 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
464 if (errno
== ENOTSUP
) {
465 return NT_STATUS_EAS_NOT_SUPPORTED
;
468 return map_nt_error_from_unix(errno
);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
480 struct ea_list
*ea_list_head
= NULL
;
481 size_t converted_size
, offset
= 0;
483 while (offset
+ 2 < data_size
) {
484 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
485 unsigned int namelen
= CVAL(pdata
,offset
);
487 offset
++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
491 (offset
> data_size
) || (namelen
> data_size
) ||
492 (offset
+ namelen
>= data_size
)) {
495 /* Ensure the name is null terminated. */
496 if (pdata
[offset
+ namelen
] != '\0') {
499 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno
)));
508 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
522 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
524 unsigned int namelen
;
525 size_t converted_size
;
535 eal
->ea
.flags
= CVAL(pdata
,0);
536 namelen
= CVAL(pdata
,1);
537 val_len
= SVAL(pdata
,2);
539 if (4 + namelen
+ 1 + val_len
> data_size
) {
543 /* Ensure the name is null terminated. */
544 if (pdata
[namelen
+ 4] != '\0') {
547 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
556 if (!eal
->ea
.value
.data
) {
560 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal
->ea
.value
.data
[val_len
] = '\0';
564 /* But don't count the null. */
565 eal
->ea
.value
.length
--;
568 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
572 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
583 struct ea_list
*ea_list_head
= NULL
;
585 size_t bytes_used
= 0;
587 while (offset
< data_size
) {
588 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
594 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
595 offset
+= bytes_used
;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list
*ealist
)
608 struct ea_list
*listp
;
611 for (listp
= ealist
; listp
; listp
= listp
->next
) {
612 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
613 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
631 struct ea_list
*nlistp
, *flistp
;
633 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
634 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
635 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
641 /* Copy the data from this entry. */
642 nlistp
->ea
.flags
= flistp
->ea
.flags
;
643 nlistp
->ea
.value
= flistp
->ea
.value
;
646 nlistp
->ea
.flags
= 0;
647 ZERO_STRUCT(nlistp
->ea
.value
);
651 *total_ea_len
= ea_list_size(name_list
);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct
*conn
,
663 struct smb_request
*req
,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send
= datasize
;
677 int params_to_send
= paramsize
;
679 const char *pp
= params
;
680 const char *pd
= pdata
;
681 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
682 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset
= 0;
684 bool overflow
= False
;
686 /* Modify the data_to_send and datasize and set the error if
687 we're trying to send more than max_data_bytes. We still send
688 the part of the packet(s) that fit. Strange, but needed
691 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
692 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
693 max_data_bytes
, datasize
));
694 datasize
= data_to_send
= max_data_bytes
;
698 /* If there genuinely are no parameters or data to send just send the empty packet */
700 if(params_to_send
== 0 && data_to_send
== 0) {
701 reply_outbuf(req
, 10, 0);
702 show_msg((char *)req
->outbuf
);
706 /* When sending params and data ensure that both are nicely aligned */
707 /* Only do this alignment when there is also data to send - else
708 can cause NT redirector problems. */
710 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
711 data_alignment_offset
= 4 - (params_to_send
% 4);
713 /* Space is bufsize minus Netbios over TCP header minus SMB header */
714 /* The alignment_offset is to align the param bytes on an even byte
715 boundary. NT 4.0 Beta needs this to work correctly. */
717 useable_space
= max_send
- (smb_size
720 + data_alignment_offset
);
722 if (useable_space
< 0) {
723 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
724 "= %d!!!", useable_space
));
725 exit_server_cleanly("send_trans2_replies: Not enough space");
728 while (params_to_send
|| data_to_send
) {
729 /* Calculate whether we will totally or partially fill this packet */
731 total_sent_thistime
= params_to_send
+ data_to_send
;
733 /* We can never send more than useable_space */
735 * Note that 'useable_space' does not include the alignment offsets,
736 * but we must include the alignment offsets in the calculation of
737 * the length of the data we send over the wire, as the alignment offsets
738 * are sent here. Fix from Marc_Jacobsen@hp.com.
741 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
743 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
744 + data_alignment_offset
);
747 * We might have SMBtrans2s in req which was transferred to
748 * the outbuf, fix that.
750 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
752 /* Set total params and data to be sent */
753 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
754 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
756 /* Calculate how many parameters and data we can fit into
757 * this packet. Parameters get precedence
760 params_sent_thistime
= MIN(params_to_send
,useable_space
);
761 data_sent_thistime
= useable_space
- params_sent_thistime
;
762 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
764 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
766 /* smb_proff is the offset from the start of the SMB header to the
767 parameter bytes, however the first 4 bytes of outbuf are
768 the Netbios over TCP header. Thus use smb_base() to subtract
769 them from the calculation */
771 SSVAL(req
->outbuf
,smb_proff
,
772 ((smb_buf(req
->outbuf
)+alignment_offset
)
773 - smb_base(req
->outbuf
)));
775 if(params_sent_thistime
== 0)
776 SSVAL(req
->outbuf
,smb_prdisp
,0);
778 /* Absolute displacement of param bytes sent in this packet */
779 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
781 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
782 if(data_sent_thistime
== 0) {
783 SSVAL(req
->outbuf
,smb_droff
,0);
784 SSVAL(req
->outbuf
,smb_drdisp
, 0);
786 /* The offset of the data bytes is the offset of the
787 parameter bytes plus the number of parameters being sent this time */
788 SSVAL(req
->outbuf
, smb_droff
,
789 ((smb_buf(req
->outbuf
)+alignment_offset
)
790 - smb_base(req
->outbuf
))
791 + params_sent_thistime
+ data_alignment_offset
);
792 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
795 /* Initialize the padding for alignment */
797 if (alignment_offset
!= 0) {
798 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
801 /* Copy the param bytes into the packet */
803 if(params_sent_thistime
) {
804 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
805 params_sent_thistime
);
808 /* Copy in the data bytes */
809 if(data_sent_thistime
) {
810 if (data_alignment_offset
!= 0) {
811 memset((smb_buf(req
->outbuf
)+alignment_offset
+
812 params_sent_thistime
), 0,
813 data_alignment_offset
);
815 memcpy(smb_buf(req
->outbuf
)+alignment_offset
816 +params_sent_thistime
+data_alignment_offset
,
817 pd
,data_sent_thistime
);
820 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
821 params_sent_thistime
, data_sent_thistime
, useable_space
));
822 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
823 params_to_send
, data_to_send
, paramsize
, datasize
));
826 error_packet_set((char *)req
->outbuf
,
827 ERRDOS
,ERRbufferoverflow
,
828 STATUS_BUFFER_OVERFLOW
,
832 /* Send the packet */
833 show_msg((char *)req
->outbuf
);
834 if (!srv_send_smb(smbd_server_fd(),
837 IS_CONN_ENCRYPTED(conn
),
839 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
841 TALLOC_FREE(req
->outbuf
);
843 pp
+= params_sent_thistime
;
844 pd
+= data_sent_thistime
;
846 params_to_send
-= params_sent_thistime
;
847 data_to_send
-= data_sent_thistime
;
850 if(params_to_send
< 0 || data_to_send
< 0) {
851 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
852 params_to_send
, data_to_send
));
860 /****************************************************************************
861 Reply to a TRANSACT2_OPEN.
862 ****************************************************************************/
864 static void call_trans2open(connection_struct
*conn
,
865 struct smb_request
*req
,
866 char **pparams
, int total_params
,
867 char **ppdata
, int total_data
,
868 unsigned int max_data_bytes
)
870 char *params
= *pparams
;
871 char *pdata
= *ppdata
;
876 bool return_additional_info
;
887 SMB_STRUCT_STAT sbuf
;
890 struct ea_list
*ea_list
= NULL
;
895 uint32 create_disposition
;
896 uint32 create_options
= 0;
897 TALLOC_CTX
*ctx
= talloc_tos();
899 SET_STAT_INVALID(sbuf
);
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params
< 29) {
906 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
910 flags
= SVAL(params
, 0);
911 deny_mode
= SVAL(params
, 2);
912 open_attr
= SVAL(params
,6);
913 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
914 if (oplock_request
) {
915 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
919 return_additional_info
= BITSETW(params
,0);
920 open_sattr
= SVAL(params
, 4);
921 open_time
= make_unix_date3(params
+8);
923 open_ofun
= SVAL(params
,12);
924 open_size
= IVAL(params
,14);
928 reply_doserror(req
, ERRSRV
, ERRaccess
);
932 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
933 total_params
- 28, STR_TERMINATE
,
935 if (!NT_STATUS_IS_OK(status
)) {
936 reply_nterror(req
, status
);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
942 (unsigned int)open_ofun
, open_size
));
944 if (open_ofun
== 0) {
945 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
949 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
954 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
958 /* Any data in this call is an EA list. */
959 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
960 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
964 if (total_data
!= 4) {
965 if (total_data
< 10) {
966 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
970 if (IVAL(pdata
,0) > total_data
) {
971 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972 IVAL(pdata
,0), (unsigned int)total_data
));
973 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
977 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
983 } else if (IVAL(pdata
,0) != 4) {
984 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
988 status
= SMB_VFS_CREATE_FILE(
991 0, /* root_dir_fid */
993 CFF_DOS_PATH
, /* create_file_flags */
994 access_mask
, /* access_mask */
995 share_mode
, /* share_access */
996 create_disposition
, /* create_disposition*/
997 create_options
, /* create_options */
998 open_attr
, /* file_attributes */
999 oplock_request
, /* oplock_request */
1000 open_size
, /* allocation_size */
1002 ea_list
, /* ea_list */
1004 &smb_action
, /* pinfo */
1007 if (!NT_STATUS_IS_OK(status
)) {
1008 if (open_was_deferred(req
->mid
)) {
1009 /* We have re-scheduled this call. */
1012 reply_openerror(req
, status
);
1016 size
= get_file_size_stat(&sbuf
);
1017 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1018 mtime
= sbuf
.st_mtime
;
1019 inode
= sbuf
.st_ino
;
1021 close_file(req
, fsp
, ERROR_CLOSE
);
1022 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1026 /* Realloc the size of parameters and data we will return */
1027 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1028 if(*pparams
== NULL
) {
1029 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1034 SSVAL(params
,0,fsp
->fnum
);
1035 SSVAL(params
,2,fattr
);
1036 srv_put_dos_date2(params
,4, mtime
);
1037 SIVAL(params
,8, (uint32
)size
);
1038 SSVAL(params
,12,deny_mode
);
1039 SSVAL(params
,14,0); /* open_type - file or directory. */
1040 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1042 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1043 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1046 SSVAL(params
,18,smb_action
);
1049 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1051 SIVAL(params
,20,inode
);
1052 SSVAL(params
,24,0); /* Padding. */
1054 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1055 SIVAL(params
, 26, ea_size
);
1057 SIVAL(params
, 26, 0);
1060 /* Send the required number of replies */
1061 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1064 /*********************************************************
1065 Routine to check if a given string matches exactly.
1066 as a special case a mask of "." does NOT match. That
1067 is required for correct wildcard semantics
1068 Case can be significant or not.
1069 **********************************************************/
1071 static bool exact_match(connection_struct
*conn
,
1075 if (mask
[0] == '.' && mask
[1] == 0)
1077 if (dptr_has_wild(conn
->dirptr
)) {
1080 if (conn
->case_sensitive
)
1081 return strcmp(str
,mask
)==0;
1083 return StrCaseCmp(str
,mask
) == 0;
1086 /****************************************************************************
1087 Return the filetype for UNIX extensions.
1088 ****************************************************************************/
1090 static uint32
unix_filetype(mode_t mode
)
1093 return UNIX_TYPE_FILE
;
1094 else if(S_ISDIR(mode
))
1095 return UNIX_TYPE_DIR
;
1097 else if(S_ISLNK(mode
))
1098 return UNIX_TYPE_SYMLINK
;
1101 else if(S_ISCHR(mode
))
1102 return UNIX_TYPE_CHARDEV
;
1105 else if(S_ISBLK(mode
))
1106 return UNIX_TYPE_BLKDEV
;
1109 else if(S_ISFIFO(mode
))
1110 return UNIX_TYPE_FIFO
;
1113 else if(S_ISSOCK(mode
))
1114 return UNIX_TYPE_SOCKET
;
1117 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1118 return UNIX_TYPE_UNKNOWN
;
1121 /****************************************************************************
1122 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1123 ****************************************************************************/
1125 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1127 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1128 SMB_STRUCT_STAT
*psbuf
,
1130 enum perm_type ptype
,
1135 if (perms
== SMB_MODE_NO_CHANGE
) {
1136 if (!VALID_STAT(*psbuf
)) {
1137 return NT_STATUS_INVALID_PARAMETER
;
1139 *ret_perms
= psbuf
->st_mode
;
1140 return NT_STATUS_OK
;
1144 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1145 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1146 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1147 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1148 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1149 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1150 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1151 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1152 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1154 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1157 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1160 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1165 /* Apply mode mask */
1166 ret
&= lp_create_mask(SNUM(conn
));
1167 /* Add in force bits */
1168 ret
|= lp_force_create_mode(SNUM(conn
));
1171 ret
&= lp_dir_mask(SNUM(conn
));
1172 /* Add in force bits */
1173 ret
|= lp_force_dir_mode(SNUM(conn
));
1175 case PERM_EXISTING_FILE
:
1176 /* Apply mode mask */
1177 ret
&= lp_security_mask(SNUM(conn
));
1178 /* Add in force bits */
1179 ret
|= lp_force_security_mode(SNUM(conn
));
1181 case PERM_EXISTING_DIR
:
1182 /* Apply mode mask */
1183 ret
&= lp_dir_security_mask(SNUM(conn
));
1184 /* Add in force bits */
1185 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1190 return NT_STATUS_OK
;
1193 /****************************************************************************
1194 Needed to show the msdfs symlinks as directories. Modifies psbuf
1195 to be a directory if it's a msdfs link.
1196 ****************************************************************************/
1198 static bool check_msdfs_link(connection_struct
*conn
,
1199 const char *pathname
,
1200 SMB_STRUCT_STAT
*psbuf
)
1202 int saved_errno
= errno
;
1203 if(lp_host_msdfs() &&
1204 lp_msdfs_root(SNUM(conn
)) &&
1205 is_msdfs_link(conn
, pathname
, psbuf
)) {
1207 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1210 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1211 errno
= saved_errno
;
1214 errno
= saved_errno
;
1219 /****************************************************************************
1220 Get a level dependent lanman2 dir entry.
1221 ****************************************************************************/
1223 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1224 connection_struct
*conn
,
1226 const char *path_mask
,
1229 int requires_resume_key
,
1235 int space_remaining
,
1237 bool *got_exact_match
,
1238 int *last_entry_off
,
1239 struct ea_list
*name_list
)
1243 SMB_STRUCT_STAT sbuf
;
1244 const char *mask
= NULL
;
1245 char *pathreal
= NULL
;
1247 char *p
, *q
, *pdata
= *ppdata
;
1251 SMB_OFF_T file_size
= 0;
1252 uint64_t allocation_size
= 0;
1254 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1255 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1257 char *last_entry_ptr
;
1259 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1260 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1261 bool check_mangled_names
= lp_manglednames(conn
->params
);
1262 char mangled_name
[13]; /* mangled 8.3 name. */
1264 *out_of_space
= False
;
1265 *got_exact_match
= False
;
1267 ZERO_STRUCT(mdate_ts
);
1268 ZERO_STRUCT(adate_ts
);
1269 ZERO_STRUCT(create_date_ts
);
1271 if (!conn
->dirptr
) {
1275 p
= strrchr_m(path_mask
,'/');
1278 mask
= talloc_strdup(ctx
,"*.*");
1288 bool ms_dfs_link
= False
;
1290 /* Needed if we run out of space */
1291 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1292 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1295 * Due to bugs in NT client redirectors we are not using
1296 * resume keys any more - set them to zero.
1297 * Check out the related comments in findfirst/findnext.
1303 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1304 (long)conn
->dirptr
,curr_dirpos
));
1311 * fname may get mangled, dname is never mangled.
1312 * Whenever we're accessing the filesystem we use
1313 * pathreal which is composed from dname.
1319 /* Mangle fname if it's an illegal name. */
1320 if (mangle_must_mangle(dname
,conn
->params
)) {
1321 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1323 continue; /* Error - couldn't mangle. */
1325 fname
= talloc_strdup(ctx
, mangled_name
);
1331 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1332 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1335 if(!got_match
&& check_mangled_names
&&
1336 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1338 * It turns out that NT matches wildcards against
1339 * both long *and* short names. This may explain some
1340 * of the wildcard wierdness from old DOS clients
1341 * that some people have been seeing.... JRA.
1343 /* Force the mangling into 8.3. */
1344 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1350 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1355 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1357 if (dont_descend
&& !isdots
) {
1364 pathreal
= talloc_asprintf(ctx
,
1369 pathreal
= talloc_asprintf(ctx
,
1380 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1381 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1383 pathreal
,strerror(errno
)));
1384 TALLOC_FREE(pathreal
);
1388 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1389 /* Needed to show the msdfs symlinks as
1392 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal
,strerror(errno
)));
1396 TALLOC_FREE(pathreal
);
1403 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1405 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1408 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1409 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1410 TALLOC_FREE(pathreal
);
1415 if (!(mode
& aDIR
)) {
1416 file_size
= get_file_size_stat(&sbuf
);
1418 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,NULL
,&sbuf
);
1420 mdate_ts
= get_mtimespec(&sbuf
);
1421 adate_ts
= get_atimespec(&sbuf
);
1422 create_date_ts
= get_create_timespec(&sbuf
,
1423 lp_fake_dir_create_times(SNUM(conn
)));
1425 if (ask_sharemode
) {
1426 struct timespec write_time_ts
;
1427 struct file_id fileid
;
1429 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1430 get_file_infos(fileid
, NULL
, &write_time_ts
);
1431 if (!null_timespec(write_time_ts
)) {
1432 mdate_ts
= write_time_ts
;
1436 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1437 dos_filetime_timespec(&create_date_ts
);
1438 dos_filetime_timespec(&mdate_ts
);
1439 dos_filetime_timespec(&adate_ts
);
1442 create_date
= convert_timespec_to_time_t(create_date_ts
);
1443 mdate
= convert_timespec_to_time_t(mdate_ts
);
1444 adate
= convert_timespec_to_time_t(adate_ts
);
1446 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1451 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1461 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1463 switch (info_level
) {
1464 case SMB_FIND_INFO_STANDARD
:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key
) {
1470 srv_put_dos_date2(p
,0,create_date
);
1471 srv_put_dos_date2(p
,4,adate
);
1472 srv_put_dos_date2(p
,8,mdate
);
1473 SIVAL(p
,12,(uint32
)file_size
);
1474 SIVAL(p
,16,(uint32
)allocation_size
);
1478 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1479 p
+= ucs2_align(base_data
, p
, 0);
1481 len
= srvstr_push(base_data
, flags2
, p
,
1482 fname
, PTR_DIFF(end_data
, p
),
1484 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1486 SCVAL(nameptr
, -1, len
- 2);
1488 SCVAL(nameptr
, -1, 0);
1492 SCVAL(nameptr
, -1, len
- 1);
1494 SCVAL(nameptr
, -1, 0);
1500 case SMB_FIND_EA_SIZE
:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key
) {
1506 srv_put_dos_date2(p
,0,create_date
);
1507 srv_put_dos_date2(p
,4,adate
);
1508 srv_put_dos_date2(p
,8,mdate
);
1509 SIVAL(p
,12,(uint32
)file_size
);
1510 SIVAL(p
,16,(uint32
)allocation_size
);
1513 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1514 SIVAL(p
,22,ea_size
); /* Extended attributes */
1518 len
= srvstr_push(base_data
, flags2
,
1519 p
, fname
, PTR_DIFF(end_data
, p
),
1520 STR_TERMINATE
| STR_NOALIGN
);
1521 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1534 SCVAL(nameptr
,0,len
);
1536 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1539 case SMB_FIND_EA_LIST
:
1541 struct ea_list
*file_list
= NULL
;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1548 if(requires_resume_key
) {
1552 srv_put_dos_date2(p
,0,create_date
);
1553 srv_put_dos_date2(p
,4,adate
);
1554 srv_put_dos_date2(p
,8,mdate
);
1555 SIVAL(p
,12,(uint32
)file_size
);
1556 SIVAL(p
,16,(uint32
)allocation_size
);
1558 p
+= 22; /* p now points to the EA area. */
1560 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1561 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1568 *out_of_space
= True
;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False
; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1576 len
= srvstr_push(base_data
, flags2
,
1577 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1578 STR_TERMINATE
| STR_NOALIGN
);
1579 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1592 SCVAL(nameptr
,0,len
);
1594 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1602 SIVAL(p
,0,reskey
); p
+= 4;
1603 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1604 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1605 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1606 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1607 SOFF_T(p
,0,file_size
); p
+= 8;
1608 SOFF_T(p
,0,allocation_size
); p
+= 8;
1609 SIVAL(p
,0,nt_extmode
); p
+= 4;
1610 q
= p
; p
+= 4; /* q is placeholder for name length. */
1612 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1613 SIVAL(p
,0,ea_size
); /* Extended attributes */
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3
&& check_mangled_names
) {
1621 if (!name_to_8_3(fname
,mangled_name
,True
,
1623 /* Error - mangle failed ! */
1624 memset(mangled_name
,'\0',12);
1626 mangled_name
[12] = 0;
1627 len
= srvstr_push(base_data
, flags2
,
1628 p
+2, mangled_name
, 24,
1629 STR_UPPER
|STR_UNICODE
);
1631 memset(p
+ 2 + len
,'\0',24 - len
);
1638 len
= srvstr_push(base_data
, flags2
, p
,
1639 fname
, PTR_DIFF(end_data
, p
),
1640 STR_TERMINATE_ASCII
);
1643 SIVAL(p
,0,0); /* Ensure any padding is null. */
1644 len
= PTR_DIFF(p
, pdata
);
1645 len
= (len
+ 3) & ~3;
1650 case SMB_FIND_FILE_DIRECTORY_INFO
:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1653 SIVAL(p
,0,reskey
); p
+= 4;
1654 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1655 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1656 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1657 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1658 SOFF_T(p
,0,file_size
); p
+= 8;
1659 SOFF_T(p
,0,allocation_size
); p
+= 8;
1660 SIVAL(p
,0,nt_extmode
); p
+= 4;
1661 len
= srvstr_push(base_data
, flags2
,
1662 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1663 STR_TERMINATE_ASCII
);
1666 SIVAL(p
,0,0); /* Ensure any padding is null. */
1667 len
= PTR_DIFF(p
, pdata
);
1668 len
= (len
+ 3) & ~3;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1676 SIVAL(p
,0,reskey
); p
+= 4;
1677 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1678 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1679 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1680 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1681 SOFF_T(p
,0,file_size
); p
+= 8;
1682 SOFF_T(p
,0,allocation_size
); p
+= 8;
1683 SIVAL(p
,0,nt_extmode
); p
+= 4;
1684 q
= p
; p
+= 4; /* q is placeholder for name length. */
1686 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1687 SIVAL(p
,0,ea_size
); /* Extended attributes */
1690 len
= srvstr_push(base_data
, flags2
, p
,
1691 fname
, PTR_DIFF(end_data
, p
),
1692 STR_TERMINATE_ASCII
);
1696 SIVAL(p
,0,0); /* Ensure any padding is null. */
1697 len
= PTR_DIFF(p
, pdata
);
1698 len
= (len
+ 3) & ~3;
1703 case SMB_FIND_FILE_NAMES_INFO
:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1706 SIVAL(p
,0,reskey
); p
+= 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len
= srvstr_push(base_data
, flags2
, p
,
1711 fname
, PTR_DIFF(end_data
, p
),
1712 STR_TERMINATE_ASCII
);
1715 SIVAL(p
,0,0); /* Ensure any padding is null. */
1716 len
= PTR_DIFF(p
, pdata
);
1717 len
= (len
+ 3) & ~3;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1725 SIVAL(p
,0,reskey
); p
+= 4;
1726 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1727 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1728 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1729 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1730 SOFF_T(p
,0,file_size
); p
+= 8;
1731 SOFF_T(p
,0,allocation_size
); p
+= 8;
1732 SIVAL(p
,0,nt_extmode
); p
+= 4;
1733 q
= p
; p
+= 4; /* q is placeholder for name length. */
1735 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1736 SIVAL(p
,0,ea_size
); /* Extended attributes */
1739 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1740 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1741 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1742 len
= srvstr_push(base_data
, flags2
, p
,
1743 fname
, PTR_DIFF(end_data
, p
),
1744 STR_TERMINATE_ASCII
);
1747 SIVAL(p
,0,0); /* Ensure any padding is null. */
1748 len
= PTR_DIFF(p
, pdata
);
1749 len
= (len
+ 3) & ~3;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1758 SIVAL(p
,0,reskey
); p
+= 4;
1759 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1760 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1761 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1762 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1763 SOFF_T(p
,0,file_size
); p
+= 8;
1764 SOFF_T(p
,0,allocation_size
); p
+= 8;
1765 SIVAL(p
,0,nt_extmode
); p
+= 4;
1766 q
= p
; p
+= 4; /* q is placeholder for name length */
1768 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1769 SIVAL(p
,0,ea_size
); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3
&& check_mangled_names
) {
1777 if (!name_to_8_3(fname
,mangled_name
,True
,
1779 /* Error - mangle failed ! */
1780 memset(mangled_name
,'\0',12);
1782 mangled_name
[12] = 0;
1783 len
= srvstr_push(base_data
, flags2
,
1784 p
+2, mangled_name
, 24,
1785 STR_UPPER
|STR_UNICODE
);
1788 memset(p
+ 2 + len
,'\0',24 - len
);
1795 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1796 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1797 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1798 len
= srvstr_push(base_data
, flags2
, p
,
1799 fname
, PTR_DIFF(end_data
, p
),
1800 STR_TERMINATE_ASCII
);
1803 SIVAL(p
,0,0); /* Ensure any padding is null. */
1804 len
= PTR_DIFF(p
, pdata
);
1805 len
= (len
+ 3) & ~3;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX
:
1813 case SMB_FIND_FILE_UNIX_INFO2
:
1815 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level
== SMB_FIND_FILE_UNIX
) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p
= store_file_unix_basic(conn
, p
,
1823 len
= srvstr_push(base_data
, flags2
, p
,
1824 fname
, PTR_DIFF(end_data
, p
),
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p
= store_file_unix_basic_info2(conn
, p
,
1832 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1833 PTR_DIFF(end_data
, p
), 0);
1834 SIVAL(nameptr
, 0, len
);
1838 SIVAL(p
,0,0); /* Ensure any padding is null. */
1840 len
= PTR_DIFF(p
, pdata
);
1841 len
= (len
+ 3) & ~3;
1842 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1854 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1855 /* Move the dirptr back to prev_dirpos */
1856 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1857 *out_of_space
= True
;
1858 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1859 return False
; /* Not finished - just out of space */
1862 /* Setup the last entry pointer, as an offset from base_data */
1863 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1864 /* Advance the data pointer to the next slot */
1870 /****************************************************************************
1871 Reply to a TRANS2_FINDFIRST.
1872 ****************************************************************************/
1874 static void call_trans2findfirst(connection_struct
*conn
,
1875 struct smb_request
*req
,
1876 char **pparams
, int total_params
,
1877 char **ppdata
, int total_data
,
1878 unsigned int max_data_bytes
)
1880 /* We must be careful here that we don't return more than the
1881 allowed number of data bytes. If this means returning fewer than
1882 maxentries then so be it. We assume that the redirector has
1883 enough room for the fixed number of parameter bytes it has
1885 struct smb_filename
*smb_dname
= NULL
;
1886 char *params
= *pparams
;
1887 char *pdata
= *ppdata
;
1891 uint16 findfirst_flags
;
1892 bool close_after_first
;
1894 bool requires_resume_key
;
1896 char *directory
= NULL
;
1899 int last_entry_off
=0;
1903 bool finished
= False
;
1904 bool dont_descend
= False
;
1905 bool out_of_space
= False
;
1906 int space_remaining
;
1907 bool mask_contains_wcard
= False
;
1908 struct ea_list
*ea_list
= NULL
;
1909 NTSTATUS ntstatus
= NT_STATUS_OK
;
1910 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1911 TALLOC_CTX
*ctx
= talloc_tos();
1913 if (total_params
< 13) {
1914 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1918 dirtype
= SVAL(params
,0);
1919 maxentries
= SVAL(params
,2);
1920 findfirst_flags
= SVAL(params
,4);
1921 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1922 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1923 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1924 info_level
= SVAL(params
,6);
1926 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1927 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1928 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1929 info_level
, max_data_bytes
));
1932 /* W2K3 seems to treat zero as 1. */
1936 switch (info_level
) {
1937 case SMB_FIND_INFO_STANDARD
:
1938 case SMB_FIND_EA_SIZE
:
1939 case SMB_FIND_EA_LIST
:
1940 case SMB_FIND_FILE_DIRECTORY_INFO
:
1941 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1942 case SMB_FIND_FILE_NAMES_INFO
:
1943 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1944 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1945 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1947 case SMB_FIND_FILE_UNIX
:
1948 case SMB_FIND_FILE_UNIX_INFO2
:
1949 /* Always use filesystem for UNIX mtime query. */
1950 ask_sharemode
= false;
1951 if (!lp_unix_extensions()) {
1952 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1957 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1961 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1962 params
+12, total_params
- 12,
1963 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1964 if (!NT_STATUS_IS_OK(ntstatus
)) {
1965 reply_nterror(req
, ntstatus
);
1969 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1970 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1973 &mask_contains_wcard
);
1974 if (!NT_STATUS_IS_OK(ntstatus
)) {
1975 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1976 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1977 ERRSRV
, ERRbadpath
);
1980 reply_nterror(req
, ntstatus
);
1984 ntstatus
= unix_convert(ctx
, conn
, directory
, &smb_dname
,
1985 (UCF_SAVE_LCOMP
| UCF_ALLOW_WCARD_LCOMP
));
1986 if (!NT_STATUS_IS_OK(ntstatus
)) {
1987 reply_nterror(req
, ntstatus
);
1991 mask
= smb_dname
->original_lcomp
;
1993 ntstatus
= get_full_smb_filename(ctx
, smb_dname
, &directory
);
1994 TALLOC_FREE(smb_dname
);
1995 if (!NT_STATUS_IS_OK(ntstatus
)) {
1996 reply_nterror(req
, ntstatus
);
2000 ntstatus
= check_name(conn
, directory
);
2001 if (!NT_STATUS_IS_OK(ntstatus
)) {
2002 reply_nterror(req
, ntstatus
);
2006 p
= strrchr_m(directory
,'/');
2008 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2009 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2010 mask
= talloc_strdup(ctx
,"*");
2012 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2015 mask_contains_wcard
= True
;
2017 directory
= talloc_strdup(talloc_tos(), "./");
2019 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2026 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2028 if (info_level
== SMB_FIND_EA_LIST
) {
2031 if (total_data
< 4) {
2032 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2036 ea_size
= IVAL(pdata
,0);
2037 if (ea_size
!= total_data
) {
2038 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2039 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2044 if (!lp_ea_support(SNUM(conn
))) {
2045 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2049 /* Pull out the list of names. */
2050 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2052 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2057 *ppdata
= (char *)SMB_REALLOC(
2058 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2059 if(*ppdata
== NULL
) {
2060 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2064 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2066 /* Realloc the params space */
2067 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2068 if (*pparams
== NULL
) {
2069 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2074 /* Save the wildcard match and attribs we are using on this directory -
2075 needed as lanman2 assumes these are being saved between calls */
2077 ntstatus
= dptr_create(conn
,
2083 mask_contains_wcard
,
2087 if (!NT_STATUS_IS_OK(ntstatus
)) {
2088 reply_nterror(req
, ntstatus
);
2092 dptr_num
= dptr_dnum(conn
->dirptr
);
2093 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2095 /* Initialize per TRANS2_FIND_FIRST operation data */
2096 dptr_init_search_op(conn
->dirptr
);
2098 /* We don't need to check for VOL here as this is returned by
2099 a different TRANS2 call. */
2101 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2102 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2103 dont_descend
= True
;
2106 space_remaining
= max_data_bytes
;
2107 out_of_space
= False
;
2109 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2110 bool got_exact_match
= False
;
2112 /* this is a heuristic to avoid seeking the dirptr except when
2113 absolutely necessary. It allows for a filename of about 40 chars */
2114 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2115 out_of_space
= True
;
2118 finished
= !get_lanman2_dir_entry(ctx
,
2121 mask
,dirtype
,info_level
,
2122 requires_resume_key
,dont_descend
,
2125 space_remaining
, &out_of_space
,
2127 &last_entry_off
, ea_list
);
2130 if (finished
&& out_of_space
)
2133 if (!finished
&& !out_of_space
)
2137 * As an optimisation if we know we aren't looking
2138 * for a wildcard name (ie. the name matches the wildcard exactly)
2139 * then we can finish on any (first) match.
2140 * This speeds up large directory searches. JRA.
2146 /* Ensure space_remaining never goes -ve. */
2147 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2148 space_remaining
= 0;
2149 out_of_space
= true;
2151 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2155 /* Check if we can close the dirptr */
2156 if(close_after_first
|| (finished
&& close_if_end
)) {
2157 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2158 dptr_close(&dptr_num
);
2162 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2163 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2164 * the protocol level is less than NT1. Tested with smbclient. JRA.
2165 * This should fix the OS/2 client bug #2335.
2168 if(numentries
== 0) {
2169 dptr_close(&dptr_num
);
2170 if (Protocol
< PROTOCOL_NT1
) {
2171 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2174 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2175 ERRDOS
, ERRbadfile
);
2180 /* At this point pdata points to numentries directory entries. */
2182 /* Set up the return parameter block */
2183 SSVAL(params
,0,dptr_num
);
2184 SSVAL(params
,2,numentries
);
2185 SSVAL(params
,4,finished
);
2186 SSVAL(params
,6,0); /* Never an EA error */
2187 SSVAL(params
,8,last_entry_off
);
2189 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2192 if ((! *directory
) && dptr_path(dptr_num
)) {
2193 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2195 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2199 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2200 smb_fn_name(req
->cmd
),
2201 mask
, directory
, dirtype
, numentries
) );
2204 * Force a name mangle here to ensure that the
2205 * mask as an 8.3 name is top of the mangled cache.
2206 * The reasons for this are subtle. Don't remove
2207 * this code unless you know what you are doing
2208 * (see PR#13758). JRA.
2211 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2212 char mangled_name
[13];
2213 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2219 /****************************************************************************
2220 Reply to a TRANS2_FINDNEXT.
2221 ****************************************************************************/
2223 static void call_trans2findnext(connection_struct
*conn
,
2224 struct smb_request
*req
,
2225 char **pparams
, int total_params
,
2226 char **ppdata
, int total_data
,
2227 unsigned int max_data_bytes
)
2229 /* We must be careful here that we don't return more than the
2230 allowed number of data bytes. If this means returning fewer than
2231 maxentries then so be it. We assume that the redirector has
2232 enough room for the fixed number of parameter bytes it has
2234 char *params
= *pparams
;
2235 char *pdata
= *ppdata
;
2241 uint16 findnext_flags
;
2242 bool close_after_request
;
2244 bool requires_resume_key
;
2246 bool mask_contains_wcard
= False
;
2247 char *resume_name
= NULL
;
2248 const char *mask
= NULL
;
2249 const char *directory
= NULL
;
2253 int i
, last_entry_off
=0;
2254 bool finished
= False
;
2255 bool dont_descend
= False
;
2256 bool out_of_space
= False
;
2257 int space_remaining
;
2258 struct ea_list
*ea_list
= NULL
;
2259 NTSTATUS ntstatus
= NT_STATUS_OK
;
2260 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2261 TALLOC_CTX
*ctx
= talloc_tos();
2263 if (total_params
< 13) {
2264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2268 dptr_num
= SVAL(params
,0);
2269 maxentries
= SVAL(params
,2);
2270 info_level
= SVAL(params
,4);
2271 resume_key
= IVAL(params
,6);
2272 findnext_flags
= SVAL(params
,10);
2273 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2274 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2275 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2276 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2278 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2280 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2281 &mask_contains_wcard
);
2282 if (!NT_STATUS_IS_OK(ntstatus
)) {
2283 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2284 complain (it thinks we're asking for the directory above the shared
2285 path or an invalid name). Catch this as the resume name is only compared, never used in
2286 a file access. JRA. */
2287 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2288 &resume_name
, params
+12,
2292 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2293 reply_nterror(req
, ntstatus
);
2298 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2299 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2300 resume_key = %d resume name = %s continue=%d level = %d\n",
2301 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2302 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2305 /* W2K3 seems to treat zero as 1. */
2309 switch (info_level
) {
2310 case SMB_FIND_INFO_STANDARD
:
2311 case SMB_FIND_EA_SIZE
:
2312 case SMB_FIND_EA_LIST
:
2313 case SMB_FIND_FILE_DIRECTORY_INFO
:
2314 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2315 case SMB_FIND_FILE_NAMES_INFO
:
2316 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2317 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2318 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2320 case SMB_FIND_FILE_UNIX
:
2321 case SMB_FIND_FILE_UNIX_INFO2
:
2322 /* Always use filesystem for UNIX mtime query. */
2323 ask_sharemode
= false;
2324 if (!lp_unix_extensions()) {
2325 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2330 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2334 if (info_level
== SMB_FIND_EA_LIST
) {
2337 if (total_data
< 4) {
2338 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2342 ea_size
= IVAL(pdata
,0);
2343 if (ea_size
!= total_data
) {
2344 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2345 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2350 if (!lp_ea_support(SNUM(conn
))) {
2351 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2355 /* Pull out the list of names. */
2356 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2358 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2363 *ppdata
= (char *)SMB_REALLOC(
2364 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2365 if(*ppdata
== NULL
) {
2366 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2371 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2373 /* Realloc the params space */
2374 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2375 if(*pparams
== NULL
) {
2376 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2382 /* Check that the dptr is valid */
2383 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2384 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2388 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2390 /* Get the wildcard mask from the dptr */
2391 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2392 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2393 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2398 directory
= conn
->dirpath
;
2400 /* Get the attr mask from the dptr */
2401 dirtype
= dptr_attr(dptr_num
);
2403 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2404 dptr_num
, mask
, dirtype
,
2406 dptr_TellDir(conn
->dirptr
)));
2408 /* Initialize per TRANS2_FIND_NEXT operation data */
2409 dptr_init_search_op(conn
->dirptr
);
2411 /* We don't need to check for VOL here as this is returned by
2412 a different TRANS2 call. */
2414 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2415 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2416 dont_descend
= True
;
2419 space_remaining
= max_data_bytes
;
2420 out_of_space
= False
;
2423 * Seek to the correct position. We no longer use the resume key but
2424 * depend on the last file name instead.
2427 if(*resume_name
&& !continue_bit
) {
2430 long current_pos
= 0;
2432 * Remember, name_to_8_3 is called by
2433 * get_lanman2_dir_entry(), so the resume name
2434 * could be mangled. Ensure we check the unmangled name.
2437 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2438 char *new_resume_name
= NULL
;
2439 mangle_lookup_name_from_8_3(ctx
,
2443 if (new_resume_name
) {
2444 resume_name
= new_resume_name
;
2449 * Fix for NT redirector problem triggered by resume key indexes
2450 * changing between directory scans. We now return a resume key of 0
2451 * and instead look for the filename to continue from (also given
2452 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2453 * findfirst/findnext (as is usual) then the directory pointer
2454 * should already be at the correct place.
2457 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2458 } /* end if resume_name && !continue_bit */
2460 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2461 bool got_exact_match
= False
;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2466 out_of_space
= True
;
2469 finished
= !get_lanman2_dir_entry(ctx
,
2472 mask
,dirtype
,info_level
,
2473 requires_resume_key
,dont_descend
,
2476 space_remaining
, &out_of_space
,
2478 &last_entry_off
, ea_list
);
2481 if (finished
&& out_of_space
)
2484 if (!finished
&& !out_of_space
)
2488 * As an optimisation if we know we aren't looking
2489 * for a wildcard name (ie. the name matches the wildcard exactly)
2490 * then we can finish on any (first) match.
2491 * This speeds up large directory searches. JRA.
2497 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2500 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2501 smb_fn_name(req
->cmd
),
2502 mask
, directory
, dirtype
, numentries
) );
2504 /* Check if we can close the dirptr */
2505 if(close_after_request
|| (finished
&& close_if_end
)) {
2506 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2507 dptr_close(&dptr_num
); /* This frees up the saved mask */
2510 /* Set up the return parameter block */
2511 SSVAL(params
,0,numentries
);
2512 SSVAL(params
,2,finished
);
2513 SSVAL(params
,4,0); /* Never an EA error */
2514 SSVAL(params
,6,last_entry_off
);
2516 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2522 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2524 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2528 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2530 SMB_ASSERT(extended_info
!= NULL
);
2532 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2533 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2534 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2535 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2536 #ifdef SAMBA_VERSION_REVISION
2537 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2539 extended_info
->samba_subversion
= 0;
2540 #ifdef SAMBA_VERSION_RC_RELEASE
2541 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2543 #ifdef SAMBA_VERSION_PRE_RELEASE
2544 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2547 #ifdef SAMBA_VERSION_VENDOR_PATCH
2548 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2550 extended_info
->samba_gitcommitdate
= 0;
2551 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2552 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2555 memset(extended_info
->samba_version_string
, 0,
2556 sizeof(extended_info
->samba_version_string
));
2558 snprintf (extended_info
->samba_version_string
,
2559 sizeof(extended_info
->samba_version_string
),
2560 "%s", samba_version_string());
2563 /****************************************************************************
2564 Reply to a TRANS2_QFSINFO (query filesystem info).
2565 ****************************************************************************/
2567 static void call_trans2qfsinfo(connection_struct
*conn
,
2568 struct smb_request
*req
,
2569 char **pparams
, int total_params
,
2570 char **ppdata
, int total_data
,
2571 unsigned int max_data_bytes
)
2573 char *pdata
, *end_data
;
2574 char *params
= *pparams
;
2578 const char *vname
= volume_label(SNUM(conn
));
2579 int snum
= SNUM(conn
);
2580 char *fstype
= lp_fstype(SNUM(conn
));
2581 uint32 additional_flags
= 0;
2583 if (total_params
< 2) {
2584 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2588 info_level
= SVAL(params
,0);
2591 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2592 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2593 "info level (0x%x) on IPC$.\n",
2594 (unsigned int)info_level
));
2595 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2600 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2601 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2602 DEBUG(0,("call_trans2qfsinfo: encryption required "
2603 "and info level 0x%x sent.\n",
2604 (unsigned int)info_level
));
2605 exit_server_cleanly("encryption required "
2611 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2613 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2614 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2615 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2619 *ppdata
= (char *)SMB_REALLOC(
2620 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2621 if (*ppdata
== NULL
) {
2622 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2627 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2628 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2630 switch (info_level
) {
2631 case SMB_INFO_ALLOCATION
:
2633 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2635 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2636 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2640 block_size
= lp_block_size(snum
);
2641 if (bsize
< block_size
) {
2642 uint64_t factor
= block_size
/bsize
;
2647 if (bsize
> block_size
) {
2648 uint64_t factor
= bsize
/block_size
;
2653 bytes_per_sector
= 512;
2654 sectors_per_unit
= bsize
/bytes_per_sector
;
2656 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2657 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2658 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2660 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2661 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2662 SIVAL(pdata
,l1_cUnit
,dsize
);
2663 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2664 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2668 case SMB_INFO_VOLUME
:
2669 /* Return volume name */
2671 * Add volume serial number - hash of a combination of
2672 * the called hostname and the service name.
2674 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2676 * Win2k3 and previous mess this up by sending a name length
2677 * one byte short. I believe only older clients (OS/2 Win9x) use
2678 * this call so try fixing this by adding a terminating null to
2679 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2683 pdata
+l2_vol_szVolLabel
, vname
,
2684 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2685 STR_NOALIGN
|STR_TERMINATE
);
2686 SCVAL(pdata
,l2_vol_cch
,len
);
2687 data_len
= l2_vol_szVolLabel
+ len
;
2688 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2689 (unsigned)st
.st_ctime
, len
, vname
));
2692 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2693 case SMB_FS_ATTRIBUTE_INFORMATION
:
2695 additional_flags
= 0;
2696 #if defined(HAVE_SYS_QUOTAS)
2697 additional_flags
|= FILE_VOLUME_QUOTAS
;
2700 if(lp_nt_acl_support(SNUM(conn
))) {
2701 additional_flags
|= FILE_PERSISTENT_ACLS
;
2704 /* Capabilities are filled in at connection time through STATVFS call */
2705 additional_flags
|= conn
->fs_capabilities
;
2707 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2708 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2709 additional_flags
); /* FS ATTRIBUTES */
2711 SIVAL(pdata
,4,255); /* Max filename component length */
2712 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2713 and will think we can't do long filenames */
2714 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2715 PTR_DIFF(end_data
, pdata
+12),
2718 data_len
= 12 + len
;
2721 case SMB_QUERY_FS_LABEL_INFO
:
2722 case SMB_FS_LABEL_INFORMATION
:
2723 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2724 PTR_DIFF(end_data
, pdata
+4), 0);
2729 case SMB_QUERY_FS_VOLUME_INFO
:
2730 case SMB_FS_VOLUME_INFORMATION
:
2733 * Add volume serial number - hash of a combination of
2734 * the called hostname and the service name.
2736 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2737 (str_checksum(get_local_machine_name())<<16));
2739 /* Max label len is 32 characters. */
2740 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2741 PTR_DIFF(end_data
, pdata
+18),
2743 SIVAL(pdata
,12,len
);
2746 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2747 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2750 case SMB_QUERY_FS_SIZE_INFO
:
2751 case SMB_FS_SIZE_INFORMATION
:
2753 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2755 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2756 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2759 block_size
= lp_block_size(snum
);
2760 if (bsize
< block_size
) {
2761 uint64_t factor
= block_size
/bsize
;
2766 if (bsize
> block_size
) {
2767 uint64_t factor
= bsize
/block_size
;
2772 bytes_per_sector
= 512;
2773 sectors_per_unit
= bsize
/bytes_per_sector
;
2774 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2775 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2776 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2777 SBIG_UINT(pdata
,0,dsize
);
2778 SBIG_UINT(pdata
,8,dfree
);
2779 SIVAL(pdata
,16,sectors_per_unit
);
2780 SIVAL(pdata
,20,bytes_per_sector
);
2784 case SMB_FS_FULL_SIZE_INFORMATION
:
2786 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2788 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2789 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2792 block_size
= lp_block_size(snum
);
2793 if (bsize
< block_size
) {
2794 uint64_t factor
= block_size
/bsize
;
2799 if (bsize
> block_size
) {
2800 uint64_t factor
= bsize
/block_size
;
2805 bytes_per_sector
= 512;
2806 sectors_per_unit
= bsize
/bytes_per_sector
;
2807 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2808 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2809 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2810 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2811 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2812 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2813 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2814 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2818 case SMB_QUERY_FS_DEVICE_INFO
:
2819 case SMB_FS_DEVICE_INFORMATION
:
2821 SIVAL(pdata
,0,0); /* dev type */
2822 SIVAL(pdata
,4,0); /* characteristics */
2825 #ifdef HAVE_SYS_QUOTAS
2826 case SMB_FS_QUOTA_INFORMATION
:
2828 * what we have to send --metze:
2830 * Unknown1: 24 NULL bytes
2831 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2832 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2833 * Quota Flags: 2 byte :
2834 * Unknown3: 6 NULL bytes
2838 * details for Quota Flags:
2840 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2841 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2842 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2843 * 0x0001 Enable Quotas: enable quota for this fs
2847 /* we need to fake up a fsp here,
2848 * because its not send in this call
2851 SMB_NTQUOTA_STRUCT quotas
;
2854 ZERO_STRUCT(quotas
);
2860 if (conn
->server_info
->utok
.uid
!= 0) {
2861 DEBUG(0,("set_user_quota: access_denied "
2862 "service [%s] user [%s]\n",
2863 lp_servicename(SNUM(conn
)),
2864 conn
->server_info
->unix_name
));
2865 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2869 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2870 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2871 reply_doserror(req
, ERRSRV
, ERRerror
);
2877 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2879 /* Unknown1 24 NULL bytes*/
2880 SBIG_UINT(pdata
,0,(uint64_t)0);
2881 SBIG_UINT(pdata
,8,(uint64_t)0);
2882 SBIG_UINT(pdata
,16,(uint64_t)0);
2884 /* Default Soft Quota 8 bytes */
2885 SBIG_UINT(pdata
,24,quotas
.softlim
);
2887 /* Default Hard Quota 8 bytes */
2888 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2890 /* Quota flag 2 bytes */
2891 SSVAL(pdata
,40,quotas
.qflags
);
2893 /* Unknown3 6 NULL bytes */
2899 #endif /* HAVE_SYS_QUOTAS */
2900 case SMB_FS_OBJECTID_INFORMATION
:
2902 unsigned char objid
[16];
2903 struct smb_extended_info extended_info
;
2904 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2905 samba_extended_info_version (&extended_info
);
2906 SIVAL(pdata
,16,extended_info
.samba_magic
);
2907 SIVAL(pdata
,20,extended_info
.samba_version
);
2908 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2909 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2910 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2916 * Query the version and capabilities of the CIFS UNIX extensions
2920 case SMB_QUERY_CIFS_UNIX_INFO
:
2922 bool large_write
= lp_min_receive_file_size() &&
2923 !srv_is_signing_active(smbd_server_conn
);
2924 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
2925 int encrypt_caps
= 0;
2927 if (!lp_unix_extensions()) {
2928 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2932 switch (conn
->encrypt_level
) {
2938 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2941 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2942 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2943 large_write
= false;
2949 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2950 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2952 /* We have POSIX ACLs, pathname, encryption,
2953 * large read/write, and locking capability. */
2955 SBIG_UINT(pdata
,4,((uint64_t)(
2956 CIFS_UNIX_POSIX_ACLS_CAP
|
2957 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2958 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2959 CIFS_UNIX_EXTATTR_CAP
|
2960 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2962 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2964 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2968 case SMB_QUERY_POSIX_FS_INFO
:
2971 vfs_statvfs_struct svfs
;
2973 if (!lp_unix_extensions()) {
2974 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2978 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2982 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2983 SIVAL(pdata
,4,svfs
.BlockSize
);
2984 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2985 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2986 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2987 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2988 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2989 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2990 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2992 } else if (rc
== EOPNOTSUPP
) {
2993 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2995 #endif /* EOPNOTSUPP */
2997 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2998 reply_doserror(req
, ERRSRV
, ERRerror
);
3004 case SMB_QUERY_POSIX_WHOAMI
:
3010 if (!lp_unix_extensions()) {
3011 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3015 if (max_data_bytes
< 40) {
3016 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
3020 /* We ARE guest if global_sid_Builtin_Guests is
3021 * in our list of SIDs.
3023 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3024 conn
->server_info
->ptok
)) {
3025 flags
|= SMB_WHOAMI_GUEST
;
3028 /* We are NOT guest if global_sid_Authenticated_Users
3029 * is in our list of SIDs.
3031 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3032 conn
->server_info
->ptok
)) {
3033 flags
&= ~SMB_WHOAMI_GUEST
;
3036 /* NOTE: 8 bytes for UID/GID, irrespective of native
3037 * platform size. This matches
3038 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3040 data_len
= 4 /* flags */
3047 + 4 /* pad/reserved */
3048 + (conn
->server_info
->utok
.ngroups
* 8)
3050 + (conn
->server_info
->ptok
->num_sids
*
3054 SIVAL(pdata
, 0, flags
);
3055 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3057 (uint64_t)conn
->server_info
->utok
.uid
);
3058 SBIG_UINT(pdata
, 16,
3059 (uint64_t)conn
->server_info
->utok
.gid
);
3062 if (data_len
>= max_data_bytes
) {
3063 /* Potential overflow, skip the GIDs and SIDs. */
3065 SIVAL(pdata
, 24, 0); /* num_groups */
3066 SIVAL(pdata
, 28, 0); /* num_sids */
3067 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3068 SIVAL(pdata
, 36, 0); /* reserved */
3074 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3075 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3077 /* We walk the SID list twice, but this call is fairly
3078 * infrequent, and I don't expect that it's performance
3079 * sensitive -- jpeach
3081 for (i
= 0, sid_bytes
= 0;
3082 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3083 sid_bytes
+= ndr_size_dom_sid(
3084 &conn
->server_info
->ptok
->user_sids
[i
],
3089 /* SID list byte count */
3090 SIVAL(pdata
, 32, sid_bytes
);
3092 /* 4 bytes pad/reserved - must be zero */
3093 SIVAL(pdata
, 36, 0);
3097 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3098 SBIG_UINT(pdata
, data_len
,
3099 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3105 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3106 int sid_len
= ndr_size_dom_sid(
3107 &conn
->server_info
->ptok
->user_sids
[i
],
3111 sid_linearize(pdata
+ data_len
, sid_len
,
3112 &conn
->server_info
->ptok
->user_sids
[i
]);
3113 data_len
+= sid_len
;
3119 case SMB_MAC_QUERY_FS_INFO
:
3121 * Thursby MAC extension... ONLY on NTFS filesystems
3122 * once we do streams then we don't need this
3124 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3126 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3131 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3136 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3139 DEBUG( 4, ( "%s info_level = %d\n",
3140 smb_fn_name(req
->cmd
), info_level
) );
3145 /****************************************************************************
3146 Reply to a TRANS2_SETFSINFO (set filesystem info).
3147 ****************************************************************************/
3149 static void call_trans2setfsinfo(connection_struct
*conn
,
3150 struct smb_request
*req
,
3151 char **pparams
, int total_params
,
3152 char **ppdata
, int total_data
,
3153 unsigned int max_data_bytes
)
3155 char *pdata
= *ppdata
;
3156 char *params
= *pparams
;
3159 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3162 if (total_params
< 4) {
3163 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3165 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3169 info_level
= SVAL(params
,2);
3172 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3173 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3174 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3175 "info level (0x%x) on IPC$.\n",
3176 (unsigned int)info_level
));
3177 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3182 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3183 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3184 DEBUG(0,("call_trans2setfsinfo: encryption required "
3185 "and info level 0x%x sent.\n",
3186 (unsigned int)info_level
));
3187 exit_server_cleanly("encryption required "
3193 switch(info_level
) {
3194 case SMB_SET_CIFS_UNIX_INFO
:
3196 uint16 client_unix_major
;
3197 uint16 client_unix_minor
;
3198 uint32 client_unix_cap_low
;
3199 uint32 client_unix_cap_high
;
3201 if (!lp_unix_extensions()) {
3203 NT_STATUS_INVALID_LEVEL
);
3207 /* There should be 12 bytes of capabilities set. */
3208 if (total_data
< 8) {
3211 NT_STATUS_INVALID_PARAMETER
);
3214 client_unix_major
= SVAL(pdata
,0);
3215 client_unix_minor
= SVAL(pdata
,2);
3216 client_unix_cap_low
= IVAL(pdata
,4);
3217 client_unix_cap_high
= IVAL(pdata
,8);
3218 /* Just print these values for now. */
3219 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3220 cap_low = 0x%x, cap_high = 0x%x\n",
3221 (unsigned int)client_unix_major
,
3222 (unsigned int)client_unix_minor
,
3223 (unsigned int)client_unix_cap_low
,
3224 (unsigned int)client_unix_cap_high
));
3226 /* Here is where we must switch to posix pathname processing... */
3227 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3228 lp_set_posix_pathnames();
3229 mangle_change_to_posix();
3232 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3233 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3234 /* Client that knows how to do posix locks,
3235 * but not posix open/mkdir operations. Set a
3236 * default type for read/write checks. */
3238 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3244 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3247 size_t param_len
= 0;
3248 size_t data_len
= total_data
;
3250 if (!lp_unix_extensions()) {
3253 NT_STATUS_INVALID_LEVEL
);
3257 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3260 NT_STATUS_NOT_SUPPORTED
);
3264 DEBUG( 4,("call_trans2setfsinfo: "
3265 "request transport encryption.\n"));
3267 status
= srv_request_encryption_setup(conn
,
3268 (unsigned char **)ppdata
,
3270 (unsigned char **)pparams
,
3273 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3274 !NT_STATUS_IS_OK(status
)) {
3275 reply_nterror(req
, status
);
3279 send_trans2_replies(conn
, req
,
3286 if (NT_STATUS_IS_OK(status
)) {
3287 /* Server-side transport
3288 * encryption is now *on*. */
3289 status
= srv_encryption_start(conn
);
3290 if (!NT_STATUS_IS_OK(status
)) {
3291 exit_server_cleanly(
3292 "Failure in setting "
3293 "up encrypted transport");
3299 case SMB_FS_QUOTA_INFORMATION
:
3301 files_struct
*fsp
= NULL
;
3302 SMB_NTQUOTA_STRUCT quotas
;
3304 ZERO_STRUCT(quotas
);
3307 if ((conn
->server_info
->utok
.uid
!= 0)
3308 ||!CAN_WRITE(conn
)) {
3309 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3310 lp_servicename(SNUM(conn
)),
3311 conn
->server_info
->unix_name
));
3312 reply_doserror(req
, ERRSRV
, ERRaccess
);
3316 /* note: normaly there're 48 bytes,
3317 * but we didn't use the last 6 bytes for now
3320 fsp
= file_fsp(req
, SVAL(params
,0));
3322 if (!check_fsp_ntquota_handle(conn
, req
,
3324 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3326 req
, NT_STATUS_INVALID_HANDLE
);
3330 if (total_data
< 42) {
3331 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3335 NT_STATUS_INVALID_PARAMETER
);
3339 /* unknown_1 24 NULL bytes in pdata*/
3341 /* the soft quotas 8 bytes (uint64_t)*/
3342 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3343 #ifdef LARGE_SMB_OFF_T
3344 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3345 #else /* LARGE_SMB_OFF_T */
3346 if ((IVAL(pdata
,28) != 0)&&
3347 ((quotas
.softlim
!= 0xFFFFFFFF)||
3348 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3349 /* more than 32 bits? */
3352 NT_STATUS_INVALID_PARAMETER
);
3355 #endif /* LARGE_SMB_OFF_T */
3357 /* the hard quotas 8 bytes (uint64_t)*/
3358 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3359 #ifdef LARGE_SMB_OFF_T
3360 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3361 #else /* LARGE_SMB_OFF_T */
3362 if ((IVAL(pdata
,36) != 0)&&
3363 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3364 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3365 /* more than 32 bits? */
3368 NT_STATUS_INVALID_PARAMETER
);
3371 #endif /* LARGE_SMB_OFF_T */
3373 /* quota_flags 2 bytes **/
3374 quotas
.qflags
= SVAL(pdata
,40);
3376 /* unknown_2 6 NULL bytes follow*/
3378 /* now set the quotas */
3379 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3380 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3381 reply_doserror(req
, ERRSRV
, ERRerror
);
3388 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3390 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3396 * sending this reply works fine,
3397 * but I'm not sure it's the same
3398 * like windows do...
3401 reply_outbuf(req
, 10, 0);
3404 #if defined(HAVE_POSIX_ACLS)
3405 /****************************************************************************
3406 Utility function to count the number of entries in a POSIX acl.
3407 ****************************************************************************/
3409 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3411 unsigned int ace_count
= 0;
3412 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3413 SMB_ACL_ENTRY_T entry
;
3415 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3417 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3418 entry_id
= SMB_ACL_NEXT_ENTRY
;
3425 /****************************************************************************
3426 Utility function to marshall a POSIX acl into wire format.
3427 ****************************************************************************/
3429 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3431 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3432 SMB_ACL_ENTRY_T entry
;
3434 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3435 SMB_ACL_TAG_T tagtype
;
3436 SMB_ACL_PERMSET_T permset
;
3437 unsigned char perms
= 0;
3438 unsigned int own_grp
;
3441 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3442 entry_id
= SMB_ACL_NEXT_ENTRY
;
3445 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3446 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3450 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3451 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3455 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3456 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3457 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3459 SCVAL(pdata
,1,perms
);
3462 case SMB_ACL_USER_OBJ
:
3463 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3464 own_grp
= (unsigned int)pst
->st_uid
;
3465 SIVAL(pdata
,2,own_grp
);
3470 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3472 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3475 own_grp
= (unsigned int)*puid
;
3476 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3477 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3478 SIVAL(pdata
,2,own_grp
);
3482 case SMB_ACL_GROUP_OBJ
:
3483 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3484 own_grp
= (unsigned int)pst
->st_gid
;
3485 SIVAL(pdata
,2,own_grp
);
3490 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3492 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3495 own_grp
= (unsigned int)*pgid
;
3496 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3497 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3498 SIVAL(pdata
,2,own_grp
);
3503 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3504 SIVAL(pdata
,2,0xFFFFFFFF);
3505 SIVAL(pdata
,6,0xFFFFFFFF);
3508 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3509 SIVAL(pdata
,2,0xFFFFFFFF);
3510 SIVAL(pdata
,6,0xFFFFFFFF);
3513 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3516 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3523 /****************************************************************************
3524 Store the FILE_UNIX_BASIC info.
3525 ****************************************************************************/
3527 static char *store_file_unix_basic(connection_struct
*conn
,
3530 const SMB_STRUCT_STAT
*psbuf
)
3532 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3533 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3535 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3538 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3541 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3542 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3543 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3546 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3550 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3554 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3557 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3561 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3565 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3568 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3572 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3579 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3580 * the chflags(2) (or equivalent) flags.
3582 * XXX: this really should be behind the VFS interface. To do this, we would
3583 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3584 * Each VFS module could then implement its own mapping as appropriate for the
3585 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3587 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3591 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3595 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3599 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3603 { UF_HIDDEN
, EXT_HIDDEN
},
3606 /* Do not remove. We need to guarantee that this array has at least one
3607 * entry to build on HP-UX.
3613 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3614 uint32
*smb_fflags
, uint32
*smb_fmask
)
3616 #ifdef HAVE_STAT_ST_FLAGS
3619 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3620 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3621 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3622 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3625 #endif /* HAVE_STAT_ST_FLAGS */
3628 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3629 const uint32 smb_fflags
,
3630 const uint32 smb_fmask
,
3633 #ifdef HAVE_STAT_ST_FLAGS
3634 uint32 max_fmask
= 0;
3637 *stat_fflags
= psbuf
->st_flags
;
3639 /* For each flags requested in smb_fmask, check the state of the
3640 * corresponding flag in smb_fflags and set or clear the matching
3644 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3645 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3646 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3647 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3648 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3650 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3655 /* If smb_fmask is asking to set any bits that are not supported by
3656 * our flag mappings, we should fail.
3658 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3665 #endif /* HAVE_STAT_ST_FLAGS */
3669 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3670 * of file flags and birth (create) time.
3672 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3675 const SMB_STRUCT_STAT
*psbuf
)
3677 uint32 file_flags
= 0;
3678 uint32 flags_mask
= 0;
3680 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3682 /* Create (birth) time 64 bit */
3683 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3686 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3687 SIVAL(pdata
, 0, file_flags
); /* flags */
3688 SIVAL(pdata
, 4, flags_mask
); /* mask */
3694 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3695 const struct stream_struct
*streams
,
3697 unsigned int max_data_bytes
,
3698 unsigned int *data_size
)
3701 unsigned int ofs
= 0;
3703 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3704 unsigned int next_offset
;
3706 smb_ucs2_t
*namebuf
;
3708 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3709 streams
[i
].name
, &namelen
) ||
3712 return NT_STATUS_INVALID_PARAMETER
;
3716 * name_buf is now null-terminated, we need to marshall as not
3722 SIVAL(data
, ofs
+4, namelen
);
3723 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3724 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3725 memcpy(data
+ofs
+24, namebuf
, namelen
);
3726 TALLOC_FREE(namebuf
);
3728 next_offset
= ofs
+ 24 + namelen
;
3730 if (i
== num_streams
-1) {
3731 SIVAL(data
, ofs
, 0);
3734 unsigned int align
= ndr_align_size(next_offset
, 8);
3736 memset(data
+next_offset
, 0, align
);
3737 next_offset
+= align
;
3739 SIVAL(data
, ofs
, next_offset
- ofs
);
3748 return NT_STATUS_OK
;
3751 /****************************************************************************
3752 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3753 ****************************************************************************/
3755 static void call_trans2qpipeinfo(connection_struct
*conn
,
3756 struct smb_request
*req
,
3757 unsigned int tran_call
,
3758 char **pparams
, int total_params
,
3759 char **ppdata
, int total_data
,
3760 unsigned int max_data_bytes
)
3762 char *params
= *pparams
;
3763 char *pdata
= *ppdata
;
3764 unsigned int data_size
= 0;
3765 unsigned int param_size
= 2;
3770 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3774 if (total_params
< 4) {
3775 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3779 fsp
= file_fsp(req
, SVAL(params
,0));
3780 if (!fsp_is_np(fsp
)) {
3781 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3785 info_level
= SVAL(params
,2);
3787 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3788 if (*pparams
== NULL
) {
3789 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3794 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3795 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3796 if (*ppdata
== NULL
) {
3797 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3802 switch (info_level
) {
3803 case SMB_FILE_STANDARD_INFORMATION
:
3805 SOFF_T(pdata
,0,4096LL);
3812 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3816 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3822 /****************************************************************************
3823 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3824 file name or file id).
3825 ****************************************************************************/
3827 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3828 struct smb_request
*req
,
3829 unsigned int tran_call
,
3830 char **pparams
, int total_params
,
3831 char **ppdata
, int total_data
,
3832 unsigned int max_data_bytes
)
3834 char *params
= *pparams
;
3835 char *pdata
= *ppdata
;
3836 char *dstart
, *dend
;
3840 SMB_OFF_T file_size
=0;
3841 uint64_t allocation_size
=0;
3842 unsigned int data_size
= 0;
3843 unsigned int param_size
= 2;
3844 SMB_STRUCT_STAT sbuf
;
3845 char *dos_fname
= NULL
;
3847 struct smb_filename
*smb_fname
= NULL
;
3852 bool delete_pending
= False
;
3854 time_t create_time
, mtime
, atime
;
3855 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3856 struct timespec write_time_ts
;
3857 files_struct
*fsp
= NULL
;
3858 struct file_id fileid
;
3859 struct ea_list
*ea_list
= NULL
;
3860 char *lock_data
= NULL
;
3861 bool ms_dfs_link
= false;
3862 TALLOC_CTX
*ctx
= talloc_tos();
3865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3870 ZERO_STRUCT(write_time_ts
);
3872 if (tran_call
== TRANSACT2_QFILEINFO
) {
3873 if (total_params
< 4) {
3874 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3879 call_trans2qpipeinfo(conn
, req
, tran_call
,
3880 pparams
, total_params
,
3886 fsp
= file_fsp(req
, SVAL(params
,0));
3887 info_level
= SVAL(params
,2);
3889 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3891 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3892 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3896 /* Initial check for valid fsp ptr. */
3897 if (!check_fsp_open(conn
, req
, fsp
)) {
3901 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3903 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3907 if(fsp
->fake_file_handle
) {
3909 * This is actually for the QUOTA_FAKE_FILE --metze
3912 /* We know this name is ok, it's already passed the checks. */
3914 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3916 * This is actually a QFILEINFO on a directory
3917 * handle (returned from an NT SMB). NT5.0 seems
3918 * to do this call. JRA.
3921 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3922 /* Always do lstat for UNIX calls. */
3923 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3924 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3925 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3928 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3929 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3930 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3934 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3935 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3938 * Original code - this is an open file.
3940 if (!check_fsp(conn
, req
, fsp
)) {
3944 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3945 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3946 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3949 pos
= fsp
->fh
->position_information
;
3950 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3951 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3955 NTSTATUS status
= NT_STATUS_OK
;
3958 if (total_params
< 7) {
3959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3963 info_level
= SVAL(params
,0);
3965 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3967 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3968 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3972 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3974 STR_TERMINATE
, &status
);
3975 if (!NT_STATUS_IS_OK(status
)) {
3976 reply_nterror(req
, status
);
3980 status
= resolve_dfspath(ctx
,
3982 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3985 if (!NT_STATUS_IS_OK(status
)) {
3986 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3987 reply_botherror(req
,
3988 NT_STATUS_PATH_NOT_COVERED
,
3989 ERRSRV
, ERRbadpath
);
3991 reply_nterror(req
, status
);
3995 status
= unix_convert(ctx
, conn
, fname
, &smb_fname
, 0);
3996 if (!NT_STATUS_IS_OK(status
)) {
3997 reply_nterror(req
, status
);
4000 sbuf
= smb_fname
->st
;
4002 status
= get_full_smb_filename(ctx
, smb_fname
, &fname
);
4003 TALLOC_FREE(smb_fname
);
4004 if (!NT_STATUS_IS_OK(status
)) {
4005 reply_nterror(req
, status
);
4009 status
= check_name(conn
, fname
);
4010 if (!NT_STATUS_IS_OK(status
)) {
4011 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
4012 reply_nterror(req
, status
);
4016 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
4017 && is_ntfs_stream_name(fname
)) {
4019 SMB_STRUCT_STAT bsbuf
;
4021 status
= split_ntfs_stream_name(talloc_tos(), fname
,
4023 if (!NT_STATUS_IS_OK(status
)) {
4024 DEBUG(10, ("create_file_unixpath: "
4025 "split_ntfs_stream_name failed: %s\n",
4026 nt_errstr(status
)));
4027 reply_nterror(req
, status
);
4031 SMB_ASSERT(!is_ntfs_stream_name(base
)); /* paranoia.. */
4033 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4034 /* Always do lstat for UNIX calls. */
4035 if (SMB_VFS_LSTAT(conn
,base
,&bsbuf
)) {
4036 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base
,strerror(errno
)));
4037 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4041 if (SMB_VFS_STAT(conn
,base
,&bsbuf
) != 0) {
4042 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base
,strerror(errno
)));
4043 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4048 fileid
= vfs_file_id_from_sbuf(conn
, &bsbuf
);
4049 get_file_infos(fileid
, &delete_pending
, NULL
);
4050 if (delete_pending
) {
4051 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4056 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4057 /* Always do lstat for UNIX calls. */
4058 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4059 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4060 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4064 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4065 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4068 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4069 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4074 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4075 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4076 if (delete_pending
) {
4077 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4082 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4083 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4087 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4088 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4090 p
= strrchr_m(fname
,'/');
4097 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4099 mode
= dos_mode(conn
,fname
,&sbuf
);
4102 mode
= FILE_ATTRIBUTE_NORMAL
;
4104 nlink
= sbuf
.st_nlink
;
4106 if (nlink
&& (mode
&aDIR
)) {
4110 if ((nlink
> 0) && delete_pending
) {
4114 fullpathname
= fname
;
4116 file_size
= get_file_size_stat(&sbuf
);
4118 /* Pull out any data sent here before we realloc. */
4119 switch (info_level
) {
4120 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4122 /* Pull any EA list from the data portion. */
4125 if (total_data
< 4) {
4127 req
, NT_STATUS_INVALID_PARAMETER
);
4130 ea_size
= IVAL(pdata
,0);
4132 if (total_data
> 0 && ea_size
!= total_data
) {
4133 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4134 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4136 req
, NT_STATUS_INVALID_PARAMETER
);
4140 if (!lp_ea_support(SNUM(conn
))) {
4141 reply_doserror(req
, ERRDOS
,
4142 ERReasnotsupported
);
4146 /* Pull out the list of names. */
4147 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4150 req
, NT_STATUS_INVALID_PARAMETER
);
4156 case SMB_QUERY_POSIX_LOCK
:
4158 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4159 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4163 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4165 req
, NT_STATUS_INVALID_PARAMETER
);
4169 /* Copy the lock range data. */
4170 lock_data
= (char *)TALLOC_MEMDUP(
4171 ctx
, pdata
, total_data
);
4173 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4181 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4182 if (*pparams
== NULL
) {
4183 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4188 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4189 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4190 if (*ppdata
== NULL
) {
4191 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4196 dend
= dstart
+ data_size
- 1;
4198 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4199 mtime_ts
= get_mtimespec(&sbuf
);
4200 atime_ts
= get_atimespec(&sbuf
);
4202 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,&sbuf
);
4205 /* Do we have this path open ? */
4207 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4208 fsp1
= file_find_di_first(fileid
);
4209 if (fsp1
&& fsp1
->initial_allocation_size
) {
4210 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, &sbuf
);
4214 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4215 mtime_ts
= write_time_ts
;
4218 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4219 dos_filetime_timespec(&create_time_ts
);
4220 dos_filetime_timespec(&mtime_ts
);
4221 dos_filetime_timespec(&atime_ts
);
4224 create_time
= convert_timespec_to_time_t(create_time_ts
);
4225 mtime
= convert_timespec_to_time_t(mtime_ts
);
4226 atime
= convert_timespec_to_time_t(atime_ts
);
4228 /* NT expects the name to be in an exact form of the *full*
4229 filename. See the trans2 torture test */
4230 if (ISDOT(base_name
)) {
4231 dos_fname
= talloc_strdup(ctx
, "\\");
4233 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4237 dos_fname
= talloc_asprintf(ctx
,
4241 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4244 string_replace(dos_fname
, '/', '\\');
4247 switch (info_level
) {
4248 case SMB_INFO_STANDARD
:
4249 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4251 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4252 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4253 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4254 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4255 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4256 SSVAL(pdata
,l1_attrFile
,mode
);
4259 case SMB_INFO_QUERY_EA_SIZE
:
4261 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4262 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4264 srv_put_dos_date2(pdata
,0,create_time
);
4265 srv_put_dos_date2(pdata
,4,atime
);
4266 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4267 SIVAL(pdata
,12,(uint32
)file_size
);
4268 SIVAL(pdata
,16,(uint32
)allocation_size
);
4269 SSVAL(pdata
,20,mode
);
4270 SIVAL(pdata
,22,ea_size
);
4274 case SMB_INFO_IS_NAME_VALID
:
4275 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4276 if (tran_call
== TRANSACT2_QFILEINFO
) {
4277 /* os/2 needs this ? really ?*/
4278 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4285 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4287 size_t total_ea_len
= 0;
4288 struct ea_list
*ea_file_list
= NULL
;
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4292 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4293 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4295 if (!ea_list
|| (total_ea_len
> data_size
)) {
4297 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4301 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4305 case SMB_INFO_QUERY_ALL_EAS
:
4307 /* We have data_size bytes to put EA's into. */
4308 size_t total_ea_len
= 0;
4310 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4312 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4313 if (!ea_list
|| (total_ea_len
> data_size
)) {
4315 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4319 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4323 case SMB_FILE_BASIC_INFORMATION
:
4324 case SMB_QUERY_FILE_BASIC_INFO
:
4326 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4327 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4328 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4330 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4334 put_long_date_timespec(pdata
,create_time_ts
);
4335 put_long_date_timespec(pdata
+8,atime_ts
);
4336 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4337 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4338 SIVAL(pdata
,32,mode
);
4340 DEBUG(5,("SMB_QFBI - "));
4341 DEBUG(5,("create: %s ", ctime(&create_time
)));
4342 DEBUG(5,("access: %s ", ctime(&atime
)));
4343 DEBUG(5,("write: %s ", ctime(&mtime
)));
4344 DEBUG(5,("change: %s ", ctime(&mtime
)));
4345 DEBUG(5,("mode: %x\n", mode
));
4348 case SMB_FILE_STANDARD_INFORMATION
:
4349 case SMB_QUERY_FILE_STANDARD_INFO
:
4351 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4353 SOFF_T(pdata
,0,allocation_size
);
4354 SOFF_T(pdata
,8,file_size
);
4355 SIVAL(pdata
,16,nlink
);
4356 SCVAL(pdata
,20,delete_pending
?1:0);
4357 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4358 SSVAL(pdata
,22,0); /* Padding. */
4361 case SMB_FILE_EA_INFORMATION
:
4362 case SMB_QUERY_FILE_EA_INFO
:
4364 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4365 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4367 SIVAL(pdata
,0,ea_size
);
4371 /* Get the 8.3 name - used if NT SMB was negotiated. */
4372 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4373 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4375 char mangled_name
[13];
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4377 if (!name_to_8_3(base_name
,mangled_name
,
4378 True
,conn
->params
)) {
4381 NT_STATUS_NO_MEMORY
);
4383 len
= srvstr_push(dstart
, req
->flags2
,
4384 pdata
+4, mangled_name
,
4385 PTR_DIFF(dend
, pdata
+4),
4387 data_size
= 4 + len
;
4392 case SMB_QUERY_FILE_NAME_INFO
:
4394 this must be *exactly* right for ACLs on mapped drives to work
4396 len
= srvstr_push(dstart
, req
->flags2
,
4398 PTR_DIFF(dend
, pdata
+4),
4400 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4401 data_size
= 4 + len
;
4405 case SMB_FILE_ALLOCATION_INFORMATION
:
4406 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4407 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4409 SOFF_T(pdata
,0,allocation_size
);
4412 case SMB_FILE_END_OF_FILE_INFORMATION
:
4413 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4414 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4416 SOFF_T(pdata
,0,file_size
);
4419 case SMB_QUERY_FILE_ALL_INFO
:
4420 case SMB_FILE_ALL_INFORMATION
:
4422 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4423 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4424 put_long_date_timespec(pdata
,create_time_ts
);
4425 put_long_date_timespec(pdata
+8,atime_ts
);
4426 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4427 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4428 SIVAL(pdata
,32,mode
);
4429 SIVAL(pdata
,36,0); /* padding. */
4431 SOFF_T(pdata
,0,allocation_size
);
4432 SOFF_T(pdata
,8,file_size
);
4433 SIVAL(pdata
,16,nlink
);
4434 SCVAL(pdata
,20,delete_pending
);
4435 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4438 SIVAL(pdata
,0,ea_size
);
4439 pdata
+= 4; /* EA info */
4440 len
= srvstr_push(dstart
, req
->flags2
,
4442 PTR_DIFF(dend
, pdata
+4),
4446 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4449 case SMB_FILE_INTERNAL_INFORMATION
:
4450 /* This should be an index number - looks like
4453 I think this causes us to fail the IFSKIT
4454 BasicFileInformationTest. -tpot */
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4457 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4458 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4462 case SMB_FILE_ACCESS_INFORMATION
:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4465 SIVAL(pdata
,0,fsp
->access_mask
);
4467 /* GENERIC_EXECUTE mapping from Windows */
4468 SIVAL(pdata
,0,0x12019F);
4473 case SMB_FILE_NAME_INFORMATION
:
4474 /* Pathname with leading '\'. */
4477 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4479 SIVAL(pdata
,0,byte_len
);
4480 data_size
= 4 + byte_len
;
4484 case SMB_FILE_DISPOSITION_INFORMATION
:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4487 SCVAL(pdata
,0,delete_pending
);
4490 case SMB_FILE_POSITION_INFORMATION
:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4493 SOFF_T(pdata
,0,pos
);
4496 case SMB_FILE_MODE_INFORMATION
:
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4498 SIVAL(pdata
,0,mode
);
4502 case SMB_FILE_ALIGNMENT_INFORMATION
:
4503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4504 SIVAL(pdata
,0,0); /* No alignment needed. */
4509 * NT4 server just returns "invalid query" to this - if we try
4510 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4513 /* The first statement above is false - verified using Thursby
4514 * client against NT4 -- gcolley.
4516 case SMB_QUERY_FILE_STREAM_INFO
:
4517 case SMB_FILE_STREAM_INFORMATION
: {
4518 unsigned int num_streams
;
4519 struct stream_struct
*streams
;
4522 DEBUG(10,("call_trans2qfilepathinfo: "
4523 "SMB_FILE_STREAM_INFORMATION\n"));
4525 status
= SMB_VFS_STREAMINFO(
4526 conn
, fsp
, fname
, talloc_tos(),
4527 &num_streams
, &streams
);
4529 if (!NT_STATUS_IS_OK(status
)) {
4530 DEBUG(10, ("could not get stream info: %s\n",
4531 nt_errstr(status
)));
4532 reply_nterror(req
, status
);
4536 status
= marshall_stream_info(num_streams
, streams
,
4537 pdata
, max_data_bytes
,
4540 if (!NT_STATUS_IS_OK(status
)) {
4541 DEBUG(10, ("marshall_stream_info failed: %s\n",
4542 nt_errstr(status
)));
4543 reply_nterror(req
, status
);
4547 TALLOC_FREE(streams
);
4551 case SMB_QUERY_COMPRESSION_INFO
:
4552 case SMB_FILE_COMPRESSION_INFORMATION
:
4553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4554 SOFF_T(pdata
,0,file_size
);
4555 SIVAL(pdata
,8,0); /* ??? */
4556 SIVAL(pdata
,12,0); /* ??? */
4560 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4562 put_long_date_timespec(pdata
,create_time_ts
);
4563 put_long_date_timespec(pdata
+8,atime_ts
);
4564 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4565 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4566 SOFF_T(pdata
,32,allocation_size
);
4567 SOFF_T(pdata
,40,file_size
);
4568 SIVAL(pdata
,48,mode
);
4569 SIVAL(pdata
,52,0); /* ??? */
4573 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4574 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4575 SIVAL(pdata
,0,mode
);
4581 * CIFS UNIX Extensions.
4584 case SMB_QUERY_FILE_UNIX_BASIC
:
4586 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4587 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4591 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4593 for (i
=0; i
<100; i
++)
4594 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4600 case SMB_QUERY_FILE_UNIX_INFO2
:
4602 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4603 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4607 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4609 for (i
=0; i
<100; i
++)
4610 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4616 case SMB_QUERY_FILE_UNIX_LINK
:
4618 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4621 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4625 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4627 if(!S_ISLNK(sbuf
.st_mode
)) {
4628 reply_unixerror(req
, ERRSRV
,
4633 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4636 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4639 reply_unixerror(req
, ERRDOS
,
4644 len
= srvstr_push(dstart
, req
->flags2
,
4646 PTR_DIFF(dend
, pdata
),
4649 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4654 #if defined(HAVE_POSIX_ACLS)
4655 case SMB_QUERY_POSIX_ACL
:
4657 SMB_ACL_T file_acl
= NULL
;
4658 SMB_ACL_T def_acl
= NULL
;
4659 uint16 num_file_acls
= 0;
4660 uint16 num_def_acls
= 0;
4662 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4663 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4665 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4668 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4669 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4673 NT_STATUS_NOT_IMPLEMENTED
);
4677 if (S_ISDIR(sbuf
.st_mode
)) {
4678 if (fsp
&& fsp
->is_directory
) {
4679 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4681 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4683 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4686 num_file_acls
= count_acl_entries(conn
, file_acl
);
4687 num_def_acls
= count_acl_entries(conn
, def_acl
);
4689 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4690 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4692 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4693 SMB_POSIX_ACL_HEADER_SIZE
) ));
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4702 NT_STATUS_BUFFER_TOO_SMALL
);
4706 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4707 SSVAL(pdata
,2,num_file_acls
);
4708 SSVAL(pdata
,4,num_def_acls
);
4709 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4711 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4714 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4717 req
, NT_STATUS_INTERNAL_ERROR
);
4720 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4725 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4729 NT_STATUS_INTERNAL_ERROR
);
4734 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4737 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4739 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4745 case SMB_QUERY_POSIX_LOCK
:
4747 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4751 enum brl_type lock_type
;
4753 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4755 req
, NT_STATUS_INVALID_PARAMETER
);
4759 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4760 case POSIX_LOCK_TYPE_READ
:
4761 lock_type
= READ_LOCK
;
4763 case POSIX_LOCK_TYPE_WRITE
:
4764 lock_type
= WRITE_LOCK
;
4766 case POSIX_LOCK_TYPE_UNLOCK
:
4768 /* There's no point in asking for an unlock... */
4771 NT_STATUS_INVALID_PARAMETER
);
4775 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4776 #if defined(HAVE_LONGLONG)
4777 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4778 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4779 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4780 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4781 #else /* HAVE_LONGLONG */
4782 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4783 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4784 #endif /* HAVE_LONGLONG */
4786 status
= query_lock(fsp
,
4793 if (ERROR_WAS_LOCK_DENIED(status
)) {
4794 /* Here we need to report who has it locked... */
4795 data_size
= POSIX_LOCK_DATA_SIZE
;
4797 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4798 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4799 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4800 #if defined(HAVE_LONGLONG)
4801 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4802 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4803 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4804 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4805 #else /* HAVE_LONGLONG */
4806 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4807 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4808 #endif /* HAVE_LONGLONG */
4810 } else if (NT_STATUS_IS_OK(status
)) {
4811 /* For success we just return a copy of what we sent
4812 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4813 data_size
= POSIX_LOCK_DATA_SIZE
;
4814 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4815 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4817 reply_nterror(req
, status
);
4824 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4828 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4834 /****************************************************************************
4835 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4837 ****************************************************************************/
4839 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4840 connection_struct
*conn
,
4841 const char *oldname_in
,
4842 const char *newname_in
)
4844 struct smb_filename
*smb_fname
= NULL
;
4845 struct smb_filename
*smb_fname_new
= NULL
;
4846 char *oldname
= NULL
;
4847 char *newname
= NULL
;
4848 NTSTATUS status
= NT_STATUS_OK
;
4850 status
= unix_convert(ctx
, conn
, oldname_in
, &smb_fname
, 0);
4851 if (!NT_STATUS_IS_OK(status
)) {
4855 status
= get_full_smb_filename(ctx
, smb_fname
, &oldname
);
4856 if (!NT_STATUS_IS_OK(status
)) {
4860 status
= check_name(conn
, oldname
);
4861 if (!NT_STATUS_IS_OK(status
)) {
4865 /* source must already exist. */
4866 if (!VALID_STAT(smb_fname
->st
)) {
4867 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4871 status
= unix_convert(ctx
, conn
, newname_in
, &smb_fname_new
, 0);
4872 if (!NT_STATUS_IS_OK(status
)) {
4876 status
= get_full_smb_filename(ctx
, smb_fname_new
, &newname
);
4877 if (!NT_STATUS_IS_OK(status
)) {
4881 status
= check_name(conn
, newname
);
4882 if (!NT_STATUS_IS_OK(status
)) {
4886 /* Disallow if newname already exists. */
4887 if (VALID_STAT(smb_fname_new
->st
)) {
4888 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4892 /* No links from a directory. */
4893 if (S_ISDIR(smb_fname
->st
.st_mode
)) {
4894 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4898 /* Ensure this is within the share. */
4899 status
= check_reduced_name(conn
, oldname
);
4900 if (!NT_STATUS_IS_OK(status
)) {
4904 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4906 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4907 status
= map_nt_error_from_unix(errno
);
4908 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4909 nt_errstr(status
), newname
, oldname
));
4913 TALLOC_FREE(smb_fname
);
4915 if (smb_fname_new
) {
4916 TALLOC_FREE(smb_fname_new
);
4921 /****************************************************************************
4922 Deal with setting the time from any of the setfilepathinfo functions.
4923 ****************************************************************************/
4925 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4928 const SMB_STRUCT_STAT
*psbuf
,
4929 struct smb_file_time
*ft
,
4930 bool setting_write_time
)
4933 FILE_NOTIFY_CHANGE_LAST_ACCESS
4934 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4936 if (!VALID_STAT(*psbuf
)) {
4937 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4940 /* get some defaults (no modifications) if any info is zero or -1. */
4941 if (null_timespec(ft
->atime
)) {
4942 ft
->atime
= get_atimespec(psbuf
);
4943 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4946 if (null_timespec(ft
->mtime
)) {
4947 ft
->mtime
= get_mtimespec(psbuf
);
4948 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4951 if (!setting_write_time
) {
4952 /* ft->mtime comes from change time, not write time. */
4953 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4956 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4957 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
4958 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4959 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
4960 if (!null_timespec(ft
->create_time
)) {
4961 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4962 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
4966 * Try and set the times of this file if
4967 * they are different from the current values.
4971 struct timespec mts
= get_mtimespec(psbuf
);
4972 struct timespec ats
= get_atimespec(psbuf
);
4973 if ((timespec_compare(&ft
->atime
, &ats
) == 0) &&
4974 (timespec_compare(&ft
->mtime
, &mts
) == 0)) {
4975 return NT_STATUS_OK
;
4979 if (setting_write_time
) {
4981 * This was a setfileinfo on an open file.
4982 * NT does this a lot. We also need to
4983 * set the time here, as it can be read by
4984 * FindFirst/FindNext and with the patch for bug #2045
4985 * in smbd/fileio.c it ensures that this timestamp is
4986 * kept sticky even after a write. We save the request
4987 * away and will set it on file close and after a write. JRA.
4990 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4991 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
4994 if (fsp
->base_fsp
) {
4995 set_sticky_write_time_fsp(fsp
->base_fsp
,
4998 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5001 set_sticky_write_time_path(conn
, fname
,
5002 vfs_file_id_from_sbuf(conn
, psbuf
),
5007 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5009 if (fsp
&& fsp
->base_fsp
) {
5010 fname
= fsp
->base_fsp
->fsp_name
;
5013 if(file_ntimes(conn
, fname
, ft
)!=0) {
5014 return map_nt_error_from_unix(errno
);
5016 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
5018 return NT_STATUS_OK
;
5021 /****************************************************************************
5022 Deal with setting the dosmode from any of the setfilepathinfo functions.
5023 ****************************************************************************/
5025 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5028 SMB_STRUCT_STAT
*psbuf
,
5031 if (!VALID_STAT(*psbuf
)) {
5032 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5036 if (fsp
->base_fsp
) {
5037 fname
= fsp
->base_fsp
->fsp_name
;
5039 fname
= fsp
->fsp_name
;
5044 if (S_ISDIR(psbuf
->st_mode
)) {
5051 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5053 /* check the mode isn't different, before changing it */
5054 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
5056 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5057 fname
, (unsigned int)dosmode
));
5059 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
5060 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5061 fname
, strerror(errno
)));
5062 return map_nt_error_from_unix(errno
);
5065 return NT_STATUS_OK
;
5068 /****************************************************************************
5069 Deal with setting the size from any of the setfilepathinfo functions.
5070 ****************************************************************************/
5072 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5073 struct smb_request
*req
,
5076 SMB_STRUCT_STAT
*psbuf
,
5079 NTSTATUS status
= NT_STATUS_OK
;
5080 files_struct
*new_fsp
= NULL
;
5082 if (!VALID_STAT(*psbuf
)) {
5083 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5086 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5088 if (size
== get_file_size_stat(psbuf
)) {
5089 return NT_STATUS_OK
;
5092 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5093 fname
, (double)size
));
5095 if (fsp
&& fsp
->fh
->fd
!= -1) {
5096 /* Handle based call. */
5097 if (vfs_set_filelen(fsp
, size
) == -1) {
5098 return map_nt_error_from_unix(errno
);
5100 trigger_write_time_update_immediate(fsp
);
5101 return NT_STATUS_OK
;
5104 status
= SMB_VFS_CREATE_FILE(
5107 0, /* root_dir_fid */
5109 0, /* create_file_flags */
5110 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5111 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5113 FILE_OPEN
, /* create_disposition*/
5114 0, /* create_options */
5115 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5116 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5117 0, /* allocation_size */
5120 &new_fsp
, /* result */
5124 if (!NT_STATUS_IS_OK(status
)) {
5125 /* NB. We check for open_was_deferred in the caller. */
5129 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5130 status
= map_nt_error_from_unix(errno
);
5131 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5135 trigger_write_time_update_immediate(new_fsp
);
5136 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5137 return NT_STATUS_OK
;
5140 /****************************************************************************
5141 Deal with SMB_INFO_SET_EA.
5142 ****************************************************************************/
5144 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5150 struct ea_list
*ea_list
= NULL
;
5151 TALLOC_CTX
*ctx
= NULL
;
5152 NTSTATUS status
= NT_STATUS_OK
;
5154 if (total_data
< 10) {
5156 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5157 length. They seem to have no effect. Bug #3212. JRA */
5159 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5160 /* We're done. We only get EA info in this call. */
5161 return NT_STATUS_OK
;
5164 return NT_STATUS_INVALID_PARAMETER
;
5167 if (IVAL(pdata
,0) > total_data
) {
5168 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5169 IVAL(pdata
,0), (unsigned int)total_data
));
5170 return NT_STATUS_INVALID_PARAMETER
;
5174 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5176 return NT_STATUS_INVALID_PARAMETER
;
5178 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5183 /****************************************************************************
5184 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5185 ****************************************************************************/
5187 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5192 SMB_STRUCT_STAT
*psbuf
)
5194 NTSTATUS status
= NT_STATUS_OK
;
5195 bool delete_on_close
;
5198 if (total_data
< 1) {
5199 return NT_STATUS_INVALID_PARAMETER
;
5203 return NT_STATUS_INVALID_HANDLE
;
5206 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5207 dosmode
= dos_mode(conn
, fname
, psbuf
);
5209 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5210 "delete_on_close = %u\n",
5212 (unsigned int)dosmode
,
5213 (unsigned int)delete_on_close
));
5215 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5217 if (!NT_STATUS_IS_OK(status
)) {
5221 /* The set is across all open files on this dev/inode pair. */
5222 if (!set_delete_on_close(fsp
, delete_on_close
,
5223 &conn
->server_info
->utok
)) {
5224 return NT_STATUS_ACCESS_DENIED
;
5226 return NT_STATUS_OK
;
5229 /****************************************************************************
5230 Deal with SMB_FILE_POSITION_INFORMATION.
5231 ****************************************************************************/
5233 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5238 uint64_t position_information
;
5240 if (total_data
< 8) {
5241 return NT_STATUS_INVALID_PARAMETER
;
5245 /* Ignore on pathname based set. */
5246 return NT_STATUS_OK
;
5249 position_information
= (uint64_t)IVAL(pdata
,0);
5250 #ifdef LARGE_SMB_OFF_T
5251 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5252 #else /* LARGE_SMB_OFF_T */
5253 if (IVAL(pdata
,4) != 0) {
5254 /* more than 32 bits? */
5255 return NT_STATUS_INVALID_PARAMETER
;
5257 #endif /* LARGE_SMB_OFF_T */
5259 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5260 fsp
->fsp_name
, (double)position_information
));
5261 fsp
->fh
->position_information
= position_information
;
5262 return NT_STATUS_OK
;
5265 /****************************************************************************
5266 Deal with SMB_FILE_MODE_INFORMATION.
5267 ****************************************************************************/
5269 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5275 if (total_data
< 4) {
5276 return NT_STATUS_INVALID_PARAMETER
;
5278 mode
= IVAL(pdata
,0);
5279 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5280 return NT_STATUS_INVALID_PARAMETER
;
5282 return NT_STATUS_OK
;
5285 /****************************************************************************
5286 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5287 ****************************************************************************/
5289 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5290 struct smb_request
*req
,
5295 char *link_target
= NULL
;
5296 const char *newname
= fname
;
5297 NTSTATUS status
= NT_STATUS_OK
;
5298 TALLOC_CTX
*ctx
= talloc_tos();
5300 /* Set a symbolic link. */
5301 /* Don't allow this if follow links is false. */
5303 if (total_data
== 0) {
5304 return NT_STATUS_INVALID_PARAMETER
;
5307 if (!lp_symlinks(SNUM(conn
))) {
5308 return NT_STATUS_ACCESS_DENIED
;
5311 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5312 total_data
, STR_TERMINATE
);
5315 return NT_STATUS_INVALID_PARAMETER
;
5318 /* !widelinks forces the target path to be within the share. */
5319 /* This means we can interpret the target as a pathname. */
5320 if (!lp_widelinks(SNUM(conn
))) {
5321 char *rel_name
= NULL
;
5322 char *last_dirp
= NULL
;
5324 if (*link_target
== '/') {
5325 /* No absolute paths allowed. */
5326 return NT_STATUS_ACCESS_DENIED
;
5328 rel_name
= talloc_strdup(ctx
,newname
);
5330 return NT_STATUS_NO_MEMORY
;
5332 last_dirp
= strrchr_m(rel_name
, '/');
5334 last_dirp
[1] = '\0';
5336 rel_name
= talloc_strdup(ctx
,"./");
5338 return NT_STATUS_NO_MEMORY
;
5341 rel_name
= talloc_asprintf_append(rel_name
,
5345 return NT_STATUS_NO_MEMORY
;
5348 status
= check_name(conn
, rel_name
);
5349 if (!NT_STATUS_IS_OK(status
)) {
5354 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5355 newname
, link_target
));
5357 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5358 return map_nt_error_from_unix(errno
);
5361 return NT_STATUS_OK
;
5364 /****************************************************************************
5365 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5366 ****************************************************************************/
5368 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5369 struct smb_request
*req
,
5370 const char *pdata
, int total_data
,
5373 char *oldname
= NULL
;
5374 TALLOC_CTX
*ctx
= talloc_tos();
5375 NTSTATUS status
= NT_STATUS_OK
;
5377 /* Set a hard link. */
5378 if (total_data
== 0) {
5379 return NT_STATUS_INVALID_PARAMETER
;
5382 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5383 total_data
, STR_TERMINATE
, &status
);
5384 if (!NT_STATUS_IS_OK(status
)) {
5388 status
= resolve_dfspath(ctx
, conn
,
5389 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5392 if (!NT_STATUS_IS_OK(status
)) {
5396 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5399 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5402 /****************************************************************************
5403 Deal with SMB_FILE_RENAME_INFORMATION.
5404 ****************************************************************************/
5406 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5407 struct smb_request
*req
,
5416 char *newname
= NULL
;
5417 char *base_name
= NULL
;
5418 struct smb_filename
*smb_fname
= NULL
;
5419 bool dest_has_wcard
= False
;
5420 NTSTATUS status
= NT_STATUS_OK
;
5422 TALLOC_CTX
*ctx
= talloc_tos();
5424 if (total_data
< 13) {
5425 return NT_STATUS_INVALID_PARAMETER
;
5428 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5429 root_fid
= IVAL(pdata
,4);
5430 len
= IVAL(pdata
,8);
5432 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5433 return NT_STATUS_INVALID_PARAMETER
;
5436 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5439 if (!NT_STATUS_IS_OK(status
)) {
5443 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5446 status
= resolve_dfspath_wcard(ctx
, conn
,
5447 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5451 if (!NT_STATUS_IS_OK(status
)) {
5455 /* Check the new name has no '/' characters. */
5456 if (strchr_m(newname
, '/')) {
5457 return NT_STATUS_NOT_SUPPORTED
;
5460 if (fsp
&& fsp
->base_fsp
) {
5461 /* newname must be a stream name. */
5462 if (newname
[0] != ':') {
5463 return NT_STATUS_NOT_SUPPORTED
;
5465 base_name
= talloc_asprintf(ctx
, "%s%s",
5466 fsp
->base_fsp
->fsp_name
,
5469 return NT_STATUS_NO_MEMORY
;
5472 /* newname must *not* be a stream name. */
5473 if (is_ntfs_stream_name(newname
)) {
5474 return NT_STATUS_NOT_SUPPORTED
;
5477 /* Create the base directory. */
5478 base_name
= talloc_strdup(ctx
, fname
);
5480 return NT_STATUS_NO_MEMORY
;
5482 p
= strrchr_m(base_name
, '/');
5486 base_name
= talloc_strdup(ctx
, "./");
5488 return NT_STATUS_NO_MEMORY
;
5491 /* Append the new name. */
5492 base_name
= talloc_asprintf_append(base_name
,
5496 return NT_STATUS_NO_MEMORY
;
5499 status
= unix_convert(ctx
, conn
, newname
, &smb_fname
,
5502 /* If an error we expect this to be
5503 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5505 if (!NT_STATUS_IS_OK(status
)
5506 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5513 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5514 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5515 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5517 smb_fname
->original_lcomp
: NULL
,
5520 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5521 fname
, base_name
));
5522 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5523 overwrite
, False
, dest_has_wcard
,
5524 FILE_WRITE_ATTRIBUTES
);
5528 TALLOC_FREE(smb_fname
);
5533 /****************************************************************************
5534 Deal with SMB_SET_POSIX_ACL.
5535 ****************************************************************************/
5537 #if defined(HAVE_POSIX_ACLS)
5538 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5543 SMB_STRUCT_STAT
*psbuf
)
5545 uint16 posix_acl_version
;
5546 uint16 num_file_acls
;
5547 uint16 num_def_acls
;
5548 bool valid_file_acls
= True
;
5549 bool valid_def_acls
= True
;
5551 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5552 return NT_STATUS_INVALID_PARAMETER
;
5554 posix_acl_version
= SVAL(pdata
,0);
5555 num_file_acls
= SVAL(pdata
,2);
5556 num_def_acls
= SVAL(pdata
,4);
5558 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5559 valid_file_acls
= False
;
5563 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5564 valid_def_acls
= False
;
5568 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5569 return NT_STATUS_INVALID_PARAMETER
;
5572 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5573 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5574 return NT_STATUS_INVALID_PARAMETER
;
5577 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5578 fname
? fname
: fsp
->fsp_name
,
5579 (unsigned int)num_file_acls
,
5580 (unsigned int)num_def_acls
));
5582 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5583 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5584 return map_nt_error_from_unix(errno
);
5587 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5588 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5589 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5590 return map_nt_error_from_unix(errno
);
5592 return NT_STATUS_OK
;
5596 /****************************************************************************
5597 Deal with SMB_SET_POSIX_LOCK.
5598 ****************************************************************************/
5600 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5601 struct smb_request
*req
,
5609 bool blocking_lock
= False
;
5610 enum brl_type lock_type
;
5612 NTSTATUS status
= NT_STATUS_OK
;
5614 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5615 return NT_STATUS_INVALID_HANDLE
;
5618 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5619 return NT_STATUS_INVALID_PARAMETER
;
5622 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5623 case POSIX_LOCK_TYPE_READ
:
5624 lock_type
= READ_LOCK
;
5626 case POSIX_LOCK_TYPE_WRITE
:
5627 /* Return the right POSIX-mappable error code for files opened read-only. */
5628 if (!fsp
->can_write
) {
5629 return NT_STATUS_INVALID_HANDLE
;
5631 lock_type
= WRITE_LOCK
;
5633 case POSIX_LOCK_TYPE_UNLOCK
:
5634 lock_type
= UNLOCK_LOCK
;
5637 return NT_STATUS_INVALID_PARAMETER
;
5640 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5641 blocking_lock
= False
;
5642 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5643 blocking_lock
= True
;
5645 return NT_STATUS_INVALID_PARAMETER
;
5648 if (!lp_blocking_locks(SNUM(conn
))) {
5649 blocking_lock
= False
;
5652 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5653 #if defined(HAVE_LONGLONG)
5654 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5655 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5656 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5657 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5658 #else /* HAVE_LONGLONG */
5659 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5660 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5661 #endif /* HAVE_LONGLONG */
5663 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5664 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5666 (unsigned int)lock_type
,
5667 (unsigned int)lock_pid
,
5671 if (lock_type
== UNLOCK_LOCK
) {
5672 status
= do_unlock(smbd_messaging_context(),
5679 uint32 block_smbpid
;
5681 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5693 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5695 * A blocking lock was requested. Package up
5696 * this smb into a queued request and push it
5697 * onto the blocking lock queue.
5699 if(push_blocking_lock_request(br_lck
,
5702 -1, /* infinite timeout. */
5710 TALLOC_FREE(br_lck
);
5714 TALLOC_FREE(br_lck
);
5720 /****************************************************************************
5721 Deal with SMB_INFO_STANDARD.
5722 ****************************************************************************/
5724 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5729 const SMB_STRUCT_STAT
*psbuf
)
5731 struct smb_file_time ft
;
5734 if (total_data
< 12) {
5735 return NT_STATUS_INVALID_PARAMETER
;
5739 ft
.create_time
= interpret_long_date(pdata
);
5742 ft
.atime
= interpret_long_date(pdata
+ 8);
5745 ft
.mtime
= interpret_long_date(pdata
+ 16);
5747 DEBUG(10,("smb_set_info_standard: file %s\n",
5748 fname
? fname
: fsp
->fsp_name
));
5750 return smb_set_file_time(conn
,
5758 /****************************************************************************
5759 Deal with SMB_SET_FILE_BASIC_INFO.
5760 ****************************************************************************/
5762 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5767 SMB_STRUCT_STAT
*psbuf
)
5769 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5770 struct timespec write_time
;
5771 struct timespec changed_time
;
5772 struct smb_file_time ft
;
5774 NTSTATUS status
= NT_STATUS_OK
;
5775 bool setting_write_time
= true;
5779 if (total_data
< 36) {
5780 return NT_STATUS_INVALID_PARAMETER
;
5783 /* Set the attributes */
5784 dosmode
= IVAL(pdata
,32);
5785 status
= smb_set_file_dosmode(conn
, fsp
, fname
, psbuf
, dosmode
);
5786 if (!NT_STATUS_IS_OK(status
)) {
5791 ft
.atime
= interpret_long_date(pdata
+8);
5793 write_time
= interpret_long_date(pdata
+16);
5794 changed_time
= interpret_long_date(pdata
+24);
5797 ft
.mtime
= timespec_min(&write_time
, &changed_time
);
5800 ft
.create_time
= interpret_long_date(pdata
);
5802 if ((timespec_compare(&write_time
, &ft
.mtime
) == 1) &&
5803 !null_timespec(write_time
)) {
5804 ft
.mtime
= write_time
;
5807 /* Prefer a defined time to an undefined one. */
5808 if (null_timespec(ft
.mtime
)) {
5809 if (null_timespec(write_time
)) {
5810 ft
.mtime
= changed_time
;
5811 setting_write_time
= false;
5813 ft
.mtime
= write_time
;
5817 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5818 fname
? fname
: fsp
->fsp_name
));
5820 return smb_set_file_time(conn
,
5825 setting_write_time
);
5828 /****************************************************************************
5829 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5830 ****************************************************************************/
5832 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5833 struct smb_request
*req
,
5838 SMB_STRUCT_STAT
*psbuf
)
5840 uint64_t allocation_size
= 0;
5841 NTSTATUS status
= NT_STATUS_OK
;
5842 files_struct
*new_fsp
= NULL
;
5844 if (!VALID_STAT(*psbuf
)) {
5845 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5848 if (total_data
< 8) {
5849 return NT_STATUS_INVALID_PARAMETER
;
5852 allocation_size
= (uint64_t)IVAL(pdata
,0);
5853 #ifdef LARGE_SMB_OFF_T
5854 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5855 #else /* LARGE_SMB_OFF_T */
5856 if (IVAL(pdata
,4) != 0) {
5857 /* more than 32 bits? */
5858 return NT_STATUS_INVALID_PARAMETER
;
5860 #endif /* LARGE_SMB_OFF_T */
5862 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5863 fname
, (double)allocation_size
));
5865 if (allocation_size
) {
5866 allocation_size
= smb_roundup(conn
, allocation_size
);
5869 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5870 fname
, (double)allocation_size
));
5872 if (fsp
&& fsp
->fh
->fd
!= -1) {
5873 /* Open file handle. */
5874 /* Only change if needed. */
5875 if (allocation_size
!= get_file_size_stat(psbuf
)) {
5876 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5877 return map_nt_error_from_unix(errno
);
5880 /* But always update the time. */
5882 * This is equivalent to a write. Ensure it's seen immediately
5883 * if there are no pending writes.
5885 trigger_write_time_update_immediate(fsp
);
5886 return NT_STATUS_OK
;
5889 /* Pathname or stat or directory file. */
5891 status
= SMB_VFS_CREATE_FILE(
5894 0, /* root_dir_fid */
5896 0, /* create_file_flags */
5897 FILE_WRITE_DATA
, /* access_mask */
5898 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5900 FILE_OPEN
, /* create_disposition*/
5901 0, /* create_options */
5902 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5903 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5904 0, /* allocation_size */
5907 &new_fsp
, /* result */
5911 if (!NT_STATUS_IS_OK(status
)) {
5912 /* NB. We check for open_was_deferred in the caller. */
5916 /* Only change if needed. */
5917 if (allocation_size
!= get_file_size_stat(psbuf
)) {
5918 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5919 status
= map_nt_error_from_unix(errno
);
5920 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5925 /* Changing the allocation size should set the last mod time. */
5927 * This is equivalent to a write. Ensure it's seen immediately
5928 * if there are no pending writes.
5930 trigger_write_time_update_immediate(new_fsp
);
5932 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5933 return NT_STATUS_OK
;
5936 /****************************************************************************
5937 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5938 ****************************************************************************/
5940 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5941 struct smb_request
*req
,
5946 SMB_STRUCT_STAT
*psbuf
)
5950 if (total_data
< 8) {
5951 return NT_STATUS_INVALID_PARAMETER
;
5954 size
= IVAL(pdata
,0);
5955 #ifdef LARGE_SMB_OFF_T
5956 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5957 #else /* LARGE_SMB_OFF_T */
5958 if (IVAL(pdata
,4) != 0) {
5959 /* more than 32 bits? */
5960 return NT_STATUS_INVALID_PARAMETER
;
5962 #endif /* LARGE_SMB_OFF_T */
5963 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5964 "file %s to %.0f\n", fname
, (double)size
));
5966 return smb_set_file_size(conn
, req
,
5973 /****************************************************************************
5974 Allow a UNIX info mknod.
5975 ****************************************************************************/
5977 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5981 SMB_STRUCT_STAT
*psbuf
)
5983 uint32 file_type
= IVAL(pdata
,56);
5984 #if defined(HAVE_MAKEDEV)
5985 uint32 dev_major
= IVAL(pdata
,60);
5986 uint32 dev_minor
= IVAL(pdata
,68);
5988 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5989 uint32 raw_unixmode
= IVAL(pdata
,84);
5993 if (total_data
< 100) {
5994 return NT_STATUS_INVALID_PARAMETER
;
5997 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5998 if (!NT_STATUS_IS_OK(status
)) {
6002 #if defined(HAVE_MAKEDEV)
6003 dev
= makedev(dev_major
, dev_minor
);
6006 switch (file_type
) {
6007 #if defined(S_IFIFO)
6008 case UNIX_TYPE_FIFO
:
6009 unixmode
|= S_IFIFO
;
6012 #if defined(S_IFSOCK)
6013 case UNIX_TYPE_SOCKET
:
6014 unixmode
|= S_IFSOCK
;
6017 #if defined(S_IFCHR)
6018 case UNIX_TYPE_CHARDEV
:
6019 unixmode
|= S_IFCHR
;
6022 #if defined(S_IFBLK)
6023 case UNIX_TYPE_BLKDEV
:
6024 unixmode
|= S_IFBLK
;
6028 return NT_STATUS_INVALID_PARAMETER
;
6031 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6032 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
6034 /* Ok - do the mknod. */
6035 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
6036 return map_nt_error_from_unix(errno
);
6039 /* If any of the other "set" calls fail we
6040 * don't want to end up with a half-constructed mknod.
6043 if (lp_inherit_perms(SNUM(conn
))) {
6045 if (!parent_dirname(talloc_tos(), fname
, &parent
, NULL
)) {
6046 return NT_STATUS_NO_MEMORY
;
6048 inherit_access_posix_acl(conn
, parent
, fname
, unixmode
);
6049 TALLOC_FREE(parent
);
6052 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
6053 status
= map_nt_error_from_unix(errno
);
6054 SMB_VFS_UNLINK(conn
,fname
);
6057 return NT_STATUS_OK
;
6060 /****************************************************************************
6061 Deal with SMB_SET_FILE_UNIX_BASIC.
6062 ****************************************************************************/
6064 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6065 struct smb_request
*req
,
6070 SMB_STRUCT_STAT
*psbuf
)
6072 struct smb_file_time ft
;
6073 uint32 raw_unixmode
;
6076 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6077 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6078 NTSTATUS status
= NT_STATUS_OK
;
6079 bool delete_on_fail
= False
;
6080 enum perm_type ptype
;
6084 if (total_data
< 100) {
6085 return NT_STATUS_INVALID_PARAMETER
;
6088 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6089 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6090 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6091 #ifdef LARGE_SMB_OFF_T
6092 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6093 #else /* LARGE_SMB_OFF_T */
6094 if (IVAL(pdata
,4) != 0) {
6095 /* more than 32 bits? */
6096 return NT_STATUS_INVALID_PARAMETER
;
6098 #endif /* LARGE_SMB_OFF_T */
6101 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6102 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6103 set_owner
= (uid_t
)IVAL(pdata
,40);
6104 set_grp
= (gid_t
)IVAL(pdata
,48);
6105 raw_unixmode
= IVAL(pdata
,84);
6107 if (VALID_STAT(*psbuf
)) {
6108 if (S_ISDIR(psbuf
->st_mode
)) {
6109 ptype
= PERM_EXISTING_DIR
;
6111 ptype
= PERM_EXISTING_FILE
;
6114 ptype
= PERM_NEW_FILE
;
6117 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
6118 if (!NT_STATUS_IS_OK(status
)) {
6122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6123 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6124 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
6126 if (!VALID_STAT(*psbuf
)) {
6128 * The only valid use of this is to create character and block
6129 * devices, and named pipes. This is deprecated (IMHO) and
6130 * a new info level should be used for mknod. JRA.
6133 status
= smb_unix_mknod(conn
,
6138 if (!NT_STATUS_IS_OK(status
)) {
6142 /* Ensure we don't try and change anything else. */
6143 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6144 size
= get_file_size_stat(psbuf
);
6145 ft
.atime
= get_atimespec(psbuf
);
6146 ft
.mtime
= get_mtimespec(psbuf
);
6148 * We continue here as we might want to change the
6151 delete_on_fail
= True
;
6155 /* Horrible backwards compatibility hack as an old server bug
6156 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6160 size
= get_file_size_stat(psbuf
);
6165 * Deal with the UNIX specific mode set.
6168 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6169 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6170 (unsigned int)unixmode
, fname
));
6171 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6172 return map_nt_error_from_unix(errno
);
6177 * Deal with the UNIX specific uid set.
6180 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6183 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6184 (unsigned int)set_owner
, fname
));
6186 if (S_ISLNK(psbuf
->st_mode
)) {
6187 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6189 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6193 status
= map_nt_error_from_unix(errno
);
6194 if (delete_on_fail
) {
6195 SMB_VFS_UNLINK(conn
,fname
);
6202 * Deal with the UNIX specific gid set.
6205 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6206 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6207 (unsigned int)set_owner
, fname
));
6208 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6209 status
= map_nt_error_from_unix(errno
);
6210 if (delete_on_fail
) {
6211 SMB_VFS_UNLINK(conn
,fname
);
6217 /* Deal with any size changes. */
6219 status
= smb_set_file_size(conn
, req
,
6224 if (!NT_STATUS_IS_OK(status
)) {
6228 /* Deal with any time changes. */
6230 return smb_set_file_time(conn
,
6238 /****************************************************************************
6239 Deal with SMB_SET_FILE_UNIX_INFO2.
6240 ****************************************************************************/
6242 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6243 struct smb_request
*req
,
6248 SMB_STRUCT_STAT
*psbuf
)
6254 if (total_data
< 116) {
6255 return NT_STATUS_INVALID_PARAMETER
;
6258 /* Start by setting all the fields that are common between UNIX_BASIC
6261 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6263 if (!NT_STATUS_IS_OK(status
)) {
6267 smb_fflags
= IVAL(pdata
, 108);
6268 smb_fmask
= IVAL(pdata
, 112);
6270 /* NB: We should only attempt to alter the file flags if the client
6271 * sends a non-zero mask.
6273 if (smb_fmask
!= 0) {
6274 int stat_fflags
= 0;
6276 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6278 /* Client asked to alter a flag we don't understand. */
6279 return NT_STATUS_INVALID_PARAMETER
;
6282 if (fsp
&& fsp
->fh
->fd
!= -1) {
6283 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6284 return NT_STATUS_NOT_SUPPORTED
;
6286 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6287 return map_nt_error_from_unix(errno
);
6292 /* XXX: need to add support for changing the create_time here. You
6293 * can do this for paths on Darwin with setattrlist(2). The right way
6294 * to hook this up is probably by extending the VFS utimes interface.
6297 return NT_STATUS_OK
;
6300 /****************************************************************************
6301 Create a directory with POSIX semantics.
6302 ****************************************************************************/
6304 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6305 struct smb_request
*req
,
6309 SMB_STRUCT_STAT
*psbuf
,
6310 int *pdata_return_size
)
6312 NTSTATUS status
= NT_STATUS_OK
;
6313 uint32 raw_unixmode
= 0;
6314 uint32 mod_unixmode
= 0;
6315 mode_t unixmode
= (mode_t
)0;
6316 files_struct
*fsp
= NULL
;
6317 uint16 info_level_return
= 0;
6319 char *pdata
= *ppdata
;
6321 if (total_data
< 18) {
6322 return NT_STATUS_INVALID_PARAMETER
;
6325 raw_unixmode
= IVAL(pdata
,8);
6326 /* Next 4 bytes are not yet defined. */
6328 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6329 if (!NT_STATUS_IS_OK(status
)) {
6333 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6335 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6336 fname
, (unsigned int)unixmode
));
6338 status
= SMB_VFS_CREATE_FILE(
6341 0, /* root_dir_fid */
6343 0, /* create_file_flags */
6344 FILE_READ_ATTRIBUTES
, /* access_mask */
6345 FILE_SHARE_NONE
, /* share_access */
6346 FILE_CREATE
, /* create_disposition*/
6347 FILE_DIRECTORY_FILE
, /* create_options */
6348 mod_unixmode
, /* file_attributes */
6349 0, /* oplock_request */
6350 0, /* allocation_size */
6357 if (NT_STATUS_IS_OK(status
)) {
6358 close_file(req
, fsp
, NORMAL_CLOSE
);
6361 info_level_return
= SVAL(pdata
,16);
6363 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6364 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6365 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6366 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6368 *pdata_return_size
= 12;
6371 /* Realloc the data size */
6372 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6373 if (*ppdata
== NULL
) {
6374 *pdata_return_size
= 0;
6375 return NT_STATUS_NO_MEMORY
;
6379 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6380 SSVAL(pdata
,2,0); /* No fnum. */
6381 SIVAL(pdata
,4,info
); /* Was directory created. */
6383 switch (info_level_return
) {
6384 case SMB_QUERY_FILE_UNIX_BASIC
:
6385 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6386 SSVAL(pdata
,10,0); /* Padding. */
6387 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6389 case SMB_QUERY_FILE_UNIX_INFO2
:
6390 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6391 SSVAL(pdata
,10,0); /* Padding. */
6392 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6395 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6396 SSVAL(pdata
,10,0); /* Padding. */
6403 /****************************************************************************
6404 Open/Create a file with POSIX semantics.
6405 ****************************************************************************/
6407 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6408 struct smb_request
*req
,
6412 SMB_STRUCT_STAT
*psbuf
,
6413 int *pdata_return_size
)
6415 bool extended_oplock_granted
= False
;
6416 char *pdata
= *ppdata
;
6418 uint32 wire_open_mode
= 0;
6419 uint32 raw_unixmode
= 0;
6420 uint32 mod_unixmode
= 0;
6421 uint32 create_disp
= 0;
6422 uint32 access_mask
= 0;
6423 uint32 create_options
= 0;
6424 NTSTATUS status
= NT_STATUS_OK
;
6425 mode_t unixmode
= (mode_t
)0;
6426 files_struct
*fsp
= NULL
;
6427 int oplock_request
= 0;
6429 uint16 info_level_return
= 0;
6431 if (total_data
< 18) {
6432 return NT_STATUS_INVALID_PARAMETER
;
6435 flags
= IVAL(pdata
,0);
6436 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6437 if (oplock_request
) {
6438 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6441 wire_open_mode
= IVAL(pdata
,4);
6443 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6444 return smb_posix_mkdir(conn
, req
,
6452 switch (wire_open_mode
& SMB_ACCMODE
) {
6454 access_mask
= FILE_READ_DATA
;
6457 access_mask
= FILE_WRITE_DATA
;
6460 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6463 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6464 (unsigned int)wire_open_mode
));
6465 return NT_STATUS_INVALID_PARAMETER
;
6468 wire_open_mode
&= ~SMB_ACCMODE
;
6470 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6471 create_disp
= FILE_CREATE
;
6472 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6473 create_disp
= FILE_OVERWRITE_IF
;
6474 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6475 create_disp
= FILE_OPEN_IF
;
6476 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
6477 create_disp
= FILE_OPEN
;
6479 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6480 (unsigned int)wire_open_mode
));
6481 return NT_STATUS_INVALID_PARAMETER
;
6484 raw_unixmode
= IVAL(pdata
,8);
6485 /* Next 4 bytes are not yet defined. */
6487 status
= unix_perms_from_wire(conn
,
6490 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6493 if (!NT_STATUS_IS_OK(status
)) {
6497 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6499 if (wire_open_mode
& SMB_O_SYNC
) {
6500 create_options
|= FILE_WRITE_THROUGH
;
6502 if (wire_open_mode
& SMB_O_APPEND
) {
6503 access_mask
|= FILE_APPEND_DATA
;
6505 if (wire_open_mode
& SMB_O_DIRECT
) {
6506 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6509 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6511 (unsigned int)wire_open_mode
,
6512 (unsigned int)unixmode
));
6514 status
= SMB_VFS_CREATE_FILE(
6517 0, /* root_dir_fid */
6519 0, /* create_file_flags */
6520 access_mask
, /* access_mask */
6521 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6523 create_disp
, /* create_disposition*/
6524 FILE_NON_DIRECTORY_FILE
, /* create_options */
6525 mod_unixmode
, /* file_attributes */
6526 oplock_request
, /* oplock_request */
6527 0, /* allocation_size */
6534 if (!NT_STATUS_IS_OK(status
)) {
6538 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6539 extended_oplock_granted
= True
;
6542 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6543 extended_oplock_granted
= True
;
6546 info_level_return
= SVAL(pdata
,16);
6548 /* Allocate the correct return size. */
6550 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6551 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6552 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6553 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6555 *pdata_return_size
= 12;
6558 /* Realloc the data size */
6559 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6560 if (*ppdata
== NULL
) {
6561 close_file(req
, fsp
, ERROR_CLOSE
);
6562 *pdata_return_size
= 0;
6563 return NT_STATUS_NO_MEMORY
;
6567 if (extended_oplock_granted
) {
6568 if (flags
& REQUEST_BATCH_OPLOCK
) {
6569 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6571 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6573 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6574 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6576 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6579 SSVAL(pdata
,2,fsp
->fnum
);
6580 SIVAL(pdata
,4,info
); /* Was file created etc. */
6582 switch (info_level_return
) {
6583 case SMB_QUERY_FILE_UNIX_BASIC
:
6584 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6585 SSVAL(pdata
,10,0); /* padding. */
6586 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6588 case SMB_QUERY_FILE_UNIX_INFO2
:
6589 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6590 SSVAL(pdata
,10,0); /* padding. */
6591 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6594 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6595 SSVAL(pdata
,10,0); /* padding. */
6598 return NT_STATUS_OK
;
6601 /****************************************************************************
6602 Delete a file with POSIX semantics.
6603 ****************************************************************************/
6605 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6606 struct smb_request
*req
,
6610 SMB_STRUCT_STAT
*psbuf
)
6612 NTSTATUS status
= NT_STATUS_OK
;
6613 files_struct
*fsp
= NULL
;
6617 int create_options
= 0;
6619 struct share_mode_lock
*lck
= NULL
;
6621 if (total_data
< 2) {
6622 return NT_STATUS_INVALID_PARAMETER
;
6625 flags
= SVAL(pdata
,0);
6627 if (!VALID_STAT(*psbuf
)) {
6628 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6631 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6632 !VALID_STAT_OF_DIR(*psbuf
)) {
6633 return NT_STATUS_NOT_A_DIRECTORY
;
6636 DEBUG(10,("smb_posix_unlink: %s %s\n",
6637 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6640 if (VALID_STAT_OF_DIR(*psbuf
)) {
6641 create_options
|= FILE_DIRECTORY_FILE
;
6644 status
= SMB_VFS_CREATE_FILE(
6647 0, /* root_dir_fid */
6649 0, /* create_file_flags */
6650 DELETE_ACCESS
, /* access_mask */
6651 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6653 FILE_OPEN
, /* create_disposition*/
6654 create_options
, /* create_options */
6655 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
6656 0, /* oplock_request */
6657 0, /* allocation_size */
6664 if (!NT_STATUS_IS_OK(status
)) {
6669 * Don't lie to client. If we can't really delete due to
6670 * non-POSIX opens return SHARING_VIOLATION.
6673 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6676 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6677 "lock for file %s\n", fsp
->fsp_name
));
6678 close_file(req
, fsp
, NORMAL_CLOSE
);
6679 return NT_STATUS_INVALID_PARAMETER
;
6683 * See if others still have the file open. If this is the case, then
6684 * don't delete. If all opens are POSIX delete we can set the delete
6685 * on close disposition.
6687 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6688 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6689 if (is_valid_share_mode_entry(e
)) {
6690 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6693 /* Fail with sharing violation. */
6694 close_file(req
, fsp
, NORMAL_CLOSE
);
6696 return NT_STATUS_SHARING_VIOLATION
;
6701 * Set the delete on close.
6703 status
= smb_set_file_disposition_info(conn
,
6710 if (!NT_STATUS_IS_OK(status
)) {
6711 close_file(req
, fsp
, NORMAL_CLOSE
);
6716 return close_file(req
, fsp
, NORMAL_CLOSE
);
6719 /****************************************************************************
6720 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6721 ****************************************************************************/
6723 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6724 struct smb_request
*req
,
6725 unsigned int tran_call
,
6726 char **pparams
, int total_params
,
6727 char **ppdata
, int total_data
,
6728 unsigned int max_data_bytes
)
6730 char *params
= *pparams
;
6731 char *pdata
= *ppdata
;
6733 SMB_STRUCT_STAT sbuf
;
6735 struct smb_filename
*smb_fname
= NULL
;
6736 files_struct
*fsp
= NULL
;
6737 NTSTATUS status
= NT_STATUS_OK
;
6738 int data_return_size
= 0;
6739 TALLOC_CTX
*ctx
= talloc_tos();
6742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6748 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6749 if (total_params
< 4) {
6750 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6754 fsp
= file_fsp(req
, SVAL(params
,0));
6755 /* Basic check for non-null fsp. */
6756 if (!check_fsp_open(conn
, req
, fsp
)) {
6759 info_level
= SVAL(params
,2);
6761 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6763 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6767 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6769 * This is actually a SETFILEINFO on a directory
6770 * handle (returned from an NT SMB). NT5.0 seems
6771 * to do this call. JRA.
6773 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6774 /* Always do lstat for UNIX calls. */
6775 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6776 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6777 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6781 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6782 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6783 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6787 } else if (fsp
->print_file
) {
6789 * Doing a DELETE_ON_CLOSE should cancel a print job.
6791 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6792 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6794 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6797 send_trans2_replies(conn
, req
, params
, 2,
6802 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6807 * Original code - this is an open file.
6809 if (!check_fsp(conn
, req
, fsp
)) {
6813 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6814 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6815 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6821 if (total_params
< 7) {
6822 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6826 info_level
= SVAL(params
,0);
6827 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6828 total_params
- 6, STR_TERMINATE
,
6830 if (!NT_STATUS_IS_OK(status
)) {
6831 reply_nterror(req
, status
);
6835 status
= resolve_dfspath(ctx
, conn
,
6836 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6839 if (!NT_STATUS_IS_OK(status
)) {
6840 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6841 reply_botherror(req
,
6842 NT_STATUS_PATH_NOT_COVERED
,
6843 ERRSRV
, ERRbadpath
);
6846 reply_nterror(req
, status
);
6850 status
= unix_convert(ctx
, conn
, fname
, &smb_fname
, 0);
6851 if (!NT_STATUS_IS_OK(status
)) {
6852 reply_nterror(req
, status
);
6855 sbuf
= smb_fname
->st
;
6857 status
= get_full_smb_filename(ctx
, smb_fname
, &fname
);
6858 TALLOC_FREE(smb_fname
);
6859 if (!NT_STATUS_IS_OK(status
)) {
6860 reply_nterror(req
, status
);
6864 status
= check_name(conn
, fname
);
6865 if (!NT_STATUS_IS_OK(status
)) {
6866 reply_nterror(req
, status
);
6870 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6872 * For CIFS UNIX extensions the target name may not exist.
6875 /* Always do lstat for UNIX calls. */
6876 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6878 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6879 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6880 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6885 if (!CAN_WRITE(conn
)) {
6886 reply_doserror(req
, ERRSRV
, ERRaccess
);
6890 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6891 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6895 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6896 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6898 /* Realloc the parameter size */
6899 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6900 if (*pparams
== NULL
) {
6901 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6908 switch (info_level
) {
6910 case SMB_INFO_STANDARD
:
6912 status
= smb_set_info_standard(conn
,
6921 case SMB_INFO_SET_EA
:
6923 status
= smb_info_set_ea(conn
,
6931 case SMB_SET_FILE_BASIC_INFO
:
6932 case SMB_FILE_BASIC_INFORMATION
:
6934 status
= smb_set_file_basic_info(conn
,
6943 case SMB_FILE_ALLOCATION_INFORMATION
:
6944 case SMB_SET_FILE_ALLOCATION_INFO
:
6946 status
= smb_set_file_allocation_info(conn
, req
,
6955 case SMB_FILE_END_OF_FILE_INFORMATION
:
6956 case SMB_SET_FILE_END_OF_FILE_INFO
:
6958 status
= smb_set_file_end_of_file_info(conn
, req
,
6967 case SMB_FILE_DISPOSITION_INFORMATION
:
6968 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6971 /* JRA - We used to just ignore this on a path ?
6972 * Shouldn't this be invalid level on a pathname
6975 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6976 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6979 status
= smb_set_file_disposition_info(conn
,
6988 case SMB_FILE_POSITION_INFORMATION
:
6990 status
= smb_file_position_information(conn
,
6997 /* From tridge Samba4 :
6998 * MODE_INFORMATION in setfileinfo (I have no
6999 * idea what "mode information" on a file is - it takes a value of 0,
7000 * 2, 4 or 6. What could it be?).
7003 case SMB_FILE_MODE_INFORMATION
:
7005 status
= smb_file_mode_information(conn
,
7012 * CIFS UNIX extensions.
7015 case SMB_SET_FILE_UNIX_BASIC
:
7017 status
= smb_set_file_unix_basic(conn
, req
,
7026 case SMB_SET_FILE_UNIX_INFO2
:
7028 status
= smb_set_file_unix_info2(conn
, req
,
7037 case SMB_SET_FILE_UNIX_LINK
:
7039 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7040 /* We must have a pathname for this. */
7041 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7044 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7049 case SMB_SET_FILE_UNIX_HLINK
:
7051 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7052 /* We must have a pathname for this. */
7053 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7056 status
= smb_set_file_unix_hlink(conn
, req
,
7062 case SMB_FILE_RENAME_INFORMATION
:
7064 status
= smb_file_rename_information(conn
, req
,
7070 #if defined(HAVE_POSIX_ACLS)
7071 case SMB_SET_POSIX_ACL
:
7073 status
= smb_set_posix_acl(conn
,
7083 case SMB_SET_POSIX_LOCK
:
7085 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7086 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7089 status
= smb_set_posix_lock(conn
, req
,
7090 pdata
, total_data
, fsp
);
7094 case SMB_POSIX_PATH_OPEN
:
7096 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7097 /* We must have a pathname for this. */
7098 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7102 status
= smb_posix_open(conn
, req
,
7111 case SMB_POSIX_PATH_UNLINK
:
7113 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7114 /* We must have a pathname for this. */
7115 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7119 status
= smb_posix_unlink(conn
, req
,
7128 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7133 if (!NT_STATUS_IS_OK(status
)) {
7134 if (open_was_deferred(req
->mid
)) {
7135 /* We have re-scheduled this call. */
7138 if (blocking_lock_was_deferred(req
->mid
)) {
7139 /* We have re-scheduled this call. */
7142 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7143 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7144 ERRSRV
, ERRbadpath
);
7147 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7148 reply_openerror(req
, status
);
7152 reply_nterror(req
, status
);
7157 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7163 /****************************************************************************
7164 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7165 ****************************************************************************/
7167 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7168 char **pparams
, int total_params
,
7169 char **ppdata
, int total_data
,
7170 unsigned int max_data_bytes
)
7172 struct smb_filename
*smb_dname
= NULL
;
7173 char *params
= *pparams
;
7174 char *pdata
= *ppdata
;
7175 char *directory
= NULL
;
7176 NTSTATUS status
= NT_STATUS_OK
;
7177 struct ea_list
*ea_list
= NULL
;
7178 TALLOC_CTX
*ctx
= talloc_tos();
7180 if (!CAN_WRITE(conn
)) {
7181 reply_doserror(req
, ERRSRV
, ERRaccess
);
7185 if (total_params
< 5) {
7186 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7190 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7191 total_params
- 4, STR_TERMINATE
,
7193 if (!NT_STATUS_IS_OK(status
)) {
7194 reply_nterror(req
, status
);
7198 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7200 status
= unix_convert(ctx
, conn
, directory
, &smb_dname
, 0);
7201 if (!NT_STATUS_IS_OK(status
)) {
7202 reply_nterror(req
, status
);
7206 status
= get_full_smb_filename(ctx
, smb_dname
, &directory
);
7207 if (!NT_STATUS_IS_OK(status
)) {
7208 reply_nterror(req
, status
);
7212 status
= check_name(conn
, directory
);
7213 if (!NT_STATUS_IS_OK(status
)) {
7214 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7215 reply_nterror(req
, status
);
7219 /* Any data in this call is an EA list. */
7220 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7221 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7226 * OS/2 workplace shell seems to send SET_EA requests of "null"
7227 * length (4 bytes containing IVAL 4).
7228 * They seem to have no effect. Bug #3212. JRA.
7231 if (total_data
!= 4) {
7232 if (total_data
< 10) {
7233 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7237 if (IVAL(pdata
,0) > total_data
) {
7238 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7239 IVAL(pdata
,0), (unsigned int)total_data
));
7240 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7244 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7247 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7251 /* If total_data == 4 Windows doesn't care what values
7252 * are placed in that field, it just ignores them.
7253 * The System i QNTC IBM SMB client puts bad values here,
7254 * so ignore them. */
7256 status
= create_directory(conn
, req
, directory
);
7258 if (!NT_STATUS_IS_OK(status
)) {
7259 reply_nterror(req
, status
);
7263 /* Try and set any given EA. */
7265 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7266 if (!NT_STATUS_IS_OK(status
)) {
7267 reply_nterror(req
, status
);
7272 /* Realloc the parameter and data sizes */
7273 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7274 if(*pparams
== NULL
) {
7275 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7282 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7287 /****************************************************************************
7288 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7289 We don't actually do this - we just send a null response.
7290 ****************************************************************************/
7292 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7293 struct smb_request
*req
,
7294 char **pparams
, int total_params
,
7295 char **ppdata
, int total_data
,
7296 unsigned int max_data_bytes
)
7298 char *params
= *pparams
;
7301 if (total_params
< 6) {
7302 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7306 info_level
= SVAL(params
,4);
7307 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7309 switch (info_level
) {
7314 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7318 /* Realloc the parameter and data sizes */
7319 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7320 if (*pparams
== NULL
) {
7321 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7326 SSVAL(params
,0,fnf_handle
);
7327 SSVAL(params
,2,0); /* No changes */
7328 SSVAL(params
,4,0); /* No EA errors */
7335 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7340 /****************************************************************************
7341 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7342 changes). Currently this does nothing.
7343 ****************************************************************************/
7345 static void call_trans2findnotifynext(connection_struct
*conn
,
7346 struct smb_request
*req
,
7347 char **pparams
, int total_params
,
7348 char **ppdata
, int total_data
,
7349 unsigned int max_data_bytes
)
7351 char *params
= *pparams
;
7353 DEBUG(3,("call_trans2findnotifynext\n"));
7355 /* Realloc the parameter and data sizes */
7356 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7357 if (*pparams
== NULL
) {
7358 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7363 SSVAL(params
,0,0); /* No changes */
7364 SSVAL(params
,2,0); /* No EA errors */
7366 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7371 /****************************************************************************
7372 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7373 ****************************************************************************/
7375 static void call_trans2getdfsreferral(connection_struct
*conn
,
7376 struct smb_request
*req
,
7377 char **pparams
, int total_params
,
7378 char **ppdata
, int total_data
,
7379 unsigned int max_data_bytes
)
7381 char *params
= *pparams
;
7382 char *pathname
= NULL
;
7384 int max_referral_level
;
7385 NTSTATUS status
= NT_STATUS_OK
;
7386 TALLOC_CTX
*ctx
= talloc_tos();
7388 DEBUG(10,("call_trans2getdfsreferral\n"));
7390 if (total_params
< 3) {
7391 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7395 max_referral_level
= SVAL(params
,0);
7397 if(!lp_host_msdfs()) {
7398 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7402 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7403 total_params
- 2, STR_TERMINATE
);
7405 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7408 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7409 ppdata
,&status
)) < 0) {
7410 reply_nterror(req
, status
);
7414 SSVAL(req
->inbuf
, smb_flg2
,
7415 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7416 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7421 #define LMCAT_SPL 0x53
7422 #define LMFUNC_GETJOBID 0x60
7424 /****************************************************************************
7425 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7426 ****************************************************************************/
7428 static void call_trans2ioctl(connection_struct
*conn
,
7429 struct smb_request
*req
,
7430 char **pparams
, int total_params
,
7431 char **ppdata
, int total_data
,
7432 unsigned int max_data_bytes
)
7434 char *pdata
= *ppdata
;
7435 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
7437 /* check for an invalid fid before proceeding */
7440 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7444 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
7445 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
7446 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7447 if (*ppdata
== NULL
) {
7448 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7453 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7454 CAN ACCEPT THIS IN UNICODE. JRA. */
7456 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7457 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7458 global_myname(), 15,
7459 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7460 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7461 lp_servicename(SNUM(conn
)), 13,
7462 STR_ASCII
|STR_TERMINATE
); /* Service name */
7463 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7468 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7469 reply_doserror(req
, ERRSRV
, ERRerror
);
7472 /****************************************************************************
7473 Reply to a SMBfindclose (stop trans2 directory search).
7474 ****************************************************************************/
7476 void reply_findclose(struct smb_request
*req
)
7480 START_PROFILE(SMBfindclose
);
7483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7484 END_PROFILE(SMBfindclose
);
7488 dptr_num
= SVALS(req
->vwv
+0, 0);
7490 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7492 dptr_close(&dptr_num
);
7494 reply_outbuf(req
, 0, 0);
7496 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7498 END_PROFILE(SMBfindclose
);
7502 /****************************************************************************
7503 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7504 ****************************************************************************/
7506 void reply_findnclose(struct smb_request
*req
)
7510 START_PROFILE(SMBfindnclose
);
7513 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7514 END_PROFILE(SMBfindnclose
);
7518 dptr_num
= SVAL(req
->vwv
+0, 0);
7520 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7522 /* We never give out valid handles for a
7523 findnotifyfirst - so any dptr_num is ok here.
7526 reply_outbuf(req
, 0, 0);
7528 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7530 END_PROFILE(SMBfindnclose
);
7534 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7535 struct trans_state
*state
)
7537 if (Protocol
>= PROTOCOL_NT1
) {
7538 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7539 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7542 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7543 if (state
->call
!= TRANSACT2_QFSINFO
&&
7544 state
->call
!= TRANSACT2_SETFSINFO
) {
7545 DEBUG(0,("handle_trans2: encryption required "
7547 (unsigned int)state
->call
));
7548 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7553 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
7555 /* Now we must call the relevant TRANS2 function */
7556 switch(state
->call
) {
7557 case TRANSACT2_OPEN
:
7559 START_PROFILE(Trans2_open
);
7560 call_trans2open(conn
, req
,
7561 &state
->param
, state
->total_param
,
7562 &state
->data
, state
->total_data
,
7563 state
->max_data_return
);
7564 END_PROFILE(Trans2_open
);
7568 case TRANSACT2_FINDFIRST
:
7570 START_PROFILE(Trans2_findfirst
);
7571 call_trans2findfirst(conn
, req
,
7572 &state
->param
, state
->total_param
,
7573 &state
->data
, state
->total_data
,
7574 state
->max_data_return
);
7575 END_PROFILE(Trans2_findfirst
);
7579 case TRANSACT2_FINDNEXT
:
7581 START_PROFILE(Trans2_findnext
);
7582 call_trans2findnext(conn
, req
,
7583 &state
->param
, state
->total_param
,
7584 &state
->data
, state
->total_data
,
7585 state
->max_data_return
);
7586 END_PROFILE(Trans2_findnext
);
7590 case TRANSACT2_QFSINFO
:
7592 START_PROFILE(Trans2_qfsinfo
);
7593 call_trans2qfsinfo(conn
, req
,
7594 &state
->param
, state
->total_param
,
7595 &state
->data
, state
->total_data
,
7596 state
->max_data_return
);
7597 END_PROFILE(Trans2_qfsinfo
);
7601 case TRANSACT2_SETFSINFO
:
7603 START_PROFILE(Trans2_setfsinfo
);
7604 call_trans2setfsinfo(conn
, req
,
7605 &state
->param
, state
->total_param
,
7606 &state
->data
, state
->total_data
,
7607 state
->max_data_return
);
7608 END_PROFILE(Trans2_setfsinfo
);
7612 case TRANSACT2_QPATHINFO
:
7613 case TRANSACT2_QFILEINFO
:
7615 START_PROFILE(Trans2_qpathinfo
);
7616 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7617 &state
->param
, state
->total_param
,
7618 &state
->data
, state
->total_data
,
7619 state
->max_data_return
);
7620 END_PROFILE(Trans2_qpathinfo
);
7624 case TRANSACT2_SETPATHINFO
:
7625 case TRANSACT2_SETFILEINFO
:
7627 START_PROFILE(Trans2_setpathinfo
);
7628 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7629 &state
->param
, state
->total_param
,
7630 &state
->data
, state
->total_data
,
7631 state
->max_data_return
);
7632 END_PROFILE(Trans2_setpathinfo
);
7636 case TRANSACT2_FINDNOTIFYFIRST
:
7638 START_PROFILE(Trans2_findnotifyfirst
);
7639 call_trans2findnotifyfirst(conn
, req
,
7640 &state
->param
, state
->total_param
,
7641 &state
->data
, state
->total_data
,
7642 state
->max_data_return
);
7643 END_PROFILE(Trans2_findnotifyfirst
);
7647 case TRANSACT2_FINDNOTIFYNEXT
:
7649 START_PROFILE(Trans2_findnotifynext
);
7650 call_trans2findnotifynext(conn
, req
,
7651 &state
->param
, state
->total_param
,
7652 &state
->data
, state
->total_data
,
7653 state
->max_data_return
);
7654 END_PROFILE(Trans2_findnotifynext
);
7658 case TRANSACT2_MKDIR
:
7660 START_PROFILE(Trans2_mkdir
);
7661 call_trans2mkdir(conn
, req
,
7662 &state
->param
, state
->total_param
,
7663 &state
->data
, state
->total_data
,
7664 state
->max_data_return
);
7665 END_PROFILE(Trans2_mkdir
);
7669 case TRANSACT2_GET_DFS_REFERRAL
:
7671 START_PROFILE(Trans2_get_dfs_referral
);
7672 call_trans2getdfsreferral(conn
, req
,
7673 &state
->param
, state
->total_param
,
7674 &state
->data
, state
->total_data
,
7675 state
->max_data_return
);
7676 END_PROFILE(Trans2_get_dfs_referral
);
7680 case TRANSACT2_IOCTL
:
7682 START_PROFILE(Trans2_ioctl
);
7683 call_trans2ioctl(conn
, req
,
7684 &state
->param
, state
->total_param
,
7685 &state
->data
, state
->total_data
,
7686 state
->max_data_return
);
7687 END_PROFILE(Trans2_ioctl
);
7692 /* Error in request */
7693 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7694 reply_doserror(req
, ERRSRV
,ERRerror
);
7698 /****************************************************************************
7699 Reply to a SMBtrans2.
7700 ****************************************************************************/
7702 void reply_trans2(struct smb_request
*req
)
7704 connection_struct
*conn
= req
->conn
;
7709 unsigned int tran_call
;
7710 struct trans_state
*state
;
7713 START_PROFILE(SMBtrans2
);
7715 if (req
->wct
< 14) {
7716 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7717 END_PROFILE(SMBtrans2
);
7721 dsoff
= SVAL(req
->vwv
+12, 0);
7722 dscnt
= SVAL(req
->vwv
+11, 0);
7723 psoff
= SVAL(req
->vwv
+10, 0);
7724 pscnt
= SVAL(req
->vwv
+9, 0);
7725 tran_call
= SVAL(req
->vwv
+14, 0);
7727 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7728 if (!NT_STATUS_IS_OK(result
)) {
7729 DEBUG(2, ("Got invalid trans2 request: %s\n",
7730 nt_errstr(result
)));
7731 reply_nterror(req
, result
);
7732 END_PROFILE(SMBtrans2
);
7737 switch (tran_call
) {
7738 /* List the allowed trans2 calls on IPC$ */
7739 case TRANSACT2_OPEN
:
7740 case TRANSACT2_GET_DFS_REFERRAL
:
7741 case TRANSACT2_QFILEINFO
:
7742 case TRANSACT2_QFSINFO
:
7743 case TRANSACT2_SETFSINFO
:
7746 reply_doserror(req
, ERRSRV
, ERRaccess
);
7747 END_PROFILE(SMBtrans2
);
7752 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
7753 DEBUG(0, ("talloc failed\n"));
7754 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7755 END_PROFILE(SMBtrans2
);
7759 state
->cmd
= SMBtrans2
;
7761 state
->mid
= req
->mid
;
7762 state
->vuid
= req
->vuid
;
7763 state
->setup_count
= SVAL(req
->vwv
+13, 0);
7764 state
->setup
= NULL
;
7765 state
->total_param
= SVAL(req
->vwv
+0, 0);
7766 state
->param
= NULL
;
7767 state
->total_data
= SVAL(req
->vwv
+1, 0);
7769 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
7770 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
7771 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
7772 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
7773 state
->one_way
= BITSETW(req
->vwv
+5, 1);
7775 state
->call
= tran_call
;
7777 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7778 is so as a sanity check */
7779 if (state
->setup_count
!= 1) {
7781 * Need to have rc=0 for ioctl to get job id for OS/2.
7782 * Network printing will fail if function is not successful.
7783 * Similar function in reply.c will be used if protocol
7784 * is LANMAN1.0 instead of LM1.2X002.
7785 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7786 * outbuf doesn't have to be set(only job id is used).
7788 if ( (state
->setup_count
== 4)
7789 && (tran_call
== TRANSACT2_IOCTL
)
7790 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
7791 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
7792 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7794 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7795 DEBUG(2,("Transaction is %d\n",tran_call
));
7797 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7798 END_PROFILE(SMBtrans2
);
7803 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7806 if (state
->total_data
) {
7808 if (trans_oob(state
->total_data
, 0, dscnt
)
7809 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
7813 /* Can't use talloc here, the core routines do realloc on the
7814 * params and data. */
7815 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7816 if (state
->data
== NULL
) {
7817 DEBUG(0,("reply_trans2: data malloc fail for %u "
7818 "bytes !\n", (unsigned int)state
->total_data
));
7820 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7821 END_PROFILE(SMBtrans2
);
7825 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7828 if (state
->total_param
) {
7830 if (trans_oob(state
->total_param
, 0, pscnt
)
7831 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
7835 /* Can't use talloc here, the core routines do realloc on the
7836 * params and data. */
7837 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7838 if (state
->param
== NULL
) {
7839 DEBUG(0,("reply_trans: param malloc fail for %u "
7840 "bytes !\n", (unsigned int)state
->total_param
));
7841 SAFE_FREE(state
->data
);
7843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7844 END_PROFILE(SMBtrans2
);
7848 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7851 state
->received_data
= dscnt
;
7852 state
->received_param
= pscnt
;
7854 if ((state
->received_param
== state
->total_param
) &&
7855 (state
->received_data
== state
->total_data
)) {
7857 handle_trans2(conn
, req
, state
);
7859 SAFE_FREE(state
->data
);
7860 SAFE_FREE(state
->param
);
7862 END_PROFILE(SMBtrans2
);
7866 DLIST_ADD(conn
->pending_trans
, state
);
7868 /* We need to send an interim response then receive the rest
7869 of the parameter/data bytes */
7870 reply_outbuf(req
, 0, 0);
7871 show_msg((char *)req
->outbuf
);
7872 END_PROFILE(SMBtrans2
);
7877 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7878 SAFE_FREE(state
->data
);
7879 SAFE_FREE(state
->param
);
7881 END_PROFILE(SMBtrans2
);
7882 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7886 /****************************************************************************
7887 Reply to a SMBtranss2
7888 ****************************************************************************/
7890 void reply_transs2(struct smb_request
*req
)
7892 connection_struct
*conn
= req
->conn
;
7893 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7894 struct trans_state
*state
;
7896 START_PROFILE(SMBtranss2
);
7898 show_msg((char *)req
->inbuf
);
7901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7902 END_PROFILE(SMBtranss2
);
7906 for (state
= conn
->pending_trans
; state
!= NULL
;
7907 state
= state
->next
) {
7908 if (state
->mid
== req
->mid
) {
7913 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7914 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7915 END_PROFILE(SMBtranss2
);
7919 /* Revise state->total_param and state->total_data in case they have
7920 changed downwards */
7922 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
7923 state
->total_param
= SVAL(req
->vwv
+0, 0);
7924 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
7925 state
->total_data
= SVAL(req
->vwv
+1, 0);
7927 pcnt
= SVAL(req
->vwv
+2, 0);
7928 poff
= SVAL(req
->vwv
+3, 0);
7929 pdisp
= SVAL(req
->vwv
+4, 0);
7931 dcnt
= SVAL(req
->vwv
+5, 0);
7932 doff
= SVAL(req
->vwv
+6, 0);
7933 ddisp
= SVAL(req
->vwv
+7, 0);
7935 state
->received_param
+= pcnt
;
7936 state
->received_data
+= dcnt
;
7938 if ((state
->received_data
> state
->total_data
) ||
7939 (state
->received_param
> state
->total_param
))
7943 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
7944 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
7947 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
7951 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
7952 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
7955 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
7958 if ((state
->received_param
< state
->total_param
) ||
7959 (state
->received_data
< state
->total_data
)) {
7960 END_PROFILE(SMBtranss2
);
7964 handle_trans2(conn
, req
, state
);
7966 DLIST_REMOVE(conn
->pending_trans
, state
);
7967 SAFE_FREE(state
->data
);
7968 SAFE_FREE(state
->param
);
7971 END_PROFILE(SMBtranss2
);
7976 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7977 DLIST_REMOVE(conn
->pending_trans
, state
);
7978 SAFE_FREE(state
->data
);
7979 SAFE_FREE(state
->param
);
7981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7982 END_PROFILE(SMBtranss2
);