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 /* useable_space can never be more than max_send minus the alignment offset. */
742 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
744 while (params_to_send
|| data_to_send
) {
745 /* Calculate whether we will totally or partially fill this packet */
747 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
749 /* We can never send more than useable_space */
751 * Note that 'useable_space' does not include the alignment offsets,
752 * but we must include the alignment offsets in the calculation of
753 * the length of the data we send over the wire, as the alignment offsets
754 * are sent here. Fix from Marc_Jacobsen@hp.com.
757 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
759 reply_outbuf(req
, 10, total_sent_thistime
);
761 /* Set total params and data to be sent */
762 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
763 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
765 /* Calculate how many parameters and data we can fit into
766 * this packet. Parameters get precedence
769 params_sent_thistime
= MIN(params_to_send
,useable_space
);
770 data_sent_thistime
= useable_space
- params_sent_thistime
;
771 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
773 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
775 /* smb_proff is the offset from the start of the SMB header to the
776 parameter bytes, however the first 4 bytes of outbuf are
777 the Netbios over TCP header. Thus use smb_base() to subtract
778 them from the calculation */
780 SSVAL(req
->outbuf
,smb_proff
,
781 ((smb_buf(req
->outbuf
)+alignment_offset
)
782 - smb_base(req
->outbuf
)));
784 if(params_sent_thistime
== 0)
785 SSVAL(req
->outbuf
,smb_prdisp
,0);
787 /* Absolute displacement of param bytes sent in this packet */
788 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
790 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
791 if(data_sent_thistime
== 0) {
792 SSVAL(req
->outbuf
,smb_droff
,0);
793 SSVAL(req
->outbuf
,smb_drdisp
, 0);
795 /* The offset of the data bytes is the offset of the
796 parameter bytes plus the number of parameters being sent this time */
797 SSVAL(req
->outbuf
, smb_droff
,
798 ((smb_buf(req
->outbuf
)+alignment_offset
)
799 - smb_base(req
->outbuf
))
800 + params_sent_thistime
+ data_alignment_offset
);
801 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
804 /* Initialize the padding for alignment */
806 if (alignment_offset
!= 0) {
807 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
810 /* Copy the param bytes into the packet */
812 if(params_sent_thistime
) {
813 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
814 params_sent_thistime
);
817 /* Copy in the data bytes */
818 if(data_sent_thistime
) {
819 if (data_alignment_offset
!= 0) {
820 memset((smb_buf(req
->outbuf
)+alignment_offset
+
821 params_sent_thistime
), 0,
822 data_alignment_offset
);
824 memcpy(smb_buf(req
->outbuf
)+alignment_offset
825 +params_sent_thistime
+data_alignment_offset
,
826 pd
,data_sent_thistime
);
829 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
830 params_sent_thistime
, data_sent_thistime
, useable_space
));
831 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
832 params_to_send
, data_to_send
, paramsize
, datasize
));
835 error_packet_set((char *)req
->outbuf
,
836 ERRDOS
,ERRbufferoverflow
,
837 STATUS_BUFFER_OVERFLOW
,
841 /* Send the packet */
842 show_msg((char *)req
->outbuf
);
843 if (!srv_send_smb(smbd_server_fd(),
845 IS_CONN_ENCRYPTED(conn
)))
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req
->outbuf
);
850 pp
+= params_sent_thistime
;
851 pd
+= data_sent_thistime
;
853 params_to_send
-= params_sent_thistime
;
854 data_to_send
-= data_sent_thistime
;
857 if(params_to_send
< 0 || data_to_send
< 0) {
858 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
859 params_to_send
, data_to_send
));
867 /****************************************************************************
868 Reply to a TRANSACT2_OPEN.
869 ****************************************************************************/
871 static void call_trans2open(connection_struct
*conn
,
872 struct smb_request
*req
,
873 char **pparams
, int total_params
,
874 char **ppdata
, int total_data
,
875 unsigned int max_data_bytes
)
877 char *params
= *pparams
;
878 char *pdata
= *ppdata
;
883 bool return_additional_info
;
894 SMB_STRUCT_STAT sbuf
;
897 struct ea_list
*ea_list
= NULL
;
902 uint32 create_disposition
;
903 uint32 create_options
= 0;
904 TALLOC_CTX
*ctx
= talloc_tos();
907 * Ensure we have enough parameters to perform the operation.
910 if (total_params
< 29) {
911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
915 flags
= SVAL(params
, 0);
916 deny_mode
= SVAL(params
, 2);
917 open_attr
= SVAL(params
,6);
918 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
919 if (oplock_request
) {
920 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
924 return_additional_info
= BITSETW(params
,0);
925 open_sattr
= SVAL(params
, 4);
926 open_time
= make_unix_date3(params
+8);
928 open_ofun
= SVAL(params
,12);
929 open_size
= IVAL(params
,14);
933 reply_doserror(req
, ERRSRV
, ERRaccess
);
937 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
938 total_params
- 28, STR_TERMINATE
,
940 if (!NT_STATUS_IS_OK(status
)) {
941 reply_nterror(req
, status
);
945 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
946 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
947 (unsigned int)open_ofun
, open_size
));
949 if (open_ofun
== 0) {
950 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
954 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
959 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
963 /* Any data in this call is an EA list. */
964 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
965 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
969 if (total_data
!= 4) {
970 if (total_data
< 10) {
971 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
975 if (IVAL(pdata
,0) > total_data
) {
976 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
977 IVAL(pdata
,0), (unsigned int)total_data
));
978 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
982 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
985 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
988 } else if (IVAL(pdata
,0) != 4) {
989 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
993 status
= create_file(conn
, /* conn */
995 0, /* root_dir_fid */
997 access_mask
, /* access_mask */
998 share_mode
, /* share_access */
999 create_disposition
, /* create_disposition*/
1000 create_options
, /* create_options */
1001 open_attr
, /* file_attributes */
1002 oplock_request
, /* oplock_request */
1003 open_size
, /* allocation_size */
1005 ea_list
, /* ea_list */
1007 &smb_action
, /* pinfo */
1010 if (!NT_STATUS_IS_OK(status
)) {
1011 if (open_was_deferred(req
->mid
)) {
1012 /* We have re-scheduled this call. */
1015 reply_openerror(req
, status
);
1019 size
= get_file_size(sbuf
);
1020 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1021 mtime
= sbuf
.st_mtime
;
1022 inode
= sbuf
.st_ino
;
1024 close_file(fsp
,ERROR_CLOSE
);
1025 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1029 /* Realloc the size of parameters and data we will return */
1030 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1031 if(*pparams
== NULL
) {
1032 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1037 SSVAL(params
,0,fsp
->fnum
);
1038 SSVAL(params
,2,fattr
);
1039 srv_put_dos_date2(params
,4, mtime
);
1040 SIVAL(params
,8, (uint32
)size
);
1041 SSVAL(params
,12,deny_mode
);
1042 SSVAL(params
,14,0); /* open_type - file or directory. */
1043 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1045 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1046 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1049 SSVAL(params
,18,smb_action
);
1052 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1054 SIVAL(params
,20,inode
);
1055 SSVAL(params
,24,0); /* Padding. */
1057 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1058 SIVAL(params
, 26, ea_size
);
1060 SIVAL(params
, 26, 0);
1063 /* Send the required number of replies */
1064 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1067 /*********************************************************
1068 Routine to check if a given string matches exactly.
1069 as a special case a mask of "." does NOT match. That
1070 is required for correct wildcard semantics
1071 Case can be significant or not.
1072 **********************************************************/
1074 static bool exact_match(connection_struct
*conn
,
1078 if (mask
[0] == '.' && mask
[1] == 0)
1080 if (conn
->case_sensitive
)
1081 return strcmp(str
,mask
)==0;
1082 if (StrCaseCmp(str
,mask
) != 0) {
1085 if (dptr_has_wild(conn
->dirptr
)) {
1091 /****************************************************************************
1092 Return the filetype for UNIX extensions.
1093 ****************************************************************************/
1095 static uint32
unix_filetype(mode_t mode
)
1098 return UNIX_TYPE_FILE
;
1099 else if(S_ISDIR(mode
))
1100 return UNIX_TYPE_DIR
;
1102 else if(S_ISLNK(mode
))
1103 return UNIX_TYPE_SYMLINK
;
1106 else if(S_ISCHR(mode
))
1107 return UNIX_TYPE_CHARDEV
;
1110 else if(S_ISBLK(mode
))
1111 return UNIX_TYPE_BLKDEV
;
1114 else if(S_ISFIFO(mode
))
1115 return UNIX_TYPE_FIFO
;
1118 else if(S_ISSOCK(mode
))
1119 return UNIX_TYPE_SOCKET
;
1122 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
1123 return UNIX_TYPE_UNKNOWN
;
1126 /****************************************************************************
1127 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1128 ****************************************************************************/
1130 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1132 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1133 SMB_STRUCT_STAT
*psbuf
,
1135 enum perm_type ptype
,
1140 if (perms
== SMB_MODE_NO_CHANGE
) {
1141 if (!VALID_STAT(*psbuf
)) {
1142 return NT_STATUS_INVALID_PARAMETER
;
1144 *ret_perms
= psbuf
->st_mode
;
1145 return NT_STATUS_OK
;
1149 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1150 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1151 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1152 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1153 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1154 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1155 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1156 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1157 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1159 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1162 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1165 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1170 /* Apply mode mask */
1171 ret
&= lp_create_mask(SNUM(conn
));
1172 /* Add in force bits */
1173 ret
|= lp_force_create_mode(SNUM(conn
));
1176 ret
&= lp_dir_mask(SNUM(conn
));
1177 /* Add in force bits */
1178 ret
|= lp_force_dir_mode(SNUM(conn
));
1180 case PERM_EXISTING_FILE
:
1181 /* Apply mode mask */
1182 ret
&= lp_security_mask(SNUM(conn
));
1183 /* Add in force bits */
1184 ret
|= lp_force_security_mode(SNUM(conn
));
1186 case PERM_EXISTING_DIR
:
1187 /* Apply mode mask */
1188 ret
&= lp_dir_security_mask(SNUM(conn
));
1189 /* Add in force bits */
1190 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1195 return NT_STATUS_OK
;
1198 /****************************************************************************
1199 Get a level dependent lanman2 dir entry.
1200 ****************************************************************************/
1202 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1203 connection_struct
*conn
,
1205 const char *path_mask
,
1208 int requires_resume_key
,
1214 int space_remaining
,
1216 bool *got_exact_match
,
1217 int *last_entry_off
,
1218 struct ea_list
*name_list
)
1222 SMB_STRUCT_STAT sbuf
;
1223 const char *mask
= NULL
;
1224 char *pathreal
= NULL
;
1225 const char *fname
= NULL
;
1226 char *p
, *q
, *pdata
= *ppdata
;
1230 SMB_OFF_T file_size
= 0;
1231 SMB_BIG_UINT allocation_size
= 0;
1233 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1234 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1236 char *last_entry_ptr
;
1238 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1239 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1240 bool check_mangled_names
= lp_manglednames(conn
->params
);
1241 char mangled_name
[13]; /* mangled 8.3 name. */
1243 *out_of_space
= False
;
1244 *got_exact_match
= False
;
1246 ZERO_STRUCT(mdate_ts
);
1247 ZERO_STRUCT(adate_ts
);
1248 ZERO_STRUCT(create_date_ts
);
1250 if (!conn
->dirptr
) {
1254 p
= strrchr_m(path_mask
,'/');
1257 mask
= talloc_strdup(ctx
,"*.*");
1267 bool ms_dfs_link
= False
;
1269 /* Needed if we run out of space */
1270 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1271 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1274 * Due to bugs in NT client redirectors we are not using
1275 * resume keys any more - set them to zero.
1276 * Check out the related comments in findfirst/findnext.
1282 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1283 (long)conn
->dirptr
,curr_dirpos
));
1290 * fname may get mangled, dname is never mangled.
1291 * Whenever we're accessing the filesystem we use
1292 * pathreal which is composed from dname.
1298 /* Mangle fname if it's an illegal name. */
1299 if (mangle_must_mangle(dname
,conn
->params
)) {
1300 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1301 continue; /* Error - couldn't mangle. */
1303 fname
= mangled_name
;
1306 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1307 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1310 if(!got_match
&& check_mangled_names
&&
1311 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1313 * It turns out that NT matches wildcards against
1314 * both long *and* short names. This may explain some
1315 * of the wildcard wierdness from old DOS clients
1316 * that some people have been seeing.... JRA.
1318 /* Force the mangling into 8.3. */
1319 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1320 continue; /* Error - couldn't mangle. */
1323 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1324 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1329 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1331 if (dont_descend
&& !isdots
) {
1337 pathreal
= talloc_asprintf(ctx
,
1342 pathreal
= talloc_asprintf(ctx
,
1352 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1353 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1354 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1355 pathreal
,strerror(errno
)));
1356 TALLOC_FREE(pathreal
);
1359 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1360 /* Needed to show the msdfs symlinks as
1363 if(lp_host_msdfs() &&
1364 lp_msdfs_root(SNUM(conn
)) &&
1365 ((ms_dfs_link
= is_msdfs_link(conn
, pathreal
, &sbuf
)) == True
)) {
1366 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1369 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
1373 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1374 pathreal
,strerror(errno
)));
1375 TALLOC_FREE(pathreal
);
1381 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1383 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1386 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1387 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1388 TALLOC_FREE(pathreal
);
1392 if (!(mode
& aDIR
)) {
1393 file_size
= get_file_size(sbuf
);
1395 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1397 mdate_ts
= get_mtimespec(&sbuf
);
1398 adate_ts
= get_atimespec(&sbuf
);
1399 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1401 if (ask_sharemode
) {
1402 struct timespec write_time_ts
;
1403 struct file_id fileid
;
1405 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1406 get_file_infos(fileid
, NULL
, &write_time_ts
);
1407 if (!null_timespec(write_time_ts
)) {
1408 mdate_ts
= write_time_ts
;
1412 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1413 dos_filetime_timespec(&create_date_ts
);
1414 dos_filetime_timespec(&mdate_ts
);
1415 dos_filetime_timespec(&adate_ts
);
1418 create_date
= convert_timespec_to_time_t(create_date_ts
);
1419 mdate
= convert_timespec_to_time_t(mdate_ts
);
1420 adate
= convert_timespec_to_time_t(adate_ts
);
1422 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1426 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1433 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1435 switch (info_level
) {
1436 case SMB_FIND_INFO_STANDARD
:
1437 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1438 if(requires_resume_key
) {
1442 srv_put_dos_date2(p
,0,create_date
);
1443 srv_put_dos_date2(p
,4,adate
);
1444 srv_put_dos_date2(p
,8,mdate
);
1445 SIVAL(p
,12,(uint32
)file_size
);
1446 SIVAL(p
,16,(uint32
)allocation_size
);
1450 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1451 p
+= ucs2_align(base_data
, p
, 0);
1453 len
= srvstr_push(base_data
, flags2
, p
,
1454 fname
, PTR_DIFF(end_data
, p
),
1456 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1458 SCVAL(nameptr
, -1, len
- 2);
1460 SCVAL(nameptr
, -1, 0);
1464 SCVAL(nameptr
, -1, len
- 1);
1466 SCVAL(nameptr
, -1, 0);
1472 case SMB_FIND_EA_SIZE
:
1473 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1474 if(requires_resume_key
) {
1478 srv_put_dos_date2(p
,0,create_date
);
1479 srv_put_dos_date2(p
,4,adate
);
1480 srv_put_dos_date2(p
,8,mdate
);
1481 SIVAL(p
,12,(uint32
)file_size
);
1482 SIVAL(p
,16,(uint32
)allocation_size
);
1485 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1486 SIVAL(p
,22,ea_size
); /* Extended attributes */
1490 len
= srvstr_push(base_data
, flags2
,
1491 p
, fname
, PTR_DIFF(end_data
, p
),
1492 STR_TERMINATE
| STR_NOALIGN
);
1493 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1506 SCVAL(nameptr
,0,len
);
1508 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1511 case SMB_FIND_EA_LIST
:
1513 struct ea_list
*file_list
= NULL
;
1516 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1520 if(requires_resume_key
) {
1524 srv_put_dos_date2(p
,0,create_date
);
1525 srv_put_dos_date2(p
,4,adate
);
1526 srv_put_dos_date2(p
,8,mdate
);
1527 SIVAL(p
,12,(uint32
)file_size
);
1528 SIVAL(p
,16,(uint32
)allocation_size
);
1530 p
+= 22; /* p now points to the EA area. */
1532 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1533 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1535 /* We need to determine if this entry will fit in the space available. */
1536 /* Max string size is 255 bytes. */
1537 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1538 /* Move the dirptr back to prev_dirpos */
1539 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1540 *out_of_space
= True
;
1541 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1542 return False
; /* Not finished - just out of space */
1545 /* Push the ea_data followed by the name. */
1546 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1548 len
= srvstr_push(base_data
, flags2
,
1549 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1550 STR_TERMINATE
| STR_NOALIGN
);
1551 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1564 SCVAL(nameptr
,0,len
);
1566 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1570 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1571 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1572 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1574 SIVAL(p
,0,reskey
); p
+= 4;
1575 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1576 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1577 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1578 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1579 SOFF_T(p
,0,file_size
); p
+= 8;
1580 SOFF_T(p
,0,allocation_size
); p
+= 8;
1581 SIVAL(p
,0,nt_extmode
); p
+= 4;
1582 q
= p
; p
+= 4; /* q is placeholder for name length. */
1584 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1585 SIVAL(p
,0,ea_size
); /* Extended attributes */
1588 /* Clear the short name buffer. This is
1589 * IMPORTANT as not doing so will trigger
1590 * a Win2k client bug. JRA.
1592 if (!was_8_3
&& check_mangled_names
) {
1593 if (!name_to_8_3(fname
,mangled_name
,True
,
1595 /* Error - mangle failed ! */
1596 memset(mangled_name
,'\0',12);
1598 mangled_name
[12] = 0;
1599 len
= srvstr_push(base_data
, flags2
,
1600 p
+2, mangled_name
, 24,
1601 STR_UPPER
|STR_UNICODE
);
1603 memset(p
+ 2 + len
,'\0',24 - len
);
1610 len
= srvstr_push(base_data
, flags2
, p
,
1611 fname
, PTR_DIFF(end_data
, p
),
1612 STR_TERMINATE_ASCII
);
1615 SIVAL(p
,0,0); /* Ensure any padding is null. */
1616 len
= PTR_DIFF(p
, pdata
);
1617 len
= (len
+ 3) & ~3;
1622 case SMB_FIND_FILE_DIRECTORY_INFO
:
1623 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1625 SIVAL(p
,0,reskey
); p
+= 4;
1626 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1627 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1628 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1629 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1630 SOFF_T(p
,0,file_size
); p
+= 8;
1631 SOFF_T(p
,0,allocation_size
); p
+= 8;
1632 SIVAL(p
,0,nt_extmode
); p
+= 4;
1633 len
= srvstr_push(base_data
, flags2
,
1634 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1635 STR_TERMINATE_ASCII
);
1638 SIVAL(p
,0,0); /* Ensure any padding is null. */
1639 len
= PTR_DIFF(p
, pdata
);
1640 len
= (len
+ 3) & ~3;
1645 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1646 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1648 SIVAL(p
,0,reskey
); p
+= 4;
1649 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1650 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1651 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1652 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1653 SOFF_T(p
,0,file_size
); p
+= 8;
1654 SOFF_T(p
,0,allocation_size
); p
+= 8;
1655 SIVAL(p
,0,nt_extmode
); p
+= 4;
1656 q
= p
; p
+= 4; /* q is placeholder for name length. */
1658 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1659 SIVAL(p
,0,ea_size
); /* Extended attributes */
1662 len
= srvstr_push(base_data
, flags2
, p
,
1663 fname
, PTR_DIFF(end_data
, p
),
1664 STR_TERMINATE_ASCII
);
1668 SIVAL(p
,0,0); /* Ensure any padding is null. */
1669 len
= PTR_DIFF(p
, pdata
);
1670 len
= (len
+ 3) & ~3;
1675 case SMB_FIND_FILE_NAMES_INFO
:
1676 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1678 SIVAL(p
,0,reskey
); p
+= 4;
1680 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1681 acl on a dir (tridge) */
1682 len
= srvstr_push(base_data
, flags2
, p
,
1683 fname
, PTR_DIFF(end_data
, p
),
1684 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_ID_FULL_DIRECTORY_INFO
:
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1697 SIVAL(p
,0,reskey
); p
+= 4;
1698 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1699 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1700 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1701 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1702 SOFF_T(p
,0,file_size
); p
+= 8;
1703 SOFF_T(p
,0,allocation_size
); p
+= 8;
1704 SIVAL(p
,0,nt_extmode
); p
+= 4;
1705 q
= p
; p
+= 4; /* q is placeholder for name length. */
1707 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1708 SIVAL(p
,0,ea_size
); /* Extended attributes */
1711 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1712 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1713 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1714 len
= srvstr_push(base_data
, flags2
, p
,
1715 fname
, PTR_DIFF(end_data
, p
),
1716 STR_TERMINATE_ASCII
);
1719 SIVAL(p
,0,0); /* Ensure any padding is null. */
1720 len
= PTR_DIFF(p
, pdata
);
1721 len
= (len
+ 3) & ~3;
1726 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1727 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1728 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1730 SIVAL(p
,0,reskey
); p
+= 4;
1731 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1732 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1733 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1734 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1735 SOFF_T(p
,0,file_size
); p
+= 8;
1736 SOFF_T(p
,0,allocation_size
); p
+= 8;
1737 SIVAL(p
,0,nt_extmode
); p
+= 4;
1738 q
= p
; p
+= 4; /* q is placeholder for name length */
1740 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1741 SIVAL(p
,0,ea_size
); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3
&& check_mangled_names
) {
1749 if (!name_to_8_3(fname
,mangled_name
,True
,
1751 /* Error - mangle failed ! */
1752 memset(mangled_name
,'\0',12);
1754 mangled_name
[12] = 0;
1755 len
= srvstr_push(base_data
, flags2
,
1756 p
+2, mangled_name
, 24,
1757 STR_UPPER
|STR_UNICODE
);
1760 memset(p
+ 2 + len
,'\0',24 - len
);
1767 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1768 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1769 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1770 len
= srvstr_push(base_data
, flags2
, p
,
1771 fname
, PTR_DIFF(end_data
, p
),
1772 STR_TERMINATE_ASCII
);
1775 SIVAL(p
,0,0); /* Ensure any padding is null. */
1776 len
= PTR_DIFF(p
, pdata
);
1777 len
= (len
+ 3) & ~3;
1782 /* CIFS UNIX Extension. */
1784 case SMB_FIND_FILE_UNIX
:
1785 case SMB_FIND_FILE_UNIX_INFO2
:
1787 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1789 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1791 if (info_level
== SMB_FIND_FILE_UNIX
) {
1792 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1793 p
= store_file_unix_basic(conn
, p
,
1795 len
= srvstr_push(base_data
, flags2
, p
,
1796 fname
, PTR_DIFF(end_data
, p
),
1799 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1800 p
= store_file_unix_basic_info2(conn
, p
,
1804 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1805 PTR_DIFF(end_data
, p
), 0);
1806 SIVAL(nameptr
, 0, len
);
1810 SIVAL(p
,0,0); /* Ensure any padding is null. */
1812 len
= PTR_DIFF(p
, pdata
);
1813 len
= (len
+ 3) & ~3;
1814 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1816 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1825 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1826 /* Move the dirptr back to prev_dirpos */
1827 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1828 *out_of_space
= True
;
1829 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1830 return False
; /* Not finished - just out of space */
1833 /* Setup the last entry pointer, as an offset from base_data */
1834 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1835 /* Advance the data pointer to the next slot */
1841 /****************************************************************************
1842 Reply to a TRANS2_FINDFIRST.
1843 ****************************************************************************/
1845 static void call_trans2findfirst(connection_struct
*conn
,
1846 struct smb_request
*req
,
1847 char **pparams
, int total_params
,
1848 char **ppdata
, int total_data
,
1849 unsigned int max_data_bytes
)
1851 /* We must be careful here that we don't return more than the
1852 allowed number of data bytes. If this means returning fewer than
1853 maxentries then so be it. We assume that the redirector has
1854 enough room for the fixed number of parameter bytes it has
1856 char *params
= *pparams
;
1857 char *pdata
= *ppdata
;
1861 uint16 findfirst_flags
;
1862 bool close_after_first
;
1864 bool requires_resume_key
;
1866 char *directory
= NULL
;
1867 const char *mask
= NULL
;
1869 int last_entry_off
=0;
1873 bool finished
= False
;
1874 bool dont_descend
= False
;
1875 bool out_of_space
= False
;
1876 int space_remaining
;
1877 bool mask_contains_wcard
= False
;
1878 SMB_STRUCT_STAT sbuf
;
1879 struct ea_list
*ea_list
= NULL
;
1880 NTSTATUS ntstatus
= NT_STATUS_OK
;
1881 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1882 TALLOC_CTX
*ctx
= talloc_tos();
1884 if (total_params
< 13) {
1885 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1889 dirtype
= SVAL(params
,0);
1890 maxentries
= SVAL(params
,2);
1891 findfirst_flags
= SVAL(params
,4);
1892 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1893 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1894 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1895 info_level
= SVAL(params
,6);
1897 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1898 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1899 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1900 info_level
, max_data_bytes
));
1903 /* W2K3 seems to treat zero as 1. */
1907 switch (info_level
) {
1908 case SMB_FIND_INFO_STANDARD
:
1909 case SMB_FIND_EA_SIZE
:
1910 case SMB_FIND_EA_LIST
:
1911 case SMB_FIND_FILE_DIRECTORY_INFO
:
1912 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1913 case SMB_FIND_FILE_NAMES_INFO
:
1914 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1915 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1916 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1918 case SMB_FIND_FILE_UNIX
:
1919 case SMB_FIND_FILE_UNIX_INFO2
:
1920 if (!lp_unix_extensions()) {
1921 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1926 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1930 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1931 params
+12, total_params
- 12,
1932 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1933 if (!NT_STATUS_IS_OK(ntstatus
)) {
1934 reply_nterror(req
, ntstatus
);
1938 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1939 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1942 &mask_contains_wcard
);
1943 if (!NT_STATUS_IS_OK(ntstatus
)) {
1944 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1945 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1946 ERRSRV
, ERRbadpath
);
1949 reply_nterror(req
, ntstatus
);
1953 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, NULL
, &sbuf
);
1954 if (!NT_STATUS_IS_OK(ntstatus
)) {
1955 reply_nterror(req
, ntstatus
);
1959 ntstatus
= check_name(conn
, directory
);
1960 if (!NT_STATUS_IS_OK(ntstatus
)) {
1961 reply_nterror(req
, ntstatus
);
1965 p
= strrchr_m(directory
,'/');
1967 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1968 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1970 mask_contains_wcard
= True
;
1974 directory
= talloc_strdup(talloc_tos(), "./");
1976 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1984 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
1986 if (info_level
== SMB_FIND_EA_LIST
) {
1989 if (total_data
< 4) {
1990 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1994 ea_size
= IVAL(pdata
,0);
1995 if (ea_size
!= total_data
) {
1996 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1997 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
1998 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2002 if (!lp_ea_support(SNUM(conn
))) {
2003 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2007 /* Pull out the list of names. */
2008 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2015 *ppdata
= (char *)SMB_REALLOC(
2016 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2017 if(*ppdata
== NULL
) {
2018 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2022 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2024 /* Realloc the params space */
2025 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2026 if (*pparams
== NULL
) {
2027 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2032 /* Save the wildcard match and attribs we are using on this directory -
2033 needed as lanman2 assumes these are being saved between calls */
2035 ntstatus
= dptr_create(conn
,
2041 mask_contains_wcard
,
2045 if (!NT_STATUS_IS_OK(ntstatus
)) {
2046 reply_nterror(req
, ntstatus
);
2050 dptr_num
= dptr_dnum(conn
->dirptr
);
2051 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2053 /* We don't need to check for VOL here as this is returned by
2054 a different TRANS2 call. */
2056 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2057 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2058 dont_descend
= True
;
2061 space_remaining
= max_data_bytes
;
2062 out_of_space
= False
;
2064 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2065 bool got_exact_match
= False
;
2067 /* this is a heuristic to avoid seeking the dirptr except when
2068 absolutely necessary. It allows for a filename of about 40 chars */
2069 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2070 out_of_space
= True
;
2073 finished
= !get_lanman2_dir_entry(ctx
,
2076 mask
,dirtype
,info_level
,
2077 requires_resume_key
,dont_descend
,
2080 space_remaining
, &out_of_space
,
2082 &last_entry_off
, ea_list
);
2085 if (finished
&& out_of_space
)
2088 if (!finished
&& !out_of_space
)
2092 * As an optimisation if we know we aren't looking
2093 * for a wildcard name (ie. the name matches the wildcard exactly)
2094 * then we can finish on any (first) match.
2095 * This speeds up large directory searches. JRA.
2101 /* Ensure space_remaining never goes -ve. */
2102 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2103 space_remaining
= 0;
2104 out_of_space
= true;
2106 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2110 /* Check if we can close the dirptr */
2111 if(close_after_first
|| (finished
&& close_if_end
)) {
2112 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2113 dptr_close(&dptr_num
);
2117 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2118 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2119 * the protocol level is less than NT1. Tested with smbclient. JRA.
2120 * This should fix the OS/2 client bug #2335.
2123 if(numentries
== 0) {
2124 dptr_close(&dptr_num
);
2125 if (Protocol
< PROTOCOL_NT1
) {
2126 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2129 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2130 ERRDOS
, ERRbadfile
);
2135 /* At this point pdata points to numentries directory entries. */
2137 /* Set up the return parameter block */
2138 SSVAL(params
,0,dptr_num
);
2139 SSVAL(params
,2,numentries
);
2140 SSVAL(params
,4,finished
);
2141 SSVAL(params
,6,0); /* Never an EA error */
2142 SSVAL(params
,8,last_entry_off
);
2144 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2147 if ((! *directory
) && dptr_path(dptr_num
)) {
2148 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2154 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2155 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2156 mask
, directory
, dirtype
, numentries
) );
2159 * Force a name mangle here to ensure that the
2160 * mask as an 8.3 name is top of the mangled cache.
2161 * The reasons for this are subtle. Don't remove
2162 * this code unless you know what you are doing
2163 * (see PR#13758). JRA.
2166 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2167 char mangled_name
[13];
2168 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2174 /****************************************************************************
2175 Reply to a TRANS2_FINDNEXT.
2176 ****************************************************************************/
2178 static void call_trans2findnext(connection_struct
*conn
,
2179 struct smb_request
*req
,
2180 char **pparams
, int total_params
,
2181 char **ppdata
, int total_data
,
2182 unsigned int max_data_bytes
)
2184 /* We must be careful here that we don't return more than the
2185 allowed number of data bytes. If this means returning fewer than
2186 maxentries then so be it. We assume that the redirector has
2187 enough room for the fixed number of parameter bytes it has
2189 char *params
= *pparams
;
2190 char *pdata
= *ppdata
;
2196 uint16 findnext_flags
;
2197 bool close_after_request
;
2199 bool requires_resume_key
;
2201 bool mask_contains_wcard
= False
;
2202 char *resume_name
= NULL
;
2203 const char *mask
= NULL
;
2204 const char *directory
= NULL
;
2208 int i
, last_entry_off
=0;
2209 bool finished
= False
;
2210 bool dont_descend
= False
;
2211 bool out_of_space
= False
;
2212 int space_remaining
;
2213 struct ea_list
*ea_list
= NULL
;
2214 NTSTATUS ntstatus
= NT_STATUS_OK
;
2215 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2216 TALLOC_CTX
*ctx
= talloc_tos();
2218 if (total_params
< 13) {
2219 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2223 dptr_num
= SVAL(params
,0);
2224 maxentries
= SVAL(params
,2);
2225 info_level
= SVAL(params
,4);
2226 resume_key
= IVAL(params
,6);
2227 findnext_flags
= SVAL(params
,10);
2228 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2229 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2230 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2231 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2233 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2235 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2236 &mask_contains_wcard
);
2237 if (!NT_STATUS_IS_OK(ntstatus
)) {
2238 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2239 complain (it thinks we're asking for the directory above the shared
2240 path or an invalid name). Catch this as the resume name is only compared, never used in
2241 a file access. JRA. */
2242 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2243 &resume_name
, params
+12,
2247 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2248 reply_nterror(req
, ntstatus
);
2253 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2254 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2255 resume_key = %d resume name = %s continue=%d level = %d\n",
2256 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2257 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2260 /* W2K3 seems to treat zero as 1. */
2264 switch (info_level
) {
2265 case SMB_FIND_INFO_STANDARD
:
2266 case SMB_FIND_EA_SIZE
:
2267 case SMB_FIND_EA_LIST
:
2268 case SMB_FIND_FILE_DIRECTORY_INFO
:
2269 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2270 case SMB_FIND_FILE_NAMES_INFO
:
2271 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2272 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2273 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2275 case SMB_FIND_FILE_UNIX
:
2276 case SMB_FIND_FILE_UNIX_INFO2
:
2277 if (!lp_unix_extensions()) {
2278 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2283 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2287 if (info_level
== SMB_FIND_EA_LIST
) {
2290 if (total_data
< 4) {
2291 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2295 ea_size
= IVAL(pdata
,0);
2296 if (ea_size
!= total_data
) {
2297 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2298 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2303 if (!lp_ea_support(SNUM(conn
))) {
2304 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2308 /* Pull out the list of names. */
2309 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2316 *ppdata
= (char *)SMB_REALLOC(
2317 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2318 if(*ppdata
== NULL
) {
2319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2324 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2326 /* Realloc the params space */
2327 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2328 if(*pparams
== NULL
) {
2329 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2335 /* Check that the dptr is valid */
2336 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2337 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2341 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2343 /* Get the wildcard mask from the dptr */
2344 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2345 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2346 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2351 directory
= conn
->dirpath
;
2353 /* Get the attr mask from the dptr */
2354 dirtype
= dptr_attr(dptr_num
);
2356 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2357 dptr_num
, mask
, dirtype
,
2359 dptr_TellDir(conn
->dirptr
)));
2361 /* We don't need to check for VOL here as this is returned by
2362 a different TRANS2 call. */
2364 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2365 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2366 dont_descend
= True
;
2369 space_remaining
= max_data_bytes
;
2370 out_of_space
= False
;
2373 * Seek to the correct position. We no longer use the resume key but
2374 * depend on the last file name instead.
2377 if(*resume_name
&& !continue_bit
) {
2380 long current_pos
= 0;
2382 * Remember, name_to_8_3 is called by
2383 * get_lanman2_dir_entry(), so the resume name
2384 * could be mangled. Ensure we check the unmangled name.
2387 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2388 char *new_resume_name
= NULL
;
2389 mangle_lookup_name_from_8_3(ctx
,
2393 if (new_resume_name
) {
2394 resume_name
= new_resume_name
;
2399 * Fix for NT redirector problem triggered by resume key indexes
2400 * changing between directory scans. We now return a resume key of 0
2401 * and instead look for the filename to continue from (also given
2402 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2403 * findfirst/findnext (as is usual) then the directory pointer
2404 * should already be at the correct place.
2407 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2408 } /* end if resume_name && !continue_bit */
2410 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2411 bool got_exact_match
= False
;
2413 /* this is a heuristic to avoid seeking the dirptr except when
2414 absolutely necessary. It allows for a filename of about 40 chars */
2415 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2416 out_of_space
= True
;
2419 finished
= !get_lanman2_dir_entry(ctx
,
2422 mask
,dirtype
,info_level
,
2423 requires_resume_key
,dont_descend
,
2426 space_remaining
, &out_of_space
,
2428 &last_entry_off
, ea_list
);
2431 if (finished
&& out_of_space
)
2434 if (!finished
&& !out_of_space
)
2438 * As an optimisation if we know we aren't looking
2439 * for a wildcard name (ie. the name matches the wildcard exactly)
2440 * then we can finish on any (first) match.
2441 * This speeds up large directory searches. JRA.
2447 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2450 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2451 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2452 mask
, directory
, dirtype
, numentries
) );
2454 /* Check if we can close the dirptr */
2455 if(close_after_request
|| (finished
&& close_if_end
)) {
2456 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2457 dptr_close(&dptr_num
); /* This frees up the saved mask */
2460 /* Set up the return parameter block */
2461 SSVAL(params
,0,numentries
);
2462 SSVAL(params
,2,finished
);
2463 SSVAL(params
,4,0); /* Never an EA error */
2464 SSVAL(params
,6,last_entry_off
);
2466 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2472 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2474 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2478 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2480 SMB_ASSERT(extended_info
!= NULL
);
2482 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2483 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2484 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2485 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2486 #ifdef SAMBA_VERSION_REVISION
2487 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2489 extended_info
->samba_subversion
= 0;
2490 #ifdef SAMBA_VERSION_RC_RELEASE
2491 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2493 #ifdef SAMBA_VERSION_PRE_RELEASE
2494 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2497 #ifdef SAMBA_VERSION_VENDOR_PATCH
2498 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2500 extended_info
->samba_gitcommitdate
= 0;
2501 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2502 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2505 memset(extended_info
->samba_version_string
, 0,
2506 sizeof(extended_info
->samba_version_string
));
2508 snprintf (extended_info
->samba_version_string
,
2509 sizeof(extended_info
->samba_version_string
),
2510 "%s", samba_version_string());
2513 /****************************************************************************
2514 Reply to a TRANS2_QFSINFO (query filesystem info).
2515 ****************************************************************************/
2517 static void call_trans2qfsinfo(connection_struct
*conn
,
2518 struct smb_request
*req
,
2519 char **pparams
, int total_params
,
2520 char **ppdata
, int total_data
,
2521 unsigned int max_data_bytes
)
2523 char *pdata
, *end_data
;
2524 char *params
= *pparams
;
2528 const char *vname
= volume_label(SNUM(conn
));
2529 int snum
= SNUM(conn
);
2530 char *fstype
= lp_fstype(SNUM(conn
));
2531 uint32 additional_flags
= 0;
2533 if (total_params
< 2) {
2534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2538 info_level
= SVAL(params
,0);
2541 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2542 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2543 "info level (0x%x) on IPC$.\n",
2544 (unsigned int)info_level
));
2545 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2550 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2551 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2552 DEBUG(0,("call_trans2qfsinfo: encryption required "
2553 "and info level 0x%x sent.\n",
2554 (unsigned int)info_level
));
2555 exit_server_cleanly("encryption required "
2561 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2563 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2564 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2565 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2569 *ppdata
= (char *)SMB_REALLOC(
2570 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2571 if (*ppdata
== NULL
) {
2572 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2577 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2578 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2580 switch (info_level
) {
2581 case SMB_INFO_ALLOCATION
:
2583 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2585 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2586 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2590 block_size
= lp_block_size(snum
);
2591 if (bsize
< block_size
) {
2592 SMB_BIG_UINT factor
= block_size
/bsize
;
2597 if (bsize
> block_size
) {
2598 SMB_BIG_UINT factor
= bsize
/block_size
;
2603 bytes_per_sector
= 512;
2604 sectors_per_unit
= bsize
/bytes_per_sector
;
2606 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2607 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2608 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2610 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2611 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2612 SIVAL(pdata
,l1_cUnit
,dsize
);
2613 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2614 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2618 case SMB_INFO_VOLUME
:
2619 /* Return volume name */
2621 * Add volume serial number - hash of a combination of
2622 * the called hostname and the service name.
2624 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2626 * Win2k3 and previous mess this up by sending a name length
2627 * one byte short. I believe only older clients (OS/2 Win9x) use
2628 * this call so try fixing this by adding a terminating null to
2629 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2633 pdata
+l2_vol_szVolLabel
, vname
,
2634 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2635 STR_NOALIGN
|STR_TERMINATE
);
2636 SCVAL(pdata
,l2_vol_cch
,len
);
2637 data_len
= l2_vol_szVolLabel
+ len
;
2638 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2639 (unsigned)st
.st_ctime
, len
, vname
));
2642 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2643 case SMB_FS_ATTRIBUTE_INFORMATION
:
2645 additional_flags
= 0;
2646 #if defined(HAVE_SYS_QUOTAS)
2647 additional_flags
|= FILE_VOLUME_QUOTAS
;
2650 if(lp_nt_acl_support(SNUM(conn
))) {
2651 additional_flags
|= FILE_PERSISTENT_ACLS
;
2654 /* Capabilities are filled in at connection time through STATVFS call */
2655 additional_flags
|= conn
->fs_capabilities
;
2657 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2658 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2659 additional_flags
); /* FS ATTRIBUTES */
2661 SIVAL(pdata
,4,255); /* Max filename component length */
2662 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2663 and will think we can't do long filenames */
2664 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2665 PTR_DIFF(end_data
, pdata
+12),
2668 data_len
= 12 + len
;
2671 case SMB_QUERY_FS_LABEL_INFO
:
2672 case SMB_FS_LABEL_INFORMATION
:
2673 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2674 PTR_DIFF(end_data
, pdata
+4), 0);
2679 case SMB_QUERY_FS_VOLUME_INFO
:
2680 case SMB_FS_VOLUME_INFORMATION
:
2683 * Add volume serial number - hash of a combination of
2684 * the called hostname and the service name.
2686 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2687 (str_checksum(get_local_machine_name())<<16));
2689 /* Max label len is 32 characters. */
2690 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2691 PTR_DIFF(end_data
, pdata
+18),
2693 SIVAL(pdata
,12,len
);
2696 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2697 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2700 case SMB_QUERY_FS_SIZE_INFO
:
2701 case SMB_FS_SIZE_INFORMATION
:
2703 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2705 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2706 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2709 block_size
= lp_block_size(snum
);
2710 if (bsize
< block_size
) {
2711 SMB_BIG_UINT factor
= block_size
/bsize
;
2716 if (bsize
> block_size
) {
2717 SMB_BIG_UINT factor
= bsize
/block_size
;
2722 bytes_per_sector
= 512;
2723 sectors_per_unit
= bsize
/bytes_per_sector
;
2724 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2725 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2726 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2727 SBIG_UINT(pdata
,0,dsize
);
2728 SBIG_UINT(pdata
,8,dfree
);
2729 SIVAL(pdata
,16,sectors_per_unit
);
2730 SIVAL(pdata
,20,bytes_per_sector
);
2734 case SMB_FS_FULL_SIZE_INFORMATION
:
2736 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2738 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2739 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2742 block_size
= lp_block_size(snum
);
2743 if (bsize
< block_size
) {
2744 SMB_BIG_UINT factor
= block_size
/bsize
;
2749 if (bsize
> block_size
) {
2750 SMB_BIG_UINT factor
= bsize
/block_size
;
2755 bytes_per_sector
= 512;
2756 sectors_per_unit
= bsize
/bytes_per_sector
;
2757 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2758 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2759 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2760 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2761 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2762 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2763 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2764 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2768 case SMB_QUERY_FS_DEVICE_INFO
:
2769 case SMB_FS_DEVICE_INFORMATION
:
2771 SIVAL(pdata
,0,0); /* dev type */
2772 SIVAL(pdata
,4,0); /* characteristics */
2775 #ifdef HAVE_SYS_QUOTAS
2776 case SMB_FS_QUOTA_INFORMATION
:
2778 * what we have to send --metze:
2780 * Unknown1: 24 NULL bytes
2781 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2782 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2783 * Quota Flags: 2 byte :
2784 * Unknown3: 6 NULL bytes
2788 * details for Quota Flags:
2790 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2791 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2792 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2793 * 0x0001 Enable Quotas: enable quota for this fs
2797 /* we need to fake up a fsp here,
2798 * because its not send in this call
2801 SMB_NTQUOTA_STRUCT quotas
;
2804 ZERO_STRUCT(quotas
);
2810 if (current_user
.ut
.uid
!= 0) {
2811 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2812 lp_servicename(SNUM(conn
)),conn
->user
));
2813 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2817 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2818 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2819 reply_doserror(req
, ERRSRV
, ERRerror
);
2825 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2827 /* Unknown1 24 NULL bytes*/
2828 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2829 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2830 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2832 /* Default Soft Quota 8 bytes */
2833 SBIG_UINT(pdata
,24,quotas
.softlim
);
2835 /* Default Hard Quota 8 bytes */
2836 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2838 /* Quota flag 2 bytes */
2839 SSVAL(pdata
,40,quotas
.qflags
);
2841 /* Unknown3 6 NULL bytes */
2847 #endif /* HAVE_SYS_QUOTAS */
2848 case SMB_FS_OBJECTID_INFORMATION
:
2850 unsigned char objid
[16];
2851 struct smb_extended_info extended_info
;
2852 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2853 samba_extended_info_version (&extended_info
);
2854 SIVAL(pdata
,16,extended_info
.samba_magic
);
2855 SIVAL(pdata
,20,extended_info
.samba_version
);
2856 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2857 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2858 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2864 * Query the version and capabilities of the CIFS UNIX extensions
2868 case SMB_QUERY_CIFS_UNIX_INFO
:
2870 bool large_write
= lp_min_receive_file_size() &&
2871 !srv_is_signing_active();
2872 bool large_read
= !srv_is_signing_active();
2873 int encrypt_caps
= 0;
2875 if (!lp_unix_extensions()) {
2876 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2880 switch (conn
->encrypt_level
) {
2886 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2889 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2890 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2891 large_write
= false;
2897 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2898 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2900 /* We have POSIX ACLs, pathname, encryption,
2901 * large read/write, and locking capability. */
2903 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2904 CIFS_UNIX_POSIX_ACLS_CAP
|
2905 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2906 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2907 CIFS_UNIX_EXTATTR_CAP
|
2908 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2910 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2912 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2916 case SMB_QUERY_POSIX_FS_INFO
:
2919 vfs_statvfs_struct svfs
;
2921 if (!lp_unix_extensions()) {
2922 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2926 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2930 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2931 SIVAL(pdata
,4,svfs
.BlockSize
);
2932 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2933 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2934 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2935 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2936 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2937 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2938 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2940 } else if (rc
== EOPNOTSUPP
) {
2941 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2943 #endif /* EOPNOTSUPP */
2945 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2946 reply_doserror(req
, ERRSRV
, ERRerror
);
2952 case SMB_QUERY_POSIX_WHOAMI
:
2958 if (!lp_unix_extensions()) {
2959 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2963 if (max_data_bytes
< 40) {
2964 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2968 /* We ARE guest if global_sid_Builtin_Guests is
2969 * in our list of SIDs.
2971 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
2972 current_user
.nt_user_token
)) {
2973 flags
|= SMB_WHOAMI_GUEST
;
2976 /* We are NOT guest if global_sid_Authenticated_Users
2977 * is in our list of SIDs.
2979 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
2980 current_user
.nt_user_token
)) {
2981 flags
&= ~SMB_WHOAMI_GUEST
;
2984 /* NOTE: 8 bytes for UID/GID, irrespective of native
2985 * platform size. This matches
2986 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2988 data_len
= 4 /* flags */
2995 + 4 /* pad/reserved */
2996 + (current_user
.ut
.ngroups
* 8)
2998 + (current_user
.nt_user_token
->num_sids
*
3002 SIVAL(pdata
, 0, flags
);
3003 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3004 SBIG_UINT(pdata
, 8, (SMB_BIG_UINT
)current_user
.ut
.uid
);
3005 SBIG_UINT(pdata
, 16, (SMB_BIG_UINT
)current_user
.ut
.gid
);
3008 if (data_len
>= max_data_bytes
) {
3009 /* Potential overflow, skip the GIDs and SIDs. */
3011 SIVAL(pdata
, 24, 0); /* num_groups */
3012 SIVAL(pdata
, 28, 0); /* num_sids */
3013 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3014 SIVAL(pdata
, 36, 0); /* reserved */
3020 SIVAL(pdata
, 24, current_user
.ut
.ngroups
);
3022 current_user
.nt_user_token
->num_sids
);
3024 /* We walk the SID list twice, but this call is fairly
3025 * infrequent, and I don't expect that it's performance
3026 * sensitive -- jpeach
3028 for (i
= 0, sid_bytes
= 0;
3029 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
3030 sid_bytes
+= ndr_size_dom_sid(
3031 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
3034 /* SID list byte count */
3035 SIVAL(pdata
, 32, sid_bytes
);
3037 /* 4 bytes pad/reserved - must be zero */
3038 SIVAL(pdata
, 36, 0);
3042 for (i
= 0; i
< current_user
.ut
.ngroups
; ++i
) {
3043 SBIG_UINT(pdata
, data_len
,
3044 (SMB_BIG_UINT
)current_user
.ut
.groups
[i
]);
3050 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
3051 int sid_len
= ndr_size_dom_sid(
3052 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
3054 sid_linearize(pdata
+ data_len
, sid_len
,
3055 ¤t_user
.nt_user_token
->user_sids
[i
]);
3056 data_len
+= sid_len
;
3062 case SMB_MAC_QUERY_FS_INFO
:
3064 * Thursby MAC extension... ONLY on NTFS filesystems
3065 * once we do streams then we don't need this
3067 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3069 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3074 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3079 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3082 DEBUG( 4, ( "%s info_level = %d\n",
3083 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
3088 /****************************************************************************
3089 Reply to a TRANS2_SETFSINFO (set filesystem info).
3090 ****************************************************************************/
3092 static void call_trans2setfsinfo(connection_struct
*conn
,
3093 struct smb_request
*req
,
3094 char **pparams
, int total_params
,
3095 char **ppdata
, int total_data
,
3096 unsigned int max_data_bytes
)
3098 char *pdata
= *ppdata
;
3099 char *params
= *pparams
;
3102 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3105 if (total_params
< 4) {
3106 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3108 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3112 info_level
= SVAL(params
,2);
3115 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3116 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3117 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3118 "info level (0x%x) on IPC$.\n",
3119 (unsigned int)info_level
));
3120 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3125 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3126 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3127 DEBUG(0,("call_trans2setfsinfo: encryption required "
3128 "and info level 0x%x sent.\n",
3129 (unsigned int)info_level
));
3130 exit_server_cleanly("encryption required "
3136 switch(info_level
) {
3137 case SMB_SET_CIFS_UNIX_INFO
:
3139 uint16 client_unix_major
;
3140 uint16 client_unix_minor
;
3141 uint32 client_unix_cap_low
;
3142 uint32 client_unix_cap_high
;
3144 if (!lp_unix_extensions()) {
3146 NT_STATUS_INVALID_LEVEL
);
3150 /* There should be 12 bytes of capabilities set. */
3151 if (total_data
< 8) {
3154 NT_STATUS_INVALID_PARAMETER
);
3157 client_unix_major
= SVAL(pdata
,0);
3158 client_unix_minor
= SVAL(pdata
,2);
3159 client_unix_cap_low
= IVAL(pdata
,4);
3160 client_unix_cap_high
= IVAL(pdata
,8);
3161 /* Just print these values for now. */
3162 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3163 cap_low = 0x%x, cap_high = 0x%x\n",
3164 (unsigned int)client_unix_major
,
3165 (unsigned int)client_unix_minor
,
3166 (unsigned int)client_unix_cap_low
,
3167 (unsigned int)client_unix_cap_high
));
3169 /* Here is where we must switch to posix pathname processing... */
3170 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3171 lp_set_posix_pathnames();
3172 mangle_change_to_posix();
3175 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3176 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3177 /* Client that knows how to do posix locks,
3178 * but not posix open/mkdir operations. Set a
3179 * default type for read/write checks. */
3181 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3187 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3190 size_t param_len
= 0;
3191 size_t data_len
= total_data
;
3193 if (!lp_unix_extensions()) {
3196 NT_STATUS_INVALID_LEVEL
);
3200 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3203 NT_STATUS_NOT_SUPPORTED
);
3207 DEBUG( 4,("call_trans2setfsinfo: "
3208 "request transport encryption.\n"));
3210 status
= srv_request_encryption_setup(conn
,
3211 (unsigned char **)ppdata
,
3213 (unsigned char **)pparams
,
3216 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3217 !NT_STATUS_IS_OK(status
)) {
3218 reply_nterror(req
, status
);
3222 send_trans2_replies(conn
, req
,
3229 if (NT_STATUS_IS_OK(status
)) {
3230 /* Server-side transport
3231 * encryption is now *on*. */
3232 status
= srv_encryption_start(conn
);
3233 if (!NT_STATUS_IS_OK(status
)) {
3234 exit_server_cleanly(
3235 "Failure in setting "
3236 "up encrypted transport");
3242 case SMB_FS_QUOTA_INFORMATION
:
3244 files_struct
*fsp
= NULL
;
3245 SMB_NTQUOTA_STRUCT quotas
;
3247 ZERO_STRUCT(quotas
);
3250 if ((current_user
.ut
.uid
!= 0)||!CAN_WRITE(conn
)) {
3251 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3252 lp_servicename(SNUM(conn
)),conn
->user
));
3253 reply_doserror(req
, ERRSRV
, ERRaccess
);
3257 /* note: normaly there're 48 bytes,
3258 * but we didn't use the last 6 bytes for now
3261 fsp
= file_fsp(SVAL(params
,0));
3262 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
3263 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3265 req
, NT_STATUS_INVALID_HANDLE
);
3269 if (total_data
< 42) {
3270 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3274 NT_STATUS_INVALID_PARAMETER
);
3278 /* unknown_1 24 NULL bytes in pdata*/
3280 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3281 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3282 #ifdef LARGE_SMB_OFF_T
3283 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3284 #else /* LARGE_SMB_OFF_T */
3285 if ((IVAL(pdata
,28) != 0)&&
3286 ((quotas
.softlim
!= 0xFFFFFFFF)||
3287 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3288 /* more than 32 bits? */
3291 NT_STATUS_INVALID_PARAMETER
);
3294 #endif /* LARGE_SMB_OFF_T */
3296 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3297 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3298 #ifdef LARGE_SMB_OFF_T
3299 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3300 #else /* LARGE_SMB_OFF_T */
3301 if ((IVAL(pdata
,36) != 0)&&
3302 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3303 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3304 /* more than 32 bits? */
3307 NT_STATUS_INVALID_PARAMETER
);
3310 #endif /* LARGE_SMB_OFF_T */
3312 /* quota_flags 2 bytes **/
3313 quotas
.qflags
= SVAL(pdata
,40);
3315 /* unknown_2 6 NULL bytes follow*/
3317 /* now set the quotas */
3318 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3319 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3320 reply_doserror(req
, ERRSRV
, ERRerror
);
3327 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3329 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3335 * sending this reply works fine,
3336 * but I'm not sure it's the same
3337 * like windows do...
3340 reply_outbuf(req
, 10, 0);
3343 #if defined(HAVE_POSIX_ACLS)
3344 /****************************************************************************
3345 Utility function to count the number of entries in a POSIX acl.
3346 ****************************************************************************/
3348 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3350 unsigned int ace_count
= 0;
3351 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3352 SMB_ACL_ENTRY_T entry
;
3354 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3356 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3357 entry_id
= SMB_ACL_NEXT_ENTRY
;
3364 /****************************************************************************
3365 Utility function to marshall a POSIX acl into wire format.
3366 ****************************************************************************/
3368 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3370 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3371 SMB_ACL_ENTRY_T entry
;
3373 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3374 SMB_ACL_TAG_T tagtype
;
3375 SMB_ACL_PERMSET_T permset
;
3376 unsigned char perms
= 0;
3377 unsigned int own_grp
;
3380 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3381 entry_id
= SMB_ACL_NEXT_ENTRY
;
3384 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3385 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3389 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3390 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3394 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3395 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3396 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3398 SCVAL(pdata
,1,perms
);
3401 case SMB_ACL_USER_OBJ
:
3402 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3403 own_grp
= (unsigned int)pst
->st_uid
;
3404 SIVAL(pdata
,2,own_grp
);
3409 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3414 own_grp
= (unsigned int)*puid
;
3415 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3416 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3417 SIVAL(pdata
,2,own_grp
);
3421 case SMB_ACL_GROUP_OBJ
:
3422 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3423 own_grp
= (unsigned int)pst
->st_gid
;
3424 SIVAL(pdata
,2,own_grp
);
3429 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3434 own_grp
= (unsigned int)*pgid
;
3435 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3436 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3437 SIVAL(pdata
,2,own_grp
);
3442 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3443 SIVAL(pdata
,2,0xFFFFFFFF);
3444 SIVAL(pdata
,6,0xFFFFFFFF);
3447 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3448 SIVAL(pdata
,2,0xFFFFFFFF);
3449 SIVAL(pdata
,6,0xFFFFFFFF);
3452 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3455 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3462 /****************************************************************************
3463 Store the FILE_UNIX_BASIC info.
3464 ****************************************************************************/
3466 static char *store_file_unix_basic(connection_struct
*conn
,
3469 const SMB_STRUCT_STAT
*psbuf
)
3471 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3472 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3474 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3477 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3480 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3481 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3482 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3485 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3489 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3493 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3496 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3500 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3504 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3507 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3511 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3518 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3519 * the chflags(2) (or equivalent) flags.
3521 * XXX: this really should be behind the VFS interface. To do this, we would
3522 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3523 * Each VFS module could then implement its own mapping as appropriate for the
3524 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3526 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3530 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3534 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3538 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3542 { UF_HIDDEN
, EXT_HIDDEN
},
3545 /* Do not remove. We need to guarantee that this array has at least one
3546 * entry to build on HP-UX.
3552 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3553 uint32
*smb_fflags
, uint32
*smb_fmask
)
3555 #ifdef HAVE_STAT_ST_FLAGS
3558 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3559 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3560 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3561 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3564 #endif /* HAVE_STAT_ST_FLAGS */
3567 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3568 const uint32 smb_fflags
,
3569 const uint32 smb_fmask
,
3572 #ifdef HAVE_STAT_ST_FLAGS
3573 uint32 max_fmask
= 0;
3576 *stat_fflags
= psbuf
->st_flags
;
3578 /* For each flags requested in smb_fmask, check the state of the
3579 * corresponding flag in smb_fflags and set or clear the matching
3583 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3584 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3585 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3586 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3587 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3589 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3594 /* If smb_fmask is asking to set any bits that are not supported by
3595 * our flag mappings, we should fail.
3597 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3604 #endif /* HAVE_STAT_ST_FLAGS */
3608 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3609 * of file flags and birth (create) time.
3611 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3614 const SMB_STRUCT_STAT
*psbuf
)
3616 uint32 file_flags
= 0;
3617 uint32 flags_mask
= 0;
3619 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3621 /* Create (birth) time 64 bit */
3622 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3625 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3626 SIVAL(pdata
, 0, file_flags
); /* flags */
3627 SIVAL(pdata
, 4, flags_mask
); /* mask */
3633 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3634 const struct stream_struct
*streams
,
3636 unsigned int max_data_bytes
,
3637 unsigned int *data_size
)
3640 unsigned int ofs
= 0;
3642 for (i
=0; i
<num_streams
; i
++) {
3643 unsigned int next_offset
;
3645 smb_ucs2_t
*namebuf
;
3647 namelen
= push_ucs2_talloc(talloc_tos(), &namebuf
,
3650 if ((namelen
== (size_t)-1) || (namelen
<= 2)) {
3651 return NT_STATUS_INVALID_PARAMETER
;
3655 * name_buf is now null-terminated, we need to marshall as not
3661 if (ofs
+ 24 + namelen
> max_data_bytes
) {
3662 TALLOC_FREE(namebuf
);
3663 return NT_STATUS_BUFFER_TOO_SMALL
;
3666 SIVAL(data
, ofs
+4, namelen
);
3667 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3668 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3669 memcpy(data
+ofs
+24, namebuf
, namelen
);
3670 TALLOC_FREE(namebuf
);
3672 next_offset
= ofs
+ 24 + namelen
;
3674 if (i
== num_streams
-1) {
3675 SIVAL(data
, ofs
, 0);
3678 unsigned int align
= ndr_align_size(next_offset
, 8);
3680 if (next_offset
+ align
> max_data_bytes
) {
3681 return NT_STATUS_BUFFER_TOO_SMALL
;
3684 memset(data
+next_offset
, 0, align
);
3685 next_offset
+= align
;
3687 SIVAL(data
, ofs
, next_offset
- ofs
);
3696 return NT_STATUS_OK
;
3699 /****************************************************************************
3700 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3701 ****************************************************************************/
3703 static void call_trans2qpipeinfo(connection_struct
*conn
,
3704 struct smb_request
*req
,
3705 unsigned int tran_call
,
3706 char **pparams
, int total_params
,
3707 char **ppdata
, int total_data
,
3708 unsigned int max_data_bytes
)
3710 char *params
= *pparams
;
3711 char *pdata
= *ppdata
;
3712 unsigned int data_size
= 0;
3713 unsigned int param_size
= 2;
3715 smb_np_struct
*p_pipe
= NULL
;
3718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3722 if (total_params
< 4) {
3723 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3727 p_pipe
= get_rpc_pipe_p(SVAL(params
,0));
3728 if (p_pipe
== NULL
) {
3729 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3733 info_level
= SVAL(params
,2);
3735 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3736 if (*pparams
== NULL
) {
3737 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3742 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3743 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3744 if (*ppdata
== NULL
) {
3745 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3750 switch (info_level
) {
3751 case SMB_FILE_STANDARD_INFORMATION
:
3753 SOFF_T(pdata
,0,4096LL);
3760 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3764 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3770 /****************************************************************************
3771 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3772 file name or file id).
3773 ****************************************************************************/
3775 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3776 struct smb_request
*req
,
3777 unsigned int tran_call
,
3778 char **pparams
, int total_params
,
3779 char **ppdata
, int total_data
,
3780 unsigned int max_data_bytes
)
3782 char *params
= *pparams
;
3783 char *pdata
= *ppdata
;
3784 char *dstart
, *dend
;
3788 SMB_OFF_T file_size
=0;
3789 SMB_BIG_UINT allocation_size
=0;
3790 unsigned int data_size
= 0;
3791 unsigned int param_size
= 2;
3792 SMB_STRUCT_STAT sbuf
;
3793 char *dos_fname
= NULL
;
3799 bool delete_pending
= False
;
3801 time_t create_time
, mtime
, atime
;
3802 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3803 struct timespec write_time_ts
;
3804 files_struct
*fsp
= NULL
;
3805 struct file_id fileid
;
3806 struct ea_list
*ea_list
= NULL
;
3807 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3808 char *lock_data
= NULL
;
3809 TALLOC_CTX
*ctx
= talloc_tos();
3812 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3817 ZERO_STRUCT(write_time_ts
);
3819 if (tran_call
== TRANSACT2_QFILEINFO
) {
3820 if (total_params
< 4) {
3821 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3826 call_trans2qpipeinfo(conn
, req
, tran_call
,
3827 pparams
, total_params
,
3833 fsp
= file_fsp(SVAL(params
,0));
3834 info_level
= SVAL(params
,2);
3836 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3838 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3839 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3843 /* Initial check for valid fsp ptr. */
3844 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
3848 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3850 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3854 if(fsp
->fake_file_handle
) {
3856 * This is actually for the QUOTA_FAKE_FILE --metze
3859 /* We know this name is ok, it's already passed the checks. */
3861 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3863 * This is actually a QFILEINFO on a directory
3864 * handle (returned from an NT SMB). NT5.0 seems
3865 * to do this call. JRA.
3868 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3869 /* Always do lstat for UNIX calls. */
3870 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3871 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3872 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3875 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3876 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3877 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3881 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3882 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3885 * Original code - this is an open file.
3887 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3891 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3892 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3893 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3896 pos
= fsp
->fh
->position_information
;
3897 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3898 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3899 access_mask
= fsp
->access_mask
;
3903 NTSTATUS status
= NT_STATUS_OK
;
3906 if (total_params
< 7) {
3907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3911 info_level
= SVAL(params
,0);
3913 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3915 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3916 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3920 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3922 STR_TERMINATE
, &status
);
3923 if (!NT_STATUS_IS_OK(status
)) {
3924 reply_nterror(req
, status
);
3928 status
= resolve_dfspath(ctx
,
3930 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3933 if (!NT_STATUS_IS_OK(status
)) {
3934 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3935 reply_botherror(req
,
3936 NT_STATUS_PATH_NOT_COVERED
,
3937 ERRSRV
, ERRbadpath
);
3939 reply_nterror(req
, status
);
3943 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3944 if (!NT_STATUS_IS_OK(status
)) {
3945 reply_nterror(req
, status
);
3948 status
= check_name(conn
, fname
);
3949 if (!NT_STATUS_IS_OK(status
)) {
3950 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3951 reply_nterror(req
, status
);
3955 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3956 /* Always do lstat for UNIX calls. */
3957 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3958 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3959 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3962 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
3963 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3964 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3968 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3969 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3970 if (delete_pending
) {
3971 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
3976 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3977 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3981 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3982 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
3984 p
= strrchr_m(fname
,'/');
3990 mode
= dos_mode(conn
,fname
,&sbuf
);
3992 mode
= FILE_ATTRIBUTE_NORMAL
;
3994 nlink
= sbuf
.st_nlink
;
3996 if (nlink
&& (mode
&aDIR
)) {
4000 if ((nlink
> 0) && delete_pending
) {
4004 fullpathname
= fname
;
4006 file_size
= get_file_size(sbuf
);
4008 /* Pull out any data sent here before we realloc. */
4009 switch (info_level
) {
4010 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4012 /* Pull any EA list from the data portion. */
4015 if (total_data
< 4) {
4017 req
, NT_STATUS_INVALID_PARAMETER
);
4020 ea_size
= IVAL(pdata
,0);
4022 if (total_data
> 0 && ea_size
!= total_data
) {
4023 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4024 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4026 req
, NT_STATUS_INVALID_PARAMETER
);
4030 if (!lp_ea_support(SNUM(conn
))) {
4031 reply_doserror(req
, ERRDOS
,
4032 ERReasnotsupported
);
4036 /* Pull out the list of names. */
4037 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4040 req
, NT_STATUS_INVALID_PARAMETER
);
4046 case SMB_QUERY_POSIX_LOCK
:
4048 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4049 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4053 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4055 req
, NT_STATUS_INVALID_PARAMETER
);
4059 /* Copy the lock range data. */
4060 lock_data
= (char *)TALLOC_MEMDUP(
4061 ctx
, pdata
, total_data
);
4063 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4071 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4072 if (*pparams
== NULL
) {
4073 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4078 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4079 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4080 if (*ppdata
== NULL
) {
4081 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4086 dend
= dstart
+ data_size
- 1;
4088 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4089 mtime_ts
= get_mtimespec(&sbuf
);
4090 atime_ts
= get_atimespec(&sbuf
);
4092 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
4095 /* Do we have this path open ? */
4097 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4098 fsp1
= file_find_di_first(fileid
);
4099 if (fsp1
&& fsp1
->initial_allocation_size
) {
4100 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
4104 if (!null_timespec(write_time_ts
)) {
4105 mtime_ts
= write_time_ts
;
4108 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4109 dos_filetime_timespec(&create_time_ts
);
4110 dos_filetime_timespec(&mtime_ts
);
4111 dos_filetime_timespec(&atime_ts
);
4114 create_time
= convert_timespec_to_time_t(create_time_ts
);
4115 mtime
= convert_timespec_to_time_t(mtime_ts
);
4116 atime
= convert_timespec_to_time_t(atime_ts
);
4118 /* NT expects the name to be in an exact form of the *full*
4119 filename. See the trans2 torture test */
4120 if (ISDOT(base_name
)) {
4121 dos_fname
= talloc_strdup(ctx
, "\\");
4123 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4127 dos_fname
= talloc_asprintf(ctx
,
4131 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4134 string_replace(dos_fname
, '/', '\\');
4137 switch (info_level
) {
4138 case SMB_INFO_STANDARD
:
4139 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4141 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4142 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4143 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4144 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4145 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4146 SSVAL(pdata
,l1_attrFile
,mode
);
4149 case SMB_INFO_QUERY_EA_SIZE
:
4151 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4154 srv_put_dos_date2(pdata
,0,create_time
);
4155 srv_put_dos_date2(pdata
,4,atime
);
4156 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4157 SIVAL(pdata
,12,(uint32
)file_size
);
4158 SIVAL(pdata
,16,(uint32
)allocation_size
);
4159 SSVAL(pdata
,20,mode
);
4160 SIVAL(pdata
,22,ea_size
);
4164 case SMB_INFO_IS_NAME_VALID
:
4165 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4166 if (tran_call
== TRANSACT2_QFILEINFO
) {
4167 /* os/2 needs this ? really ?*/
4168 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4175 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4177 size_t total_ea_len
= 0;
4178 struct ea_list
*ea_file_list
= NULL
;
4180 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4182 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4183 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4185 if (!ea_list
|| (total_ea_len
> data_size
)) {
4187 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4191 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4195 case SMB_INFO_QUERY_ALL_EAS
:
4197 /* We have data_size bytes to put EA's into. */
4198 size_t total_ea_len
= 0;
4200 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4202 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4203 if (!ea_list
|| (total_ea_len
> data_size
)) {
4205 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4209 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4213 case SMB_FILE_BASIC_INFORMATION
:
4214 case SMB_QUERY_FILE_BASIC_INFO
:
4216 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4218 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4220 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4224 put_long_date_timespec(pdata
,create_time_ts
);
4225 put_long_date_timespec(pdata
+8,atime_ts
);
4226 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4227 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4228 SIVAL(pdata
,32,mode
);
4230 DEBUG(5,("SMB_QFBI - "));
4231 DEBUG(5,("create: %s ", ctime(&create_time
)));
4232 DEBUG(5,("access: %s ", ctime(&atime
)));
4233 DEBUG(5,("write: %s ", ctime(&mtime
)));
4234 DEBUG(5,("change: %s ", ctime(&mtime
)));
4235 DEBUG(5,("mode: %x\n", mode
));
4238 case SMB_FILE_STANDARD_INFORMATION
:
4239 case SMB_QUERY_FILE_STANDARD_INFO
:
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4243 SOFF_T(pdata
,0,allocation_size
);
4244 SOFF_T(pdata
,8,file_size
);
4245 SIVAL(pdata
,16,nlink
);
4246 SCVAL(pdata
,20,delete_pending
?1:0);
4247 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4248 SSVAL(pdata
,22,0); /* Padding. */
4251 case SMB_FILE_EA_INFORMATION
:
4252 case SMB_QUERY_FILE_EA_INFO
:
4254 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4255 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4257 SIVAL(pdata
,0,ea_size
);
4261 /* Get the 8.3 name - used if NT SMB was negotiated. */
4262 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4263 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4265 char mangled_name
[13];
4266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4267 if (!name_to_8_3(base_name
,mangled_name
,
4268 True
,conn
->params
)) {
4271 NT_STATUS_NO_MEMORY
);
4273 len
= srvstr_push(dstart
, req
->flags2
,
4274 pdata
+4, mangled_name
,
4275 PTR_DIFF(dend
, pdata
+4),
4277 data_size
= 4 + len
;
4282 case SMB_QUERY_FILE_NAME_INFO
:
4284 this must be *exactly* right for ACLs on mapped drives to work
4286 len
= srvstr_push(dstart
, req
->flags2
,
4288 PTR_DIFF(dend
, pdata
+4),
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4291 data_size
= 4 + len
;
4295 case SMB_FILE_ALLOCATION_INFORMATION
:
4296 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4299 SOFF_T(pdata
,0,allocation_size
);
4302 case SMB_FILE_END_OF_FILE_INFORMATION
:
4303 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4304 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4306 SOFF_T(pdata
,0,file_size
);
4309 case SMB_QUERY_FILE_ALL_INFO
:
4310 case SMB_FILE_ALL_INFORMATION
:
4312 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4314 put_long_date_timespec(pdata
,create_time_ts
);
4315 put_long_date_timespec(pdata
+8,atime_ts
);
4316 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4317 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4318 SIVAL(pdata
,32,mode
);
4319 SIVAL(pdata
,36,0); /* padding. */
4321 SOFF_T(pdata
,0,allocation_size
);
4322 SOFF_T(pdata
,8,file_size
);
4323 SIVAL(pdata
,16,nlink
);
4324 SCVAL(pdata
,20,delete_pending
);
4325 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4328 SIVAL(pdata
,0,ea_size
);
4329 pdata
+= 4; /* EA info */
4330 len
= srvstr_push(dstart
, req
->flags2
,
4332 PTR_DIFF(dend
, pdata
+4),
4336 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4339 case SMB_FILE_INTERNAL_INFORMATION
:
4340 /* This should be an index number - looks like
4343 I think this causes us to fail the IFSKIT
4344 BasicFileInformationTest. -tpot */
4346 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4347 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4348 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4352 case SMB_FILE_ACCESS_INFORMATION
:
4353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4354 SIVAL(pdata
,0,access_mask
);
4358 case SMB_FILE_NAME_INFORMATION
:
4359 /* Pathname with leading '\'. */
4362 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4363 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4364 SIVAL(pdata
,0,byte_len
);
4365 data_size
= 4 + byte_len
;
4369 case SMB_FILE_DISPOSITION_INFORMATION
:
4370 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4372 SCVAL(pdata
,0,delete_pending
);
4375 case SMB_FILE_POSITION_INFORMATION
:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4378 SOFF_T(pdata
,0,pos
);
4381 case SMB_FILE_MODE_INFORMATION
:
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4383 SIVAL(pdata
,0,mode
);
4387 case SMB_FILE_ALIGNMENT_INFORMATION
:
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4389 SIVAL(pdata
,0,0); /* No alignment needed. */
4394 * NT4 server just returns "invalid query" to this - if we try
4395 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4398 /* The first statement above is false - verified using Thursby
4399 * client against NT4 -- gcolley.
4401 case SMB_QUERY_FILE_STREAM_INFO
:
4402 case SMB_FILE_STREAM_INFORMATION
: {
4403 unsigned int num_streams
;
4404 struct stream_struct
*streams
;
4407 DEBUG(10,("call_trans2qfilepathinfo: "
4408 "SMB_FILE_STREAM_INFORMATION\n"));
4410 status
= SMB_VFS_STREAMINFO(
4411 conn
, fsp
, fname
, talloc_tos(),
4412 &num_streams
, &streams
);
4414 if (!NT_STATUS_IS_OK(status
)) {
4415 DEBUG(10, ("could not get stream info: %s\n",
4416 nt_errstr(status
)));
4417 reply_nterror(req
, status
);
4421 status
= marshall_stream_info(num_streams
, streams
,
4422 pdata
, max_data_bytes
,
4425 if (!NT_STATUS_IS_OK(status
)) {
4426 DEBUG(10, ("marshall_stream_info failed: %s\n",
4427 nt_errstr(status
)));
4428 reply_nterror(req
, status
);
4432 TALLOC_FREE(streams
);
4436 case SMB_QUERY_COMPRESSION_INFO
:
4437 case SMB_FILE_COMPRESSION_INFORMATION
:
4438 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4439 SOFF_T(pdata
,0,file_size
);
4440 SIVAL(pdata
,8,0); /* ??? */
4441 SIVAL(pdata
,12,0); /* ??? */
4445 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4447 put_long_date_timespec(pdata
,create_time_ts
);
4448 put_long_date_timespec(pdata
+8,atime_ts
);
4449 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4450 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4451 SOFF_T(pdata
,32,allocation_size
);
4452 SOFF_T(pdata
,40,file_size
);
4453 SIVAL(pdata
,48,mode
);
4454 SIVAL(pdata
,52,0); /* ??? */
4458 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4460 SIVAL(pdata
,0,mode
);
4466 * CIFS UNIX Extensions.
4469 case SMB_QUERY_FILE_UNIX_BASIC
:
4471 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4472 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4476 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4478 for (i
=0; i
<100; i
++)
4479 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4485 case SMB_QUERY_FILE_UNIX_INFO2
:
4487 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4488 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4492 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4494 for (i
=0; i
<100; i
++)
4495 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4501 case SMB_QUERY_FILE_UNIX_LINK
:
4503 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4506 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4510 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4512 if(!S_ISLNK(sbuf
.st_mode
)) {
4513 reply_unixerror(req
, ERRSRV
,
4518 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4521 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4524 reply_unixerror(req
, ERRDOS
,
4529 len
= srvstr_push(dstart
, req
->flags2
,
4531 PTR_DIFF(dend
, pdata
),
4534 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4539 #if defined(HAVE_POSIX_ACLS)
4540 case SMB_QUERY_POSIX_ACL
:
4542 SMB_ACL_T file_acl
= NULL
;
4543 SMB_ACL_T def_acl
= NULL
;
4544 uint16 num_file_acls
= 0;
4545 uint16 num_def_acls
= 0;
4547 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4548 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4550 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4553 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4554 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4558 NT_STATUS_NOT_IMPLEMENTED
);
4562 if (S_ISDIR(sbuf
.st_mode
)) {
4563 if (fsp
&& fsp
->is_directory
) {
4564 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4566 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4568 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4571 num_file_acls
= count_acl_entries(conn
, file_acl
);
4572 num_def_acls
= count_acl_entries(conn
, def_acl
);
4574 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4575 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4577 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4578 SMB_POSIX_ACL_HEADER_SIZE
) ));
4580 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4583 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4587 NT_STATUS_BUFFER_TOO_SMALL
);
4591 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4592 SSVAL(pdata
,2,num_file_acls
);
4593 SSVAL(pdata
,4,num_def_acls
);
4594 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4596 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4599 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4602 req
, NT_STATUS_INTERNAL_ERROR
);
4605 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4607 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4610 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4614 NT_STATUS_INTERNAL_ERROR
);
4619 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4622 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4624 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4630 case SMB_QUERY_POSIX_LOCK
:
4632 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4634 SMB_BIG_UINT offset
;
4636 enum brl_type lock_type
;
4638 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4640 req
, NT_STATUS_INVALID_PARAMETER
);
4644 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4645 case POSIX_LOCK_TYPE_READ
:
4646 lock_type
= READ_LOCK
;
4648 case POSIX_LOCK_TYPE_WRITE
:
4649 lock_type
= WRITE_LOCK
;
4651 case POSIX_LOCK_TYPE_UNLOCK
:
4653 /* There's no point in asking for an unlock... */
4656 NT_STATUS_INVALID_PARAMETER
);
4660 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4661 #if defined(HAVE_LONGLONG)
4662 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4663 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4664 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4665 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4666 #else /* HAVE_LONGLONG */
4667 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4668 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4669 #endif /* HAVE_LONGLONG */
4671 status
= query_lock(fsp
,
4678 if (ERROR_WAS_LOCK_DENIED(status
)) {
4679 /* Here we need to report who has it locked... */
4680 data_size
= POSIX_LOCK_DATA_SIZE
;
4682 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4683 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4684 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4685 #if defined(HAVE_LONGLONG)
4686 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4687 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4688 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4689 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4690 #else /* HAVE_LONGLONG */
4691 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4692 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4693 #endif /* HAVE_LONGLONG */
4695 } else if (NT_STATUS_IS_OK(status
)) {
4696 /* For success we just return a copy of what we sent
4697 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4698 data_size
= POSIX_LOCK_DATA_SIZE
;
4699 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4700 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4702 reply_nterror(req
, status
);
4709 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4713 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4719 /****************************************************************************
4720 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4722 ****************************************************************************/
4724 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4725 connection_struct
*conn
,
4726 const char *oldname_in
,
4727 const char *newname_in
)
4729 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4730 char *last_component_oldname
= NULL
;
4731 char *last_component_newname
= NULL
;
4732 char *oldname
= NULL
;
4733 char *newname
= NULL
;
4734 NTSTATUS status
= NT_STATUS_OK
;
4739 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4740 &last_component_oldname
, &sbuf1
);
4741 if (!NT_STATUS_IS_OK(status
)) {
4745 status
= check_name(conn
, oldname
);
4746 if (!NT_STATUS_IS_OK(status
)) {
4750 /* source must already exist. */
4751 if (!VALID_STAT(sbuf1
)) {
4752 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4755 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4756 &last_component_newname
, &sbuf2
);
4757 if (!NT_STATUS_IS_OK(status
)) {
4761 status
= check_name(conn
, newname
);
4762 if (!NT_STATUS_IS_OK(status
)) {
4766 /* Disallow if newname already exists. */
4767 if (VALID_STAT(sbuf2
)) {
4768 return NT_STATUS_OBJECT_NAME_COLLISION
;
4771 /* No links from a directory. */
4772 if (S_ISDIR(sbuf1
.st_mode
)) {
4773 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4776 /* Ensure this is within the share. */
4777 status
= check_reduced_name(conn
, oldname
);
4778 if (!NT_STATUS_IS_OK(status
)) {
4782 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4784 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4785 status
= map_nt_error_from_unix(errno
);
4786 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4787 nt_errstr(status
), newname
, oldname
));
4793 /****************************************************************************
4794 Deal with setting the time from any of the setfilepathinfo functions.
4795 ****************************************************************************/
4797 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4800 const SMB_STRUCT_STAT
*psbuf
,
4801 struct timespec ts
[2],
4802 bool setting_write_time
)
4805 FILE_NOTIFY_CHANGE_LAST_ACCESS
4806 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4808 if (!VALID_STAT(*psbuf
)) {
4809 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4812 /* get some defaults (no modifications) if any info is zero or -1. */
4813 if (null_timespec(ts
[0])) {
4814 ts
[0] = get_atimespec(psbuf
);
4815 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4818 if (null_timespec(ts
[1])) {
4819 ts
[1] = get_mtimespec(psbuf
);
4820 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4823 if (!setting_write_time
) {
4824 /* ts[1] comes from change time, not write time. */
4825 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4828 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4829 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4832 * Try and set the times of this file if
4833 * they are different from the current values.
4837 struct timespec mts
= get_mtimespec(psbuf
);
4838 struct timespec ats
= get_atimespec(psbuf
);
4839 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4840 return NT_STATUS_OK
;
4844 if (setting_write_time
) {
4846 * This was a setfileinfo on an open file.
4847 * NT does this a lot. We also need to
4848 * set the time here, as it can be read by
4849 * FindFirst/FindNext and with the patch for bug #2045
4850 * in smbd/fileio.c it ensures that this timestamp is
4851 * kept sticky even after a write. We save the request
4852 * away and will set it on file close and after a write. JRA.
4855 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4856 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4859 set_write_time_fsp(fsp
, ts
[1], true);
4861 set_write_time_path(conn
, fname
,
4862 vfs_file_id_from_sbuf(conn
, psbuf
),
4867 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4869 if(file_ntimes(conn
, fname
, ts
)!=0) {
4870 return map_nt_error_from_unix(errno
);
4872 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4874 return NT_STATUS_OK
;
4877 /****************************************************************************
4878 Deal with setting the dosmode from any of the setfilepathinfo functions.
4879 ****************************************************************************/
4881 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4883 SMB_STRUCT_STAT
*psbuf
,
4886 if (!VALID_STAT(*psbuf
)) {
4887 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4891 if (S_ISDIR(psbuf
->st_mode
)) {
4898 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
4900 /* check the mode isn't different, before changing it */
4901 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
4903 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4904 fname
, (unsigned int)dosmode
));
4906 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
4907 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4908 fname
, strerror(errno
)));
4909 return map_nt_error_from_unix(errno
);
4912 return NT_STATUS_OK
;
4915 /****************************************************************************
4916 Deal with setting the size from any of the setfilepathinfo functions.
4917 ****************************************************************************/
4919 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4920 struct smb_request
*req
,
4923 SMB_STRUCT_STAT
*psbuf
,
4926 NTSTATUS status
= NT_STATUS_OK
;
4927 files_struct
*new_fsp
= NULL
;
4929 if (!VALID_STAT(*psbuf
)) {
4930 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4933 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
4935 if (size
== get_file_size(*psbuf
)) {
4936 return NT_STATUS_OK
;
4939 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4940 fname
, (double)size
));
4942 if (fsp
&& fsp
->fh
->fd
!= -1) {
4943 /* Handle based call. */
4944 if (vfs_set_filelen(fsp
, size
) == -1) {
4945 return map_nt_error_from_unix(errno
);
4947 return NT_STATUS_OK
;
4950 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
4951 FILE_WRITE_ATTRIBUTES
,
4952 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
4955 FILE_ATTRIBUTE_NORMAL
,
4956 FORCE_OPLOCK_BREAK_TO_NONE
,
4959 if (!NT_STATUS_IS_OK(status
)) {
4960 /* NB. We check for open_was_deferred in the caller. */
4964 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4965 status
= map_nt_error_from_unix(errno
);
4966 close_file(new_fsp
,NORMAL_CLOSE
);
4970 close_file(new_fsp
,NORMAL_CLOSE
);
4971 return NT_STATUS_OK
;
4974 /****************************************************************************
4975 Deal with SMB_INFO_SET_EA.
4976 ****************************************************************************/
4978 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4984 struct ea_list
*ea_list
= NULL
;
4985 TALLOC_CTX
*ctx
= NULL
;
4986 NTSTATUS status
= NT_STATUS_OK
;
4988 if (total_data
< 10) {
4990 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4991 length. They seem to have no effect. Bug #3212. JRA */
4993 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4994 /* We're done. We only get EA info in this call. */
4995 return NT_STATUS_OK
;
4998 return NT_STATUS_INVALID_PARAMETER
;
5001 if (IVAL(pdata
,0) > total_data
) {
5002 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5003 IVAL(pdata
,0), (unsigned int)total_data
));
5004 return NT_STATUS_INVALID_PARAMETER
;
5008 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5010 return NT_STATUS_INVALID_PARAMETER
;
5012 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5017 /****************************************************************************
5018 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5019 ****************************************************************************/
5021 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5026 SMB_STRUCT_STAT
*psbuf
)
5028 NTSTATUS status
= NT_STATUS_OK
;
5029 bool delete_on_close
;
5032 if (total_data
< 1) {
5033 return NT_STATUS_INVALID_PARAMETER
;
5037 return NT_STATUS_INVALID_HANDLE
;
5040 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5041 dosmode
= dos_mode(conn
, fname
, psbuf
);
5043 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5044 "delete_on_close = %u\n",
5046 (unsigned int)dosmode
,
5047 (unsigned int)delete_on_close
));
5049 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5051 if (!NT_STATUS_IS_OK(status
)) {
5055 /* The set is across all open files on this dev/inode pair. */
5056 if (!set_delete_on_close(fsp
, delete_on_close
, ¤t_user
.ut
)) {
5057 return NT_STATUS_ACCESS_DENIED
;
5059 return NT_STATUS_OK
;
5062 /****************************************************************************
5063 Deal with SMB_FILE_POSITION_INFORMATION.
5064 ****************************************************************************/
5066 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5071 SMB_BIG_UINT position_information
;
5073 if (total_data
< 8) {
5074 return NT_STATUS_INVALID_PARAMETER
;
5078 /* Ignore on pathname based set. */
5079 return NT_STATUS_OK
;
5082 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5083 #ifdef LARGE_SMB_OFF_T
5084 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5085 #else /* LARGE_SMB_OFF_T */
5086 if (IVAL(pdata
,4) != 0) {
5087 /* more than 32 bits? */
5088 return NT_STATUS_INVALID_PARAMETER
;
5090 #endif /* LARGE_SMB_OFF_T */
5092 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5093 fsp
->fsp_name
, (double)position_information
));
5094 fsp
->fh
->position_information
= position_information
;
5095 return NT_STATUS_OK
;
5098 /****************************************************************************
5099 Deal with SMB_FILE_MODE_INFORMATION.
5100 ****************************************************************************/
5102 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5108 if (total_data
< 4) {
5109 return NT_STATUS_INVALID_PARAMETER
;
5111 mode
= IVAL(pdata
,0);
5112 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5113 return NT_STATUS_INVALID_PARAMETER
;
5115 return NT_STATUS_OK
;
5118 /****************************************************************************
5119 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5120 ****************************************************************************/
5122 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5123 struct smb_request
*req
,
5128 char *link_target
= NULL
;
5129 const char *newname
= fname
;
5130 NTSTATUS status
= NT_STATUS_OK
;
5131 TALLOC_CTX
*ctx
= talloc_tos();
5133 /* Set a symbolic link. */
5134 /* Don't allow this if follow links is false. */
5136 if (total_data
== 0) {
5137 return NT_STATUS_INVALID_PARAMETER
;
5140 if (!lp_symlinks(SNUM(conn
))) {
5141 return NT_STATUS_ACCESS_DENIED
;
5144 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5145 total_data
, STR_TERMINATE
);
5148 return NT_STATUS_INVALID_PARAMETER
;
5151 /* !widelinks forces the target path to be within the share. */
5152 /* This means we can interpret the target as a pathname. */
5153 if (!lp_widelinks(SNUM(conn
))) {
5154 char *rel_name
= NULL
;
5155 char *last_dirp
= NULL
;
5157 if (*link_target
== '/') {
5158 /* No absolute paths allowed. */
5159 return NT_STATUS_ACCESS_DENIED
;
5161 rel_name
= talloc_strdup(ctx
,newname
);
5163 return NT_STATUS_NO_MEMORY
;
5165 last_dirp
= strrchr_m(rel_name
, '/');
5167 last_dirp
[1] = '\0';
5169 rel_name
= talloc_strdup(ctx
,"./");
5171 return NT_STATUS_NO_MEMORY
;
5174 rel_name
= talloc_asprintf_append(rel_name
,
5178 return NT_STATUS_NO_MEMORY
;
5181 status
= check_name(conn
, rel_name
);
5182 if (!NT_STATUS_IS_OK(status
)) {
5187 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5188 newname
, link_target
));
5190 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5191 return map_nt_error_from_unix(errno
);
5194 return NT_STATUS_OK
;
5197 /****************************************************************************
5198 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5199 ****************************************************************************/
5201 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5202 struct smb_request
*req
,
5203 const char *pdata
, int total_data
,
5206 char *oldname
= NULL
;
5207 TALLOC_CTX
*ctx
= talloc_tos();
5208 NTSTATUS status
= NT_STATUS_OK
;
5210 /* Set a hard link. */
5211 if (total_data
== 0) {
5212 return NT_STATUS_INVALID_PARAMETER
;
5215 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5216 total_data
, STR_TERMINATE
, &status
);
5217 if (!NT_STATUS_IS_OK(status
)) {
5221 status
= resolve_dfspath(ctx
, conn
,
5222 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5225 if (!NT_STATUS_IS_OK(status
)) {
5229 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5232 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5235 /****************************************************************************
5236 Deal with SMB_FILE_RENAME_INFORMATION.
5237 ****************************************************************************/
5239 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5240 struct smb_request
*req
,
5249 char *newname
= NULL
;
5250 char *base_name
= NULL
;
5251 bool dest_has_wcard
= False
;
5252 NTSTATUS status
= NT_STATUS_OK
;
5254 TALLOC_CTX
*ctx
= talloc_tos();
5256 if (total_data
< 13) {
5257 return NT_STATUS_INVALID_PARAMETER
;
5260 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5261 root_fid
= IVAL(pdata
,4);
5262 len
= IVAL(pdata
,8);
5264 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5265 return NT_STATUS_INVALID_PARAMETER
;
5268 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5271 if (!NT_STATUS_IS_OK(status
)) {
5275 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5278 status
= resolve_dfspath_wcard(ctx
, conn
,
5279 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5283 if (!NT_STATUS_IS_OK(status
)) {
5287 /* Check the new name has no '/' characters. */
5288 if (strchr_m(newname
, '/')) {
5289 return NT_STATUS_NOT_SUPPORTED
;
5292 /* Create the base directory. */
5293 base_name
= talloc_strdup(ctx
, fname
);
5295 return NT_STATUS_NO_MEMORY
;
5297 p
= strrchr_m(base_name
, '/');
5301 base_name
= talloc_strdup(ctx
, "./");
5303 return NT_STATUS_NO_MEMORY
;
5306 /* Append the new name. */
5307 base_name
= talloc_asprintf_append(base_name
,
5311 return NT_STATUS_NO_MEMORY
;
5315 SMB_STRUCT_STAT sbuf
;
5316 char *newname_last_component
= NULL
;
5320 status
= unix_convert(ctx
, conn
, newname
, False
,
5322 &newname_last_component
,
5325 /* If an error we expect this to be
5326 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5328 if (!NT_STATUS_IS_OK(status
)
5329 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5334 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5335 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5336 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5337 newname_last_component
, 0,
5340 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5341 fname
, base_name
));
5342 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5343 overwrite
, False
, dest_has_wcard
,
5344 FILE_WRITE_ATTRIBUTES
);
5350 /****************************************************************************
5351 Deal with SMB_SET_POSIX_ACL.
5352 ****************************************************************************/
5354 #if defined(HAVE_POSIX_ACLS)
5355 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5360 SMB_STRUCT_STAT
*psbuf
)
5362 uint16 posix_acl_version
;
5363 uint16 num_file_acls
;
5364 uint16 num_def_acls
;
5365 bool valid_file_acls
= True
;
5366 bool valid_def_acls
= True
;
5368 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5369 return NT_STATUS_INVALID_PARAMETER
;
5371 posix_acl_version
= SVAL(pdata
,0);
5372 num_file_acls
= SVAL(pdata
,2);
5373 num_def_acls
= SVAL(pdata
,4);
5375 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5376 valid_file_acls
= False
;
5380 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5381 valid_def_acls
= False
;
5385 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5386 return NT_STATUS_INVALID_PARAMETER
;
5389 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5390 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5391 return NT_STATUS_INVALID_PARAMETER
;
5394 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5395 fname
? fname
: fsp
->fsp_name
,
5396 (unsigned int)num_file_acls
,
5397 (unsigned int)num_def_acls
));
5399 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5400 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5401 return map_nt_error_from_unix(errno
);
5404 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5405 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5406 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5407 return map_nt_error_from_unix(errno
);
5409 return NT_STATUS_OK
;
5413 /****************************************************************************
5414 Deal with SMB_SET_POSIX_LOCK.
5415 ****************************************************************************/
5417 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5418 const struct smb_request
*req
,
5424 SMB_BIG_UINT offset
;
5426 bool blocking_lock
= False
;
5427 enum brl_type lock_type
;
5429 NTSTATUS status
= NT_STATUS_OK
;
5431 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5432 return NT_STATUS_INVALID_HANDLE
;
5435 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5436 return NT_STATUS_INVALID_PARAMETER
;
5439 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5440 case POSIX_LOCK_TYPE_READ
:
5441 lock_type
= READ_LOCK
;
5443 case POSIX_LOCK_TYPE_WRITE
:
5444 /* Return the right POSIX-mappable error code for files opened read-only. */
5445 if (!fsp
->can_write
) {
5446 return NT_STATUS_INVALID_HANDLE
;
5448 lock_type
= WRITE_LOCK
;
5450 case POSIX_LOCK_TYPE_UNLOCK
:
5451 lock_type
= UNLOCK_LOCK
;
5454 return NT_STATUS_INVALID_PARAMETER
;
5457 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5458 blocking_lock
= False
;
5459 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5460 blocking_lock
= True
;
5462 return NT_STATUS_INVALID_PARAMETER
;
5465 if (!lp_blocking_locks(SNUM(conn
))) {
5466 blocking_lock
= False
;
5469 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5470 #if defined(HAVE_LONGLONG)
5471 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5472 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5473 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5474 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5475 #else /* HAVE_LONGLONG */
5476 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5477 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5478 #endif /* HAVE_LONGLONG */
5480 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5481 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5483 (unsigned int)lock_type
,
5484 (unsigned int)lock_pid
,
5488 if (lock_type
== UNLOCK_LOCK
) {
5489 status
= do_unlock(smbd_messaging_context(),
5496 uint32 block_smbpid
;
5498 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5509 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5511 * A blocking lock was requested. Package up
5512 * this smb into a queued request and push it
5513 * onto the blocking lock queue.
5515 if(push_blocking_lock_request(br_lck
,
5518 -1, /* infinite timeout. */
5526 TALLOC_FREE(br_lck
);
5530 TALLOC_FREE(br_lck
);
5536 /****************************************************************************
5537 Deal with SMB_INFO_STANDARD.
5538 ****************************************************************************/
5540 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5545 const SMB_STRUCT_STAT
*psbuf
)
5547 struct timespec ts
[2];
5549 if (total_data
< 12) {
5550 return NT_STATUS_INVALID_PARAMETER
;
5554 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5556 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5558 DEBUG(10,("smb_set_info_standard: file %s\n",
5559 fname
? fname
: fsp
->fsp_name
));
5561 return smb_set_file_time(conn
,
5569 /****************************************************************************
5570 Deal with SMB_SET_FILE_BASIC_INFO.
5571 ****************************************************************************/
5573 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5578 SMB_STRUCT_STAT
*psbuf
)
5580 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5581 struct timespec write_time
;
5582 struct timespec changed_time
;
5584 struct timespec ts
[2];
5585 NTSTATUS status
= NT_STATUS_OK
;
5586 bool setting_write_time
= true;
5588 if (total_data
< 36) {
5589 return NT_STATUS_INVALID_PARAMETER
;
5592 /* Set the attributes */
5593 dosmode
= IVAL(pdata
,32);
5594 status
= smb_set_file_dosmode(conn
,
5598 if (!NT_STATUS_IS_OK(status
)) {
5602 /* Ignore create time at offset pdata. */
5605 ts
[0] = interpret_long_date(pdata
+8);
5607 write_time
= interpret_long_date(pdata
+16);
5608 changed_time
= interpret_long_date(pdata
+24);
5611 ts
[1] = timespec_min(&write_time
, &changed_time
);
5613 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5617 /* Prefer a defined time to an undefined one. */
5618 if (null_timespec(ts
[1])) {
5619 if (null_timespec(write_time
)) {
5620 ts
[1] = changed_time
;
5621 setting_write_time
= false;
5627 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5628 fname
? fname
: fsp
->fsp_name
));
5630 return smb_set_file_time(conn
,
5635 setting_write_time
);
5638 /****************************************************************************
5639 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5640 ****************************************************************************/
5642 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5643 struct smb_request
*req
,
5648 SMB_STRUCT_STAT
*psbuf
)
5650 SMB_BIG_UINT allocation_size
= 0;
5651 NTSTATUS status
= NT_STATUS_OK
;
5652 files_struct
*new_fsp
= NULL
;
5654 if (!VALID_STAT(*psbuf
)) {
5655 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5658 if (total_data
< 8) {
5659 return NT_STATUS_INVALID_PARAMETER
;
5662 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5663 #ifdef LARGE_SMB_OFF_T
5664 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5665 #else /* LARGE_SMB_OFF_T */
5666 if (IVAL(pdata
,4) != 0) {
5667 /* more than 32 bits? */
5668 return NT_STATUS_INVALID_PARAMETER
;
5670 #endif /* LARGE_SMB_OFF_T */
5672 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5673 fname
, (double)allocation_size
));
5675 if (allocation_size
) {
5676 allocation_size
= smb_roundup(conn
, allocation_size
);
5679 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5680 fname
, (double)allocation_size
));
5682 if (fsp
&& fsp
->fh
->fd
!= -1) {
5683 /* Open file handle. */
5684 /* Only change if needed. */
5685 if (allocation_size
!= get_file_size(*psbuf
)) {
5686 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5687 return map_nt_error_from_unix(errno
);
5690 /* But always update the time. */
5692 * This is equivalent to a write. Ensure it's seen immediately
5693 * if there are no pending writes.
5695 trigger_write_time_update(fsp
);
5696 return NT_STATUS_OK
;
5699 /* Pathname or stat or directory file. */
5701 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5703 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5706 FILE_ATTRIBUTE_NORMAL
,
5707 FORCE_OPLOCK_BREAK_TO_NONE
,
5710 if (!NT_STATUS_IS_OK(status
)) {
5711 /* NB. We check for open_was_deferred in the caller. */
5715 /* Only change if needed. */
5716 if (allocation_size
!= get_file_size(*psbuf
)) {
5717 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5718 status
= map_nt_error_from_unix(errno
);
5719 close_file(new_fsp
,NORMAL_CLOSE
);
5724 /* Changing the allocation size should set the last mod time. */
5726 * This is equivalent to a write. Ensure it's seen immediately
5727 * if there are no pending writes.
5729 trigger_write_time_update(new_fsp
);
5731 close_file(new_fsp
,NORMAL_CLOSE
);
5732 return NT_STATUS_OK
;
5735 /****************************************************************************
5736 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5737 ****************************************************************************/
5739 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5740 struct smb_request
*req
,
5745 SMB_STRUCT_STAT
*psbuf
)
5749 if (total_data
< 8) {
5750 return NT_STATUS_INVALID_PARAMETER
;
5753 size
= IVAL(pdata
,0);
5754 #ifdef LARGE_SMB_OFF_T
5755 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5756 #else /* LARGE_SMB_OFF_T */
5757 if (IVAL(pdata
,4) != 0) {
5758 /* more than 32 bits? */
5759 return NT_STATUS_INVALID_PARAMETER
;
5761 #endif /* LARGE_SMB_OFF_T */
5762 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5763 "file %s to %.0f\n", fname
, (double)size
));
5765 return smb_set_file_size(conn
, req
,
5772 /****************************************************************************
5773 Allow a UNIX info mknod.
5774 ****************************************************************************/
5776 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5780 SMB_STRUCT_STAT
*psbuf
)
5782 uint32 file_type
= IVAL(pdata
,56);
5783 #if defined(HAVE_MAKEDEV)
5784 uint32 dev_major
= IVAL(pdata
,60);
5785 uint32 dev_minor
= IVAL(pdata
,68);
5787 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5788 uint32 raw_unixmode
= IVAL(pdata
,84);
5792 if (total_data
< 100) {
5793 return NT_STATUS_INVALID_PARAMETER
;
5796 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5797 if (!NT_STATUS_IS_OK(status
)) {
5801 #if defined(HAVE_MAKEDEV)
5802 dev
= makedev(dev_major
, dev_minor
);
5805 switch (file_type
) {
5806 #if defined(S_IFIFO)
5807 case UNIX_TYPE_FIFO
:
5808 unixmode
|= S_IFIFO
;
5811 #if defined(S_IFSOCK)
5812 case UNIX_TYPE_SOCKET
:
5813 unixmode
|= S_IFSOCK
;
5816 #if defined(S_IFCHR)
5817 case UNIX_TYPE_CHARDEV
:
5818 unixmode
|= S_IFCHR
;
5821 #if defined(S_IFBLK)
5822 case UNIX_TYPE_BLKDEV
:
5823 unixmode
|= S_IFBLK
;
5827 return NT_STATUS_INVALID_PARAMETER
;
5830 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5831 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5833 /* Ok - do the mknod. */
5834 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5835 return map_nt_error_from_unix(errno
);
5838 /* If any of the other "set" calls fail we
5839 * don't want to end up with a half-constructed mknod.
5842 if (lp_inherit_perms(SNUM(conn
))) {
5844 conn
, parent_dirname(fname
),
5848 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5849 status
= map_nt_error_from_unix(errno
);
5850 SMB_VFS_UNLINK(conn
,fname
);
5853 return NT_STATUS_OK
;
5856 /****************************************************************************
5857 Deal with SMB_SET_FILE_UNIX_BASIC.
5858 ****************************************************************************/
5860 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5861 struct smb_request
*req
,
5866 SMB_STRUCT_STAT
*psbuf
)
5868 struct timespec ts
[2];
5869 uint32 raw_unixmode
;
5872 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5873 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5874 NTSTATUS status
= NT_STATUS_OK
;
5875 bool delete_on_fail
= False
;
5876 enum perm_type ptype
;
5878 if (total_data
< 100) {
5879 return NT_STATUS_INVALID_PARAMETER
;
5882 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5883 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5884 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5885 #ifdef LARGE_SMB_OFF_T
5886 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5887 #else /* LARGE_SMB_OFF_T */
5888 if (IVAL(pdata
,4) != 0) {
5889 /* more than 32 bits? */
5890 return NT_STATUS_INVALID_PARAMETER
;
5892 #endif /* LARGE_SMB_OFF_T */
5895 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
5896 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
5897 set_owner
= (uid_t
)IVAL(pdata
,40);
5898 set_grp
= (gid_t
)IVAL(pdata
,48);
5899 raw_unixmode
= IVAL(pdata
,84);
5901 if (VALID_STAT(*psbuf
)) {
5902 if (S_ISDIR(psbuf
->st_mode
)) {
5903 ptype
= PERM_EXISTING_DIR
;
5905 ptype
= PERM_EXISTING_FILE
;
5908 ptype
= PERM_NEW_FILE
;
5911 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
5912 if (!NT_STATUS_IS_OK(status
)) {
5916 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5917 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5918 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
5920 if (!VALID_STAT(*psbuf
)) {
5922 * The only valid use of this is to create character and block
5923 * devices, and named pipes. This is deprecated (IMHO) and
5924 * a new info level should be used for mknod. JRA.
5927 status
= smb_unix_mknod(conn
,
5932 if (!NT_STATUS_IS_OK(status
)) {
5936 /* Ensure we don't try and change anything else. */
5937 raw_unixmode
= SMB_MODE_NO_CHANGE
;
5938 size
= get_file_size(*psbuf
);
5939 ts
[0] = get_atimespec(psbuf
);
5940 ts
[1] = get_mtimespec(psbuf
);
5942 * We continue here as we might want to change the
5945 delete_on_fail
= True
;
5949 /* Horrible backwards compatibility hack as an old server bug
5950 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5954 size
= get_file_size(*psbuf
);
5959 * Deal with the UNIX specific mode set.
5962 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5963 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5964 (unsigned int)unixmode
, fname
));
5965 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
5966 return map_nt_error_from_unix(errno
);
5971 * Deal with the UNIX specific uid set.
5974 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
5977 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5978 (unsigned int)set_owner
, fname
));
5980 if (S_ISLNK(psbuf
->st_mode
)) {
5981 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
5983 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
5987 status
= map_nt_error_from_unix(errno
);
5988 if (delete_on_fail
) {
5989 SMB_VFS_UNLINK(conn
,fname
);
5996 * Deal with the UNIX specific gid set.
5999 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6000 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6001 (unsigned int)set_owner
, fname
));
6002 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6003 status
= map_nt_error_from_unix(errno
);
6004 if (delete_on_fail
) {
6005 SMB_VFS_UNLINK(conn
,fname
);
6011 /* Deal with any size changes. */
6013 status
= smb_set_file_size(conn
, req
,
6018 if (!NT_STATUS_IS_OK(status
)) {
6022 /* Deal with any time changes. */
6024 return smb_set_file_time(conn
,
6032 /****************************************************************************
6033 Deal with SMB_SET_FILE_UNIX_INFO2.
6034 ****************************************************************************/
6036 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6037 struct smb_request
*req
,
6042 SMB_STRUCT_STAT
*psbuf
)
6048 if (total_data
< 116) {
6049 return NT_STATUS_INVALID_PARAMETER
;
6052 /* Start by setting all the fields that are common between UNIX_BASIC
6055 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6057 if (!NT_STATUS_IS_OK(status
)) {
6061 smb_fflags
= IVAL(pdata
, 108);
6062 smb_fmask
= IVAL(pdata
, 112);
6064 /* NB: We should only attempt to alter the file flags if the client
6065 * sends a non-zero mask.
6067 if (smb_fmask
!= 0) {
6068 int stat_fflags
= 0;
6070 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6072 /* Client asked to alter a flag we don't understand. */
6073 return NT_STATUS_INVALID_PARAMETER
;
6076 if (fsp
&& fsp
->fh
->fd
!= -1) {
6077 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6078 return NT_STATUS_NOT_SUPPORTED
;
6080 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6081 return map_nt_error_from_unix(errno
);
6086 /* XXX: need to add support for changing the create_time here. You
6087 * can do this for paths on Darwin with setattrlist(2). The right way
6088 * to hook this up is probably by extending the VFS utimes interface.
6091 return NT_STATUS_OK
;
6094 /****************************************************************************
6095 Create a directory with POSIX semantics.
6096 ****************************************************************************/
6098 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6099 struct smb_request
*req
,
6103 SMB_STRUCT_STAT
*psbuf
,
6104 int *pdata_return_size
)
6106 NTSTATUS status
= NT_STATUS_OK
;
6107 uint32 raw_unixmode
= 0;
6108 uint32 mod_unixmode
= 0;
6109 mode_t unixmode
= (mode_t
)0;
6110 files_struct
*fsp
= NULL
;
6111 uint16 info_level_return
= 0;
6113 char *pdata
= *ppdata
;
6115 if (total_data
< 18) {
6116 return NT_STATUS_INVALID_PARAMETER
;
6119 raw_unixmode
= IVAL(pdata
,8);
6120 /* Next 4 bytes are not yet defined. */
6122 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6123 if (!NT_STATUS_IS_OK(status
)) {
6127 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6129 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6130 fname
, (unsigned int)unixmode
));
6132 status
= open_directory(conn
, req
,
6135 FILE_READ_ATTRIBUTES
, /* Just a stat open */
6136 FILE_SHARE_NONE
, /* Ignored for stat opens */
6143 if (NT_STATUS_IS_OK(status
)) {
6144 close_file(fsp
, NORMAL_CLOSE
);
6147 info_level_return
= SVAL(pdata
,16);
6149 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6150 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6151 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6152 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6154 *pdata_return_size
= 12;
6157 /* Realloc the data size */
6158 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6159 if (*ppdata
== NULL
) {
6160 *pdata_return_size
= 0;
6161 return NT_STATUS_NO_MEMORY
;
6165 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6166 SSVAL(pdata
,2,0); /* No fnum. */
6167 SIVAL(pdata
,4,info
); /* Was directory created. */
6169 switch (info_level_return
) {
6170 case SMB_QUERY_FILE_UNIX_BASIC
:
6171 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6172 SSVAL(pdata
,10,0); /* Padding. */
6173 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6175 case SMB_QUERY_FILE_UNIX_INFO2
:
6176 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6177 SSVAL(pdata
,10,0); /* Padding. */
6178 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6181 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6182 SSVAL(pdata
,10,0); /* Padding. */
6189 /****************************************************************************
6190 Open/Create a file with POSIX semantics.
6191 ****************************************************************************/
6193 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6194 struct smb_request
*req
,
6198 SMB_STRUCT_STAT
*psbuf
,
6199 int *pdata_return_size
)
6201 bool extended_oplock_granted
= False
;
6202 char *pdata
= *ppdata
;
6204 uint32 wire_open_mode
= 0;
6205 uint32 raw_unixmode
= 0;
6206 uint32 mod_unixmode
= 0;
6207 uint32 create_disp
= 0;
6208 uint32 access_mask
= 0;
6209 uint32 create_options
= 0;
6210 NTSTATUS status
= NT_STATUS_OK
;
6211 mode_t unixmode
= (mode_t
)0;
6212 files_struct
*fsp
= NULL
;
6213 int oplock_request
= 0;
6215 uint16 info_level_return
= 0;
6217 if (total_data
< 18) {
6218 return NT_STATUS_INVALID_PARAMETER
;
6221 flags
= IVAL(pdata
,0);
6222 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6223 if (oplock_request
) {
6224 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6227 wire_open_mode
= IVAL(pdata
,4);
6229 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6230 return smb_posix_mkdir(conn
, req
,
6238 switch (wire_open_mode
& SMB_ACCMODE
) {
6240 access_mask
= FILE_READ_DATA
;
6243 access_mask
= FILE_WRITE_DATA
;
6246 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6249 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6250 (unsigned int)wire_open_mode
));
6251 return NT_STATUS_INVALID_PARAMETER
;
6254 wire_open_mode
&= ~SMB_ACCMODE
;
6256 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6257 create_disp
= FILE_CREATE
;
6258 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6259 create_disp
= FILE_OVERWRITE_IF
;
6260 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6261 create_disp
= FILE_OPEN_IF
;
6263 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6264 (unsigned int)wire_open_mode
));
6265 return NT_STATUS_INVALID_PARAMETER
;
6268 raw_unixmode
= IVAL(pdata
,8);
6269 /* Next 4 bytes are not yet defined. */
6271 status
= unix_perms_from_wire(conn
,
6274 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6277 if (!NT_STATUS_IS_OK(status
)) {
6281 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6283 if (wire_open_mode
& SMB_O_SYNC
) {
6284 create_options
|= FILE_WRITE_THROUGH
;
6286 if (wire_open_mode
& SMB_O_APPEND
) {
6287 access_mask
|= FILE_APPEND_DATA
;
6289 if (wire_open_mode
& SMB_O_DIRECT
) {
6290 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6293 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6295 (unsigned int)wire_open_mode
,
6296 (unsigned int)unixmode
));
6298 status
= open_file_ntcreate(conn
, req
,
6302 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6304 0, /* no create options yet. */
6310 if (!NT_STATUS_IS_OK(status
)) {
6314 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6315 extended_oplock_granted
= True
;
6318 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6319 extended_oplock_granted
= True
;
6322 info_level_return
= SVAL(pdata
,16);
6324 /* Allocate the correct return size. */
6326 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6327 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6328 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6329 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6331 *pdata_return_size
= 12;
6334 /* Realloc the data size */
6335 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6336 if (*ppdata
== NULL
) {
6337 close_file(fsp
,ERROR_CLOSE
);
6338 *pdata_return_size
= 0;
6339 return NT_STATUS_NO_MEMORY
;
6343 if (extended_oplock_granted
) {
6344 if (flags
& REQUEST_BATCH_OPLOCK
) {
6345 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6347 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6349 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6350 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6352 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6355 SSVAL(pdata
,2,fsp
->fnum
);
6356 SIVAL(pdata
,4,info
); /* Was file created etc. */
6358 switch (info_level_return
) {
6359 case SMB_QUERY_FILE_UNIX_BASIC
:
6360 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6361 SSVAL(pdata
,10,0); /* padding. */
6362 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6364 case SMB_QUERY_FILE_UNIX_INFO2
:
6365 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6366 SSVAL(pdata
,10,0); /* padding. */
6367 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6370 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6371 SSVAL(pdata
,10,0); /* padding. */
6374 return NT_STATUS_OK
;
6377 /****************************************************************************
6378 Delete a file with POSIX semantics.
6379 ****************************************************************************/
6381 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6382 struct smb_request
*req
,
6386 SMB_STRUCT_STAT
*psbuf
)
6388 NTSTATUS status
= NT_STATUS_OK
;
6389 files_struct
*fsp
= NULL
;
6394 struct share_mode_lock
*lck
= NULL
;
6396 if (total_data
< 2) {
6397 return NT_STATUS_INVALID_PARAMETER
;
6400 flags
= SVAL(pdata
,0);
6402 if (!VALID_STAT(*psbuf
)) {
6403 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6406 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6407 !VALID_STAT_OF_DIR(*psbuf
)) {
6408 return NT_STATUS_NOT_A_DIRECTORY
;
6411 DEBUG(10,("smb_posix_unlink: %s %s\n",
6412 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6415 if (VALID_STAT_OF_DIR(*psbuf
)) {
6416 status
= open_directory(conn
, req
,
6420 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6423 FILE_FLAG_POSIX_SEMANTICS
|0777,
6428 status
= open_file_ntcreate(conn
, req
,
6432 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6435 FILE_FLAG_POSIX_SEMANTICS
|0777,
6436 0, /* No oplock, but break existing ones. */
6441 if (!NT_STATUS_IS_OK(status
)) {
6446 * Don't lie to client. If we can't really delete due to
6447 * non-POSIX opens return SHARING_VIOLATION.
6450 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6453 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6454 "lock for file %s\n", fsp
->fsp_name
));
6455 close_file(fsp
, NORMAL_CLOSE
);
6456 return NT_STATUS_INVALID_PARAMETER
;
6460 * See if others still have the file open. If this is the case, then
6461 * don't delete. If all opens are POSIX delete we can set the delete
6462 * on close disposition.
6464 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6465 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6466 if (is_valid_share_mode_entry(e
)) {
6467 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6470 /* Fail with sharing violation. */
6471 close_file(fsp
, NORMAL_CLOSE
);
6473 return NT_STATUS_SHARING_VIOLATION
;
6478 * Set the delete on close.
6480 status
= smb_set_file_disposition_info(conn
,
6487 if (!NT_STATUS_IS_OK(status
)) {
6488 close_file(fsp
, NORMAL_CLOSE
);
6493 return close_file(fsp
, NORMAL_CLOSE
);
6496 /****************************************************************************
6497 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6498 ****************************************************************************/
6500 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6501 struct smb_request
*req
,
6502 unsigned int tran_call
,
6503 char **pparams
, int total_params
,
6504 char **ppdata
, int total_data
,
6505 unsigned int max_data_bytes
)
6507 char *params
= *pparams
;
6508 char *pdata
= *ppdata
;
6510 SMB_STRUCT_STAT sbuf
;
6512 files_struct
*fsp
= NULL
;
6513 NTSTATUS status
= NT_STATUS_OK
;
6514 int data_return_size
= 0;
6515 TALLOC_CTX
*ctx
= talloc_tos();
6518 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6524 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6525 if (total_params
< 4) {
6526 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6530 fsp
= file_fsp(SVAL(params
,0));
6531 /* Basic check for non-null fsp. */
6532 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
6535 info_level
= SVAL(params
,2);
6537 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6539 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6543 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6545 * This is actually a SETFILEINFO on a directory
6546 * handle (returned from an NT SMB). NT5.0 seems
6547 * to do this call. JRA.
6549 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6550 /* Always do lstat for UNIX calls. */
6551 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6552 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6553 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6557 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6558 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6559 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6563 } else if (fsp
->print_file
) {
6565 * Doing a DELETE_ON_CLOSE should cancel a print job.
6567 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6568 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6570 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6573 send_trans2_replies(conn
, req
, params
, 2,
6578 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6583 * Original code - this is an open file.
6585 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
6589 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6590 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6591 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6597 if (total_params
< 7) {
6598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6602 info_level
= SVAL(params
,0);
6603 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6604 total_params
- 6, STR_TERMINATE
,
6606 if (!NT_STATUS_IS_OK(status
)) {
6607 reply_nterror(req
, status
);
6611 status
= resolve_dfspath(ctx
, conn
,
6612 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6615 if (!NT_STATUS_IS_OK(status
)) {
6616 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6617 reply_botherror(req
,
6618 NT_STATUS_PATH_NOT_COVERED
,
6619 ERRSRV
, ERRbadpath
);
6622 reply_nterror(req
, status
);
6626 status
= unix_convert(ctx
, conn
, fname
, False
,
6627 &fname
, NULL
, &sbuf
);
6628 if (!NT_STATUS_IS_OK(status
)) {
6629 reply_nterror(req
, status
);
6633 status
= check_name(conn
, fname
);
6634 if (!NT_STATUS_IS_OK(status
)) {
6635 reply_nterror(req
, status
);
6639 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6641 * For CIFS UNIX extensions the target name may not exist.
6644 /* Always do lstat for UNIX calls. */
6645 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6647 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6648 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6649 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6654 if (!CAN_WRITE(conn
)) {
6655 reply_doserror(req
, ERRSRV
, ERRaccess
);
6659 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6660 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6664 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6665 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6667 /* Realloc the parameter size */
6668 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6669 if (*pparams
== NULL
) {
6670 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6677 switch (info_level
) {
6679 case SMB_INFO_STANDARD
:
6681 status
= smb_set_info_standard(conn
,
6690 case SMB_INFO_SET_EA
:
6692 status
= smb_info_set_ea(conn
,
6700 case SMB_SET_FILE_BASIC_INFO
:
6701 case SMB_FILE_BASIC_INFORMATION
:
6703 status
= smb_set_file_basic_info(conn
,
6712 case SMB_FILE_ALLOCATION_INFORMATION
:
6713 case SMB_SET_FILE_ALLOCATION_INFO
:
6715 status
= smb_set_file_allocation_info(conn
, req
,
6724 case SMB_FILE_END_OF_FILE_INFORMATION
:
6725 case SMB_SET_FILE_END_OF_FILE_INFO
:
6727 status
= smb_set_file_end_of_file_info(conn
, req
,
6736 case SMB_FILE_DISPOSITION_INFORMATION
:
6737 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6740 /* JRA - We used to just ignore this on a path ?
6741 * Shouldn't this be invalid level on a pathname
6744 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6745 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6748 status
= smb_set_file_disposition_info(conn
,
6757 case SMB_FILE_POSITION_INFORMATION
:
6759 status
= smb_file_position_information(conn
,
6766 /* From tridge Samba4 :
6767 * MODE_INFORMATION in setfileinfo (I have no
6768 * idea what "mode information" on a file is - it takes a value of 0,
6769 * 2, 4 or 6. What could it be?).
6772 case SMB_FILE_MODE_INFORMATION
:
6774 status
= smb_file_mode_information(conn
,
6781 * CIFS UNIX extensions.
6784 case SMB_SET_FILE_UNIX_BASIC
:
6786 status
= smb_set_file_unix_basic(conn
, req
,
6795 case SMB_SET_FILE_UNIX_INFO2
:
6797 status
= smb_set_file_unix_info2(conn
, req
,
6806 case SMB_SET_FILE_UNIX_LINK
:
6808 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6809 /* We must have a pathname for this. */
6810 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6813 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6818 case SMB_SET_FILE_UNIX_HLINK
:
6820 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6821 /* We must have a pathname for this. */
6822 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6825 status
= smb_set_file_unix_hlink(conn
, req
,
6831 case SMB_FILE_RENAME_INFORMATION
:
6833 status
= smb_file_rename_information(conn
, req
,
6839 #if defined(HAVE_POSIX_ACLS)
6840 case SMB_SET_POSIX_ACL
:
6842 status
= smb_set_posix_acl(conn
,
6852 case SMB_SET_POSIX_LOCK
:
6854 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6855 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6858 status
= smb_set_posix_lock(conn
, req
,
6859 pdata
, total_data
, fsp
);
6863 case SMB_POSIX_PATH_OPEN
:
6865 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6866 /* We must have a pathname for this. */
6867 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6871 status
= smb_posix_open(conn
, req
,
6880 case SMB_POSIX_PATH_UNLINK
:
6882 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6883 /* We must have a pathname for this. */
6884 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6888 status
= smb_posix_unlink(conn
, req
,
6897 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6902 if (!NT_STATUS_IS_OK(status
)) {
6903 if (open_was_deferred(req
->mid
)) {
6904 /* We have re-scheduled this call. */
6907 if (blocking_lock_was_deferred(req
->mid
)) {
6908 /* We have re-scheduled this call. */
6911 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6912 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6913 ERRSRV
, ERRbadpath
);
6916 if (info_level
== SMB_POSIX_PATH_OPEN
) {
6917 reply_openerror(req
, status
);
6921 reply_nterror(req
, status
);
6926 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
6932 /****************************************************************************
6933 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6934 ****************************************************************************/
6936 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
6937 char **pparams
, int total_params
,
6938 char **ppdata
, int total_data
,
6939 unsigned int max_data_bytes
)
6941 char *params
= *pparams
;
6942 char *pdata
= *ppdata
;
6943 char *directory
= NULL
;
6944 SMB_STRUCT_STAT sbuf
;
6945 NTSTATUS status
= NT_STATUS_OK
;
6946 struct ea_list
*ea_list
= NULL
;
6947 TALLOC_CTX
*ctx
= talloc_tos();
6949 if (!CAN_WRITE(conn
)) {
6950 reply_doserror(req
, ERRSRV
, ERRaccess
);
6954 if (total_params
< 5) {
6955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6959 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
6960 total_params
- 4, STR_TERMINATE
,
6962 if (!NT_STATUS_IS_OK(status
)) {
6963 reply_nterror(req
, status
);
6967 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
6969 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
6970 if (!NT_STATUS_IS_OK(status
)) {
6971 reply_nterror(req
, status
);
6975 status
= check_name(conn
, directory
);
6976 if (!NT_STATUS_IS_OK(status
)) {
6977 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
6978 reply_nterror(req
, status
);
6982 /* Any data in this call is an EA list. */
6983 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
6984 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
6989 * OS/2 workplace shell seems to send SET_EA requests of "null"
6990 * length (4 bytes containing IVAL 4).
6991 * They seem to have no effect. Bug #3212. JRA.
6994 if (total_data
!= 4) {
6995 if (total_data
< 10) {
6996 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7000 if (IVAL(pdata
,0) > total_data
) {
7001 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7002 IVAL(pdata
,0), (unsigned int)total_data
));
7003 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7007 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7013 } else if (IVAL(pdata
,0) != 4) {
7014 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7018 status
= create_directory(conn
, req
, directory
);
7020 if (!NT_STATUS_IS_OK(status
)) {
7021 reply_nterror(req
, status
);
7025 /* Try and set any given EA. */
7027 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7028 if (!NT_STATUS_IS_OK(status
)) {
7029 reply_nterror(req
, status
);
7034 /* Realloc the parameter and data sizes */
7035 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7036 if(*pparams
== NULL
) {
7037 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7044 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7049 /****************************************************************************
7050 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7051 We don't actually do this - we just send a null response.
7052 ****************************************************************************/
7054 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7055 struct smb_request
*req
,
7056 char **pparams
, int total_params
,
7057 char **ppdata
, int total_data
,
7058 unsigned int max_data_bytes
)
7060 static uint16 fnf_handle
= 257;
7061 char *params
= *pparams
;
7064 if (total_params
< 6) {
7065 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7069 info_level
= SVAL(params
,4);
7070 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7072 switch (info_level
) {
7077 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7081 /* Realloc the parameter and data sizes */
7082 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7083 if (*pparams
== NULL
) {
7084 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7089 SSVAL(params
,0,fnf_handle
);
7090 SSVAL(params
,2,0); /* No changes */
7091 SSVAL(params
,4,0); /* No EA errors */
7098 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7103 /****************************************************************************
7104 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7105 changes). Currently this does nothing.
7106 ****************************************************************************/
7108 static void call_trans2findnotifynext(connection_struct
*conn
,
7109 struct smb_request
*req
,
7110 char **pparams
, int total_params
,
7111 char **ppdata
, int total_data
,
7112 unsigned int max_data_bytes
)
7114 char *params
= *pparams
;
7116 DEBUG(3,("call_trans2findnotifynext\n"));
7118 /* Realloc the parameter and data sizes */
7119 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7120 if (*pparams
== NULL
) {
7121 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7126 SSVAL(params
,0,0); /* No changes */
7127 SSVAL(params
,2,0); /* No EA errors */
7129 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7134 /****************************************************************************
7135 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7136 ****************************************************************************/
7138 static void call_trans2getdfsreferral(connection_struct
*conn
,
7139 struct smb_request
*req
,
7140 char **pparams
, int total_params
,
7141 char **ppdata
, int total_data
,
7142 unsigned int max_data_bytes
)
7144 char *params
= *pparams
;
7145 char *pathname
= NULL
;
7147 int max_referral_level
;
7148 NTSTATUS status
= NT_STATUS_OK
;
7149 TALLOC_CTX
*ctx
= talloc_tos();
7151 DEBUG(10,("call_trans2getdfsreferral\n"));
7153 if (total_params
< 3) {
7154 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7158 max_referral_level
= SVAL(params
,0);
7160 if(!lp_host_msdfs()) {
7161 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7165 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7166 total_params
- 2, STR_TERMINATE
);
7168 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7171 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7172 ppdata
,&status
)) < 0) {
7173 reply_nterror(req
, status
);
7177 SSVAL(req
->inbuf
, smb_flg2
,
7178 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7179 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7184 #define LMCAT_SPL 0x53
7185 #define LMFUNC_GETJOBID 0x60
7187 /****************************************************************************
7188 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7189 ****************************************************************************/
7191 static void call_trans2ioctl(connection_struct
*conn
,
7192 struct smb_request
*req
,
7193 char **pparams
, int total_params
,
7194 char **ppdata
, int total_data
,
7195 unsigned int max_data_bytes
)
7197 char *pdata
= *ppdata
;
7198 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv15
));
7200 /* check for an invalid fid before proceeding */
7203 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7207 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7208 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7209 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7210 if (*ppdata
== NULL
) {
7211 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7216 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7217 CAN ACCEPT THIS IN UNICODE. JRA. */
7219 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7220 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7221 global_myname(), 15,
7222 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7223 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7224 lp_servicename(SNUM(conn
)), 13,
7225 STR_ASCII
|STR_TERMINATE
); /* Service name */
7226 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7231 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7232 reply_doserror(req
, ERRSRV
, ERRerror
);
7235 /****************************************************************************
7236 Reply to a SMBfindclose (stop trans2 directory search).
7237 ****************************************************************************/
7239 void reply_findclose(struct smb_request
*req
)
7243 START_PROFILE(SMBfindclose
);
7246 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7247 END_PROFILE(SMBfindclose
);
7251 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7253 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7255 dptr_close(&dptr_num
);
7257 reply_outbuf(req
, 0, 0);
7259 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7261 END_PROFILE(SMBfindclose
);
7265 /****************************************************************************
7266 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7267 ****************************************************************************/
7269 void reply_findnclose(struct smb_request
*req
)
7273 START_PROFILE(SMBfindnclose
);
7276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7277 END_PROFILE(SMBfindnclose
);
7281 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7283 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7285 /* We never give out valid handles for a
7286 findnotifyfirst - so any dptr_num is ok here.
7289 reply_outbuf(req
, 0, 0);
7291 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7293 END_PROFILE(SMBfindnclose
);
7297 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7298 struct trans_state
*state
)
7300 if (Protocol
>= PROTOCOL_NT1
) {
7301 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7302 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7305 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7306 if (state
->call
!= TRANSACT2_QFSINFO
&&
7307 state
->call
!= TRANSACT2_SETFSINFO
) {
7308 DEBUG(0,("handle_trans2: encryption required "
7310 (unsigned int)state
->call
));
7311 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7316 /* Now we must call the relevant TRANS2 function */
7317 switch(state
->call
) {
7318 case TRANSACT2_OPEN
:
7320 START_PROFILE(Trans2_open
);
7321 call_trans2open(conn
, req
,
7322 &state
->param
, state
->total_param
,
7323 &state
->data
, state
->total_data
,
7324 state
->max_data_return
);
7325 END_PROFILE(Trans2_open
);
7329 case TRANSACT2_FINDFIRST
:
7331 START_PROFILE(Trans2_findfirst
);
7332 call_trans2findfirst(conn
, req
,
7333 &state
->param
, state
->total_param
,
7334 &state
->data
, state
->total_data
,
7335 state
->max_data_return
);
7336 END_PROFILE(Trans2_findfirst
);
7340 case TRANSACT2_FINDNEXT
:
7342 START_PROFILE(Trans2_findnext
);
7343 call_trans2findnext(conn
, req
,
7344 &state
->param
, state
->total_param
,
7345 &state
->data
, state
->total_data
,
7346 state
->max_data_return
);
7347 END_PROFILE(Trans2_findnext
);
7351 case TRANSACT2_QFSINFO
:
7353 START_PROFILE(Trans2_qfsinfo
);
7354 call_trans2qfsinfo(conn
, req
,
7355 &state
->param
, state
->total_param
,
7356 &state
->data
, state
->total_data
,
7357 state
->max_data_return
);
7358 END_PROFILE(Trans2_qfsinfo
);
7362 case TRANSACT2_SETFSINFO
:
7364 START_PROFILE(Trans2_setfsinfo
);
7365 call_trans2setfsinfo(conn
, req
,
7366 &state
->param
, state
->total_param
,
7367 &state
->data
, state
->total_data
,
7368 state
->max_data_return
);
7369 END_PROFILE(Trans2_setfsinfo
);
7373 case TRANSACT2_QPATHINFO
:
7374 case TRANSACT2_QFILEINFO
:
7376 START_PROFILE(Trans2_qpathinfo
);
7377 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7378 &state
->param
, state
->total_param
,
7379 &state
->data
, state
->total_data
,
7380 state
->max_data_return
);
7381 END_PROFILE(Trans2_qpathinfo
);
7385 case TRANSACT2_SETPATHINFO
:
7386 case TRANSACT2_SETFILEINFO
:
7388 START_PROFILE(Trans2_setpathinfo
);
7389 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7390 &state
->param
, state
->total_param
,
7391 &state
->data
, state
->total_data
,
7392 state
->max_data_return
);
7393 END_PROFILE(Trans2_setpathinfo
);
7397 case TRANSACT2_FINDNOTIFYFIRST
:
7399 START_PROFILE(Trans2_findnotifyfirst
);
7400 call_trans2findnotifyfirst(conn
, req
,
7401 &state
->param
, state
->total_param
,
7402 &state
->data
, state
->total_data
,
7403 state
->max_data_return
);
7404 END_PROFILE(Trans2_findnotifyfirst
);
7408 case TRANSACT2_FINDNOTIFYNEXT
:
7410 START_PROFILE(Trans2_findnotifynext
);
7411 call_trans2findnotifynext(conn
, req
,
7412 &state
->param
, state
->total_param
,
7413 &state
->data
, state
->total_data
,
7414 state
->max_data_return
);
7415 END_PROFILE(Trans2_findnotifynext
);
7419 case TRANSACT2_MKDIR
:
7421 START_PROFILE(Trans2_mkdir
);
7422 call_trans2mkdir(conn
, req
,
7423 &state
->param
, state
->total_param
,
7424 &state
->data
, state
->total_data
,
7425 state
->max_data_return
);
7426 END_PROFILE(Trans2_mkdir
);
7430 case TRANSACT2_GET_DFS_REFERRAL
:
7432 START_PROFILE(Trans2_get_dfs_referral
);
7433 call_trans2getdfsreferral(conn
, req
,
7434 &state
->param
, state
->total_param
,
7435 &state
->data
, state
->total_data
,
7436 state
->max_data_return
);
7437 END_PROFILE(Trans2_get_dfs_referral
);
7441 case TRANSACT2_IOCTL
:
7443 START_PROFILE(Trans2_ioctl
);
7444 call_trans2ioctl(conn
, req
,
7445 &state
->param
, state
->total_param
,
7446 &state
->data
, state
->total_data
,
7447 state
->max_data_return
);
7448 END_PROFILE(Trans2_ioctl
);
7453 /* Error in request */
7454 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7455 reply_doserror(req
, ERRSRV
,ERRerror
);
7459 /****************************************************************************
7460 Reply to a SMBtrans2.
7461 ****************************************************************************/
7463 void reply_trans2(struct smb_request
*req
)
7465 connection_struct
*conn
= req
->conn
;
7470 unsigned int tran_call
;
7472 unsigned int av_size
;
7473 struct trans_state
*state
;
7476 START_PROFILE(SMBtrans2
);
7478 if (req
->wct
< 14) {
7479 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7480 END_PROFILE(SMBtrans2
);
7484 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7485 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7486 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7487 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7488 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7489 size
= smb_len(req
->inbuf
) + 4;
7490 av_size
= smb_len(req
->inbuf
);
7492 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7493 if (!NT_STATUS_IS_OK(result
)) {
7494 DEBUG(2, ("Got invalid trans2 request: %s\n",
7495 nt_errstr(result
)));
7496 reply_nterror(req
, result
);
7497 END_PROFILE(SMBtrans2
);
7502 switch (tran_call
) {
7503 /* List the allowed trans2 calls on IPC$ */
7504 case TRANSACT2_OPEN
:
7505 case TRANSACT2_GET_DFS_REFERRAL
:
7506 case TRANSACT2_QFILEINFO
:
7507 case TRANSACT2_QFSINFO
:
7508 case TRANSACT2_SETFSINFO
:
7511 reply_doserror(req
, ERRSRV
, ERRaccess
);
7512 END_PROFILE(SMBtrans2
);
7517 if ((state
= TALLOC_P(conn
->mem_ctx
, struct trans_state
)) == NULL
) {
7518 DEBUG(0, ("talloc failed\n"));
7519 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7520 END_PROFILE(SMBtrans2
);
7524 state
->cmd
= SMBtrans2
;
7526 state
->mid
= req
->mid
;
7527 state
->vuid
= req
->vuid
;
7528 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7529 state
->setup
= NULL
;
7530 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7531 state
->param
= NULL
;
7532 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7534 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7535 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7536 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7537 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7538 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7540 state
->call
= tran_call
;
7542 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7543 is so as a sanity check */
7544 if (state
->setup_count
!= 1) {
7546 * Need to have rc=0 for ioctl to get job id for OS/2.
7547 * Network printing will fail if function is not successful.
7548 * Similar function in reply.c will be used if protocol
7549 * is LANMAN1.0 instead of LM1.2X002.
7550 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7551 * outbuf doesn't have to be set(only job id is used).
7553 if ( (state
->setup_count
== 4)
7554 && (tran_call
== TRANSACT2_IOCTL
)
7555 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7556 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7557 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7559 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7560 DEBUG(2,("Transaction is %d\n",tran_call
));
7562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7563 END_PROFILE(SMBtrans2
);
7568 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7571 if (state
->total_data
) {
7572 /* Can't use talloc here, the core routines do realloc on the
7573 * params and data. */
7574 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7575 if (state
->data
== NULL
) {
7576 DEBUG(0,("reply_trans2: data malloc fail for %u "
7577 "bytes !\n", (unsigned int)state
->total_data
));
7579 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7580 END_PROFILE(SMBtrans2
);
7584 if (dscnt
> state
->total_data
||
7585 dsoff
+dscnt
< dsoff
) {
7589 if (dsoff
> av_size
||
7591 dsoff
+dscnt
> av_size
) {
7595 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7598 if (state
->total_param
) {
7599 /* Can't use talloc here, the core routines do realloc on the
7600 * params and data. */
7601 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7602 if (state
->param
== NULL
) {
7603 DEBUG(0,("reply_trans: param malloc fail for %u "
7604 "bytes !\n", (unsigned int)state
->total_param
));
7605 SAFE_FREE(state
->data
);
7607 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7608 END_PROFILE(SMBtrans2
);
7612 if (pscnt
> state
->total_param
||
7613 psoff
+pscnt
< psoff
) {
7617 if (psoff
> av_size
||
7619 psoff
+pscnt
> av_size
) {
7623 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7626 state
->received_data
= dscnt
;
7627 state
->received_param
= pscnt
;
7629 if ((state
->received_param
== state
->total_param
) &&
7630 (state
->received_data
== state
->total_data
)) {
7632 handle_trans2(conn
, req
, state
);
7634 SAFE_FREE(state
->data
);
7635 SAFE_FREE(state
->param
);
7637 END_PROFILE(SMBtrans2
);
7641 DLIST_ADD(conn
->pending_trans
, state
);
7643 /* We need to send an interim response then receive the rest
7644 of the parameter/data bytes */
7645 reply_outbuf(req
, 0, 0);
7646 show_msg((char *)req
->outbuf
);
7647 END_PROFILE(SMBtrans2
);
7652 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7653 SAFE_FREE(state
->data
);
7654 SAFE_FREE(state
->param
);
7656 END_PROFILE(SMBtrans2
);
7657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7661 /****************************************************************************
7662 Reply to a SMBtranss2
7663 ****************************************************************************/
7665 void reply_transs2(struct smb_request
*req
)
7667 connection_struct
*conn
= req
->conn
;
7668 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7669 struct trans_state
*state
;
7671 unsigned int av_size
;
7673 START_PROFILE(SMBtranss2
);
7675 show_msg((char *)req
->inbuf
);
7678 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7679 END_PROFILE(SMBtranss2
);
7683 size
= smb_len(req
->inbuf
)+4;
7684 av_size
= smb_len(req
->inbuf
);
7686 for (state
= conn
->pending_trans
; state
!= NULL
;
7687 state
= state
->next
) {
7688 if (state
->mid
== req
->mid
) {
7693 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7694 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7695 END_PROFILE(SMBtranss2
);
7699 /* Revise state->total_param and state->total_data in case they have
7700 changed downwards */
7702 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7703 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7704 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7705 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7707 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7708 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7709 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7711 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7712 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7713 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7715 state
->received_param
+= pcnt
;
7716 state
->received_data
+= dcnt
;
7718 if ((state
->received_data
> state
->total_data
) ||
7719 (state
->received_param
> state
->total_param
))
7723 if (pdisp
> state
->total_param
||
7724 pcnt
> state
->total_param
||
7725 pdisp
+pcnt
> state
->total_param
||
7726 pdisp
+pcnt
< pdisp
) {
7730 if (poff
> av_size
||
7732 poff
+pcnt
> av_size
||
7737 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7742 if (ddisp
> state
->total_data
||
7743 dcnt
> state
->total_data
||
7744 ddisp
+dcnt
> state
->total_data
||
7745 ddisp
+dcnt
< ddisp
) {
7749 if (ddisp
> av_size
||
7751 ddisp
+dcnt
> av_size
||
7752 ddisp
+dcnt
< ddisp
) {
7756 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7760 if ((state
->received_param
< state
->total_param
) ||
7761 (state
->received_data
< state
->total_data
)) {
7762 END_PROFILE(SMBtranss2
);
7767 * construct_reply_common will copy smb_com from inbuf to
7768 * outbuf. SMBtranss2 is wrong here.
7770 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7772 handle_trans2(conn
, req
, state
);
7774 DLIST_REMOVE(conn
->pending_trans
, state
);
7775 SAFE_FREE(state
->data
);
7776 SAFE_FREE(state
->param
);
7779 END_PROFILE(SMBtranss2
);
7784 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7785 DLIST_REMOVE(conn
->pending_trans
, state
);
7786 SAFE_FREE(state
->data
);
7787 SAFE_FREE(state
->param
);
7789 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7790 END_PROFILE(SMBtranss2
);