2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol
;
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct
*conn
,
37 const SMB_STRUCT_STAT
*psbuf
);
39 static char *store_file_unix_basic_info2(connection_struct
*conn
,
42 const SMB_STRUCT_STAT
*psbuf
);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
51 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type
= get_remote_arch();
55 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
56 val
= SMB_ROUNDUP(val
,rval
);
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name
)
71 static const char * const prohibited_ea_names
[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME
,
73 SAMBA_XATTR_DOS_ATTRIB
,
79 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
80 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
83 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
94 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
95 files_struct
*fsp
, const char *fname
,
96 const char *ea_name
, struct ea_struct
*pea
)
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size
= 256;
105 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
107 return NT_STATUS_NO_MEMORY
;
110 if (fsp
&& fsp
->fh
->fd
!= -1) {
111 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
113 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
116 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
122 return map_nt_error_from_unix(errno
);
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
126 dump_data(10, (uint8
*)val
, sizeret
);
129 if (strnequal(ea_name
, "user.", 5)) {
130 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
132 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
134 if (pea
->name
== NULL
) {
136 return NT_STATUS_NO_MEMORY
;
138 pea
->value
.data
= (unsigned char *)val
;
139 pea
->value
.length
= (size_t)sizeret
;
143 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
144 files_struct
*fsp
, const char *fname
,
145 char ***pnames
, size_t *pnum_names
)
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size
= 1024;
149 char *ea_namelist
= NULL
;
154 ssize_t sizeret
= -1;
156 if (!lp_ea_support(SNUM(conn
))) {
163 * TALLOC the result early to get the talloc hierarchy right.
166 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY
;
172 while (ea_namelist_size
<= 65536) {
174 ea_namelist
= TALLOC_REALLOC_ARRAY(
175 names
, ea_namelist
, char, ea_namelist_size
);
176 if (ea_namelist
== NULL
) {
177 DEBUG(0, ("talloc failed\n"));
179 return NT_STATUS_NO_MEMORY
;
182 if (fsp
&& fsp
->fh
->fd
!= -1) {
183 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
186 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
190 if ((sizeret
== -1) && (errno
== ERANGE
)) {
191 ea_namelist_size
*= 2;
200 return map_nt_error_from_unix(errno
);
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret
));
214 * Ensure the result is 0-terminated
217 if (ea_namelist
[sizeret
-1] != '\0') {
219 return NT_STATUS_INTERNAL_ERROR
;
227 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
231 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY
;
241 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
242 names
[num_names
++] = p
;
246 *pnum_names
= num_names
;
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
254 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
255 const char *fname
, size_t *pea_total_len
)
257 /* Get a list of all xattrs. Max namesize is 64k. */
260 struct ea_list
*ea_list_head
= NULL
;
265 if (!lp_ea_support(SNUM(conn
))) {
269 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
272 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
276 for (i
=0; i
<num_names
; i
++) {
277 struct ea_list
*listp
;
280 if (strnequal(names
[i
], "system.", 7)
281 || samba_private_attr_name(names
[i
]))
284 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
295 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
298 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
302 (unsigned int)listp
->ea
.value
.length
));
304 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
308 /* Add on 4 for total length. */
309 if (*pea_total_len
) {
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len
));
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
322 ****************************************************************************/
324 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
325 connection_struct
*conn
, struct ea_list
*ea_list
)
327 unsigned int ret_data_size
= 4;
330 SMB_ASSERT(total_data_size
>= 4);
332 if (!lp_ea_support(SNUM(conn
))) {
337 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
340 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
341 dos_namelen
= strlen(dos_ea_name
);
342 if (dos_namelen
> 255 || dos_namelen
== 0) {
345 if (ea_list
->ea
.value
.length
> 65535) {
348 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
352 /* We know we have room. */
353 SCVAL(p
,0,ea_list
->ea
.flags
);
354 SCVAL(p
,1,dos_namelen
);
355 SSVAL(p
,2,ea_list
->ea
.value
.length
);
356 fstrcpy(p
+4, dos_ea_name
);
357 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
359 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
360 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
363 ret_data_size
= PTR_DIFF(p
, pdata
);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
365 SIVAL(pdata
,0,ret_data_size
);
366 return ret_data_size
;
369 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
371 size_t total_ea_len
= 0;
372 TALLOC_CTX
*mem_ctx
= NULL
;
374 if (!lp_ea_support(SNUM(conn
))) {
377 mem_ctx
= talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
386 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
389 TALLOC_CTX
*mem_ctx
= talloc_tos();
390 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
392 for (; ea_list
; ea_list
= ea_list
->next
) {
393 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name
[5], ea_list
->ea
.name
));
396 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
406 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
408 if (!lp_ea_support(SNUM(conn
))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED
;
412 for (;ea_list
; ea_list
= ea_list
->next
) {
414 fstring unix_ea_name
;
416 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
419 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
423 if (samba_private_attr_name(unix_ea_name
)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
425 return NT_STATUS_ACCESS_DENIED
;
428 if (ea_list
->ea
.value
.length
== 0) {
429 /* Remove the attribute. */
430 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name
, fsp
->fsp_name
));
433 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name
, fname
));
437 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
440 /* Removing a non existent attribute always succeeds. */
441 if (ret
== -1 && errno
== ENOATTR
) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
448 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name
, fsp
->fsp_name
));
451 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
452 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name
, fname
));
456 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
457 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
463 if (errno
== ENOTSUP
) {
464 return NT_STATUS_EAS_NOT_SUPPORTED
;
467 return map_nt_error_from_unix(errno
);
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
477 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
479 struct ea_list
*ea_list_head
= NULL
;
480 size_t converted_size
, offset
= 0;
482 while (offset
+ 2 < data_size
) {
483 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
484 unsigned int namelen
= CVAL(pdata
,offset
);
486 offset
++; /* Go past the namelen byte. */
488 /* integer wrap paranioa. */
489 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
490 (offset
> data_size
) || (namelen
> data_size
) ||
491 (offset
+ namelen
>= data_size
)) {
494 /* Ensure the name is null terminated. */
495 if (pdata
[offset
+ namelen
] != '\0') {
498 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno
)));
507 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
519 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
521 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
523 unsigned int namelen
;
524 size_t converted_size
;
534 eal
->ea
.flags
= CVAL(pdata
,0);
535 namelen
= CVAL(pdata
,1);
536 val_len
= SVAL(pdata
,2);
538 if (4 + namelen
+ 1 + val_len
> data_size
) {
542 /* Ensure the name is null terminated. */
543 if (pdata
[namelen
+ 4] != '\0') {
546 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
554 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
555 if (!eal
->ea
.value
.data
) {
559 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
561 /* Ensure we're null terminated just in case we print the value. */
562 eal
->ea
.value
.data
[val_len
] = '\0';
563 /* But don't count the null. */
564 eal
->ea
.value
.length
--;
567 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
571 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
580 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
582 struct ea_list
*ea_list_head
= NULL
;
584 size_t bytes_used
= 0;
586 while (offset
< data_size
) {
587 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
593 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
594 offset
+= bytes_used
;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list
*ealist
)
607 struct ea_list
*listp
;
610 for (listp
= ealist
; listp
; listp
= listp
->next
) {
611 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
612 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
614 /* Add on 4 for total length. */
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
628 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
630 struct ea_list
*nlistp
, *flistp
;
632 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
633 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
634 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
640 /* Copy the data from this entry. */
641 nlistp
->ea
.flags
= flistp
->ea
.flags
;
642 nlistp
->ea
.value
= flistp
->ea
.value
;
645 nlistp
->ea
.flags
= 0;
646 ZERO_STRUCT(nlistp
->ea
.value
);
650 *total_ea_len
= ea_list_size(name_list
);
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
661 void send_trans2_replies(connection_struct
*conn
,
662 struct smb_request
*req
,
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
675 int data_to_send
= datasize
;
676 int params_to_send
= paramsize
;
678 const char *pp
= params
;
679 const char *pd
= pdata
;
680 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
681 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset
= 0;
683 bool overflow
= False
;
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
690 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes
, datasize
));
693 datasize
= data_to_send
= max_data_bytes
;
697 /* If there genuinely are no parameters or data to send just send the empty packet */
699 if(params_to_send
== 0 && data_to_send
== 0) {
700 reply_outbuf(req
, 10, 0);
701 show_msg((char *)req
->outbuf
);
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
709 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
710 data_alignment_offset
= 4 - (params_to_send
% 4);
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
716 useable_space
= max_send
- (smb_size
719 + data_alignment_offset
);
721 if (useable_space
< 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space
));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
727 while (params_to_send
|| data_to_send
) {
728 /* Calculate whether we will totally or partially fill this packet */
730 total_sent_thistime
= params_to_send
+ data_to_send
;
732 /* We can never send more than useable_space */
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
740 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
742 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
743 + data_alignment_offset
);
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
749 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
751 /* Set total params and data to be sent */
752 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
753 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
759 params_sent_thistime
= MIN(params_to_send
,useable_space
);
760 data_sent_thistime
= useable_space
- params_sent_thistime
;
761 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
763 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
770 SSVAL(req
->outbuf
,smb_proff
,
771 ((smb_buf(req
->outbuf
)+alignment_offset
)
772 - smb_base(req
->outbuf
)));
774 if(params_sent_thistime
== 0)
775 SSVAL(req
->outbuf
,smb_prdisp
,0);
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
780 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
781 if(data_sent_thistime
== 0) {
782 SSVAL(req
->outbuf
,smb_droff
,0);
783 SSVAL(req
->outbuf
,smb_drdisp
, 0);
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req
->outbuf
, smb_droff
,
788 ((smb_buf(req
->outbuf
)+alignment_offset
)
789 - smb_base(req
->outbuf
))
790 + params_sent_thistime
+ data_alignment_offset
);
791 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
794 /* Initialize the padding for alignment */
796 if (alignment_offset
!= 0) {
797 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
800 /* Copy the param bytes into the packet */
802 if(params_sent_thistime
) {
803 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
804 params_sent_thistime
);
807 /* Copy in the data bytes */
808 if(data_sent_thistime
) {
809 if (data_alignment_offset
!= 0) {
810 memset((smb_buf(req
->outbuf
)+alignment_offset
+
811 params_sent_thistime
), 0,
812 data_alignment_offset
);
814 memcpy(smb_buf(req
->outbuf
)+alignment_offset
815 +params_sent_thistime
+data_alignment_offset
,
816 pd
,data_sent_thistime
);
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime
, data_sent_thistime
, useable_space
));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send
, data_to_send
, paramsize
, datasize
));
825 error_packet_set((char *)req
->outbuf
,
826 ERRDOS
,ERRbufferoverflow
,
827 STATUS_BUFFER_OVERFLOW
,
831 /* Send the packet */
832 show_msg((char *)req
->outbuf
);
833 if (!srv_send_smb(smbd_server_fd(),
835 IS_CONN_ENCRYPTED(conn
),
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
839 TALLOC_FREE(req
->outbuf
);
841 pp
+= params_sent_thistime
;
842 pd
+= data_sent_thistime
;
844 params_to_send
-= params_sent_thistime
;
845 data_to_send
-= data_sent_thistime
;
848 if(params_to_send
< 0 || data_to_send
< 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send
, data_to_send
));
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
862 static void call_trans2open(connection_struct
*conn
,
863 struct smb_request
*req
,
864 char **pparams
, int total_params
,
865 char **ppdata
, int total_data
,
866 unsigned int max_data_bytes
)
868 char *params
= *pparams
;
869 char *pdata
= *ppdata
;
874 bool return_additional_info
;
885 SMB_STRUCT_STAT sbuf
;
888 struct ea_list
*ea_list
= NULL
;
893 uint32 create_disposition
;
894 uint32 create_options
= 0;
895 TALLOC_CTX
*ctx
= talloc_tos();
898 * Ensure we have enough parameters to perform the operation.
901 if (total_params
< 29) {
902 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
906 flags
= SVAL(params
, 0);
907 deny_mode
= SVAL(params
, 2);
908 open_attr
= SVAL(params
,6);
909 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
910 if (oplock_request
) {
911 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
915 return_additional_info
= BITSETW(params
,0);
916 open_sattr
= SVAL(params
, 4);
917 open_time
= make_unix_date3(params
+8);
919 open_ofun
= SVAL(params
,12);
920 open_size
= IVAL(params
,14);
924 reply_doserror(req
, ERRSRV
, ERRaccess
);
928 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
929 total_params
- 28, STR_TERMINATE
,
931 if (!NT_STATUS_IS_OK(status
)) {
932 reply_nterror(req
, status
);
936 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
937 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
938 (unsigned int)open_ofun
, open_size
));
940 if (open_ofun
== 0) {
941 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
945 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
950 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
954 /* Any data in this call is an EA list. */
955 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
956 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
960 if (total_data
!= 4) {
961 if (total_data
< 10) {
962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
966 if (IVAL(pdata
,0) > total_data
) {
967 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
968 IVAL(pdata
,0), (unsigned int)total_data
));
969 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
973 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
976 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
979 } else if (IVAL(pdata
,0) != 4) {
980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
984 status
= SMB_VFS_CREATE_FILE(
987 0, /* root_dir_fid */
989 CFF_DOS_PATH
, /* create_file_flags */
990 access_mask
, /* access_mask */
991 share_mode
, /* share_access */
992 create_disposition
, /* create_disposition*/
993 create_options
, /* create_options */
994 open_attr
, /* file_attributes */
995 oplock_request
, /* oplock_request */
996 open_size
, /* allocation_size */
998 ea_list
, /* ea_list */
1000 &smb_action
, /* pinfo */
1003 if (!NT_STATUS_IS_OK(status
)) {
1004 if (open_was_deferred(req
->mid
)) {
1005 /* We have re-scheduled this call. */
1008 reply_openerror(req
, status
);
1012 size
= get_file_size_stat(&sbuf
);
1013 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1014 mtime
= sbuf
.st_mtime
;
1015 inode
= sbuf
.st_ino
;
1017 close_file(req
, fsp
, ERROR_CLOSE
);
1018 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1022 /* Realloc the size of parameters and data we will return */
1023 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1024 if(*pparams
== NULL
) {
1025 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1030 SSVAL(params
,0,fsp
->fnum
);
1031 SSVAL(params
,2,fattr
);
1032 srv_put_dos_date2(params
,4, mtime
);
1033 SIVAL(params
,8, (uint32
)size
);
1034 SSVAL(params
,12,deny_mode
);
1035 SSVAL(params
,14,0); /* open_type - file or directory. */
1036 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1038 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1039 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1042 SSVAL(params
,18,smb_action
);
1045 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1047 SIVAL(params
,20,inode
);
1048 SSVAL(params
,24,0); /* Padding. */
1050 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1051 SIVAL(params
, 26, ea_size
);
1053 SIVAL(params
, 26, 0);
1056 /* Send the required number of replies */
1057 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1060 /*********************************************************
1061 Routine to check if a given string matches exactly.
1062 as a special case a mask of "." does NOT match. That
1063 is required for correct wildcard semantics
1064 Case can be significant or not.
1065 **********************************************************/
1067 static bool exact_match(connection_struct
*conn
,
1071 if (mask
[0] == '.' && mask
[1] == 0)
1073 if (dptr_has_wild(conn
->dirptr
)) {
1076 if (conn
->case_sensitive
)
1077 return strcmp(str
,mask
)==0;
1079 return StrCaseCmp(str
,mask
) == 0;
1082 /****************************************************************************
1083 Return the filetype for UNIX extensions.
1084 ****************************************************************************/
1086 static uint32
unix_filetype(mode_t mode
)
1089 return UNIX_TYPE_FILE
;
1090 else if(S_ISDIR(mode
))
1091 return UNIX_TYPE_DIR
;
1093 else if(S_ISLNK(mode
))
1094 return UNIX_TYPE_SYMLINK
;
1097 else if(S_ISCHR(mode
))
1098 return UNIX_TYPE_CHARDEV
;
1101 else if(S_ISBLK(mode
))
1102 return UNIX_TYPE_BLKDEV
;
1105 else if(S_ISFIFO(mode
))
1106 return UNIX_TYPE_FIFO
;
1109 else if(S_ISSOCK(mode
))
1110 return UNIX_TYPE_SOCKET
;
1113 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1114 return UNIX_TYPE_UNKNOWN
;
1117 /****************************************************************************
1118 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1119 ****************************************************************************/
1121 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1123 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1124 SMB_STRUCT_STAT
*psbuf
,
1126 enum perm_type ptype
,
1131 if (perms
== SMB_MODE_NO_CHANGE
) {
1132 if (!VALID_STAT(*psbuf
)) {
1133 return NT_STATUS_INVALID_PARAMETER
;
1135 *ret_perms
= psbuf
->st_mode
;
1136 return NT_STATUS_OK
;
1140 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1141 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1142 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1143 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1144 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1145 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1146 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1147 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1148 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1150 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1153 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1156 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1161 /* Apply mode mask */
1162 ret
&= lp_create_mask(SNUM(conn
));
1163 /* Add in force bits */
1164 ret
|= lp_force_create_mode(SNUM(conn
));
1167 ret
&= lp_dir_mask(SNUM(conn
));
1168 /* Add in force bits */
1169 ret
|= lp_force_dir_mode(SNUM(conn
));
1171 case PERM_EXISTING_FILE
:
1172 /* Apply mode mask */
1173 ret
&= lp_security_mask(SNUM(conn
));
1174 /* Add in force bits */
1175 ret
|= lp_force_security_mode(SNUM(conn
));
1177 case PERM_EXISTING_DIR
:
1178 /* Apply mode mask */
1179 ret
&= lp_dir_security_mask(SNUM(conn
));
1180 /* Add in force bits */
1181 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1186 return NT_STATUS_OK
;
1189 /****************************************************************************
1190 Needed to show the msdfs symlinks as directories. Modifies psbuf
1191 to be a directory if it's a msdfs link.
1192 ****************************************************************************/
1194 static bool check_msdfs_link(connection_struct
*conn
,
1195 const char *pathname
,
1196 SMB_STRUCT_STAT
*psbuf
)
1198 int saved_errno
= errno
;
1199 if(lp_host_msdfs() &&
1200 lp_msdfs_root(SNUM(conn
)) &&
1201 is_msdfs_link(conn
, pathname
, psbuf
)) {
1203 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1207 errno
= saved_errno
;
1210 errno
= saved_errno
;
1215 /****************************************************************************
1216 Get a level dependent lanman2 dir entry.
1217 ****************************************************************************/
1219 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1220 connection_struct
*conn
,
1222 const char *path_mask
,
1225 int requires_resume_key
,
1231 int space_remaining
,
1233 bool *got_exact_match
,
1234 int *last_entry_off
,
1235 struct ea_list
*name_list
)
1239 SMB_STRUCT_STAT sbuf
;
1240 const char *mask
= NULL
;
1241 char *pathreal
= NULL
;
1242 const char *fname
= NULL
;
1243 char *p
, *q
, *pdata
= *ppdata
;
1247 SMB_OFF_T file_size
= 0;
1248 uint64_t allocation_size
= 0;
1250 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1251 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1253 char *last_entry_ptr
;
1255 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1256 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1257 bool check_mangled_names
= lp_manglednames(conn
->params
);
1258 char mangled_name
[13]; /* mangled 8.3 name. */
1260 *out_of_space
= False
;
1261 *got_exact_match
= False
;
1263 ZERO_STRUCT(mdate_ts
);
1264 ZERO_STRUCT(adate_ts
);
1265 ZERO_STRUCT(create_date_ts
);
1267 if (!conn
->dirptr
) {
1271 p
= strrchr_m(path_mask
,'/');
1274 mask
= talloc_strdup(ctx
,"*.*");
1284 bool ms_dfs_link
= False
;
1286 /* Needed if we run out of space */
1287 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1288 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1291 * Due to bugs in NT client redirectors we are not using
1292 * resume keys any more - set them to zero.
1293 * Check out the related comments in findfirst/findnext.
1299 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1300 (long)conn
->dirptr
,curr_dirpos
));
1307 * fname may get mangled, dname is never mangled.
1308 * Whenever we're accessing the filesystem we use
1309 * pathreal which is composed from dname.
1315 /* Mangle fname if it's an illegal name. */
1316 if (mangle_must_mangle(dname
,conn
->params
)) {
1317 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1318 continue; /* Error - couldn't mangle. */
1320 fname
= mangled_name
;
1323 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1324 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1327 if(!got_match
&& check_mangled_names
&&
1328 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1330 * It turns out that NT matches wildcards against
1331 * both long *and* short names. This may explain some
1332 * of the wildcard wierdness from old DOS clients
1333 * that some people have been seeing.... JRA.
1335 /* Force the mangling into 8.3. */
1336 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1337 continue; /* Error - couldn't mangle. */
1340 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1341 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1346 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1348 if (dont_descend
&& !isdots
) {
1354 pathreal
= talloc_asprintf(ctx
,
1359 pathreal
= talloc_asprintf(ctx
,
1369 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1370 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1371 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1372 pathreal
,strerror(errno
)));
1373 TALLOC_FREE(pathreal
);
1376 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1377 /* Needed to show the msdfs symlinks as
1380 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1383 pathreal
,strerror(errno
)));
1384 TALLOC_FREE(pathreal
);
1390 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1392 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1395 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1396 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1397 TALLOC_FREE(pathreal
);
1401 if (!(mode
& aDIR
)) {
1402 file_size
= get_file_size_stat(&sbuf
);
1404 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,NULL
,&sbuf
);
1406 mdate_ts
= get_mtimespec(&sbuf
);
1407 adate_ts
= get_atimespec(&sbuf
);
1408 create_date_ts
= get_create_timespec(&sbuf
,
1409 lp_fake_dir_create_times(SNUM(conn
)));
1411 if (ask_sharemode
) {
1412 struct timespec write_time_ts
;
1413 struct file_id fileid
;
1415 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1416 get_file_infos(fileid
, NULL
, &write_time_ts
);
1417 if (!null_timespec(write_time_ts
)) {
1418 mdate_ts
= write_time_ts
;
1422 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1423 dos_filetime_timespec(&create_date_ts
);
1424 dos_filetime_timespec(&mdate_ts
);
1425 dos_filetime_timespec(&adate_ts
);
1428 create_date
= convert_timespec_to_time_t(create_date_ts
);
1429 mdate
= convert_timespec_to_time_t(mdate_ts
);
1430 adate
= convert_timespec_to_time_t(adate_ts
);
1432 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1437 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1444 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1446 switch (info_level
) {
1447 case SMB_FIND_INFO_STANDARD
:
1448 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1449 if(requires_resume_key
) {
1453 srv_put_dos_date2(p
,0,create_date
);
1454 srv_put_dos_date2(p
,4,adate
);
1455 srv_put_dos_date2(p
,8,mdate
);
1456 SIVAL(p
,12,(uint32
)file_size
);
1457 SIVAL(p
,16,(uint32
)allocation_size
);
1461 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1462 p
+= ucs2_align(base_data
, p
, 0);
1464 len
= srvstr_push(base_data
, flags2
, p
,
1465 fname
, PTR_DIFF(end_data
, p
),
1467 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1469 SCVAL(nameptr
, -1, len
- 2);
1471 SCVAL(nameptr
, -1, 0);
1475 SCVAL(nameptr
, -1, len
- 1);
1477 SCVAL(nameptr
, -1, 0);
1483 case SMB_FIND_EA_SIZE
:
1484 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1485 if(requires_resume_key
) {
1489 srv_put_dos_date2(p
,0,create_date
);
1490 srv_put_dos_date2(p
,4,adate
);
1491 srv_put_dos_date2(p
,8,mdate
);
1492 SIVAL(p
,12,(uint32
)file_size
);
1493 SIVAL(p
,16,(uint32
)allocation_size
);
1496 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1497 SIVAL(p
,22,ea_size
); /* Extended attributes */
1501 len
= srvstr_push(base_data
, flags2
,
1502 p
, fname
, PTR_DIFF(end_data
, p
),
1503 STR_TERMINATE
| STR_NOALIGN
);
1504 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1517 SCVAL(nameptr
,0,len
);
1519 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1522 case SMB_FIND_EA_LIST
:
1524 struct ea_list
*file_list
= NULL
;
1527 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1531 if(requires_resume_key
) {
1535 srv_put_dos_date2(p
,0,create_date
);
1536 srv_put_dos_date2(p
,4,adate
);
1537 srv_put_dos_date2(p
,8,mdate
);
1538 SIVAL(p
,12,(uint32
)file_size
);
1539 SIVAL(p
,16,(uint32
)allocation_size
);
1541 p
+= 22; /* p now points to the EA area. */
1543 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1544 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1546 /* We need to determine if this entry will fit in the space available. */
1547 /* Max string size is 255 bytes. */
1548 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1549 /* Move the dirptr back to prev_dirpos */
1550 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1551 *out_of_space
= True
;
1552 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1553 return False
; /* Not finished - just out of space */
1556 /* Push the ea_data followed by the name. */
1557 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1559 len
= srvstr_push(base_data
, flags2
,
1560 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1561 STR_TERMINATE
| STR_NOALIGN
);
1562 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1575 SCVAL(nameptr
,0,len
);
1577 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1581 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1582 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1583 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1585 SIVAL(p
,0,reskey
); p
+= 4;
1586 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1587 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1588 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1589 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1590 SOFF_T(p
,0,file_size
); p
+= 8;
1591 SOFF_T(p
,0,allocation_size
); p
+= 8;
1592 SIVAL(p
,0,nt_extmode
); p
+= 4;
1593 q
= p
; p
+= 4; /* q is placeholder for name length. */
1595 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1596 SIVAL(p
,0,ea_size
); /* Extended attributes */
1599 /* Clear the short name buffer. This is
1600 * IMPORTANT as not doing so will trigger
1601 * a Win2k client bug. JRA.
1603 if (!was_8_3
&& check_mangled_names
) {
1604 if (!name_to_8_3(fname
,mangled_name
,True
,
1606 /* Error - mangle failed ! */
1607 memset(mangled_name
,'\0',12);
1609 mangled_name
[12] = 0;
1610 len
= srvstr_push(base_data
, flags2
,
1611 p
+2, mangled_name
, 24,
1612 STR_UPPER
|STR_UNICODE
);
1614 memset(p
+ 2 + len
,'\0',24 - len
);
1621 len
= srvstr_push(base_data
, flags2
, p
,
1622 fname
, PTR_DIFF(end_data
, p
),
1623 STR_TERMINATE_ASCII
);
1626 SIVAL(p
,0,0); /* Ensure any padding is null. */
1627 len
= PTR_DIFF(p
, pdata
);
1628 len
= (len
+ 3) & ~3;
1633 case SMB_FIND_FILE_DIRECTORY_INFO
:
1634 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1636 SIVAL(p
,0,reskey
); p
+= 4;
1637 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1638 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1639 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1640 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1641 SOFF_T(p
,0,file_size
); p
+= 8;
1642 SOFF_T(p
,0,allocation_size
); p
+= 8;
1643 SIVAL(p
,0,nt_extmode
); p
+= 4;
1644 len
= srvstr_push(base_data
, flags2
,
1645 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1646 STR_TERMINATE_ASCII
);
1649 SIVAL(p
,0,0); /* Ensure any padding is null. */
1650 len
= PTR_DIFF(p
, pdata
);
1651 len
= (len
+ 3) & ~3;
1656 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1657 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1659 SIVAL(p
,0,reskey
); p
+= 4;
1660 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1661 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1662 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1663 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1664 SOFF_T(p
,0,file_size
); p
+= 8;
1665 SOFF_T(p
,0,allocation_size
); p
+= 8;
1666 SIVAL(p
,0,nt_extmode
); p
+= 4;
1667 q
= p
; p
+= 4; /* q is placeholder for name length. */
1669 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1670 SIVAL(p
,0,ea_size
); /* Extended attributes */
1673 len
= srvstr_push(base_data
, flags2
, p
,
1674 fname
, PTR_DIFF(end_data
, p
),
1675 STR_TERMINATE_ASCII
);
1679 SIVAL(p
,0,0); /* Ensure any padding is null. */
1680 len
= PTR_DIFF(p
, pdata
);
1681 len
= (len
+ 3) & ~3;
1686 case SMB_FIND_FILE_NAMES_INFO
:
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1689 SIVAL(p
,0,reskey
); p
+= 4;
1691 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1692 acl on a dir (tridge) */
1693 len
= srvstr_push(base_data
, flags2
, p
,
1694 fname
, PTR_DIFF(end_data
, p
),
1695 STR_TERMINATE_ASCII
);
1698 SIVAL(p
,0,0); /* Ensure any padding is null. */
1699 len
= PTR_DIFF(p
, pdata
);
1700 len
= (len
+ 3) & ~3;
1705 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1706 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1708 SIVAL(p
,0,reskey
); p
+= 4;
1709 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1710 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1711 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1712 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1713 SOFF_T(p
,0,file_size
); p
+= 8;
1714 SOFF_T(p
,0,allocation_size
); p
+= 8;
1715 SIVAL(p
,0,nt_extmode
); p
+= 4;
1716 q
= p
; p
+= 4; /* q is placeholder for name length. */
1718 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1719 SIVAL(p
,0,ea_size
); /* Extended attributes */
1722 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1723 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1724 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1725 len
= srvstr_push(base_data
, flags2
, p
,
1726 fname
, PTR_DIFF(end_data
, p
),
1727 STR_TERMINATE_ASCII
);
1730 SIVAL(p
,0,0); /* Ensure any padding is null. */
1731 len
= PTR_DIFF(p
, pdata
);
1732 len
= (len
+ 3) & ~3;
1737 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1738 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1739 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1741 SIVAL(p
,0,reskey
); p
+= 4;
1742 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1743 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1744 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1745 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1746 SOFF_T(p
,0,file_size
); p
+= 8;
1747 SOFF_T(p
,0,allocation_size
); p
+= 8;
1748 SIVAL(p
,0,nt_extmode
); p
+= 4;
1749 q
= p
; p
+= 4; /* q is placeholder for name length */
1751 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1752 SIVAL(p
,0,ea_size
); /* Extended attributes */
1755 /* Clear the short name buffer. This is
1756 * IMPORTANT as not doing so will trigger
1757 * a Win2k client bug. JRA.
1759 if (!was_8_3
&& check_mangled_names
) {
1760 if (!name_to_8_3(fname
,mangled_name
,True
,
1762 /* Error - mangle failed ! */
1763 memset(mangled_name
,'\0',12);
1765 mangled_name
[12] = 0;
1766 len
= srvstr_push(base_data
, flags2
,
1767 p
+2, mangled_name
, 24,
1768 STR_UPPER
|STR_UNICODE
);
1771 memset(p
+ 2 + len
,'\0',24 - len
);
1778 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1779 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1780 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1781 len
= srvstr_push(base_data
, flags2
, p
,
1782 fname
, PTR_DIFF(end_data
, p
),
1783 STR_TERMINATE_ASCII
);
1786 SIVAL(p
,0,0); /* Ensure any padding is null. */
1787 len
= PTR_DIFF(p
, pdata
);
1788 len
= (len
+ 3) & ~3;
1793 /* CIFS UNIX Extension. */
1795 case SMB_FIND_FILE_UNIX
:
1796 case SMB_FIND_FILE_UNIX_INFO2
:
1798 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1800 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1802 if (info_level
== SMB_FIND_FILE_UNIX
) {
1803 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1804 p
= store_file_unix_basic(conn
, p
,
1806 len
= srvstr_push(base_data
, flags2
, p
,
1807 fname
, PTR_DIFF(end_data
, p
),
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1811 p
= store_file_unix_basic_info2(conn
, p
,
1815 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1816 PTR_DIFF(end_data
, p
), 0);
1817 SIVAL(nameptr
, 0, len
);
1821 SIVAL(p
,0,0); /* Ensure any padding is null. */
1823 len
= PTR_DIFF(p
, pdata
);
1824 len
= (len
+ 3) & ~3;
1825 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1827 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1836 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1837 /* Move the dirptr back to prev_dirpos */
1838 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1839 *out_of_space
= True
;
1840 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1841 return False
; /* Not finished - just out of space */
1844 /* Setup the last entry pointer, as an offset from base_data */
1845 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1846 /* Advance the data pointer to the next slot */
1852 /****************************************************************************
1853 Reply to a TRANS2_FINDFIRST.
1854 ****************************************************************************/
1856 static void call_trans2findfirst(connection_struct
*conn
,
1857 struct smb_request
*req
,
1858 char **pparams
, int total_params
,
1859 char **ppdata
, int total_data
,
1860 unsigned int max_data_bytes
)
1862 /* We must be careful here that we don't return more than the
1863 allowed number of data bytes. If this means returning fewer than
1864 maxentries then so be it. We assume that the redirector has
1865 enough room for the fixed number of parameter bytes it has
1867 char *params
= *pparams
;
1868 char *pdata
= *ppdata
;
1872 uint16 findfirst_flags
;
1873 bool close_after_first
;
1875 bool requires_resume_key
;
1877 char *directory
= NULL
;
1880 int last_entry_off
=0;
1884 bool finished
= False
;
1885 bool dont_descend
= False
;
1886 bool out_of_space
= False
;
1887 int space_remaining
;
1888 bool mask_contains_wcard
= False
;
1889 SMB_STRUCT_STAT sbuf
;
1890 struct ea_list
*ea_list
= NULL
;
1891 NTSTATUS ntstatus
= NT_STATUS_OK
;
1892 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1893 TALLOC_CTX
*ctx
= talloc_tos();
1895 if (total_params
< 13) {
1896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1900 dirtype
= SVAL(params
,0);
1901 maxentries
= SVAL(params
,2);
1902 findfirst_flags
= SVAL(params
,4);
1903 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1904 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1905 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1906 info_level
= SVAL(params
,6);
1908 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1909 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1910 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1911 info_level
, max_data_bytes
));
1914 /* W2K3 seems to treat zero as 1. */
1918 switch (info_level
) {
1919 case SMB_FIND_INFO_STANDARD
:
1920 case SMB_FIND_EA_SIZE
:
1921 case SMB_FIND_EA_LIST
:
1922 case SMB_FIND_FILE_DIRECTORY_INFO
:
1923 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1924 case SMB_FIND_FILE_NAMES_INFO
:
1925 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1926 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1927 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1929 case SMB_FIND_FILE_UNIX
:
1930 case SMB_FIND_FILE_UNIX_INFO2
:
1931 /* Always use filesystem for UNIX mtime query. */
1932 ask_sharemode
= false;
1933 if (!lp_unix_extensions()) {
1934 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1939 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1943 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1944 params
+12, total_params
- 12,
1945 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1946 if (!NT_STATUS_IS_OK(ntstatus
)) {
1947 reply_nterror(req
, ntstatus
);
1951 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1952 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1955 &mask_contains_wcard
);
1956 if (!NT_STATUS_IS_OK(ntstatus
)) {
1957 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1958 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1959 ERRSRV
, ERRbadpath
);
1962 reply_nterror(req
, ntstatus
);
1966 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, &mask
, &sbuf
);
1967 if (!NT_STATUS_IS_OK(ntstatus
)) {
1968 reply_nterror(req
, ntstatus
);
1972 ntstatus
= check_name(conn
, directory
);
1973 if (!NT_STATUS_IS_OK(ntstatus
)) {
1974 reply_nterror(req
, ntstatus
);
1978 p
= strrchr_m(directory
,'/');
1980 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1981 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1982 mask
= talloc_strdup(ctx
,"*");
1984 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1987 mask_contains_wcard
= True
;
1989 directory
= talloc_strdup(talloc_tos(), "./");
1991 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1998 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2000 if (info_level
== SMB_FIND_EA_LIST
) {
2003 if (total_data
< 4) {
2004 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2008 ea_size
= IVAL(pdata
,0);
2009 if (ea_size
!= total_data
) {
2010 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2011 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2012 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2016 if (!lp_ea_support(SNUM(conn
))) {
2017 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2021 /* Pull out the list of names. */
2022 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2024 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2029 *ppdata
= (char *)SMB_REALLOC(
2030 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2031 if(*ppdata
== NULL
) {
2032 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2036 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2038 /* Realloc the params space */
2039 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2040 if (*pparams
== NULL
) {
2041 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2046 /* Save the wildcard match and attribs we are using on this directory -
2047 needed as lanman2 assumes these are being saved between calls */
2049 ntstatus
= dptr_create(conn
,
2055 mask_contains_wcard
,
2059 if (!NT_STATUS_IS_OK(ntstatus
)) {
2060 reply_nterror(req
, ntstatus
);
2064 dptr_num
= dptr_dnum(conn
->dirptr
);
2065 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2067 /* Initialize per TRANS2_FIND_FIRST operation data */
2068 dptr_init_search_op(conn
->dirptr
);
2070 /* We don't need to check for VOL here as this is returned by
2071 a different TRANS2 call. */
2073 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2074 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2075 dont_descend
= True
;
2078 space_remaining
= max_data_bytes
;
2079 out_of_space
= False
;
2081 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2082 bool got_exact_match
= False
;
2084 /* this is a heuristic to avoid seeking the dirptr except when
2085 absolutely necessary. It allows for a filename of about 40 chars */
2086 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2087 out_of_space
= True
;
2090 finished
= !get_lanman2_dir_entry(ctx
,
2093 mask
,dirtype
,info_level
,
2094 requires_resume_key
,dont_descend
,
2097 space_remaining
, &out_of_space
,
2099 &last_entry_off
, ea_list
);
2102 if (finished
&& out_of_space
)
2105 if (!finished
&& !out_of_space
)
2109 * As an optimisation if we know we aren't looking
2110 * for a wildcard name (ie. the name matches the wildcard exactly)
2111 * then we can finish on any (first) match.
2112 * This speeds up large directory searches. JRA.
2118 /* Ensure space_remaining never goes -ve. */
2119 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2120 space_remaining
= 0;
2121 out_of_space
= true;
2123 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2127 /* Check if we can close the dirptr */
2128 if(close_after_first
|| (finished
&& close_if_end
)) {
2129 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2130 dptr_close(&dptr_num
);
2134 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2135 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2136 * the protocol level is less than NT1. Tested with smbclient. JRA.
2137 * This should fix the OS/2 client bug #2335.
2140 if(numentries
== 0) {
2141 dptr_close(&dptr_num
);
2142 if (Protocol
< PROTOCOL_NT1
) {
2143 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2146 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2147 ERRDOS
, ERRbadfile
);
2152 /* At this point pdata points to numentries directory entries. */
2154 /* Set up the return parameter block */
2155 SSVAL(params
,0,dptr_num
);
2156 SSVAL(params
,2,numentries
);
2157 SSVAL(params
,4,finished
);
2158 SSVAL(params
,6,0); /* Never an EA error */
2159 SSVAL(params
,8,last_entry_off
);
2161 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2164 if ((! *directory
) && dptr_path(dptr_num
)) {
2165 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2167 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2171 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2172 smb_fn_name(req
->cmd
),
2173 mask
, directory
, dirtype
, numentries
) );
2176 * Force a name mangle here to ensure that the
2177 * mask as an 8.3 name is top of the mangled cache.
2178 * The reasons for this are subtle. Don't remove
2179 * this code unless you know what you are doing
2180 * (see PR#13758). JRA.
2183 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2184 char mangled_name
[13];
2185 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDNEXT.
2193 ****************************************************************************/
2195 static void call_trans2findnext(connection_struct
*conn
,
2196 struct smb_request
*req
,
2197 char **pparams
, int total_params
,
2198 char **ppdata
, int total_data
,
2199 unsigned int max_data_bytes
)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2206 char *params
= *pparams
;
2207 char *pdata
= *ppdata
;
2213 uint16 findnext_flags
;
2214 bool close_after_request
;
2216 bool requires_resume_key
;
2218 bool mask_contains_wcard
= False
;
2219 char *resume_name
= NULL
;
2220 const char *mask
= NULL
;
2221 const char *directory
= NULL
;
2225 int i
, last_entry_off
=0;
2226 bool finished
= False
;
2227 bool dont_descend
= False
;
2228 bool out_of_space
= False
;
2229 int space_remaining
;
2230 struct ea_list
*ea_list
= NULL
;
2231 NTSTATUS ntstatus
= NT_STATUS_OK
;
2232 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2233 TALLOC_CTX
*ctx
= talloc_tos();
2235 if (total_params
< 13) {
2236 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2240 dptr_num
= SVAL(params
,0);
2241 maxentries
= SVAL(params
,2);
2242 info_level
= SVAL(params
,4);
2243 resume_key
= IVAL(params
,6);
2244 findnext_flags
= SVAL(params
,10);
2245 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2246 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2247 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2248 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2250 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2252 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2253 &mask_contains_wcard
);
2254 if (!NT_STATUS_IS_OK(ntstatus
)) {
2255 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2256 complain (it thinks we're asking for the directory above the shared
2257 path or an invalid name). Catch this as the resume name is only compared, never used in
2258 a file access. JRA. */
2259 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2260 &resume_name
, params
+12,
2264 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2265 reply_nterror(req
, ntstatus
);
2270 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2271 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2272 resume_key = %d resume name = %s continue=%d level = %d\n",
2273 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2274 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2277 /* W2K3 seems to treat zero as 1. */
2281 switch (info_level
) {
2282 case SMB_FIND_INFO_STANDARD
:
2283 case SMB_FIND_EA_SIZE
:
2284 case SMB_FIND_EA_LIST
:
2285 case SMB_FIND_FILE_DIRECTORY_INFO
:
2286 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2287 case SMB_FIND_FILE_NAMES_INFO
:
2288 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2289 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2290 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2292 case SMB_FIND_FILE_UNIX
:
2293 case SMB_FIND_FILE_UNIX_INFO2
:
2294 /* Always use filesystem for UNIX mtime query. */
2295 ask_sharemode
= false;
2296 if (!lp_unix_extensions()) {
2297 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2302 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2306 if (info_level
== SMB_FIND_EA_LIST
) {
2309 if (total_data
< 4) {
2310 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2314 ea_size
= IVAL(pdata
,0);
2315 if (ea_size
!= total_data
) {
2316 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2317 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2318 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2322 if (!lp_ea_support(SNUM(conn
))) {
2323 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2327 /* Pull out the list of names. */
2328 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2330 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2335 *ppdata
= (char *)SMB_REALLOC(
2336 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2337 if(*ppdata
== NULL
) {
2338 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2343 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2345 /* Realloc the params space */
2346 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2347 if(*pparams
== NULL
) {
2348 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2354 /* Check that the dptr is valid */
2355 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2356 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2360 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2362 /* Get the wildcard mask from the dptr */
2363 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2364 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2365 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2370 directory
= conn
->dirpath
;
2372 /* Get the attr mask from the dptr */
2373 dirtype
= dptr_attr(dptr_num
);
2375 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2376 dptr_num
, mask
, dirtype
,
2378 dptr_TellDir(conn
->dirptr
)));
2380 /* Initialize per TRANS2_FIND_NEXT operation data */
2381 dptr_init_search_op(conn
->dirptr
);
2383 /* We don't need to check for VOL here as this is returned by
2384 a different TRANS2 call. */
2386 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2387 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2388 dont_descend
= True
;
2391 space_remaining
= max_data_bytes
;
2392 out_of_space
= False
;
2395 * Seek to the correct position. We no longer use the resume key but
2396 * depend on the last file name instead.
2399 if(*resume_name
&& !continue_bit
) {
2402 long current_pos
= 0;
2404 * Remember, name_to_8_3 is called by
2405 * get_lanman2_dir_entry(), so the resume name
2406 * could be mangled. Ensure we check the unmangled name.
2409 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2410 char *new_resume_name
= NULL
;
2411 mangle_lookup_name_from_8_3(ctx
,
2415 if (new_resume_name
) {
2416 resume_name
= new_resume_name
;
2421 * Fix for NT redirector problem triggered by resume key indexes
2422 * changing between directory scans. We now return a resume key of 0
2423 * and instead look for the filename to continue from (also given
2424 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2425 * findfirst/findnext (as is usual) then the directory pointer
2426 * should already be at the correct place.
2429 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2430 } /* end if resume_name && !continue_bit */
2432 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2433 bool got_exact_match
= False
;
2435 /* this is a heuristic to avoid seeking the dirptr except when
2436 absolutely necessary. It allows for a filename of about 40 chars */
2437 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2438 out_of_space
= True
;
2441 finished
= !get_lanman2_dir_entry(ctx
,
2444 mask
,dirtype
,info_level
,
2445 requires_resume_key
,dont_descend
,
2448 space_remaining
, &out_of_space
,
2450 &last_entry_off
, ea_list
);
2453 if (finished
&& out_of_space
)
2456 if (!finished
&& !out_of_space
)
2460 * As an optimisation if we know we aren't looking
2461 * for a wildcard name (ie. the name matches the wildcard exactly)
2462 * then we can finish on any (first) match.
2463 * This speeds up large directory searches. JRA.
2469 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2472 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2473 smb_fn_name(req
->cmd
),
2474 mask
, directory
, dirtype
, numentries
) );
2476 /* Check if we can close the dirptr */
2477 if(close_after_request
|| (finished
&& close_if_end
)) {
2478 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2479 dptr_close(&dptr_num
); /* This frees up the saved mask */
2482 /* Set up the return parameter block */
2483 SSVAL(params
,0,numentries
);
2484 SSVAL(params
,2,finished
);
2485 SSVAL(params
,4,0); /* Never an EA error */
2486 SSVAL(params
,6,last_entry_off
);
2488 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2494 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2496 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2500 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2502 SMB_ASSERT(extended_info
!= NULL
);
2504 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2505 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2506 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2507 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2508 #ifdef SAMBA_VERSION_REVISION
2509 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2511 extended_info
->samba_subversion
= 0;
2512 #ifdef SAMBA_VERSION_RC_RELEASE
2513 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2515 #ifdef SAMBA_VERSION_PRE_RELEASE
2516 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2519 #ifdef SAMBA_VERSION_VENDOR_PATCH
2520 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2522 extended_info
->samba_gitcommitdate
= 0;
2523 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2524 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2527 memset(extended_info
->samba_version_string
, 0,
2528 sizeof(extended_info
->samba_version_string
));
2530 snprintf (extended_info
->samba_version_string
,
2531 sizeof(extended_info
->samba_version_string
),
2532 "%s", samba_version_string());
2535 /****************************************************************************
2536 Reply to a TRANS2_QFSINFO (query filesystem info).
2537 ****************************************************************************/
2539 static void call_trans2qfsinfo(connection_struct
*conn
,
2540 struct smb_request
*req
,
2541 char **pparams
, int total_params
,
2542 char **ppdata
, int total_data
,
2543 unsigned int max_data_bytes
)
2545 char *pdata
, *end_data
;
2546 char *params
= *pparams
;
2550 const char *vname
= volume_label(SNUM(conn
));
2551 int snum
= SNUM(conn
);
2552 char *fstype
= lp_fstype(SNUM(conn
));
2553 uint32 additional_flags
= 0;
2555 if (total_params
< 2) {
2556 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2560 info_level
= SVAL(params
,0);
2563 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2564 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2565 "info level (0x%x) on IPC$.\n",
2566 (unsigned int)info_level
));
2567 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2572 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2573 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2574 DEBUG(0,("call_trans2qfsinfo: encryption required "
2575 "and info level 0x%x sent.\n",
2576 (unsigned int)info_level
));
2577 exit_server_cleanly("encryption required "
2583 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2585 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2586 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2587 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2591 *ppdata
= (char *)SMB_REALLOC(
2592 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2593 if (*ppdata
== NULL
) {
2594 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2599 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2600 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2602 switch (info_level
) {
2603 case SMB_INFO_ALLOCATION
:
2605 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2607 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2608 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2612 block_size
= lp_block_size(snum
);
2613 if (bsize
< block_size
) {
2614 uint64_t factor
= block_size
/bsize
;
2619 if (bsize
> block_size
) {
2620 uint64_t factor
= bsize
/block_size
;
2625 bytes_per_sector
= 512;
2626 sectors_per_unit
= bsize
/bytes_per_sector
;
2628 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2629 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2630 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2632 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2633 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2634 SIVAL(pdata
,l1_cUnit
,dsize
);
2635 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2636 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2640 case SMB_INFO_VOLUME
:
2641 /* Return volume name */
2643 * Add volume serial number - hash of a combination of
2644 * the called hostname and the service name.
2646 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2648 * Win2k3 and previous mess this up by sending a name length
2649 * one byte short. I believe only older clients (OS/2 Win9x) use
2650 * this call so try fixing this by adding a terminating null to
2651 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2655 pdata
+l2_vol_szVolLabel
, vname
,
2656 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2657 STR_NOALIGN
|STR_TERMINATE
);
2658 SCVAL(pdata
,l2_vol_cch
,len
);
2659 data_len
= l2_vol_szVolLabel
+ len
;
2660 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2661 (unsigned)st
.st_ctime
, len
, vname
));
2664 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2665 case SMB_FS_ATTRIBUTE_INFORMATION
:
2667 additional_flags
= 0;
2668 #if defined(HAVE_SYS_QUOTAS)
2669 additional_flags
|= FILE_VOLUME_QUOTAS
;
2672 if(lp_nt_acl_support(SNUM(conn
))) {
2673 additional_flags
|= FILE_PERSISTENT_ACLS
;
2676 /* Capabilities are filled in at connection time through STATVFS call */
2677 additional_flags
|= conn
->fs_capabilities
;
2679 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2680 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2681 additional_flags
); /* FS ATTRIBUTES */
2683 SIVAL(pdata
,4,255); /* Max filename component length */
2684 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2685 and will think we can't do long filenames */
2686 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2687 PTR_DIFF(end_data
, pdata
+12),
2690 data_len
= 12 + len
;
2693 case SMB_QUERY_FS_LABEL_INFO
:
2694 case SMB_FS_LABEL_INFORMATION
:
2695 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2696 PTR_DIFF(end_data
, pdata
+4), 0);
2701 case SMB_QUERY_FS_VOLUME_INFO
:
2702 case SMB_FS_VOLUME_INFORMATION
:
2705 * Add volume serial number - hash of a combination of
2706 * the called hostname and the service name.
2708 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2709 (str_checksum(get_local_machine_name())<<16));
2711 /* Max label len is 32 characters. */
2712 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2713 PTR_DIFF(end_data
, pdata
+18),
2715 SIVAL(pdata
,12,len
);
2718 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2719 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2722 case SMB_QUERY_FS_SIZE_INFO
:
2723 case SMB_FS_SIZE_INFORMATION
:
2725 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2727 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2728 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2731 block_size
= lp_block_size(snum
);
2732 if (bsize
< block_size
) {
2733 uint64_t factor
= block_size
/bsize
;
2738 if (bsize
> block_size
) {
2739 uint64_t factor
= bsize
/block_size
;
2744 bytes_per_sector
= 512;
2745 sectors_per_unit
= bsize
/bytes_per_sector
;
2746 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2747 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2748 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2749 SBIG_UINT(pdata
,0,dsize
);
2750 SBIG_UINT(pdata
,8,dfree
);
2751 SIVAL(pdata
,16,sectors_per_unit
);
2752 SIVAL(pdata
,20,bytes_per_sector
);
2756 case SMB_FS_FULL_SIZE_INFORMATION
:
2758 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2760 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2761 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2764 block_size
= lp_block_size(snum
);
2765 if (bsize
< block_size
) {
2766 uint64_t factor
= block_size
/bsize
;
2771 if (bsize
> block_size
) {
2772 uint64_t factor
= bsize
/block_size
;
2777 bytes_per_sector
= 512;
2778 sectors_per_unit
= bsize
/bytes_per_sector
;
2779 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2780 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2781 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2782 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2783 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2784 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2785 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2786 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2790 case SMB_QUERY_FS_DEVICE_INFO
:
2791 case SMB_FS_DEVICE_INFORMATION
:
2793 SIVAL(pdata
,0,0); /* dev type */
2794 SIVAL(pdata
,4,0); /* characteristics */
2797 #ifdef HAVE_SYS_QUOTAS
2798 case SMB_FS_QUOTA_INFORMATION
:
2800 * what we have to send --metze:
2802 * Unknown1: 24 NULL bytes
2803 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2804 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2805 * Quota Flags: 2 byte :
2806 * Unknown3: 6 NULL bytes
2810 * details for Quota Flags:
2812 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2813 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2814 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2815 * 0x0001 Enable Quotas: enable quota for this fs
2819 /* we need to fake up a fsp here,
2820 * because its not send in this call
2823 SMB_NTQUOTA_STRUCT quotas
;
2826 ZERO_STRUCT(quotas
);
2832 if (conn
->server_info
->utok
.uid
!= 0) {
2833 DEBUG(0,("set_user_quota: access_denied "
2834 "service [%s] user [%s]\n",
2835 lp_servicename(SNUM(conn
)),
2836 conn
->server_info
->unix_name
));
2837 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2841 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2842 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2843 reply_doserror(req
, ERRSRV
, ERRerror
);
2849 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2851 /* Unknown1 24 NULL bytes*/
2852 SBIG_UINT(pdata
,0,(uint64_t)0);
2853 SBIG_UINT(pdata
,8,(uint64_t)0);
2854 SBIG_UINT(pdata
,16,(uint64_t)0);
2856 /* Default Soft Quota 8 bytes */
2857 SBIG_UINT(pdata
,24,quotas
.softlim
);
2859 /* Default Hard Quota 8 bytes */
2860 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2862 /* Quota flag 2 bytes */
2863 SSVAL(pdata
,40,quotas
.qflags
);
2865 /* Unknown3 6 NULL bytes */
2871 #endif /* HAVE_SYS_QUOTAS */
2872 case SMB_FS_OBJECTID_INFORMATION
:
2874 unsigned char objid
[16];
2875 struct smb_extended_info extended_info
;
2876 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2877 samba_extended_info_version (&extended_info
);
2878 SIVAL(pdata
,16,extended_info
.samba_magic
);
2879 SIVAL(pdata
,20,extended_info
.samba_version
);
2880 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2881 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2882 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2888 * Query the version and capabilities of the CIFS UNIX extensions
2892 case SMB_QUERY_CIFS_UNIX_INFO
:
2894 bool large_write
= lp_min_receive_file_size() &&
2895 !srv_is_signing_active();
2896 bool large_read
= !srv_is_signing_active();
2897 int encrypt_caps
= 0;
2899 if (!lp_unix_extensions()) {
2900 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2904 switch (conn
->encrypt_level
) {
2910 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2913 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2914 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2915 large_write
= false;
2921 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2922 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2924 /* We have POSIX ACLs, pathname, encryption,
2925 * large read/write, and locking capability. */
2927 SBIG_UINT(pdata
,4,((uint64_t)(
2928 CIFS_UNIX_POSIX_ACLS_CAP
|
2929 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2930 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2931 CIFS_UNIX_EXTATTR_CAP
|
2932 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2934 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2936 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2940 case SMB_QUERY_POSIX_FS_INFO
:
2943 vfs_statvfs_struct svfs
;
2945 if (!lp_unix_extensions()) {
2946 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2950 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2954 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2955 SIVAL(pdata
,4,svfs
.BlockSize
);
2956 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2957 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2958 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2959 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2960 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2961 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2962 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2964 } else if (rc
== EOPNOTSUPP
) {
2965 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2967 #endif /* EOPNOTSUPP */
2969 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2970 reply_doserror(req
, ERRSRV
, ERRerror
);
2976 case SMB_QUERY_POSIX_WHOAMI
:
2982 if (!lp_unix_extensions()) {
2983 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2987 if (max_data_bytes
< 40) {
2988 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2992 /* We ARE guest if global_sid_Builtin_Guests is
2993 * in our list of SIDs.
2995 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
2996 conn
->server_info
->ptok
)) {
2997 flags
|= SMB_WHOAMI_GUEST
;
3000 /* We are NOT guest if global_sid_Authenticated_Users
3001 * is in our list of SIDs.
3003 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3004 conn
->server_info
->ptok
)) {
3005 flags
&= ~SMB_WHOAMI_GUEST
;
3008 /* NOTE: 8 bytes for UID/GID, irrespective of native
3009 * platform size. This matches
3010 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3012 data_len
= 4 /* flags */
3019 + 4 /* pad/reserved */
3020 + (conn
->server_info
->utok
.ngroups
* 8)
3022 + (conn
->server_info
->ptok
->num_sids
*
3026 SIVAL(pdata
, 0, flags
);
3027 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3029 (uint64_t)conn
->server_info
->utok
.uid
);
3030 SBIG_UINT(pdata
, 16,
3031 (uint64_t)conn
->server_info
->utok
.gid
);
3034 if (data_len
>= max_data_bytes
) {
3035 /* Potential overflow, skip the GIDs and SIDs. */
3037 SIVAL(pdata
, 24, 0); /* num_groups */
3038 SIVAL(pdata
, 28, 0); /* num_sids */
3039 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3040 SIVAL(pdata
, 36, 0); /* reserved */
3046 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3047 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3049 /* We walk the SID list twice, but this call is fairly
3050 * infrequent, and I don't expect that it's performance
3051 * sensitive -- jpeach
3053 for (i
= 0, sid_bytes
= 0;
3054 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3055 sid_bytes
+= ndr_size_dom_sid(
3056 &conn
->server_info
->ptok
->user_sids
[i
],
3061 /* SID list byte count */
3062 SIVAL(pdata
, 32, sid_bytes
);
3064 /* 4 bytes pad/reserved - must be zero */
3065 SIVAL(pdata
, 36, 0);
3069 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3070 SBIG_UINT(pdata
, data_len
,
3071 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3077 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3078 int sid_len
= ndr_size_dom_sid(
3079 &conn
->server_info
->ptok
->user_sids
[i
],
3083 sid_linearize(pdata
+ data_len
, sid_len
,
3084 &conn
->server_info
->ptok
->user_sids
[i
]);
3085 data_len
+= sid_len
;
3091 case SMB_MAC_QUERY_FS_INFO
:
3093 * Thursby MAC extension... ONLY on NTFS filesystems
3094 * once we do streams then we don't need this
3096 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3098 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3103 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3108 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3111 DEBUG( 4, ( "%s info_level = %d\n",
3112 smb_fn_name(req
->cmd
), info_level
) );
3117 /****************************************************************************
3118 Reply to a TRANS2_SETFSINFO (set filesystem info).
3119 ****************************************************************************/
3121 static void call_trans2setfsinfo(connection_struct
*conn
,
3122 struct smb_request
*req
,
3123 char **pparams
, int total_params
,
3124 char **ppdata
, int total_data
,
3125 unsigned int max_data_bytes
)
3127 char *pdata
= *ppdata
;
3128 char *params
= *pparams
;
3131 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3134 if (total_params
< 4) {
3135 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3141 info_level
= SVAL(params
,2);
3144 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3145 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3146 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3147 "info level (0x%x) on IPC$.\n",
3148 (unsigned int)info_level
));
3149 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3154 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3155 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3156 DEBUG(0,("call_trans2setfsinfo: encryption required "
3157 "and info level 0x%x sent.\n",
3158 (unsigned int)info_level
));
3159 exit_server_cleanly("encryption required "
3165 switch(info_level
) {
3166 case SMB_SET_CIFS_UNIX_INFO
:
3168 uint16 client_unix_major
;
3169 uint16 client_unix_minor
;
3170 uint32 client_unix_cap_low
;
3171 uint32 client_unix_cap_high
;
3173 if (!lp_unix_extensions()) {
3175 NT_STATUS_INVALID_LEVEL
);
3179 /* There should be 12 bytes of capabilities set. */
3180 if (total_data
< 8) {
3183 NT_STATUS_INVALID_PARAMETER
);
3186 client_unix_major
= SVAL(pdata
,0);
3187 client_unix_minor
= SVAL(pdata
,2);
3188 client_unix_cap_low
= IVAL(pdata
,4);
3189 client_unix_cap_high
= IVAL(pdata
,8);
3190 /* Just print these values for now. */
3191 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3192 cap_low = 0x%x, cap_high = 0x%x\n",
3193 (unsigned int)client_unix_major
,
3194 (unsigned int)client_unix_minor
,
3195 (unsigned int)client_unix_cap_low
,
3196 (unsigned int)client_unix_cap_high
));
3198 /* Here is where we must switch to posix pathname processing... */
3199 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3200 lp_set_posix_pathnames();
3201 mangle_change_to_posix();
3204 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3205 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3206 /* Client that knows how to do posix locks,
3207 * but not posix open/mkdir operations. Set a
3208 * default type for read/write checks. */
3210 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3216 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3219 size_t param_len
= 0;
3220 size_t data_len
= total_data
;
3222 if (!lp_unix_extensions()) {
3225 NT_STATUS_INVALID_LEVEL
);
3229 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3232 NT_STATUS_NOT_SUPPORTED
);
3236 DEBUG( 4,("call_trans2setfsinfo: "
3237 "request transport encryption.\n"));
3239 status
= srv_request_encryption_setup(conn
,
3240 (unsigned char **)ppdata
,
3242 (unsigned char **)pparams
,
3245 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3246 !NT_STATUS_IS_OK(status
)) {
3247 reply_nterror(req
, status
);
3251 send_trans2_replies(conn
, req
,
3258 if (NT_STATUS_IS_OK(status
)) {
3259 /* Server-side transport
3260 * encryption is now *on*. */
3261 status
= srv_encryption_start(conn
);
3262 if (!NT_STATUS_IS_OK(status
)) {
3263 exit_server_cleanly(
3264 "Failure in setting "
3265 "up encrypted transport");
3271 case SMB_FS_QUOTA_INFORMATION
:
3273 files_struct
*fsp
= NULL
;
3274 SMB_NTQUOTA_STRUCT quotas
;
3276 ZERO_STRUCT(quotas
);
3279 if ((conn
->server_info
->utok
.uid
!= 0)
3280 ||!CAN_WRITE(conn
)) {
3281 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3282 lp_servicename(SNUM(conn
)),
3283 conn
->server_info
->unix_name
));
3284 reply_doserror(req
, ERRSRV
, ERRaccess
);
3288 /* note: normaly there're 48 bytes,
3289 * but we didn't use the last 6 bytes for now
3292 fsp
= file_fsp(req
, SVAL(params
,0));
3294 if (!check_fsp_ntquota_handle(conn
, req
,
3296 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3298 req
, NT_STATUS_INVALID_HANDLE
);
3302 if (total_data
< 42) {
3303 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3307 NT_STATUS_INVALID_PARAMETER
);
3311 /* unknown_1 24 NULL bytes in pdata*/
3313 /* the soft quotas 8 bytes (uint64_t)*/
3314 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3315 #ifdef LARGE_SMB_OFF_T
3316 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3317 #else /* LARGE_SMB_OFF_T */
3318 if ((IVAL(pdata
,28) != 0)&&
3319 ((quotas
.softlim
!= 0xFFFFFFFF)||
3320 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3321 /* more than 32 bits? */
3324 NT_STATUS_INVALID_PARAMETER
);
3327 #endif /* LARGE_SMB_OFF_T */
3329 /* the hard quotas 8 bytes (uint64_t)*/
3330 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata
,36) != 0)&&
3335 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3336 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3340 NT_STATUS_INVALID_PARAMETER
);
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* quota_flags 2 bytes **/
3346 quotas
.qflags
= SVAL(pdata
,40);
3348 /* unknown_2 6 NULL bytes follow*/
3350 /* now set the quotas */
3351 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3352 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3353 reply_doserror(req
, ERRSRV
, ERRerror
);
3360 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3362 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3368 * sending this reply works fine,
3369 * but I'm not sure it's the same
3370 * like windows do...
3373 reply_outbuf(req
, 10, 0);
3376 #if defined(HAVE_POSIX_ACLS)
3377 /****************************************************************************
3378 Utility function to count the number of entries in a POSIX acl.
3379 ****************************************************************************/
3381 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3383 unsigned int ace_count
= 0;
3384 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3385 SMB_ACL_ENTRY_T entry
;
3387 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3389 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3390 entry_id
= SMB_ACL_NEXT_ENTRY
;
3397 /****************************************************************************
3398 Utility function to marshall a POSIX acl into wire format.
3399 ****************************************************************************/
3401 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3403 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3404 SMB_ACL_ENTRY_T entry
;
3406 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3407 SMB_ACL_TAG_T tagtype
;
3408 SMB_ACL_PERMSET_T permset
;
3409 unsigned char perms
= 0;
3410 unsigned int own_grp
;
3413 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3414 entry_id
= SMB_ACL_NEXT_ENTRY
;
3417 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3418 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3422 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3423 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3427 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3428 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3429 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3431 SCVAL(pdata
,1,perms
);
3434 case SMB_ACL_USER_OBJ
:
3435 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3436 own_grp
= (unsigned int)pst
->st_uid
;
3437 SIVAL(pdata
,2,own_grp
);
3442 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3444 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3447 own_grp
= (unsigned int)*puid
;
3448 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3449 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3450 SIVAL(pdata
,2,own_grp
);
3454 case SMB_ACL_GROUP_OBJ
:
3455 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3456 own_grp
= (unsigned int)pst
->st_gid
;
3457 SIVAL(pdata
,2,own_grp
);
3462 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3464 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3467 own_grp
= (unsigned int)*pgid
;
3468 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3469 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3470 SIVAL(pdata
,2,own_grp
);
3475 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3476 SIVAL(pdata
,2,0xFFFFFFFF);
3477 SIVAL(pdata
,6,0xFFFFFFFF);
3480 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3481 SIVAL(pdata
,2,0xFFFFFFFF);
3482 SIVAL(pdata
,6,0xFFFFFFFF);
3485 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3488 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3495 /****************************************************************************
3496 Store the FILE_UNIX_BASIC info.
3497 ****************************************************************************/
3499 static char *store_file_unix_basic(connection_struct
*conn
,
3502 const SMB_STRUCT_STAT
*psbuf
)
3504 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3505 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3507 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3510 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3513 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3514 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3515 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3518 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3522 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3526 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3529 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3533 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3537 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3540 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3544 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3551 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3552 * the chflags(2) (or equivalent) flags.
3554 * XXX: this really should be behind the VFS interface. To do this, we would
3555 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3556 * Each VFS module could then implement its own mapping as appropriate for the
3557 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3559 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3563 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3567 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3571 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3575 { UF_HIDDEN
, EXT_HIDDEN
},
3578 /* Do not remove. We need to guarantee that this array has at least one
3579 * entry to build on HP-UX.
3585 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3586 uint32
*smb_fflags
, uint32
*smb_fmask
)
3588 #ifdef HAVE_STAT_ST_FLAGS
3591 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3592 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3593 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3594 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3597 #endif /* HAVE_STAT_ST_FLAGS */
3600 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3601 const uint32 smb_fflags
,
3602 const uint32 smb_fmask
,
3605 #ifdef HAVE_STAT_ST_FLAGS
3606 uint32 max_fmask
= 0;
3609 *stat_fflags
= psbuf
->st_flags
;
3611 /* For each flags requested in smb_fmask, check the state of the
3612 * corresponding flag in smb_fflags and set or clear the matching
3616 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3617 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3618 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3619 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3620 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3622 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3627 /* If smb_fmask is asking to set any bits that are not supported by
3628 * our flag mappings, we should fail.
3630 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3637 #endif /* HAVE_STAT_ST_FLAGS */
3641 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3642 * of file flags and birth (create) time.
3644 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3647 const SMB_STRUCT_STAT
*psbuf
)
3649 uint32 file_flags
= 0;
3650 uint32 flags_mask
= 0;
3652 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3654 /* Create (birth) time 64 bit */
3655 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3658 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3659 SIVAL(pdata
, 0, file_flags
); /* flags */
3660 SIVAL(pdata
, 4, flags_mask
); /* mask */
3666 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3667 const struct stream_struct
*streams
,
3669 unsigned int max_data_bytes
,
3670 unsigned int *data_size
)
3673 unsigned int ofs
= 0;
3675 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3676 unsigned int next_offset
;
3678 smb_ucs2_t
*namebuf
;
3680 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3681 streams
[i
].name
, &namelen
) ||
3684 return NT_STATUS_INVALID_PARAMETER
;
3688 * name_buf is now null-terminated, we need to marshall as not
3694 SIVAL(data
, ofs
+4, namelen
);
3695 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3696 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3697 memcpy(data
+ofs
+24, namebuf
, namelen
);
3698 TALLOC_FREE(namebuf
);
3700 next_offset
= ofs
+ 24 + namelen
;
3702 if (i
== num_streams
-1) {
3703 SIVAL(data
, ofs
, 0);
3706 unsigned int align
= ndr_align_size(next_offset
, 8);
3708 memset(data
+next_offset
, 0, align
);
3709 next_offset
+= align
;
3711 SIVAL(data
, ofs
, next_offset
- ofs
);
3720 return NT_STATUS_OK
;
3723 /****************************************************************************
3724 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3725 ****************************************************************************/
3727 static void call_trans2qpipeinfo(connection_struct
*conn
,
3728 struct smb_request
*req
,
3729 unsigned int tran_call
,
3730 char **pparams
, int total_params
,
3731 char **ppdata
, int total_data
,
3732 unsigned int max_data_bytes
)
3734 char *params
= *pparams
;
3735 char *pdata
= *ppdata
;
3736 unsigned int data_size
= 0;
3737 unsigned int param_size
= 2;
3742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3746 if (total_params
< 4) {
3747 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3751 fsp
= file_fsp(req
, SVAL(params
,0));
3752 if (!fsp_is_np(fsp
)) {
3753 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3757 info_level
= SVAL(params
,2);
3759 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3760 if (*pparams
== NULL
) {
3761 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3766 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3767 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3768 if (*ppdata
== NULL
) {
3769 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3774 switch (info_level
) {
3775 case SMB_FILE_STANDARD_INFORMATION
:
3777 SOFF_T(pdata
,0,4096LL);
3784 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3788 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3794 /****************************************************************************
3795 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3796 file name or file id).
3797 ****************************************************************************/
3799 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3800 struct smb_request
*req
,
3801 unsigned int tran_call
,
3802 char **pparams
, int total_params
,
3803 char **ppdata
, int total_data
,
3804 unsigned int max_data_bytes
)
3806 char *params
= *pparams
;
3807 char *pdata
= *ppdata
;
3808 char *dstart
, *dend
;
3812 SMB_OFF_T file_size
=0;
3813 uint64_t allocation_size
=0;
3814 unsigned int data_size
= 0;
3815 unsigned int param_size
= 2;
3816 SMB_STRUCT_STAT sbuf
;
3817 char *dos_fname
= NULL
;
3823 bool delete_pending
= False
;
3825 time_t create_time
, mtime
, atime
;
3826 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3827 struct timespec write_time_ts
;
3828 files_struct
*fsp
= NULL
;
3829 struct file_id fileid
;
3830 struct ea_list
*ea_list
= NULL
;
3831 char *lock_data
= NULL
;
3832 bool ms_dfs_link
= false;
3833 TALLOC_CTX
*ctx
= talloc_tos();
3836 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3841 ZERO_STRUCT(write_time_ts
);
3843 if (tran_call
== TRANSACT2_QFILEINFO
) {
3844 if (total_params
< 4) {
3845 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3850 call_trans2qpipeinfo(conn
, req
, tran_call
,
3851 pparams
, total_params
,
3857 fsp
= file_fsp(req
, SVAL(params
,0));
3858 info_level
= SVAL(params
,2);
3860 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3862 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3863 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3867 /* Initial check for valid fsp ptr. */
3868 if (!check_fsp_open(conn
, req
, fsp
)) {
3872 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3874 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3878 if(fsp
->fake_file_handle
) {
3880 * This is actually for the QUOTA_FAKE_FILE --metze
3883 /* We know this name is ok, it's already passed the checks. */
3885 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3887 * This is actually a QFILEINFO on a directory
3888 * handle (returned from an NT SMB). NT5.0 seems
3889 * to do this call. JRA.
3892 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3893 /* Always do lstat for UNIX calls. */
3894 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3895 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3896 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3899 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3900 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3901 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3905 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3906 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3909 * Original code - this is an open file.
3911 if (!check_fsp(conn
, req
, fsp
)) {
3915 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3916 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3917 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3920 pos
= fsp
->fh
->position_information
;
3921 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3922 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3926 NTSTATUS status
= NT_STATUS_OK
;
3929 if (total_params
< 7) {
3930 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3934 info_level
= SVAL(params
,0);
3936 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3938 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3939 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3943 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3945 STR_TERMINATE
, &status
);
3946 if (!NT_STATUS_IS_OK(status
)) {
3947 reply_nterror(req
, status
);
3951 status
= resolve_dfspath(ctx
,
3953 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3956 if (!NT_STATUS_IS_OK(status
)) {
3957 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3958 reply_botherror(req
,
3959 NT_STATUS_PATH_NOT_COVERED
,
3960 ERRSRV
, ERRbadpath
);
3962 reply_nterror(req
, status
);
3966 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3967 if (!NT_STATUS_IS_OK(status
)) {
3968 reply_nterror(req
, status
);
3971 status
= check_name(conn
, fname
);
3972 if (!NT_STATUS_IS_OK(status
)) {
3973 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3974 reply_nterror(req
, status
);
3978 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
3979 && is_ntfs_stream_name(fname
)) {
3981 SMB_STRUCT_STAT bsbuf
;
3983 status
= split_ntfs_stream_name(talloc_tos(), fname
,
3985 if (!NT_STATUS_IS_OK(status
)) {
3986 DEBUG(10, ("create_file_unixpath: "
3987 "split_ntfs_stream_name failed: %s\n",
3988 nt_errstr(status
)));
3989 reply_nterror(req
, status
);
3993 SMB_ASSERT(!is_ntfs_stream_name(base
)); /* paranoia.. */
3995 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3996 /* Always do lstat for UNIX calls. */
3997 if (SMB_VFS_LSTAT(conn
,base
,&bsbuf
)) {
3998 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base
,strerror(errno
)));
3999 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4003 if (SMB_VFS_STAT(conn
,base
,&bsbuf
) != 0) {
4004 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base
,strerror(errno
)));
4005 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4010 fileid
= vfs_file_id_from_sbuf(conn
, &bsbuf
);
4011 get_file_infos(fileid
, &delete_pending
, NULL
);
4012 if (delete_pending
) {
4013 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4018 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4019 /* Always do lstat for UNIX calls. */
4020 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4021 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4022 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4026 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4027 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4030 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4031 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4036 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4037 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4038 if (delete_pending
) {
4039 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4044 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4045 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4049 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4050 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4052 p
= strrchr_m(fname
,'/');
4059 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4061 mode
= dos_mode(conn
,fname
,&sbuf
);
4064 mode
= FILE_ATTRIBUTE_NORMAL
;
4066 nlink
= sbuf
.st_nlink
;
4068 if (nlink
&& (mode
&aDIR
)) {
4072 if ((nlink
> 0) && delete_pending
) {
4076 fullpathname
= fname
;
4078 file_size
= get_file_size_stat(&sbuf
);
4080 /* Pull out any data sent here before we realloc. */
4081 switch (info_level
) {
4082 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4084 /* Pull any EA list from the data portion. */
4087 if (total_data
< 4) {
4089 req
, NT_STATUS_INVALID_PARAMETER
);
4092 ea_size
= IVAL(pdata
,0);
4094 if (total_data
> 0 && ea_size
!= total_data
) {
4095 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4096 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4098 req
, NT_STATUS_INVALID_PARAMETER
);
4102 if (!lp_ea_support(SNUM(conn
))) {
4103 reply_doserror(req
, ERRDOS
,
4104 ERReasnotsupported
);
4108 /* Pull out the list of names. */
4109 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4112 req
, NT_STATUS_INVALID_PARAMETER
);
4118 case SMB_QUERY_POSIX_LOCK
:
4120 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4121 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4125 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4127 req
, NT_STATUS_INVALID_PARAMETER
);
4131 /* Copy the lock range data. */
4132 lock_data
= (char *)TALLOC_MEMDUP(
4133 ctx
, pdata
, total_data
);
4135 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4143 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4144 if (*pparams
== NULL
) {
4145 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4150 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4151 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4152 if (*ppdata
== NULL
) {
4153 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4158 dend
= dstart
+ data_size
- 1;
4160 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4161 mtime_ts
= get_mtimespec(&sbuf
);
4162 atime_ts
= get_atimespec(&sbuf
);
4164 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,&sbuf
);
4167 /* Do we have this path open ? */
4169 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4170 fsp1
= file_find_di_first(fileid
);
4171 if (fsp1
&& fsp1
->initial_allocation_size
) {
4172 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, &sbuf
);
4176 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4177 mtime_ts
= write_time_ts
;
4180 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4181 dos_filetime_timespec(&create_time_ts
);
4182 dos_filetime_timespec(&mtime_ts
);
4183 dos_filetime_timespec(&atime_ts
);
4186 create_time
= convert_timespec_to_time_t(create_time_ts
);
4187 mtime
= convert_timespec_to_time_t(mtime_ts
);
4188 atime
= convert_timespec_to_time_t(atime_ts
);
4190 /* NT expects the name to be in an exact form of the *full*
4191 filename. See the trans2 torture test */
4192 if (ISDOT(base_name
)) {
4193 dos_fname
= talloc_strdup(ctx
, "\\");
4195 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4199 dos_fname
= talloc_asprintf(ctx
,
4203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4206 string_replace(dos_fname
, '/', '\\');
4209 switch (info_level
) {
4210 case SMB_INFO_STANDARD
:
4211 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4213 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4214 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4215 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4216 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4217 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4218 SSVAL(pdata
,l1_attrFile
,mode
);
4221 case SMB_INFO_QUERY_EA_SIZE
:
4223 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4224 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4226 srv_put_dos_date2(pdata
,0,create_time
);
4227 srv_put_dos_date2(pdata
,4,atime
);
4228 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4229 SIVAL(pdata
,12,(uint32
)file_size
);
4230 SIVAL(pdata
,16,(uint32
)allocation_size
);
4231 SSVAL(pdata
,20,mode
);
4232 SIVAL(pdata
,22,ea_size
);
4236 case SMB_INFO_IS_NAME_VALID
:
4237 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4238 if (tran_call
== TRANSACT2_QFILEINFO
) {
4239 /* os/2 needs this ? really ?*/
4240 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4247 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4249 size_t total_ea_len
= 0;
4250 struct ea_list
*ea_file_list
= NULL
;
4252 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4254 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4255 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4257 if (!ea_list
|| (total_ea_len
> data_size
)) {
4259 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4263 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4267 case SMB_INFO_QUERY_ALL_EAS
:
4269 /* We have data_size bytes to put EA's into. */
4270 size_t total_ea_len
= 0;
4272 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4274 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4275 if (!ea_list
|| (total_ea_len
> data_size
)) {
4277 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4281 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4285 case SMB_FILE_BASIC_INFORMATION
:
4286 case SMB_QUERY_FILE_BASIC_INFO
:
4288 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4289 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4290 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4292 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4296 put_long_date_timespec(pdata
,create_time_ts
);
4297 put_long_date_timespec(pdata
+8,atime_ts
);
4298 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4299 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4300 SIVAL(pdata
,32,mode
);
4302 DEBUG(5,("SMB_QFBI - "));
4303 DEBUG(5,("create: %s ", ctime(&create_time
)));
4304 DEBUG(5,("access: %s ", ctime(&atime
)));
4305 DEBUG(5,("write: %s ", ctime(&mtime
)));
4306 DEBUG(5,("change: %s ", ctime(&mtime
)));
4307 DEBUG(5,("mode: %x\n", mode
));
4310 case SMB_FILE_STANDARD_INFORMATION
:
4311 case SMB_QUERY_FILE_STANDARD_INFO
:
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4315 SOFF_T(pdata
,0,allocation_size
);
4316 SOFF_T(pdata
,8,file_size
);
4317 SIVAL(pdata
,16,nlink
);
4318 SCVAL(pdata
,20,delete_pending
?1:0);
4319 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4320 SSVAL(pdata
,22,0); /* Padding. */
4323 case SMB_FILE_EA_INFORMATION
:
4324 case SMB_QUERY_FILE_EA_INFO
:
4326 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4327 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4329 SIVAL(pdata
,0,ea_size
);
4333 /* Get the 8.3 name - used if NT SMB was negotiated. */
4334 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4335 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4337 char mangled_name
[13];
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4339 if (!name_to_8_3(base_name
,mangled_name
,
4340 True
,conn
->params
)) {
4343 NT_STATUS_NO_MEMORY
);
4345 len
= srvstr_push(dstart
, req
->flags2
,
4346 pdata
+4, mangled_name
,
4347 PTR_DIFF(dend
, pdata
+4),
4349 data_size
= 4 + len
;
4354 case SMB_QUERY_FILE_NAME_INFO
:
4356 this must be *exactly* right for ACLs on mapped drives to work
4358 len
= srvstr_push(dstart
, req
->flags2
,
4360 PTR_DIFF(dend
, pdata
+4),
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4363 data_size
= 4 + len
;
4367 case SMB_FILE_ALLOCATION_INFORMATION
:
4368 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4371 SOFF_T(pdata
,0,allocation_size
);
4374 case SMB_FILE_END_OF_FILE_INFORMATION
:
4375 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4378 SOFF_T(pdata
,0,file_size
);
4381 case SMB_QUERY_FILE_ALL_INFO
:
4382 case SMB_FILE_ALL_INFORMATION
:
4384 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4386 put_long_date_timespec(pdata
,create_time_ts
);
4387 put_long_date_timespec(pdata
+8,atime_ts
);
4388 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4389 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4390 SIVAL(pdata
,32,mode
);
4391 SIVAL(pdata
,36,0); /* padding. */
4393 SOFF_T(pdata
,0,allocation_size
);
4394 SOFF_T(pdata
,8,file_size
);
4395 SIVAL(pdata
,16,nlink
);
4396 SCVAL(pdata
,20,delete_pending
);
4397 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4400 SIVAL(pdata
,0,ea_size
);
4401 pdata
+= 4; /* EA info */
4402 len
= srvstr_push(dstart
, req
->flags2
,
4404 PTR_DIFF(dend
, pdata
+4),
4408 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4411 case SMB_FILE_INTERNAL_INFORMATION
:
4412 /* This should be an index number - looks like
4415 I think this causes us to fail the IFSKIT
4416 BasicFileInformationTest. -tpot */
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4419 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4420 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4424 case SMB_FILE_ACCESS_INFORMATION
:
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4427 SIVAL(pdata
,0,fsp
->access_mask
);
4429 /* GENERIC_EXECUTE mapping from Windows */
4430 SIVAL(pdata
,0,0x12019F);
4435 case SMB_FILE_NAME_INFORMATION
:
4436 /* Pathname with leading '\'. */
4439 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4441 SIVAL(pdata
,0,byte_len
);
4442 data_size
= 4 + byte_len
;
4446 case SMB_FILE_DISPOSITION_INFORMATION
:
4447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4449 SCVAL(pdata
,0,delete_pending
);
4452 case SMB_FILE_POSITION_INFORMATION
:
4453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4455 SOFF_T(pdata
,0,pos
);
4458 case SMB_FILE_MODE_INFORMATION
:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4460 SIVAL(pdata
,0,mode
);
4464 case SMB_FILE_ALIGNMENT_INFORMATION
:
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4466 SIVAL(pdata
,0,0); /* No alignment needed. */
4471 * NT4 server just returns "invalid query" to this - if we try
4472 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4475 /* The first statement above is false - verified using Thursby
4476 * client against NT4 -- gcolley.
4478 case SMB_QUERY_FILE_STREAM_INFO
:
4479 case SMB_FILE_STREAM_INFORMATION
: {
4480 unsigned int num_streams
;
4481 struct stream_struct
*streams
;
4484 DEBUG(10,("call_trans2qfilepathinfo: "
4485 "SMB_FILE_STREAM_INFORMATION\n"));
4487 status
= SMB_VFS_STREAMINFO(
4488 conn
, fsp
, fname
, talloc_tos(),
4489 &num_streams
, &streams
);
4491 if (!NT_STATUS_IS_OK(status
)) {
4492 DEBUG(10, ("could not get stream info: %s\n",
4493 nt_errstr(status
)));
4494 reply_nterror(req
, status
);
4498 status
= marshall_stream_info(num_streams
, streams
,
4499 pdata
, max_data_bytes
,
4502 if (!NT_STATUS_IS_OK(status
)) {
4503 DEBUG(10, ("marshall_stream_info failed: %s\n",
4504 nt_errstr(status
)));
4505 reply_nterror(req
, status
);
4509 TALLOC_FREE(streams
);
4513 case SMB_QUERY_COMPRESSION_INFO
:
4514 case SMB_FILE_COMPRESSION_INFORMATION
:
4515 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4516 SOFF_T(pdata
,0,file_size
);
4517 SIVAL(pdata
,8,0); /* ??? */
4518 SIVAL(pdata
,12,0); /* ??? */
4522 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4523 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4524 put_long_date_timespec(pdata
,create_time_ts
);
4525 put_long_date_timespec(pdata
+8,atime_ts
);
4526 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4527 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4528 SOFF_T(pdata
,32,allocation_size
);
4529 SOFF_T(pdata
,40,file_size
);
4530 SIVAL(pdata
,48,mode
);
4531 SIVAL(pdata
,52,0); /* ??? */
4535 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4536 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4537 SIVAL(pdata
,0,mode
);
4543 * CIFS UNIX Extensions.
4546 case SMB_QUERY_FILE_UNIX_BASIC
:
4548 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4549 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4553 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4555 for (i
=0; i
<100; i
++)
4556 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4562 case SMB_QUERY_FILE_UNIX_INFO2
:
4564 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4565 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4569 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4571 for (i
=0; i
<100; i
++)
4572 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4578 case SMB_QUERY_FILE_UNIX_LINK
:
4580 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4583 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4589 if(!S_ISLNK(sbuf
.st_mode
)) {
4590 reply_unixerror(req
, ERRSRV
,
4595 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4598 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4601 reply_unixerror(req
, ERRDOS
,
4606 len
= srvstr_push(dstart
, req
->flags2
,
4608 PTR_DIFF(dend
, pdata
),
4611 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4616 #if defined(HAVE_POSIX_ACLS)
4617 case SMB_QUERY_POSIX_ACL
:
4619 SMB_ACL_T file_acl
= NULL
;
4620 SMB_ACL_T def_acl
= NULL
;
4621 uint16 num_file_acls
= 0;
4622 uint16 num_def_acls
= 0;
4624 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4625 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4627 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4630 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4631 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4635 NT_STATUS_NOT_IMPLEMENTED
);
4639 if (S_ISDIR(sbuf
.st_mode
)) {
4640 if (fsp
&& fsp
->is_directory
) {
4641 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4643 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4645 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4648 num_file_acls
= count_acl_entries(conn
, file_acl
);
4649 num_def_acls
= count_acl_entries(conn
, def_acl
);
4651 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4652 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4654 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4655 SMB_POSIX_ACL_HEADER_SIZE
) ));
4657 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4660 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4664 NT_STATUS_BUFFER_TOO_SMALL
);
4668 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4669 SSVAL(pdata
,2,num_file_acls
);
4670 SSVAL(pdata
,4,num_def_acls
);
4671 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4679 req
, NT_STATUS_INTERNAL_ERROR
);
4682 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4691 NT_STATUS_INTERNAL_ERROR
);
4696 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4701 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4707 case SMB_QUERY_POSIX_LOCK
:
4709 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4713 enum brl_type lock_type
;
4715 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4717 req
, NT_STATUS_INVALID_PARAMETER
);
4721 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4722 case POSIX_LOCK_TYPE_READ
:
4723 lock_type
= READ_LOCK
;
4725 case POSIX_LOCK_TYPE_WRITE
:
4726 lock_type
= WRITE_LOCK
;
4728 case POSIX_LOCK_TYPE_UNLOCK
:
4730 /* There's no point in asking for an unlock... */
4733 NT_STATUS_INVALID_PARAMETER
);
4737 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4738 #if defined(HAVE_LONGLONG)
4739 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4740 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4741 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4742 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4743 #else /* HAVE_LONGLONG */
4744 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4745 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4746 #endif /* HAVE_LONGLONG */
4748 status
= query_lock(fsp
,
4755 if (ERROR_WAS_LOCK_DENIED(status
)) {
4756 /* Here we need to report who has it locked... */
4757 data_size
= POSIX_LOCK_DATA_SIZE
;
4759 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4760 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4761 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4762 #if defined(HAVE_LONGLONG)
4763 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4764 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4765 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4766 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4767 #else /* HAVE_LONGLONG */
4768 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4769 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4770 #endif /* HAVE_LONGLONG */
4772 } else if (NT_STATUS_IS_OK(status
)) {
4773 /* For success we just return a copy of what we sent
4774 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4775 data_size
= POSIX_LOCK_DATA_SIZE
;
4776 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4777 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4779 reply_nterror(req
, status
);
4786 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4790 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4796 /****************************************************************************
4797 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4799 ****************************************************************************/
4801 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4802 connection_struct
*conn
,
4803 const char *oldname_in
,
4804 const char *newname_in
)
4806 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4807 char *last_component_oldname
= NULL
;
4808 char *last_component_newname
= NULL
;
4809 char *oldname
= NULL
;
4810 char *newname
= NULL
;
4811 NTSTATUS status
= NT_STATUS_OK
;
4816 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4817 &last_component_oldname
, &sbuf1
);
4818 if (!NT_STATUS_IS_OK(status
)) {
4822 status
= check_name(conn
, oldname
);
4823 if (!NT_STATUS_IS_OK(status
)) {
4827 /* source must already exist. */
4828 if (!VALID_STAT(sbuf1
)) {
4829 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4832 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4833 &last_component_newname
, &sbuf2
);
4834 if (!NT_STATUS_IS_OK(status
)) {
4838 status
= check_name(conn
, newname
);
4839 if (!NT_STATUS_IS_OK(status
)) {
4843 /* Disallow if newname already exists. */
4844 if (VALID_STAT(sbuf2
)) {
4845 return NT_STATUS_OBJECT_NAME_COLLISION
;
4848 /* No links from a directory. */
4849 if (S_ISDIR(sbuf1
.st_mode
)) {
4850 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4853 /* Ensure this is within the share. */
4854 status
= check_reduced_name(conn
, oldname
);
4855 if (!NT_STATUS_IS_OK(status
)) {
4859 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4861 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4862 status
= map_nt_error_from_unix(errno
);
4863 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4864 nt_errstr(status
), newname
, oldname
));
4870 /****************************************************************************
4871 Deal with setting the time from any of the setfilepathinfo functions.
4872 ****************************************************************************/
4874 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4877 const SMB_STRUCT_STAT
*psbuf
,
4878 struct smb_file_time
*ft
,
4879 bool setting_write_time
)
4882 FILE_NOTIFY_CHANGE_LAST_ACCESS
4883 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4885 if (!VALID_STAT(*psbuf
)) {
4886 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4889 /* get some defaults (no modifications) if any info is zero or -1. */
4890 if (null_timespec(ft
->atime
)) {
4891 ft
->atime
= get_atimespec(psbuf
);
4892 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4895 if (null_timespec(ft
->mtime
)) {
4896 ft
->mtime
= get_mtimespec(psbuf
);
4897 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4900 if (!setting_write_time
) {
4901 /* ft->mtime comes from change time, not write time. */
4902 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4905 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4906 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
4907 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4908 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
4909 if (!null_timespec(ft
->create_time
)) {
4910 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4911 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
4915 * Try and set the times of this file if
4916 * they are different from the current values.
4920 struct timespec mts
= get_mtimespec(psbuf
);
4921 struct timespec ats
= get_atimespec(psbuf
);
4922 if ((timespec_compare(&ft
->atime
, &ats
) == 0) &&
4923 (timespec_compare(&ft
->mtime
, &mts
) == 0)) {
4924 return NT_STATUS_OK
;
4928 if (setting_write_time
) {
4930 * This was a setfileinfo on an open file.
4931 * NT does this a lot. We also need to
4932 * set the time here, as it can be read by
4933 * FindFirst/FindNext and with the patch for bug #2045
4934 * in smbd/fileio.c it ensures that this timestamp is
4935 * kept sticky even after a write. We save the request
4936 * away and will set it on file close and after a write. JRA.
4939 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4940 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
4943 if (fsp
->base_fsp
) {
4944 set_sticky_write_time_fsp(fsp
->base_fsp
,
4947 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
4950 set_sticky_write_time_path(conn
, fname
,
4951 vfs_file_id_from_sbuf(conn
, psbuf
),
4956 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4958 if (fsp
&& fsp
->base_fsp
) {
4959 fname
= fsp
->base_fsp
->fsp_name
;
4962 if(file_ntimes(conn
, fname
, ft
)!=0) {
4963 return map_nt_error_from_unix(errno
);
4965 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4967 return NT_STATUS_OK
;
4970 /****************************************************************************
4971 Deal with setting the dosmode from any of the setfilepathinfo functions.
4972 ****************************************************************************/
4974 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4977 SMB_STRUCT_STAT
*psbuf
,
4980 if (!VALID_STAT(*psbuf
)) {
4981 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4985 if (fsp
->base_fsp
) {
4986 fname
= fsp
->base_fsp
->fsp_name
;
4988 fname
= fsp
->fsp_name
;
4993 if (S_ISDIR(psbuf
->st_mode
)) {
5000 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5002 /* check the mode isn't different, before changing it */
5003 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
5005 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5006 fname
, (unsigned int)dosmode
));
5008 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
5009 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5010 fname
, strerror(errno
)));
5011 return map_nt_error_from_unix(errno
);
5014 return NT_STATUS_OK
;
5017 /****************************************************************************
5018 Deal with setting the size from any of the setfilepathinfo functions.
5019 ****************************************************************************/
5021 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5022 struct smb_request
*req
,
5025 SMB_STRUCT_STAT
*psbuf
,
5028 NTSTATUS status
= NT_STATUS_OK
;
5029 files_struct
*new_fsp
= NULL
;
5031 if (!VALID_STAT(*psbuf
)) {
5032 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5035 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5037 if (size
== get_file_size_stat(psbuf
)) {
5038 return NT_STATUS_OK
;
5041 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5042 fname
, (double)size
));
5044 if (fsp
&& fsp
->fh
->fd
!= -1) {
5045 /* Handle based call. */
5046 if (vfs_set_filelen(fsp
, size
) == -1) {
5047 return map_nt_error_from_unix(errno
);
5049 trigger_write_time_update_immediate(fsp
);
5050 return NT_STATUS_OK
;
5053 status
= SMB_VFS_CREATE_FILE(
5056 0, /* root_dir_fid */
5058 0, /* create_file_flags */
5059 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5060 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5062 FILE_OPEN
, /* create_disposition*/
5063 0, /* create_options */
5064 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5065 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5066 0, /* allocation_size */
5069 &new_fsp
, /* result */
5073 if (!NT_STATUS_IS_OK(status
)) {
5074 /* NB. We check for open_was_deferred in the caller. */
5078 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5079 status
= map_nt_error_from_unix(errno
);
5080 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5084 trigger_write_time_update_immediate(new_fsp
);
5085 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5086 return NT_STATUS_OK
;
5089 /****************************************************************************
5090 Deal with SMB_INFO_SET_EA.
5091 ****************************************************************************/
5093 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5099 struct ea_list
*ea_list
= NULL
;
5100 TALLOC_CTX
*ctx
= NULL
;
5101 NTSTATUS status
= NT_STATUS_OK
;
5103 if (total_data
< 10) {
5105 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5106 length. They seem to have no effect. Bug #3212. JRA */
5108 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5109 /* We're done. We only get EA info in this call. */
5110 return NT_STATUS_OK
;
5113 return NT_STATUS_INVALID_PARAMETER
;
5116 if (IVAL(pdata
,0) > total_data
) {
5117 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5118 IVAL(pdata
,0), (unsigned int)total_data
));
5119 return NT_STATUS_INVALID_PARAMETER
;
5123 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5125 return NT_STATUS_INVALID_PARAMETER
;
5127 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5132 /****************************************************************************
5133 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5134 ****************************************************************************/
5136 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5141 SMB_STRUCT_STAT
*psbuf
)
5143 NTSTATUS status
= NT_STATUS_OK
;
5144 bool delete_on_close
;
5147 if (total_data
< 1) {
5148 return NT_STATUS_INVALID_PARAMETER
;
5152 return NT_STATUS_INVALID_HANDLE
;
5155 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5156 dosmode
= dos_mode(conn
, fname
, psbuf
);
5158 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5159 "delete_on_close = %u\n",
5161 (unsigned int)dosmode
,
5162 (unsigned int)delete_on_close
));
5164 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5166 if (!NT_STATUS_IS_OK(status
)) {
5170 /* The set is across all open files on this dev/inode pair. */
5171 if (!set_delete_on_close(fsp
, delete_on_close
,
5172 &conn
->server_info
->utok
)) {
5173 return NT_STATUS_ACCESS_DENIED
;
5175 return NT_STATUS_OK
;
5178 /****************************************************************************
5179 Deal with SMB_FILE_POSITION_INFORMATION.
5180 ****************************************************************************/
5182 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5187 uint64_t position_information
;
5189 if (total_data
< 8) {
5190 return NT_STATUS_INVALID_PARAMETER
;
5194 /* Ignore on pathname based set. */
5195 return NT_STATUS_OK
;
5198 position_information
= (uint64_t)IVAL(pdata
,0);
5199 #ifdef LARGE_SMB_OFF_T
5200 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5201 #else /* LARGE_SMB_OFF_T */
5202 if (IVAL(pdata
,4) != 0) {
5203 /* more than 32 bits? */
5204 return NT_STATUS_INVALID_PARAMETER
;
5206 #endif /* LARGE_SMB_OFF_T */
5208 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5209 fsp
->fsp_name
, (double)position_information
));
5210 fsp
->fh
->position_information
= position_information
;
5211 return NT_STATUS_OK
;
5214 /****************************************************************************
5215 Deal with SMB_FILE_MODE_INFORMATION.
5216 ****************************************************************************/
5218 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5224 if (total_data
< 4) {
5225 return NT_STATUS_INVALID_PARAMETER
;
5227 mode
= IVAL(pdata
,0);
5228 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5229 return NT_STATUS_INVALID_PARAMETER
;
5231 return NT_STATUS_OK
;
5234 /****************************************************************************
5235 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5236 ****************************************************************************/
5238 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5239 struct smb_request
*req
,
5244 char *link_target
= NULL
;
5245 const char *newname
= fname
;
5246 NTSTATUS status
= NT_STATUS_OK
;
5247 TALLOC_CTX
*ctx
= talloc_tos();
5249 /* Set a symbolic link. */
5250 /* Don't allow this if follow links is false. */
5252 if (total_data
== 0) {
5253 return NT_STATUS_INVALID_PARAMETER
;
5256 if (!lp_symlinks(SNUM(conn
))) {
5257 return NT_STATUS_ACCESS_DENIED
;
5260 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5261 total_data
, STR_TERMINATE
);
5264 return NT_STATUS_INVALID_PARAMETER
;
5267 /* !widelinks forces the target path to be within the share. */
5268 /* This means we can interpret the target as a pathname. */
5269 if (!lp_widelinks(SNUM(conn
))) {
5270 char *rel_name
= NULL
;
5271 char *last_dirp
= NULL
;
5273 if (*link_target
== '/') {
5274 /* No absolute paths allowed. */
5275 return NT_STATUS_ACCESS_DENIED
;
5277 rel_name
= talloc_strdup(ctx
,newname
);
5279 return NT_STATUS_NO_MEMORY
;
5281 last_dirp
= strrchr_m(rel_name
, '/');
5283 last_dirp
[1] = '\0';
5285 rel_name
= talloc_strdup(ctx
,"./");
5287 return NT_STATUS_NO_MEMORY
;
5290 rel_name
= talloc_asprintf_append(rel_name
,
5294 return NT_STATUS_NO_MEMORY
;
5297 status
= check_name(conn
, rel_name
);
5298 if (!NT_STATUS_IS_OK(status
)) {
5303 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5304 newname
, link_target
));
5306 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5307 return map_nt_error_from_unix(errno
);
5310 return NT_STATUS_OK
;
5313 /****************************************************************************
5314 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5315 ****************************************************************************/
5317 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5318 struct smb_request
*req
,
5319 const char *pdata
, int total_data
,
5322 char *oldname
= NULL
;
5323 TALLOC_CTX
*ctx
= talloc_tos();
5324 NTSTATUS status
= NT_STATUS_OK
;
5326 /* Set a hard link. */
5327 if (total_data
== 0) {
5328 return NT_STATUS_INVALID_PARAMETER
;
5331 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5332 total_data
, STR_TERMINATE
, &status
);
5333 if (!NT_STATUS_IS_OK(status
)) {
5337 status
= resolve_dfspath(ctx
, conn
,
5338 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5341 if (!NT_STATUS_IS_OK(status
)) {
5345 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5348 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5351 /****************************************************************************
5352 Deal with SMB_FILE_RENAME_INFORMATION.
5353 ****************************************************************************/
5355 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5356 struct smb_request
*req
,
5365 char *newname
= NULL
;
5366 char *base_name
= NULL
;
5367 bool dest_has_wcard
= False
;
5368 SMB_STRUCT_STAT sbuf
;
5369 char *newname_last_component
= NULL
;
5370 NTSTATUS status
= NT_STATUS_OK
;
5372 TALLOC_CTX
*ctx
= talloc_tos();
5374 if (total_data
< 13) {
5375 return NT_STATUS_INVALID_PARAMETER
;
5380 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5381 root_fid
= IVAL(pdata
,4);
5382 len
= IVAL(pdata
,8);
5384 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5385 return NT_STATUS_INVALID_PARAMETER
;
5388 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5391 if (!NT_STATUS_IS_OK(status
)) {
5395 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5398 status
= resolve_dfspath_wcard(ctx
, conn
,
5399 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5403 if (!NT_STATUS_IS_OK(status
)) {
5407 /* Check the new name has no '/' characters. */
5408 if (strchr_m(newname
, '/')) {
5409 return NT_STATUS_NOT_SUPPORTED
;
5412 if (fsp
&& fsp
->base_fsp
) {
5413 /* newname must be a stream name. */
5414 if (newname
[0] != ':') {
5415 return NT_STATUS_NOT_SUPPORTED
;
5417 base_name
= talloc_asprintf(ctx
, "%s%s",
5418 fsp
->base_fsp
->fsp_name
,
5421 return NT_STATUS_NO_MEMORY
;
5424 /* newname must *not* be a stream name. */
5425 if (is_ntfs_stream_name(newname
)) {
5426 return NT_STATUS_NOT_SUPPORTED
;
5429 /* Create the base directory. */
5430 base_name
= talloc_strdup(ctx
, fname
);
5432 return NT_STATUS_NO_MEMORY
;
5434 p
= strrchr_m(base_name
, '/');
5438 base_name
= talloc_strdup(ctx
, "./");
5440 return NT_STATUS_NO_MEMORY
;
5443 /* Append the new name. */
5444 base_name
= talloc_asprintf_append(base_name
,
5448 return NT_STATUS_NO_MEMORY
;
5451 status
= unix_convert(ctx
, conn
, newname
, False
,
5453 &newname_last_component
,
5456 /* If an error we expect this to be
5457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5459 if (!NT_STATUS_IS_OK(status
)
5460 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5467 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5468 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5469 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5470 newname_last_component
, 0,
5473 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5474 fname
, base_name
));
5475 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5476 overwrite
, False
, dest_has_wcard
,
5477 FILE_WRITE_ATTRIBUTES
);
5483 /****************************************************************************
5484 Deal with SMB_SET_POSIX_ACL.
5485 ****************************************************************************/
5487 #if defined(HAVE_POSIX_ACLS)
5488 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5493 SMB_STRUCT_STAT
*psbuf
)
5495 uint16 posix_acl_version
;
5496 uint16 num_file_acls
;
5497 uint16 num_def_acls
;
5498 bool valid_file_acls
= True
;
5499 bool valid_def_acls
= True
;
5501 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5502 return NT_STATUS_INVALID_PARAMETER
;
5504 posix_acl_version
= SVAL(pdata
,0);
5505 num_file_acls
= SVAL(pdata
,2);
5506 num_def_acls
= SVAL(pdata
,4);
5508 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5509 valid_file_acls
= False
;
5513 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5514 valid_def_acls
= False
;
5518 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5519 return NT_STATUS_INVALID_PARAMETER
;
5522 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5523 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5524 return NT_STATUS_INVALID_PARAMETER
;
5527 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5528 fname
? fname
: fsp
->fsp_name
,
5529 (unsigned int)num_file_acls
,
5530 (unsigned int)num_def_acls
));
5532 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5533 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5534 return map_nt_error_from_unix(errno
);
5537 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5538 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5539 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5540 return map_nt_error_from_unix(errno
);
5542 return NT_STATUS_OK
;
5546 /****************************************************************************
5547 Deal with SMB_SET_POSIX_LOCK.
5548 ****************************************************************************/
5550 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5551 struct smb_request
*req
,
5559 bool blocking_lock
= False
;
5560 enum brl_type lock_type
;
5562 NTSTATUS status
= NT_STATUS_OK
;
5564 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5565 return NT_STATUS_INVALID_HANDLE
;
5568 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5569 return NT_STATUS_INVALID_PARAMETER
;
5572 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5573 case POSIX_LOCK_TYPE_READ
:
5574 lock_type
= READ_LOCK
;
5576 case POSIX_LOCK_TYPE_WRITE
:
5577 /* Return the right POSIX-mappable error code for files opened read-only. */
5578 if (!fsp
->can_write
) {
5579 return NT_STATUS_INVALID_HANDLE
;
5581 lock_type
= WRITE_LOCK
;
5583 case POSIX_LOCK_TYPE_UNLOCK
:
5584 lock_type
= UNLOCK_LOCK
;
5587 return NT_STATUS_INVALID_PARAMETER
;
5590 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5591 blocking_lock
= False
;
5592 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5593 blocking_lock
= True
;
5595 return NT_STATUS_INVALID_PARAMETER
;
5598 if (!lp_blocking_locks(SNUM(conn
))) {
5599 blocking_lock
= False
;
5602 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5603 #if defined(HAVE_LONGLONG)
5604 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5605 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5606 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5607 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5608 #else /* HAVE_LONGLONG */
5609 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5610 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5611 #endif /* HAVE_LONGLONG */
5613 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5614 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5616 (unsigned int)lock_type
,
5617 (unsigned int)lock_pid
,
5621 if (lock_type
== UNLOCK_LOCK
) {
5622 status
= do_unlock(smbd_messaging_context(),
5629 uint32 block_smbpid
;
5631 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5643 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5645 * A blocking lock was requested. Package up
5646 * this smb into a queued request and push it
5647 * onto the blocking lock queue.
5649 if(push_blocking_lock_request(br_lck
,
5652 -1, /* infinite timeout. */
5660 TALLOC_FREE(br_lck
);
5664 TALLOC_FREE(br_lck
);
5670 /****************************************************************************
5671 Deal with SMB_INFO_STANDARD.
5672 ****************************************************************************/
5674 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5679 const SMB_STRUCT_STAT
*psbuf
)
5681 struct smb_file_time ft
;
5684 if (total_data
< 12) {
5685 return NT_STATUS_INVALID_PARAMETER
;
5689 ft
.create_time
= interpret_long_date(pdata
);
5692 ft
.atime
= interpret_long_date(pdata
+ 8);
5695 ft
.mtime
= interpret_long_date(pdata
+ 16);
5697 DEBUG(10,("smb_set_info_standard: file %s\n",
5698 fname
? fname
: fsp
->fsp_name
));
5700 return smb_set_file_time(conn
,
5708 /****************************************************************************
5709 Deal with SMB_SET_FILE_BASIC_INFO.
5710 ****************************************************************************/
5712 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5717 SMB_STRUCT_STAT
*psbuf
)
5719 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5720 struct timespec write_time
;
5721 struct timespec changed_time
;
5722 struct smb_file_time ft
;
5724 NTSTATUS status
= NT_STATUS_OK
;
5725 bool setting_write_time
= true;
5729 if (total_data
< 36) {
5730 return NT_STATUS_INVALID_PARAMETER
;
5733 /* Set the attributes */
5734 dosmode
= IVAL(pdata
,32);
5735 status
= smb_set_file_dosmode(conn
, fsp
, fname
, psbuf
, dosmode
);
5736 if (!NT_STATUS_IS_OK(status
)) {
5741 ft
.atime
= interpret_long_date(pdata
+8);
5743 write_time
= interpret_long_date(pdata
+16);
5744 changed_time
= interpret_long_date(pdata
+24);
5747 ft
.mtime
= timespec_min(&write_time
, &changed_time
);
5750 ft
.create_time
= interpret_long_date(pdata
);
5752 if ((timespec_compare(&write_time
, &ft
.mtime
) == 1) &&
5753 !null_timespec(write_time
)) {
5754 ft
.mtime
= write_time
;
5757 /* Prefer a defined time to an undefined one. */
5758 if (null_timespec(ft
.mtime
)) {
5759 if (null_timespec(write_time
)) {
5760 ft
.mtime
= changed_time
;
5761 setting_write_time
= false;
5763 ft
.mtime
= write_time
;
5767 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5768 fname
? fname
: fsp
->fsp_name
));
5770 return smb_set_file_time(conn
,
5775 setting_write_time
);
5778 /****************************************************************************
5779 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5780 ****************************************************************************/
5782 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5783 struct smb_request
*req
,
5788 SMB_STRUCT_STAT
*psbuf
)
5790 uint64_t allocation_size
= 0;
5791 NTSTATUS status
= NT_STATUS_OK
;
5792 files_struct
*new_fsp
= NULL
;
5794 if (!VALID_STAT(*psbuf
)) {
5795 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5798 if (total_data
< 8) {
5799 return NT_STATUS_INVALID_PARAMETER
;
5802 allocation_size
= (uint64_t)IVAL(pdata
,0);
5803 #ifdef LARGE_SMB_OFF_T
5804 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5805 #else /* LARGE_SMB_OFF_T */
5806 if (IVAL(pdata
,4) != 0) {
5807 /* more than 32 bits? */
5808 return NT_STATUS_INVALID_PARAMETER
;
5810 #endif /* LARGE_SMB_OFF_T */
5812 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5813 fname
, (double)allocation_size
));
5815 if (allocation_size
) {
5816 allocation_size
= smb_roundup(conn
, allocation_size
);
5819 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5820 fname
, (double)allocation_size
));
5822 if (fsp
&& fsp
->fh
->fd
!= -1) {
5823 /* Open file handle. */
5824 /* Only change if needed. */
5825 if (allocation_size
!= get_file_size_stat(psbuf
)) {
5826 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5827 return map_nt_error_from_unix(errno
);
5830 /* But always update the time. */
5832 * This is equivalent to a write. Ensure it's seen immediately
5833 * if there are no pending writes.
5835 trigger_write_time_update_immediate(fsp
);
5836 return NT_STATUS_OK
;
5839 /* Pathname or stat or directory file. */
5841 status
= SMB_VFS_CREATE_FILE(
5844 0, /* root_dir_fid */
5846 0, /* create_file_flags */
5847 FILE_WRITE_DATA
, /* access_mask */
5848 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5850 FILE_OPEN
, /* create_disposition*/
5851 0, /* create_options */
5852 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5853 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5854 0, /* allocation_size */
5857 &new_fsp
, /* result */
5861 if (!NT_STATUS_IS_OK(status
)) {
5862 /* NB. We check for open_was_deferred in the caller. */
5866 /* Only change if needed. */
5867 if (allocation_size
!= get_file_size_stat(psbuf
)) {
5868 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5869 status
= map_nt_error_from_unix(errno
);
5870 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5875 /* Changing the allocation size should set the last mod time. */
5877 * This is equivalent to a write. Ensure it's seen immediately
5878 * if there are no pending writes.
5880 trigger_write_time_update_immediate(new_fsp
);
5882 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5883 return NT_STATUS_OK
;
5886 /****************************************************************************
5887 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5888 ****************************************************************************/
5890 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5891 struct smb_request
*req
,
5896 SMB_STRUCT_STAT
*psbuf
)
5900 if (total_data
< 8) {
5901 return NT_STATUS_INVALID_PARAMETER
;
5904 size
= IVAL(pdata
,0);
5905 #ifdef LARGE_SMB_OFF_T
5906 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5907 #else /* LARGE_SMB_OFF_T */
5908 if (IVAL(pdata
,4) != 0) {
5909 /* more than 32 bits? */
5910 return NT_STATUS_INVALID_PARAMETER
;
5912 #endif /* LARGE_SMB_OFF_T */
5913 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5914 "file %s to %.0f\n", fname
, (double)size
));
5916 return smb_set_file_size(conn
, req
,
5923 /****************************************************************************
5924 Allow a UNIX info mknod.
5925 ****************************************************************************/
5927 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5931 SMB_STRUCT_STAT
*psbuf
)
5933 uint32 file_type
= IVAL(pdata
,56);
5934 #if defined(HAVE_MAKEDEV)
5935 uint32 dev_major
= IVAL(pdata
,60);
5936 uint32 dev_minor
= IVAL(pdata
,68);
5938 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5939 uint32 raw_unixmode
= IVAL(pdata
,84);
5943 if (total_data
< 100) {
5944 return NT_STATUS_INVALID_PARAMETER
;
5947 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5948 if (!NT_STATUS_IS_OK(status
)) {
5952 #if defined(HAVE_MAKEDEV)
5953 dev
= makedev(dev_major
, dev_minor
);
5956 switch (file_type
) {
5957 #if defined(S_IFIFO)
5958 case UNIX_TYPE_FIFO
:
5959 unixmode
|= S_IFIFO
;
5962 #if defined(S_IFSOCK)
5963 case UNIX_TYPE_SOCKET
:
5964 unixmode
|= S_IFSOCK
;
5967 #if defined(S_IFCHR)
5968 case UNIX_TYPE_CHARDEV
:
5969 unixmode
|= S_IFCHR
;
5972 #if defined(S_IFBLK)
5973 case UNIX_TYPE_BLKDEV
:
5974 unixmode
|= S_IFBLK
;
5978 return NT_STATUS_INVALID_PARAMETER
;
5981 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5982 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5984 /* Ok - do the mknod. */
5985 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5986 return map_nt_error_from_unix(errno
);
5989 /* If any of the other "set" calls fail we
5990 * don't want to end up with a half-constructed mknod.
5993 if (lp_inherit_perms(SNUM(conn
))) {
5995 if (!parent_dirname(talloc_tos(), fname
, &parent
, NULL
)) {
5996 return NT_STATUS_NO_MEMORY
;
5998 inherit_access_posix_acl(conn
, parent
, fname
, unixmode
);
5999 TALLOC_FREE(parent
);
6002 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
6003 status
= map_nt_error_from_unix(errno
);
6004 SMB_VFS_UNLINK(conn
,fname
);
6007 return NT_STATUS_OK
;
6010 /****************************************************************************
6011 Deal with SMB_SET_FILE_UNIX_BASIC.
6012 ****************************************************************************/
6014 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6015 struct smb_request
*req
,
6020 SMB_STRUCT_STAT
*psbuf
)
6022 struct smb_file_time ft
;
6023 uint32 raw_unixmode
;
6026 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6027 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6028 NTSTATUS status
= NT_STATUS_OK
;
6029 bool delete_on_fail
= False
;
6030 enum perm_type ptype
;
6034 if (total_data
< 100) {
6035 return NT_STATUS_INVALID_PARAMETER
;
6038 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6039 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6040 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6041 #ifdef LARGE_SMB_OFF_T
6042 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6043 #else /* LARGE_SMB_OFF_T */
6044 if (IVAL(pdata
,4) != 0) {
6045 /* more than 32 bits? */
6046 return NT_STATUS_INVALID_PARAMETER
;
6048 #endif /* LARGE_SMB_OFF_T */
6051 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6052 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6053 set_owner
= (uid_t
)IVAL(pdata
,40);
6054 set_grp
= (gid_t
)IVAL(pdata
,48);
6055 raw_unixmode
= IVAL(pdata
,84);
6057 if (VALID_STAT(*psbuf
)) {
6058 if (S_ISDIR(psbuf
->st_mode
)) {
6059 ptype
= PERM_EXISTING_DIR
;
6061 ptype
= PERM_EXISTING_FILE
;
6064 ptype
= PERM_NEW_FILE
;
6067 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
6068 if (!NT_STATUS_IS_OK(status
)) {
6072 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6073 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6074 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
6076 if (!VALID_STAT(*psbuf
)) {
6078 * The only valid use of this is to create character and block
6079 * devices, and named pipes. This is deprecated (IMHO) and
6080 * a new info level should be used for mknod. JRA.
6083 status
= smb_unix_mknod(conn
,
6088 if (!NT_STATUS_IS_OK(status
)) {
6092 /* Ensure we don't try and change anything else. */
6093 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6094 size
= get_file_size_stat(psbuf
);
6095 ft
.atime
= get_atimespec(psbuf
);
6096 ft
.mtime
= get_mtimespec(psbuf
);
6098 * We continue here as we might want to change the
6101 delete_on_fail
= True
;
6105 /* Horrible backwards compatibility hack as an old server bug
6106 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6110 size
= get_file_size_stat(psbuf
);
6115 * Deal with the UNIX specific mode set.
6118 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6119 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6120 (unsigned int)unixmode
, fname
));
6121 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6122 return map_nt_error_from_unix(errno
);
6127 * Deal with the UNIX specific uid set.
6130 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6133 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6134 (unsigned int)set_owner
, fname
));
6136 if (S_ISLNK(psbuf
->st_mode
)) {
6137 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6139 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6143 status
= map_nt_error_from_unix(errno
);
6144 if (delete_on_fail
) {
6145 SMB_VFS_UNLINK(conn
,fname
);
6152 * Deal with the UNIX specific gid set.
6155 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6156 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6157 (unsigned int)set_owner
, fname
));
6158 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6159 status
= map_nt_error_from_unix(errno
);
6160 if (delete_on_fail
) {
6161 SMB_VFS_UNLINK(conn
,fname
);
6167 /* Deal with any size changes. */
6169 status
= smb_set_file_size(conn
, req
,
6174 if (!NT_STATUS_IS_OK(status
)) {
6178 /* Deal with any time changes. */
6180 return smb_set_file_time(conn
,
6188 /****************************************************************************
6189 Deal with SMB_SET_FILE_UNIX_INFO2.
6190 ****************************************************************************/
6192 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6193 struct smb_request
*req
,
6198 SMB_STRUCT_STAT
*psbuf
)
6204 if (total_data
< 116) {
6205 return NT_STATUS_INVALID_PARAMETER
;
6208 /* Start by setting all the fields that are common between UNIX_BASIC
6211 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6213 if (!NT_STATUS_IS_OK(status
)) {
6217 smb_fflags
= IVAL(pdata
, 108);
6218 smb_fmask
= IVAL(pdata
, 112);
6220 /* NB: We should only attempt to alter the file flags if the client
6221 * sends a non-zero mask.
6223 if (smb_fmask
!= 0) {
6224 int stat_fflags
= 0;
6226 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6228 /* Client asked to alter a flag we don't understand. */
6229 return NT_STATUS_INVALID_PARAMETER
;
6232 if (fsp
&& fsp
->fh
->fd
!= -1) {
6233 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6234 return NT_STATUS_NOT_SUPPORTED
;
6236 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6237 return map_nt_error_from_unix(errno
);
6242 /* XXX: need to add support for changing the create_time here. You
6243 * can do this for paths on Darwin with setattrlist(2). The right way
6244 * to hook this up is probably by extending the VFS utimes interface.
6247 return NT_STATUS_OK
;
6250 /****************************************************************************
6251 Create a directory with POSIX semantics.
6252 ****************************************************************************/
6254 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6255 struct smb_request
*req
,
6259 SMB_STRUCT_STAT
*psbuf
,
6260 int *pdata_return_size
)
6262 NTSTATUS status
= NT_STATUS_OK
;
6263 uint32 raw_unixmode
= 0;
6264 uint32 mod_unixmode
= 0;
6265 mode_t unixmode
= (mode_t
)0;
6266 files_struct
*fsp
= NULL
;
6267 uint16 info_level_return
= 0;
6269 char *pdata
= *ppdata
;
6271 if (total_data
< 18) {
6272 return NT_STATUS_INVALID_PARAMETER
;
6275 raw_unixmode
= IVAL(pdata
,8);
6276 /* Next 4 bytes are not yet defined. */
6278 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6279 if (!NT_STATUS_IS_OK(status
)) {
6283 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6286 fname
, (unsigned int)unixmode
));
6288 status
= SMB_VFS_CREATE_FILE(
6291 0, /* root_dir_fid */
6293 0, /* create_file_flags */
6294 FILE_READ_ATTRIBUTES
, /* access_mask */
6295 FILE_SHARE_NONE
, /* share_access */
6296 FILE_CREATE
, /* create_disposition*/
6297 FILE_DIRECTORY_FILE
, /* create_options */
6298 mod_unixmode
, /* file_attributes */
6299 0, /* oplock_request */
6300 0, /* allocation_size */
6307 if (NT_STATUS_IS_OK(status
)) {
6308 close_file(req
, fsp
, NORMAL_CLOSE
);
6311 info_level_return
= SVAL(pdata
,16);
6313 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6314 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6315 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6316 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6318 *pdata_return_size
= 12;
6321 /* Realloc the data size */
6322 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6323 if (*ppdata
== NULL
) {
6324 *pdata_return_size
= 0;
6325 return NT_STATUS_NO_MEMORY
;
6329 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6330 SSVAL(pdata
,2,0); /* No fnum. */
6331 SIVAL(pdata
,4,info
); /* Was directory created. */
6333 switch (info_level_return
) {
6334 case SMB_QUERY_FILE_UNIX_BASIC
:
6335 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6336 SSVAL(pdata
,10,0); /* Padding. */
6337 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6339 case SMB_QUERY_FILE_UNIX_INFO2
:
6340 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6341 SSVAL(pdata
,10,0); /* Padding. */
6342 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6345 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6346 SSVAL(pdata
,10,0); /* Padding. */
6353 /****************************************************************************
6354 Open/Create a file with POSIX semantics.
6355 ****************************************************************************/
6357 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6358 struct smb_request
*req
,
6362 SMB_STRUCT_STAT
*psbuf
,
6363 int *pdata_return_size
)
6365 bool extended_oplock_granted
= False
;
6366 char *pdata
= *ppdata
;
6368 uint32 wire_open_mode
= 0;
6369 uint32 raw_unixmode
= 0;
6370 uint32 mod_unixmode
= 0;
6371 uint32 create_disp
= 0;
6372 uint32 access_mask
= 0;
6373 uint32 create_options
= 0;
6374 NTSTATUS status
= NT_STATUS_OK
;
6375 mode_t unixmode
= (mode_t
)0;
6376 files_struct
*fsp
= NULL
;
6377 int oplock_request
= 0;
6379 uint16 info_level_return
= 0;
6381 if (total_data
< 18) {
6382 return NT_STATUS_INVALID_PARAMETER
;
6385 flags
= IVAL(pdata
,0);
6386 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6387 if (oplock_request
) {
6388 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6391 wire_open_mode
= IVAL(pdata
,4);
6393 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6394 return smb_posix_mkdir(conn
, req
,
6402 switch (wire_open_mode
& SMB_ACCMODE
) {
6404 access_mask
= FILE_READ_DATA
;
6407 access_mask
= FILE_WRITE_DATA
;
6410 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6413 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6414 (unsigned int)wire_open_mode
));
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 wire_open_mode
&= ~SMB_ACCMODE
;
6420 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6421 create_disp
= FILE_CREATE
;
6422 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6423 create_disp
= FILE_OVERWRITE_IF
;
6424 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6425 create_disp
= FILE_OPEN_IF
;
6426 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
6427 create_disp
= FILE_OPEN
;
6429 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6430 (unsigned int)wire_open_mode
));
6431 return NT_STATUS_INVALID_PARAMETER
;
6434 raw_unixmode
= IVAL(pdata
,8);
6435 /* Next 4 bytes are not yet defined. */
6437 status
= unix_perms_from_wire(conn
,
6440 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6443 if (!NT_STATUS_IS_OK(status
)) {
6447 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6449 if (wire_open_mode
& SMB_O_SYNC
) {
6450 create_options
|= FILE_WRITE_THROUGH
;
6452 if (wire_open_mode
& SMB_O_APPEND
) {
6453 access_mask
|= FILE_APPEND_DATA
;
6455 if (wire_open_mode
& SMB_O_DIRECT
) {
6456 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6459 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6461 (unsigned int)wire_open_mode
,
6462 (unsigned int)unixmode
));
6464 status
= SMB_VFS_CREATE_FILE(
6467 0, /* root_dir_fid */
6469 0, /* create_file_flags */
6470 access_mask
, /* access_mask */
6471 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6473 create_disp
, /* create_disposition*/
6474 0, /* create_options */
6475 mod_unixmode
, /* file_attributes */
6476 oplock_request
, /* oplock_request */
6477 0, /* allocation_size */
6484 if (!NT_STATUS_IS_OK(status
)) {
6488 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6489 extended_oplock_granted
= True
;
6492 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6493 extended_oplock_granted
= True
;
6496 info_level_return
= SVAL(pdata
,16);
6498 /* Allocate the correct return size. */
6500 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6501 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6502 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6503 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6505 *pdata_return_size
= 12;
6508 /* Realloc the data size */
6509 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6510 if (*ppdata
== NULL
) {
6511 close_file(req
, fsp
, ERROR_CLOSE
);
6512 *pdata_return_size
= 0;
6513 return NT_STATUS_NO_MEMORY
;
6517 if (extended_oplock_granted
) {
6518 if (flags
& REQUEST_BATCH_OPLOCK
) {
6519 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6521 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6523 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6524 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6526 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6529 SSVAL(pdata
,2,fsp
->fnum
);
6530 SIVAL(pdata
,4,info
); /* Was file created etc. */
6532 switch (info_level_return
) {
6533 case SMB_QUERY_FILE_UNIX_BASIC
:
6534 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6535 SSVAL(pdata
,10,0); /* padding. */
6536 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6538 case SMB_QUERY_FILE_UNIX_INFO2
:
6539 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6540 SSVAL(pdata
,10,0); /* padding. */
6541 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6544 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6545 SSVAL(pdata
,10,0); /* padding. */
6548 return NT_STATUS_OK
;
6551 /****************************************************************************
6552 Delete a file with POSIX semantics.
6553 ****************************************************************************/
6555 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6556 struct smb_request
*req
,
6560 SMB_STRUCT_STAT
*psbuf
)
6562 NTSTATUS status
= NT_STATUS_OK
;
6563 files_struct
*fsp
= NULL
;
6567 int create_options
= 0;
6569 struct share_mode_lock
*lck
= NULL
;
6571 if (total_data
< 2) {
6572 return NT_STATUS_INVALID_PARAMETER
;
6575 flags
= SVAL(pdata
,0);
6577 if (!VALID_STAT(*psbuf
)) {
6578 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6581 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6582 !VALID_STAT_OF_DIR(*psbuf
)) {
6583 return NT_STATUS_NOT_A_DIRECTORY
;
6586 DEBUG(10,("smb_posix_unlink: %s %s\n",
6587 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6590 if (VALID_STAT_OF_DIR(*psbuf
)) {
6591 create_options
|= FILE_DIRECTORY_FILE
;
6594 status
= SMB_VFS_CREATE_FILE(
6597 0, /* root_dir_fid */
6599 0, /* create_file_flags */
6600 DELETE_ACCESS
, /* access_mask */
6601 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6603 FILE_OPEN
, /* create_disposition*/
6604 create_options
, /* create_options */
6605 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
6606 0, /* oplock_request */
6607 0, /* allocation_size */
6614 if (!NT_STATUS_IS_OK(status
)) {
6619 * Don't lie to client. If we can't really delete due to
6620 * non-POSIX opens return SHARING_VIOLATION.
6623 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6626 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6627 "lock for file %s\n", fsp
->fsp_name
));
6628 close_file(req
, fsp
, NORMAL_CLOSE
);
6629 return NT_STATUS_INVALID_PARAMETER
;
6633 * See if others still have the file open. If this is the case, then
6634 * don't delete. If all opens are POSIX delete we can set the delete
6635 * on close disposition.
6637 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6638 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6639 if (is_valid_share_mode_entry(e
)) {
6640 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6643 /* Fail with sharing violation. */
6644 close_file(req
, fsp
, NORMAL_CLOSE
);
6646 return NT_STATUS_SHARING_VIOLATION
;
6651 * Set the delete on close.
6653 status
= smb_set_file_disposition_info(conn
,
6660 if (!NT_STATUS_IS_OK(status
)) {
6661 close_file(req
, fsp
, NORMAL_CLOSE
);
6666 return close_file(req
, fsp
, NORMAL_CLOSE
);
6669 /****************************************************************************
6670 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6671 ****************************************************************************/
6673 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6674 struct smb_request
*req
,
6675 unsigned int tran_call
,
6676 char **pparams
, int total_params
,
6677 char **ppdata
, int total_data
,
6678 unsigned int max_data_bytes
)
6680 char *params
= *pparams
;
6681 char *pdata
= *ppdata
;
6683 SMB_STRUCT_STAT sbuf
;
6685 files_struct
*fsp
= NULL
;
6686 NTSTATUS status
= NT_STATUS_OK
;
6687 int data_return_size
= 0;
6688 TALLOC_CTX
*ctx
= talloc_tos();
6691 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6697 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6698 if (total_params
< 4) {
6699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6703 fsp
= file_fsp(req
, SVAL(params
,0));
6704 /* Basic check for non-null fsp. */
6705 if (!check_fsp_open(conn
, req
, fsp
)) {
6708 info_level
= SVAL(params
,2);
6710 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6712 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6716 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6718 * This is actually a SETFILEINFO on a directory
6719 * handle (returned from an NT SMB). NT5.0 seems
6720 * to do this call. JRA.
6722 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6723 /* Always do lstat for UNIX calls. */
6724 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6725 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6726 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6730 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6731 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6732 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6736 } else if (fsp
->print_file
) {
6738 * Doing a DELETE_ON_CLOSE should cancel a print job.
6740 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6741 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6743 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6746 send_trans2_replies(conn
, req
, params
, 2,
6751 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6756 * Original code - this is an open file.
6758 if (!check_fsp(conn
, req
, fsp
)) {
6762 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6763 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6764 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6770 if (total_params
< 7) {
6771 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6775 info_level
= SVAL(params
,0);
6776 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6777 total_params
- 6, STR_TERMINATE
,
6779 if (!NT_STATUS_IS_OK(status
)) {
6780 reply_nterror(req
, status
);
6784 status
= resolve_dfspath(ctx
, conn
,
6785 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6788 if (!NT_STATUS_IS_OK(status
)) {
6789 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6790 reply_botherror(req
,
6791 NT_STATUS_PATH_NOT_COVERED
,
6792 ERRSRV
, ERRbadpath
);
6795 reply_nterror(req
, status
);
6799 status
= unix_convert(ctx
, conn
, fname
, False
,
6800 &fname
, NULL
, &sbuf
);
6801 if (!NT_STATUS_IS_OK(status
)) {
6802 reply_nterror(req
, status
);
6806 status
= check_name(conn
, fname
);
6807 if (!NT_STATUS_IS_OK(status
)) {
6808 reply_nterror(req
, status
);
6812 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6814 * For CIFS UNIX extensions the target name may not exist.
6817 /* Always do lstat for UNIX calls. */
6818 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6820 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6821 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6822 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6827 if (!CAN_WRITE(conn
)) {
6828 reply_doserror(req
, ERRSRV
, ERRaccess
);
6832 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6833 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6837 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6838 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6840 /* Realloc the parameter size */
6841 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6842 if (*pparams
== NULL
) {
6843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6850 switch (info_level
) {
6852 case SMB_INFO_STANDARD
:
6854 status
= smb_set_info_standard(conn
,
6863 case SMB_INFO_SET_EA
:
6865 status
= smb_info_set_ea(conn
,
6873 case SMB_SET_FILE_BASIC_INFO
:
6874 case SMB_FILE_BASIC_INFORMATION
:
6876 status
= smb_set_file_basic_info(conn
,
6885 case SMB_FILE_ALLOCATION_INFORMATION
:
6886 case SMB_SET_FILE_ALLOCATION_INFO
:
6888 status
= smb_set_file_allocation_info(conn
, req
,
6897 case SMB_FILE_END_OF_FILE_INFORMATION
:
6898 case SMB_SET_FILE_END_OF_FILE_INFO
:
6900 status
= smb_set_file_end_of_file_info(conn
, req
,
6909 case SMB_FILE_DISPOSITION_INFORMATION
:
6910 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6913 /* JRA - We used to just ignore this on a path ?
6914 * Shouldn't this be invalid level on a pathname
6917 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6918 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6921 status
= smb_set_file_disposition_info(conn
,
6930 case SMB_FILE_POSITION_INFORMATION
:
6932 status
= smb_file_position_information(conn
,
6939 /* From tridge Samba4 :
6940 * MODE_INFORMATION in setfileinfo (I have no
6941 * idea what "mode information" on a file is - it takes a value of 0,
6942 * 2, 4 or 6. What could it be?).
6945 case SMB_FILE_MODE_INFORMATION
:
6947 status
= smb_file_mode_information(conn
,
6954 * CIFS UNIX extensions.
6957 case SMB_SET_FILE_UNIX_BASIC
:
6959 status
= smb_set_file_unix_basic(conn
, req
,
6968 case SMB_SET_FILE_UNIX_INFO2
:
6970 status
= smb_set_file_unix_info2(conn
, req
,
6979 case SMB_SET_FILE_UNIX_LINK
:
6981 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6982 /* We must have a pathname for this. */
6983 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6986 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6991 case SMB_SET_FILE_UNIX_HLINK
:
6993 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6994 /* We must have a pathname for this. */
6995 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6998 status
= smb_set_file_unix_hlink(conn
, req
,
7004 case SMB_FILE_RENAME_INFORMATION
:
7006 status
= smb_file_rename_information(conn
, req
,
7012 #if defined(HAVE_POSIX_ACLS)
7013 case SMB_SET_POSIX_ACL
:
7015 status
= smb_set_posix_acl(conn
,
7025 case SMB_SET_POSIX_LOCK
:
7027 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7028 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7031 status
= smb_set_posix_lock(conn
, req
,
7032 pdata
, total_data
, fsp
);
7036 case SMB_POSIX_PATH_OPEN
:
7038 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7039 /* We must have a pathname for this. */
7040 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7044 status
= smb_posix_open(conn
, req
,
7053 case SMB_POSIX_PATH_UNLINK
:
7055 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7056 /* We must have a pathname for this. */
7057 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7061 status
= smb_posix_unlink(conn
, req
,
7070 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7075 if (!NT_STATUS_IS_OK(status
)) {
7076 if (open_was_deferred(req
->mid
)) {
7077 /* We have re-scheduled this call. */
7080 if (blocking_lock_was_deferred(req
->mid
)) {
7081 /* We have re-scheduled this call. */
7084 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7085 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7086 ERRSRV
, ERRbadpath
);
7089 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7090 reply_openerror(req
, status
);
7094 reply_nterror(req
, status
);
7099 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7105 /****************************************************************************
7106 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7107 ****************************************************************************/
7109 static void call_trans2mkdir(connection_struct
*conn
, 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
;
7115 char *pdata
= *ppdata
;
7116 char *directory
= NULL
;
7117 SMB_STRUCT_STAT sbuf
;
7118 NTSTATUS status
= NT_STATUS_OK
;
7119 struct ea_list
*ea_list
= NULL
;
7120 TALLOC_CTX
*ctx
= talloc_tos();
7122 if (!CAN_WRITE(conn
)) {
7123 reply_doserror(req
, ERRSRV
, ERRaccess
);
7127 if (total_params
< 5) {
7128 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7132 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7133 total_params
- 4, STR_TERMINATE
,
7135 if (!NT_STATUS_IS_OK(status
)) {
7136 reply_nterror(req
, status
);
7140 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7142 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
7143 if (!NT_STATUS_IS_OK(status
)) {
7144 reply_nterror(req
, status
);
7148 status
= check_name(conn
, directory
);
7149 if (!NT_STATUS_IS_OK(status
)) {
7150 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7151 reply_nterror(req
, status
);
7155 /* Any data in this call is an EA list. */
7156 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7157 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7162 * OS/2 workplace shell seems to send SET_EA requests of "null"
7163 * length (4 bytes containing IVAL 4).
7164 * They seem to have no effect. Bug #3212. JRA.
7167 if (total_data
!= 4) {
7168 if (total_data
< 10) {
7169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7173 if (IVAL(pdata
,0) > total_data
) {
7174 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7175 IVAL(pdata
,0), (unsigned int)total_data
));
7176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7180 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7187 /* If total_data == 4 Windows doesn't care what values
7188 * are placed in that field, it just ignores them.
7189 * The System i QNTC IBM SMB client puts bad values here,
7190 * so ignore them. */
7192 status
= create_directory(conn
, req
, directory
);
7194 if (!NT_STATUS_IS_OK(status
)) {
7195 reply_nterror(req
, status
);
7199 /* Try and set any given EA. */
7201 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7202 if (!NT_STATUS_IS_OK(status
)) {
7203 reply_nterror(req
, status
);
7208 /* Realloc the parameter and data sizes */
7209 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7210 if(*pparams
== NULL
) {
7211 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7218 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7223 /****************************************************************************
7224 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7225 We don't actually do this - we just send a null response.
7226 ****************************************************************************/
7228 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7229 struct smb_request
*req
,
7230 char **pparams
, int total_params
,
7231 char **ppdata
, int total_data
,
7232 unsigned int max_data_bytes
)
7234 char *params
= *pparams
;
7237 if (total_params
< 6) {
7238 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7242 info_level
= SVAL(params
,4);
7243 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7245 switch (info_level
) {
7250 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7254 /* Realloc the parameter and data sizes */
7255 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7256 if (*pparams
== NULL
) {
7257 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7262 SSVAL(params
,0,fnf_handle
);
7263 SSVAL(params
,2,0); /* No changes */
7264 SSVAL(params
,4,0); /* No EA errors */
7271 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7276 /****************************************************************************
7277 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7278 changes). Currently this does nothing.
7279 ****************************************************************************/
7281 static void call_trans2findnotifynext(connection_struct
*conn
,
7282 struct smb_request
*req
,
7283 char **pparams
, int total_params
,
7284 char **ppdata
, int total_data
,
7285 unsigned int max_data_bytes
)
7287 char *params
= *pparams
;
7289 DEBUG(3,("call_trans2findnotifynext\n"));
7291 /* Realloc the parameter and data sizes */
7292 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7293 if (*pparams
== NULL
) {
7294 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7299 SSVAL(params
,0,0); /* No changes */
7300 SSVAL(params
,2,0); /* No EA errors */
7302 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7307 /****************************************************************************
7308 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7309 ****************************************************************************/
7311 static void call_trans2getdfsreferral(connection_struct
*conn
,
7312 struct smb_request
*req
,
7313 char **pparams
, int total_params
,
7314 char **ppdata
, int total_data
,
7315 unsigned int max_data_bytes
)
7317 char *params
= *pparams
;
7318 char *pathname
= NULL
;
7320 int max_referral_level
;
7321 NTSTATUS status
= NT_STATUS_OK
;
7322 TALLOC_CTX
*ctx
= talloc_tos();
7324 DEBUG(10,("call_trans2getdfsreferral\n"));
7326 if (total_params
< 3) {
7327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7331 max_referral_level
= SVAL(params
,0);
7333 if(!lp_host_msdfs()) {
7334 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7338 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7339 total_params
- 2, STR_TERMINATE
);
7341 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7344 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7345 ppdata
,&status
)) < 0) {
7346 reply_nterror(req
, status
);
7350 SSVAL(req
->inbuf
, smb_flg2
,
7351 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7352 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7357 #define LMCAT_SPL 0x53
7358 #define LMFUNC_GETJOBID 0x60
7360 /****************************************************************************
7361 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7362 ****************************************************************************/
7364 static void call_trans2ioctl(connection_struct
*conn
,
7365 struct smb_request
*req
,
7366 char **pparams
, int total_params
,
7367 char **ppdata
, int total_data
,
7368 unsigned int max_data_bytes
)
7370 char *pdata
= *ppdata
;
7371 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
7373 /* check for an invalid fid before proceeding */
7376 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7380 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
7381 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
7382 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7383 if (*ppdata
== NULL
) {
7384 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7389 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7390 CAN ACCEPT THIS IN UNICODE. JRA. */
7392 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7393 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7394 global_myname(), 15,
7395 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7396 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7397 lp_servicename(SNUM(conn
)), 13,
7398 STR_ASCII
|STR_TERMINATE
); /* Service name */
7399 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7404 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7405 reply_doserror(req
, ERRSRV
, ERRerror
);
7408 /****************************************************************************
7409 Reply to a SMBfindclose (stop trans2 directory search).
7410 ****************************************************************************/
7412 void reply_findclose(struct smb_request
*req
)
7416 START_PROFILE(SMBfindclose
);
7419 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7420 END_PROFILE(SMBfindclose
);
7424 dptr_num
= SVALS(req
->vwv
+0, 0);
7426 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7428 dptr_close(&dptr_num
);
7430 reply_outbuf(req
, 0, 0);
7432 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7434 END_PROFILE(SMBfindclose
);
7438 /****************************************************************************
7439 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7440 ****************************************************************************/
7442 void reply_findnclose(struct smb_request
*req
)
7446 START_PROFILE(SMBfindnclose
);
7449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7450 END_PROFILE(SMBfindnclose
);
7454 dptr_num
= SVAL(req
->vwv
+0, 0);
7456 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7458 /* We never give out valid handles for a
7459 findnotifyfirst - so any dptr_num is ok here.
7462 reply_outbuf(req
, 0, 0);
7464 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7466 END_PROFILE(SMBfindnclose
);
7470 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7471 struct trans_state
*state
)
7473 if (Protocol
>= PROTOCOL_NT1
) {
7474 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7475 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7478 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7479 if (state
->call
!= TRANSACT2_QFSINFO
&&
7480 state
->call
!= TRANSACT2_SETFSINFO
) {
7481 DEBUG(0,("handle_trans2: encryption required "
7483 (unsigned int)state
->call
));
7484 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7489 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
7491 /* Now we must call the relevant TRANS2 function */
7492 switch(state
->call
) {
7493 case TRANSACT2_OPEN
:
7495 START_PROFILE(Trans2_open
);
7496 call_trans2open(conn
, req
,
7497 &state
->param
, state
->total_param
,
7498 &state
->data
, state
->total_data
,
7499 state
->max_data_return
);
7500 END_PROFILE(Trans2_open
);
7504 case TRANSACT2_FINDFIRST
:
7506 START_PROFILE(Trans2_findfirst
);
7507 call_trans2findfirst(conn
, req
,
7508 &state
->param
, state
->total_param
,
7509 &state
->data
, state
->total_data
,
7510 state
->max_data_return
);
7511 END_PROFILE(Trans2_findfirst
);
7515 case TRANSACT2_FINDNEXT
:
7517 START_PROFILE(Trans2_findnext
);
7518 call_trans2findnext(conn
, req
,
7519 &state
->param
, state
->total_param
,
7520 &state
->data
, state
->total_data
,
7521 state
->max_data_return
);
7522 END_PROFILE(Trans2_findnext
);
7526 case TRANSACT2_QFSINFO
:
7528 START_PROFILE(Trans2_qfsinfo
);
7529 call_trans2qfsinfo(conn
, req
,
7530 &state
->param
, state
->total_param
,
7531 &state
->data
, state
->total_data
,
7532 state
->max_data_return
);
7533 END_PROFILE(Trans2_qfsinfo
);
7537 case TRANSACT2_SETFSINFO
:
7539 START_PROFILE(Trans2_setfsinfo
);
7540 call_trans2setfsinfo(conn
, req
,
7541 &state
->param
, state
->total_param
,
7542 &state
->data
, state
->total_data
,
7543 state
->max_data_return
);
7544 END_PROFILE(Trans2_setfsinfo
);
7548 case TRANSACT2_QPATHINFO
:
7549 case TRANSACT2_QFILEINFO
:
7551 START_PROFILE(Trans2_qpathinfo
);
7552 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7553 &state
->param
, state
->total_param
,
7554 &state
->data
, state
->total_data
,
7555 state
->max_data_return
);
7556 END_PROFILE(Trans2_qpathinfo
);
7560 case TRANSACT2_SETPATHINFO
:
7561 case TRANSACT2_SETFILEINFO
:
7563 START_PROFILE(Trans2_setpathinfo
);
7564 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7565 &state
->param
, state
->total_param
,
7566 &state
->data
, state
->total_data
,
7567 state
->max_data_return
);
7568 END_PROFILE(Trans2_setpathinfo
);
7572 case TRANSACT2_FINDNOTIFYFIRST
:
7574 START_PROFILE(Trans2_findnotifyfirst
);
7575 call_trans2findnotifyfirst(conn
, req
,
7576 &state
->param
, state
->total_param
,
7577 &state
->data
, state
->total_data
,
7578 state
->max_data_return
);
7579 END_PROFILE(Trans2_findnotifyfirst
);
7583 case TRANSACT2_FINDNOTIFYNEXT
:
7585 START_PROFILE(Trans2_findnotifynext
);
7586 call_trans2findnotifynext(conn
, req
,
7587 &state
->param
, state
->total_param
,
7588 &state
->data
, state
->total_data
,
7589 state
->max_data_return
);
7590 END_PROFILE(Trans2_findnotifynext
);
7594 case TRANSACT2_MKDIR
:
7596 START_PROFILE(Trans2_mkdir
);
7597 call_trans2mkdir(conn
, req
,
7598 &state
->param
, state
->total_param
,
7599 &state
->data
, state
->total_data
,
7600 state
->max_data_return
);
7601 END_PROFILE(Trans2_mkdir
);
7605 case TRANSACT2_GET_DFS_REFERRAL
:
7607 START_PROFILE(Trans2_get_dfs_referral
);
7608 call_trans2getdfsreferral(conn
, req
,
7609 &state
->param
, state
->total_param
,
7610 &state
->data
, state
->total_data
,
7611 state
->max_data_return
);
7612 END_PROFILE(Trans2_get_dfs_referral
);
7616 case TRANSACT2_IOCTL
:
7618 START_PROFILE(Trans2_ioctl
);
7619 call_trans2ioctl(conn
, req
,
7620 &state
->param
, state
->total_param
,
7621 &state
->data
, state
->total_data
,
7622 state
->max_data_return
);
7623 END_PROFILE(Trans2_ioctl
);
7628 /* Error in request */
7629 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7630 reply_doserror(req
, ERRSRV
,ERRerror
);
7634 /****************************************************************************
7635 Reply to a SMBtrans2.
7636 ****************************************************************************/
7638 void reply_trans2(struct smb_request
*req
)
7640 connection_struct
*conn
= req
->conn
;
7645 unsigned int tran_call
;
7646 struct trans_state
*state
;
7649 START_PROFILE(SMBtrans2
);
7651 if (req
->wct
< 14) {
7652 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7653 END_PROFILE(SMBtrans2
);
7657 dsoff
= SVAL(req
->vwv
+12, 0);
7658 dscnt
= SVAL(req
->vwv
+11, 0);
7659 psoff
= SVAL(req
->vwv
+10, 0);
7660 pscnt
= SVAL(req
->vwv
+9, 0);
7661 tran_call
= SVAL(req
->vwv
+14, 0);
7663 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7664 if (!NT_STATUS_IS_OK(result
)) {
7665 DEBUG(2, ("Got invalid trans2 request: %s\n",
7666 nt_errstr(result
)));
7667 reply_nterror(req
, result
);
7668 END_PROFILE(SMBtrans2
);
7673 switch (tran_call
) {
7674 /* List the allowed trans2 calls on IPC$ */
7675 case TRANSACT2_OPEN
:
7676 case TRANSACT2_GET_DFS_REFERRAL
:
7677 case TRANSACT2_QFILEINFO
:
7678 case TRANSACT2_QFSINFO
:
7679 case TRANSACT2_SETFSINFO
:
7682 reply_doserror(req
, ERRSRV
, ERRaccess
);
7683 END_PROFILE(SMBtrans2
);
7688 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
7689 DEBUG(0, ("talloc failed\n"));
7690 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7691 END_PROFILE(SMBtrans2
);
7695 state
->cmd
= SMBtrans2
;
7697 state
->mid
= req
->mid
;
7698 state
->vuid
= req
->vuid
;
7699 state
->setup_count
= SVAL(req
->vwv
+13, 0);
7700 state
->setup
= NULL
;
7701 state
->total_param
= SVAL(req
->vwv
+0, 0);
7702 state
->param
= NULL
;
7703 state
->total_data
= SVAL(req
->vwv
+1, 0);
7705 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
7706 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
7707 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
7708 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
7709 state
->one_way
= BITSETW(req
->vwv
+5, 1);
7711 state
->call
= tran_call
;
7713 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7714 is so as a sanity check */
7715 if (state
->setup_count
!= 1) {
7717 * Need to have rc=0 for ioctl to get job id for OS/2.
7718 * Network printing will fail if function is not successful.
7719 * Similar function in reply.c will be used if protocol
7720 * is LANMAN1.0 instead of LM1.2X002.
7721 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7722 * outbuf doesn't have to be set(only job id is used).
7724 if ( (state
->setup_count
== 4)
7725 && (tran_call
== TRANSACT2_IOCTL
)
7726 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
7727 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
7728 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7730 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7731 DEBUG(2,("Transaction is %d\n",tran_call
));
7733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7734 END_PROFILE(SMBtrans2
);
7739 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7742 if (state
->total_data
) {
7744 if (trans_oob(state
->total_data
, 0, dscnt
)
7745 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
7749 /* Can't use talloc here, the core routines do realloc on the
7750 * params and data. */
7751 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7752 if (state
->data
== NULL
) {
7753 DEBUG(0,("reply_trans2: data malloc fail for %u "
7754 "bytes !\n", (unsigned int)state
->total_data
));
7756 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7757 END_PROFILE(SMBtrans2
);
7761 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7764 if (state
->total_param
) {
7766 if (trans_oob(state
->total_param
, 0, pscnt
)
7767 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
7771 /* Can't use talloc here, the core routines do realloc on the
7772 * params and data. */
7773 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7774 if (state
->param
== NULL
) {
7775 DEBUG(0,("reply_trans: param malloc fail for %u "
7776 "bytes !\n", (unsigned int)state
->total_param
));
7777 SAFE_FREE(state
->data
);
7779 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7780 END_PROFILE(SMBtrans2
);
7784 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7787 state
->received_data
= dscnt
;
7788 state
->received_param
= pscnt
;
7790 if ((state
->received_param
== state
->total_param
) &&
7791 (state
->received_data
== state
->total_data
)) {
7793 handle_trans2(conn
, req
, state
);
7795 SAFE_FREE(state
->data
);
7796 SAFE_FREE(state
->param
);
7798 END_PROFILE(SMBtrans2
);
7802 DLIST_ADD(conn
->pending_trans
, state
);
7804 /* We need to send an interim response then receive the rest
7805 of the parameter/data bytes */
7806 reply_outbuf(req
, 0, 0);
7807 show_msg((char *)req
->outbuf
);
7808 END_PROFILE(SMBtrans2
);
7813 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7814 SAFE_FREE(state
->data
);
7815 SAFE_FREE(state
->param
);
7817 END_PROFILE(SMBtrans2
);
7818 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7822 /****************************************************************************
7823 Reply to a SMBtranss2
7824 ****************************************************************************/
7826 void reply_transs2(struct smb_request
*req
)
7828 connection_struct
*conn
= req
->conn
;
7829 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7830 struct trans_state
*state
;
7832 START_PROFILE(SMBtranss2
);
7834 show_msg((char *)req
->inbuf
);
7837 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7838 END_PROFILE(SMBtranss2
);
7842 for (state
= conn
->pending_trans
; state
!= NULL
;
7843 state
= state
->next
) {
7844 if (state
->mid
== req
->mid
) {
7849 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7850 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7851 END_PROFILE(SMBtranss2
);
7855 /* Revise state->total_param and state->total_data in case they have
7856 changed downwards */
7858 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
7859 state
->total_param
= SVAL(req
->vwv
+0, 0);
7860 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
7861 state
->total_data
= SVAL(req
->vwv
+1, 0);
7863 pcnt
= SVAL(req
->vwv
+2, 0);
7864 poff
= SVAL(req
->vwv
+3, 0);
7865 pdisp
= SVAL(req
->vwv
+4, 0);
7867 dcnt
= SVAL(req
->vwv
+5, 0);
7868 doff
= SVAL(req
->vwv
+6, 0);
7869 ddisp
= SVAL(req
->vwv
+7, 0);
7871 state
->received_param
+= pcnt
;
7872 state
->received_data
+= dcnt
;
7874 if ((state
->received_data
> state
->total_data
) ||
7875 (state
->received_param
> state
->total_param
))
7879 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
7880 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
7883 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
7887 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
7888 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
7891 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
7894 if ((state
->received_param
< state
->total_param
) ||
7895 (state
->received_data
< state
->total_data
)) {
7896 END_PROFILE(SMBtranss2
);
7900 handle_trans2(conn
, req
, state
);
7902 DLIST_REMOVE(conn
->pending_trans
, state
);
7903 SAFE_FREE(state
->data
);
7904 SAFE_FREE(state
->param
);
7907 END_PROFILE(SMBtranss2
);
7912 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7913 DLIST_REMOVE(conn
->pending_trans
, state
);
7914 SAFE_FREE(state
->data
);
7915 SAFE_FREE(state
->param
);
7917 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7918 END_PROFILE(SMBtranss2
);