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/>.
29 extern enum protocol_types Protocol
;
30 extern uint32 global_client_caps
;
31 extern struct current_user current_user
;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct
*conn
,
39 const SMB_STRUCT_STAT
*psbuf
);
41 static char *store_file_unix_basic_info2(connection_struct
*conn
,
44 const SMB_STRUCT_STAT
*psbuf
);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
53 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type
= get_remote_arch();
57 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
58 val
= SMB_ROUNDUP(val
,rval
);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, const SMB_STRUCT_STAT
*sbuf
)
72 if(S_ISDIR(sbuf
->st_mode
)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
79 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
82 if (fsp
&& fsp
->initial_allocation_size
)
83 ret
= MAX(ret
,fsp
->initial_allocation_size
);
85 return smb_roundup(conn
, ret
);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name
)
98 static const char *prohibited_ea_names
[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME
,
100 SAMBA_XATTR_DOS_ATTRIB
,
106 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
107 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
110 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
122 files_struct
*fsp
, const char *fname
,
123 const char *ea_name
, struct ea_struct
*pea
)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size
= 256;
132 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
134 return NT_STATUS_NO_MEMORY
;
137 if (fsp
&& fsp
->fh
->fd
!= -1) {
138 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
140 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
143 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
149 return map_nt_error_from_unix(errno
);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
153 dump_data(10, (uint8
*)val
, sizeret
);
156 if (strnequal(ea_name
, "user.", 5)) {
157 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
159 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
161 if (pea
->name
== NULL
) {
163 return NT_STATUS_NO_MEMORY
;
165 pea
->value
.data
= (unsigned char *)val
;
166 pea
->value
.length
= (size_t)sizeret
;
170 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
171 files_struct
*fsp
, const char *fname
,
172 char ***pnames
, size_t *pnum_names
)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size
= 1024;
176 char *ea_namelist
= NULL
;
183 if (!lp_ea_support(SNUM(conn
))) {
190 * TALLOC the result early to get the talloc hierarchy right.
193 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY
;
199 while (ea_namelist_size
<= 65536) {
201 ea_namelist
= TALLOC_REALLOC_ARRAY(
202 names
, ea_namelist
, char, ea_namelist_size
);
203 if (ea_namelist
== NULL
) {
204 DEBUG(0, ("talloc failed\n"));
206 return NT_STATUS_NO_MEMORY
;
209 if (fsp
&& fsp
->fh
->fd
!= -1) {
210 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
213 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
217 if ((sizeret
== -1) && (errno
== ERANGE
)) {
218 ea_namelist_size
*= 2;
227 return map_nt_error_from_unix(errno
);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret
));
241 * Ensure the result is 0-terminated
244 if (ea_namelist
[sizeret
-1] != '\0') {
246 return NT_STATUS_INTERNAL_ERROR
;
254 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
258 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
260 DEBUG(0, ("talloc failed\n"));
262 return NT_STATUS_NO_MEMORY
;
268 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
269 names
[num_names
++] = p
;
273 *pnum_names
= num_names
;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
282 const char *fname
, size_t *pea_total_len
)
284 /* Get a list of all xattrs. Max namesize is 64k. */
287 struct ea_list
*ea_list_head
= NULL
;
292 if (!lp_ea_support(SNUM(conn
))) {
296 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
299 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
303 for (i
=0; i
<num_names
; i
++) {
304 struct ea_list
*listp
;
307 if (strnequal(names
[i
], "system.", 7)
308 || samba_private_attr_name(names
[i
]))
311 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
322 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
325 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
329 (unsigned int)listp
->ea
.value
.length
));
331 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
335 /* Add on 4 for total length. */
336 if (*pea_total_len
) {
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len
));
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
352 connection_struct
*conn
, struct ea_list
*ea_list
)
354 unsigned int ret_data_size
= 4;
357 SMB_ASSERT(total_data_size
>= 4);
359 if (!lp_ea_support(SNUM(conn
))) {
364 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
367 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
368 dos_namelen
= strlen(dos_ea_name
);
369 if (dos_namelen
> 255 || dos_namelen
== 0) {
372 if (ea_list
->ea
.value
.length
> 65535) {
375 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
379 /* We know we have room. */
380 SCVAL(p
,0,ea_list
->ea
.flags
);
381 SCVAL(p
,1,dos_namelen
);
382 SSVAL(p
,2,ea_list
->ea
.value
.length
);
383 fstrcpy(p
+4, dos_ea_name
);
384 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
386 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
387 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
390 ret_data_size
= PTR_DIFF(p
, pdata
);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
392 SIVAL(pdata
,0,ret_data_size
);
393 return ret_data_size
;
396 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
398 size_t total_ea_len
= 0;
399 TALLOC_CTX
*mem_ctx
= NULL
;
401 if (!lp_ea_support(SNUM(conn
))) {
404 mem_ctx
= talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
416 TALLOC_CTX
*mem_ctx
= talloc_tos();
417 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
419 for (; ea_list
; ea_list
= ea_list
->next
) {
420 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name
[5], ea_list
->ea
.name
));
423 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
435 if (!lp_ea_support(SNUM(conn
))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED
;
439 for (;ea_list
; ea_list
= ea_list
->next
) {
441 fstring unix_ea_name
;
443 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
446 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
450 if (samba_private_attr_name(unix_ea_name
)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
452 return NT_STATUS_ACCESS_DENIED
;
455 if (ea_list
->ea
.value
.length
== 0) {
456 /* Remove the attribute. */
457 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name
, fsp
->fsp_name
));
460 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name
, fname
));
464 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
467 /* Removing a non existent attribute always succeeds. */
468 if (ret
== -1 && errno
== ENOATTR
) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
475 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name
, fsp
->fsp_name
));
478 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
479 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name
, fname
));
483 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
484 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
490 if (errno
== ENOTSUP
) {
491 return NT_STATUS_EAS_NOT_SUPPORTED
;
494 return map_nt_error_from_unix(errno
);
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
506 struct ea_list
*ea_list_head
= NULL
;
509 while (offset
+ 2 < data_size
) {
510 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
511 unsigned int namelen
= CVAL(pdata
,offset
);
513 offset
++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
517 (offset
> data_size
) || (namelen
> data_size
) ||
518 (offset
+ namelen
>= data_size
)) {
521 /* Ensure the name is null terminated. */
522 if (pdata
[offset
+ namelen
] != '\0') {
525 pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
]);
530 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
544 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
546 unsigned int namelen
;
556 eal
->ea
.flags
= CVAL(pdata
,0);
557 namelen
= CVAL(pdata
,1);
558 val_len
= SVAL(pdata
,2);
560 if (4 + namelen
+ 1 + val_len
> data_size
) {
564 /* Ensure the name is null terminated. */
565 if (pdata
[namelen
+ 4] != '\0') {
568 pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4);
573 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
574 if (!eal
->ea
.value
.data
) {
578 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal
->ea
.value
.data
[val_len
] = '\0';
582 /* But don't count the null. */
583 eal
->ea
.value
.length
--;
586 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
590 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
601 struct ea_list
*ea_list_head
= NULL
;
603 size_t bytes_used
= 0;
605 while (offset
< data_size
) {
606 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
612 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
613 offset
+= bytes_used
;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list
*ealist
)
626 struct ea_list
*listp
;
629 for (listp
= ealist
; listp
; listp
= listp
->next
) {
630 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
631 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
633 /* Add on 4 for total length. */
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
649 struct ea_list
*nlistp
, *flistp
;
651 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
652 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
653 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
659 /* Copy the data from this entry. */
660 nlistp
->ea
.flags
= flistp
->ea
.flags
;
661 nlistp
->ea
.value
= flistp
->ea
.value
;
664 nlistp
->ea
.flags
= 0;
665 ZERO_STRUCT(nlistp
->ea
.value
);
669 *total_ea_len
= ea_list_size(name_list
);
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct
*conn
,
681 struct smb_request
*req
,
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send
= datasize
;
695 int params_to_send
= paramsize
;
697 const char *pp
= params
;
698 const char *pd
= pdata
;
699 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
700 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset
= 0;
702 bool overflow
= False
;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
709 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes
, datasize
));
712 datasize
= data_to_send
= max_data_bytes
;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send
== 0 && data_to_send
== 0) {
719 reply_outbuf(req
, 10, 0);
720 show_msg((char *)req
->outbuf
);
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
729 data_alignment_offset
= 4 - (params_to_send
% 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space
= max_send
- (smb_size
738 + data_alignment_offset
);
740 if (useable_space
< 0) {
741 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
742 "= %d!!!", useable_space
));
743 exit_server_cleanly("send_trans2_replies: Not enough space");
746 while (params_to_send
|| data_to_send
) {
747 /* Calculate whether we will totally or partially fill this packet */
749 total_sent_thistime
= params_to_send
+ data_to_send
;
751 /* We can never send more than useable_space */
753 * Note that 'useable_space' does not include the alignment offsets,
754 * but we must include the alignment offsets in the calculation of
755 * the length of the data we send over the wire, as the alignment offsets
756 * are sent here. Fix from Marc_Jacobsen@hp.com.
759 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
761 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
762 + data_alignment_offset
);
764 /* Set total params and data to be sent */
765 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
766 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
768 /* Calculate how many parameters and data we can fit into
769 * this packet. Parameters get precedence
772 params_sent_thistime
= MIN(params_to_send
,useable_space
);
773 data_sent_thistime
= useable_space
- params_sent_thistime
;
774 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
776 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
778 /* smb_proff is the offset from the start of the SMB header to the
779 parameter bytes, however the first 4 bytes of outbuf are
780 the Netbios over TCP header. Thus use smb_base() to subtract
781 them from the calculation */
783 SSVAL(req
->outbuf
,smb_proff
,
784 ((smb_buf(req
->outbuf
)+alignment_offset
)
785 - smb_base(req
->outbuf
)));
787 if(params_sent_thistime
== 0)
788 SSVAL(req
->outbuf
,smb_prdisp
,0);
790 /* Absolute displacement of param bytes sent in this packet */
791 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
793 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
794 if(data_sent_thistime
== 0) {
795 SSVAL(req
->outbuf
,smb_droff
,0);
796 SSVAL(req
->outbuf
,smb_drdisp
, 0);
798 /* The offset of the data bytes is the offset of the
799 parameter bytes plus the number of parameters being sent this time */
800 SSVAL(req
->outbuf
, smb_droff
,
801 ((smb_buf(req
->outbuf
)+alignment_offset
)
802 - smb_base(req
->outbuf
))
803 + params_sent_thistime
+ data_alignment_offset
);
804 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
807 /* Initialize the padding for alignment */
809 if (alignment_offset
!= 0) {
810 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
813 /* Copy the param bytes into the packet */
815 if(params_sent_thistime
) {
816 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
817 params_sent_thistime
);
820 /* Copy in the data bytes */
821 if(data_sent_thistime
) {
822 if (data_alignment_offset
!= 0) {
823 memset((smb_buf(req
->outbuf
)+alignment_offset
+
824 params_sent_thistime
), 0,
825 data_alignment_offset
);
827 memcpy(smb_buf(req
->outbuf
)+alignment_offset
828 +params_sent_thistime
+data_alignment_offset
,
829 pd
,data_sent_thistime
);
832 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
833 params_sent_thistime
, data_sent_thistime
, useable_space
));
834 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
835 params_to_send
, data_to_send
, paramsize
, datasize
));
838 error_packet_set((char *)req
->outbuf
,
839 ERRDOS
,ERRbufferoverflow
,
840 STATUS_BUFFER_OVERFLOW
,
844 /* Send the packet */
845 show_msg((char *)req
->outbuf
);
846 if (!srv_send_smb(smbd_server_fd(),
848 IS_CONN_ENCRYPTED(conn
)))
849 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
851 TALLOC_FREE(req
->outbuf
);
853 pp
+= params_sent_thistime
;
854 pd
+= data_sent_thistime
;
856 params_to_send
-= params_sent_thistime
;
857 data_to_send
-= data_sent_thistime
;
860 if(params_to_send
< 0 || data_to_send
< 0) {
861 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
862 params_to_send
, data_to_send
));
870 /****************************************************************************
871 Reply to a TRANSACT2_OPEN.
872 ****************************************************************************/
874 static void call_trans2open(connection_struct
*conn
,
875 struct smb_request
*req
,
876 char **pparams
, int total_params
,
877 char **ppdata
, int total_data
,
878 unsigned int max_data_bytes
)
880 char *params
= *pparams
;
881 char *pdata
= *ppdata
;
886 bool return_additional_info
;
897 SMB_STRUCT_STAT sbuf
;
900 struct ea_list
*ea_list
= NULL
;
905 uint32 create_disposition
;
906 uint32 create_options
= 0;
907 TALLOC_CTX
*ctx
= talloc_tos();
910 * Ensure we have enough parameters to perform the operation.
913 if (total_params
< 29) {
914 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
918 flags
= SVAL(params
, 0);
919 deny_mode
= SVAL(params
, 2);
920 open_attr
= SVAL(params
,6);
921 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
922 if (oplock_request
) {
923 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
927 return_additional_info
= BITSETW(params
,0);
928 open_sattr
= SVAL(params
, 4);
929 open_time
= make_unix_date3(params
+8);
931 open_ofun
= SVAL(params
,12);
932 open_size
= IVAL(params
,14);
936 reply_doserror(req
, ERRSRV
, ERRaccess
);
940 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
941 total_params
- 28, STR_TERMINATE
,
943 if (!NT_STATUS_IS_OK(status
)) {
944 reply_nterror(req
, status
);
948 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
949 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
950 (unsigned int)open_ofun
, open_size
));
952 if (open_ofun
== 0) {
953 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
957 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
962 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
966 /* Any data in this call is an EA list. */
967 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
968 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
972 if (total_data
!= 4) {
973 if (total_data
< 10) {
974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
978 if (IVAL(pdata
,0) > total_data
) {
979 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
980 IVAL(pdata
,0), (unsigned int)total_data
));
981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
985 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
988 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
991 } else if (IVAL(pdata
,0) != 4) {
992 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
996 status
= create_file(conn
, /* conn */
998 0, /* root_dir_fid */
1000 access_mask
, /* access_mask */
1001 share_mode
, /* share_access */
1002 create_disposition
, /* create_disposition*/
1003 create_options
, /* create_options */
1004 open_attr
, /* file_attributes */
1005 oplock_request
, /* oplock_request */
1006 open_size
, /* allocation_size */
1008 ea_list
, /* ea_list */
1010 &smb_action
, /* pinfo */
1013 if (!NT_STATUS_IS_OK(status
)) {
1014 if (open_was_deferred(req
->mid
)) {
1015 /* We have re-scheduled this call. */
1018 reply_openerror(req
, status
);
1022 size
= get_file_size(sbuf
);
1023 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1024 mtime
= sbuf
.st_mtime
;
1025 inode
= sbuf
.st_ino
;
1027 close_file(fsp
,ERROR_CLOSE
);
1028 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1032 /* Realloc the size of parameters and data we will return */
1033 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1034 if(*pparams
== NULL
) {
1035 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1040 SSVAL(params
,0,fsp
->fnum
);
1041 SSVAL(params
,2,fattr
);
1042 srv_put_dos_date2(params
,4, mtime
);
1043 SIVAL(params
,8, (uint32
)size
);
1044 SSVAL(params
,12,deny_mode
);
1045 SSVAL(params
,14,0); /* open_type - file or directory. */
1046 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1048 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1049 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1052 SSVAL(params
,18,smb_action
);
1055 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1057 SIVAL(params
,20,inode
);
1058 SSVAL(params
,24,0); /* Padding. */
1060 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1061 SIVAL(params
, 26, ea_size
);
1063 SIVAL(params
, 26, 0);
1066 /* Send the required number of replies */
1067 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1070 /*********************************************************
1071 Routine to check if a given string matches exactly.
1072 as a special case a mask of "." does NOT match. That
1073 is required for correct wildcard semantics
1074 Case can be significant or not.
1075 **********************************************************/
1077 static bool exact_match(connection_struct
*conn
,
1081 if (mask
[0] == '.' && mask
[1] == 0)
1083 if (dptr_has_wild(conn
->dirptr
)) {
1086 if (conn
->case_sensitive
)
1087 return strcmp(str
,mask
)==0;
1089 return StrCaseCmp(str
,mask
) == 0;
1092 /****************************************************************************
1093 Return the filetype for UNIX extensions.
1094 ****************************************************************************/
1096 static uint32
unix_filetype(mode_t mode
)
1099 return UNIX_TYPE_FILE
;
1100 else if(S_ISDIR(mode
))
1101 return UNIX_TYPE_DIR
;
1103 else if(S_ISLNK(mode
))
1104 return UNIX_TYPE_SYMLINK
;
1107 else if(S_ISCHR(mode
))
1108 return UNIX_TYPE_CHARDEV
;
1111 else if(S_ISBLK(mode
))
1112 return UNIX_TYPE_BLKDEV
;
1115 else if(S_ISFIFO(mode
))
1116 return UNIX_TYPE_FIFO
;
1119 else if(S_ISSOCK(mode
))
1120 return UNIX_TYPE_SOCKET
;
1123 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1124 return UNIX_TYPE_UNKNOWN
;
1127 /****************************************************************************
1128 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1129 ****************************************************************************/
1131 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1133 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1134 SMB_STRUCT_STAT
*psbuf
,
1136 enum perm_type ptype
,
1141 if (perms
== SMB_MODE_NO_CHANGE
) {
1142 if (!VALID_STAT(*psbuf
)) {
1143 return NT_STATUS_INVALID_PARAMETER
;
1145 *ret_perms
= psbuf
->st_mode
;
1146 return NT_STATUS_OK
;
1150 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1151 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1152 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1153 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1154 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1155 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1156 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1157 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1158 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1160 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1163 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1166 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1171 /* Apply mode mask */
1172 ret
&= lp_create_mask(SNUM(conn
));
1173 /* Add in force bits */
1174 ret
|= lp_force_create_mode(SNUM(conn
));
1177 ret
&= lp_dir_mask(SNUM(conn
));
1178 /* Add in force bits */
1179 ret
|= lp_force_dir_mode(SNUM(conn
));
1181 case PERM_EXISTING_FILE
:
1182 /* Apply mode mask */
1183 ret
&= lp_security_mask(SNUM(conn
));
1184 /* Add in force bits */
1185 ret
|= lp_force_security_mode(SNUM(conn
));
1187 case PERM_EXISTING_DIR
:
1188 /* Apply mode mask */
1189 ret
&= lp_dir_security_mask(SNUM(conn
));
1190 /* Add in force bits */
1191 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1196 return NT_STATUS_OK
;
1199 /****************************************************************************
1200 Needed to show the msdfs symlinks as directories. Modifies psbuf
1201 to be a directory if it's a msdfs link.
1202 ****************************************************************************/
1204 static bool check_msdfs_link(connection_struct
*conn
,
1205 const char *pathname
,
1206 SMB_STRUCT_STAT
*psbuf
)
1208 int saved_errno
= errno
;
1209 if(lp_host_msdfs() &&
1210 lp_msdfs_root(SNUM(conn
)) &&
1211 is_msdfs_link(conn
, pathname
, psbuf
)) {
1213 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1216 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1217 errno
= saved_errno
;
1220 errno
= saved_errno
;
1225 /****************************************************************************
1226 Get a level dependent lanman2 dir entry.
1227 ****************************************************************************/
1229 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1230 connection_struct
*conn
,
1232 const char *path_mask
,
1235 int requires_resume_key
,
1241 int space_remaining
,
1243 bool *got_exact_match
,
1244 int *last_entry_off
,
1245 struct ea_list
*name_list
)
1249 SMB_STRUCT_STAT sbuf
;
1250 const char *mask
= NULL
;
1251 char *pathreal
= NULL
;
1252 const char *fname
= NULL
;
1253 char *p
, *q
, *pdata
= *ppdata
;
1257 SMB_OFF_T file_size
= 0;
1258 SMB_BIG_UINT allocation_size
= 0;
1260 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1261 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1263 char *last_entry_ptr
;
1265 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1266 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1267 bool check_mangled_names
= lp_manglednames(conn
->params
);
1268 char mangled_name
[13]; /* mangled 8.3 name. */
1270 *out_of_space
= False
;
1271 *got_exact_match
= False
;
1273 ZERO_STRUCT(mdate_ts
);
1274 ZERO_STRUCT(adate_ts
);
1275 ZERO_STRUCT(create_date_ts
);
1277 if (!conn
->dirptr
) {
1281 p
= strrchr_m(path_mask
,'/');
1284 mask
= talloc_strdup(ctx
,"*.*");
1294 bool ms_dfs_link
= False
;
1296 /* Needed if we run out of space */
1297 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1298 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1301 * Due to bugs in NT client redirectors we are not using
1302 * resume keys any more - set them to zero.
1303 * Check out the related comments in findfirst/findnext.
1309 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1310 (long)conn
->dirptr
,curr_dirpos
));
1317 * fname may get mangled, dname is never mangled.
1318 * Whenever we're accessing the filesystem we use
1319 * pathreal which is composed from dname.
1325 /* Mangle fname if it's an illegal name. */
1326 if (mangle_must_mangle(dname
,conn
->params
)) {
1327 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1328 continue; /* Error - couldn't mangle. */
1330 fname
= mangled_name
;
1333 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1334 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1337 if(!got_match
&& check_mangled_names
&&
1338 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1340 * It turns out that NT matches wildcards against
1341 * both long *and* short names. This may explain some
1342 * of the wildcard wierdness from old DOS clients
1343 * that some people have been seeing.... JRA.
1345 /* Force the mangling into 8.3. */
1346 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1347 continue; /* Error - couldn't mangle. */
1350 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1351 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1356 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1358 if (dont_descend
&& !isdots
) {
1364 pathreal
= talloc_asprintf(ctx
,
1369 pathreal
= talloc_asprintf(ctx
,
1379 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1380 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1381 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1382 pathreal
,strerror(errno
)));
1383 TALLOC_FREE(pathreal
);
1386 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1387 /* Needed to show the msdfs symlinks as
1390 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal
,strerror(errno
)));
1394 TALLOC_FREE(pathreal
);
1400 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1402 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1405 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1406 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1407 TALLOC_FREE(pathreal
);
1411 if (!(mode
& aDIR
)) {
1412 file_size
= get_file_size(sbuf
);
1414 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1416 mdate_ts
= get_mtimespec(&sbuf
);
1417 adate_ts
= get_atimespec(&sbuf
);
1418 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1420 if (ask_sharemode
) {
1421 struct timespec write_time_ts
;
1422 struct file_id fileid
;
1424 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1425 get_file_infos(fileid
, NULL
, &write_time_ts
);
1426 if (!null_timespec(write_time_ts
)) {
1427 mdate_ts
= write_time_ts
;
1431 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1432 dos_filetime_timespec(&create_date_ts
);
1433 dos_filetime_timespec(&mdate_ts
);
1434 dos_filetime_timespec(&adate_ts
);
1437 create_date
= convert_timespec_to_time_t(create_date_ts
);
1438 mdate
= convert_timespec_to_time_t(mdate_ts
);
1439 adate
= convert_timespec_to_time_t(adate_ts
);
1441 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1445 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1452 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1454 switch (info_level
) {
1455 case SMB_FIND_INFO_STANDARD
:
1456 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1457 if(requires_resume_key
) {
1461 srv_put_dos_date2(p
,0,create_date
);
1462 srv_put_dos_date2(p
,4,adate
);
1463 srv_put_dos_date2(p
,8,mdate
);
1464 SIVAL(p
,12,(uint32
)file_size
);
1465 SIVAL(p
,16,(uint32
)allocation_size
);
1469 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1470 p
+= ucs2_align(base_data
, p
, 0);
1472 len
= srvstr_push(base_data
, flags2
, p
,
1473 fname
, PTR_DIFF(end_data
, p
),
1475 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1477 SCVAL(nameptr
, -1, len
- 2);
1479 SCVAL(nameptr
, -1, 0);
1483 SCVAL(nameptr
, -1, len
- 1);
1485 SCVAL(nameptr
, -1, 0);
1491 case SMB_FIND_EA_SIZE
:
1492 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1493 if(requires_resume_key
) {
1497 srv_put_dos_date2(p
,0,create_date
);
1498 srv_put_dos_date2(p
,4,adate
);
1499 srv_put_dos_date2(p
,8,mdate
);
1500 SIVAL(p
,12,(uint32
)file_size
);
1501 SIVAL(p
,16,(uint32
)allocation_size
);
1504 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1505 SIVAL(p
,22,ea_size
); /* Extended attributes */
1509 len
= srvstr_push(base_data
, flags2
,
1510 p
, fname
, PTR_DIFF(end_data
, p
),
1511 STR_TERMINATE
| STR_NOALIGN
);
1512 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1525 SCVAL(nameptr
,0,len
);
1527 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1530 case SMB_FIND_EA_LIST
:
1532 struct ea_list
*file_list
= NULL
;
1535 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1539 if(requires_resume_key
) {
1543 srv_put_dos_date2(p
,0,create_date
);
1544 srv_put_dos_date2(p
,4,adate
);
1545 srv_put_dos_date2(p
,8,mdate
);
1546 SIVAL(p
,12,(uint32
)file_size
);
1547 SIVAL(p
,16,(uint32
)allocation_size
);
1549 p
+= 22; /* p now points to the EA area. */
1551 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1552 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1554 /* We need to determine if this entry will fit in the space available. */
1555 /* Max string size is 255 bytes. */
1556 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1557 /* Move the dirptr back to prev_dirpos */
1558 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1559 *out_of_space
= True
;
1560 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1561 return False
; /* Not finished - just out of space */
1564 /* Push the ea_data followed by the name. */
1565 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1567 len
= srvstr_push(base_data
, flags2
,
1568 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1569 STR_TERMINATE
| STR_NOALIGN
);
1570 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1583 SCVAL(nameptr
,0,len
);
1585 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1589 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1590 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1591 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1593 SIVAL(p
,0,reskey
); p
+= 4;
1594 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1595 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1596 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1597 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1598 SOFF_T(p
,0,file_size
); p
+= 8;
1599 SOFF_T(p
,0,allocation_size
); p
+= 8;
1600 SIVAL(p
,0,nt_extmode
); p
+= 4;
1601 q
= p
; p
+= 4; /* q is placeholder for name length. */
1603 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1604 SIVAL(p
,0,ea_size
); /* Extended attributes */
1607 /* Clear the short name buffer. This is
1608 * IMPORTANT as not doing so will trigger
1609 * a Win2k client bug. JRA.
1611 if (!was_8_3
&& check_mangled_names
) {
1612 if (!name_to_8_3(fname
,mangled_name
,True
,
1614 /* Error - mangle failed ! */
1615 memset(mangled_name
,'\0',12);
1617 mangled_name
[12] = 0;
1618 len
= srvstr_push(base_data
, flags2
,
1619 p
+2, mangled_name
, 24,
1620 STR_UPPER
|STR_UNICODE
);
1622 memset(p
+ 2 + len
,'\0',24 - len
);
1629 len
= srvstr_push(base_data
, flags2
, p
,
1630 fname
, PTR_DIFF(end_data
, p
),
1631 STR_TERMINATE_ASCII
);
1634 SIVAL(p
,0,0); /* Ensure any padding is null. */
1635 len
= PTR_DIFF(p
, pdata
);
1636 len
= (len
+ 3) & ~3;
1641 case SMB_FIND_FILE_DIRECTORY_INFO
:
1642 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1644 SIVAL(p
,0,reskey
); p
+= 4;
1645 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1646 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1647 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1648 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1649 SOFF_T(p
,0,file_size
); p
+= 8;
1650 SOFF_T(p
,0,allocation_size
); p
+= 8;
1651 SIVAL(p
,0,nt_extmode
); p
+= 4;
1652 len
= srvstr_push(base_data
, flags2
,
1653 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1654 STR_TERMINATE_ASCII
);
1657 SIVAL(p
,0,0); /* Ensure any padding is null. */
1658 len
= PTR_DIFF(p
, pdata
);
1659 len
= (len
+ 3) & ~3;
1664 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1665 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1667 SIVAL(p
,0,reskey
); p
+= 4;
1668 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1669 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1670 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1671 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1672 SOFF_T(p
,0,file_size
); p
+= 8;
1673 SOFF_T(p
,0,allocation_size
); p
+= 8;
1674 SIVAL(p
,0,nt_extmode
); p
+= 4;
1675 q
= p
; p
+= 4; /* q is placeholder for name length. */
1677 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1678 SIVAL(p
,0,ea_size
); /* Extended attributes */
1681 len
= srvstr_push(base_data
, flags2
, p
,
1682 fname
, PTR_DIFF(end_data
, p
),
1683 STR_TERMINATE_ASCII
);
1687 SIVAL(p
,0,0); /* Ensure any padding is null. */
1688 len
= PTR_DIFF(p
, pdata
);
1689 len
= (len
+ 3) & ~3;
1694 case SMB_FIND_FILE_NAMES_INFO
:
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1697 SIVAL(p
,0,reskey
); p
+= 4;
1699 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1700 acl on a dir (tridge) */
1701 len
= srvstr_push(base_data
, flags2
, p
,
1702 fname
, PTR_DIFF(end_data
, p
),
1703 STR_TERMINATE_ASCII
);
1706 SIVAL(p
,0,0); /* Ensure any padding is null. */
1707 len
= PTR_DIFF(p
, pdata
);
1708 len
= (len
+ 3) & ~3;
1713 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1714 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1716 SIVAL(p
,0,reskey
); p
+= 4;
1717 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1718 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1719 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1720 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1721 SOFF_T(p
,0,file_size
); p
+= 8;
1722 SOFF_T(p
,0,allocation_size
); p
+= 8;
1723 SIVAL(p
,0,nt_extmode
); p
+= 4;
1724 q
= p
; p
+= 4; /* q is placeholder for name length. */
1726 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1727 SIVAL(p
,0,ea_size
); /* Extended attributes */
1730 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1731 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1732 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1733 len
= srvstr_push(base_data
, flags2
, p
,
1734 fname
, PTR_DIFF(end_data
, p
),
1735 STR_TERMINATE_ASCII
);
1738 SIVAL(p
,0,0); /* Ensure any padding is null. */
1739 len
= PTR_DIFF(p
, pdata
);
1740 len
= (len
+ 3) & ~3;
1745 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1746 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1747 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1749 SIVAL(p
,0,reskey
); p
+= 4;
1750 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1751 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1752 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1753 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1754 SOFF_T(p
,0,file_size
); p
+= 8;
1755 SOFF_T(p
,0,allocation_size
); p
+= 8;
1756 SIVAL(p
,0,nt_extmode
); p
+= 4;
1757 q
= p
; p
+= 4; /* q is placeholder for name length */
1759 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1760 SIVAL(p
,0,ea_size
); /* Extended attributes */
1763 /* Clear the short name buffer. This is
1764 * IMPORTANT as not doing so will trigger
1765 * a Win2k client bug. JRA.
1767 if (!was_8_3
&& check_mangled_names
) {
1768 if (!name_to_8_3(fname
,mangled_name
,True
,
1770 /* Error - mangle failed ! */
1771 memset(mangled_name
,'\0',12);
1773 mangled_name
[12] = 0;
1774 len
= srvstr_push(base_data
, flags2
,
1775 p
+2, mangled_name
, 24,
1776 STR_UPPER
|STR_UNICODE
);
1779 memset(p
+ 2 + len
,'\0',24 - len
);
1786 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1787 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1788 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1789 len
= srvstr_push(base_data
, flags2
, p
,
1790 fname
, PTR_DIFF(end_data
, p
),
1791 STR_TERMINATE_ASCII
);
1794 SIVAL(p
,0,0); /* Ensure any padding is null. */
1795 len
= PTR_DIFF(p
, pdata
);
1796 len
= (len
+ 3) & ~3;
1801 /* CIFS UNIX Extension. */
1803 case SMB_FIND_FILE_UNIX
:
1804 case SMB_FIND_FILE_UNIX_INFO2
:
1806 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1808 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1810 if (info_level
== SMB_FIND_FILE_UNIX
) {
1811 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1812 p
= store_file_unix_basic(conn
, p
,
1814 len
= srvstr_push(base_data
, flags2
, p
,
1815 fname
, PTR_DIFF(end_data
, p
),
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1819 p
= store_file_unix_basic_info2(conn
, p
,
1823 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1824 PTR_DIFF(end_data
, p
), 0);
1825 SIVAL(nameptr
, 0, len
);
1829 SIVAL(p
,0,0); /* Ensure any padding is null. */
1831 len
= PTR_DIFF(p
, pdata
);
1832 len
= (len
+ 3) & ~3;
1833 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1835 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1845 /* Move the dirptr back to prev_dirpos */
1846 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1847 *out_of_space
= True
;
1848 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1849 return False
; /* Not finished - just out of space */
1852 /* Setup the last entry pointer, as an offset from base_data */
1853 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1854 /* Advance the data pointer to the next slot */
1860 /****************************************************************************
1861 Reply to a TRANS2_FINDFIRST.
1862 ****************************************************************************/
1864 static void call_trans2findfirst(connection_struct
*conn
,
1865 struct smb_request
*req
,
1866 char **pparams
, int total_params
,
1867 char **ppdata
, int total_data
,
1868 unsigned int max_data_bytes
)
1870 /* We must be careful here that we don't return more than the
1871 allowed number of data bytes. If this means returning fewer than
1872 maxentries then so be it. We assume that the redirector has
1873 enough room for the fixed number of parameter bytes it has
1875 char *params
= *pparams
;
1876 char *pdata
= *ppdata
;
1880 uint16 findfirst_flags
;
1881 bool close_after_first
;
1883 bool requires_resume_key
;
1885 char *directory
= NULL
;
1888 int last_entry_off
=0;
1892 bool finished
= False
;
1893 bool dont_descend
= False
;
1894 bool out_of_space
= False
;
1895 int space_remaining
;
1896 bool mask_contains_wcard
= False
;
1897 SMB_STRUCT_STAT sbuf
;
1898 struct ea_list
*ea_list
= NULL
;
1899 NTSTATUS ntstatus
= NT_STATUS_OK
;
1900 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1901 TALLOC_CTX
*ctx
= talloc_tos();
1903 if (total_params
< 13) {
1904 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1908 dirtype
= SVAL(params
,0);
1909 maxentries
= SVAL(params
,2);
1910 findfirst_flags
= SVAL(params
,4);
1911 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1912 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1913 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1914 info_level
= SVAL(params
,6);
1916 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1917 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1918 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1919 info_level
, max_data_bytes
));
1922 /* W2K3 seems to treat zero as 1. */
1926 switch (info_level
) {
1927 case SMB_FIND_INFO_STANDARD
:
1928 case SMB_FIND_EA_SIZE
:
1929 case SMB_FIND_EA_LIST
:
1930 case SMB_FIND_FILE_DIRECTORY_INFO
:
1931 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1932 case SMB_FIND_FILE_NAMES_INFO
:
1933 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1934 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1935 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1937 case SMB_FIND_FILE_UNIX
:
1938 case SMB_FIND_FILE_UNIX_INFO2
:
1939 /* Always use filesystem for UNIX mtime query. */
1940 ask_sharemode
= false;
1941 if (!lp_unix_extensions()) {
1942 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1947 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1951 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1952 params
+12, total_params
- 12,
1953 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1954 if (!NT_STATUS_IS_OK(ntstatus
)) {
1955 reply_nterror(req
, ntstatus
);
1959 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1960 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1963 &mask_contains_wcard
);
1964 if (!NT_STATUS_IS_OK(ntstatus
)) {
1965 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1966 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1967 ERRSRV
, ERRbadpath
);
1970 reply_nterror(req
, ntstatus
);
1974 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, &mask
, &sbuf
);
1975 if (!NT_STATUS_IS_OK(ntstatus
)) {
1976 reply_nterror(req
, ntstatus
);
1980 ntstatus
= check_name(conn
, directory
);
1981 if (!NT_STATUS_IS_OK(ntstatus
)) {
1982 reply_nterror(req
, ntstatus
);
1986 p
= strrchr_m(directory
,'/');
1988 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1989 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1990 mask
= talloc_strdup(ctx
,"*");
1992 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1995 mask_contains_wcard
= True
;
1997 directory
= talloc_strdup(talloc_tos(), "./");
1999 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2006 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2008 if (info_level
== SMB_FIND_EA_LIST
) {
2011 if (total_data
< 4) {
2012 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2016 ea_size
= IVAL(pdata
,0);
2017 if (ea_size
!= total_data
) {
2018 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2019 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2020 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2024 if (!lp_ea_support(SNUM(conn
))) {
2025 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2029 /* Pull out the list of names. */
2030 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2032 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2037 *ppdata
= (char *)SMB_REALLOC(
2038 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2039 if(*ppdata
== NULL
) {
2040 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2044 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2046 /* Realloc the params space */
2047 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2048 if (*pparams
== NULL
) {
2049 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2054 /* Save the wildcard match and attribs we are using on this directory -
2055 needed as lanman2 assumes these are being saved between calls */
2057 ntstatus
= dptr_create(conn
,
2063 mask_contains_wcard
,
2067 if (!NT_STATUS_IS_OK(ntstatus
)) {
2068 reply_nterror(req
, ntstatus
);
2072 dptr_num
= dptr_dnum(conn
->dirptr
);
2073 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2075 /* We don't need to check for VOL here as this is returned by
2076 a different TRANS2 call. */
2078 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2079 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2080 dont_descend
= True
;
2083 space_remaining
= max_data_bytes
;
2084 out_of_space
= False
;
2086 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2087 bool got_exact_match
= False
;
2089 /* this is a heuristic to avoid seeking the dirptr except when
2090 absolutely necessary. It allows for a filename of about 40 chars */
2091 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2092 out_of_space
= True
;
2095 finished
= !get_lanman2_dir_entry(ctx
,
2098 mask
,dirtype
,info_level
,
2099 requires_resume_key
,dont_descend
,
2102 space_remaining
, &out_of_space
,
2104 &last_entry_off
, ea_list
);
2107 if (finished
&& out_of_space
)
2110 if (!finished
&& !out_of_space
)
2114 * As an optimisation if we know we aren't looking
2115 * for a wildcard name (ie. the name matches the wildcard exactly)
2116 * then we can finish on any (first) match.
2117 * This speeds up large directory searches. JRA.
2123 /* Ensure space_remaining never goes -ve. */
2124 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2125 space_remaining
= 0;
2126 out_of_space
= true;
2128 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2132 /* Check if we can close the dirptr */
2133 if(close_after_first
|| (finished
&& close_if_end
)) {
2134 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2135 dptr_close(&dptr_num
);
2139 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2140 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2141 * the protocol level is less than NT1. Tested with smbclient. JRA.
2142 * This should fix the OS/2 client bug #2335.
2145 if(numentries
== 0) {
2146 dptr_close(&dptr_num
);
2147 if (Protocol
< PROTOCOL_NT1
) {
2148 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2151 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2152 ERRDOS
, ERRbadfile
);
2157 /* At this point pdata points to numentries directory entries. */
2159 /* Set up the return parameter block */
2160 SSVAL(params
,0,dptr_num
);
2161 SSVAL(params
,2,numentries
);
2162 SSVAL(params
,4,finished
);
2163 SSVAL(params
,6,0); /* Never an EA error */
2164 SSVAL(params
,8,last_entry_off
);
2166 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2169 if ((! *directory
) && dptr_path(dptr_num
)) {
2170 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2172 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2176 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2177 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2178 mask
, directory
, dirtype
, numentries
) );
2181 * Force a name mangle here to ensure that the
2182 * mask as an 8.3 name is top of the mangled cache.
2183 * The reasons for this are subtle. Don't remove
2184 * this code unless you know what you are doing
2185 * (see PR#13758). JRA.
2188 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2189 char mangled_name
[13];
2190 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2196 /****************************************************************************
2197 Reply to a TRANS2_FINDNEXT.
2198 ****************************************************************************/
2200 static void call_trans2findnext(connection_struct
*conn
,
2201 struct smb_request
*req
,
2202 char **pparams
, int total_params
,
2203 char **ppdata
, int total_data
,
2204 unsigned int max_data_bytes
)
2206 /* We must be careful here that we don't return more than the
2207 allowed number of data bytes. If this means returning fewer than
2208 maxentries then so be it. We assume that the redirector has
2209 enough room for the fixed number of parameter bytes it has
2211 char *params
= *pparams
;
2212 char *pdata
= *ppdata
;
2218 uint16 findnext_flags
;
2219 bool close_after_request
;
2221 bool requires_resume_key
;
2223 bool mask_contains_wcard
= False
;
2224 char *resume_name
= NULL
;
2225 const char *mask
= NULL
;
2226 const char *directory
= NULL
;
2230 int i
, last_entry_off
=0;
2231 bool finished
= False
;
2232 bool dont_descend
= False
;
2233 bool out_of_space
= False
;
2234 int space_remaining
;
2235 struct ea_list
*ea_list
= NULL
;
2236 NTSTATUS ntstatus
= NT_STATUS_OK
;
2237 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2238 TALLOC_CTX
*ctx
= talloc_tos();
2240 if (total_params
< 13) {
2241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2245 dptr_num
= SVAL(params
,0);
2246 maxentries
= SVAL(params
,2);
2247 info_level
= SVAL(params
,4);
2248 resume_key
= IVAL(params
,6);
2249 findnext_flags
= SVAL(params
,10);
2250 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2251 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2252 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2253 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2255 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2257 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2258 &mask_contains_wcard
);
2259 if (!NT_STATUS_IS_OK(ntstatus
)) {
2260 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2261 complain (it thinks we're asking for the directory above the shared
2262 path or an invalid name). Catch this as the resume name is only compared, never used in
2263 a file access. JRA. */
2264 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2265 &resume_name
, params
+12,
2269 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2270 reply_nterror(req
, ntstatus
);
2275 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2276 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2277 resume_key = %d resume name = %s continue=%d level = %d\n",
2278 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2279 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2282 /* W2K3 seems to treat zero as 1. */
2286 switch (info_level
) {
2287 case SMB_FIND_INFO_STANDARD
:
2288 case SMB_FIND_EA_SIZE
:
2289 case SMB_FIND_EA_LIST
:
2290 case SMB_FIND_FILE_DIRECTORY_INFO
:
2291 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2292 case SMB_FIND_FILE_NAMES_INFO
:
2293 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2294 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2295 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2297 case SMB_FIND_FILE_UNIX
:
2298 case SMB_FIND_FILE_UNIX_INFO2
:
2299 /* Always use filesystem for UNIX mtime query. */
2300 ask_sharemode
= false;
2301 if (!lp_unix_extensions()) {
2302 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2307 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2311 if (info_level
== SMB_FIND_EA_LIST
) {
2314 if (total_data
< 4) {
2315 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2319 ea_size
= IVAL(pdata
,0);
2320 if (ea_size
!= total_data
) {
2321 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2322 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2323 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2327 if (!lp_ea_support(SNUM(conn
))) {
2328 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2332 /* Pull out the list of names. */
2333 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2335 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2340 *ppdata
= (char *)SMB_REALLOC(
2341 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2342 if(*ppdata
== NULL
) {
2343 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2348 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2350 /* Realloc the params space */
2351 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2352 if(*pparams
== NULL
) {
2353 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2359 /* Check that the dptr is valid */
2360 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2361 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2365 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2367 /* Get the wildcard mask from the dptr */
2368 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2369 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2370 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2375 directory
= conn
->dirpath
;
2377 /* Get the attr mask from the dptr */
2378 dirtype
= dptr_attr(dptr_num
);
2380 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2381 dptr_num
, mask
, dirtype
,
2383 dptr_TellDir(conn
->dirptr
)));
2385 /* We don't need to check for VOL here as this is returned by
2386 a different TRANS2 call. */
2388 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2389 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2390 dont_descend
= True
;
2393 space_remaining
= max_data_bytes
;
2394 out_of_space
= False
;
2397 * Seek to the correct position. We no longer use the resume key but
2398 * depend on the last file name instead.
2401 if(*resume_name
&& !continue_bit
) {
2404 long current_pos
= 0;
2406 * Remember, name_to_8_3 is called by
2407 * get_lanman2_dir_entry(), so the resume name
2408 * could be mangled. Ensure we check the unmangled name.
2411 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2412 char *new_resume_name
= NULL
;
2413 mangle_lookup_name_from_8_3(ctx
,
2417 if (new_resume_name
) {
2418 resume_name
= new_resume_name
;
2423 * Fix for NT redirector problem triggered by resume key indexes
2424 * changing between directory scans. We now return a resume key of 0
2425 * and instead look for the filename to continue from (also given
2426 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2427 * findfirst/findnext (as is usual) then the directory pointer
2428 * should already be at the correct place.
2431 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2432 } /* end if resume_name && !continue_bit */
2434 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2435 bool got_exact_match
= False
;
2437 /* this is a heuristic to avoid seeking the dirptr except when
2438 absolutely necessary. It allows for a filename of about 40 chars */
2439 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2440 out_of_space
= True
;
2443 finished
= !get_lanman2_dir_entry(ctx
,
2446 mask
,dirtype
,info_level
,
2447 requires_resume_key
,dont_descend
,
2450 space_remaining
, &out_of_space
,
2452 &last_entry_off
, ea_list
);
2455 if (finished
&& out_of_space
)
2458 if (!finished
&& !out_of_space
)
2462 * As an optimisation if we know we aren't looking
2463 * for a wildcard name (ie. the name matches the wildcard exactly)
2464 * then we can finish on any (first) match.
2465 * This speeds up large directory searches. JRA.
2471 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2474 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2475 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2476 mask
, directory
, dirtype
, numentries
) );
2478 /* Check if we can close the dirptr */
2479 if(close_after_request
|| (finished
&& close_if_end
)) {
2480 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2481 dptr_close(&dptr_num
); /* This frees up the saved mask */
2484 /* Set up the return parameter block */
2485 SSVAL(params
,0,numentries
);
2486 SSVAL(params
,2,finished
);
2487 SSVAL(params
,4,0); /* Never an EA error */
2488 SSVAL(params
,6,last_entry_off
);
2490 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2496 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2498 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2502 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2504 SMB_ASSERT(extended_info
!= NULL
);
2506 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2507 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2508 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2509 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2510 #ifdef SAMBA_VERSION_REVISION
2511 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2513 extended_info
->samba_subversion
= 0;
2514 #ifdef SAMBA_VERSION_RC_RELEASE
2515 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2517 #ifdef SAMBA_VERSION_PRE_RELEASE
2518 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2521 #ifdef SAMBA_VERSION_VENDOR_PATCH
2522 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2524 extended_info
->samba_gitcommitdate
= 0;
2525 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2526 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2529 memset(extended_info
->samba_version_string
, 0,
2530 sizeof(extended_info
->samba_version_string
));
2532 snprintf (extended_info
->samba_version_string
,
2533 sizeof(extended_info
->samba_version_string
),
2534 "%s", samba_version_string());
2537 /****************************************************************************
2538 Reply to a TRANS2_QFSINFO (query filesystem info).
2539 ****************************************************************************/
2541 static void call_trans2qfsinfo(connection_struct
*conn
,
2542 struct smb_request
*req
,
2543 char **pparams
, int total_params
,
2544 char **ppdata
, int total_data
,
2545 unsigned int max_data_bytes
)
2547 char *pdata
, *end_data
;
2548 char *params
= *pparams
;
2552 const char *vname
= volume_label(SNUM(conn
));
2553 int snum
= SNUM(conn
);
2554 char *fstype
= lp_fstype(SNUM(conn
));
2555 uint32 additional_flags
= 0;
2557 if (total_params
< 2) {
2558 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2562 info_level
= SVAL(params
,0);
2565 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2566 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2567 "info level (0x%x) on IPC$.\n",
2568 (unsigned int)info_level
));
2569 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2574 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2575 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2576 DEBUG(0,("call_trans2qfsinfo: encryption required "
2577 "and info level 0x%x sent.\n",
2578 (unsigned int)info_level
));
2579 exit_server_cleanly("encryption required "
2585 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2587 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2588 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2589 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2593 *ppdata
= (char *)SMB_REALLOC(
2594 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2595 if (*ppdata
== NULL
) {
2596 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2601 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2602 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2604 switch (info_level
) {
2605 case SMB_INFO_ALLOCATION
:
2607 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2609 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2610 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2614 block_size
= lp_block_size(snum
);
2615 if (bsize
< block_size
) {
2616 SMB_BIG_UINT factor
= block_size
/bsize
;
2621 if (bsize
> block_size
) {
2622 SMB_BIG_UINT factor
= bsize
/block_size
;
2627 bytes_per_sector
= 512;
2628 sectors_per_unit
= bsize
/bytes_per_sector
;
2630 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2631 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2632 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2634 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2635 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2636 SIVAL(pdata
,l1_cUnit
,dsize
);
2637 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2638 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2642 case SMB_INFO_VOLUME
:
2643 /* Return volume name */
2645 * Add volume serial number - hash of a combination of
2646 * the called hostname and the service name.
2648 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2650 * Win2k3 and previous mess this up by sending a name length
2651 * one byte short. I believe only older clients (OS/2 Win9x) use
2652 * this call so try fixing this by adding a terminating null to
2653 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2657 pdata
+l2_vol_szVolLabel
, vname
,
2658 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2659 STR_NOALIGN
|STR_TERMINATE
);
2660 SCVAL(pdata
,l2_vol_cch
,len
);
2661 data_len
= l2_vol_szVolLabel
+ len
;
2662 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2663 (unsigned)st
.st_ctime
, len
, vname
));
2666 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2667 case SMB_FS_ATTRIBUTE_INFORMATION
:
2669 additional_flags
= 0;
2670 #if defined(HAVE_SYS_QUOTAS)
2671 additional_flags
|= FILE_VOLUME_QUOTAS
;
2674 if(lp_nt_acl_support(SNUM(conn
))) {
2675 additional_flags
|= FILE_PERSISTENT_ACLS
;
2678 /* Capabilities are filled in at connection time through STATVFS call */
2679 additional_flags
|= conn
->fs_capabilities
;
2681 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2682 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2683 additional_flags
); /* FS ATTRIBUTES */
2685 SIVAL(pdata
,4,255); /* Max filename component length */
2686 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2687 and will think we can't do long filenames */
2688 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2689 PTR_DIFF(end_data
, pdata
+12),
2692 data_len
= 12 + len
;
2695 case SMB_QUERY_FS_LABEL_INFO
:
2696 case SMB_FS_LABEL_INFORMATION
:
2697 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2698 PTR_DIFF(end_data
, pdata
+4), 0);
2703 case SMB_QUERY_FS_VOLUME_INFO
:
2704 case SMB_FS_VOLUME_INFORMATION
:
2707 * Add volume serial number - hash of a combination of
2708 * the called hostname and the service name.
2710 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2711 (str_checksum(get_local_machine_name())<<16));
2713 /* Max label len is 32 characters. */
2714 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2715 PTR_DIFF(end_data
, pdata
+18),
2717 SIVAL(pdata
,12,len
);
2720 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2721 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2724 case SMB_QUERY_FS_SIZE_INFO
:
2725 case SMB_FS_SIZE_INFORMATION
:
2727 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2729 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2730 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2733 block_size
= lp_block_size(snum
);
2734 if (bsize
< block_size
) {
2735 SMB_BIG_UINT factor
= block_size
/bsize
;
2740 if (bsize
> block_size
) {
2741 SMB_BIG_UINT factor
= bsize
/block_size
;
2746 bytes_per_sector
= 512;
2747 sectors_per_unit
= bsize
/bytes_per_sector
;
2748 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2749 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2750 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2751 SBIG_UINT(pdata
,0,dsize
);
2752 SBIG_UINT(pdata
,8,dfree
);
2753 SIVAL(pdata
,16,sectors_per_unit
);
2754 SIVAL(pdata
,20,bytes_per_sector
);
2758 case SMB_FS_FULL_SIZE_INFORMATION
:
2760 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2762 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2763 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2766 block_size
= lp_block_size(snum
);
2767 if (bsize
< block_size
) {
2768 SMB_BIG_UINT factor
= block_size
/bsize
;
2773 if (bsize
> block_size
) {
2774 SMB_BIG_UINT factor
= bsize
/block_size
;
2779 bytes_per_sector
= 512;
2780 sectors_per_unit
= bsize
/bytes_per_sector
;
2781 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2782 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2783 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2784 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2785 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2786 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2787 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2788 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2792 case SMB_QUERY_FS_DEVICE_INFO
:
2793 case SMB_FS_DEVICE_INFORMATION
:
2795 SIVAL(pdata
,0,0); /* dev type */
2796 SIVAL(pdata
,4,0); /* characteristics */
2799 #ifdef HAVE_SYS_QUOTAS
2800 case SMB_FS_QUOTA_INFORMATION
:
2802 * what we have to send --metze:
2804 * Unknown1: 24 NULL bytes
2805 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2806 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2807 * Quota Flags: 2 byte :
2808 * Unknown3: 6 NULL bytes
2812 * details for Quota Flags:
2814 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2815 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2816 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2817 * 0x0001 Enable Quotas: enable quota for this fs
2821 /* we need to fake up a fsp here,
2822 * because its not send in this call
2825 SMB_NTQUOTA_STRUCT quotas
;
2828 ZERO_STRUCT(quotas
);
2834 if (current_user
.ut
.uid
!= 0) {
2835 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2836 lp_servicename(SNUM(conn
)),conn
->user
));
2837 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2841 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2842 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2843 reply_doserror(req
, ERRSRV
, ERRerror
);
2849 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2851 /* Unknown1 24 NULL bytes*/
2852 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2853 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2854 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2856 /* Default Soft Quota 8 bytes */
2857 SBIG_UINT(pdata
,24,quotas
.softlim
);
2859 /* Default Hard Quota 8 bytes */
2860 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2862 /* Quota flag 2 bytes */
2863 SSVAL(pdata
,40,quotas
.qflags
);
2865 /* Unknown3 6 NULL bytes */
2871 #endif /* HAVE_SYS_QUOTAS */
2872 case SMB_FS_OBJECTID_INFORMATION
:
2874 unsigned char objid
[16];
2875 struct smb_extended_info extended_info
;
2876 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2877 samba_extended_info_version (&extended_info
);
2878 SIVAL(pdata
,16,extended_info
.samba_magic
);
2879 SIVAL(pdata
,20,extended_info
.samba_version
);
2880 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2881 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2882 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2888 * Query the version and capabilities of the CIFS UNIX extensions
2892 case SMB_QUERY_CIFS_UNIX_INFO
:
2894 bool large_write
= lp_min_receive_file_size() &&
2895 !srv_is_signing_active();
2896 bool large_read
= !srv_is_signing_active();
2897 int encrypt_caps
= 0;
2899 if (!lp_unix_extensions()) {
2900 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2904 switch (conn
->encrypt_level
) {
2910 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2913 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2914 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2915 large_write
= false;
2921 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2922 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2924 /* We have POSIX ACLs, pathname, encryption,
2925 * large read/write, and locking capability. */
2927 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2928 CIFS_UNIX_POSIX_ACLS_CAP
|
2929 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2930 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2931 CIFS_UNIX_EXTATTR_CAP
|
2932 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2934 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2936 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2940 case SMB_QUERY_POSIX_FS_INFO
:
2943 vfs_statvfs_struct svfs
;
2945 if (!lp_unix_extensions()) {
2946 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2950 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2954 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2955 SIVAL(pdata
,4,svfs
.BlockSize
);
2956 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2957 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2958 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2959 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2960 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2961 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2962 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2964 } else if (rc
== EOPNOTSUPP
) {
2965 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2967 #endif /* EOPNOTSUPP */
2969 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2970 reply_doserror(req
, ERRSRV
, ERRerror
);
2976 case SMB_QUERY_POSIX_WHOAMI
:
2982 if (!lp_unix_extensions()) {
2983 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2987 if (max_data_bytes
< 40) {
2988 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2992 /* We ARE guest if global_sid_Builtin_Guests is
2993 * in our list of SIDs.
2995 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
2996 current_user
.nt_user_token
)) {
2997 flags
|= SMB_WHOAMI_GUEST
;
3000 /* We are NOT guest if global_sid_Authenticated_Users
3001 * is in our list of SIDs.
3003 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3004 current_user
.nt_user_token
)) {
3005 flags
&= ~SMB_WHOAMI_GUEST
;
3008 /* NOTE: 8 bytes for UID/GID, irrespective of native
3009 * platform size. This matches
3010 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3012 data_len
= 4 /* flags */
3019 + 4 /* pad/reserved */
3020 + (current_user
.ut
.ngroups
* 8)
3022 + (current_user
.nt_user_token
->num_sids
*
3026 SIVAL(pdata
, 0, flags
);
3027 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3028 SBIG_UINT(pdata
, 8, (SMB_BIG_UINT
)current_user
.ut
.uid
);
3029 SBIG_UINT(pdata
, 16, (SMB_BIG_UINT
)current_user
.ut
.gid
);
3032 if (data_len
>= max_data_bytes
) {
3033 /* Potential overflow, skip the GIDs and SIDs. */
3035 SIVAL(pdata
, 24, 0); /* num_groups */
3036 SIVAL(pdata
, 28, 0); /* num_sids */
3037 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3038 SIVAL(pdata
, 36, 0); /* reserved */
3044 SIVAL(pdata
, 24, current_user
.ut
.ngroups
);
3046 current_user
.nt_user_token
->num_sids
);
3048 /* We walk the SID list twice, but this call is fairly
3049 * infrequent, and I don't expect that it's performance
3050 * sensitive -- jpeach
3052 for (i
= 0, sid_bytes
= 0;
3053 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
3054 sid_bytes
+= ndr_size_dom_sid(
3055 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
3058 /* SID list byte count */
3059 SIVAL(pdata
, 32, sid_bytes
);
3061 /* 4 bytes pad/reserved - must be zero */
3062 SIVAL(pdata
, 36, 0);
3066 for (i
= 0; i
< current_user
.ut
.ngroups
; ++i
) {
3067 SBIG_UINT(pdata
, data_len
,
3068 (SMB_BIG_UINT
)current_user
.ut
.groups
[i
]);
3074 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
3075 int sid_len
= ndr_size_dom_sid(
3076 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
3078 sid_linearize(pdata
+ data_len
, sid_len
,
3079 ¤t_user
.nt_user_token
->user_sids
[i
]);
3080 data_len
+= sid_len
;
3086 case SMB_MAC_QUERY_FS_INFO
:
3088 * Thursby MAC extension... ONLY on NTFS filesystems
3089 * once we do streams then we don't need this
3091 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3093 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3098 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3103 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3106 DEBUG( 4, ( "%s info_level = %d\n",
3107 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
3112 /****************************************************************************
3113 Reply to a TRANS2_SETFSINFO (set filesystem info).
3114 ****************************************************************************/
3116 static void call_trans2setfsinfo(connection_struct
*conn
,
3117 struct smb_request
*req
,
3118 char **pparams
, int total_params
,
3119 char **ppdata
, int total_data
,
3120 unsigned int max_data_bytes
)
3122 char *pdata
= *ppdata
;
3123 char *params
= *pparams
;
3126 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3129 if (total_params
< 4) {
3130 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3132 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3136 info_level
= SVAL(params
,2);
3139 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3140 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3141 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3142 "info level (0x%x) on IPC$.\n",
3143 (unsigned int)info_level
));
3144 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3149 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3150 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3151 DEBUG(0,("call_trans2setfsinfo: encryption required "
3152 "and info level 0x%x sent.\n",
3153 (unsigned int)info_level
));
3154 exit_server_cleanly("encryption required "
3160 switch(info_level
) {
3161 case SMB_SET_CIFS_UNIX_INFO
:
3163 uint16 client_unix_major
;
3164 uint16 client_unix_minor
;
3165 uint32 client_unix_cap_low
;
3166 uint32 client_unix_cap_high
;
3168 if (!lp_unix_extensions()) {
3170 NT_STATUS_INVALID_LEVEL
);
3174 /* There should be 12 bytes of capabilities set. */
3175 if (total_data
< 8) {
3178 NT_STATUS_INVALID_PARAMETER
);
3181 client_unix_major
= SVAL(pdata
,0);
3182 client_unix_minor
= SVAL(pdata
,2);
3183 client_unix_cap_low
= IVAL(pdata
,4);
3184 client_unix_cap_high
= IVAL(pdata
,8);
3185 /* Just print these values for now. */
3186 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3187 cap_low = 0x%x, cap_high = 0x%x\n",
3188 (unsigned int)client_unix_major
,
3189 (unsigned int)client_unix_minor
,
3190 (unsigned int)client_unix_cap_low
,
3191 (unsigned int)client_unix_cap_high
));
3193 /* Here is where we must switch to posix pathname processing... */
3194 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3195 lp_set_posix_pathnames();
3196 mangle_change_to_posix();
3199 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3200 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3201 /* Client that knows how to do posix locks,
3202 * but not posix open/mkdir operations. Set a
3203 * default type for read/write checks. */
3205 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3211 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3214 size_t param_len
= 0;
3215 size_t data_len
= total_data
;
3217 if (!lp_unix_extensions()) {
3220 NT_STATUS_INVALID_LEVEL
);
3224 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3227 NT_STATUS_NOT_SUPPORTED
);
3231 DEBUG( 4,("call_trans2setfsinfo: "
3232 "request transport encryption.\n"));
3234 status
= srv_request_encryption_setup(conn
,
3235 (unsigned char **)ppdata
,
3237 (unsigned char **)pparams
,
3240 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3241 !NT_STATUS_IS_OK(status
)) {
3242 reply_nterror(req
, status
);
3246 send_trans2_replies(conn
, req
,
3253 if (NT_STATUS_IS_OK(status
)) {
3254 /* Server-side transport
3255 * encryption is now *on*. */
3256 status
= srv_encryption_start(conn
);
3257 if (!NT_STATUS_IS_OK(status
)) {
3258 exit_server_cleanly(
3259 "Failure in setting "
3260 "up encrypted transport");
3266 case SMB_FS_QUOTA_INFORMATION
:
3268 files_struct
*fsp
= NULL
;
3269 SMB_NTQUOTA_STRUCT quotas
;
3271 ZERO_STRUCT(quotas
);
3274 if ((current_user
.ut
.uid
!= 0)||!CAN_WRITE(conn
)) {
3275 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3276 lp_servicename(SNUM(conn
)),conn
->user
));
3277 reply_doserror(req
, ERRSRV
, ERRaccess
);
3281 /* note: normaly there're 48 bytes,
3282 * but we didn't use the last 6 bytes for now
3285 fsp
= file_fsp(SVAL(params
,0));
3286 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
3287 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3289 req
, NT_STATUS_INVALID_HANDLE
);
3293 if (total_data
< 42) {
3294 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3298 NT_STATUS_INVALID_PARAMETER
);
3302 /* unknown_1 24 NULL bytes in pdata*/
3304 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3305 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3306 #ifdef LARGE_SMB_OFF_T
3307 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3308 #else /* LARGE_SMB_OFF_T */
3309 if ((IVAL(pdata
,28) != 0)&&
3310 ((quotas
.softlim
!= 0xFFFFFFFF)||
3311 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3312 /* more than 32 bits? */
3315 NT_STATUS_INVALID_PARAMETER
);
3318 #endif /* LARGE_SMB_OFF_T */
3320 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3321 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3322 #ifdef LARGE_SMB_OFF_T
3323 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3324 #else /* LARGE_SMB_OFF_T */
3325 if ((IVAL(pdata
,36) != 0)&&
3326 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3327 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3328 /* more than 32 bits? */
3331 NT_STATUS_INVALID_PARAMETER
);
3334 #endif /* LARGE_SMB_OFF_T */
3336 /* quota_flags 2 bytes **/
3337 quotas
.qflags
= SVAL(pdata
,40);
3339 /* unknown_2 6 NULL bytes follow*/
3341 /* now set the quotas */
3342 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3343 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3344 reply_doserror(req
, ERRSRV
, ERRerror
);
3351 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3353 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3359 * sending this reply works fine,
3360 * but I'm not sure it's the same
3361 * like windows do...
3364 reply_outbuf(req
, 10, 0);
3367 #if defined(HAVE_POSIX_ACLS)
3368 /****************************************************************************
3369 Utility function to count the number of entries in a POSIX acl.
3370 ****************************************************************************/
3372 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3374 unsigned int ace_count
= 0;
3375 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3376 SMB_ACL_ENTRY_T entry
;
3378 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3380 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3381 entry_id
= SMB_ACL_NEXT_ENTRY
;
3388 /****************************************************************************
3389 Utility function to marshall a POSIX acl into wire format.
3390 ****************************************************************************/
3392 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3394 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3395 SMB_ACL_ENTRY_T entry
;
3397 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3398 SMB_ACL_TAG_T tagtype
;
3399 SMB_ACL_PERMSET_T permset
;
3400 unsigned char perms
= 0;
3401 unsigned int own_grp
;
3404 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3405 entry_id
= SMB_ACL_NEXT_ENTRY
;
3408 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3409 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3413 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3414 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3418 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3419 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3420 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3422 SCVAL(pdata
,1,perms
);
3425 case SMB_ACL_USER_OBJ
:
3426 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3427 own_grp
= (unsigned int)pst
->st_uid
;
3428 SIVAL(pdata
,2,own_grp
);
3433 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3438 own_grp
= (unsigned int)*puid
;
3439 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3440 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3441 SIVAL(pdata
,2,own_grp
);
3445 case SMB_ACL_GROUP_OBJ
:
3446 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3447 own_grp
= (unsigned int)pst
->st_gid
;
3448 SIVAL(pdata
,2,own_grp
);
3453 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3455 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3458 own_grp
= (unsigned int)*pgid
;
3459 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3460 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3461 SIVAL(pdata
,2,own_grp
);
3466 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3467 SIVAL(pdata
,2,0xFFFFFFFF);
3468 SIVAL(pdata
,6,0xFFFFFFFF);
3471 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3472 SIVAL(pdata
,2,0xFFFFFFFF);
3473 SIVAL(pdata
,6,0xFFFFFFFF);
3476 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3479 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3486 /****************************************************************************
3487 Store the FILE_UNIX_BASIC info.
3488 ****************************************************************************/
3490 static char *store_file_unix_basic(connection_struct
*conn
,
3493 const SMB_STRUCT_STAT
*psbuf
)
3495 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3496 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3498 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3501 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3504 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3505 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3506 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3509 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3513 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3517 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3520 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3524 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3528 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3531 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3535 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3542 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3543 * the chflags(2) (or equivalent) flags.
3545 * XXX: this really should be behind the VFS interface. To do this, we would
3546 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3547 * Each VFS module could then implement its own mapping as appropriate for the
3548 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3550 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3554 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3558 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3562 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3566 { UF_HIDDEN
, EXT_HIDDEN
},
3569 /* Do not remove. We need to guarantee that this array has at least one
3570 * entry to build on HP-UX.
3576 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3577 uint32
*smb_fflags
, uint32
*smb_fmask
)
3579 #ifdef HAVE_STAT_ST_FLAGS
3582 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3583 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3584 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3585 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3588 #endif /* HAVE_STAT_ST_FLAGS */
3591 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3592 const uint32 smb_fflags
,
3593 const uint32 smb_fmask
,
3596 #ifdef HAVE_STAT_ST_FLAGS
3597 uint32 max_fmask
= 0;
3600 *stat_fflags
= psbuf
->st_flags
;
3602 /* For each flags requested in smb_fmask, check the state of the
3603 * corresponding flag in smb_fflags and set or clear the matching
3607 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3608 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3609 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3610 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3611 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3613 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3618 /* If smb_fmask is asking to set any bits that are not supported by
3619 * our flag mappings, we should fail.
3621 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3628 #endif /* HAVE_STAT_ST_FLAGS */
3632 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3633 * of file flags and birth (create) time.
3635 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3638 const SMB_STRUCT_STAT
*psbuf
)
3640 uint32 file_flags
= 0;
3641 uint32 flags_mask
= 0;
3643 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3645 /* Create (birth) time 64 bit */
3646 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3649 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3650 SIVAL(pdata
, 0, file_flags
); /* flags */
3651 SIVAL(pdata
, 4, flags_mask
); /* mask */
3657 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3658 const struct stream_struct
*streams
,
3660 unsigned int max_data_bytes
,
3661 unsigned int *data_size
)
3664 unsigned int ofs
= 0;
3666 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3667 unsigned int next_offset
;
3669 smb_ucs2_t
*namebuf
;
3671 namelen
= push_ucs2_talloc(talloc_tos(), &namebuf
,
3674 if ((namelen
== (size_t)-1) || (namelen
<= 2)) {
3675 return NT_STATUS_INVALID_PARAMETER
;
3679 * name_buf is now null-terminated, we need to marshall as not
3685 SIVAL(data
, ofs
+4, namelen
);
3686 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3687 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3688 memcpy(data
+ofs
+24, namebuf
, namelen
);
3689 TALLOC_FREE(namebuf
);
3691 next_offset
= ofs
+ 24 + namelen
;
3693 if (i
== num_streams
-1) {
3694 SIVAL(data
, ofs
, 0);
3697 unsigned int align
= ndr_align_size(next_offset
, 8);
3699 memset(data
+next_offset
, 0, align
);
3700 next_offset
+= align
;
3702 SIVAL(data
, ofs
, next_offset
- ofs
);
3711 return NT_STATUS_OK
;
3714 /****************************************************************************
3715 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3716 ****************************************************************************/
3718 static void call_trans2qpipeinfo(connection_struct
*conn
,
3719 struct smb_request
*req
,
3720 unsigned int tran_call
,
3721 char **pparams
, int total_params
,
3722 char **ppdata
, int total_data
,
3723 unsigned int max_data_bytes
)
3725 char *params
= *pparams
;
3726 char *pdata
= *ppdata
;
3727 unsigned int data_size
= 0;
3728 unsigned int param_size
= 2;
3730 smb_np_struct
*p_pipe
= NULL
;
3733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3737 if (total_params
< 4) {
3738 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3742 p_pipe
= get_rpc_pipe_p(SVAL(params
,0));
3743 if (p_pipe
== NULL
) {
3744 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3748 info_level
= SVAL(params
,2);
3750 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3751 if (*pparams
== NULL
) {
3752 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3757 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3758 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3759 if (*ppdata
== NULL
) {
3760 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3765 switch (info_level
) {
3766 case SMB_FILE_STANDARD_INFORMATION
:
3768 SOFF_T(pdata
,0,4096LL);
3775 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3779 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3785 /****************************************************************************
3786 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3787 file name or file id).
3788 ****************************************************************************/
3790 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3791 struct smb_request
*req
,
3792 unsigned int tran_call
,
3793 char **pparams
, int total_params
,
3794 char **ppdata
, int total_data
,
3795 unsigned int max_data_bytes
)
3797 char *params
= *pparams
;
3798 char *pdata
= *ppdata
;
3799 char *dstart
, *dend
;
3803 SMB_OFF_T file_size
=0;
3804 SMB_BIG_UINT allocation_size
=0;
3805 unsigned int data_size
= 0;
3806 unsigned int param_size
= 2;
3807 SMB_STRUCT_STAT sbuf
;
3808 char *dos_fname
= NULL
;
3814 bool delete_pending
= False
;
3816 time_t create_time
, mtime
, atime
;
3817 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3818 struct timespec write_time_ts
;
3819 files_struct
*fsp
= NULL
;
3820 struct file_id fileid
;
3821 struct ea_list
*ea_list
= NULL
;
3822 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3823 char *lock_data
= NULL
;
3824 bool ms_dfs_link
= false;
3825 TALLOC_CTX
*ctx
= talloc_tos();
3828 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3833 ZERO_STRUCT(write_time_ts
);
3835 if (tran_call
== TRANSACT2_QFILEINFO
) {
3836 if (total_params
< 4) {
3837 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3842 call_trans2qpipeinfo(conn
, req
, tran_call
,
3843 pparams
, total_params
,
3849 fsp
= file_fsp(SVAL(params
,0));
3850 info_level
= SVAL(params
,2);
3852 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3854 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3855 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3859 /* Initial check for valid fsp ptr. */
3860 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
3864 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3866 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3870 if(fsp
->fake_file_handle
) {
3872 * This is actually for the QUOTA_FAKE_FILE --metze
3875 /* We know this name is ok, it's already passed the checks. */
3877 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3879 * This is actually a QFILEINFO on a directory
3880 * handle (returned from an NT SMB). NT5.0 seems
3881 * to do this call. JRA.
3884 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3885 /* Always do lstat for UNIX calls. */
3886 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3887 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3888 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3891 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3892 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3893 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3897 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3898 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3901 * Original code - this is an open file.
3903 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3907 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3908 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3909 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3912 pos
= fsp
->fh
->position_information
;
3913 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3914 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3915 access_mask
= fsp
->access_mask
;
3919 NTSTATUS status
= NT_STATUS_OK
;
3922 if (total_params
< 7) {
3923 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3927 info_level
= SVAL(params
,0);
3929 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3931 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3932 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3936 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3938 STR_TERMINATE
, &status
);
3939 if (!NT_STATUS_IS_OK(status
)) {
3940 reply_nterror(req
, status
);
3944 status
= resolve_dfspath(ctx
,
3946 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3949 if (!NT_STATUS_IS_OK(status
)) {
3950 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3951 reply_botherror(req
,
3952 NT_STATUS_PATH_NOT_COVERED
,
3953 ERRSRV
, ERRbadpath
);
3955 reply_nterror(req
, status
);
3959 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3960 if (!NT_STATUS_IS_OK(status
)) {
3961 reply_nterror(req
, status
);
3964 status
= check_name(conn
, fname
);
3965 if (!NT_STATUS_IS_OK(status
)) {
3966 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3967 reply_nterror(req
, status
);
3971 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
3972 && is_ntfs_stream_name(fname
)) {
3974 SMB_STRUCT_STAT bsbuf
;
3976 status
= split_ntfs_stream_name(talloc_tos(), fname
,
3978 if (!NT_STATUS_IS_OK(status
)) {
3979 DEBUG(10, ("create_file_unixpath: "
3980 "split_ntfs_stream_name failed: %s\n",
3981 nt_errstr(status
)));
3982 reply_nterror(req
, status
);
3986 SMB_ASSERT(!is_ntfs_stream_name(base
)); /* paranoia.. */
3988 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3989 /* Always do lstat for UNIX calls. */
3990 if (SMB_VFS_LSTAT(conn
,base
,&bsbuf
)) {
3991 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base
,strerror(errno
)));
3992 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3996 if (SMB_VFS_STAT(conn
,base
,&bsbuf
) != 0) {
3997 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base
,strerror(errno
)));
3998 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4003 fileid
= vfs_file_id_from_sbuf(conn
, &bsbuf
);
4004 get_file_infos(fileid
, &delete_pending
, NULL
);
4005 if (delete_pending
) {
4006 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4011 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4012 /* Always do lstat for UNIX calls. */
4013 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4015 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4019 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4020 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4023 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4024 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4029 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4030 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4031 if (delete_pending
) {
4032 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4037 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4038 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4042 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4043 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4045 p
= strrchr_m(fname
,'/');
4052 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4054 mode
= dos_mode(conn
,fname
,&sbuf
);
4057 mode
= FILE_ATTRIBUTE_NORMAL
;
4059 nlink
= sbuf
.st_nlink
;
4061 if (nlink
&& (mode
&aDIR
)) {
4065 if ((nlink
> 0) && delete_pending
) {
4069 fullpathname
= fname
;
4071 file_size
= get_file_size(sbuf
);
4073 /* Pull out any data sent here before we realloc. */
4074 switch (info_level
) {
4075 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4077 /* Pull any EA list from the data portion. */
4080 if (total_data
< 4) {
4082 req
, NT_STATUS_INVALID_PARAMETER
);
4085 ea_size
= IVAL(pdata
,0);
4087 if (total_data
> 0 && ea_size
!= total_data
) {
4088 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4089 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4091 req
, NT_STATUS_INVALID_PARAMETER
);
4095 if (!lp_ea_support(SNUM(conn
))) {
4096 reply_doserror(req
, ERRDOS
,
4097 ERReasnotsupported
);
4101 /* Pull out the list of names. */
4102 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4105 req
, NT_STATUS_INVALID_PARAMETER
);
4111 case SMB_QUERY_POSIX_LOCK
:
4113 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4114 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4118 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4120 req
, NT_STATUS_INVALID_PARAMETER
);
4124 /* Copy the lock range data. */
4125 lock_data
= (char *)TALLOC_MEMDUP(
4126 ctx
, pdata
, total_data
);
4128 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4136 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4137 if (*pparams
== NULL
) {
4138 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4143 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4144 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4145 if (*ppdata
== NULL
) {
4146 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4151 dend
= dstart
+ data_size
- 1;
4153 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4154 mtime_ts
= get_mtimespec(&sbuf
);
4155 atime_ts
= get_atimespec(&sbuf
);
4157 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
4160 /* Do we have this path open ? */
4162 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4163 fsp1
= file_find_di_first(fileid
);
4164 if (fsp1
&& fsp1
->initial_allocation_size
) {
4165 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
4169 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4170 mtime_ts
= write_time_ts
;
4173 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4174 dos_filetime_timespec(&create_time_ts
);
4175 dos_filetime_timespec(&mtime_ts
);
4176 dos_filetime_timespec(&atime_ts
);
4179 create_time
= convert_timespec_to_time_t(create_time_ts
);
4180 mtime
= convert_timespec_to_time_t(mtime_ts
);
4181 atime
= convert_timespec_to_time_t(atime_ts
);
4183 /* NT expects the name to be in an exact form of the *full*
4184 filename. See the trans2 torture test */
4185 if (ISDOT(base_name
)) {
4186 dos_fname
= talloc_strdup(ctx
, "\\");
4188 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4192 dos_fname
= talloc_asprintf(ctx
,
4196 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4199 string_replace(dos_fname
, '/', '\\');
4202 switch (info_level
) {
4203 case SMB_INFO_STANDARD
:
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4206 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4207 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4208 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4209 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4210 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4211 SSVAL(pdata
,l1_attrFile
,mode
);
4214 case SMB_INFO_QUERY_EA_SIZE
:
4216 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4219 srv_put_dos_date2(pdata
,0,create_time
);
4220 srv_put_dos_date2(pdata
,4,atime
);
4221 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4222 SIVAL(pdata
,12,(uint32
)file_size
);
4223 SIVAL(pdata
,16,(uint32
)allocation_size
);
4224 SSVAL(pdata
,20,mode
);
4225 SIVAL(pdata
,22,ea_size
);
4229 case SMB_INFO_IS_NAME_VALID
:
4230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4231 if (tran_call
== TRANSACT2_QFILEINFO
) {
4232 /* os/2 needs this ? really ?*/
4233 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4240 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4242 size_t total_ea_len
= 0;
4243 struct ea_list
*ea_file_list
= NULL
;
4245 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4247 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4248 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4250 if (!ea_list
|| (total_ea_len
> data_size
)) {
4252 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4256 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4260 case SMB_INFO_QUERY_ALL_EAS
:
4262 /* We have data_size bytes to put EA's into. */
4263 size_t total_ea_len
= 0;
4265 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4267 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4268 if (!ea_list
|| (total_ea_len
> data_size
)) {
4270 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4274 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4278 case SMB_FILE_BASIC_INFORMATION
:
4279 case SMB_QUERY_FILE_BASIC_INFO
:
4281 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4282 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4283 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4285 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4289 put_long_date_timespec(pdata
,create_time_ts
);
4290 put_long_date_timespec(pdata
+8,atime_ts
);
4291 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4292 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4293 SIVAL(pdata
,32,mode
);
4295 DEBUG(5,("SMB_QFBI - "));
4296 DEBUG(5,("create: %s ", ctime(&create_time
)));
4297 DEBUG(5,("access: %s ", ctime(&atime
)));
4298 DEBUG(5,("write: %s ", ctime(&mtime
)));
4299 DEBUG(5,("change: %s ", ctime(&mtime
)));
4300 DEBUG(5,("mode: %x\n", mode
));
4303 case SMB_FILE_STANDARD_INFORMATION
:
4304 case SMB_QUERY_FILE_STANDARD_INFO
:
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4308 SOFF_T(pdata
,0,allocation_size
);
4309 SOFF_T(pdata
,8,file_size
);
4310 SIVAL(pdata
,16,nlink
);
4311 SCVAL(pdata
,20,delete_pending
?1:0);
4312 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4313 SSVAL(pdata
,22,0); /* Padding. */
4316 case SMB_FILE_EA_INFORMATION
:
4317 case SMB_QUERY_FILE_EA_INFO
:
4319 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4320 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4322 SIVAL(pdata
,0,ea_size
);
4326 /* Get the 8.3 name - used if NT SMB was negotiated. */
4327 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4328 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4330 char mangled_name
[13];
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4332 if (!name_to_8_3(base_name
,mangled_name
,
4333 True
,conn
->params
)) {
4336 NT_STATUS_NO_MEMORY
);
4338 len
= srvstr_push(dstart
, req
->flags2
,
4339 pdata
+4, mangled_name
,
4340 PTR_DIFF(dend
, pdata
+4),
4342 data_size
= 4 + len
;
4347 case SMB_QUERY_FILE_NAME_INFO
:
4349 this must be *exactly* right for ACLs on mapped drives to work
4351 len
= srvstr_push(dstart
, req
->flags2
,
4353 PTR_DIFF(dend
, pdata
+4),
4355 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4356 data_size
= 4 + len
;
4360 case SMB_FILE_ALLOCATION_INFORMATION
:
4361 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4364 SOFF_T(pdata
,0,allocation_size
);
4367 case SMB_FILE_END_OF_FILE_INFORMATION
:
4368 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4371 SOFF_T(pdata
,0,file_size
);
4374 case SMB_QUERY_FILE_ALL_INFO
:
4375 case SMB_FILE_ALL_INFORMATION
:
4377 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4379 put_long_date_timespec(pdata
,create_time_ts
);
4380 put_long_date_timespec(pdata
+8,atime_ts
);
4381 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4382 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4383 SIVAL(pdata
,32,mode
);
4384 SIVAL(pdata
,36,0); /* padding. */
4386 SOFF_T(pdata
,0,allocation_size
);
4387 SOFF_T(pdata
,8,file_size
);
4388 SIVAL(pdata
,16,nlink
);
4389 SCVAL(pdata
,20,delete_pending
);
4390 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4393 SIVAL(pdata
,0,ea_size
);
4394 pdata
+= 4; /* EA info */
4395 len
= srvstr_push(dstart
, req
->flags2
,
4397 PTR_DIFF(dend
, pdata
+4),
4401 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4404 case SMB_FILE_INTERNAL_INFORMATION
:
4405 /* This should be an index number - looks like
4408 I think this causes us to fail the IFSKIT
4409 BasicFileInformationTest. -tpot */
4411 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4412 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4413 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4417 case SMB_FILE_ACCESS_INFORMATION
:
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4419 SIVAL(pdata
,0,access_mask
);
4423 case SMB_FILE_NAME_INFORMATION
:
4424 /* Pathname with leading '\'. */
4427 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4428 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4429 SIVAL(pdata
,0,byte_len
);
4430 data_size
= 4 + byte_len
;
4434 case SMB_FILE_DISPOSITION_INFORMATION
:
4435 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4437 SCVAL(pdata
,0,delete_pending
);
4440 case SMB_FILE_POSITION_INFORMATION
:
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4443 SOFF_T(pdata
,0,pos
);
4446 case SMB_FILE_MODE_INFORMATION
:
4447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4448 SIVAL(pdata
,0,mode
);
4452 case SMB_FILE_ALIGNMENT_INFORMATION
:
4453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4454 SIVAL(pdata
,0,0); /* No alignment needed. */
4459 * NT4 server just returns "invalid query" to this - if we try
4460 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4463 /* The first statement above is false - verified using Thursby
4464 * client against NT4 -- gcolley.
4466 case SMB_QUERY_FILE_STREAM_INFO
:
4467 case SMB_FILE_STREAM_INFORMATION
: {
4468 unsigned int num_streams
;
4469 struct stream_struct
*streams
;
4472 DEBUG(10,("call_trans2qfilepathinfo: "
4473 "SMB_FILE_STREAM_INFORMATION\n"));
4475 status
= SMB_VFS_STREAMINFO(
4476 conn
, fsp
, fname
, talloc_tos(),
4477 &num_streams
, &streams
);
4479 if (!NT_STATUS_IS_OK(status
)) {
4480 DEBUG(10, ("could not get stream info: %s\n",
4481 nt_errstr(status
)));
4482 reply_nterror(req
, status
);
4486 status
= marshall_stream_info(num_streams
, streams
,
4487 pdata
, max_data_bytes
,
4490 if (!NT_STATUS_IS_OK(status
)) {
4491 DEBUG(10, ("marshall_stream_info failed: %s\n",
4492 nt_errstr(status
)));
4493 reply_nterror(req
, status
);
4497 TALLOC_FREE(streams
);
4501 case SMB_QUERY_COMPRESSION_INFO
:
4502 case SMB_FILE_COMPRESSION_INFORMATION
:
4503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4504 SOFF_T(pdata
,0,file_size
);
4505 SIVAL(pdata
,8,0); /* ??? */
4506 SIVAL(pdata
,12,0); /* ??? */
4510 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4511 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4512 put_long_date_timespec(pdata
,create_time_ts
);
4513 put_long_date_timespec(pdata
+8,atime_ts
);
4514 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4515 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4516 SOFF_T(pdata
,32,allocation_size
);
4517 SOFF_T(pdata
,40,file_size
);
4518 SIVAL(pdata
,48,mode
);
4519 SIVAL(pdata
,52,0); /* ??? */
4523 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4524 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4525 SIVAL(pdata
,0,mode
);
4531 * CIFS UNIX Extensions.
4534 case SMB_QUERY_FILE_UNIX_BASIC
:
4536 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4537 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4541 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4543 for (i
=0; i
<100; i
++)
4544 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4550 case SMB_QUERY_FILE_UNIX_INFO2
:
4552 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4553 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4557 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4559 for (i
=0; i
<100; i
++)
4560 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4566 case SMB_QUERY_FILE_UNIX_LINK
:
4568 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4571 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4575 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4577 if(!S_ISLNK(sbuf
.st_mode
)) {
4578 reply_unixerror(req
, ERRSRV
,
4583 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4586 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4589 reply_unixerror(req
, ERRDOS
,
4594 len
= srvstr_push(dstart
, req
->flags2
,
4596 PTR_DIFF(dend
, pdata
),
4599 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4604 #if defined(HAVE_POSIX_ACLS)
4605 case SMB_QUERY_POSIX_ACL
:
4607 SMB_ACL_T file_acl
= NULL
;
4608 SMB_ACL_T def_acl
= NULL
;
4609 uint16 num_file_acls
= 0;
4610 uint16 num_def_acls
= 0;
4612 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4613 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4615 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4618 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4619 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4623 NT_STATUS_NOT_IMPLEMENTED
);
4627 if (S_ISDIR(sbuf
.st_mode
)) {
4628 if (fsp
&& fsp
->is_directory
) {
4629 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4631 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4633 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4636 num_file_acls
= count_acl_entries(conn
, file_acl
);
4637 num_def_acls
= count_acl_entries(conn
, def_acl
);
4639 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4640 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4642 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4643 SMB_POSIX_ACL_HEADER_SIZE
) ));
4645 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4648 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4652 NT_STATUS_BUFFER_TOO_SMALL
);
4656 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4657 SSVAL(pdata
,2,num_file_acls
);
4658 SSVAL(pdata
,4,num_def_acls
);
4659 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4661 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4667 req
, NT_STATUS_INTERNAL_ERROR
);
4670 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4672 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4675 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4679 NT_STATUS_INTERNAL_ERROR
);
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4689 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4695 case SMB_QUERY_POSIX_LOCK
:
4697 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4699 SMB_BIG_UINT offset
;
4701 enum brl_type lock_type
;
4703 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4705 req
, NT_STATUS_INVALID_PARAMETER
);
4709 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4710 case POSIX_LOCK_TYPE_READ
:
4711 lock_type
= READ_LOCK
;
4713 case POSIX_LOCK_TYPE_WRITE
:
4714 lock_type
= WRITE_LOCK
;
4716 case POSIX_LOCK_TYPE_UNLOCK
:
4718 /* There's no point in asking for an unlock... */
4721 NT_STATUS_INVALID_PARAMETER
);
4725 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4726 #if defined(HAVE_LONGLONG)
4727 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4728 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4729 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4730 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4731 #else /* HAVE_LONGLONG */
4732 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4733 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4734 #endif /* HAVE_LONGLONG */
4736 status
= query_lock(fsp
,
4743 if (ERROR_WAS_LOCK_DENIED(status
)) {
4744 /* Here we need to report who has it locked... */
4745 data_size
= POSIX_LOCK_DATA_SIZE
;
4747 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4748 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4749 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4750 #if defined(HAVE_LONGLONG)
4751 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4752 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4753 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4754 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4755 #else /* HAVE_LONGLONG */
4756 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4757 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4758 #endif /* HAVE_LONGLONG */
4760 } else if (NT_STATUS_IS_OK(status
)) {
4761 /* For success we just return a copy of what we sent
4762 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4763 data_size
= POSIX_LOCK_DATA_SIZE
;
4764 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4765 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4767 reply_nterror(req
, status
);
4774 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4778 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4784 /****************************************************************************
4785 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4787 ****************************************************************************/
4789 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4790 connection_struct
*conn
,
4791 const char *oldname_in
,
4792 const char *newname_in
)
4794 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4795 char *last_component_oldname
= NULL
;
4796 char *last_component_newname
= NULL
;
4797 char *oldname
= NULL
;
4798 char *newname
= NULL
;
4799 NTSTATUS status
= NT_STATUS_OK
;
4804 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4805 &last_component_oldname
, &sbuf1
);
4806 if (!NT_STATUS_IS_OK(status
)) {
4810 status
= check_name(conn
, oldname
);
4811 if (!NT_STATUS_IS_OK(status
)) {
4815 /* source must already exist. */
4816 if (!VALID_STAT(sbuf1
)) {
4817 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4820 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4821 &last_component_newname
, &sbuf2
);
4822 if (!NT_STATUS_IS_OK(status
)) {
4826 status
= check_name(conn
, newname
);
4827 if (!NT_STATUS_IS_OK(status
)) {
4831 /* Disallow if newname already exists. */
4832 if (VALID_STAT(sbuf2
)) {
4833 return NT_STATUS_OBJECT_NAME_COLLISION
;
4836 /* No links from a directory. */
4837 if (S_ISDIR(sbuf1
.st_mode
)) {
4838 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4841 /* Ensure this is within the share. */
4842 status
= check_reduced_name(conn
, oldname
);
4843 if (!NT_STATUS_IS_OK(status
)) {
4847 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4849 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4850 status
= map_nt_error_from_unix(errno
);
4851 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4852 nt_errstr(status
), newname
, oldname
));
4858 /****************************************************************************
4859 Deal with setting the time from any of the setfilepathinfo functions.
4860 ****************************************************************************/
4862 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4865 const SMB_STRUCT_STAT
*psbuf
,
4866 struct timespec ts
[2],
4867 bool setting_write_time
)
4870 FILE_NOTIFY_CHANGE_LAST_ACCESS
4871 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4873 if (!VALID_STAT(*psbuf
)) {
4874 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4877 /* get some defaults (no modifications) if any info is zero or -1. */
4878 if (null_timespec(ts
[0])) {
4879 ts
[0] = get_atimespec(psbuf
);
4880 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4883 if (null_timespec(ts
[1])) {
4884 ts
[1] = get_mtimespec(psbuf
);
4885 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4888 if (!setting_write_time
) {
4889 /* ts[1] comes from change time, not write time. */
4890 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4893 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4894 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4897 * Try and set the times of this file if
4898 * they are different from the current values.
4902 struct timespec mts
= get_mtimespec(psbuf
);
4903 struct timespec ats
= get_atimespec(psbuf
);
4904 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4905 return NT_STATUS_OK
;
4909 if (setting_write_time
) {
4911 * This was a setfileinfo on an open file.
4912 * NT does this a lot. We also need to
4913 * set the time here, as it can be read by
4914 * FindFirst/FindNext and with the patch for bug #2045
4915 * in smbd/fileio.c it ensures that this timestamp is
4916 * kept sticky even after a write. We save the request
4917 * away and will set it on file close and after a write. JRA.
4920 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4921 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4924 if (fsp
->base_fsp
) {
4925 set_sticky_write_time_fsp(fsp
->base_fsp
, ts
[1]);
4927 set_sticky_write_time_fsp(fsp
, ts
[1]);
4930 set_sticky_write_time_path(conn
, fname
,
4931 vfs_file_id_from_sbuf(conn
, psbuf
),
4936 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4938 if (fsp
&& fsp
->base_fsp
) {
4939 fname
= fsp
->base_fsp
->fsp_name
;
4942 if(file_ntimes(conn
, fname
, ts
)!=0) {
4943 return map_nt_error_from_unix(errno
);
4945 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4947 return NT_STATUS_OK
;
4950 /****************************************************************************
4951 Deal with setting the dosmode from any of the setfilepathinfo functions.
4952 ****************************************************************************/
4954 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4957 SMB_STRUCT_STAT
*psbuf
,
4960 if (!VALID_STAT(*psbuf
)) {
4961 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4965 if (fsp
->base_fsp
) {
4966 fname
= fsp
->base_fsp
->fsp_name
;
4968 fname
= fsp
->fsp_name
;
4973 if (S_ISDIR(psbuf
->st_mode
)) {
4980 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
4982 /* check the mode isn't different, before changing it */
4983 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
4985 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4986 fname
, (unsigned int)dosmode
));
4988 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
4989 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4990 fname
, strerror(errno
)));
4991 return map_nt_error_from_unix(errno
);
4994 return NT_STATUS_OK
;
4997 /****************************************************************************
4998 Deal with setting the size from any of the setfilepathinfo functions.
4999 ****************************************************************************/
5001 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5002 struct smb_request
*req
,
5005 SMB_STRUCT_STAT
*psbuf
,
5008 NTSTATUS status
= NT_STATUS_OK
;
5009 files_struct
*new_fsp
= NULL
;
5011 if (!VALID_STAT(*psbuf
)) {
5012 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5015 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5017 if (size
== get_file_size(*psbuf
)) {
5018 return NT_STATUS_OK
;
5021 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5022 fname
, (double)size
));
5024 if (fsp
&& fsp
->fh
->fd
!= -1) {
5025 /* Handle based call. */
5026 if (vfs_set_filelen(fsp
, size
) == -1) {
5027 return map_nt_error_from_unix(errno
);
5029 trigger_write_time_update_immediate(fsp
);
5030 return NT_STATUS_OK
;
5033 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5034 FILE_WRITE_ATTRIBUTES
,
5035 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5038 FILE_ATTRIBUTE_NORMAL
,
5039 FORCE_OPLOCK_BREAK_TO_NONE
,
5042 if (!NT_STATUS_IS_OK(status
)) {
5043 /* NB. We check for open_was_deferred in the caller. */
5047 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5048 status
= map_nt_error_from_unix(errno
);
5049 close_file(new_fsp
,NORMAL_CLOSE
);
5053 trigger_write_time_update_immediate(new_fsp
);
5054 close_file(new_fsp
,NORMAL_CLOSE
);
5055 return NT_STATUS_OK
;
5058 /****************************************************************************
5059 Deal with SMB_INFO_SET_EA.
5060 ****************************************************************************/
5062 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5068 struct ea_list
*ea_list
= NULL
;
5069 TALLOC_CTX
*ctx
= NULL
;
5070 NTSTATUS status
= NT_STATUS_OK
;
5072 if (total_data
< 10) {
5074 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5075 length. They seem to have no effect. Bug #3212. JRA */
5077 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5078 /* We're done. We only get EA info in this call. */
5079 return NT_STATUS_OK
;
5082 return NT_STATUS_INVALID_PARAMETER
;
5085 if (IVAL(pdata
,0) > total_data
) {
5086 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5087 IVAL(pdata
,0), (unsigned int)total_data
));
5088 return NT_STATUS_INVALID_PARAMETER
;
5092 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5094 return NT_STATUS_INVALID_PARAMETER
;
5096 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5101 /****************************************************************************
5102 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5103 ****************************************************************************/
5105 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5110 SMB_STRUCT_STAT
*psbuf
)
5112 NTSTATUS status
= NT_STATUS_OK
;
5113 bool delete_on_close
;
5116 if (total_data
< 1) {
5117 return NT_STATUS_INVALID_PARAMETER
;
5121 return NT_STATUS_INVALID_HANDLE
;
5124 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5125 dosmode
= dos_mode(conn
, fname
, psbuf
);
5127 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5128 "delete_on_close = %u\n",
5130 (unsigned int)dosmode
,
5131 (unsigned int)delete_on_close
));
5133 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5135 if (!NT_STATUS_IS_OK(status
)) {
5139 /* The set is across all open files on this dev/inode pair. */
5140 if (!set_delete_on_close(fsp
, delete_on_close
, ¤t_user
.ut
)) {
5141 return NT_STATUS_ACCESS_DENIED
;
5143 return NT_STATUS_OK
;
5146 /****************************************************************************
5147 Deal with SMB_FILE_POSITION_INFORMATION.
5148 ****************************************************************************/
5150 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5155 SMB_BIG_UINT position_information
;
5157 if (total_data
< 8) {
5158 return NT_STATUS_INVALID_PARAMETER
;
5162 /* Ignore on pathname based set. */
5163 return NT_STATUS_OK
;
5166 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5167 #ifdef LARGE_SMB_OFF_T
5168 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5169 #else /* LARGE_SMB_OFF_T */
5170 if (IVAL(pdata
,4) != 0) {
5171 /* more than 32 bits? */
5172 return NT_STATUS_INVALID_PARAMETER
;
5174 #endif /* LARGE_SMB_OFF_T */
5176 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5177 fsp
->fsp_name
, (double)position_information
));
5178 fsp
->fh
->position_information
= position_information
;
5179 return NT_STATUS_OK
;
5182 /****************************************************************************
5183 Deal with SMB_FILE_MODE_INFORMATION.
5184 ****************************************************************************/
5186 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5192 if (total_data
< 4) {
5193 return NT_STATUS_INVALID_PARAMETER
;
5195 mode
= IVAL(pdata
,0);
5196 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5197 return NT_STATUS_INVALID_PARAMETER
;
5199 return NT_STATUS_OK
;
5202 /****************************************************************************
5203 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5204 ****************************************************************************/
5206 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5207 struct smb_request
*req
,
5212 char *link_target
= NULL
;
5213 const char *newname
= fname
;
5214 NTSTATUS status
= NT_STATUS_OK
;
5215 TALLOC_CTX
*ctx
= talloc_tos();
5217 /* Set a symbolic link. */
5218 /* Don't allow this if follow links is false. */
5220 if (total_data
== 0) {
5221 return NT_STATUS_INVALID_PARAMETER
;
5224 if (!lp_symlinks(SNUM(conn
))) {
5225 return NT_STATUS_ACCESS_DENIED
;
5228 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5229 total_data
, STR_TERMINATE
);
5232 return NT_STATUS_INVALID_PARAMETER
;
5235 /* !widelinks forces the target path to be within the share. */
5236 /* This means we can interpret the target as a pathname. */
5237 if (!lp_widelinks(SNUM(conn
))) {
5238 char *rel_name
= NULL
;
5239 char *last_dirp
= NULL
;
5241 if (*link_target
== '/') {
5242 /* No absolute paths allowed. */
5243 return NT_STATUS_ACCESS_DENIED
;
5245 rel_name
= talloc_strdup(ctx
,newname
);
5247 return NT_STATUS_NO_MEMORY
;
5249 last_dirp
= strrchr_m(rel_name
, '/');
5251 last_dirp
[1] = '\0';
5253 rel_name
= talloc_strdup(ctx
,"./");
5255 return NT_STATUS_NO_MEMORY
;
5258 rel_name
= talloc_asprintf_append(rel_name
,
5262 return NT_STATUS_NO_MEMORY
;
5265 status
= check_name(conn
, rel_name
);
5266 if (!NT_STATUS_IS_OK(status
)) {
5271 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5272 newname
, link_target
));
5274 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5275 return map_nt_error_from_unix(errno
);
5278 return NT_STATUS_OK
;
5281 /****************************************************************************
5282 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5283 ****************************************************************************/
5285 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5286 struct smb_request
*req
,
5287 const char *pdata
, int total_data
,
5290 char *oldname
= NULL
;
5291 TALLOC_CTX
*ctx
= talloc_tos();
5292 NTSTATUS status
= NT_STATUS_OK
;
5294 /* Set a hard link. */
5295 if (total_data
== 0) {
5296 return NT_STATUS_INVALID_PARAMETER
;
5299 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5300 total_data
, STR_TERMINATE
, &status
);
5301 if (!NT_STATUS_IS_OK(status
)) {
5305 status
= resolve_dfspath(ctx
, conn
,
5306 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5309 if (!NT_STATUS_IS_OK(status
)) {
5313 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5316 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5319 /****************************************************************************
5320 Deal with SMB_FILE_RENAME_INFORMATION.
5321 ****************************************************************************/
5323 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5324 struct smb_request
*req
,
5333 char *newname
= NULL
;
5334 char *base_name
= NULL
;
5335 bool dest_has_wcard
= False
;
5336 SMB_STRUCT_STAT sbuf
;
5337 char *newname_last_component
= NULL
;
5338 NTSTATUS status
= NT_STATUS_OK
;
5340 TALLOC_CTX
*ctx
= talloc_tos();
5342 if (total_data
< 13) {
5343 return NT_STATUS_INVALID_PARAMETER
;
5348 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5349 root_fid
= IVAL(pdata
,4);
5350 len
= IVAL(pdata
,8);
5352 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5353 return NT_STATUS_INVALID_PARAMETER
;
5356 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5359 if (!NT_STATUS_IS_OK(status
)) {
5363 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5366 status
= resolve_dfspath_wcard(ctx
, conn
,
5367 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5371 if (!NT_STATUS_IS_OK(status
)) {
5375 /* Check the new name has no '/' characters. */
5376 if (strchr_m(newname
, '/')) {
5377 return NT_STATUS_NOT_SUPPORTED
;
5380 if (fsp
&& fsp
->base_fsp
) {
5381 /* newname must be a stream name. */
5382 if (newname
[0] != ':') {
5383 return NT_STATUS_NOT_SUPPORTED
;
5385 base_name
= talloc_asprintf(ctx
, "%s%s",
5386 fsp
->base_fsp
->fsp_name
,
5389 return NT_STATUS_NO_MEMORY
;
5392 /* newname must *not* be a stream name. */
5393 if (is_ntfs_stream_name(newname
)) {
5394 return NT_STATUS_NOT_SUPPORTED
;
5397 /* Create the base directory. */
5398 base_name
= talloc_strdup(ctx
, fname
);
5400 return NT_STATUS_NO_MEMORY
;
5402 p
= strrchr_m(base_name
, '/');
5406 base_name
= talloc_strdup(ctx
, "./");
5408 return NT_STATUS_NO_MEMORY
;
5411 /* Append the new name. */
5412 base_name
= talloc_asprintf_append(base_name
,
5416 return NT_STATUS_NO_MEMORY
;
5419 status
= unix_convert(ctx
, conn
, newname
, False
,
5421 &newname_last_component
,
5424 /* If an error we expect this to be
5425 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5427 if (!NT_STATUS_IS_OK(status
)
5428 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5435 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5436 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5437 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5438 newname_last_component
, 0,
5441 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5442 fname
, base_name
));
5443 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5444 overwrite
, False
, dest_has_wcard
,
5445 FILE_WRITE_ATTRIBUTES
);
5451 /****************************************************************************
5452 Deal with SMB_SET_POSIX_ACL.
5453 ****************************************************************************/
5455 #if defined(HAVE_POSIX_ACLS)
5456 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5461 SMB_STRUCT_STAT
*psbuf
)
5463 uint16 posix_acl_version
;
5464 uint16 num_file_acls
;
5465 uint16 num_def_acls
;
5466 bool valid_file_acls
= True
;
5467 bool valid_def_acls
= True
;
5469 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5470 return NT_STATUS_INVALID_PARAMETER
;
5472 posix_acl_version
= SVAL(pdata
,0);
5473 num_file_acls
= SVAL(pdata
,2);
5474 num_def_acls
= SVAL(pdata
,4);
5476 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5477 valid_file_acls
= False
;
5481 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5482 valid_def_acls
= False
;
5486 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5487 return NT_STATUS_INVALID_PARAMETER
;
5490 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5491 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5492 return NT_STATUS_INVALID_PARAMETER
;
5495 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5496 fname
? fname
: fsp
->fsp_name
,
5497 (unsigned int)num_file_acls
,
5498 (unsigned int)num_def_acls
));
5500 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5501 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5502 return map_nt_error_from_unix(errno
);
5505 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5506 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5507 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5508 return map_nt_error_from_unix(errno
);
5510 return NT_STATUS_OK
;
5514 /****************************************************************************
5515 Deal with SMB_SET_POSIX_LOCK.
5516 ****************************************************************************/
5518 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5519 const struct smb_request
*req
,
5525 SMB_BIG_UINT offset
;
5527 bool blocking_lock
= False
;
5528 enum brl_type lock_type
;
5530 NTSTATUS status
= NT_STATUS_OK
;
5532 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5533 return NT_STATUS_INVALID_HANDLE
;
5536 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5537 return NT_STATUS_INVALID_PARAMETER
;
5540 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5541 case POSIX_LOCK_TYPE_READ
:
5542 lock_type
= READ_LOCK
;
5544 case POSIX_LOCK_TYPE_WRITE
:
5545 /* Return the right POSIX-mappable error code for files opened read-only. */
5546 if (!fsp
->can_write
) {
5547 return NT_STATUS_INVALID_HANDLE
;
5549 lock_type
= WRITE_LOCK
;
5551 case POSIX_LOCK_TYPE_UNLOCK
:
5552 lock_type
= UNLOCK_LOCK
;
5555 return NT_STATUS_INVALID_PARAMETER
;
5558 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5559 blocking_lock
= False
;
5560 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5561 blocking_lock
= True
;
5563 return NT_STATUS_INVALID_PARAMETER
;
5566 if (!lp_blocking_locks(SNUM(conn
))) {
5567 blocking_lock
= False
;
5570 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5571 #if defined(HAVE_LONGLONG)
5572 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5573 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5574 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5575 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5576 #else /* HAVE_LONGLONG */
5577 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5578 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5579 #endif /* HAVE_LONGLONG */
5581 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5582 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5584 (unsigned int)lock_type
,
5585 (unsigned int)lock_pid
,
5589 if (lock_type
== UNLOCK_LOCK
) {
5590 status
= do_unlock(smbd_messaging_context(),
5597 uint32 block_smbpid
;
5599 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5610 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5612 * A blocking lock was requested. Package up
5613 * this smb into a queued request and push it
5614 * onto the blocking lock queue.
5616 if(push_blocking_lock_request(br_lck
,
5619 -1, /* infinite timeout. */
5627 TALLOC_FREE(br_lck
);
5631 TALLOC_FREE(br_lck
);
5637 /****************************************************************************
5638 Deal with SMB_INFO_STANDARD.
5639 ****************************************************************************/
5641 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5646 const SMB_STRUCT_STAT
*psbuf
)
5648 struct timespec ts
[2];
5650 if (total_data
< 12) {
5651 return NT_STATUS_INVALID_PARAMETER
;
5655 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5657 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5659 DEBUG(10,("smb_set_info_standard: file %s\n",
5660 fname
? fname
: fsp
->fsp_name
));
5662 return smb_set_file_time(conn
,
5670 /****************************************************************************
5671 Deal with SMB_SET_FILE_BASIC_INFO.
5672 ****************************************************************************/
5674 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5679 SMB_STRUCT_STAT
*psbuf
)
5681 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5682 struct timespec write_time
;
5683 struct timespec changed_time
;
5685 struct timespec ts
[2];
5686 NTSTATUS status
= NT_STATUS_OK
;
5687 bool setting_write_time
= true;
5689 if (total_data
< 36) {
5690 return NT_STATUS_INVALID_PARAMETER
;
5693 /* Set the attributes */
5694 dosmode
= IVAL(pdata
,32);
5695 status
= smb_set_file_dosmode(conn
,
5701 if (!NT_STATUS_IS_OK(status
)) {
5705 /* Ignore create time at offset pdata. */
5708 ts
[0] = interpret_long_date(pdata
+8);
5710 write_time
= interpret_long_date(pdata
+16);
5711 changed_time
= interpret_long_date(pdata
+24);
5714 ts
[1] = timespec_min(&write_time
, &changed_time
);
5716 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5720 /* Prefer a defined time to an undefined one. */
5721 if (null_timespec(ts
[1])) {
5722 if (null_timespec(write_time
)) {
5723 ts
[1] = changed_time
;
5724 setting_write_time
= false;
5730 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5731 fname
? fname
: fsp
->fsp_name
));
5733 return smb_set_file_time(conn
,
5738 setting_write_time
);
5741 /****************************************************************************
5742 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5743 ****************************************************************************/
5745 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5746 struct smb_request
*req
,
5751 SMB_STRUCT_STAT
*psbuf
)
5753 SMB_BIG_UINT allocation_size
= 0;
5754 NTSTATUS status
= NT_STATUS_OK
;
5755 files_struct
*new_fsp
= NULL
;
5757 if (!VALID_STAT(*psbuf
)) {
5758 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5761 if (total_data
< 8) {
5762 return NT_STATUS_INVALID_PARAMETER
;
5765 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5766 #ifdef LARGE_SMB_OFF_T
5767 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5768 #else /* LARGE_SMB_OFF_T */
5769 if (IVAL(pdata
,4) != 0) {
5770 /* more than 32 bits? */
5771 return NT_STATUS_INVALID_PARAMETER
;
5773 #endif /* LARGE_SMB_OFF_T */
5775 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5776 fname
, (double)allocation_size
));
5778 if (allocation_size
) {
5779 allocation_size
= smb_roundup(conn
, allocation_size
);
5782 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5783 fname
, (double)allocation_size
));
5785 if (fsp
&& fsp
->fh
->fd
!= -1) {
5786 /* Open file handle. */
5787 /* Only change if needed. */
5788 if (allocation_size
!= get_file_size(*psbuf
)) {
5789 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5790 return map_nt_error_from_unix(errno
);
5793 /* But always update the time. */
5795 * This is equivalent to a write. Ensure it's seen immediately
5796 * if there are no pending writes.
5798 trigger_write_time_update_immediate(fsp
);
5799 return NT_STATUS_OK
;
5802 /* Pathname or stat or directory file. */
5804 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5806 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5809 FILE_ATTRIBUTE_NORMAL
,
5810 FORCE_OPLOCK_BREAK_TO_NONE
,
5813 if (!NT_STATUS_IS_OK(status
)) {
5814 /* NB. We check for open_was_deferred in the caller. */
5818 /* Only change if needed. */
5819 if (allocation_size
!= get_file_size(*psbuf
)) {
5820 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5821 status
= map_nt_error_from_unix(errno
);
5822 close_file(new_fsp
,NORMAL_CLOSE
);
5827 /* Changing the allocation size should set the last mod time. */
5829 * This is equivalent to a write. Ensure it's seen immediately
5830 * if there are no pending writes.
5832 trigger_write_time_update_immediate(new_fsp
);
5834 close_file(new_fsp
,NORMAL_CLOSE
);
5835 return NT_STATUS_OK
;
5838 /****************************************************************************
5839 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5840 ****************************************************************************/
5842 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5843 struct smb_request
*req
,
5848 SMB_STRUCT_STAT
*psbuf
)
5852 if (total_data
< 8) {
5853 return NT_STATUS_INVALID_PARAMETER
;
5856 size
= IVAL(pdata
,0);
5857 #ifdef LARGE_SMB_OFF_T
5858 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5859 #else /* LARGE_SMB_OFF_T */
5860 if (IVAL(pdata
,4) != 0) {
5861 /* more than 32 bits? */
5862 return NT_STATUS_INVALID_PARAMETER
;
5864 #endif /* LARGE_SMB_OFF_T */
5865 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5866 "file %s to %.0f\n", fname
, (double)size
));
5868 return smb_set_file_size(conn
, req
,
5875 /****************************************************************************
5876 Allow a UNIX info mknod.
5877 ****************************************************************************/
5879 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5883 SMB_STRUCT_STAT
*psbuf
)
5885 uint32 file_type
= IVAL(pdata
,56);
5886 #if defined(HAVE_MAKEDEV)
5887 uint32 dev_major
= IVAL(pdata
,60);
5888 uint32 dev_minor
= IVAL(pdata
,68);
5890 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5891 uint32 raw_unixmode
= IVAL(pdata
,84);
5895 if (total_data
< 100) {
5896 return NT_STATUS_INVALID_PARAMETER
;
5899 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5900 if (!NT_STATUS_IS_OK(status
)) {
5904 #if defined(HAVE_MAKEDEV)
5905 dev
= makedev(dev_major
, dev_minor
);
5908 switch (file_type
) {
5909 #if defined(S_IFIFO)
5910 case UNIX_TYPE_FIFO
:
5911 unixmode
|= S_IFIFO
;
5914 #if defined(S_IFSOCK)
5915 case UNIX_TYPE_SOCKET
:
5916 unixmode
|= S_IFSOCK
;
5919 #if defined(S_IFCHR)
5920 case UNIX_TYPE_CHARDEV
:
5921 unixmode
|= S_IFCHR
;
5924 #if defined(S_IFBLK)
5925 case UNIX_TYPE_BLKDEV
:
5926 unixmode
|= S_IFBLK
;
5930 return NT_STATUS_INVALID_PARAMETER
;
5933 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5934 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5936 /* Ok - do the mknod. */
5937 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5938 return map_nt_error_from_unix(errno
);
5941 /* If any of the other "set" calls fail we
5942 * don't want to end up with a half-constructed mknod.
5945 if (lp_inherit_perms(SNUM(conn
))) {
5947 conn
, parent_dirname(fname
),
5951 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5952 status
= map_nt_error_from_unix(errno
);
5953 SMB_VFS_UNLINK(conn
,fname
);
5956 return NT_STATUS_OK
;
5959 /****************************************************************************
5960 Deal with SMB_SET_FILE_UNIX_BASIC.
5961 ****************************************************************************/
5963 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5964 struct smb_request
*req
,
5969 SMB_STRUCT_STAT
*psbuf
)
5971 struct timespec ts
[2];
5972 uint32 raw_unixmode
;
5975 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5976 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5977 NTSTATUS status
= NT_STATUS_OK
;
5978 bool delete_on_fail
= False
;
5979 enum perm_type ptype
;
5981 if (total_data
< 100) {
5982 return NT_STATUS_INVALID_PARAMETER
;
5985 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5986 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5987 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5988 #ifdef LARGE_SMB_OFF_T
5989 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5990 #else /* LARGE_SMB_OFF_T */
5991 if (IVAL(pdata
,4) != 0) {
5992 /* more than 32 bits? */
5993 return NT_STATUS_INVALID_PARAMETER
;
5995 #endif /* LARGE_SMB_OFF_T */
5998 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
5999 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
6000 set_owner
= (uid_t
)IVAL(pdata
,40);
6001 set_grp
= (gid_t
)IVAL(pdata
,48);
6002 raw_unixmode
= IVAL(pdata
,84);
6004 if (VALID_STAT(*psbuf
)) {
6005 if (S_ISDIR(psbuf
->st_mode
)) {
6006 ptype
= PERM_EXISTING_DIR
;
6008 ptype
= PERM_EXISTING_FILE
;
6011 ptype
= PERM_NEW_FILE
;
6014 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
6015 if (!NT_STATUS_IS_OK(status
)) {
6019 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6020 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6021 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
6023 if (!VALID_STAT(*psbuf
)) {
6025 * The only valid use of this is to create character and block
6026 * devices, and named pipes. This is deprecated (IMHO) and
6027 * a new info level should be used for mknod. JRA.
6030 status
= smb_unix_mknod(conn
,
6035 if (!NT_STATUS_IS_OK(status
)) {
6039 /* Ensure we don't try and change anything else. */
6040 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6041 size
= get_file_size(*psbuf
);
6042 ts
[0] = get_atimespec(psbuf
);
6043 ts
[1] = get_mtimespec(psbuf
);
6045 * We continue here as we might want to change the
6048 delete_on_fail
= True
;
6052 /* Horrible backwards compatibility hack as an old server bug
6053 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6057 size
= get_file_size(*psbuf
);
6062 * Deal with the UNIX specific mode set.
6065 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6066 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6067 (unsigned int)unixmode
, fname
));
6068 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6069 return map_nt_error_from_unix(errno
);
6074 * Deal with the UNIX specific uid set.
6077 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6080 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6081 (unsigned int)set_owner
, fname
));
6083 if (S_ISLNK(psbuf
->st_mode
)) {
6084 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6086 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6090 status
= map_nt_error_from_unix(errno
);
6091 if (delete_on_fail
) {
6092 SMB_VFS_UNLINK(conn
,fname
);
6099 * Deal with the UNIX specific gid set.
6102 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6103 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6104 (unsigned int)set_owner
, fname
));
6105 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6106 status
= map_nt_error_from_unix(errno
);
6107 if (delete_on_fail
) {
6108 SMB_VFS_UNLINK(conn
,fname
);
6114 /* Deal with any size changes. */
6116 status
= smb_set_file_size(conn
, req
,
6121 if (!NT_STATUS_IS_OK(status
)) {
6125 /* Deal with any time changes. */
6127 return smb_set_file_time(conn
,
6135 /****************************************************************************
6136 Deal with SMB_SET_FILE_UNIX_INFO2.
6137 ****************************************************************************/
6139 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6140 struct smb_request
*req
,
6145 SMB_STRUCT_STAT
*psbuf
)
6151 if (total_data
< 116) {
6152 return NT_STATUS_INVALID_PARAMETER
;
6155 /* Start by setting all the fields that are common between UNIX_BASIC
6158 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6160 if (!NT_STATUS_IS_OK(status
)) {
6164 smb_fflags
= IVAL(pdata
, 108);
6165 smb_fmask
= IVAL(pdata
, 112);
6167 /* NB: We should only attempt to alter the file flags if the client
6168 * sends a non-zero mask.
6170 if (smb_fmask
!= 0) {
6171 int stat_fflags
= 0;
6173 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6175 /* Client asked to alter a flag we don't understand. */
6176 return NT_STATUS_INVALID_PARAMETER
;
6179 if (fsp
&& fsp
->fh
->fd
!= -1) {
6180 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6181 return NT_STATUS_NOT_SUPPORTED
;
6183 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6184 return map_nt_error_from_unix(errno
);
6189 /* XXX: need to add support for changing the create_time here. You
6190 * can do this for paths on Darwin with setattrlist(2). The right way
6191 * to hook this up is probably by extending the VFS utimes interface.
6194 return NT_STATUS_OK
;
6197 /****************************************************************************
6198 Create a directory with POSIX semantics.
6199 ****************************************************************************/
6201 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6202 struct smb_request
*req
,
6206 SMB_STRUCT_STAT
*psbuf
,
6207 int *pdata_return_size
)
6209 NTSTATUS status
= NT_STATUS_OK
;
6210 uint32 raw_unixmode
= 0;
6211 uint32 mod_unixmode
= 0;
6212 mode_t unixmode
= (mode_t
)0;
6213 files_struct
*fsp
= NULL
;
6214 uint16 info_level_return
= 0;
6216 char *pdata
= *ppdata
;
6218 if (total_data
< 18) {
6219 return NT_STATUS_INVALID_PARAMETER
;
6222 raw_unixmode
= IVAL(pdata
,8);
6223 /* Next 4 bytes are not yet defined. */
6225 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6226 if (!NT_STATUS_IS_OK(status
)) {
6230 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6232 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6233 fname
, (unsigned int)unixmode
));
6235 status
= open_directory(conn
, req
,
6238 FILE_READ_ATTRIBUTES
, /* Just a stat open */
6239 FILE_SHARE_NONE
, /* Ignored for stat opens */
6246 if (NT_STATUS_IS_OK(status
)) {
6247 close_file(fsp
, NORMAL_CLOSE
);
6250 info_level_return
= SVAL(pdata
,16);
6252 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6253 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6254 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6255 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6257 *pdata_return_size
= 12;
6260 /* Realloc the data size */
6261 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6262 if (*ppdata
== NULL
) {
6263 *pdata_return_size
= 0;
6264 return NT_STATUS_NO_MEMORY
;
6268 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6269 SSVAL(pdata
,2,0); /* No fnum. */
6270 SIVAL(pdata
,4,info
); /* Was directory created. */
6272 switch (info_level_return
) {
6273 case SMB_QUERY_FILE_UNIX_BASIC
:
6274 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6275 SSVAL(pdata
,10,0); /* Padding. */
6276 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6278 case SMB_QUERY_FILE_UNIX_INFO2
:
6279 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6280 SSVAL(pdata
,10,0); /* Padding. */
6281 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6284 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6285 SSVAL(pdata
,10,0); /* Padding. */
6292 /****************************************************************************
6293 Open/Create a file with POSIX semantics.
6294 ****************************************************************************/
6296 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6297 struct smb_request
*req
,
6301 SMB_STRUCT_STAT
*psbuf
,
6302 int *pdata_return_size
)
6304 bool extended_oplock_granted
= False
;
6305 char *pdata
= *ppdata
;
6307 uint32 wire_open_mode
= 0;
6308 uint32 raw_unixmode
= 0;
6309 uint32 mod_unixmode
= 0;
6310 uint32 create_disp
= 0;
6311 uint32 access_mask
= 0;
6312 uint32 create_options
= 0;
6313 NTSTATUS status
= NT_STATUS_OK
;
6314 mode_t unixmode
= (mode_t
)0;
6315 files_struct
*fsp
= NULL
;
6316 int oplock_request
= 0;
6318 uint16 info_level_return
= 0;
6320 if (total_data
< 18) {
6321 return NT_STATUS_INVALID_PARAMETER
;
6324 flags
= IVAL(pdata
,0);
6325 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6326 if (oplock_request
) {
6327 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6330 wire_open_mode
= IVAL(pdata
,4);
6332 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6333 return smb_posix_mkdir(conn
, req
,
6341 switch (wire_open_mode
& SMB_ACCMODE
) {
6343 access_mask
= FILE_READ_DATA
;
6346 access_mask
= FILE_WRITE_DATA
;
6349 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6352 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6353 (unsigned int)wire_open_mode
));
6354 return NT_STATUS_INVALID_PARAMETER
;
6357 wire_open_mode
&= ~SMB_ACCMODE
;
6359 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6360 create_disp
= FILE_CREATE
;
6361 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6362 create_disp
= FILE_OVERWRITE_IF
;
6363 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6364 create_disp
= FILE_OPEN_IF
;
6366 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6367 (unsigned int)wire_open_mode
));
6368 return NT_STATUS_INVALID_PARAMETER
;
6371 raw_unixmode
= IVAL(pdata
,8);
6372 /* Next 4 bytes are not yet defined. */
6374 status
= unix_perms_from_wire(conn
,
6377 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6380 if (!NT_STATUS_IS_OK(status
)) {
6384 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6386 if (wire_open_mode
& SMB_O_SYNC
) {
6387 create_options
|= FILE_WRITE_THROUGH
;
6389 if (wire_open_mode
& SMB_O_APPEND
) {
6390 access_mask
|= FILE_APPEND_DATA
;
6392 if (wire_open_mode
& SMB_O_DIRECT
) {
6393 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6396 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6398 (unsigned int)wire_open_mode
,
6399 (unsigned int)unixmode
));
6401 status
= open_file_ntcreate(conn
, req
,
6405 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6407 0, /* no create options yet. */
6413 if (!NT_STATUS_IS_OK(status
)) {
6417 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6418 extended_oplock_granted
= True
;
6421 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6422 extended_oplock_granted
= True
;
6425 info_level_return
= SVAL(pdata
,16);
6427 /* Allocate the correct return size. */
6429 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6430 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6431 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6432 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6434 *pdata_return_size
= 12;
6437 /* Realloc the data size */
6438 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6439 if (*ppdata
== NULL
) {
6440 close_file(fsp
,ERROR_CLOSE
);
6441 *pdata_return_size
= 0;
6442 return NT_STATUS_NO_MEMORY
;
6446 if (extended_oplock_granted
) {
6447 if (flags
& REQUEST_BATCH_OPLOCK
) {
6448 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6450 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6452 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6453 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6455 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6458 SSVAL(pdata
,2,fsp
->fnum
);
6459 SIVAL(pdata
,4,info
); /* Was file created etc. */
6461 switch (info_level_return
) {
6462 case SMB_QUERY_FILE_UNIX_BASIC
:
6463 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6464 SSVAL(pdata
,10,0); /* padding. */
6465 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6467 case SMB_QUERY_FILE_UNIX_INFO2
:
6468 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6469 SSVAL(pdata
,10,0); /* padding. */
6470 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6473 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6474 SSVAL(pdata
,10,0); /* padding. */
6477 return NT_STATUS_OK
;
6480 /****************************************************************************
6481 Delete a file with POSIX semantics.
6482 ****************************************************************************/
6484 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6485 struct smb_request
*req
,
6489 SMB_STRUCT_STAT
*psbuf
)
6491 NTSTATUS status
= NT_STATUS_OK
;
6492 files_struct
*fsp
= NULL
;
6497 struct share_mode_lock
*lck
= NULL
;
6499 if (total_data
< 2) {
6500 return NT_STATUS_INVALID_PARAMETER
;
6503 flags
= SVAL(pdata
,0);
6505 if (!VALID_STAT(*psbuf
)) {
6506 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6509 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6510 !VALID_STAT_OF_DIR(*psbuf
)) {
6511 return NT_STATUS_NOT_A_DIRECTORY
;
6514 DEBUG(10,("smb_posix_unlink: %s %s\n",
6515 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6518 if (VALID_STAT_OF_DIR(*psbuf
)) {
6519 status
= open_directory(conn
, req
,
6523 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6526 FILE_FLAG_POSIX_SEMANTICS
|0777,
6531 status
= open_file_ntcreate(conn
, req
,
6535 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6538 FILE_FLAG_POSIX_SEMANTICS
|0777,
6539 0, /* No oplock, but break existing ones. */
6544 if (!NT_STATUS_IS_OK(status
)) {
6549 * Don't lie to client. If we can't really delete due to
6550 * non-POSIX opens return SHARING_VIOLATION.
6553 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6556 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6557 "lock for file %s\n", fsp
->fsp_name
));
6558 close_file(fsp
, NORMAL_CLOSE
);
6559 return NT_STATUS_INVALID_PARAMETER
;
6563 * See if others still have the file open. If this is the case, then
6564 * don't delete. If all opens are POSIX delete we can set the delete
6565 * on close disposition.
6567 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6568 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6569 if (is_valid_share_mode_entry(e
)) {
6570 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6573 /* Fail with sharing violation. */
6574 close_file(fsp
, NORMAL_CLOSE
);
6576 return NT_STATUS_SHARING_VIOLATION
;
6581 * Set the delete on close.
6583 status
= smb_set_file_disposition_info(conn
,
6590 if (!NT_STATUS_IS_OK(status
)) {
6591 close_file(fsp
, NORMAL_CLOSE
);
6596 return close_file(fsp
, NORMAL_CLOSE
);
6599 /****************************************************************************
6600 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6601 ****************************************************************************/
6603 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6604 struct smb_request
*req
,
6605 unsigned int tran_call
,
6606 char **pparams
, int total_params
,
6607 char **ppdata
, int total_data
,
6608 unsigned int max_data_bytes
)
6610 char *params
= *pparams
;
6611 char *pdata
= *ppdata
;
6613 SMB_STRUCT_STAT sbuf
;
6615 files_struct
*fsp
= NULL
;
6616 NTSTATUS status
= NT_STATUS_OK
;
6617 int data_return_size
= 0;
6618 TALLOC_CTX
*ctx
= talloc_tos();
6621 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6627 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6628 if (total_params
< 4) {
6629 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6633 fsp
= file_fsp(SVAL(params
,0));
6634 /* Basic check for non-null fsp. */
6635 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
6638 info_level
= SVAL(params
,2);
6640 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6642 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6646 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6648 * This is actually a SETFILEINFO on a directory
6649 * handle (returned from an NT SMB). NT5.0 seems
6650 * to do this call. JRA.
6652 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6653 /* Always do lstat for UNIX calls. */
6654 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6655 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6656 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6660 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6661 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6662 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6666 } else if (fsp
->print_file
) {
6668 * Doing a DELETE_ON_CLOSE should cancel a print job.
6670 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6671 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6673 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6676 send_trans2_replies(conn
, req
, params
, 2,
6681 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6686 * Original code - this is an open file.
6688 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
6692 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6693 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6694 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6700 if (total_params
< 7) {
6701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6705 info_level
= SVAL(params
,0);
6706 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6707 total_params
- 6, STR_TERMINATE
,
6709 if (!NT_STATUS_IS_OK(status
)) {
6710 reply_nterror(req
, status
);
6714 status
= resolve_dfspath(ctx
, conn
,
6715 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6718 if (!NT_STATUS_IS_OK(status
)) {
6719 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6720 reply_botherror(req
,
6721 NT_STATUS_PATH_NOT_COVERED
,
6722 ERRSRV
, ERRbadpath
);
6725 reply_nterror(req
, status
);
6729 status
= unix_convert(ctx
, conn
, fname
, False
,
6730 &fname
, NULL
, &sbuf
);
6731 if (!NT_STATUS_IS_OK(status
)) {
6732 reply_nterror(req
, status
);
6736 status
= check_name(conn
, fname
);
6737 if (!NT_STATUS_IS_OK(status
)) {
6738 reply_nterror(req
, status
);
6742 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6744 * For CIFS UNIX extensions the target name may not exist.
6747 /* Always do lstat for UNIX calls. */
6748 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6750 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6751 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6752 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6757 if (!CAN_WRITE(conn
)) {
6758 reply_doserror(req
, ERRSRV
, ERRaccess
);
6762 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6763 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6767 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6768 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6770 /* Realloc the parameter size */
6771 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6772 if (*pparams
== NULL
) {
6773 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6780 switch (info_level
) {
6782 case SMB_INFO_STANDARD
:
6784 status
= smb_set_info_standard(conn
,
6793 case SMB_INFO_SET_EA
:
6795 status
= smb_info_set_ea(conn
,
6803 case SMB_SET_FILE_BASIC_INFO
:
6804 case SMB_FILE_BASIC_INFORMATION
:
6806 status
= smb_set_file_basic_info(conn
,
6815 case SMB_FILE_ALLOCATION_INFORMATION
:
6816 case SMB_SET_FILE_ALLOCATION_INFO
:
6818 status
= smb_set_file_allocation_info(conn
, req
,
6827 case SMB_FILE_END_OF_FILE_INFORMATION
:
6828 case SMB_SET_FILE_END_OF_FILE_INFO
:
6830 status
= smb_set_file_end_of_file_info(conn
, req
,
6839 case SMB_FILE_DISPOSITION_INFORMATION
:
6840 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6843 /* JRA - We used to just ignore this on a path ?
6844 * Shouldn't this be invalid level on a pathname
6847 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6848 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6851 status
= smb_set_file_disposition_info(conn
,
6860 case SMB_FILE_POSITION_INFORMATION
:
6862 status
= smb_file_position_information(conn
,
6869 /* From tridge Samba4 :
6870 * MODE_INFORMATION in setfileinfo (I have no
6871 * idea what "mode information" on a file is - it takes a value of 0,
6872 * 2, 4 or 6. What could it be?).
6875 case SMB_FILE_MODE_INFORMATION
:
6877 status
= smb_file_mode_information(conn
,
6884 * CIFS UNIX extensions.
6887 case SMB_SET_FILE_UNIX_BASIC
:
6889 status
= smb_set_file_unix_basic(conn
, req
,
6898 case SMB_SET_FILE_UNIX_INFO2
:
6900 status
= smb_set_file_unix_info2(conn
, req
,
6909 case SMB_SET_FILE_UNIX_LINK
:
6911 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6912 /* We must have a pathname for this. */
6913 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6916 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6921 case SMB_SET_FILE_UNIX_HLINK
:
6923 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6924 /* We must have a pathname for this. */
6925 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6928 status
= smb_set_file_unix_hlink(conn
, req
,
6934 case SMB_FILE_RENAME_INFORMATION
:
6936 status
= smb_file_rename_information(conn
, req
,
6942 #if defined(HAVE_POSIX_ACLS)
6943 case SMB_SET_POSIX_ACL
:
6945 status
= smb_set_posix_acl(conn
,
6955 case SMB_SET_POSIX_LOCK
:
6957 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6958 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6961 status
= smb_set_posix_lock(conn
, req
,
6962 pdata
, total_data
, fsp
);
6966 case SMB_POSIX_PATH_OPEN
:
6968 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6969 /* We must have a pathname for this. */
6970 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6974 status
= smb_posix_open(conn
, req
,
6983 case SMB_POSIX_PATH_UNLINK
:
6985 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6986 /* We must have a pathname for this. */
6987 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6991 status
= smb_posix_unlink(conn
, req
,
7000 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7005 if (!NT_STATUS_IS_OK(status
)) {
7006 if (open_was_deferred(req
->mid
)) {
7007 /* We have re-scheduled this call. */
7010 if (blocking_lock_was_deferred(req
->mid
)) {
7011 /* We have re-scheduled this call. */
7014 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7015 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7016 ERRSRV
, ERRbadpath
);
7019 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7020 reply_openerror(req
, status
);
7024 reply_nterror(req
, status
);
7029 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7035 /****************************************************************************
7036 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7037 ****************************************************************************/
7039 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7040 char **pparams
, int total_params
,
7041 char **ppdata
, int total_data
,
7042 unsigned int max_data_bytes
)
7044 char *params
= *pparams
;
7045 char *pdata
= *ppdata
;
7046 char *directory
= NULL
;
7047 SMB_STRUCT_STAT sbuf
;
7048 NTSTATUS status
= NT_STATUS_OK
;
7049 struct ea_list
*ea_list
= NULL
;
7050 TALLOC_CTX
*ctx
= talloc_tos();
7052 if (!CAN_WRITE(conn
)) {
7053 reply_doserror(req
, ERRSRV
, ERRaccess
);
7057 if (total_params
< 5) {
7058 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7062 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7063 total_params
- 4, STR_TERMINATE
,
7065 if (!NT_STATUS_IS_OK(status
)) {
7066 reply_nterror(req
, status
);
7070 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7072 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
7073 if (!NT_STATUS_IS_OK(status
)) {
7074 reply_nterror(req
, status
);
7078 status
= check_name(conn
, directory
);
7079 if (!NT_STATUS_IS_OK(status
)) {
7080 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7081 reply_nterror(req
, status
);
7085 /* Any data in this call is an EA list. */
7086 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7087 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7092 * OS/2 workplace shell seems to send SET_EA requests of "null"
7093 * length (4 bytes containing IVAL 4).
7094 * They seem to have no effect. Bug #3212. JRA.
7097 if (total_data
!= 4) {
7098 if (total_data
< 10) {
7099 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7103 if (IVAL(pdata
,0) > total_data
) {
7104 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7105 IVAL(pdata
,0), (unsigned int)total_data
));
7106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7110 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7113 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7117 /* If total_data == 4 Windows doesn't care what values
7118 * are placed in that field, it just ignores them.
7119 * The System i QNTC IBM SMB client puts bad values here,
7120 * so ignore them. */
7122 status
= create_directory(conn
, req
, directory
);
7124 if (!NT_STATUS_IS_OK(status
)) {
7125 reply_nterror(req
, status
);
7129 /* Try and set any given EA. */
7131 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7132 if (!NT_STATUS_IS_OK(status
)) {
7133 reply_nterror(req
, status
);
7138 /* Realloc the parameter and data sizes */
7139 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7140 if(*pparams
== NULL
) {
7141 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7148 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7153 /****************************************************************************
7154 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7155 We don't actually do this - we just send a null response.
7156 ****************************************************************************/
7158 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7159 struct smb_request
*req
,
7160 char **pparams
, int total_params
,
7161 char **ppdata
, int total_data
,
7162 unsigned int max_data_bytes
)
7164 static uint16 fnf_handle
= 257;
7165 char *params
= *pparams
;
7168 if (total_params
< 6) {
7169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7173 info_level
= SVAL(params
,4);
7174 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7176 switch (info_level
) {
7181 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7185 /* Realloc the parameter and data sizes */
7186 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7187 if (*pparams
== NULL
) {
7188 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7193 SSVAL(params
,0,fnf_handle
);
7194 SSVAL(params
,2,0); /* No changes */
7195 SSVAL(params
,4,0); /* No EA errors */
7202 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7207 /****************************************************************************
7208 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7209 changes). Currently this does nothing.
7210 ****************************************************************************/
7212 static void call_trans2findnotifynext(connection_struct
*conn
,
7213 struct smb_request
*req
,
7214 char **pparams
, int total_params
,
7215 char **ppdata
, int total_data
,
7216 unsigned int max_data_bytes
)
7218 char *params
= *pparams
;
7220 DEBUG(3,("call_trans2findnotifynext\n"));
7222 /* Realloc the parameter and data sizes */
7223 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7224 if (*pparams
== NULL
) {
7225 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7230 SSVAL(params
,0,0); /* No changes */
7231 SSVAL(params
,2,0); /* No EA errors */
7233 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7238 /****************************************************************************
7239 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7240 ****************************************************************************/
7242 static void call_trans2getdfsreferral(connection_struct
*conn
,
7243 struct smb_request
*req
,
7244 char **pparams
, int total_params
,
7245 char **ppdata
, int total_data
,
7246 unsigned int max_data_bytes
)
7248 char *params
= *pparams
;
7249 char *pathname
= NULL
;
7251 int max_referral_level
;
7252 NTSTATUS status
= NT_STATUS_OK
;
7253 TALLOC_CTX
*ctx
= talloc_tos();
7255 DEBUG(10,("call_trans2getdfsreferral\n"));
7257 if (total_params
< 3) {
7258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7262 max_referral_level
= SVAL(params
,0);
7264 if(!lp_host_msdfs()) {
7265 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7269 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7270 total_params
- 2, STR_TERMINATE
);
7272 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7275 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7276 ppdata
,&status
)) < 0) {
7277 reply_nterror(req
, status
);
7281 SSVAL(req
->inbuf
, smb_flg2
,
7282 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7283 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7288 #define LMCAT_SPL 0x53
7289 #define LMFUNC_GETJOBID 0x60
7291 /****************************************************************************
7292 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7293 ****************************************************************************/
7295 static void call_trans2ioctl(connection_struct
*conn
,
7296 struct smb_request
*req
,
7297 char **pparams
, int total_params
,
7298 char **ppdata
, int total_data
,
7299 unsigned int max_data_bytes
)
7301 char *pdata
= *ppdata
;
7302 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv15
));
7304 /* check for an invalid fid before proceeding */
7307 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7311 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7312 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7313 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7314 if (*ppdata
== NULL
) {
7315 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7320 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7321 CAN ACCEPT THIS IN UNICODE. JRA. */
7323 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7324 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7325 global_myname(), 15,
7326 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7327 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7328 lp_servicename(SNUM(conn
)), 13,
7329 STR_ASCII
|STR_TERMINATE
); /* Service name */
7330 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7335 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7336 reply_doserror(req
, ERRSRV
, ERRerror
);
7339 /****************************************************************************
7340 Reply to a SMBfindclose (stop trans2 directory search).
7341 ****************************************************************************/
7343 void reply_findclose(struct smb_request
*req
)
7347 START_PROFILE(SMBfindclose
);
7350 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7351 END_PROFILE(SMBfindclose
);
7355 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7357 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7359 dptr_close(&dptr_num
);
7361 reply_outbuf(req
, 0, 0);
7363 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7365 END_PROFILE(SMBfindclose
);
7369 /****************************************************************************
7370 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7371 ****************************************************************************/
7373 void reply_findnclose(struct smb_request
*req
)
7377 START_PROFILE(SMBfindnclose
);
7380 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7381 END_PROFILE(SMBfindnclose
);
7385 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7387 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7389 /* We never give out valid handles for a
7390 findnotifyfirst - so any dptr_num is ok here.
7393 reply_outbuf(req
, 0, 0);
7395 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7397 END_PROFILE(SMBfindnclose
);
7401 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7402 struct trans_state
*state
)
7404 if (Protocol
>= PROTOCOL_NT1
) {
7405 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7406 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7409 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7410 if (state
->call
!= TRANSACT2_QFSINFO
&&
7411 state
->call
!= TRANSACT2_SETFSINFO
) {
7412 DEBUG(0,("handle_trans2: encryption required "
7414 (unsigned int)state
->call
));
7415 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7420 /* Now we must call the relevant TRANS2 function */
7421 switch(state
->call
) {
7422 case TRANSACT2_OPEN
:
7424 START_PROFILE(Trans2_open
);
7425 call_trans2open(conn
, req
,
7426 &state
->param
, state
->total_param
,
7427 &state
->data
, state
->total_data
,
7428 state
->max_data_return
);
7429 END_PROFILE(Trans2_open
);
7433 case TRANSACT2_FINDFIRST
:
7435 START_PROFILE(Trans2_findfirst
);
7436 call_trans2findfirst(conn
, req
,
7437 &state
->param
, state
->total_param
,
7438 &state
->data
, state
->total_data
,
7439 state
->max_data_return
);
7440 END_PROFILE(Trans2_findfirst
);
7444 case TRANSACT2_FINDNEXT
:
7446 START_PROFILE(Trans2_findnext
);
7447 call_trans2findnext(conn
, req
,
7448 &state
->param
, state
->total_param
,
7449 &state
->data
, state
->total_data
,
7450 state
->max_data_return
);
7451 END_PROFILE(Trans2_findnext
);
7455 case TRANSACT2_QFSINFO
:
7457 START_PROFILE(Trans2_qfsinfo
);
7458 call_trans2qfsinfo(conn
, req
,
7459 &state
->param
, state
->total_param
,
7460 &state
->data
, state
->total_data
,
7461 state
->max_data_return
);
7462 END_PROFILE(Trans2_qfsinfo
);
7466 case TRANSACT2_SETFSINFO
:
7468 START_PROFILE(Trans2_setfsinfo
);
7469 call_trans2setfsinfo(conn
, req
,
7470 &state
->param
, state
->total_param
,
7471 &state
->data
, state
->total_data
,
7472 state
->max_data_return
);
7473 END_PROFILE(Trans2_setfsinfo
);
7477 case TRANSACT2_QPATHINFO
:
7478 case TRANSACT2_QFILEINFO
:
7480 START_PROFILE(Trans2_qpathinfo
);
7481 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7482 &state
->param
, state
->total_param
,
7483 &state
->data
, state
->total_data
,
7484 state
->max_data_return
);
7485 END_PROFILE(Trans2_qpathinfo
);
7489 case TRANSACT2_SETPATHINFO
:
7490 case TRANSACT2_SETFILEINFO
:
7492 START_PROFILE(Trans2_setpathinfo
);
7493 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7494 &state
->param
, state
->total_param
,
7495 &state
->data
, state
->total_data
,
7496 state
->max_data_return
);
7497 END_PROFILE(Trans2_setpathinfo
);
7501 case TRANSACT2_FINDNOTIFYFIRST
:
7503 START_PROFILE(Trans2_findnotifyfirst
);
7504 call_trans2findnotifyfirst(conn
, req
,
7505 &state
->param
, state
->total_param
,
7506 &state
->data
, state
->total_data
,
7507 state
->max_data_return
);
7508 END_PROFILE(Trans2_findnotifyfirst
);
7512 case TRANSACT2_FINDNOTIFYNEXT
:
7514 START_PROFILE(Trans2_findnotifynext
);
7515 call_trans2findnotifynext(conn
, req
,
7516 &state
->param
, state
->total_param
,
7517 &state
->data
, state
->total_data
,
7518 state
->max_data_return
);
7519 END_PROFILE(Trans2_findnotifynext
);
7523 case TRANSACT2_MKDIR
:
7525 START_PROFILE(Trans2_mkdir
);
7526 call_trans2mkdir(conn
, req
,
7527 &state
->param
, state
->total_param
,
7528 &state
->data
, state
->total_data
,
7529 state
->max_data_return
);
7530 END_PROFILE(Trans2_mkdir
);
7534 case TRANSACT2_GET_DFS_REFERRAL
:
7536 START_PROFILE(Trans2_get_dfs_referral
);
7537 call_trans2getdfsreferral(conn
, req
,
7538 &state
->param
, state
->total_param
,
7539 &state
->data
, state
->total_data
,
7540 state
->max_data_return
);
7541 END_PROFILE(Trans2_get_dfs_referral
);
7545 case TRANSACT2_IOCTL
:
7547 START_PROFILE(Trans2_ioctl
);
7548 call_trans2ioctl(conn
, req
,
7549 &state
->param
, state
->total_param
,
7550 &state
->data
, state
->total_data
,
7551 state
->max_data_return
);
7552 END_PROFILE(Trans2_ioctl
);
7557 /* Error in request */
7558 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7559 reply_doserror(req
, ERRSRV
,ERRerror
);
7563 /****************************************************************************
7564 Reply to a SMBtrans2.
7565 ****************************************************************************/
7567 void reply_trans2(struct smb_request
*req
)
7569 connection_struct
*conn
= req
->conn
;
7574 unsigned int tran_call
;
7576 unsigned int av_size
;
7577 struct trans_state
*state
;
7580 START_PROFILE(SMBtrans2
);
7582 if (req
->wct
< 14) {
7583 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7584 END_PROFILE(SMBtrans2
);
7588 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7589 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7590 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7591 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7592 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7593 size
= smb_len(req
->inbuf
) + 4;
7594 av_size
= smb_len(req
->inbuf
);
7596 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7597 if (!NT_STATUS_IS_OK(result
)) {
7598 DEBUG(2, ("Got invalid trans2 request: %s\n",
7599 nt_errstr(result
)));
7600 reply_nterror(req
, result
);
7601 END_PROFILE(SMBtrans2
);
7606 switch (tran_call
) {
7607 /* List the allowed trans2 calls on IPC$ */
7608 case TRANSACT2_OPEN
:
7609 case TRANSACT2_GET_DFS_REFERRAL
:
7610 case TRANSACT2_QFILEINFO
:
7611 case TRANSACT2_QFSINFO
:
7612 case TRANSACT2_SETFSINFO
:
7615 reply_doserror(req
, ERRSRV
, ERRaccess
);
7616 END_PROFILE(SMBtrans2
);
7621 if ((state
= TALLOC_P(conn
->mem_ctx
, struct trans_state
)) == NULL
) {
7622 DEBUG(0, ("talloc failed\n"));
7623 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7624 END_PROFILE(SMBtrans2
);
7628 state
->cmd
= SMBtrans2
;
7630 state
->mid
= req
->mid
;
7631 state
->vuid
= req
->vuid
;
7632 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7633 state
->setup
= NULL
;
7634 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7635 state
->param
= NULL
;
7636 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7638 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7639 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7640 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7641 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7642 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7644 state
->call
= tran_call
;
7646 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7647 is so as a sanity check */
7648 if (state
->setup_count
!= 1) {
7650 * Need to have rc=0 for ioctl to get job id for OS/2.
7651 * Network printing will fail if function is not successful.
7652 * Similar function in reply.c will be used if protocol
7653 * is LANMAN1.0 instead of LM1.2X002.
7654 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7655 * outbuf doesn't have to be set(only job id is used).
7657 if ( (state
->setup_count
== 4)
7658 && (tran_call
== TRANSACT2_IOCTL
)
7659 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7660 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7661 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7663 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7664 DEBUG(2,("Transaction is %d\n",tran_call
));
7666 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7667 END_PROFILE(SMBtrans2
);
7672 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7675 if (state
->total_data
) {
7676 /* Can't use talloc here, the core routines do realloc on the
7677 * params and data. */
7678 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7679 if (state
->data
== NULL
) {
7680 DEBUG(0,("reply_trans2: data malloc fail for %u "
7681 "bytes !\n", (unsigned int)state
->total_data
));
7683 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7684 END_PROFILE(SMBtrans2
);
7688 if (dscnt
> state
->total_data
||
7689 dsoff
+dscnt
< dsoff
) {
7693 if (dsoff
> av_size
||
7695 dsoff
+dscnt
> av_size
) {
7699 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7702 if (state
->total_param
) {
7703 /* Can't use talloc here, the core routines do realloc on the
7704 * params and data. */
7705 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7706 if (state
->param
== NULL
) {
7707 DEBUG(0,("reply_trans: param malloc fail for %u "
7708 "bytes !\n", (unsigned int)state
->total_param
));
7709 SAFE_FREE(state
->data
);
7711 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7712 END_PROFILE(SMBtrans2
);
7716 if (pscnt
> state
->total_param
||
7717 psoff
+pscnt
< psoff
) {
7721 if (psoff
> av_size
||
7723 psoff
+pscnt
> av_size
) {
7727 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7730 state
->received_data
= dscnt
;
7731 state
->received_param
= pscnt
;
7733 if ((state
->received_param
== state
->total_param
) &&
7734 (state
->received_data
== state
->total_data
)) {
7736 handle_trans2(conn
, req
, state
);
7738 SAFE_FREE(state
->data
);
7739 SAFE_FREE(state
->param
);
7741 END_PROFILE(SMBtrans2
);
7745 DLIST_ADD(conn
->pending_trans
, state
);
7747 /* We need to send an interim response then receive the rest
7748 of the parameter/data bytes */
7749 reply_outbuf(req
, 0, 0);
7750 show_msg((char *)req
->outbuf
);
7751 END_PROFILE(SMBtrans2
);
7756 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7757 SAFE_FREE(state
->data
);
7758 SAFE_FREE(state
->param
);
7760 END_PROFILE(SMBtrans2
);
7761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7765 /****************************************************************************
7766 Reply to a SMBtranss2
7767 ****************************************************************************/
7769 void reply_transs2(struct smb_request
*req
)
7771 connection_struct
*conn
= req
->conn
;
7772 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7773 struct trans_state
*state
;
7775 unsigned int av_size
;
7777 START_PROFILE(SMBtranss2
);
7779 show_msg((char *)req
->inbuf
);
7782 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7783 END_PROFILE(SMBtranss2
);
7787 size
= smb_len(req
->inbuf
)+4;
7788 av_size
= smb_len(req
->inbuf
);
7790 for (state
= conn
->pending_trans
; state
!= NULL
;
7791 state
= state
->next
) {
7792 if (state
->mid
== req
->mid
) {
7797 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7799 END_PROFILE(SMBtranss2
);
7803 /* Revise state->total_param and state->total_data in case they have
7804 changed downwards */
7806 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7807 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7808 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7809 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7811 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7812 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7813 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7815 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7816 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7817 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7819 state
->received_param
+= pcnt
;
7820 state
->received_data
+= dcnt
;
7822 if ((state
->received_data
> state
->total_data
) ||
7823 (state
->received_param
> state
->total_param
))
7827 if (pdisp
> state
->total_param
||
7828 pcnt
> state
->total_param
||
7829 pdisp
+pcnt
> state
->total_param
||
7830 pdisp
+pcnt
< pdisp
) {
7834 if (poff
> av_size
||
7836 poff
+pcnt
> av_size
||
7841 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7846 if (ddisp
> state
->total_data
||
7847 dcnt
> state
->total_data
||
7848 ddisp
+dcnt
> state
->total_data
||
7849 ddisp
+dcnt
< ddisp
) {
7853 if (doff
> av_size
||
7855 doff
+dcnt
> av_size
||
7860 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7864 if ((state
->received_param
< state
->total_param
) ||
7865 (state
->received_data
< state
->total_data
)) {
7866 END_PROFILE(SMBtranss2
);
7871 * construct_reply_common will copy smb_com from inbuf to
7872 * outbuf. SMBtranss2 is wrong here.
7874 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7876 handle_trans2(conn
, req
, state
);
7878 DLIST_REMOVE(conn
->pending_trans
, state
);
7879 SAFE_FREE(state
->data
);
7880 SAFE_FREE(state
->param
);
7883 END_PROFILE(SMBtranss2
);
7888 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7889 DLIST_REMOVE(conn
->pending_trans
, state
);
7890 SAFE_FREE(state
->data
);
7891 SAFE_FREE(state
->param
);
7893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7894 END_PROFILE(SMBtranss2
);