2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol
;
30 extern uint32 global_client_caps
;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
52 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, const SMB_STRUCT_STAT
*sbuf
)
71 if(S_ISDIR(sbuf
->st_mode
)) {
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
78 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
81 if (fsp
&& fsp
->initial_allocation_size
)
82 ret
= MAX(ret
,fsp
->initial_allocation_size
);
84 return smb_roundup(conn
, ret
);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name
)
97 static const char *prohibited_ea_names
[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME
,
99 SAMBA_XATTR_DOS_ATTRIB
,
105 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
106 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
109 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
121 files_struct
*fsp
, const char *fname
,
122 const char *ea_name
, struct ea_struct
*pea
)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size
= 256;
131 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
133 return NT_STATUS_NO_MEMORY
;
136 if (fsp
&& fsp
->fh
->fd
!= -1) {
137 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
139 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
142 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
148 return map_nt_error_from_unix(errno
);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
152 dump_data(10, (uint8
*)val
, sizeret
);
155 if (strnequal(ea_name
, "user.", 5)) {
156 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
158 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
160 if (pea
->name
== NULL
) {
162 return NT_STATUS_NO_MEMORY
;
164 pea
->value
.data
= (unsigned char *)val
;
165 pea
->value
.length
= (size_t)sizeret
;
169 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
170 files_struct
*fsp
, const char *fname
,
171 char ***pnames
, size_t *pnum_names
)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size
= 1024;
175 char *ea_namelist
= NULL
;
180 ssize_t sizeret
= -1;
182 if (!lp_ea_support(SNUM(conn
))) {
189 * TALLOC the result early to get the talloc hierarchy right.
192 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY
;
198 while (ea_namelist_size
<= 65536) {
200 ea_namelist
= TALLOC_REALLOC_ARRAY(
201 names
, ea_namelist
, char, ea_namelist_size
);
202 if (ea_namelist
== NULL
) {
203 DEBUG(0, ("talloc failed\n"));
205 return NT_STATUS_NO_MEMORY
;
208 if (fsp
&& fsp
->fh
->fd
!= -1) {
209 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
212 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
216 if ((sizeret
== -1) && (errno
== ERANGE
)) {
217 ea_namelist_size
*= 2;
226 return map_nt_error_from_unix(errno
);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret
));
240 * Ensure the result is 0-terminated
243 if (ea_namelist
[sizeret
-1] != '\0') {
245 return NT_STATUS_INTERNAL_ERROR
;
253 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
257 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
259 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY
;
267 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
268 names
[num_names
++] = p
;
272 *pnum_names
= num_names
;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
281 const char *fname
, size_t *pea_total_len
)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list
*ea_list_head
= NULL
;
291 if (!lp_ea_support(SNUM(conn
))) {
295 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
298 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
302 for (i
=0; i
<num_names
; i
++) {
303 struct ea_list
*listp
;
306 if (strnequal(names
[i
], "system.", 7)
307 || samba_private_attr_name(names
[i
]))
310 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
321 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
324 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
328 (unsigned int)listp
->ea
.value
.length
));
330 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
334 /* Add on 4 for total length. */
335 if (*pea_total_len
) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len
));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
351 connection_struct
*conn
, struct ea_list
*ea_list
)
353 unsigned int ret_data_size
= 4;
356 SMB_ASSERT(total_data_size
>= 4);
358 if (!lp_ea_support(SNUM(conn
))) {
363 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
366 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
367 dos_namelen
= strlen(dos_ea_name
);
368 if (dos_namelen
> 255 || dos_namelen
== 0) {
371 if (ea_list
->ea
.value
.length
> 65535) {
374 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
378 /* We know we have room. */
379 SCVAL(p
,0,ea_list
->ea
.flags
);
380 SCVAL(p
,1,dos_namelen
);
381 SSVAL(p
,2,ea_list
->ea
.value
.length
);
382 fstrcpy(p
+4, dos_ea_name
);
383 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
385 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
386 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
389 ret_data_size
= PTR_DIFF(p
, pdata
);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
391 SIVAL(pdata
,0,ret_data_size
);
392 return ret_data_size
;
395 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
397 size_t total_ea_len
= 0;
398 TALLOC_CTX
*mem_ctx
= NULL
;
400 if (!lp_ea_support(SNUM(conn
))) {
403 mem_ctx
= talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
415 TALLOC_CTX
*mem_ctx
= talloc_tos();
416 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
418 for (; ea_list
; ea_list
= ea_list
->next
) {
419 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name
[5], ea_list
->ea
.name
));
422 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
434 if (!lp_ea_support(SNUM(conn
))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED
;
438 for (;ea_list
; ea_list
= ea_list
->next
) {
440 fstring unix_ea_name
;
442 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
445 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
449 if (samba_private_attr_name(unix_ea_name
)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
451 return NT_STATUS_ACCESS_DENIED
;
454 if (ea_list
->ea
.value
.length
== 0) {
455 /* Remove the attribute. */
456 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name
, fsp
->fsp_name
));
459 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name
, fname
));
463 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
466 /* Removing a non existent attribute always succeeds. */
467 if (ret
== -1 && errno
== ENOATTR
) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
474 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name
, fsp
->fsp_name
));
477 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
478 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name
, fname
));
482 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
483 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
489 if (errno
== ENOTSUP
) {
490 return NT_STATUS_EAS_NOT_SUPPORTED
;
493 return map_nt_error_from_unix(errno
);
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
505 struct ea_list
*ea_list_head
= NULL
;
506 size_t converted_size
, offset
= 0;
508 while (offset
+ 2 < data_size
) {
509 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
510 unsigned int namelen
= CVAL(pdata
,offset
);
512 offset
++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
516 (offset
> data_size
) || (namelen
> data_size
) ||
517 (offset
+ namelen
>= data_size
)) {
520 /* Ensure the name is null terminated. */
521 if (pdata
[offset
+ namelen
] != '\0') {
524 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno
)));
533 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
547 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
549 unsigned int namelen
;
550 size_t converted_size
;
560 eal
->ea
.flags
= CVAL(pdata
,0);
561 namelen
= CVAL(pdata
,1);
562 val_len
= SVAL(pdata
,2);
564 if (4 + namelen
+ 1 + val_len
> data_size
) {
568 /* Ensure the name is null terminated. */
569 if (pdata
[namelen
+ 4] != '\0') {
572 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
580 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
581 if (!eal
->ea
.value
.data
) {
585 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal
->ea
.value
.data
[val_len
] = '\0';
589 /* But don't count the null. */
590 eal
->ea
.value
.length
--;
593 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
597 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
608 struct ea_list
*ea_list_head
= NULL
;
610 size_t bytes_used
= 0;
612 while (offset
< data_size
) {
613 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
619 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
620 offset
+= bytes_used
;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list
*ealist
)
633 struct ea_list
*listp
;
636 for (listp
= ealist
; listp
; listp
= listp
->next
) {
637 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
638 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
640 /* Add on 4 for total length. */
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
656 struct ea_list
*nlistp
, *flistp
;
658 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
659 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
660 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
666 /* Copy the data from this entry. */
667 nlistp
->ea
.flags
= flistp
->ea
.flags
;
668 nlistp
->ea
.value
= flistp
->ea
.value
;
671 nlistp
->ea
.flags
= 0;
672 ZERO_STRUCT(nlistp
->ea
.value
);
676 *total_ea_len
= ea_list_size(name_list
);
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct
*conn
,
688 struct smb_request
*req
,
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send
= datasize
;
702 int params_to_send
= paramsize
;
704 const char *pp
= params
;
705 const char *pd
= pdata
;
706 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
707 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset
= 0;
709 bool overflow
= False
;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
716 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes
, datasize
));
719 datasize
= data_to_send
= max_data_bytes
;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send
== 0 && data_to_send
== 0) {
726 reply_outbuf(req
, 10, 0);
727 show_msg((char *)req
->outbuf
);
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
736 data_alignment_offset
= 4 - (params_to_send
% 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space
= max_send
- (smb_size
745 + data_alignment_offset
);
747 if (useable_space
< 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space
));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send
|| data_to_send
) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime
= params_to_send
+ data_to_send
;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
768 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
769 + data_alignment_offset
);
771 /* Set total params and data to be sent */
772 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
773 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime
= MIN(params_to_send
,useable_space
);
780 data_sent_thistime
= useable_space
- params_sent_thistime
;
781 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
783 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req
->outbuf
,smb_proff
,
791 ((smb_buf(req
->outbuf
)+alignment_offset
)
792 - smb_base(req
->outbuf
)));
794 if(params_sent_thistime
== 0)
795 SSVAL(req
->outbuf
,smb_prdisp
,0);
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
800 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
801 if(data_sent_thistime
== 0) {
802 SSVAL(req
->outbuf
,smb_droff
,0);
803 SSVAL(req
->outbuf
,smb_drdisp
, 0);
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req
->outbuf
, smb_droff
,
808 ((smb_buf(req
->outbuf
)+alignment_offset
)
809 - smb_base(req
->outbuf
))
810 + params_sent_thistime
+ data_alignment_offset
);
811 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
814 /* Initialize the padding for alignment */
816 if (alignment_offset
!= 0) {
817 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime
) {
823 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
824 params_sent_thistime
);
827 /* Copy in the data bytes */
828 if(data_sent_thistime
) {
829 if (data_alignment_offset
!= 0) {
830 memset((smb_buf(req
->outbuf
)+alignment_offset
+
831 params_sent_thistime
), 0,
832 data_alignment_offset
);
834 memcpy(smb_buf(req
->outbuf
)+alignment_offset
835 +params_sent_thistime
+data_alignment_offset
,
836 pd
,data_sent_thistime
);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime
, data_sent_thistime
, useable_space
));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send
, data_to_send
, paramsize
, datasize
));
845 error_packet_set((char *)req
->outbuf
,
846 ERRDOS
,ERRbufferoverflow
,
847 STATUS_BUFFER_OVERFLOW
,
851 /* Send the packet */
852 show_msg((char *)req
->outbuf
);
853 if (!srv_send_smb(smbd_server_fd(),
855 IS_CONN_ENCRYPTED(conn
)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req
->outbuf
);
860 pp
+= params_sent_thistime
;
861 pd
+= data_sent_thistime
;
863 params_to_send
-= params_sent_thistime
;
864 data_to_send
-= data_sent_thistime
;
867 if(params_to_send
< 0 || data_to_send
< 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send
, data_to_send
));
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct
*conn
,
882 struct smb_request
*req
,
883 char **pparams
, int total_params
,
884 char **ppdata
, int total_data
,
885 unsigned int max_data_bytes
)
887 char *params
= *pparams
;
888 char *pdata
= *ppdata
;
893 bool return_additional_info
;
904 SMB_STRUCT_STAT sbuf
;
907 struct ea_list
*ea_list
= NULL
;
912 uint32 create_disposition
;
913 uint32 create_options
= 0;
914 TALLOC_CTX
*ctx
= talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params
< 29) {
921 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
925 flags
= SVAL(params
, 0);
926 deny_mode
= SVAL(params
, 2);
927 open_attr
= SVAL(params
,6);
928 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
929 if (oplock_request
) {
930 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
934 return_additional_info
= BITSETW(params
,0);
935 open_sattr
= SVAL(params
, 4);
936 open_time
= make_unix_date3(params
+8);
938 open_ofun
= SVAL(params
,12);
939 open_size
= IVAL(params
,14);
943 reply_doserror(req
, ERRSRV
, ERRaccess
);
947 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
948 total_params
- 28, STR_TERMINATE
,
950 if (!NT_STATUS_IS_OK(status
)) {
951 reply_nterror(req
, status
);
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
957 (unsigned int)open_ofun
, open_size
));
959 if (open_ofun
== 0) {
960 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
964 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
969 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
973 /* Any data in this call is an EA list. */
974 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
975 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
979 if (total_data
!= 4) {
980 if (total_data
< 10) {
981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
985 if (IVAL(pdata
,0) > total_data
) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata
,0), (unsigned int)total_data
));
988 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
992 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
995 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
998 } else if (IVAL(pdata
,0) != 4) {
999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1003 status
= create_file(conn
, /* conn */
1005 0, /* root_dir_fid */
1007 access_mask
, /* access_mask */
1008 share_mode
, /* share_access */
1009 create_disposition
, /* create_disposition*/
1010 create_options
, /* create_options */
1011 open_attr
, /* file_attributes */
1012 oplock_request
, /* oplock_request */
1013 open_size
, /* allocation_size */
1015 ea_list
, /* ea_list */
1017 &smb_action
, /* pinfo */
1020 if (!NT_STATUS_IS_OK(status
)) {
1021 if (open_was_deferred(req
->mid
)) {
1022 /* We have re-scheduled this call. */
1025 reply_openerror(req
, status
);
1029 size
= get_file_size(sbuf
);
1030 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1031 mtime
= sbuf
.st_mtime
;
1032 inode
= sbuf
.st_ino
;
1034 close_file(fsp
,ERROR_CLOSE
);
1035 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1041 if(*pparams
== NULL
) {
1042 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1047 SSVAL(params
,0,fsp
->fnum
);
1048 SSVAL(params
,2,fattr
);
1049 srv_put_dos_date2(params
,4, mtime
);
1050 SIVAL(params
,8, (uint32
)size
);
1051 SSVAL(params
,12,deny_mode
);
1052 SSVAL(params
,14,0); /* open_type - file or directory. */
1053 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1056 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1059 SSVAL(params
,18,smb_action
);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params
,20,inode
);
1065 SSVAL(params
,24,0); /* Padding. */
1067 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1068 SIVAL(params
, 26, ea_size
);
1070 SIVAL(params
, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct
*conn
,
1088 if (mask
[0] == '.' && mask
[1] == 0)
1090 if (dptr_has_wild(conn
->dirptr
)) {
1093 if (conn
->case_sensitive
)
1094 return strcmp(str
,mask
)==0;
1096 return StrCaseCmp(str
,mask
) == 0;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32
unix_filetype(mode_t mode
)
1106 return UNIX_TYPE_FILE
;
1107 else if(S_ISDIR(mode
))
1108 return UNIX_TYPE_DIR
;
1110 else if(S_ISLNK(mode
))
1111 return UNIX_TYPE_SYMLINK
;
1114 else if(S_ISCHR(mode
))
1115 return UNIX_TYPE_CHARDEV
;
1118 else if(S_ISBLK(mode
))
1119 return UNIX_TYPE_BLKDEV
;
1122 else if(S_ISFIFO(mode
))
1123 return UNIX_TYPE_FIFO
;
1126 else if(S_ISSOCK(mode
))
1127 return UNIX_TYPE_SOCKET
;
1130 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1131 return UNIX_TYPE_UNKNOWN
;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1140 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1141 SMB_STRUCT_STAT
*psbuf
,
1143 enum perm_type ptype
,
1148 if (perms
== SMB_MODE_NO_CHANGE
) {
1149 if (!VALID_STAT(*psbuf
)) {
1150 return NT_STATUS_INVALID_PARAMETER
;
1152 *ret_perms
= psbuf
->st_mode
;
1153 return NT_STATUS_OK
;
1157 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1158 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1159 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1160 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1161 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1162 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1163 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1164 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1165 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1167 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1170 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1173 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1178 /* Apply mode mask */
1179 ret
&= lp_create_mask(SNUM(conn
));
1180 /* Add in force bits */
1181 ret
|= lp_force_create_mode(SNUM(conn
));
1184 ret
&= lp_dir_mask(SNUM(conn
));
1185 /* Add in force bits */
1186 ret
|= lp_force_dir_mode(SNUM(conn
));
1188 case PERM_EXISTING_FILE
:
1189 /* Apply mode mask */
1190 ret
&= lp_security_mask(SNUM(conn
));
1191 /* Add in force bits */
1192 ret
|= lp_force_security_mode(SNUM(conn
));
1194 case PERM_EXISTING_DIR
:
1195 /* Apply mode mask */
1196 ret
&= lp_dir_security_mask(SNUM(conn
));
1197 /* Add in force bits */
1198 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1203 return NT_STATUS_OK
;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct
*conn
,
1212 const char *pathname
,
1213 SMB_STRUCT_STAT
*psbuf
)
1215 int saved_errno
= errno
;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn
)) &&
1218 is_msdfs_link(conn
, pathname
, psbuf
)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1223 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1224 errno
= saved_errno
;
1227 errno
= saved_errno
;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1237 connection_struct
*conn
,
1239 const char *path_mask
,
1242 int requires_resume_key
,
1248 int space_remaining
,
1250 bool *got_exact_match
,
1251 int *last_entry_off
,
1252 struct ea_list
*name_list
)
1256 SMB_STRUCT_STAT sbuf
;
1257 const char *mask
= NULL
;
1258 char *pathreal
= NULL
;
1259 const char *fname
= NULL
;
1260 char *p
, *q
, *pdata
= *ppdata
;
1264 SMB_OFF_T file_size
= 0;
1265 SMB_BIG_UINT allocation_size
= 0;
1267 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1268 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1270 char *last_entry_ptr
;
1272 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1273 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1274 bool check_mangled_names
= lp_manglednames(conn
->params
);
1275 char mangled_name
[13]; /* mangled 8.3 name. */
1277 *out_of_space
= False
;
1278 *got_exact_match
= False
;
1280 ZERO_STRUCT(mdate_ts
);
1281 ZERO_STRUCT(adate_ts
);
1282 ZERO_STRUCT(create_date_ts
);
1284 if (!conn
->dirptr
) {
1288 p
= strrchr_m(path_mask
,'/');
1291 mask
= talloc_strdup(ctx
,"*.*");
1301 bool ms_dfs_link
= False
;
1303 /* Needed if we run out of space */
1304 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1305 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1308 * Due to bugs in NT client redirectors we are not using
1309 * resume keys any more - set them to zero.
1310 * Check out the related comments in findfirst/findnext.
1316 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1317 (long)conn
->dirptr
,curr_dirpos
));
1324 * fname may get mangled, dname is never mangled.
1325 * Whenever we're accessing the filesystem we use
1326 * pathreal which is composed from dname.
1332 /* Mangle fname if it's an illegal name. */
1333 if (mangle_must_mangle(dname
,conn
->params
)) {
1334 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1335 continue; /* Error - couldn't mangle. */
1337 fname
= mangled_name
;
1340 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1341 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1344 if(!got_match
&& check_mangled_names
&&
1345 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1347 * It turns out that NT matches wildcards against
1348 * both long *and* short names. This may explain some
1349 * of the wildcard wierdness from old DOS clients
1350 * that some people have been seeing.... JRA.
1352 /* Force the mangling into 8.3. */
1353 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1354 continue; /* Error - couldn't mangle. */
1357 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1358 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1363 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1365 if (dont_descend
&& !isdots
) {
1371 pathreal
= talloc_asprintf(ctx
,
1376 pathreal
= talloc_asprintf(ctx
,
1386 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1387 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal
,strerror(errno
)));
1390 TALLOC_FREE(pathreal
);
1393 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1394 /* Needed to show the msdfs symlinks as
1397 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1400 pathreal
,strerror(errno
)));
1401 TALLOC_FREE(pathreal
);
1407 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1409 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1412 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1413 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1414 TALLOC_FREE(pathreal
);
1418 if (!(mode
& aDIR
)) {
1419 file_size
= get_file_size(sbuf
);
1421 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1423 mdate_ts
= get_mtimespec(&sbuf
);
1424 adate_ts
= get_atimespec(&sbuf
);
1425 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1427 if (ask_sharemode
) {
1428 struct timespec write_time_ts
;
1429 struct file_id fileid
;
1431 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1432 get_file_infos(fileid
, NULL
, &write_time_ts
);
1433 if (!null_timespec(write_time_ts
)) {
1434 mdate_ts
= write_time_ts
;
1438 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1439 dos_filetime_timespec(&create_date_ts
);
1440 dos_filetime_timespec(&mdate_ts
);
1441 dos_filetime_timespec(&adate_ts
);
1444 create_date
= convert_timespec_to_time_t(create_date_ts
);
1445 mdate
= convert_timespec_to_time_t(mdate_ts
);
1446 adate
= convert_timespec_to_time_t(adate_ts
);
1448 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1452 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1459 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1461 switch (info_level
) {
1462 case SMB_FIND_INFO_STANDARD
:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key
) {
1468 srv_put_dos_date2(p
,0,create_date
);
1469 srv_put_dos_date2(p
,4,adate
);
1470 srv_put_dos_date2(p
,8,mdate
);
1471 SIVAL(p
,12,(uint32
)file_size
);
1472 SIVAL(p
,16,(uint32
)allocation_size
);
1476 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1477 p
+= ucs2_align(base_data
, p
, 0);
1479 len
= srvstr_push(base_data
, flags2
, p
,
1480 fname
, PTR_DIFF(end_data
, p
),
1482 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1484 SCVAL(nameptr
, -1, len
- 2);
1486 SCVAL(nameptr
, -1, 0);
1490 SCVAL(nameptr
, -1, len
- 1);
1492 SCVAL(nameptr
, -1, 0);
1498 case SMB_FIND_EA_SIZE
:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key
) {
1504 srv_put_dos_date2(p
,0,create_date
);
1505 srv_put_dos_date2(p
,4,adate
);
1506 srv_put_dos_date2(p
,8,mdate
);
1507 SIVAL(p
,12,(uint32
)file_size
);
1508 SIVAL(p
,16,(uint32
)allocation_size
);
1511 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1512 SIVAL(p
,22,ea_size
); /* Extended attributes */
1516 len
= srvstr_push(base_data
, flags2
,
1517 p
, fname
, PTR_DIFF(end_data
, p
),
1518 STR_TERMINATE
| STR_NOALIGN
);
1519 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1532 SCVAL(nameptr
,0,len
);
1534 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1537 case SMB_FIND_EA_LIST
:
1539 struct ea_list
*file_list
= NULL
;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1546 if(requires_resume_key
) {
1550 srv_put_dos_date2(p
,0,create_date
);
1551 srv_put_dos_date2(p
,4,adate
);
1552 srv_put_dos_date2(p
,8,mdate
);
1553 SIVAL(p
,12,(uint32
)file_size
);
1554 SIVAL(p
,16,(uint32
)allocation_size
);
1556 p
+= 22; /* p now points to the EA area. */
1558 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1559 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1566 *out_of_space
= True
;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False
; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1574 len
= srvstr_push(base_data
, flags2
,
1575 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1576 STR_TERMINATE
| STR_NOALIGN
);
1577 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1590 SCVAL(nameptr
,0,len
);
1592 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1600 SIVAL(p
,0,reskey
); p
+= 4;
1601 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1602 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1603 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1604 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1605 SOFF_T(p
,0,file_size
); p
+= 8;
1606 SOFF_T(p
,0,allocation_size
); p
+= 8;
1607 SIVAL(p
,0,nt_extmode
); p
+= 4;
1608 q
= p
; p
+= 4; /* q is placeholder for name length. */
1610 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1611 SIVAL(p
,0,ea_size
); /* Extended attributes */
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3
&& check_mangled_names
) {
1619 if (!name_to_8_3(fname
,mangled_name
,True
,
1621 /* Error - mangle failed ! */
1622 memset(mangled_name
,'\0',12);
1624 mangled_name
[12] = 0;
1625 len
= srvstr_push(base_data
, flags2
,
1626 p
+2, mangled_name
, 24,
1627 STR_UPPER
|STR_UNICODE
);
1629 memset(p
+ 2 + len
,'\0',24 - len
);
1636 len
= srvstr_push(base_data
, flags2
, p
,
1637 fname
, PTR_DIFF(end_data
, p
),
1638 STR_TERMINATE_ASCII
);
1641 SIVAL(p
,0,0); /* Ensure any padding is null. */
1642 len
= PTR_DIFF(p
, pdata
);
1643 len
= (len
+ 3) & ~3;
1648 case SMB_FIND_FILE_DIRECTORY_INFO
:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1651 SIVAL(p
,0,reskey
); p
+= 4;
1652 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1653 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1654 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1655 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1656 SOFF_T(p
,0,file_size
); p
+= 8;
1657 SOFF_T(p
,0,allocation_size
); p
+= 8;
1658 SIVAL(p
,0,nt_extmode
); p
+= 4;
1659 len
= srvstr_push(base_data
, flags2
,
1660 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1661 STR_TERMINATE_ASCII
);
1664 SIVAL(p
,0,0); /* Ensure any padding is null. */
1665 len
= PTR_DIFF(p
, pdata
);
1666 len
= (len
+ 3) & ~3;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1674 SIVAL(p
,0,reskey
); p
+= 4;
1675 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1676 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1677 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1678 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1679 SOFF_T(p
,0,file_size
); p
+= 8;
1680 SOFF_T(p
,0,allocation_size
); p
+= 8;
1681 SIVAL(p
,0,nt_extmode
); p
+= 4;
1682 q
= p
; p
+= 4; /* q is placeholder for name length. */
1684 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1685 SIVAL(p
,0,ea_size
); /* Extended attributes */
1688 len
= srvstr_push(base_data
, flags2
, p
,
1689 fname
, PTR_DIFF(end_data
, p
),
1690 STR_TERMINATE_ASCII
);
1694 SIVAL(p
,0,0); /* Ensure any padding is null. */
1695 len
= PTR_DIFF(p
, pdata
);
1696 len
= (len
+ 3) & ~3;
1701 case SMB_FIND_FILE_NAMES_INFO
:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1704 SIVAL(p
,0,reskey
); p
+= 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len
= srvstr_push(base_data
, flags2
, p
,
1709 fname
, PTR_DIFF(end_data
, p
),
1710 STR_TERMINATE_ASCII
);
1713 SIVAL(p
,0,0); /* Ensure any padding is null. */
1714 len
= PTR_DIFF(p
, pdata
);
1715 len
= (len
+ 3) & ~3;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1723 SIVAL(p
,0,reskey
); p
+= 4;
1724 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1725 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1726 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1727 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1728 SOFF_T(p
,0,file_size
); p
+= 8;
1729 SOFF_T(p
,0,allocation_size
); p
+= 8;
1730 SIVAL(p
,0,nt_extmode
); p
+= 4;
1731 q
= p
; p
+= 4; /* q is placeholder for name length. */
1733 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1734 SIVAL(p
,0,ea_size
); /* Extended attributes */
1737 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1738 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1739 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1740 len
= srvstr_push(base_data
, flags2
, p
,
1741 fname
, PTR_DIFF(end_data
, p
),
1742 STR_TERMINATE_ASCII
);
1745 SIVAL(p
,0,0); /* Ensure any padding is null. */
1746 len
= PTR_DIFF(p
, pdata
);
1747 len
= (len
+ 3) & ~3;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1756 SIVAL(p
,0,reskey
); p
+= 4;
1757 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1758 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1759 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1760 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1761 SOFF_T(p
,0,file_size
); p
+= 8;
1762 SOFF_T(p
,0,allocation_size
); p
+= 8;
1763 SIVAL(p
,0,nt_extmode
); p
+= 4;
1764 q
= p
; p
+= 4; /* q is placeholder for name length */
1766 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1767 SIVAL(p
,0,ea_size
); /* Extended attributes */
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3
&& check_mangled_names
) {
1775 if (!name_to_8_3(fname
,mangled_name
,True
,
1777 /* Error - mangle failed ! */
1778 memset(mangled_name
,'\0',12);
1780 mangled_name
[12] = 0;
1781 len
= srvstr_push(base_data
, flags2
,
1782 p
+2, mangled_name
, 24,
1783 STR_UPPER
|STR_UNICODE
);
1786 memset(p
+ 2 + len
,'\0',24 - len
);
1793 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1794 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1795 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1796 len
= srvstr_push(base_data
, flags2
, p
,
1797 fname
, PTR_DIFF(end_data
, p
),
1798 STR_TERMINATE_ASCII
);
1801 SIVAL(p
,0,0); /* Ensure any padding is null. */
1802 len
= PTR_DIFF(p
, pdata
);
1803 len
= (len
+ 3) & ~3;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX
:
1811 case SMB_FIND_FILE_UNIX_INFO2
:
1813 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level
== SMB_FIND_FILE_UNIX
) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p
= store_file_unix_basic(conn
, p
,
1821 len
= srvstr_push(base_data
, flags2
, p
,
1822 fname
, PTR_DIFF(end_data
, p
),
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p
= store_file_unix_basic_info2(conn
, p
,
1830 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1831 PTR_DIFF(end_data
, p
), 0);
1832 SIVAL(nameptr
, 0, len
);
1836 SIVAL(p
,0,0); /* Ensure any padding is null. */
1838 len
= PTR_DIFF(p
, pdata
);
1839 len
= (len
+ 3) & ~3;
1840 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1851 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1852 /* Move the dirptr back to prev_dirpos */
1853 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1854 *out_of_space
= True
;
1855 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1856 return False
; /* Not finished - just out of space */
1859 /* Setup the last entry pointer, as an offset from base_data */
1860 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1861 /* Advance the data pointer to the next slot */
1867 /****************************************************************************
1868 Reply to a TRANS2_FINDFIRST.
1869 ****************************************************************************/
1871 static void call_trans2findfirst(connection_struct
*conn
,
1872 struct smb_request
*req
,
1873 char **pparams
, int total_params
,
1874 char **ppdata
, int total_data
,
1875 unsigned int max_data_bytes
)
1877 /* We must be careful here that we don't return more than the
1878 allowed number of data bytes. If this means returning fewer than
1879 maxentries then so be it. We assume that the redirector has
1880 enough room for the fixed number of parameter bytes it has
1882 char *params
= *pparams
;
1883 char *pdata
= *ppdata
;
1887 uint16 findfirst_flags
;
1888 bool close_after_first
;
1890 bool requires_resume_key
;
1892 char *directory
= NULL
;
1895 int last_entry_off
=0;
1899 bool finished
= False
;
1900 bool dont_descend
= False
;
1901 bool out_of_space
= False
;
1902 int space_remaining
;
1903 bool mask_contains_wcard
= False
;
1904 SMB_STRUCT_STAT sbuf
;
1905 struct ea_list
*ea_list
= NULL
;
1906 NTSTATUS ntstatus
= NT_STATUS_OK
;
1907 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1908 TALLOC_CTX
*ctx
= talloc_tos();
1910 if (total_params
< 13) {
1911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1915 dirtype
= SVAL(params
,0);
1916 maxentries
= SVAL(params
,2);
1917 findfirst_flags
= SVAL(params
,4);
1918 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1919 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1920 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1921 info_level
= SVAL(params
,6);
1923 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1924 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1925 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1926 info_level
, max_data_bytes
));
1929 /* W2K3 seems to treat zero as 1. */
1933 switch (info_level
) {
1934 case SMB_FIND_INFO_STANDARD
:
1935 case SMB_FIND_EA_SIZE
:
1936 case SMB_FIND_EA_LIST
:
1937 case SMB_FIND_FILE_DIRECTORY_INFO
:
1938 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1939 case SMB_FIND_FILE_NAMES_INFO
:
1940 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1942 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1944 case SMB_FIND_FILE_UNIX
:
1945 case SMB_FIND_FILE_UNIX_INFO2
:
1946 /* Always use filesystem for UNIX mtime query. */
1947 ask_sharemode
= false;
1948 if (!lp_unix_extensions()) {
1949 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1954 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1958 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1959 params
+12, total_params
- 12,
1960 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1961 if (!NT_STATUS_IS_OK(ntstatus
)) {
1962 reply_nterror(req
, ntstatus
);
1966 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1967 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1970 &mask_contains_wcard
);
1971 if (!NT_STATUS_IS_OK(ntstatus
)) {
1972 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1973 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1974 ERRSRV
, ERRbadpath
);
1977 reply_nterror(req
, ntstatus
);
1981 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, &mask
, &sbuf
);
1982 if (!NT_STATUS_IS_OK(ntstatus
)) {
1983 reply_nterror(req
, ntstatus
);
1987 ntstatus
= check_name(conn
, directory
);
1988 if (!NT_STATUS_IS_OK(ntstatus
)) {
1989 reply_nterror(req
, ntstatus
);
1993 p
= strrchr_m(directory
,'/');
1995 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1996 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1997 mask
= talloc_strdup(ctx
,"*");
1999 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2002 mask_contains_wcard
= True
;
2004 directory
= talloc_strdup(talloc_tos(), "./");
2006 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2013 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2015 if (info_level
== SMB_FIND_EA_LIST
) {
2018 if (total_data
< 4) {
2019 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2023 ea_size
= IVAL(pdata
,0);
2024 if (ea_size
!= total_data
) {
2025 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2026 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2027 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2031 if (!lp_ea_support(SNUM(conn
))) {
2032 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2036 /* Pull out the list of names. */
2037 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2039 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2044 *ppdata
= (char *)SMB_REALLOC(
2045 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2046 if(*ppdata
== NULL
) {
2047 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2051 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2053 /* Realloc the params space */
2054 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2055 if (*pparams
== NULL
) {
2056 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2061 /* Save the wildcard match and attribs we are using on this directory -
2062 needed as lanman2 assumes these are being saved between calls */
2064 ntstatus
= dptr_create(conn
,
2070 mask_contains_wcard
,
2074 if (!NT_STATUS_IS_OK(ntstatus
)) {
2075 reply_nterror(req
, ntstatus
);
2079 dptr_num
= dptr_dnum(conn
->dirptr
);
2080 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2082 /* We don't need to check for VOL here as this is returned by
2083 a different TRANS2 call. */
2085 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2086 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2087 dont_descend
= True
;
2090 space_remaining
= max_data_bytes
;
2091 out_of_space
= False
;
2093 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2094 bool got_exact_match
= False
;
2096 /* this is a heuristic to avoid seeking the dirptr except when
2097 absolutely necessary. It allows for a filename of about 40 chars */
2098 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2099 out_of_space
= True
;
2102 finished
= !get_lanman2_dir_entry(ctx
,
2105 mask
,dirtype
,info_level
,
2106 requires_resume_key
,dont_descend
,
2109 space_remaining
, &out_of_space
,
2111 &last_entry_off
, ea_list
);
2114 if (finished
&& out_of_space
)
2117 if (!finished
&& !out_of_space
)
2121 * As an optimisation if we know we aren't looking
2122 * for a wildcard name (ie. the name matches the wildcard exactly)
2123 * then we can finish on any (first) match.
2124 * This speeds up large directory searches. JRA.
2130 /* Ensure space_remaining never goes -ve. */
2131 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2132 space_remaining
= 0;
2133 out_of_space
= true;
2135 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2139 /* Check if we can close the dirptr */
2140 if(close_after_first
|| (finished
&& close_if_end
)) {
2141 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2142 dptr_close(&dptr_num
);
2146 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2147 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2148 * the protocol level is less than NT1. Tested with smbclient. JRA.
2149 * This should fix the OS/2 client bug #2335.
2152 if(numentries
== 0) {
2153 dptr_close(&dptr_num
);
2154 if (Protocol
< PROTOCOL_NT1
) {
2155 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2158 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2159 ERRDOS
, ERRbadfile
);
2164 /* At this point pdata points to numentries directory entries. */
2166 /* Set up the return parameter block */
2167 SSVAL(params
,0,dptr_num
);
2168 SSVAL(params
,2,numentries
);
2169 SSVAL(params
,4,finished
);
2170 SSVAL(params
,6,0); /* Never an EA error */
2171 SSVAL(params
,8,last_entry_off
);
2173 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2176 if ((! *directory
) && dptr_path(dptr_num
)) {
2177 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2179 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2183 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2184 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2185 mask
, directory
, dirtype
, numentries
) );
2188 * Force a name mangle here to ensure that the
2189 * mask as an 8.3 name is top of the mangled cache.
2190 * The reasons for this are subtle. Don't remove
2191 * this code unless you know what you are doing
2192 * (see PR#13758). JRA.
2195 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2196 char mangled_name
[13];
2197 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2203 /****************************************************************************
2204 Reply to a TRANS2_FINDNEXT.
2205 ****************************************************************************/
2207 static void call_trans2findnext(connection_struct
*conn
,
2208 struct smb_request
*req
,
2209 char **pparams
, int total_params
,
2210 char **ppdata
, int total_data
,
2211 unsigned int max_data_bytes
)
2213 /* We must be careful here that we don't return more than the
2214 allowed number of data bytes. If this means returning fewer than
2215 maxentries then so be it. We assume that the redirector has
2216 enough room for the fixed number of parameter bytes it has
2218 char *params
= *pparams
;
2219 char *pdata
= *ppdata
;
2225 uint16 findnext_flags
;
2226 bool close_after_request
;
2228 bool requires_resume_key
;
2230 bool mask_contains_wcard
= False
;
2231 char *resume_name
= NULL
;
2232 const char *mask
= NULL
;
2233 const char *directory
= NULL
;
2237 int i
, last_entry_off
=0;
2238 bool finished
= False
;
2239 bool dont_descend
= False
;
2240 bool out_of_space
= False
;
2241 int space_remaining
;
2242 struct ea_list
*ea_list
= NULL
;
2243 NTSTATUS ntstatus
= NT_STATUS_OK
;
2244 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2245 TALLOC_CTX
*ctx
= talloc_tos();
2247 if (total_params
< 13) {
2248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2252 dptr_num
= SVAL(params
,0);
2253 maxentries
= SVAL(params
,2);
2254 info_level
= SVAL(params
,4);
2255 resume_key
= IVAL(params
,6);
2256 findnext_flags
= SVAL(params
,10);
2257 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2258 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2259 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2260 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2262 if (!continue_bit
) {
2263 /* We only need resume_name if continue_bit is zero. */
2264 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2266 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2267 &mask_contains_wcard
);
2268 if (!NT_STATUS_IS_OK(ntstatus
)) {
2269 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2270 complain (it thinks we're asking for the directory above the shared
2271 path or an invalid name). Catch this as the resume name is only compared, never used in
2272 a file access. JRA. */
2273 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2274 &resume_name
, params
+12,
2278 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2279 reply_nterror(req
, ntstatus
);
2285 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2286 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2287 resume_key = %d resume name = %s continue=%d level = %d\n",
2288 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2289 requires_resume_key
, resume_key
,
2290 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2293 /* W2K3 seems to treat zero as 1. */
2297 switch (info_level
) {
2298 case SMB_FIND_INFO_STANDARD
:
2299 case SMB_FIND_EA_SIZE
:
2300 case SMB_FIND_EA_LIST
:
2301 case SMB_FIND_FILE_DIRECTORY_INFO
:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2303 case SMB_FIND_FILE_NAMES_INFO
:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2308 case SMB_FIND_FILE_UNIX
:
2309 case SMB_FIND_FILE_UNIX_INFO2
:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode
= false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2318 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2322 if (info_level
== SMB_FIND_EA_LIST
) {
2325 if (total_data
< 4) {
2326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2330 ea_size
= IVAL(pdata
,0);
2331 if (ea_size
!= total_data
) {
2332 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2334 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2338 if (!lp_ea_support(SNUM(conn
))) {
2339 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2343 /* Pull out the list of names. */
2344 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2351 *ppdata
= (char *)SMB_REALLOC(
2352 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2353 if(*ppdata
== NULL
) {
2354 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2359 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2361 /* Realloc the params space */
2362 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2363 if(*pparams
== NULL
) {
2364 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2370 /* Check that the dptr is valid */
2371 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2372 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2376 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2378 /* Get the wildcard mask from the dptr */
2379 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2380 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2381 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2386 directory
= conn
->dirpath
;
2388 /* Get the attr mask from the dptr */
2389 dirtype
= dptr_attr(dptr_num
);
2391 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392 dptr_num
, mask
, dirtype
,
2394 dptr_TellDir(conn
->dirptr
)));
2396 /* We don't need to check for VOL here as this is returned by
2397 a different TRANS2 call. */
2399 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2400 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2401 dont_descend
= True
;
2404 space_remaining
= max_data_bytes
;
2405 out_of_space
= False
;
2408 * Seek to the correct position. We no longer use the resume key but
2409 * depend on the last file name instead.
2412 if(!continue_bit
&& resume_name
&& *resume_name
) {
2415 long current_pos
= 0;
2417 * Remember, name_to_8_3 is called by
2418 * get_lanman2_dir_entry(), so the resume name
2419 * could be mangled. Ensure we check the unmangled name.
2422 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2423 char *new_resume_name
= NULL
;
2424 mangle_lookup_name_from_8_3(ctx
,
2428 if (new_resume_name
) {
2429 resume_name
= new_resume_name
;
2434 * Fix for NT redirector problem triggered by resume key indexes
2435 * changing between directory scans. We now return a resume key of 0
2436 * and instead look for the filename to continue from (also given
2437 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2438 * findfirst/findnext (as is usual) then the directory pointer
2439 * should already be at the correct place.
2442 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2443 } /* end if resume_name && !continue_bit */
2445 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2446 bool got_exact_match
= False
;
2448 /* this is a heuristic to avoid seeking the dirptr except when
2449 absolutely necessary. It allows for a filename of about 40 chars */
2450 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2451 out_of_space
= True
;
2454 finished
= !get_lanman2_dir_entry(ctx
,
2457 mask
,dirtype
,info_level
,
2458 requires_resume_key
,dont_descend
,
2461 space_remaining
, &out_of_space
,
2463 &last_entry_off
, ea_list
);
2466 if (finished
&& out_of_space
)
2469 if (!finished
&& !out_of_space
)
2473 * As an optimisation if we know we aren't looking
2474 * for a wildcard name (ie. the name matches the wildcard exactly)
2475 * then we can finish on any (first) match.
2476 * This speeds up large directory searches. JRA.
2482 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2485 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2486 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2487 mask
, directory
, dirtype
, numentries
) );
2489 /* Check if we can close the dirptr */
2490 if(close_after_request
|| (finished
&& close_if_end
)) {
2491 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2492 dptr_close(&dptr_num
); /* This frees up the saved mask */
2495 /* Set up the return parameter block */
2496 SSVAL(params
,0,numentries
);
2497 SSVAL(params
,2,finished
);
2498 SSVAL(params
,4,0); /* Never an EA error */
2499 SSVAL(params
,6,last_entry_off
);
2501 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2507 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2509 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2513 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2515 SMB_ASSERT(extended_info
!= NULL
);
2517 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2518 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2519 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2520 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2521 #ifdef SAMBA_VERSION_REVISION
2522 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2524 extended_info
->samba_subversion
= 0;
2525 #ifdef SAMBA_VERSION_RC_RELEASE
2526 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2528 #ifdef SAMBA_VERSION_PRE_RELEASE
2529 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2532 #ifdef SAMBA_VERSION_VENDOR_PATCH
2533 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2535 extended_info
->samba_gitcommitdate
= 0;
2536 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2537 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2540 memset(extended_info
->samba_version_string
, 0,
2541 sizeof(extended_info
->samba_version_string
));
2543 snprintf (extended_info
->samba_version_string
,
2544 sizeof(extended_info
->samba_version_string
),
2545 "%s", samba_version_string());
2548 /****************************************************************************
2549 Reply to a TRANS2_QFSINFO (query filesystem info).
2550 ****************************************************************************/
2552 static void call_trans2qfsinfo(connection_struct
*conn
,
2553 struct smb_request
*req
,
2554 char **pparams
, int total_params
,
2555 char **ppdata
, int total_data
,
2556 unsigned int max_data_bytes
)
2558 char *pdata
, *end_data
;
2559 char *params
= *pparams
;
2563 const char *vname
= volume_label(SNUM(conn
));
2564 int snum
= SNUM(conn
);
2565 char *fstype
= lp_fstype(SNUM(conn
));
2566 uint32 additional_flags
= 0;
2568 if (total_params
< 2) {
2569 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2573 info_level
= SVAL(params
,0);
2576 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2577 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2578 "info level (0x%x) on IPC$.\n",
2579 (unsigned int)info_level
));
2580 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2585 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2586 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2587 DEBUG(0,("call_trans2qfsinfo: encryption required "
2588 "and info level 0x%x sent.\n",
2589 (unsigned int)info_level
));
2590 exit_server_cleanly("encryption required "
2596 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2598 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2599 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2600 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2604 *ppdata
= (char *)SMB_REALLOC(
2605 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2606 if (*ppdata
== NULL
) {
2607 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2612 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2613 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2615 switch (info_level
) {
2616 case SMB_INFO_ALLOCATION
:
2618 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2620 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2621 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2625 block_size
= lp_block_size(snum
);
2626 if (bsize
< block_size
) {
2627 SMB_BIG_UINT factor
= block_size
/bsize
;
2632 if (bsize
> block_size
) {
2633 SMB_BIG_UINT factor
= bsize
/block_size
;
2638 bytes_per_sector
= 512;
2639 sectors_per_unit
= bsize
/bytes_per_sector
;
2641 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2642 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2643 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2645 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2646 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2647 SIVAL(pdata
,l1_cUnit
,dsize
);
2648 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2649 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2653 case SMB_INFO_VOLUME
:
2654 /* Return volume name */
2656 * Add volume serial number - hash of a combination of
2657 * the called hostname and the service name.
2659 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2661 * Win2k3 and previous mess this up by sending a name length
2662 * one byte short. I believe only older clients (OS/2 Win9x) use
2663 * this call so try fixing this by adding a terminating null to
2664 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2668 pdata
+l2_vol_szVolLabel
, vname
,
2669 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2670 STR_NOALIGN
|STR_TERMINATE
);
2671 SCVAL(pdata
,l2_vol_cch
,len
);
2672 data_len
= l2_vol_szVolLabel
+ len
;
2673 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2674 (unsigned)st
.st_ctime
, len
, vname
));
2677 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2678 case SMB_FS_ATTRIBUTE_INFORMATION
:
2680 additional_flags
= 0;
2681 #if defined(HAVE_SYS_QUOTAS)
2682 additional_flags
|= FILE_VOLUME_QUOTAS
;
2685 if(lp_nt_acl_support(SNUM(conn
))) {
2686 additional_flags
|= FILE_PERSISTENT_ACLS
;
2689 /* Capabilities are filled in at connection time through STATVFS call */
2690 additional_flags
|= conn
->fs_capabilities
;
2692 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2693 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2694 additional_flags
); /* FS ATTRIBUTES */
2696 SIVAL(pdata
,4,255); /* Max filename component length */
2697 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2698 and will think we can't do long filenames */
2699 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2700 PTR_DIFF(end_data
, pdata
+12),
2703 data_len
= 12 + len
;
2706 case SMB_QUERY_FS_LABEL_INFO
:
2707 case SMB_FS_LABEL_INFORMATION
:
2708 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2709 PTR_DIFF(end_data
, pdata
+4), 0);
2714 case SMB_QUERY_FS_VOLUME_INFO
:
2715 case SMB_FS_VOLUME_INFORMATION
:
2718 * Add volume serial number - hash of a combination of
2719 * the called hostname and the service name.
2721 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2722 (str_checksum(get_local_machine_name())<<16));
2724 /* Max label len is 32 characters. */
2725 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2726 PTR_DIFF(end_data
, pdata
+18),
2728 SIVAL(pdata
,12,len
);
2731 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2732 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2735 case SMB_QUERY_FS_SIZE_INFO
:
2736 case SMB_FS_SIZE_INFORMATION
:
2738 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2740 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2741 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2744 block_size
= lp_block_size(snum
);
2745 if (bsize
< block_size
) {
2746 SMB_BIG_UINT factor
= block_size
/bsize
;
2751 if (bsize
> block_size
) {
2752 SMB_BIG_UINT factor
= bsize
/block_size
;
2757 bytes_per_sector
= 512;
2758 sectors_per_unit
= bsize
/bytes_per_sector
;
2759 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2760 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2761 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2762 SBIG_UINT(pdata
,0,dsize
);
2763 SBIG_UINT(pdata
,8,dfree
);
2764 SIVAL(pdata
,16,sectors_per_unit
);
2765 SIVAL(pdata
,20,bytes_per_sector
);
2769 case SMB_FS_FULL_SIZE_INFORMATION
:
2771 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2773 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2774 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2777 block_size
= lp_block_size(snum
);
2778 if (bsize
< block_size
) {
2779 SMB_BIG_UINT factor
= block_size
/bsize
;
2784 if (bsize
> block_size
) {
2785 SMB_BIG_UINT factor
= bsize
/block_size
;
2790 bytes_per_sector
= 512;
2791 sectors_per_unit
= bsize
/bytes_per_sector
;
2792 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2793 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2794 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2795 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2796 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2797 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2798 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2799 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2803 case SMB_QUERY_FS_DEVICE_INFO
:
2804 case SMB_FS_DEVICE_INFORMATION
:
2806 SIVAL(pdata
,0,0); /* dev type */
2807 SIVAL(pdata
,4,0); /* characteristics */
2810 #ifdef HAVE_SYS_QUOTAS
2811 case SMB_FS_QUOTA_INFORMATION
:
2813 * what we have to send --metze:
2815 * Unknown1: 24 NULL bytes
2816 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2817 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2818 * Quota Flags: 2 byte :
2819 * Unknown3: 6 NULL bytes
2823 * details for Quota Flags:
2825 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2826 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2827 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2828 * 0x0001 Enable Quotas: enable quota for this fs
2832 /* we need to fake up a fsp here,
2833 * because its not send in this call
2836 SMB_NTQUOTA_STRUCT quotas
;
2839 ZERO_STRUCT(quotas
);
2845 if (conn
->server_info
->utok
.uid
!= 0) {
2846 DEBUG(0,("set_user_quota: access_denied "
2847 "service [%s] user [%s]\n",
2848 lp_servicename(SNUM(conn
)),
2849 conn
->server_info
->unix_name
));
2850 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2854 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2855 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2856 reply_doserror(req
, ERRSRV
, ERRerror
);
2862 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2864 /* Unknown1 24 NULL bytes*/
2865 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2866 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2867 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2869 /* Default Soft Quota 8 bytes */
2870 SBIG_UINT(pdata
,24,quotas
.softlim
);
2872 /* Default Hard Quota 8 bytes */
2873 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2875 /* Quota flag 2 bytes */
2876 SSVAL(pdata
,40,quotas
.qflags
);
2878 /* Unknown3 6 NULL bytes */
2884 #endif /* HAVE_SYS_QUOTAS */
2885 case SMB_FS_OBJECTID_INFORMATION
:
2887 unsigned char objid
[16];
2888 struct smb_extended_info extended_info
;
2889 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2890 samba_extended_info_version (&extended_info
);
2891 SIVAL(pdata
,16,extended_info
.samba_magic
);
2892 SIVAL(pdata
,20,extended_info
.samba_version
);
2893 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2894 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2895 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2901 * Query the version and capabilities of the CIFS UNIX extensions
2905 case SMB_QUERY_CIFS_UNIX_INFO
:
2907 bool large_write
= lp_min_receive_file_size() &&
2908 !srv_is_signing_active();
2909 bool large_read
= !srv_is_signing_active();
2910 int encrypt_caps
= 0;
2912 if (!lp_unix_extensions()) {
2913 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2917 switch (conn
->encrypt_level
) {
2923 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2926 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2927 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2928 large_write
= false;
2934 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2935 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2937 /* We have POSIX ACLs, pathname, encryption,
2938 * large read/write, and locking capability. */
2940 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2941 CIFS_UNIX_POSIX_ACLS_CAP
|
2942 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2943 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2944 CIFS_UNIX_EXTATTR_CAP
|
2945 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2947 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2949 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2953 case SMB_QUERY_POSIX_FS_INFO
:
2956 vfs_statvfs_struct svfs
;
2958 if (!lp_unix_extensions()) {
2959 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2963 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2967 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2968 SIVAL(pdata
,4,svfs
.BlockSize
);
2969 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2970 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2971 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2972 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2973 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2974 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2975 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2977 } else if (rc
== EOPNOTSUPP
) {
2978 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2980 #endif /* EOPNOTSUPP */
2982 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2983 reply_doserror(req
, ERRSRV
, ERRerror
);
2989 case SMB_QUERY_POSIX_WHOAMI
:
2995 if (!lp_unix_extensions()) {
2996 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3000 if (max_data_bytes
< 40) {
3001 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
3005 /* We ARE guest if global_sid_Builtin_Guests is
3006 * in our list of SIDs.
3008 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3009 conn
->server_info
->ptok
)) {
3010 flags
|= SMB_WHOAMI_GUEST
;
3013 /* We are NOT guest if global_sid_Authenticated_Users
3014 * is in our list of SIDs.
3016 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3017 conn
->server_info
->ptok
)) {
3018 flags
&= ~SMB_WHOAMI_GUEST
;
3021 /* NOTE: 8 bytes for UID/GID, irrespective of native
3022 * platform size. This matches
3023 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3025 data_len
= 4 /* flags */
3032 + 4 /* pad/reserved */
3033 + (conn
->server_info
->utok
.ngroups
* 8)
3035 + (conn
->server_info
->ptok
->num_sids
*
3039 SIVAL(pdata
, 0, flags
);
3040 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3042 (SMB_BIG_UINT
)conn
->server_info
->utok
.uid
);
3043 SBIG_UINT(pdata
, 16,
3044 (SMB_BIG_UINT
)conn
->server_info
->utok
.gid
);
3047 if (data_len
>= max_data_bytes
) {
3048 /* Potential overflow, skip the GIDs and SIDs. */
3050 SIVAL(pdata
, 24, 0); /* num_groups */
3051 SIVAL(pdata
, 28, 0); /* num_sids */
3052 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3053 SIVAL(pdata
, 36, 0); /* reserved */
3059 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3060 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3062 /* We walk the SID list twice, but this call is fairly
3063 * infrequent, and I don't expect that it's performance
3064 * sensitive -- jpeach
3066 for (i
= 0, sid_bytes
= 0;
3067 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3068 sid_bytes
+= ndr_size_dom_sid(
3069 &conn
->server_info
->ptok
->user_sids
[i
],
3073 /* SID list byte count */
3074 SIVAL(pdata
, 32, sid_bytes
);
3076 /* 4 bytes pad/reserved - must be zero */
3077 SIVAL(pdata
, 36, 0);
3081 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3082 SBIG_UINT(pdata
, data_len
,
3083 (SMB_BIG_UINT
)conn
->server_info
->utok
.groups
[i
]);
3089 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3090 int sid_len
= ndr_size_dom_sid(
3091 &conn
->server_info
->ptok
->user_sids
[i
],
3094 sid_linearize(pdata
+ data_len
, sid_len
,
3095 &conn
->server_info
->ptok
->user_sids
[i
]);
3096 data_len
+= sid_len
;
3102 case SMB_MAC_QUERY_FS_INFO
:
3104 * Thursby MAC extension... ONLY on NTFS filesystems
3105 * once we do streams then we don't need this
3107 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3109 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3114 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3119 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3122 DEBUG( 4, ( "%s info_level = %d\n",
3123 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
3128 /****************************************************************************
3129 Reply to a TRANS2_SETFSINFO (set filesystem info).
3130 ****************************************************************************/
3132 static void call_trans2setfsinfo(connection_struct
*conn
,
3133 struct smb_request
*req
,
3134 char **pparams
, int total_params
,
3135 char **ppdata
, int total_data
,
3136 unsigned int max_data_bytes
)
3138 char *pdata
= *ppdata
;
3139 char *params
= *pparams
;
3142 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3145 if (total_params
< 4) {
3146 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3148 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3152 info_level
= SVAL(params
,2);
3155 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3156 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3157 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3158 "info level (0x%x) on IPC$.\n",
3159 (unsigned int)info_level
));
3160 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3165 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3166 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3167 DEBUG(0,("call_trans2setfsinfo: encryption required "
3168 "and info level 0x%x sent.\n",
3169 (unsigned int)info_level
));
3170 exit_server_cleanly("encryption required "
3176 switch(info_level
) {
3177 case SMB_SET_CIFS_UNIX_INFO
:
3179 uint16 client_unix_major
;
3180 uint16 client_unix_minor
;
3181 uint32 client_unix_cap_low
;
3182 uint32 client_unix_cap_high
;
3184 if (!lp_unix_extensions()) {
3186 NT_STATUS_INVALID_LEVEL
);
3190 /* There should be 12 bytes of capabilities set. */
3191 if (total_data
< 8) {
3194 NT_STATUS_INVALID_PARAMETER
);
3197 client_unix_major
= SVAL(pdata
,0);
3198 client_unix_minor
= SVAL(pdata
,2);
3199 client_unix_cap_low
= IVAL(pdata
,4);
3200 client_unix_cap_high
= IVAL(pdata
,8);
3201 /* Just print these values for now. */
3202 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3203 cap_low = 0x%x, cap_high = 0x%x\n",
3204 (unsigned int)client_unix_major
,
3205 (unsigned int)client_unix_minor
,
3206 (unsigned int)client_unix_cap_low
,
3207 (unsigned int)client_unix_cap_high
));
3209 /* Here is where we must switch to posix pathname processing... */
3210 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3211 lp_set_posix_pathnames();
3212 mangle_change_to_posix();
3215 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3216 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3217 /* Client that knows how to do posix locks,
3218 * but not posix open/mkdir operations. Set a
3219 * default type for read/write checks. */
3221 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3227 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3230 size_t param_len
= 0;
3231 size_t data_len
= total_data
;
3233 if (!lp_unix_extensions()) {
3236 NT_STATUS_INVALID_LEVEL
);
3240 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3243 NT_STATUS_NOT_SUPPORTED
);
3247 DEBUG( 4,("call_trans2setfsinfo: "
3248 "request transport encryption.\n"));
3250 status
= srv_request_encryption_setup(conn
,
3251 (unsigned char **)ppdata
,
3253 (unsigned char **)pparams
,
3256 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3257 !NT_STATUS_IS_OK(status
)) {
3258 reply_nterror(req
, status
);
3262 send_trans2_replies(conn
, req
,
3269 if (NT_STATUS_IS_OK(status
)) {
3270 /* Server-side transport
3271 * encryption is now *on*. */
3272 status
= srv_encryption_start(conn
);
3273 if (!NT_STATUS_IS_OK(status
)) {
3274 exit_server_cleanly(
3275 "Failure in setting "
3276 "up encrypted transport");
3282 case SMB_FS_QUOTA_INFORMATION
:
3284 files_struct
*fsp
= NULL
;
3285 SMB_NTQUOTA_STRUCT quotas
;
3287 ZERO_STRUCT(quotas
);
3290 if ((conn
->server_info
->utok
.uid
!= 0)
3291 ||!CAN_WRITE(conn
)) {
3292 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3293 lp_servicename(SNUM(conn
)),
3294 conn
->server_info
->unix_name
));
3295 reply_doserror(req
, ERRSRV
, ERRaccess
);
3299 /* note: normaly there're 48 bytes,
3300 * but we didn't use the last 6 bytes for now
3303 fsp
= file_fsp(SVAL(params
,0));
3305 if (!check_fsp_ntquota_handle(conn
, req
,
3307 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3309 req
, NT_STATUS_INVALID_HANDLE
);
3313 if (total_data
< 42) {
3314 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3318 NT_STATUS_INVALID_PARAMETER
);
3322 /* unknown_1 24 NULL bytes in pdata*/
3324 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3325 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3326 #ifdef LARGE_SMB_OFF_T
3327 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3328 #else /* LARGE_SMB_OFF_T */
3329 if ((IVAL(pdata
,28) != 0)&&
3330 ((quotas
.softlim
!= 0xFFFFFFFF)||
3331 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3332 /* more than 32 bits? */
3335 NT_STATUS_INVALID_PARAMETER
);
3338 #endif /* LARGE_SMB_OFF_T */
3340 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3341 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3342 #ifdef LARGE_SMB_OFF_T
3343 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3344 #else /* LARGE_SMB_OFF_T */
3345 if ((IVAL(pdata
,36) != 0)&&
3346 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3347 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3348 /* more than 32 bits? */
3351 NT_STATUS_INVALID_PARAMETER
);
3354 #endif /* LARGE_SMB_OFF_T */
3356 /* quota_flags 2 bytes **/
3357 quotas
.qflags
= SVAL(pdata
,40);
3359 /* unknown_2 6 NULL bytes follow*/
3361 /* now set the quotas */
3362 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3363 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3364 reply_doserror(req
, ERRSRV
, ERRerror
);
3371 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3373 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3379 * sending this reply works fine,
3380 * but I'm not sure it's the same
3381 * like windows do...
3384 reply_outbuf(req
, 10, 0);
3387 #if defined(HAVE_POSIX_ACLS)
3388 /****************************************************************************
3389 Utility function to count the number of entries in a POSIX acl.
3390 ****************************************************************************/
3392 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3394 unsigned int ace_count
= 0;
3395 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3396 SMB_ACL_ENTRY_T entry
;
3398 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3400 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3401 entry_id
= SMB_ACL_NEXT_ENTRY
;
3408 /****************************************************************************
3409 Utility function to marshall a POSIX acl into wire format.
3410 ****************************************************************************/
3412 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3414 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3415 SMB_ACL_ENTRY_T entry
;
3417 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3418 SMB_ACL_TAG_T tagtype
;
3419 SMB_ACL_PERMSET_T permset
;
3420 unsigned char perms
= 0;
3421 unsigned int own_grp
;
3424 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3425 entry_id
= SMB_ACL_NEXT_ENTRY
;
3428 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3429 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3433 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3438 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3439 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3440 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3442 SCVAL(pdata
,1,perms
);
3445 case SMB_ACL_USER_OBJ
:
3446 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3447 own_grp
= (unsigned int)pst
->st_uid
;
3448 SIVAL(pdata
,2,own_grp
);
3453 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3455 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3458 own_grp
= (unsigned int)*puid
;
3459 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3460 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3461 SIVAL(pdata
,2,own_grp
);
3465 case SMB_ACL_GROUP_OBJ
:
3466 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3467 own_grp
= (unsigned int)pst
->st_gid
;
3468 SIVAL(pdata
,2,own_grp
);
3473 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3475 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3478 own_grp
= (unsigned int)*pgid
;
3479 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3480 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3481 SIVAL(pdata
,2,own_grp
);
3486 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3487 SIVAL(pdata
,2,0xFFFFFFFF);
3488 SIVAL(pdata
,6,0xFFFFFFFF);
3491 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3492 SIVAL(pdata
,2,0xFFFFFFFF);
3493 SIVAL(pdata
,6,0xFFFFFFFF);
3496 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3499 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3506 /****************************************************************************
3507 Store the FILE_UNIX_BASIC info.
3508 ****************************************************************************/
3510 static char *store_file_unix_basic(connection_struct
*conn
,
3513 const SMB_STRUCT_STAT
*psbuf
)
3515 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3516 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3518 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3521 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3524 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3525 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3526 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3529 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3533 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3537 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3540 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3544 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3548 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3551 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3555 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3562 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3563 * the chflags(2) (or equivalent) flags.
3565 * XXX: this really should be behind the VFS interface. To do this, we would
3566 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3567 * Each VFS module could then implement its own mapping as appropriate for the
3568 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3570 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3574 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3578 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3582 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3586 { UF_HIDDEN
, EXT_HIDDEN
},
3589 /* Do not remove. We need to guarantee that this array has at least one
3590 * entry to build on HP-UX.
3596 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3597 uint32
*smb_fflags
, uint32
*smb_fmask
)
3599 #ifdef HAVE_STAT_ST_FLAGS
3602 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3603 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3604 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3605 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3608 #endif /* HAVE_STAT_ST_FLAGS */
3611 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3612 const uint32 smb_fflags
,
3613 const uint32 smb_fmask
,
3616 #ifdef HAVE_STAT_ST_FLAGS
3617 uint32 max_fmask
= 0;
3620 *stat_fflags
= psbuf
->st_flags
;
3622 /* For each flags requested in smb_fmask, check the state of the
3623 * corresponding flag in smb_fflags and set or clear the matching
3627 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3628 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3629 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3630 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3631 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3633 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3638 /* If smb_fmask is asking to set any bits that are not supported by
3639 * our flag mappings, we should fail.
3641 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3648 #endif /* HAVE_STAT_ST_FLAGS */
3652 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3653 * of file flags and birth (create) time.
3655 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3658 const SMB_STRUCT_STAT
*psbuf
)
3660 uint32 file_flags
= 0;
3661 uint32 flags_mask
= 0;
3663 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3665 /* Create (birth) time 64 bit */
3666 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3669 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3670 SIVAL(pdata
, 0, file_flags
); /* flags */
3671 SIVAL(pdata
, 4, flags_mask
); /* mask */
3677 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3678 const struct stream_struct
*streams
,
3680 unsigned int max_data_bytes
,
3681 unsigned int *data_size
)
3684 unsigned int ofs
= 0;
3686 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3687 unsigned int next_offset
;
3689 smb_ucs2_t
*namebuf
;
3691 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3692 streams
[i
].name
, &namelen
) ||
3695 return NT_STATUS_INVALID_PARAMETER
;
3699 * name_buf is now null-terminated, we need to marshall as not
3705 SIVAL(data
, ofs
+4, namelen
);
3706 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3707 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3708 memcpy(data
+ofs
+24, namebuf
, namelen
);
3709 TALLOC_FREE(namebuf
);
3711 next_offset
= ofs
+ 24 + namelen
;
3713 if (i
== num_streams
-1) {
3714 SIVAL(data
, ofs
, 0);
3717 unsigned int align
= ndr_align_size(next_offset
, 8);
3719 memset(data
+next_offset
, 0, align
);
3720 next_offset
+= align
;
3722 SIVAL(data
, ofs
, next_offset
- ofs
);
3731 return NT_STATUS_OK
;
3734 /****************************************************************************
3735 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3736 ****************************************************************************/
3738 static void call_trans2qpipeinfo(connection_struct
*conn
,
3739 struct smb_request
*req
,
3740 unsigned int tran_call
,
3741 char **pparams
, int total_params
,
3742 char **ppdata
, int total_data
,
3743 unsigned int max_data_bytes
)
3745 char *params
= *pparams
;
3746 char *pdata
= *ppdata
;
3747 unsigned int data_size
= 0;
3748 unsigned int param_size
= 2;
3750 smb_np_struct
*p_pipe
= NULL
;
3753 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3757 if (total_params
< 4) {
3758 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3762 p_pipe
= get_rpc_pipe_p(SVAL(params
,0));
3763 if (p_pipe
== NULL
) {
3764 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3768 info_level
= SVAL(params
,2);
3770 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3771 if (*pparams
== NULL
) {
3772 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3777 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3778 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3779 if (*ppdata
== NULL
) {
3780 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3785 switch (info_level
) {
3786 case SMB_FILE_STANDARD_INFORMATION
:
3788 SOFF_T(pdata
,0,4096LL);
3795 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3799 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3805 /****************************************************************************
3806 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3807 file name or file id).
3808 ****************************************************************************/
3810 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3811 struct smb_request
*req
,
3812 unsigned int tran_call
,
3813 char **pparams
, int total_params
,
3814 char **ppdata
, int total_data
,
3815 unsigned int max_data_bytes
)
3817 char *params
= *pparams
;
3818 char *pdata
= *ppdata
;
3819 char *dstart
, *dend
;
3823 SMB_OFF_T file_size
=0;
3824 SMB_BIG_UINT allocation_size
=0;
3825 unsigned int data_size
= 0;
3826 unsigned int param_size
= 2;
3827 SMB_STRUCT_STAT sbuf
;
3828 char *dos_fname
= NULL
;
3834 bool delete_pending
= False
;
3836 time_t create_time
, mtime
, atime
;
3837 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3838 struct timespec write_time_ts
;
3839 files_struct
*fsp
= NULL
;
3840 struct file_id fileid
;
3841 struct ea_list
*ea_list
= NULL
;
3842 char *lock_data
= NULL
;
3843 bool ms_dfs_link
= false;
3844 TALLOC_CTX
*ctx
= talloc_tos();
3847 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3852 ZERO_STRUCT(write_time_ts
);
3854 if (tran_call
== TRANSACT2_QFILEINFO
) {
3855 if (total_params
< 4) {
3856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3861 call_trans2qpipeinfo(conn
, req
, tran_call
,
3862 pparams
, total_params
,
3868 fsp
= file_fsp(SVAL(params
,0));
3869 info_level
= SVAL(params
,2);
3871 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3873 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3874 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3878 /* Initial check for valid fsp ptr. */
3879 if (!check_fsp_open(conn
, req
, fsp
)) {
3883 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3885 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3889 if(fsp
->fake_file_handle
) {
3891 * This is actually for the QUOTA_FAKE_FILE --metze
3894 /* We know this name is ok, it's already passed the checks. */
3896 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3898 * This is actually a QFILEINFO on a directory
3899 * handle (returned from an NT SMB). NT5.0 seems
3900 * to do this call. JRA.
3903 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3904 /* Always do lstat for UNIX calls. */
3905 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3906 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3907 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3910 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3911 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3912 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3916 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3917 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3920 * Original code - this is an open file.
3922 if (!check_fsp(conn
, req
, fsp
)) {
3926 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3927 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3928 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3931 pos
= fsp
->fh
->position_information
;
3932 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3933 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3937 NTSTATUS status
= NT_STATUS_OK
;
3940 if (total_params
< 7) {
3941 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3945 info_level
= SVAL(params
,0);
3947 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3949 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3950 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3954 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3956 STR_TERMINATE
, &status
);
3957 if (!NT_STATUS_IS_OK(status
)) {
3958 reply_nterror(req
, status
);
3962 status
= resolve_dfspath(ctx
,
3964 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3967 if (!NT_STATUS_IS_OK(status
)) {
3968 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3969 reply_botherror(req
,
3970 NT_STATUS_PATH_NOT_COVERED
,
3971 ERRSRV
, ERRbadpath
);
3973 reply_nterror(req
, status
);
3977 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3978 if (!NT_STATUS_IS_OK(status
)) {
3979 reply_nterror(req
, status
);
3982 status
= check_name(conn
, fname
);
3983 if (!NT_STATUS_IS_OK(status
)) {
3984 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3985 reply_nterror(req
, status
);
3989 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
3990 && is_ntfs_stream_name(fname
)) {
3992 SMB_STRUCT_STAT bsbuf
;
3994 status
= split_ntfs_stream_name(talloc_tos(), fname
,
3996 if (!NT_STATUS_IS_OK(status
)) {
3997 DEBUG(10, ("create_file_unixpath: "
3998 "split_ntfs_stream_name failed: %s\n",
3999 nt_errstr(status
)));
4000 reply_nterror(req
, status
);
4004 SMB_ASSERT(!is_ntfs_stream_name(base
)); /* paranoia.. */
4006 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4007 /* Always do lstat for UNIX calls. */
4008 if (SMB_VFS_LSTAT(conn
,base
,&bsbuf
)) {
4009 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base
,strerror(errno
)));
4010 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4014 if (SMB_VFS_STAT(conn
,base
,&bsbuf
) != 0) {
4015 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base
,strerror(errno
)));
4016 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4021 fileid
= vfs_file_id_from_sbuf(conn
, &bsbuf
);
4022 get_file_infos(fileid
, &delete_pending
, NULL
);
4023 if (delete_pending
) {
4024 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4029 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4030 /* Always do lstat for UNIX calls. */
4031 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4032 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4033 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4037 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4038 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4041 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4042 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4047 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4048 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4049 if (delete_pending
) {
4050 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4055 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4056 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4060 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4061 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4063 p
= strrchr_m(fname
,'/');
4070 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4072 mode
= dos_mode(conn
,fname
,&sbuf
);
4075 mode
= FILE_ATTRIBUTE_NORMAL
;
4077 nlink
= sbuf
.st_nlink
;
4079 if (nlink
&& (mode
&aDIR
)) {
4083 if ((nlink
> 0) && delete_pending
) {
4087 fullpathname
= fname
;
4089 file_size
= get_file_size(sbuf
);
4091 /* Pull out any data sent here before we realloc. */
4092 switch (info_level
) {
4093 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4095 /* Pull any EA list from the data portion. */
4098 if (total_data
< 4) {
4100 req
, NT_STATUS_INVALID_PARAMETER
);
4103 ea_size
= IVAL(pdata
,0);
4105 if (total_data
> 0 && ea_size
!= total_data
) {
4106 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4107 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4109 req
, NT_STATUS_INVALID_PARAMETER
);
4113 if (!lp_ea_support(SNUM(conn
))) {
4114 reply_doserror(req
, ERRDOS
,
4115 ERReasnotsupported
);
4119 /* Pull out the list of names. */
4120 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4123 req
, NT_STATUS_INVALID_PARAMETER
);
4129 case SMB_QUERY_POSIX_LOCK
:
4131 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4132 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4136 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4138 req
, NT_STATUS_INVALID_PARAMETER
);
4142 /* Copy the lock range data. */
4143 lock_data
= (char *)TALLOC_MEMDUP(
4144 ctx
, pdata
, total_data
);
4146 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4154 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4155 if (*pparams
== NULL
) {
4156 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4161 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4162 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4163 if (*ppdata
== NULL
) {
4164 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4169 dend
= dstart
+ data_size
- 1;
4171 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4172 mtime_ts
= get_mtimespec(&sbuf
);
4173 atime_ts
= get_atimespec(&sbuf
);
4175 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
4178 /* Do we have this path open ? */
4180 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4181 fsp1
= file_find_di_first(fileid
);
4182 if (fsp1
&& fsp1
->initial_allocation_size
) {
4183 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
4187 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4188 mtime_ts
= write_time_ts
;
4191 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4192 dos_filetime_timespec(&create_time_ts
);
4193 dos_filetime_timespec(&mtime_ts
);
4194 dos_filetime_timespec(&atime_ts
);
4197 create_time
= convert_timespec_to_time_t(create_time_ts
);
4198 mtime
= convert_timespec_to_time_t(mtime_ts
);
4199 atime
= convert_timespec_to_time_t(atime_ts
);
4201 /* NT expects the name to be in an exact form of the *full*
4202 filename. See the trans2 torture test */
4203 if (ISDOT(base_name
)) {
4204 dos_fname
= talloc_strdup(ctx
, "\\");
4206 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4210 dos_fname
= talloc_asprintf(ctx
,
4214 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4217 string_replace(dos_fname
, '/', '\\');
4220 switch (info_level
) {
4221 case SMB_INFO_STANDARD
:
4222 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4224 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4225 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4226 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4227 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4228 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4229 SSVAL(pdata
,l1_attrFile
,mode
);
4232 case SMB_INFO_QUERY_EA_SIZE
:
4234 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4235 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4237 srv_put_dos_date2(pdata
,0,create_time
);
4238 srv_put_dos_date2(pdata
,4,atime
);
4239 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4240 SIVAL(pdata
,12,(uint32
)file_size
);
4241 SIVAL(pdata
,16,(uint32
)allocation_size
);
4242 SSVAL(pdata
,20,mode
);
4243 SIVAL(pdata
,22,ea_size
);
4247 case SMB_INFO_IS_NAME_VALID
:
4248 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4249 if (tran_call
== TRANSACT2_QFILEINFO
) {
4250 /* os/2 needs this ? really ?*/
4251 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4258 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4260 size_t total_ea_len
= 0;
4261 struct ea_list
*ea_file_list
= NULL
;
4263 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4265 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4266 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4268 if (!ea_list
|| (total_ea_len
> data_size
)) {
4270 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4274 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4278 case SMB_INFO_QUERY_ALL_EAS
:
4280 /* We have data_size bytes to put EA's into. */
4281 size_t total_ea_len
= 0;
4283 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4285 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4286 if (!ea_list
|| (total_ea_len
> data_size
)) {
4288 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4292 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4296 case SMB_FILE_BASIC_INFORMATION
:
4297 case SMB_QUERY_FILE_BASIC_INFO
:
4299 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4300 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4301 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4303 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4307 put_long_date_timespec(pdata
,create_time_ts
);
4308 put_long_date_timespec(pdata
+8,atime_ts
);
4309 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4310 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4311 SIVAL(pdata
,32,mode
);
4313 DEBUG(5,("SMB_QFBI - "));
4314 DEBUG(5,("create: %s ", ctime(&create_time
)));
4315 DEBUG(5,("access: %s ", ctime(&atime
)));
4316 DEBUG(5,("write: %s ", ctime(&mtime
)));
4317 DEBUG(5,("change: %s ", ctime(&mtime
)));
4318 DEBUG(5,("mode: %x\n", mode
));
4321 case SMB_FILE_STANDARD_INFORMATION
:
4322 case SMB_QUERY_FILE_STANDARD_INFO
:
4324 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4326 SOFF_T(pdata
,0,allocation_size
);
4327 SOFF_T(pdata
,8,file_size
);
4328 SIVAL(pdata
,16,nlink
);
4329 SCVAL(pdata
,20,delete_pending
?1:0);
4330 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4331 SSVAL(pdata
,22,0); /* Padding. */
4334 case SMB_FILE_EA_INFORMATION
:
4335 case SMB_QUERY_FILE_EA_INFO
:
4337 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4340 SIVAL(pdata
,0,ea_size
);
4344 /* Get the 8.3 name - used if NT SMB was negotiated. */
4345 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4346 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4348 char mangled_name
[13];
4349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4350 if (!name_to_8_3(base_name
,mangled_name
,
4351 True
,conn
->params
)) {
4354 NT_STATUS_NO_MEMORY
);
4356 len
= srvstr_push(dstart
, req
->flags2
,
4357 pdata
+4, mangled_name
,
4358 PTR_DIFF(dend
, pdata
+4),
4360 data_size
= 4 + len
;
4365 case SMB_QUERY_FILE_NAME_INFO
:
4367 this must be *exactly* right for ACLs on mapped drives to work
4369 len
= srvstr_push(dstart
, req
->flags2
,
4371 PTR_DIFF(dend
, pdata
+4),
4373 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4374 data_size
= 4 + len
;
4378 case SMB_FILE_ALLOCATION_INFORMATION
:
4379 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4382 SOFF_T(pdata
,0,allocation_size
);
4385 case SMB_FILE_END_OF_FILE_INFORMATION
:
4386 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4389 SOFF_T(pdata
,0,file_size
);
4392 case SMB_QUERY_FILE_ALL_INFO
:
4393 case SMB_FILE_ALL_INFORMATION
:
4395 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4396 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4397 put_long_date_timespec(pdata
,create_time_ts
);
4398 put_long_date_timespec(pdata
+8,atime_ts
);
4399 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4400 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4401 SIVAL(pdata
,32,mode
);
4402 SIVAL(pdata
,36,0); /* padding. */
4404 SOFF_T(pdata
,0,allocation_size
);
4405 SOFF_T(pdata
,8,file_size
);
4406 SIVAL(pdata
,16,nlink
);
4407 SCVAL(pdata
,20,delete_pending
);
4408 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4411 SIVAL(pdata
,0,ea_size
);
4412 pdata
+= 4; /* EA info */
4413 len
= srvstr_push(dstart
, req
->flags2
,
4415 PTR_DIFF(dend
, pdata
+4),
4419 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4422 case SMB_FILE_INTERNAL_INFORMATION
:
4423 /* This should be an index number - looks like
4426 I think this causes us to fail the IFSKIT
4427 BasicFileInformationTest. -tpot */
4429 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4430 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4431 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4435 case SMB_FILE_ACCESS_INFORMATION
:
4436 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4438 SIVAL(pdata
,0,fsp
->access_mask
);
4440 /* GENERIC_EXECUTE mapping from Windows */
4441 SIVAL(pdata
,0,0x12019F);
4446 case SMB_FILE_NAME_INFORMATION
:
4447 /* Pathname with leading '\'. */
4450 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4452 SIVAL(pdata
,0,byte_len
);
4453 data_size
= 4 + byte_len
;
4457 case SMB_FILE_DISPOSITION_INFORMATION
:
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4460 SCVAL(pdata
,0,delete_pending
);
4463 case SMB_FILE_POSITION_INFORMATION
:
4464 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4466 SOFF_T(pdata
,0,pos
);
4469 case SMB_FILE_MODE_INFORMATION
:
4470 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4471 SIVAL(pdata
,0,mode
);
4475 case SMB_FILE_ALIGNMENT_INFORMATION
:
4476 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4477 SIVAL(pdata
,0,0); /* No alignment needed. */
4482 * NT4 server just returns "invalid query" to this - if we try
4483 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4486 /* The first statement above is false - verified using Thursby
4487 * client against NT4 -- gcolley.
4489 case SMB_QUERY_FILE_STREAM_INFO
:
4490 case SMB_FILE_STREAM_INFORMATION
: {
4491 unsigned int num_streams
;
4492 struct stream_struct
*streams
;
4495 DEBUG(10,("call_trans2qfilepathinfo: "
4496 "SMB_FILE_STREAM_INFORMATION\n"));
4498 status
= SMB_VFS_STREAMINFO(
4499 conn
, fsp
, fname
, talloc_tos(),
4500 &num_streams
, &streams
);
4502 if (!NT_STATUS_IS_OK(status
)) {
4503 DEBUG(10, ("could not get stream info: %s\n",
4504 nt_errstr(status
)));
4505 reply_nterror(req
, status
);
4509 status
= marshall_stream_info(num_streams
, streams
,
4510 pdata
, max_data_bytes
,
4513 if (!NT_STATUS_IS_OK(status
)) {
4514 DEBUG(10, ("marshall_stream_info failed: %s\n",
4515 nt_errstr(status
)));
4516 reply_nterror(req
, status
);
4520 TALLOC_FREE(streams
);
4524 case SMB_QUERY_COMPRESSION_INFO
:
4525 case SMB_FILE_COMPRESSION_INFORMATION
:
4526 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4527 SOFF_T(pdata
,0,file_size
);
4528 SIVAL(pdata
,8,0); /* ??? */
4529 SIVAL(pdata
,12,0); /* ??? */
4533 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4534 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4535 put_long_date_timespec(pdata
,create_time_ts
);
4536 put_long_date_timespec(pdata
+8,atime_ts
);
4537 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4538 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4539 SOFF_T(pdata
,32,allocation_size
);
4540 SOFF_T(pdata
,40,file_size
);
4541 SIVAL(pdata
,48,mode
);
4542 SIVAL(pdata
,52,0); /* ??? */
4546 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4547 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4548 SIVAL(pdata
,0,mode
);
4554 * CIFS UNIX Extensions.
4557 case SMB_QUERY_FILE_UNIX_BASIC
:
4559 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4560 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4564 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4566 for (i
=0; i
<100; i
++)
4567 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4573 case SMB_QUERY_FILE_UNIX_INFO2
:
4575 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4576 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4580 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4582 for (i
=0; i
<100; i
++)
4583 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4589 case SMB_QUERY_FILE_UNIX_LINK
:
4591 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4594 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4598 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4600 if(!S_ISLNK(sbuf
.st_mode
)) {
4601 reply_unixerror(req
, ERRSRV
,
4606 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4609 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4612 reply_unixerror(req
, ERRDOS
,
4617 len
= srvstr_push(dstart
, req
->flags2
,
4619 PTR_DIFF(dend
, pdata
),
4622 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4627 #if defined(HAVE_POSIX_ACLS)
4628 case SMB_QUERY_POSIX_ACL
:
4630 SMB_ACL_T file_acl
= NULL
;
4631 SMB_ACL_T def_acl
= NULL
;
4632 uint16 num_file_acls
= 0;
4633 uint16 num_def_acls
= 0;
4635 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4636 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4638 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4641 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4642 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4646 NT_STATUS_NOT_IMPLEMENTED
);
4650 if (S_ISDIR(sbuf
.st_mode
)) {
4651 if (fsp
&& fsp
->is_directory
) {
4652 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4654 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4656 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4659 num_file_acls
= count_acl_entries(conn
, file_acl
);
4660 num_def_acls
= count_acl_entries(conn
, def_acl
);
4662 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4663 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4665 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4666 SMB_POSIX_ACL_HEADER_SIZE
) ));
4668 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4671 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4675 NT_STATUS_BUFFER_TOO_SMALL
);
4679 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4680 SSVAL(pdata
,2,num_file_acls
);
4681 SSVAL(pdata
,4,num_def_acls
);
4682 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4684 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4690 req
, NT_STATUS_INTERNAL_ERROR
);
4693 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4702 NT_STATUS_INTERNAL_ERROR
);
4707 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4712 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4718 case SMB_QUERY_POSIX_LOCK
:
4720 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4722 SMB_BIG_UINT offset
;
4724 enum brl_type lock_type
;
4726 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4728 req
, NT_STATUS_INVALID_PARAMETER
);
4732 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4733 case POSIX_LOCK_TYPE_READ
:
4734 lock_type
= READ_LOCK
;
4736 case POSIX_LOCK_TYPE_WRITE
:
4737 lock_type
= WRITE_LOCK
;
4739 case POSIX_LOCK_TYPE_UNLOCK
:
4741 /* There's no point in asking for an unlock... */
4744 NT_STATUS_INVALID_PARAMETER
);
4748 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4749 #if defined(HAVE_LONGLONG)
4750 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4751 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4752 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4753 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4754 #else /* HAVE_LONGLONG */
4755 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4756 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4757 #endif /* HAVE_LONGLONG */
4759 status
= query_lock(fsp
,
4766 if (ERROR_WAS_LOCK_DENIED(status
)) {
4767 /* Here we need to report who has it locked... */
4768 data_size
= POSIX_LOCK_DATA_SIZE
;
4770 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4771 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4772 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4773 #if defined(HAVE_LONGLONG)
4774 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4775 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4776 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4777 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4778 #else /* HAVE_LONGLONG */
4779 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4780 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4781 #endif /* HAVE_LONGLONG */
4783 } else if (NT_STATUS_IS_OK(status
)) {
4784 /* For success we just return a copy of what we sent
4785 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4786 data_size
= POSIX_LOCK_DATA_SIZE
;
4787 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4788 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4790 reply_nterror(req
, status
);
4797 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4801 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4807 /****************************************************************************
4808 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4810 ****************************************************************************/
4812 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4813 connection_struct
*conn
,
4814 const char *oldname_in
,
4815 const char *newname_in
)
4817 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4818 char *last_component_oldname
= NULL
;
4819 char *last_component_newname
= NULL
;
4820 char *oldname
= NULL
;
4821 char *newname
= NULL
;
4822 NTSTATUS status
= NT_STATUS_OK
;
4827 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4828 &last_component_oldname
, &sbuf1
);
4829 if (!NT_STATUS_IS_OK(status
)) {
4833 status
= check_name(conn
, oldname
);
4834 if (!NT_STATUS_IS_OK(status
)) {
4838 /* source must already exist. */
4839 if (!VALID_STAT(sbuf1
)) {
4840 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4843 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4844 &last_component_newname
, &sbuf2
);
4845 if (!NT_STATUS_IS_OK(status
)) {
4849 status
= check_name(conn
, newname
);
4850 if (!NT_STATUS_IS_OK(status
)) {
4854 /* Disallow if newname already exists. */
4855 if (VALID_STAT(sbuf2
)) {
4856 return NT_STATUS_OBJECT_NAME_COLLISION
;
4859 /* No links from a directory. */
4860 if (S_ISDIR(sbuf1
.st_mode
)) {
4861 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4864 /* Ensure this is within the share. */
4865 status
= check_reduced_name(conn
, oldname
);
4866 if (!NT_STATUS_IS_OK(status
)) {
4870 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4872 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4873 status
= map_nt_error_from_unix(errno
);
4874 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4875 nt_errstr(status
), newname
, oldname
));
4881 /****************************************************************************
4882 Deal with setting the time from any of the setfilepathinfo functions.
4883 ****************************************************************************/
4885 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4888 const SMB_STRUCT_STAT
*psbuf
,
4889 struct timespec ts
[2],
4890 bool setting_write_time
)
4893 FILE_NOTIFY_CHANGE_LAST_ACCESS
4894 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4896 if (!VALID_STAT(*psbuf
)) {
4897 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4900 /* get some defaults (no modifications) if any info is zero or -1. */
4901 if (null_timespec(ts
[0])) {
4902 ts
[0] = get_atimespec(psbuf
);
4903 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4906 if (null_timespec(ts
[1])) {
4907 ts
[1] = get_mtimespec(psbuf
);
4908 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4911 if (!setting_write_time
) {
4912 /* ts[1] comes from change time, not write time. */
4913 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4916 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4917 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4920 * Try and set the times of this file if
4921 * they are different from the current values.
4925 struct timespec mts
= get_mtimespec(psbuf
);
4926 struct timespec ats
= get_atimespec(psbuf
);
4927 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4928 return NT_STATUS_OK
;
4932 if (setting_write_time
) {
4934 * This was a Windows setfileinfo on an open file.
4935 * NT does this a lot. We also need to
4936 * set the time here, as it can be read by
4937 * FindFirst/FindNext and with the patch for bug #2045
4938 * in smbd/fileio.c it ensures that this timestamp is
4939 * kept sticky even after a write. We save the request
4940 * away and will set it on file close and after a write. JRA.
4943 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4944 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4947 if (fsp
->base_fsp
) {
4948 set_sticky_write_time_fsp(fsp
->base_fsp
, ts
[1]);
4950 set_sticky_write_time_fsp(fsp
, ts
[1]);
4953 set_sticky_write_time_path(conn
, fname
,
4954 vfs_file_id_from_sbuf(conn
, psbuf
),
4959 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4961 if (fsp
&& fsp
->base_fsp
) {
4962 fname
= fsp
->base_fsp
->fsp_name
;
4965 if(file_ntimes(conn
, fname
, ts
)!=0) {
4966 return map_nt_error_from_unix(errno
);
4968 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4970 return NT_STATUS_OK
;
4973 /****************************************************************************
4974 Deal with setting the dosmode from any of the setfilepathinfo functions.
4975 ****************************************************************************/
4977 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4980 SMB_STRUCT_STAT
*psbuf
,
4983 if (!VALID_STAT(*psbuf
)) {
4984 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4988 if (fsp
->base_fsp
) {
4989 fname
= fsp
->base_fsp
->fsp_name
;
4991 fname
= fsp
->fsp_name
;
4996 if (S_ISDIR(psbuf
->st_mode
)) {
5003 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5005 /* check the mode isn't different, before changing it */
5006 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
5008 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5009 fname
, (unsigned int)dosmode
));
5011 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
5012 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5013 fname
, strerror(errno
)));
5014 return map_nt_error_from_unix(errno
);
5017 return NT_STATUS_OK
;
5020 /****************************************************************************
5021 Deal with setting the size from any of the setfilepathinfo functions.
5022 ****************************************************************************/
5024 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5025 struct smb_request
*req
,
5028 SMB_STRUCT_STAT
*psbuf
,
5031 NTSTATUS status
= NT_STATUS_OK
;
5032 files_struct
*new_fsp
= NULL
;
5034 if (!VALID_STAT(*psbuf
)) {
5035 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5038 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5040 if (size
== get_file_size(*psbuf
)) {
5041 return NT_STATUS_OK
;
5044 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5045 fname
, (double)size
));
5047 if (fsp
&& fsp
->fh
->fd
!= -1) {
5048 /* Handle based call. */
5049 if (vfs_set_filelen(fsp
, size
) == -1) {
5050 return map_nt_error_from_unix(errno
);
5052 trigger_write_time_update_immediate(fsp
);
5053 return NT_STATUS_OK
;
5056 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5057 FILE_WRITE_ATTRIBUTES
,
5058 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5061 FILE_ATTRIBUTE_NORMAL
,
5062 FORCE_OPLOCK_BREAK_TO_NONE
,
5065 if (!NT_STATUS_IS_OK(status
)) {
5066 /* NB. We check for open_was_deferred in the caller. */
5070 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5071 status
= map_nt_error_from_unix(errno
);
5072 close_file(new_fsp
,NORMAL_CLOSE
);
5076 trigger_write_time_update_immediate(new_fsp
);
5077 close_file(new_fsp
,NORMAL_CLOSE
);
5078 return NT_STATUS_OK
;
5081 /****************************************************************************
5082 Deal with SMB_INFO_SET_EA.
5083 ****************************************************************************/
5085 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5091 struct ea_list
*ea_list
= NULL
;
5092 TALLOC_CTX
*ctx
= NULL
;
5093 NTSTATUS status
= NT_STATUS_OK
;
5095 if (total_data
< 10) {
5097 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5098 length. They seem to have no effect. Bug #3212. JRA */
5100 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5101 /* We're done. We only get EA info in this call. */
5102 return NT_STATUS_OK
;
5105 return NT_STATUS_INVALID_PARAMETER
;
5108 if (IVAL(pdata
,0) > total_data
) {
5109 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5110 IVAL(pdata
,0), (unsigned int)total_data
));
5111 return NT_STATUS_INVALID_PARAMETER
;
5115 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5117 return NT_STATUS_INVALID_PARAMETER
;
5119 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5124 /****************************************************************************
5125 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5126 ****************************************************************************/
5128 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5133 SMB_STRUCT_STAT
*psbuf
)
5135 NTSTATUS status
= NT_STATUS_OK
;
5136 bool delete_on_close
;
5139 if (total_data
< 1) {
5140 return NT_STATUS_INVALID_PARAMETER
;
5144 return NT_STATUS_INVALID_HANDLE
;
5147 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5148 dosmode
= dos_mode(conn
, fname
, psbuf
);
5150 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5151 "delete_on_close = %u\n",
5153 (unsigned int)dosmode
,
5154 (unsigned int)delete_on_close
));
5156 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5158 if (!NT_STATUS_IS_OK(status
)) {
5162 /* The set is across all open files on this dev/inode pair. */
5163 if (!set_delete_on_close(fsp
, delete_on_close
,
5164 &conn
->server_info
->utok
)) {
5165 return NT_STATUS_ACCESS_DENIED
;
5167 return NT_STATUS_OK
;
5170 /****************************************************************************
5171 Deal with SMB_FILE_POSITION_INFORMATION.
5172 ****************************************************************************/
5174 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5179 SMB_BIG_UINT position_information
;
5181 if (total_data
< 8) {
5182 return NT_STATUS_INVALID_PARAMETER
;
5186 /* Ignore on pathname based set. */
5187 return NT_STATUS_OK
;
5190 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5191 #ifdef LARGE_SMB_OFF_T
5192 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5193 #else /* LARGE_SMB_OFF_T */
5194 if (IVAL(pdata
,4) != 0) {
5195 /* more than 32 bits? */
5196 return NT_STATUS_INVALID_PARAMETER
;
5198 #endif /* LARGE_SMB_OFF_T */
5200 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5201 fsp
->fsp_name
, (double)position_information
));
5202 fsp
->fh
->position_information
= position_information
;
5203 return NT_STATUS_OK
;
5206 /****************************************************************************
5207 Deal with SMB_FILE_MODE_INFORMATION.
5208 ****************************************************************************/
5210 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5216 if (total_data
< 4) {
5217 return NT_STATUS_INVALID_PARAMETER
;
5219 mode
= IVAL(pdata
,0);
5220 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5221 return NT_STATUS_INVALID_PARAMETER
;
5223 return NT_STATUS_OK
;
5226 /****************************************************************************
5227 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5228 ****************************************************************************/
5230 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5231 struct smb_request
*req
,
5236 char *link_target
= NULL
;
5237 const char *newname
= fname
;
5238 NTSTATUS status
= NT_STATUS_OK
;
5239 TALLOC_CTX
*ctx
= talloc_tos();
5241 /* Set a symbolic link. */
5242 /* Don't allow this if follow links is false. */
5244 if (total_data
== 0) {
5245 return NT_STATUS_INVALID_PARAMETER
;
5248 if (!lp_symlinks(SNUM(conn
))) {
5249 return NT_STATUS_ACCESS_DENIED
;
5252 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5253 total_data
, STR_TERMINATE
);
5256 return NT_STATUS_INVALID_PARAMETER
;
5259 /* !widelinks forces the target path to be within the share. */
5260 /* This means we can interpret the target as a pathname. */
5261 if (!lp_widelinks(SNUM(conn
))) {
5262 char *rel_name
= NULL
;
5263 char *last_dirp
= NULL
;
5265 if (*link_target
== '/') {
5266 /* No absolute paths allowed. */
5267 return NT_STATUS_ACCESS_DENIED
;
5269 rel_name
= talloc_strdup(ctx
,newname
);
5271 return NT_STATUS_NO_MEMORY
;
5273 last_dirp
= strrchr_m(rel_name
, '/');
5275 last_dirp
[1] = '\0';
5277 rel_name
= talloc_strdup(ctx
,"./");
5279 return NT_STATUS_NO_MEMORY
;
5282 rel_name
= talloc_asprintf_append(rel_name
,
5286 return NT_STATUS_NO_MEMORY
;
5289 status
= check_name(conn
, rel_name
);
5290 if (!NT_STATUS_IS_OK(status
)) {
5295 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5296 newname
, link_target
));
5298 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5299 return map_nt_error_from_unix(errno
);
5302 return NT_STATUS_OK
;
5305 /****************************************************************************
5306 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5307 ****************************************************************************/
5309 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5310 struct smb_request
*req
,
5311 const char *pdata
, int total_data
,
5314 char *oldname
= NULL
;
5315 TALLOC_CTX
*ctx
= talloc_tos();
5316 NTSTATUS status
= NT_STATUS_OK
;
5318 /* Set a hard link. */
5319 if (total_data
== 0) {
5320 return NT_STATUS_INVALID_PARAMETER
;
5323 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5324 total_data
, STR_TERMINATE
, &status
);
5325 if (!NT_STATUS_IS_OK(status
)) {
5329 status
= resolve_dfspath(ctx
, conn
,
5330 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5333 if (!NT_STATUS_IS_OK(status
)) {
5337 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5340 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5343 /****************************************************************************
5344 Deal with SMB_FILE_RENAME_INFORMATION.
5345 ****************************************************************************/
5347 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5348 struct smb_request
*req
,
5357 char *newname
= NULL
;
5358 char *base_name
= NULL
;
5359 bool dest_has_wcard
= False
;
5360 SMB_STRUCT_STAT sbuf
;
5361 char *newname_last_component
= NULL
;
5362 NTSTATUS status
= NT_STATUS_OK
;
5364 TALLOC_CTX
*ctx
= talloc_tos();
5366 if (total_data
< 13) {
5367 return NT_STATUS_INVALID_PARAMETER
;
5372 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5373 root_fid
= IVAL(pdata
,4);
5374 len
= IVAL(pdata
,8);
5376 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5377 return NT_STATUS_INVALID_PARAMETER
;
5380 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5383 if (!NT_STATUS_IS_OK(status
)) {
5387 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5390 status
= resolve_dfspath_wcard(ctx
, conn
,
5391 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5395 if (!NT_STATUS_IS_OK(status
)) {
5399 /* Check the new name has no '/' characters. */
5400 if (strchr_m(newname
, '/')) {
5401 return NT_STATUS_NOT_SUPPORTED
;
5404 if (fsp
&& fsp
->base_fsp
) {
5405 /* newname must be a stream name. */
5406 if (newname
[0] != ':') {
5407 return NT_STATUS_NOT_SUPPORTED
;
5409 base_name
= talloc_asprintf(ctx
, "%s%s",
5410 fsp
->base_fsp
->fsp_name
,
5413 return NT_STATUS_NO_MEMORY
;
5416 /* newname must *not* be a stream name. */
5417 if (is_ntfs_stream_name(newname
)) {
5418 return NT_STATUS_NOT_SUPPORTED
;
5421 /* Create the base directory. */
5422 base_name
= talloc_strdup(ctx
, fname
);
5424 return NT_STATUS_NO_MEMORY
;
5426 p
= strrchr_m(base_name
, '/');
5430 base_name
= talloc_strdup(ctx
, "./");
5432 return NT_STATUS_NO_MEMORY
;
5435 /* Append the new name. */
5436 base_name
= talloc_asprintf_append(base_name
,
5440 return NT_STATUS_NO_MEMORY
;
5443 status
= unix_convert(ctx
, conn
, newname
, False
,
5445 &newname_last_component
,
5448 /* If an error we expect this to be
5449 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5451 if (!NT_STATUS_IS_OK(status
)
5452 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5459 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5460 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5461 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5462 newname_last_component
, 0,
5465 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5466 fname
, base_name
));
5467 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5468 overwrite
, False
, dest_has_wcard
,
5469 FILE_WRITE_ATTRIBUTES
);
5475 /****************************************************************************
5476 Deal with SMB_SET_POSIX_ACL.
5477 ****************************************************************************/
5479 #if defined(HAVE_POSIX_ACLS)
5480 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5485 SMB_STRUCT_STAT
*psbuf
)
5487 uint16 posix_acl_version
;
5488 uint16 num_file_acls
;
5489 uint16 num_def_acls
;
5490 bool valid_file_acls
= True
;
5491 bool valid_def_acls
= True
;
5493 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5494 return NT_STATUS_INVALID_PARAMETER
;
5496 posix_acl_version
= SVAL(pdata
,0);
5497 num_file_acls
= SVAL(pdata
,2);
5498 num_def_acls
= SVAL(pdata
,4);
5500 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5501 valid_file_acls
= False
;
5505 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5506 valid_def_acls
= False
;
5510 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5511 return NT_STATUS_INVALID_PARAMETER
;
5514 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5515 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5516 return NT_STATUS_INVALID_PARAMETER
;
5519 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5520 fname
? fname
: fsp
->fsp_name
,
5521 (unsigned int)num_file_acls
,
5522 (unsigned int)num_def_acls
));
5524 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5525 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5526 return map_nt_error_from_unix(errno
);
5529 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5530 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5531 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5532 return map_nt_error_from_unix(errno
);
5534 return NT_STATUS_OK
;
5538 /****************************************************************************
5539 Deal with SMB_SET_POSIX_LOCK.
5540 ****************************************************************************/
5542 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5543 const struct smb_request
*req
,
5549 SMB_BIG_UINT offset
;
5551 bool blocking_lock
= False
;
5552 enum brl_type lock_type
;
5554 NTSTATUS status
= NT_STATUS_OK
;
5556 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5557 return NT_STATUS_INVALID_HANDLE
;
5560 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5561 return NT_STATUS_INVALID_PARAMETER
;
5564 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5565 case POSIX_LOCK_TYPE_READ
:
5566 lock_type
= READ_LOCK
;
5568 case POSIX_LOCK_TYPE_WRITE
:
5569 /* Return the right POSIX-mappable error code for files opened read-only. */
5570 if (!fsp
->can_write
) {
5571 return NT_STATUS_INVALID_HANDLE
;
5573 lock_type
= WRITE_LOCK
;
5575 case POSIX_LOCK_TYPE_UNLOCK
:
5576 lock_type
= UNLOCK_LOCK
;
5579 return NT_STATUS_INVALID_PARAMETER
;
5582 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5583 blocking_lock
= False
;
5584 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5585 blocking_lock
= True
;
5587 return NT_STATUS_INVALID_PARAMETER
;
5590 if (!lp_blocking_locks(SNUM(conn
))) {
5591 blocking_lock
= False
;
5594 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5595 #if defined(HAVE_LONGLONG)
5596 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5597 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5598 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5599 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5600 #else /* HAVE_LONGLONG */
5601 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5602 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5603 #endif /* HAVE_LONGLONG */
5605 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5606 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5608 (unsigned int)lock_type
,
5609 (unsigned int)lock_pid
,
5613 if (lock_type
== UNLOCK_LOCK
) {
5614 status
= do_unlock(smbd_messaging_context(),
5621 uint32 block_smbpid
;
5623 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5634 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5636 * A blocking lock was requested. Package up
5637 * this smb into a queued request and push it
5638 * onto the blocking lock queue.
5640 if(push_blocking_lock_request(br_lck
,
5643 -1, /* infinite timeout. */
5651 TALLOC_FREE(br_lck
);
5655 TALLOC_FREE(br_lck
);
5661 /****************************************************************************
5662 Deal with SMB_INFO_STANDARD.
5663 ****************************************************************************/
5665 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5670 const SMB_STRUCT_STAT
*psbuf
)
5672 struct timespec ts
[2];
5674 if (total_data
< 12) {
5675 return NT_STATUS_INVALID_PARAMETER
;
5679 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5681 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5683 DEBUG(10,("smb_set_info_standard: file %s\n",
5684 fname
? fname
: fsp
->fsp_name
));
5686 return smb_set_file_time(conn
,
5694 /****************************************************************************
5695 Deal with SMB_SET_FILE_BASIC_INFO.
5696 ****************************************************************************/
5698 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5703 SMB_STRUCT_STAT
*psbuf
)
5705 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5706 struct timespec write_time
;
5707 struct timespec changed_time
;
5709 struct timespec ts
[2];
5710 NTSTATUS status
= NT_STATUS_OK
;
5711 bool setting_write_time
= true;
5713 if (total_data
< 36) {
5714 return NT_STATUS_INVALID_PARAMETER
;
5717 /* Set the attributes */
5718 dosmode
= IVAL(pdata
,32);
5719 status
= smb_set_file_dosmode(conn
,
5725 if (!NT_STATUS_IS_OK(status
)) {
5729 /* Ignore create time at offset pdata. */
5732 ts
[0] = interpret_long_date(pdata
+8);
5734 write_time
= interpret_long_date(pdata
+16);
5735 changed_time
= interpret_long_date(pdata
+24);
5738 ts
[1] = timespec_min(&write_time
, &changed_time
);
5740 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5744 /* Prefer a defined time to an undefined one. */
5745 if (null_timespec(ts
[1])) {
5746 if (null_timespec(write_time
)) {
5747 ts
[1] = changed_time
;
5748 setting_write_time
= false;
5754 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5755 fname
? fname
: fsp
->fsp_name
));
5757 return smb_set_file_time(conn
,
5762 setting_write_time
);
5765 /****************************************************************************
5766 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5767 ****************************************************************************/
5769 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5770 struct smb_request
*req
,
5775 SMB_STRUCT_STAT
*psbuf
)
5777 SMB_BIG_UINT allocation_size
= 0;
5778 NTSTATUS status
= NT_STATUS_OK
;
5779 files_struct
*new_fsp
= NULL
;
5781 if (!VALID_STAT(*psbuf
)) {
5782 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5785 if (total_data
< 8) {
5786 return NT_STATUS_INVALID_PARAMETER
;
5789 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5790 #ifdef LARGE_SMB_OFF_T
5791 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5792 #else /* LARGE_SMB_OFF_T */
5793 if (IVAL(pdata
,4) != 0) {
5794 /* more than 32 bits? */
5795 return NT_STATUS_INVALID_PARAMETER
;
5797 #endif /* LARGE_SMB_OFF_T */
5799 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5800 fname
, (double)allocation_size
));
5802 if (allocation_size
) {
5803 allocation_size
= smb_roundup(conn
, allocation_size
);
5806 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5807 fname
, (double)allocation_size
));
5809 if (fsp
&& fsp
->fh
->fd
!= -1) {
5810 /* Open file handle. */
5811 /* Only change if needed. */
5812 if (allocation_size
!= get_file_size(*psbuf
)) {
5813 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5814 return map_nt_error_from_unix(errno
);
5817 /* But always update the time. */
5819 * This is equivalent to a write. Ensure it's seen immediately
5820 * if there are no pending writes.
5822 trigger_write_time_update_immediate(fsp
);
5823 return NT_STATUS_OK
;
5826 /* Pathname or stat or directory file. */
5828 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5830 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5833 FILE_ATTRIBUTE_NORMAL
,
5834 FORCE_OPLOCK_BREAK_TO_NONE
,
5837 if (!NT_STATUS_IS_OK(status
)) {
5838 /* NB. We check for open_was_deferred in the caller. */
5842 /* Only change if needed. */
5843 if (allocation_size
!= get_file_size(*psbuf
)) {
5844 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5845 status
= map_nt_error_from_unix(errno
);
5846 close_file(new_fsp
,NORMAL_CLOSE
);
5851 /* Changing the allocation size should set the last mod time. */
5853 * This is equivalent to a write. Ensure it's seen immediately
5854 * if there are no pending writes.
5856 trigger_write_time_update_immediate(new_fsp
);
5858 close_file(new_fsp
,NORMAL_CLOSE
);
5859 return NT_STATUS_OK
;
5862 /****************************************************************************
5863 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5864 ****************************************************************************/
5866 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5867 struct smb_request
*req
,
5872 SMB_STRUCT_STAT
*psbuf
)
5876 if (total_data
< 8) {
5877 return NT_STATUS_INVALID_PARAMETER
;
5880 size
= IVAL(pdata
,0);
5881 #ifdef LARGE_SMB_OFF_T
5882 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5883 #else /* LARGE_SMB_OFF_T */
5884 if (IVAL(pdata
,4) != 0) {
5885 /* more than 32 bits? */
5886 return NT_STATUS_INVALID_PARAMETER
;
5888 #endif /* LARGE_SMB_OFF_T */
5889 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5890 "file %s to %.0f\n", fname
, (double)size
));
5892 return smb_set_file_size(conn
, req
,
5899 /****************************************************************************
5900 Allow a UNIX info mknod.
5901 ****************************************************************************/
5903 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5907 SMB_STRUCT_STAT
*psbuf
)
5909 uint32 file_type
= IVAL(pdata
,56);
5910 #if defined(HAVE_MAKEDEV)
5911 uint32 dev_major
= IVAL(pdata
,60);
5912 uint32 dev_minor
= IVAL(pdata
,68);
5914 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5915 uint32 raw_unixmode
= IVAL(pdata
,84);
5919 if (total_data
< 100) {
5920 return NT_STATUS_INVALID_PARAMETER
;
5923 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5924 if (!NT_STATUS_IS_OK(status
)) {
5928 #if defined(HAVE_MAKEDEV)
5929 dev
= makedev(dev_major
, dev_minor
);
5932 switch (file_type
) {
5933 #if defined(S_IFIFO)
5934 case UNIX_TYPE_FIFO
:
5935 unixmode
|= S_IFIFO
;
5938 #if defined(S_IFSOCK)
5939 case UNIX_TYPE_SOCKET
:
5940 unixmode
|= S_IFSOCK
;
5943 #if defined(S_IFCHR)
5944 case UNIX_TYPE_CHARDEV
:
5945 unixmode
|= S_IFCHR
;
5948 #if defined(S_IFBLK)
5949 case UNIX_TYPE_BLKDEV
:
5950 unixmode
|= S_IFBLK
;
5954 return NT_STATUS_INVALID_PARAMETER
;
5957 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5958 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5960 /* Ok - do the mknod. */
5961 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5962 return map_nt_error_from_unix(errno
);
5965 /* If any of the other "set" calls fail we
5966 * don't want to end up with a half-constructed mknod.
5969 if (lp_inherit_perms(SNUM(conn
))) {
5970 inherit_access_posix_acl(
5971 conn
, parent_dirname(fname
),
5975 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5976 status
= map_nt_error_from_unix(errno
);
5977 SMB_VFS_UNLINK(conn
,fname
);
5980 return NT_STATUS_OK
;
5983 /****************************************************************************
5984 Deal with SMB_SET_FILE_UNIX_BASIC.
5985 ****************************************************************************/
5987 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5988 struct smb_request
*req
,
5993 SMB_STRUCT_STAT
*psbuf
)
5995 struct timespec ts
[2];
5996 uint32 raw_unixmode
;
5999 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6000 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6001 NTSTATUS status
= NT_STATUS_OK
;
6002 bool delete_on_fail
= False
;
6003 enum perm_type ptype
;
6004 files_struct
*all_fsps
= NULL
;
6005 bool modify_mtime
= true;
6008 if (total_data
< 100) {
6009 return NT_STATUS_INVALID_PARAMETER
;
6012 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6013 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6014 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6015 #ifdef LARGE_SMB_OFF_T
6016 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6017 #else /* LARGE_SMB_OFF_T */
6018 if (IVAL(pdata
,4) != 0) {
6019 /* more than 32 bits? */
6020 return NT_STATUS_INVALID_PARAMETER
;
6022 #endif /* LARGE_SMB_OFF_T */
6025 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
6026 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
6027 set_owner
= (uid_t
)IVAL(pdata
,40);
6028 set_grp
= (gid_t
)IVAL(pdata
,48);
6029 raw_unixmode
= IVAL(pdata
,84);
6031 if (VALID_STAT(*psbuf
)) {
6032 if (S_ISDIR(psbuf
->st_mode
)) {
6033 ptype
= PERM_EXISTING_DIR
;
6035 ptype
= PERM_EXISTING_FILE
;
6038 ptype
= PERM_NEW_FILE
;
6041 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
6042 if (!NT_STATUS_IS_OK(status
)) {
6046 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6047 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6048 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
6050 if (!VALID_STAT(*psbuf
)) {
6052 * The only valid use of this is to create character and block
6053 * devices, and named pipes. This is deprecated (IMHO) and
6054 * a new info level should be used for mknod. JRA.
6057 status
= smb_unix_mknod(conn
,
6062 if (!NT_STATUS_IS_OK(status
)) {
6066 /* Ensure we don't try and change anything else. */
6067 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6068 size
= get_file_size(*psbuf
);
6069 ts
[0] = get_atimespec(psbuf
);
6070 ts
[1] = get_mtimespec(psbuf
);
6072 * We continue here as we might want to change the
6075 delete_on_fail
= True
;
6079 /* Horrible backwards compatibility hack as an old server bug
6080 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6084 size
= get_file_size(*psbuf
);
6089 * Deal with the UNIX specific mode set.
6092 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6093 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6094 (unsigned int)unixmode
, fname
));
6095 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6096 return map_nt_error_from_unix(errno
);
6101 * Deal with the UNIX specific uid set.
6104 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6107 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6108 (unsigned int)set_owner
, fname
));
6110 if (S_ISLNK(psbuf
->st_mode
)) {
6111 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6113 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6117 status
= map_nt_error_from_unix(errno
);
6118 if (delete_on_fail
) {
6119 SMB_VFS_UNLINK(conn
,fname
);
6126 * Deal with the UNIX specific gid set.
6129 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6130 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6131 (unsigned int)set_owner
, fname
));
6132 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6133 status
= map_nt_error_from_unix(errno
);
6134 if (delete_on_fail
) {
6135 SMB_VFS_UNLINK(conn
,fname
);
6141 /* Deal with any size changes. */
6143 status
= smb_set_file_size(conn
, req
,
6148 if (!NT_STATUS_IS_OK(status
)) {
6152 /* Deal with any time changes. */
6153 id
= vfs_file_id_from_sbuf(conn
, psbuf
);
6154 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6155 all_fsps
= file_find_di_next(all_fsps
)) {
6157 * We're setting the time explicitly for UNIX.
6158 * Cancel any pending changes over all handles.
6160 all_fsps
->update_write_time_on_close
= false;
6161 TALLOC_FREE(all_fsps
->update_write_time_event
);
6165 * Override the "setting_write_time"
6166 * parameter here as it almost does what
6167 * we need. Just remember if we modified
6168 * mtime and send the notify ourselves.
6170 if (null_timespec(ts
[1])) {
6171 modify_mtime
= false;
6174 status
= smb_set_file_time(conn
,
6182 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6183 FILE_NOTIFY_CHANGE_LAST_WRITE
, fname
);
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
= open_directory(conn
, req
,
6291 FILE_READ_ATTRIBUTES
, /* Just a stat open */
6292 FILE_SHARE_NONE
, /* Ignored for stat opens */
6299 if (NT_STATUS_IS_OK(status
)) {
6300 close_file(fsp
, NORMAL_CLOSE
);
6303 info_level_return
= SVAL(pdata
,16);
6305 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6306 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6307 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6308 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6310 *pdata_return_size
= 12;
6313 /* Realloc the data size */
6314 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6315 if (*ppdata
== NULL
) {
6316 *pdata_return_size
= 0;
6317 return NT_STATUS_NO_MEMORY
;
6321 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6322 SSVAL(pdata
,2,0); /* No fnum. */
6323 SIVAL(pdata
,4,info
); /* Was directory created. */
6325 switch (info_level_return
) {
6326 case SMB_QUERY_FILE_UNIX_BASIC
:
6327 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6328 SSVAL(pdata
,10,0); /* Padding. */
6329 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6331 case SMB_QUERY_FILE_UNIX_INFO2
:
6332 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6333 SSVAL(pdata
,10,0); /* Padding. */
6334 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6337 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6338 SSVAL(pdata
,10,0); /* Padding. */
6345 /****************************************************************************
6346 Open/Create a file with POSIX semantics.
6347 ****************************************************************************/
6349 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6350 struct smb_request
*req
,
6354 SMB_STRUCT_STAT
*psbuf
,
6355 int *pdata_return_size
)
6357 bool extended_oplock_granted
= False
;
6358 char *pdata
= *ppdata
;
6360 uint32 wire_open_mode
= 0;
6361 uint32 raw_unixmode
= 0;
6362 uint32 mod_unixmode
= 0;
6363 uint32 create_disp
= 0;
6364 uint32 access_mask
= 0;
6365 uint32 create_options
= 0;
6366 NTSTATUS status
= NT_STATUS_OK
;
6367 mode_t unixmode
= (mode_t
)0;
6368 files_struct
*fsp
= NULL
;
6369 int oplock_request
= 0;
6371 uint16 info_level_return
= 0;
6373 if (total_data
< 18) {
6374 return NT_STATUS_INVALID_PARAMETER
;
6377 flags
= IVAL(pdata
,0);
6378 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6379 if (oplock_request
) {
6380 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6383 wire_open_mode
= IVAL(pdata
,4);
6385 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6386 return smb_posix_mkdir(conn
, req
,
6394 switch (wire_open_mode
& SMB_ACCMODE
) {
6396 access_mask
= FILE_READ_DATA
;
6399 access_mask
= FILE_WRITE_DATA
;
6402 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6405 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6406 (unsigned int)wire_open_mode
));
6407 return NT_STATUS_INVALID_PARAMETER
;
6410 wire_open_mode
&= ~SMB_ACCMODE
;
6412 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6413 create_disp
= FILE_CREATE
;
6414 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6415 create_disp
= FILE_OVERWRITE_IF
;
6416 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6417 create_disp
= FILE_OPEN_IF
;
6418 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
6419 create_disp
= FILE_OPEN
;
6421 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6422 (unsigned int)wire_open_mode
));
6423 return NT_STATUS_INVALID_PARAMETER
;
6426 raw_unixmode
= IVAL(pdata
,8);
6427 /* Next 4 bytes are not yet defined. */
6429 status
= unix_perms_from_wire(conn
,
6432 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6435 if (!NT_STATUS_IS_OK(status
)) {
6439 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6441 if (wire_open_mode
& SMB_O_SYNC
) {
6442 create_options
|= FILE_WRITE_THROUGH
;
6444 if (wire_open_mode
& SMB_O_APPEND
) {
6445 access_mask
|= FILE_APPEND_DATA
;
6447 if (wire_open_mode
& SMB_O_DIRECT
) {
6448 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6451 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6453 (unsigned int)wire_open_mode
,
6454 (unsigned int)unixmode
));
6456 status
= open_file_ntcreate(conn
, req
,
6460 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6462 0, /* no create options yet. */
6468 if (!NT_STATUS_IS_OK(status
)) {
6472 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6473 extended_oplock_granted
= True
;
6476 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6477 extended_oplock_granted
= True
;
6480 info_level_return
= SVAL(pdata
,16);
6482 /* Allocate the correct return size. */
6484 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6485 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6486 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6487 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6489 *pdata_return_size
= 12;
6492 /* Realloc the data size */
6493 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6494 if (*ppdata
== NULL
) {
6495 close_file(fsp
,ERROR_CLOSE
);
6496 *pdata_return_size
= 0;
6497 return NT_STATUS_NO_MEMORY
;
6501 if (extended_oplock_granted
) {
6502 if (flags
& REQUEST_BATCH_OPLOCK
) {
6503 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6505 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6507 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6508 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6510 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6513 SSVAL(pdata
,2,fsp
->fnum
);
6514 SIVAL(pdata
,4,info
); /* Was file created etc. */
6516 switch (info_level_return
) {
6517 case SMB_QUERY_FILE_UNIX_BASIC
:
6518 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6519 SSVAL(pdata
,10,0); /* padding. */
6520 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6522 case SMB_QUERY_FILE_UNIX_INFO2
:
6523 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6524 SSVAL(pdata
,10,0); /* padding. */
6525 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6528 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6529 SSVAL(pdata
,10,0); /* padding. */
6532 return NT_STATUS_OK
;
6535 /****************************************************************************
6536 Delete a file with POSIX semantics.
6537 ****************************************************************************/
6539 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6540 struct smb_request
*req
,
6544 SMB_STRUCT_STAT
*psbuf
)
6546 NTSTATUS status
= NT_STATUS_OK
;
6547 files_struct
*fsp
= NULL
;
6552 struct share_mode_lock
*lck
= NULL
;
6554 if (total_data
< 2) {
6555 return NT_STATUS_INVALID_PARAMETER
;
6558 flags
= SVAL(pdata
,0);
6560 if (!VALID_STAT(*psbuf
)) {
6561 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6564 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6565 !VALID_STAT_OF_DIR(*psbuf
)) {
6566 return NT_STATUS_NOT_A_DIRECTORY
;
6569 DEBUG(10,("smb_posix_unlink: %s %s\n",
6570 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6573 if (VALID_STAT_OF_DIR(*psbuf
)) {
6574 status
= open_directory(conn
, req
,
6578 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6581 FILE_FLAG_POSIX_SEMANTICS
|0777,
6586 status
= open_file_ntcreate(conn
, req
,
6590 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6593 FILE_FLAG_POSIX_SEMANTICS
|0777,
6594 0, /* No oplock, but break existing ones. */
6599 if (!NT_STATUS_IS_OK(status
)) {
6604 * Don't lie to client. If we can't really delete due to
6605 * non-POSIX opens return SHARING_VIOLATION.
6608 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6611 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6612 "lock for file %s\n", fsp
->fsp_name
));
6613 close_file(fsp
, NORMAL_CLOSE
);
6614 return NT_STATUS_INVALID_PARAMETER
;
6618 * See if others still have the file open. If this is the case, then
6619 * don't delete. If all opens are POSIX delete we can set the delete
6620 * on close disposition.
6622 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6623 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6624 if (is_valid_share_mode_entry(e
)) {
6625 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6628 /* Fail with sharing violation. */
6629 close_file(fsp
, NORMAL_CLOSE
);
6631 return NT_STATUS_SHARING_VIOLATION
;
6636 * Set the delete on close.
6638 status
= smb_set_file_disposition_info(conn
,
6645 if (!NT_STATUS_IS_OK(status
)) {
6646 close_file(fsp
, NORMAL_CLOSE
);
6651 return close_file(fsp
, NORMAL_CLOSE
);
6654 /****************************************************************************
6655 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6656 ****************************************************************************/
6658 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6659 struct smb_request
*req
,
6660 unsigned int tran_call
,
6661 char **pparams
, int total_params
,
6662 char **ppdata
, int total_data
,
6663 unsigned int max_data_bytes
)
6665 char *params
= *pparams
;
6666 char *pdata
= *ppdata
;
6668 SMB_STRUCT_STAT sbuf
;
6670 files_struct
*fsp
= NULL
;
6671 NTSTATUS status
= NT_STATUS_OK
;
6672 int data_return_size
= 0;
6673 TALLOC_CTX
*ctx
= talloc_tos();
6676 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6682 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6683 if (total_params
< 4) {
6684 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6688 fsp
= file_fsp(SVAL(params
,0));
6689 /* Basic check for non-null fsp. */
6690 if (!check_fsp_open(conn
, req
, fsp
)) {
6693 info_level
= SVAL(params
,2);
6695 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6697 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6701 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6703 * This is actually a SETFILEINFO on a directory
6704 * handle (returned from an NT SMB). NT5.0 seems
6705 * to do this call. JRA.
6707 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6708 /* Always do lstat for UNIX calls. */
6709 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6710 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6711 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6715 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6716 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6717 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6721 } else if (fsp
->print_file
) {
6723 * Doing a DELETE_ON_CLOSE should cancel a print job.
6725 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6726 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6728 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6731 send_trans2_replies(conn
, req
, params
, 2,
6736 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6741 * Original code - this is an open file.
6743 if (!check_fsp(conn
, req
, fsp
)) {
6747 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6748 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6749 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6755 if (total_params
< 7) {
6756 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6760 info_level
= SVAL(params
,0);
6761 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6762 total_params
- 6, STR_TERMINATE
,
6764 if (!NT_STATUS_IS_OK(status
)) {
6765 reply_nterror(req
, status
);
6769 status
= resolve_dfspath(ctx
, conn
,
6770 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6773 if (!NT_STATUS_IS_OK(status
)) {
6774 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6775 reply_botherror(req
,
6776 NT_STATUS_PATH_NOT_COVERED
,
6777 ERRSRV
, ERRbadpath
);
6780 reply_nterror(req
, status
);
6784 status
= unix_convert(ctx
, conn
, fname
, False
,
6785 &fname
, NULL
, &sbuf
);
6786 if (!NT_STATUS_IS_OK(status
)) {
6787 reply_nterror(req
, status
);
6791 status
= check_name(conn
, fname
);
6792 if (!NT_STATUS_IS_OK(status
)) {
6793 reply_nterror(req
, status
);
6797 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6799 * For CIFS UNIX extensions the target name may not exist.
6802 /* Always do lstat for UNIX calls. */
6803 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6805 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6806 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6807 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6812 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6813 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6817 if (!CAN_WRITE(conn
)) {
6818 /* Allow POSIX opens. The open path will deny
6819 * any non-readonly opens. */
6820 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
6821 reply_doserror(req
, ERRSRV
, ERRaccess
);
6826 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6827 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6829 /* Realloc the parameter size */
6830 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6831 if (*pparams
== NULL
) {
6832 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6839 switch (info_level
) {
6841 case SMB_INFO_STANDARD
:
6843 status
= smb_set_info_standard(conn
,
6852 case SMB_INFO_SET_EA
:
6854 status
= smb_info_set_ea(conn
,
6862 case SMB_SET_FILE_BASIC_INFO
:
6863 case SMB_FILE_BASIC_INFORMATION
:
6865 status
= smb_set_file_basic_info(conn
,
6874 case SMB_FILE_ALLOCATION_INFORMATION
:
6875 case SMB_SET_FILE_ALLOCATION_INFO
:
6877 status
= smb_set_file_allocation_info(conn
, req
,
6886 case SMB_FILE_END_OF_FILE_INFORMATION
:
6887 case SMB_SET_FILE_END_OF_FILE_INFO
:
6889 status
= smb_set_file_end_of_file_info(conn
, req
,
6898 case SMB_FILE_DISPOSITION_INFORMATION
:
6899 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6902 /* JRA - We used to just ignore this on a path ?
6903 * Shouldn't this be invalid level on a pathname
6906 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6907 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6910 status
= smb_set_file_disposition_info(conn
,
6919 case SMB_FILE_POSITION_INFORMATION
:
6921 status
= smb_file_position_information(conn
,
6928 /* From tridge Samba4 :
6929 * MODE_INFORMATION in setfileinfo (I have no
6930 * idea what "mode information" on a file is - it takes a value of 0,
6931 * 2, 4 or 6. What could it be?).
6934 case SMB_FILE_MODE_INFORMATION
:
6936 status
= smb_file_mode_information(conn
,
6943 * CIFS UNIX extensions.
6946 case SMB_SET_FILE_UNIX_BASIC
:
6948 status
= smb_set_file_unix_basic(conn
, req
,
6957 case SMB_SET_FILE_UNIX_INFO2
:
6959 status
= smb_set_file_unix_info2(conn
, req
,
6968 case SMB_SET_FILE_UNIX_LINK
:
6970 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6971 /* We must have a pathname for this. */
6972 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6975 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6980 case SMB_SET_FILE_UNIX_HLINK
:
6982 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6983 /* We must have a pathname for this. */
6984 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6987 status
= smb_set_file_unix_hlink(conn
, req
,
6993 case SMB_FILE_RENAME_INFORMATION
:
6995 status
= smb_file_rename_information(conn
, req
,
7001 #if defined(HAVE_POSIX_ACLS)
7002 case SMB_SET_POSIX_ACL
:
7004 status
= smb_set_posix_acl(conn
,
7014 case SMB_SET_POSIX_LOCK
:
7016 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7017 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7020 status
= smb_set_posix_lock(conn
, req
,
7021 pdata
, total_data
, fsp
);
7025 case SMB_POSIX_PATH_OPEN
:
7027 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7028 /* We must have a pathname for this. */
7029 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7033 status
= smb_posix_open(conn
, req
,
7042 case SMB_POSIX_PATH_UNLINK
:
7044 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7045 /* We must have a pathname for this. */
7046 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7050 status
= smb_posix_unlink(conn
, req
,
7059 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7064 if (!NT_STATUS_IS_OK(status
)) {
7065 if (open_was_deferred(req
->mid
)) {
7066 /* We have re-scheduled this call. */
7069 if (blocking_lock_was_deferred(req
->mid
)) {
7070 /* We have re-scheduled this call. */
7073 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7074 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7075 ERRSRV
, ERRbadpath
);
7078 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7079 reply_openerror(req
, status
);
7083 reply_nterror(req
, status
);
7088 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7094 /****************************************************************************
7095 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7096 ****************************************************************************/
7098 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7099 char **pparams
, int total_params
,
7100 char **ppdata
, int total_data
,
7101 unsigned int max_data_bytes
)
7103 char *params
= *pparams
;
7104 char *pdata
= *ppdata
;
7105 char *directory
= NULL
;
7106 SMB_STRUCT_STAT sbuf
;
7107 NTSTATUS status
= NT_STATUS_OK
;
7108 struct ea_list
*ea_list
= NULL
;
7109 TALLOC_CTX
*ctx
= talloc_tos();
7111 if (!CAN_WRITE(conn
)) {
7112 reply_doserror(req
, ERRSRV
, ERRaccess
);
7116 if (total_params
< 5) {
7117 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7121 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7122 total_params
- 4, STR_TERMINATE
,
7124 if (!NT_STATUS_IS_OK(status
)) {
7125 reply_nterror(req
, status
);
7129 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7131 status
= resolve_dfspath(ctx
,
7133 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7136 if (!NT_STATUS_IS_OK(status
)) {
7137 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7138 reply_botherror(req
,
7139 NT_STATUS_PATH_NOT_COVERED
,
7140 ERRSRV
, ERRbadpath
);
7142 reply_nterror(req
, status
);
7146 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
7147 if (!NT_STATUS_IS_OK(status
)) {
7148 reply_nterror(req
, status
);
7152 status
= check_name(conn
, directory
);
7153 if (!NT_STATUS_IS_OK(status
)) {
7154 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7155 reply_nterror(req
, status
);
7159 /* Any data in this call is an EA list. */
7160 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7161 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7166 * OS/2 workplace shell seems to send SET_EA requests of "null"
7167 * length (4 bytes containing IVAL 4).
7168 * They seem to have no effect. Bug #3212. JRA.
7171 if (total_data
!= 4) {
7172 if (total_data
< 10) {
7173 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7177 if (IVAL(pdata
,0) > total_data
) {
7178 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7179 IVAL(pdata
,0), (unsigned int)total_data
));
7180 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7184 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7187 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7191 /* If total_data == 4 Windows doesn't care what values
7192 * are placed in that field, it just ignores them.
7193 * The System i QNTC IBM SMB client puts bad values here,
7194 * so ignore them. */
7196 status
= create_directory(conn
, req
, directory
);
7198 if (!NT_STATUS_IS_OK(status
)) {
7199 reply_nterror(req
, status
);
7203 /* Try and set any given EA. */
7205 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7206 if (!NT_STATUS_IS_OK(status
)) {
7207 reply_nterror(req
, status
);
7212 /* Realloc the parameter and data sizes */
7213 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7214 if(*pparams
== NULL
) {
7215 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7222 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7227 /****************************************************************************
7228 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7229 We don't actually do this - we just send a null response.
7230 ****************************************************************************/
7232 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7233 struct smb_request
*req
,
7234 char **pparams
, int total_params
,
7235 char **ppdata
, int total_data
,
7236 unsigned int max_data_bytes
)
7238 static uint16 fnf_handle
= 257;
7239 char *params
= *pparams
;
7242 if (total_params
< 6) {
7243 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7247 info_level
= SVAL(params
,4);
7248 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7250 switch (info_level
) {
7255 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7259 /* Realloc the parameter and data sizes */
7260 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7261 if (*pparams
== NULL
) {
7262 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7267 SSVAL(params
,0,fnf_handle
);
7268 SSVAL(params
,2,0); /* No changes */
7269 SSVAL(params
,4,0); /* No EA errors */
7276 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7281 /****************************************************************************
7282 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7283 changes). Currently this does nothing.
7284 ****************************************************************************/
7286 static void call_trans2findnotifynext(connection_struct
*conn
,
7287 struct smb_request
*req
,
7288 char **pparams
, int total_params
,
7289 char **ppdata
, int total_data
,
7290 unsigned int max_data_bytes
)
7292 char *params
= *pparams
;
7294 DEBUG(3,("call_trans2findnotifynext\n"));
7296 /* Realloc the parameter and data sizes */
7297 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7298 if (*pparams
== NULL
) {
7299 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7304 SSVAL(params
,0,0); /* No changes */
7305 SSVAL(params
,2,0); /* No EA errors */
7307 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7312 /****************************************************************************
7313 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7314 ****************************************************************************/
7316 static void call_trans2getdfsreferral(connection_struct
*conn
,
7317 struct smb_request
*req
,
7318 char **pparams
, int total_params
,
7319 char **ppdata
, int total_data
,
7320 unsigned int max_data_bytes
)
7322 char *params
= *pparams
;
7323 char *pathname
= NULL
;
7325 int max_referral_level
;
7326 NTSTATUS status
= NT_STATUS_OK
;
7327 TALLOC_CTX
*ctx
= talloc_tos();
7329 DEBUG(10,("call_trans2getdfsreferral\n"));
7331 if (total_params
< 3) {
7332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7336 max_referral_level
= SVAL(params
,0);
7338 if(!lp_host_msdfs()) {
7339 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7343 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7344 total_params
- 2, STR_TERMINATE
);
7346 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7349 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7350 ppdata
,&status
)) < 0) {
7351 reply_nterror(req
, status
);
7355 SSVAL(req
->inbuf
, smb_flg2
,
7356 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7357 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7362 #define LMCAT_SPL 0x53
7363 #define LMFUNC_GETJOBID 0x60
7365 /****************************************************************************
7366 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7367 ****************************************************************************/
7369 static void call_trans2ioctl(connection_struct
*conn
,
7370 struct smb_request
*req
,
7371 char **pparams
, int total_params
,
7372 char **ppdata
, int total_data
,
7373 unsigned int max_data_bytes
)
7375 char *pdata
= *ppdata
;
7376 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv15
));
7378 /* check for an invalid fid before proceeding */
7381 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7385 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7386 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7387 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7388 if (*ppdata
== NULL
) {
7389 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7394 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7395 CAN ACCEPT THIS IN UNICODE. JRA. */
7397 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7398 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7399 global_myname(), 15,
7400 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7401 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7402 lp_servicename(SNUM(conn
)), 13,
7403 STR_ASCII
|STR_TERMINATE
); /* Service name */
7404 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7409 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7410 reply_doserror(req
, ERRSRV
, ERRerror
);
7413 /****************************************************************************
7414 Reply to a SMBfindclose (stop trans2 directory search).
7415 ****************************************************************************/
7417 void reply_findclose(struct smb_request
*req
)
7421 START_PROFILE(SMBfindclose
);
7424 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7425 END_PROFILE(SMBfindclose
);
7429 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7431 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7433 dptr_close(&dptr_num
);
7435 reply_outbuf(req
, 0, 0);
7437 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7439 END_PROFILE(SMBfindclose
);
7443 /****************************************************************************
7444 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7445 ****************************************************************************/
7447 void reply_findnclose(struct smb_request
*req
)
7451 START_PROFILE(SMBfindnclose
);
7454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7455 END_PROFILE(SMBfindnclose
);
7459 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7461 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7463 /* We never give out valid handles for a
7464 findnotifyfirst - so any dptr_num is ok here.
7467 reply_outbuf(req
, 0, 0);
7469 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7471 END_PROFILE(SMBfindnclose
);
7475 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7476 struct trans_state
*state
)
7478 if (Protocol
>= PROTOCOL_NT1
) {
7479 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7480 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7483 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7484 if (state
->call
!= TRANSACT2_QFSINFO
&&
7485 state
->call
!= TRANSACT2_SETFSINFO
) {
7486 DEBUG(0,("handle_trans2: encryption required "
7488 (unsigned int)state
->call
));
7489 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7494 /* Now we must call the relevant TRANS2 function */
7495 switch(state
->call
) {
7496 case TRANSACT2_OPEN
:
7498 START_PROFILE(Trans2_open
);
7499 call_trans2open(conn
, req
,
7500 &state
->param
, state
->total_param
,
7501 &state
->data
, state
->total_data
,
7502 state
->max_data_return
);
7503 END_PROFILE(Trans2_open
);
7507 case TRANSACT2_FINDFIRST
:
7509 START_PROFILE(Trans2_findfirst
);
7510 call_trans2findfirst(conn
, req
,
7511 &state
->param
, state
->total_param
,
7512 &state
->data
, state
->total_data
,
7513 state
->max_data_return
);
7514 END_PROFILE(Trans2_findfirst
);
7518 case TRANSACT2_FINDNEXT
:
7520 START_PROFILE(Trans2_findnext
);
7521 call_trans2findnext(conn
, req
,
7522 &state
->param
, state
->total_param
,
7523 &state
->data
, state
->total_data
,
7524 state
->max_data_return
);
7525 END_PROFILE(Trans2_findnext
);
7529 case TRANSACT2_QFSINFO
:
7531 START_PROFILE(Trans2_qfsinfo
);
7532 call_trans2qfsinfo(conn
, req
,
7533 &state
->param
, state
->total_param
,
7534 &state
->data
, state
->total_data
,
7535 state
->max_data_return
);
7536 END_PROFILE(Trans2_qfsinfo
);
7540 case TRANSACT2_SETFSINFO
:
7542 START_PROFILE(Trans2_setfsinfo
);
7543 call_trans2setfsinfo(conn
, req
,
7544 &state
->param
, state
->total_param
,
7545 &state
->data
, state
->total_data
,
7546 state
->max_data_return
);
7547 END_PROFILE(Trans2_setfsinfo
);
7551 case TRANSACT2_QPATHINFO
:
7552 case TRANSACT2_QFILEINFO
:
7554 START_PROFILE(Trans2_qpathinfo
);
7555 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7556 &state
->param
, state
->total_param
,
7557 &state
->data
, state
->total_data
,
7558 state
->max_data_return
);
7559 END_PROFILE(Trans2_qpathinfo
);
7563 case TRANSACT2_SETPATHINFO
:
7564 case TRANSACT2_SETFILEINFO
:
7566 START_PROFILE(Trans2_setpathinfo
);
7567 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7568 &state
->param
, state
->total_param
,
7569 &state
->data
, state
->total_data
,
7570 state
->max_data_return
);
7571 END_PROFILE(Trans2_setpathinfo
);
7575 case TRANSACT2_FINDNOTIFYFIRST
:
7577 START_PROFILE(Trans2_findnotifyfirst
);
7578 call_trans2findnotifyfirst(conn
, req
,
7579 &state
->param
, state
->total_param
,
7580 &state
->data
, state
->total_data
,
7581 state
->max_data_return
);
7582 END_PROFILE(Trans2_findnotifyfirst
);
7586 case TRANSACT2_FINDNOTIFYNEXT
:
7588 START_PROFILE(Trans2_findnotifynext
);
7589 call_trans2findnotifynext(conn
, req
,
7590 &state
->param
, state
->total_param
,
7591 &state
->data
, state
->total_data
,
7592 state
->max_data_return
);
7593 END_PROFILE(Trans2_findnotifynext
);
7597 case TRANSACT2_MKDIR
:
7599 START_PROFILE(Trans2_mkdir
);
7600 call_trans2mkdir(conn
, req
,
7601 &state
->param
, state
->total_param
,
7602 &state
->data
, state
->total_data
,
7603 state
->max_data_return
);
7604 END_PROFILE(Trans2_mkdir
);
7608 case TRANSACT2_GET_DFS_REFERRAL
:
7610 START_PROFILE(Trans2_get_dfs_referral
);
7611 call_trans2getdfsreferral(conn
, req
,
7612 &state
->param
, state
->total_param
,
7613 &state
->data
, state
->total_data
,
7614 state
->max_data_return
);
7615 END_PROFILE(Trans2_get_dfs_referral
);
7619 case TRANSACT2_IOCTL
:
7621 START_PROFILE(Trans2_ioctl
);
7622 call_trans2ioctl(conn
, req
,
7623 &state
->param
, state
->total_param
,
7624 &state
->data
, state
->total_data
,
7625 state
->max_data_return
);
7626 END_PROFILE(Trans2_ioctl
);
7631 /* Error in request */
7632 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7633 reply_doserror(req
, ERRSRV
,ERRerror
);
7637 /****************************************************************************
7638 Reply to a SMBtrans2.
7639 ****************************************************************************/
7641 void reply_trans2(struct smb_request
*req
)
7643 connection_struct
*conn
= req
->conn
;
7648 unsigned int tran_call
;
7650 unsigned int av_size
;
7651 struct trans_state
*state
;
7654 START_PROFILE(SMBtrans2
);
7656 if (req
->wct
< 14) {
7657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7658 END_PROFILE(SMBtrans2
);
7662 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7663 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7664 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7665 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7666 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7667 size
= smb_len(req
->inbuf
) + 4;
7668 av_size
= smb_len(req
->inbuf
);
7670 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7671 if (!NT_STATUS_IS_OK(result
)) {
7672 DEBUG(2, ("Got invalid trans2 request: %s\n",
7673 nt_errstr(result
)));
7674 reply_nterror(req
, result
);
7675 END_PROFILE(SMBtrans2
);
7680 switch (tran_call
) {
7681 /* List the allowed trans2 calls on IPC$ */
7682 case TRANSACT2_OPEN
:
7683 case TRANSACT2_GET_DFS_REFERRAL
:
7684 case TRANSACT2_QFILEINFO
:
7685 case TRANSACT2_QFSINFO
:
7686 case TRANSACT2_SETFSINFO
:
7689 reply_doserror(req
, ERRSRV
, ERRaccess
);
7690 END_PROFILE(SMBtrans2
);
7695 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
7696 DEBUG(0, ("talloc failed\n"));
7697 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7698 END_PROFILE(SMBtrans2
);
7702 state
->cmd
= SMBtrans2
;
7704 state
->mid
= req
->mid
;
7705 state
->vuid
= req
->vuid
;
7706 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7707 state
->setup
= NULL
;
7708 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7709 state
->param
= NULL
;
7710 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7712 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7713 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7714 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7715 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7716 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7718 state
->call
= tran_call
;
7720 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7721 is so as a sanity check */
7722 if (state
->setup_count
!= 1) {
7724 * Need to have rc=0 for ioctl to get job id for OS/2.
7725 * Network printing will fail if function is not successful.
7726 * Similar function in reply.c will be used if protocol
7727 * is LANMAN1.0 instead of LM1.2X002.
7728 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7729 * outbuf doesn't have to be set(only job id is used).
7731 if ( (state
->setup_count
== 4)
7732 && (tran_call
== TRANSACT2_IOCTL
)
7733 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7734 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7735 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7737 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7738 DEBUG(2,("Transaction is %d\n",tran_call
));
7740 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7741 END_PROFILE(SMBtrans2
);
7746 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7749 if (state
->total_data
) {
7750 /* Can't use talloc here, the core routines do realloc on the
7751 * params and data. */
7752 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7753 if (state
->data
== NULL
) {
7754 DEBUG(0,("reply_trans2: data malloc fail for %u "
7755 "bytes !\n", (unsigned int)state
->total_data
));
7757 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7758 END_PROFILE(SMBtrans2
);
7762 if (dscnt
> state
->total_data
||
7763 dsoff
+dscnt
< dsoff
) {
7767 if (dsoff
> av_size
||
7769 dsoff
+dscnt
> av_size
) {
7773 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7776 if (state
->total_param
) {
7777 /* Can't use talloc here, the core routines do realloc on the
7778 * params and data. */
7779 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7780 if (state
->param
== NULL
) {
7781 DEBUG(0,("reply_trans: param malloc fail for %u "
7782 "bytes !\n", (unsigned int)state
->total_param
));
7783 SAFE_FREE(state
->data
);
7785 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7786 END_PROFILE(SMBtrans2
);
7790 if (pscnt
> state
->total_param
||
7791 psoff
+pscnt
< psoff
) {
7795 if (psoff
> av_size
||
7797 psoff
+pscnt
> av_size
) {
7801 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7804 state
->received_data
= dscnt
;
7805 state
->received_param
= pscnt
;
7807 if ((state
->received_param
== state
->total_param
) &&
7808 (state
->received_data
== state
->total_data
)) {
7810 handle_trans2(conn
, req
, state
);
7812 SAFE_FREE(state
->data
);
7813 SAFE_FREE(state
->param
);
7815 END_PROFILE(SMBtrans2
);
7819 DLIST_ADD(conn
->pending_trans
, state
);
7821 /* We need to send an interim response then receive the rest
7822 of the parameter/data bytes */
7823 reply_outbuf(req
, 0, 0);
7824 show_msg((char *)req
->outbuf
);
7825 END_PROFILE(SMBtrans2
);
7830 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7831 SAFE_FREE(state
->data
);
7832 SAFE_FREE(state
->param
);
7834 END_PROFILE(SMBtrans2
);
7835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7839 /****************************************************************************
7840 Reply to a SMBtranss2
7841 ****************************************************************************/
7843 void reply_transs2(struct smb_request
*req
)
7845 connection_struct
*conn
= req
->conn
;
7846 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7847 struct trans_state
*state
;
7849 unsigned int av_size
;
7851 START_PROFILE(SMBtranss2
);
7853 show_msg((char *)req
->inbuf
);
7856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7857 END_PROFILE(SMBtranss2
);
7861 size
= smb_len(req
->inbuf
)+4;
7862 av_size
= smb_len(req
->inbuf
);
7864 for (state
= conn
->pending_trans
; state
!= NULL
;
7865 state
= state
->next
) {
7866 if (state
->mid
== req
->mid
) {
7871 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7872 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7873 END_PROFILE(SMBtranss2
);
7877 /* Revise state->total_param and state->total_data in case they have
7878 changed downwards */
7880 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7881 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7882 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7883 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7885 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7886 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7887 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7889 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7890 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7891 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7893 state
->received_param
+= pcnt
;
7894 state
->received_data
+= dcnt
;
7896 if ((state
->received_data
> state
->total_data
) ||
7897 (state
->received_param
> state
->total_param
))
7901 if (pdisp
> state
->total_param
||
7902 pcnt
> state
->total_param
||
7903 pdisp
+pcnt
> state
->total_param
||
7904 pdisp
+pcnt
< pdisp
) {
7908 if (poff
> av_size
||
7910 poff
+pcnt
> av_size
||
7915 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7920 if (ddisp
> state
->total_data
||
7921 dcnt
> state
->total_data
||
7922 ddisp
+dcnt
> state
->total_data
||
7923 ddisp
+dcnt
< ddisp
) {
7927 if (doff
> av_size
||
7929 doff
+dcnt
> av_size
||
7934 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7938 if ((state
->received_param
< state
->total_param
) ||
7939 (state
->received_data
< state
->total_data
)) {
7940 END_PROFILE(SMBtranss2
);
7945 * construct_reply_common will copy smb_com from inbuf to
7946 * outbuf. SMBtranss2 is wrong here.
7948 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7950 handle_trans2(conn
, req
, state
);
7952 DLIST_REMOVE(conn
->pending_trans
, state
);
7953 SAFE_FREE(state
->data
);
7954 SAFE_FREE(state
->param
);
7957 END_PROFILE(SMBtranss2
);
7962 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7963 DLIST_REMOVE(conn
->pending_trans
, state
);
7964 SAFE_FREE(state
->data
);
7965 SAFE_FREE(state
->param
);
7967 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7968 END_PROFILE(SMBtranss2
);