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(req
, 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 (conn
->case_sensitive
)
1091 return strcmp(str
,mask
)==0;
1092 if (StrCaseCmp(str
,mask
) != 0) {
1095 if (dptr_has_wild(conn
->dirptr
)) {
1101 /****************************************************************************
1102 Return the filetype for UNIX extensions.
1103 ****************************************************************************/
1105 static uint32
unix_filetype(mode_t mode
)
1108 return UNIX_TYPE_FILE
;
1109 else if(S_ISDIR(mode
))
1110 return UNIX_TYPE_DIR
;
1112 else if(S_ISLNK(mode
))
1113 return UNIX_TYPE_SYMLINK
;
1116 else if(S_ISCHR(mode
))
1117 return UNIX_TYPE_CHARDEV
;
1120 else if(S_ISBLK(mode
))
1121 return UNIX_TYPE_BLKDEV
;
1124 else if(S_ISFIFO(mode
))
1125 return UNIX_TYPE_FIFO
;
1128 else if(S_ISSOCK(mode
))
1129 return UNIX_TYPE_SOCKET
;
1132 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
1133 return UNIX_TYPE_UNKNOWN
;
1136 /****************************************************************************
1137 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1138 ****************************************************************************/
1140 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1142 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1143 SMB_STRUCT_STAT
*psbuf
,
1145 enum perm_type ptype
,
1150 if (perms
== SMB_MODE_NO_CHANGE
) {
1151 if (!VALID_STAT(*psbuf
)) {
1152 return NT_STATUS_INVALID_PARAMETER
;
1154 *ret_perms
= psbuf
->st_mode
;
1155 return NT_STATUS_OK
;
1159 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1160 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1161 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1162 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1163 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1164 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1165 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1166 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1167 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1169 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1172 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1175 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1180 /* Apply mode mask */
1181 ret
&= lp_create_mask(SNUM(conn
));
1182 /* Add in force bits */
1183 ret
|= lp_force_create_mode(SNUM(conn
));
1186 ret
&= lp_dir_mask(SNUM(conn
));
1187 /* Add in force bits */
1188 ret
|= lp_force_dir_mode(SNUM(conn
));
1190 case PERM_EXISTING_FILE
:
1191 /* Apply mode mask */
1192 ret
&= lp_security_mask(SNUM(conn
));
1193 /* Add in force bits */
1194 ret
|= lp_force_security_mode(SNUM(conn
));
1196 case PERM_EXISTING_DIR
:
1197 /* Apply mode mask */
1198 ret
&= lp_dir_security_mask(SNUM(conn
));
1199 /* Add in force bits */
1200 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1205 return NT_STATUS_OK
;
1208 /****************************************************************************
1209 Needed to show the msdfs symlinks as directories. Modifies psbuf
1210 to be a directory if it's a msdfs link.
1211 ****************************************************************************/
1213 static bool check_msdfs_link(connection_struct
*conn
,
1214 const char *pathname
,
1215 SMB_STRUCT_STAT
*psbuf
)
1217 int saved_errno
= errno
;
1218 if(lp_host_msdfs() &&
1219 lp_msdfs_root(SNUM(conn
)) &&
1220 is_msdfs_link(conn
, pathname
, psbuf
)) {
1222 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1225 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1226 errno
= saved_errno
;
1229 errno
= saved_errno
;
1234 /****************************************************************************
1235 Get a level dependent lanman2 dir entry.
1236 ****************************************************************************/
1238 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1239 connection_struct
*conn
,
1241 const char *path_mask
,
1244 int requires_resume_key
,
1250 int space_remaining
,
1252 bool *got_exact_match
,
1253 int *last_entry_off
,
1254 struct ea_list
*name_list
)
1258 SMB_STRUCT_STAT sbuf
;
1259 const char *mask
= NULL
;
1260 char *pathreal
= NULL
;
1261 const char *fname
= NULL
;
1262 char *p
, *q
, *pdata
= *ppdata
;
1266 SMB_OFF_T file_size
= 0;
1267 SMB_BIG_UINT allocation_size
= 0;
1269 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1270 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1272 char *last_entry_ptr
;
1274 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1275 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1276 bool check_mangled_names
= lp_manglednames(conn
->params
);
1277 char mangled_name
[13]; /* mangled 8.3 name. */
1279 *out_of_space
= False
;
1280 *got_exact_match
= False
;
1282 ZERO_STRUCT(mdate_ts
);
1283 ZERO_STRUCT(adate_ts
);
1284 ZERO_STRUCT(create_date_ts
);
1286 if (!conn
->dirptr
) {
1290 p
= strrchr_m(path_mask
,'/');
1293 mask
= talloc_strdup(ctx
,"*.*");
1303 bool ms_dfs_link
= False
;
1305 /* Needed if we run out of space */
1306 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1307 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1310 * Due to bugs in NT client redirectors we are not using
1311 * resume keys any more - set them to zero.
1312 * Check out the related comments in findfirst/findnext.
1318 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1319 (long)conn
->dirptr
,curr_dirpos
));
1326 * fname may get mangled, dname is never mangled.
1327 * Whenever we're accessing the filesystem we use
1328 * pathreal which is composed from dname.
1334 /* Mangle fname if it's an illegal name. */
1335 if (mangle_must_mangle(dname
,conn
->params
)) {
1336 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1337 continue; /* Error - couldn't mangle. */
1339 fname
= mangled_name
;
1342 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1343 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1346 if(!got_match
&& check_mangled_names
&&
1347 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1349 * It turns out that NT matches wildcards against
1350 * both long *and* short names. This may explain some
1351 * of the wildcard wierdness from old DOS clients
1352 * that some people have been seeing.... JRA.
1354 /* Force the mangling into 8.3. */
1355 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1356 continue; /* Error - couldn't mangle. */
1359 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1360 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1365 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1367 if (dont_descend
&& !isdots
) {
1373 pathreal
= talloc_asprintf(ctx
,
1378 pathreal
= talloc_asprintf(ctx
,
1388 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1389 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1390 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1391 pathreal
,strerror(errno
)));
1392 TALLOC_FREE(pathreal
);
1395 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1396 /* Needed to show the msdfs symlinks as
1399 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1401 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1402 pathreal
,strerror(errno
)));
1403 TALLOC_FREE(pathreal
);
1409 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1411 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1414 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1415 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1416 TALLOC_FREE(pathreal
);
1420 if (!(mode
& aDIR
)) {
1421 file_size
= get_file_size(sbuf
);
1423 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1425 mdate_ts
= get_mtimespec(&sbuf
);
1426 adate_ts
= get_atimespec(&sbuf
);
1427 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1429 if (ask_sharemode
) {
1430 struct timespec write_time_ts
;
1431 struct file_id fileid
;
1433 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1434 get_file_infos(fileid
, NULL
, &write_time_ts
);
1435 if (!null_timespec(write_time_ts
)) {
1436 mdate_ts
= write_time_ts
;
1440 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1441 dos_filetime_timespec(&create_date_ts
);
1442 dos_filetime_timespec(&mdate_ts
);
1443 dos_filetime_timespec(&adate_ts
);
1446 create_date
= convert_timespec_to_time_t(create_date_ts
);
1447 mdate
= convert_timespec_to_time_t(mdate_ts
);
1448 adate
= convert_timespec_to_time_t(adate_ts
);
1450 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1454 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1461 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1463 switch (info_level
) {
1464 case SMB_FIND_INFO_STANDARD
:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key
) {
1470 srv_put_dos_date2(p
,0,create_date
);
1471 srv_put_dos_date2(p
,4,adate
);
1472 srv_put_dos_date2(p
,8,mdate
);
1473 SIVAL(p
,12,(uint32
)file_size
);
1474 SIVAL(p
,16,(uint32
)allocation_size
);
1478 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1479 p
+= ucs2_align(base_data
, p
, 0);
1481 len
= srvstr_push(base_data
, flags2
, p
,
1482 fname
, PTR_DIFF(end_data
, p
),
1484 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1486 SCVAL(nameptr
, -1, len
- 2);
1488 SCVAL(nameptr
, -1, 0);
1492 SCVAL(nameptr
, -1, len
- 1);
1494 SCVAL(nameptr
, -1, 0);
1500 case SMB_FIND_EA_SIZE
:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key
) {
1506 srv_put_dos_date2(p
,0,create_date
);
1507 srv_put_dos_date2(p
,4,adate
);
1508 srv_put_dos_date2(p
,8,mdate
);
1509 SIVAL(p
,12,(uint32
)file_size
);
1510 SIVAL(p
,16,(uint32
)allocation_size
);
1513 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1514 SIVAL(p
,22,ea_size
); /* Extended attributes */
1518 len
= srvstr_push(base_data
, flags2
,
1519 p
, fname
, PTR_DIFF(end_data
, p
),
1520 STR_TERMINATE
| STR_NOALIGN
);
1521 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1534 SCVAL(nameptr
,0,len
);
1536 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1539 case SMB_FIND_EA_LIST
:
1541 struct ea_list
*file_list
= NULL
;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1548 if(requires_resume_key
) {
1552 srv_put_dos_date2(p
,0,create_date
);
1553 srv_put_dos_date2(p
,4,adate
);
1554 srv_put_dos_date2(p
,8,mdate
);
1555 SIVAL(p
,12,(uint32
)file_size
);
1556 SIVAL(p
,16,(uint32
)allocation_size
);
1558 p
+= 22; /* p now points to the EA area. */
1560 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1561 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1568 *out_of_space
= True
;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False
; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1576 len
= srvstr_push(base_data
, flags2
,
1577 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1578 STR_TERMINATE
| STR_NOALIGN
);
1579 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1592 SCVAL(nameptr
,0,len
);
1594 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1602 SIVAL(p
,0,reskey
); p
+= 4;
1603 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1604 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1605 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1606 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1607 SOFF_T(p
,0,file_size
); p
+= 8;
1608 SOFF_T(p
,0,allocation_size
); p
+= 8;
1609 SIVAL(p
,0,nt_extmode
); p
+= 4;
1610 q
= p
; p
+= 4; /* q is placeholder for name length. */
1612 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1613 SIVAL(p
,0,ea_size
); /* Extended attributes */
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3
&& check_mangled_names
) {
1621 if (!name_to_8_3(fname
,mangled_name
,True
,
1623 /* Error - mangle failed ! */
1624 memset(mangled_name
,'\0',12);
1626 mangled_name
[12] = 0;
1627 len
= srvstr_push(base_data
, flags2
,
1628 p
+2, mangled_name
, 24,
1629 STR_UPPER
|STR_UNICODE
);
1631 memset(p
+ 2 + len
,'\0',24 - len
);
1638 len
= srvstr_push(base_data
, flags2
, p
,
1639 fname
, PTR_DIFF(end_data
, p
),
1640 STR_TERMINATE_ASCII
);
1643 SIVAL(p
,0,0); /* Ensure any padding is null. */
1644 len
= PTR_DIFF(p
, pdata
);
1645 len
= (len
+ 3) & ~3;
1650 case SMB_FIND_FILE_DIRECTORY_INFO
:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1653 SIVAL(p
,0,reskey
); p
+= 4;
1654 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1655 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1656 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1657 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1658 SOFF_T(p
,0,file_size
); p
+= 8;
1659 SOFF_T(p
,0,allocation_size
); p
+= 8;
1660 SIVAL(p
,0,nt_extmode
); p
+= 4;
1661 len
= srvstr_push(base_data
, flags2
,
1662 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1663 STR_TERMINATE_ASCII
);
1666 SIVAL(p
,0,0); /* Ensure any padding is null. */
1667 len
= PTR_DIFF(p
, pdata
);
1668 len
= (len
+ 3) & ~3;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1676 SIVAL(p
,0,reskey
); p
+= 4;
1677 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1678 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1679 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1680 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1681 SOFF_T(p
,0,file_size
); p
+= 8;
1682 SOFF_T(p
,0,allocation_size
); p
+= 8;
1683 SIVAL(p
,0,nt_extmode
); p
+= 4;
1684 q
= p
; p
+= 4; /* q is placeholder for name length. */
1686 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1687 SIVAL(p
,0,ea_size
); /* Extended attributes */
1690 len
= srvstr_push(base_data
, flags2
, p
,
1691 fname
, PTR_DIFF(end_data
, p
),
1692 STR_TERMINATE_ASCII
);
1696 SIVAL(p
,0,0); /* Ensure any padding is null. */
1697 len
= PTR_DIFF(p
, pdata
);
1698 len
= (len
+ 3) & ~3;
1703 case SMB_FIND_FILE_NAMES_INFO
:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1706 SIVAL(p
,0,reskey
); p
+= 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len
= srvstr_push(base_data
, flags2
, p
,
1711 fname
, PTR_DIFF(end_data
, p
),
1712 STR_TERMINATE_ASCII
);
1715 SIVAL(p
,0,0); /* Ensure any padding is null. */
1716 len
= PTR_DIFF(p
, pdata
);
1717 len
= (len
+ 3) & ~3;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1725 SIVAL(p
,0,reskey
); p
+= 4;
1726 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1727 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1728 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1729 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1730 SOFF_T(p
,0,file_size
); p
+= 8;
1731 SOFF_T(p
,0,allocation_size
); p
+= 8;
1732 SIVAL(p
,0,nt_extmode
); p
+= 4;
1733 q
= p
; p
+= 4; /* q is placeholder for name length. */
1735 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1736 SIVAL(p
,0,ea_size
); /* Extended attributes */
1739 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1740 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1741 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1742 len
= srvstr_push(base_data
, flags2
, p
,
1743 fname
, PTR_DIFF(end_data
, p
),
1744 STR_TERMINATE_ASCII
);
1747 SIVAL(p
,0,0); /* Ensure any padding is null. */
1748 len
= PTR_DIFF(p
, pdata
);
1749 len
= (len
+ 3) & ~3;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1758 SIVAL(p
,0,reskey
); p
+= 4;
1759 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1760 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1761 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1762 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1763 SOFF_T(p
,0,file_size
); p
+= 8;
1764 SOFF_T(p
,0,allocation_size
); p
+= 8;
1765 SIVAL(p
,0,nt_extmode
); p
+= 4;
1766 q
= p
; p
+= 4; /* q is placeholder for name length */
1768 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1769 SIVAL(p
,0,ea_size
); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3
&& check_mangled_names
) {
1777 if (!name_to_8_3(fname
,mangled_name
,True
,
1779 /* Error - mangle failed ! */
1780 memset(mangled_name
,'\0',12);
1782 mangled_name
[12] = 0;
1783 len
= srvstr_push(base_data
, flags2
,
1784 p
+2, mangled_name
, 24,
1785 STR_UPPER
|STR_UNICODE
);
1788 memset(p
+ 2 + len
,'\0',24 - len
);
1795 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1796 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1797 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1798 len
= srvstr_push(base_data
, flags2
, p
,
1799 fname
, PTR_DIFF(end_data
, p
),
1800 STR_TERMINATE_ASCII
);
1803 SIVAL(p
,0,0); /* Ensure any padding is null. */
1804 len
= PTR_DIFF(p
, pdata
);
1805 len
= (len
+ 3) & ~3;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX
:
1813 case SMB_FIND_FILE_UNIX_INFO2
:
1815 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level
== SMB_FIND_FILE_UNIX
) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p
= store_file_unix_basic(conn
, p
,
1823 len
= srvstr_push(base_data
, flags2
, p
,
1824 fname
, PTR_DIFF(end_data
, p
),
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p
= store_file_unix_basic_info2(conn
, p
,
1832 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1833 PTR_DIFF(end_data
, p
), 0);
1834 SIVAL(nameptr
, 0, len
);
1838 SIVAL(p
,0,0); /* Ensure any padding is null. */
1840 len
= PTR_DIFF(p
, pdata
);
1841 len
= (len
+ 3) & ~3;
1842 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1853 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1856 *out_of_space
= True
;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False
; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1863 /* Advance the data pointer to the next slot */
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct
*conn
,
1874 struct smb_request
*req
,
1875 char **pparams
, int total_params
,
1876 char **ppdata
, int total_data
,
1877 unsigned int max_data_bytes
)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1884 char *params
= *pparams
;
1885 char *pdata
= *ppdata
;
1889 uint16 findfirst_flags
;
1890 bool close_after_first
;
1892 bool requires_resume_key
;
1894 char *directory
= NULL
;
1897 int last_entry_off
=0;
1901 bool finished
= False
;
1902 bool dont_descend
= False
;
1903 bool out_of_space
= False
;
1904 int space_remaining
;
1905 bool mask_contains_wcard
= False
;
1906 SMB_STRUCT_STAT sbuf
;
1907 struct ea_list
*ea_list
= NULL
;
1908 NTSTATUS ntstatus
= NT_STATUS_OK
;
1909 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX
*ctx
= talloc_tos();
1912 if (total_params
< 13) {
1913 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1917 dirtype
= SVAL(params
,0);
1918 maxentries
= SVAL(params
,2);
1919 findfirst_flags
= SVAL(params
,4);
1920 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1921 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1922 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1923 info_level
= SVAL(params
,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1928 info_level
, max_data_bytes
));
1931 /* W2K3 seems to treat zero as 1. */
1935 switch (info_level
) {
1936 case SMB_FIND_INFO_STANDARD
:
1937 case SMB_FIND_EA_SIZE
:
1938 case SMB_FIND_EA_LIST
:
1939 case SMB_FIND_FILE_DIRECTORY_INFO
:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1941 case SMB_FIND_FILE_NAMES_INFO
:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1946 case SMB_FIND_FILE_UNIX
:
1947 case SMB_FIND_FILE_UNIX_INFO2
:
1948 /* Always use filesystem for UNIX mtime query. */
1949 ask_sharemode
= false;
1950 if (!lp_unix_extensions()) {
1951 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1956 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1960 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1961 params
+12, total_params
- 12,
1962 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1963 if (!NT_STATUS_IS_OK(ntstatus
)) {
1964 reply_nterror(req
, ntstatus
);
1968 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1969 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1972 &mask_contains_wcard
);
1973 if (!NT_STATUS_IS_OK(ntstatus
)) {
1974 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1975 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1976 ERRSRV
, ERRbadpath
);
1979 reply_nterror(req
, ntstatus
);
1983 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, &mask
, &sbuf
);
1984 if (!NT_STATUS_IS_OK(ntstatus
)) {
1985 reply_nterror(req
, ntstatus
);
1989 ntstatus
= check_name(conn
, directory
);
1990 if (!NT_STATUS_IS_OK(ntstatus
)) {
1991 reply_nterror(req
, ntstatus
);
1995 p
= strrchr_m(directory
,'/');
1997 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1998 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1999 mask
= talloc_strdup(ctx
,"*");
2001 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2004 mask_contains_wcard
= True
;
2006 directory
= talloc_strdup(talloc_tos(), "./");
2008 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2015 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2017 if (info_level
== SMB_FIND_EA_LIST
) {
2020 if (total_data
< 4) {
2021 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2025 ea_size
= IVAL(pdata
,0);
2026 if (ea_size
!= total_data
) {
2027 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2028 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2033 if (!lp_ea_support(SNUM(conn
))) {
2034 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2038 /* Pull out the list of names. */
2039 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2041 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2046 *ppdata
= (char *)SMB_REALLOC(
2047 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2048 if(*ppdata
== NULL
) {
2049 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2053 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2055 /* Realloc the params space */
2056 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2057 if (*pparams
== NULL
) {
2058 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2063 /* Save the wildcard match and attribs we are using on this directory -
2064 needed as lanman2 assumes these are being saved between calls */
2066 ntstatus
= dptr_create(conn
,
2072 mask_contains_wcard
,
2076 if (!NT_STATUS_IS_OK(ntstatus
)) {
2077 reply_nterror(req
, ntstatus
);
2081 dptr_num
= dptr_dnum(conn
->dirptr
);
2082 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2084 /* We don't need to check for VOL here as this is returned by
2085 a different TRANS2 call. */
2087 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2088 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2089 dont_descend
= True
;
2092 space_remaining
= max_data_bytes
;
2093 out_of_space
= False
;
2095 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2096 bool got_exact_match
= False
;
2098 /* this is a heuristic to avoid seeking the dirptr except when
2099 absolutely necessary. It allows for a filename of about 40 chars */
2100 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2101 out_of_space
= True
;
2104 finished
= !get_lanman2_dir_entry(ctx
,
2107 mask
,dirtype
,info_level
,
2108 requires_resume_key
,dont_descend
,
2111 space_remaining
, &out_of_space
,
2113 &last_entry_off
, ea_list
);
2116 if (finished
&& out_of_space
)
2119 if (!finished
&& !out_of_space
)
2123 * As an optimisation if we know we aren't looking
2124 * for a wildcard name (ie. the name matches the wildcard exactly)
2125 * then we can finish on any (first) match.
2126 * This speeds up large directory searches. JRA.
2132 /* Ensure space_remaining never goes -ve. */
2133 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2134 space_remaining
= 0;
2135 out_of_space
= true;
2137 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2141 /* Check if we can close the dirptr */
2142 if(close_after_first
|| (finished
&& close_if_end
)) {
2143 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2144 dptr_close(&dptr_num
);
2148 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2149 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2150 * the protocol level is less than NT1. Tested with smbclient. JRA.
2151 * This should fix the OS/2 client bug #2335.
2154 if(numentries
== 0) {
2155 dptr_close(&dptr_num
);
2156 if (Protocol
< PROTOCOL_NT1
) {
2157 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2160 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2161 ERRDOS
, ERRbadfile
);
2166 /* At this point pdata points to numentries directory entries. */
2168 /* Set up the return parameter block */
2169 SSVAL(params
,0,dptr_num
);
2170 SSVAL(params
,2,numentries
);
2171 SSVAL(params
,4,finished
);
2172 SSVAL(params
,6,0); /* Never an EA error */
2173 SSVAL(params
,8,last_entry_off
);
2175 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2178 if ((! *directory
) && dptr_path(dptr_num
)) {
2179 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2181 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2185 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2186 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2187 mask
, directory
, dirtype
, numentries
) );
2190 * Force a name mangle here to ensure that the
2191 * mask as an 8.3 name is top of the mangled cache.
2192 * The reasons for this are subtle. Don't remove
2193 * this code unless you know what you are doing
2194 * (see PR#13758). JRA.
2197 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2198 char mangled_name
[13];
2199 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2205 /****************************************************************************
2206 Reply to a TRANS2_FINDNEXT.
2207 ****************************************************************************/
2209 static void call_trans2findnext(connection_struct
*conn
,
2210 struct smb_request
*req
,
2211 char **pparams
, int total_params
,
2212 char **ppdata
, int total_data
,
2213 unsigned int max_data_bytes
)
2215 /* We must be careful here that we don't return more than the
2216 allowed number of data bytes. If this means returning fewer than
2217 maxentries then so be it. We assume that the redirector has
2218 enough room for the fixed number of parameter bytes it has
2220 char *params
= *pparams
;
2221 char *pdata
= *ppdata
;
2227 uint16 findnext_flags
;
2228 bool close_after_request
;
2230 bool requires_resume_key
;
2232 bool mask_contains_wcard
= False
;
2233 char *resume_name
= NULL
;
2234 const char *mask
= NULL
;
2235 const char *directory
= NULL
;
2239 int i
, last_entry_off
=0;
2240 bool finished
= False
;
2241 bool dont_descend
= False
;
2242 bool out_of_space
= False
;
2243 int space_remaining
;
2244 struct ea_list
*ea_list
= NULL
;
2245 NTSTATUS ntstatus
= NT_STATUS_OK
;
2246 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2247 TALLOC_CTX
*ctx
= talloc_tos();
2249 if (total_params
< 13) {
2250 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2254 dptr_num
= SVAL(params
,0);
2255 maxentries
= SVAL(params
,2);
2256 info_level
= SVAL(params
,4);
2257 resume_key
= IVAL(params
,6);
2258 findnext_flags
= SVAL(params
,10);
2259 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2260 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2261 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2262 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
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
);
2284 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2285 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2286 resume_key = %d resume name = %s continue=%d level = %d\n",
2287 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2288 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2291 /* W2K3 seems to treat zero as 1. */
2295 switch (info_level
) {
2296 case SMB_FIND_INFO_STANDARD
:
2297 case SMB_FIND_EA_SIZE
:
2298 case SMB_FIND_EA_LIST
:
2299 case SMB_FIND_FILE_DIRECTORY_INFO
:
2300 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2301 case SMB_FIND_FILE_NAMES_INFO
:
2302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2303 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2304 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2306 case SMB_FIND_FILE_UNIX
:
2307 case SMB_FIND_FILE_UNIX_INFO2
:
2308 /* Always use filesystem for UNIX mtime query. */
2309 ask_sharemode
= false;
2310 if (!lp_unix_extensions()) {
2311 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2316 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2320 if (info_level
== SMB_FIND_EA_LIST
) {
2323 if (total_data
< 4) {
2324 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2328 ea_size
= IVAL(pdata
,0);
2329 if (ea_size
!= total_data
) {
2330 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2336 if (!lp_ea_support(SNUM(conn
))) {
2337 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2341 /* Pull out the list of names. */
2342 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2344 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2349 *ppdata
= (char *)SMB_REALLOC(
2350 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2351 if(*ppdata
== NULL
) {
2352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2357 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2359 /* Realloc the params space */
2360 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2361 if(*pparams
== NULL
) {
2362 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2368 /* Check that the dptr is valid */
2369 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2370 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2374 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2376 /* Get the wildcard mask from the dptr */
2377 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2378 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2379 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2384 directory
= conn
->dirpath
;
2386 /* Get the attr mask from the dptr */
2387 dirtype
= dptr_attr(dptr_num
);
2389 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2390 dptr_num
, mask
, dirtype
,
2392 dptr_TellDir(conn
->dirptr
)));
2394 /* We don't need to check for VOL here as this is returned by
2395 a different TRANS2 call. */
2397 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2398 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2399 dont_descend
= True
;
2402 space_remaining
= max_data_bytes
;
2403 out_of_space
= False
;
2406 * Seek to the correct position. We no longer use the resume key but
2407 * depend on the last file name instead.
2410 if(*resume_name
&& !continue_bit
) {
2413 long current_pos
= 0;
2415 * Remember, name_to_8_3 is called by
2416 * get_lanman2_dir_entry(), so the resume name
2417 * could be mangled. Ensure we check the unmangled name.
2420 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2421 char *new_resume_name
= NULL
;
2422 mangle_lookup_name_from_8_3(ctx
,
2426 if (new_resume_name
) {
2427 resume_name
= new_resume_name
;
2432 * Fix for NT redirector problem triggered by resume key indexes
2433 * changing between directory scans. We now return a resume key of 0
2434 * and instead look for the filename to continue from (also given
2435 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2436 * findfirst/findnext (as is usual) then the directory pointer
2437 * should already be at the correct place.
2440 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2441 } /* end if resume_name && !continue_bit */
2443 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2444 bool got_exact_match
= False
;
2446 /* this is a heuristic to avoid seeking the dirptr except when
2447 absolutely necessary. It allows for a filename of about 40 chars */
2448 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2449 out_of_space
= True
;
2452 finished
= !get_lanman2_dir_entry(ctx
,
2455 mask
,dirtype
,info_level
,
2456 requires_resume_key
,dont_descend
,
2459 space_remaining
, &out_of_space
,
2461 &last_entry_off
, ea_list
);
2464 if (finished
&& out_of_space
)
2467 if (!finished
&& !out_of_space
)
2471 * As an optimisation if we know we aren't looking
2472 * for a wildcard name (ie. the name matches the wildcard exactly)
2473 * then we can finish on any (first) match.
2474 * This speeds up large directory searches. JRA.
2480 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2483 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2484 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2485 mask
, directory
, dirtype
, numentries
) );
2487 /* Check if we can close the dirptr */
2488 if(close_after_request
|| (finished
&& close_if_end
)) {
2489 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2490 dptr_close(&dptr_num
); /* This frees up the saved mask */
2493 /* Set up the return parameter block */
2494 SSVAL(params
,0,numentries
);
2495 SSVAL(params
,2,finished
);
2496 SSVAL(params
,4,0); /* Never an EA error */
2497 SSVAL(params
,6,last_entry_off
);
2499 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2505 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2507 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2511 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2513 SMB_ASSERT(extended_info
!= NULL
);
2515 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2516 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2517 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2518 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2519 #ifdef SAMBA_VERSION_REVISION
2520 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2522 extended_info
->samba_subversion
= 0;
2523 #ifdef SAMBA_VERSION_RC_RELEASE
2524 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2526 #ifdef SAMBA_VERSION_PRE_RELEASE
2527 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2530 #ifdef SAMBA_VERSION_VENDOR_PATCH
2531 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2533 extended_info
->samba_gitcommitdate
= 0;
2534 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2535 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2538 memset(extended_info
->samba_version_string
, 0,
2539 sizeof(extended_info
->samba_version_string
));
2541 snprintf (extended_info
->samba_version_string
,
2542 sizeof(extended_info
->samba_version_string
),
2543 "%s", samba_version_string());
2546 /****************************************************************************
2547 Reply to a TRANS2_QFSINFO (query filesystem info).
2548 ****************************************************************************/
2550 static void call_trans2qfsinfo(connection_struct
*conn
,
2551 struct smb_request
*req
,
2552 char **pparams
, int total_params
,
2553 char **ppdata
, int total_data
,
2554 unsigned int max_data_bytes
)
2556 char *pdata
, *end_data
;
2557 char *params
= *pparams
;
2561 const char *vname
= volume_label(SNUM(conn
));
2562 int snum
= SNUM(conn
);
2563 char *fstype
= lp_fstype(SNUM(conn
));
2564 uint32 additional_flags
= 0;
2566 if (total_params
< 2) {
2567 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2571 info_level
= SVAL(params
,0);
2574 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2575 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2576 "info level (0x%x) on IPC$.\n",
2577 (unsigned int)info_level
));
2578 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2583 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2584 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2585 DEBUG(0,("call_trans2qfsinfo: encryption required "
2586 "and info level 0x%x sent.\n",
2587 (unsigned int)info_level
));
2588 exit_server_cleanly("encryption required "
2594 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2596 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2597 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2598 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2602 *ppdata
= (char *)SMB_REALLOC(
2603 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2604 if (*ppdata
== NULL
) {
2605 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2610 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2611 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2613 switch (info_level
) {
2614 case SMB_INFO_ALLOCATION
:
2616 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2618 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2619 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2623 block_size
= lp_block_size(snum
);
2624 if (bsize
< block_size
) {
2625 SMB_BIG_UINT factor
= block_size
/bsize
;
2630 if (bsize
> block_size
) {
2631 SMB_BIG_UINT factor
= bsize
/block_size
;
2636 bytes_per_sector
= 512;
2637 sectors_per_unit
= bsize
/bytes_per_sector
;
2639 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2640 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2641 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2643 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2644 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2645 SIVAL(pdata
,l1_cUnit
,dsize
);
2646 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2647 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2651 case SMB_INFO_VOLUME
:
2652 /* Return volume name */
2654 * Add volume serial number - hash of a combination of
2655 * the called hostname and the service name.
2657 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2659 * Win2k3 and previous mess this up by sending a name length
2660 * one byte short. I believe only older clients (OS/2 Win9x) use
2661 * this call so try fixing this by adding a terminating null to
2662 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2666 pdata
+l2_vol_szVolLabel
, vname
,
2667 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2668 STR_NOALIGN
|STR_TERMINATE
);
2669 SCVAL(pdata
,l2_vol_cch
,len
);
2670 data_len
= l2_vol_szVolLabel
+ len
;
2671 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2672 (unsigned)st
.st_ctime
, len
, vname
));
2675 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2676 case SMB_FS_ATTRIBUTE_INFORMATION
:
2678 additional_flags
= 0;
2679 #if defined(HAVE_SYS_QUOTAS)
2680 additional_flags
|= FILE_VOLUME_QUOTAS
;
2683 if(lp_nt_acl_support(SNUM(conn
))) {
2684 additional_flags
|= FILE_PERSISTENT_ACLS
;
2687 /* Capabilities are filled in at connection time through STATVFS call */
2688 additional_flags
|= conn
->fs_capabilities
;
2690 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2691 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2692 additional_flags
); /* FS ATTRIBUTES */
2694 SIVAL(pdata
,4,255); /* Max filename component length */
2695 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2696 and will think we can't do long filenames */
2697 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2698 PTR_DIFF(end_data
, pdata
+12),
2701 data_len
= 12 + len
;
2704 case SMB_QUERY_FS_LABEL_INFO
:
2705 case SMB_FS_LABEL_INFORMATION
:
2706 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2707 PTR_DIFF(end_data
, pdata
+4), 0);
2712 case SMB_QUERY_FS_VOLUME_INFO
:
2713 case SMB_FS_VOLUME_INFORMATION
:
2716 * Add volume serial number - hash of a combination of
2717 * the called hostname and the service name.
2719 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2720 (str_checksum(get_local_machine_name())<<16));
2722 /* Max label len is 32 characters. */
2723 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2724 PTR_DIFF(end_data
, pdata
+18),
2726 SIVAL(pdata
,12,len
);
2729 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2730 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2733 case SMB_QUERY_FS_SIZE_INFO
:
2734 case SMB_FS_SIZE_INFORMATION
:
2736 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2738 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2739 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2742 block_size
= lp_block_size(snum
);
2743 if (bsize
< block_size
) {
2744 SMB_BIG_UINT factor
= block_size
/bsize
;
2749 if (bsize
> block_size
) {
2750 SMB_BIG_UINT factor
= bsize
/block_size
;
2755 bytes_per_sector
= 512;
2756 sectors_per_unit
= bsize
/bytes_per_sector
;
2757 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2758 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2759 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2760 SBIG_UINT(pdata
,0,dsize
);
2761 SBIG_UINT(pdata
,8,dfree
);
2762 SIVAL(pdata
,16,sectors_per_unit
);
2763 SIVAL(pdata
,20,bytes_per_sector
);
2767 case SMB_FS_FULL_SIZE_INFORMATION
:
2769 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2771 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2772 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2775 block_size
= lp_block_size(snum
);
2776 if (bsize
< block_size
) {
2777 SMB_BIG_UINT factor
= block_size
/bsize
;
2782 if (bsize
> block_size
) {
2783 SMB_BIG_UINT factor
= bsize
/block_size
;
2788 bytes_per_sector
= 512;
2789 sectors_per_unit
= bsize
/bytes_per_sector
;
2790 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2791 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2792 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2793 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2794 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2795 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2796 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2797 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2801 case SMB_QUERY_FS_DEVICE_INFO
:
2802 case SMB_FS_DEVICE_INFORMATION
:
2804 SIVAL(pdata
,0,0); /* dev type */
2805 SIVAL(pdata
,4,0); /* characteristics */
2808 #ifdef HAVE_SYS_QUOTAS
2809 case SMB_FS_QUOTA_INFORMATION
:
2811 * what we have to send --metze:
2813 * Unknown1: 24 NULL bytes
2814 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2815 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2816 * Quota Flags: 2 byte :
2817 * Unknown3: 6 NULL bytes
2821 * details for Quota Flags:
2823 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2824 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2825 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2826 * 0x0001 Enable Quotas: enable quota for this fs
2830 /* we need to fake up a fsp here,
2831 * because its not send in this call
2834 SMB_NTQUOTA_STRUCT quotas
;
2837 ZERO_STRUCT(quotas
);
2843 if (conn
->server_info
->utok
.uid
!= 0) {
2844 DEBUG(0,("set_user_quota: access_denied "
2845 "service [%s] user [%s]\n",
2846 lp_servicename(SNUM(conn
)),
2847 conn
->server_info
->unix_name
));
2848 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2852 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2853 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2854 reply_doserror(req
, ERRSRV
, ERRerror
);
2860 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2862 /* Unknown1 24 NULL bytes*/
2863 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2864 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2865 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2867 /* Default Soft Quota 8 bytes */
2868 SBIG_UINT(pdata
,24,quotas
.softlim
);
2870 /* Default Hard Quota 8 bytes */
2871 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2873 /* Quota flag 2 bytes */
2874 SSVAL(pdata
,40,quotas
.qflags
);
2876 /* Unknown3 6 NULL bytes */
2882 #endif /* HAVE_SYS_QUOTAS */
2883 case SMB_FS_OBJECTID_INFORMATION
:
2885 unsigned char objid
[16];
2886 struct smb_extended_info extended_info
;
2887 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2888 samba_extended_info_version (&extended_info
);
2889 SIVAL(pdata
,16,extended_info
.samba_magic
);
2890 SIVAL(pdata
,20,extended_info
.samba_version
);
2891 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2892 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2893 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2899 * Query the version and capabilities of the CIFS UNIX extensions
2903 case SMB_QUERY_CIFS_UNIX_INFO
:
2905 bool large_write
= lp_min_receive_file_size() &&
2906 !srv_is_signing_active();
2907 bool large_read
= !srv_is_signing_active();
2908 int encrypt_caps
= 0;
2910 if (!lp_unix_extensions()) {
2911 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2915 switch (conn
->encrypt_level
) {
2921 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2924 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2925 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2926 large_write
= false;
2932 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2933 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2935 /* We have POSIX ACLs, pathname, encryption,
2936 * large read/write, and locking capability. */
2938 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2939 CIFS_UNIX_POSIX_ACLS_CAP
|
2940 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2941 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2942 CIFS_UNIX_EXTATTR_CAP
|
2943 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2945 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2947 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2951 case SMB_QUERY_POSIX_FS_INFO
:
2954 vfs_statvfs_struct svfs
;
2956 if (!lp_unix_extensions()) {
2957 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2961 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2965 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2966 SIVAL(pdata
,4,svfs
.BlockSize
);
2967 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2968 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2969 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2970 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2971 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2972 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2973 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2975 } else if (rc
== EOPNOTSUPP
) {
2976 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2978 #endif /* EOPNOTSUPP */
2980 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2981 reply_doserror(req
, ERRSRV
, ERRerror
);
2987 case SMB_QUERY_POSIX_WHOAMI
:
2993 if (!lp_unix_extensions()) {
2994 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2998 if (max_data_bytes
< 40) {
2999 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
3003 /* We ARE guest if global_sid_Builtin_Guests is
3004 * in our list of SIDs.
3006 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3007 conn
->server_info
->ptok
)) {
3008 flags
|= SMB_WHOAMI_GUEST
;
3011 /* We are NOT guest if global_sid_Authenticated_Users
3012 * is in our list of SIDs.
3014 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3015 conn
->server_info
->ptok
)) {
3016 flags
&= ~SMB_WHOAMI_GUEST
;
3019 /* NOTE: 8 bytes for UID/GID, irrespective of native
3020 * platform size. This matches
3021 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3023 data_len
= 4 /* flags */
3030 + 4 /* pad/reserved */
3031 + (conn
->server_info
->utok
.ngroups
* 8)
3033 + (conn
->server_info
->ptok
->num_sids
*
3037 SIVAL(pdata
, 0, flags
);
3038 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3040 (SMB_BIG_UINT
)conn
->server_info
->utok
.uid
);
3041 SBIG_UINT(pdata
, 16,
3042 (SMB_BIG_UINT
)conn
->server_info
->utok
.gid
);
3045 if (data_len
>= max_data_bytes
) {
3046 /* Potential overflow, skip the GIDs and SIDs. */
3048 SIVAL(pdata
, 24, 0); /* num_groups */
3049 SIVAL(pdata
, 28, 0); /* num_sids */
3050 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3051 SIVAL(pdata
, 36, 0); /* reserved */
3057 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3058 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3060 /* We walk the SID list twice, but this call is fairly
3061 * infrequent, and I don't expect that it's performance
3062 * sensitive -- jpeach
3064 for (i
= 0, sid_bytes
= 0;
3065 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3066 sid_bytes
+= ndr_size_dom_sid(
3067 &conn
->server_info
->ptok
->user_sids
[i
],
3071 /* SID list byte count */
3072 SIVAL(pdata
, 32, sid_bytes
);
3074 /* 4 bytes pad/reserved - must be zero */
3075 SIVAL(pdata
, 36, 0);
3079 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3080 SBIG_UINT(pdata
, data_len
,
3081 (SMB_BIG_UINT
)conn
->server_info
->utok
.groups
[i
]);
3087 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3088 int sid_len
= ndr_size_dom_sid(
3089 &conn
->server_info
->ptok
->user_sids
[i
],
3092 sid_linearize(pdata
+ data_len
, sid_len
,
3093 &conn
->server_info
->ptok
->user_sids
[i
]);
3094 data_len
+= sid_len
;
3100 case SMB_MAC_QUERY_FS_INFO
:
3102 * Thursby MAC extension... ONLY on NTFS filesystems
3103 * once we do streams then we don't need this
3105 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3107 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3112 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3117 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3120 DEBUG( 4, ( "%s info_level = %d\n",
3121 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
3126 /****************************************************************************
3127 Reply to a TRANS2_SETFSINFO (set filesystem info).
3128 ****************************************************************************/
3130 static void call_trans2setfsinfo(connection_struct
*conn
,
3131 struct smb_request
*req
,
3132 char **pparams
, int total_params
,
3133 char **ppdata
, int total_data
,
3134 unsigned int max_data_bytes
)
3136 char *pdata
= *ppdata
;
3137 char *params
= *pparams
;
3140 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3143 if (total_params
< 4) {
3144 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3146 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3150 info_level
= SVAL(params
,2);
3153 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3154 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3155 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3156 "info level (0x%x) on IPC$.\n",
3157 (unsigned int)info_level
));
3158 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3163 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3164 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3165 DEBUG(0,("call_trans2setfsinfo: encryption required "
3166 "and info level 0x%x sent.\n",
3167 (unsigned int)info_level
));
3168 exit_server_cleanly("encryption required "
3174 switch(info_level
) {
3175 case SMB_SET_CIFS_UNIX_INFO
:
3177 uint16 client_unix_major
;
3178 uint16 client_unix_minor
;
3179 uint32 client_unix_cap_low
;
3180 uint32 client_unix_cap_high
;
3182 if (!lp_unix_extensions()) {
3184 NT_STATUS_INVALID_LEVEL
);
3188 /* There should be 12 bytes of capabilities set. */
3189 if (total_data
< 8) {
3192 NT_STATUS_INVALID_PARAMETER
);
3195 client_unix_major
= SVAL(pdata
,0);
3196 client_unix_minor
= SVAL(pdata
,2);
3197 client_unix_cap_low
= IVAL(pdata
,4);
3198 client_unix_cap_high
= IVAL(pdata
,8);
3199 /* Just print these values for now. */
3200 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3201 cap_low = 0x%x, cap_high = 0x%x\n",
3202 (unsigned int)client_unix_major
,
3203 (unsigned int)client_unix_minor
,
3204 (unsigned int)client_unix_cap_low
,
3205 (unsigned int)client_unix_cap_high
));
3207 /* Here is where we must switch to posix pathname processing... */
3208 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3209 lp_set_posix_pathnames();
3210 mangle_change_to_posix();
3213 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3214 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3215 /* Client that knows how to do posix locks,
3216 * but not posix open/mkdir operations. Set a
3217 * default type for read/write checks. */
3219 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3225 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3228 size_t param_len
= 0;
3229 size_t data_len
= total_data
;
3231 if (!lp_unix_extensions()) {
3234 NT_STATUS_INVALID_LEVEL
);
3238 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3241 NT_STATUS_NOT_SUPPORTED
);
3245 DEBUG( 4,("call_trans2setfsinfo: "
3246 "request transport encryption.\n"));
3248 status
= srv_request_encryption_setup(conn
,
3249 (unsigned char **)ppdata
,
3251 (unsigned char **)pparams
,
3254 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3255 !NT_STATUS_IS_OK(status
)) {
3256 reply_nterror(req
, status
);
3260 send_trans2_replies(conn
, req
,
3267 if (NT_STATUS_IS_OK(status
)) {
3268 /* Server-side transport
3269 * encryption is now *on*. */
3270 status
= srv_encryption_start(conn
);
3271 if (!NT_STATUS_IS_OK(status
)) {
3272 exit_server_cleanly(
3273 "Failure in setting "
3274 "up encrypted transport");
3280 case SMB_FS_QUOTA_INFORMATION
:
3282 files_struct
*fsp
= NULL
;
3283 SMB_NTQUOTA_STRUCT quotas
;
3285 ZERO_STRUCT(quotas
);
3288 if ((conn
->server_info
->utok
.uid
!= 0)
3289 ||!CAN_WRITE(conn
)) {
3290 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3291 lp_servicename(SNUM(conn
)),
3292 conn
->server_info
->unix_name
));
3293 reply_doserror(req
, ERRSRV
, ERRaccess
);
3297 /* note: normaly there're 48 bytes,
3298 * but we didn't use the last 6 bytes for now
3301 fsp
= file_fsp(req
, SVAL(params
,0));
3303 if (!check_fsp_ntquota_handle(conn
, req
,
3305 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3307 req
, NT_STATUS_INVALID_HANDLE
);
3311 if (total_data
< 42) {
3312 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3316 NT_STATUS_INVALID_PARAMETER
);
3320 /* unknown_1 24 NULL bytes in pdata*/
3322 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3323 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3324 #ifdef LARGE_SMB_OFF_T
3325 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3326 #else /* LARGE_SMB_OFF_T */
3327 if ((IVAL(pdata
,28) != 0)&&
3328 ((quotas
.softlim
!= 0xFFFFFFFF)||
3329 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3330 /* more than 32 bits? */
3333 NT_STATUS_INVALID_PARAMETER
);
3336 #endif /* LARGE_SMB_OFF_T */
3338 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3339 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3340 #ifdef LARGE_SMB_OFF_T
3341 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3342 #else /* LARGE_SMB_OFF_T */
3343 if ((IVAL(pdata
,36) != 0)&&
3344 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3345 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3346 /* more than 32 bits? */
3349 NT_STATUS_INVALID_PARAMETER
);
3352 #endif /* LARGE_SMB_OFF_T */
3354 /* quota_flags 2 bytes **/
3355 quotas
.qflags
= SVAL(pdata
,40);
3357 /* unknown_2 6 NULL bytes follow*/
3359 /* now set the quotas */
3360 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3361 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3362 reply_doserror(req
, ERRSRV
, ERRerror
);
3369 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3371 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3377 * sending this reply works fine,
3378 * but I'm not sure it's the same
3379 * like windows do...
3382 reply_outbuf(req
, 10, 0);
3385 #if defined(HAVE_POSIX_ACLS)
3386 /****************************************************************************
3387 Utility function to count the number of entries in a POSIX acl.
3388 ****************************************************************************/
3390 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3392 unsigned int ace_count
= 0;
3393 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3394 SMB_ACL_ENTRY_T entry
;
3396 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3398 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3399 entry_id
= SMB_ACL_NEXT_ENTRY
;
3406 /****************************************************************************
3407 Utility function to marshall a POSIX acl into wire format.
3408 ****************************************************************************/
3410 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3412 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3413 SMB_ACL_ENTRY_T entry
;
3415 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3416 SMB_ACL_TAG_T tagtype
;
3417 SMB_ACL_PERMSET_T permset
;
3418 unsigned char perms
= 0;
3419 unsigned int own_grp
;
3422 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3423 entry_id
= SMB_ACL_NEXT_ENTRY
;
3426 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3427 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3431 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3432 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3436 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3437 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3438 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3440 SCVAL(pdata
,1,perms
);
3443 case SMB_ACL_USER_OBJ
:
3444 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3445 own_grp
= (unsigned int)pst
->st_uid
;
3446 SIVAL(pdata
,2,own_grp
);
3451 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3456 own_grp
= (unsigned int)*puid
;
3457 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3458 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3459 SIVAL(pdata
,2,own_grp
);
3463 case SMB_ACL_GROUP_OBJ
:
3464 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3465 own_grp
= (unsigned int)pst
->st_gid
;
3466 SIVAL(pdata
,2,own_grp
);
3471 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3473 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3476 own_grp
= (unsigned int)*pgid
;
3477 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3478 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3479 SIVAL(pdata
,2,own_grp
);
3484 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3485 SIVAL(pdata
,2,0xFFFFFFFF);
3486 SIVAL(pdata
,6,0xFFFFFFFF);
3489 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3490 SIVAL(pdata
,2,0xFFFFFFFF);
3491 SIVAL(pdata
,6,0xFFFFFFFF);
3494 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3497 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3504 /****************************************************************************
3505 Store the FILE_UNIX_BASIC info.
3506 ****************************************************************************/
3508 static char *store_file_unix_basic(connection_struct
*conn
,
3511 const SMB_STRUCT_STAT
*psbuf
)
3513 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3514 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3516 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3519 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3522 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3523 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3524 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3527 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3531 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3535 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3538 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3542 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3546 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3549 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3553 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3560 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3561 * the chflags(2) (or equivalent) flags.
3563 * XXX: this really should be behind the VFS interface. To do this, we would
3564 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3565 * Each VFS module could then implement its own mapping as appropriate for the
3566 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3568 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3572 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3576 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3580 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3584 { UF_HIDDEN
, EXT_HIDDEN
},
3587 /* Do not remove. We need to guarantee that this array has at least one
3588 * entry to build on HP-UX.
3594 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3595 uint32
*smb_fflags
, uint32
*smb_fmask
)
3597 #ifdef HAVE_STAT_ST_FLAGS
3600 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3601 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3602 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3603 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3606 #endif /* HAVE_STAT_ST_FLAGS */
3609 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3610 const uint32 smb_fflags
,
3611 const uint32 smb_fmask
,
3614 #ifdef HAVE_STAT_ST_FLAGS
3615 uint32 max_fmask
= 0;
3618 *stat_fflags
= psbuf
->st_flags
;
3620 /* For each flags requested in smb_fmask, check the state of the
3621 * corresponding flag in smb_fflags and set or clear the matching
3625 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3626 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3627 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3628 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3629 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3631 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3636 /* If smb_fmask is asking to set any bits that are not supported by
3637 * our flag mappings, we should fail.
3639 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3646 #endif /* HAVE_STAT_ST_FLAGS */
3650 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3651 * of file flags and birth (create) time.
3653 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3656 const SMB_STRUCT_STAT
*psbuf
)
3658 uint32 file_flags
= 0;
3659 uint32 flags_mask
= 0;
3661 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3663 /* Create (birth) time 64 bit */
3664 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3667 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3668 SIVAL(pdata
, 0, file_flags
); /* flags */
3669 SIVAL(pdata
, 4, flags_mask
); /* mask */
3675 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3676 const struct stream_struct
*streams
,
3678 unsigned int max_data_bytes
,
3679 unsigned int *data_size
)
3682 unsigned int ofs
= 0;
3684 for (i
=0; i
<num_streams
; i
++) {
3685 unsigned int next_offset
;
3687 smb_ucs2_t
*namebuf
;
3689 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3690 streams
[i
].name
, &namelen
) ||
3693 return NT_STATUS_INVALID_PARAMETER
;
3697 * name_buf is now null-terminated, we need to marshall as not
3703 if (ofs
+ 24 + namelen
> max_data_bytes
) {
3704 TALLOC_FREE(namebuf
);
3705 return NT_STATUS_BUFFER_TOO_SMALL
;
3708 SIVAL(data
, ofs
+4, namelen
);
3709 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3710 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3711 memcpy(data
+ofs
+24, namebuf
, namelen
);
3712 TALLOC_FREE(namebuf
);
3714 next_offset
= ofs
+ 24 + namelen
;
3716 if (i
== num_streams
-1) {
3717 SIVAL(data
, ofs
, 0);
3720 unsigned int align
= ndr_align_size(next_offset
, 8);
3722 if (next_offset
+ align
> max_data_bytes
) {
3723 return NT_STATUS_BUFFER_TOO_SMALL
;
3726 memset(data
+next_offset
, 0, align
);
3727 next_offset
+= align
;
3729 SIVAL(data
, ofs
, next_offset
- ofs
);
3738 return NT_STATUS_OK
;
3741 /****************************************************************************
3742 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3743 ****************************************************************************/
3745 static void call_trans2qpipeinfo(connection_struct
*conn
,
3746 struct smb_request
*req
,
3747 unsigned int tran_call
,
3748 char **pparams
, int total_params
,
3749 char **ppdata
, int total_data
,
3750 unsigned int max_data_bytes
)
3752 char *params
= *pparams
;
3753 char *pdata
= *ppdata
;
3754 unsigned int data_size
= 0;
3755 unsigned int param_size
= 2;
3760 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3764 if (total_params
< 4) {
3765 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3769 fsp
= file_fsp(req
, SVAL(params
,0));
3770 if (!fsp_is_np(fsp
)) {
3771 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3775 info_level
= SVAL(params
,2);
3777 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3778 if (*pparams
== NULL
) {
3779 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3784 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3785 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3786 if (*ppdata
== NULL
) {
3787 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3792 switch (info_level
) {
3793 case SMB_FILE_STANDARD_INFORMATION
:
3795 SOFF_T(pdata
,0,4096LL);
3802 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3806 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3812 /****************************************************************************
3813 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3814 file name or file id).
3815 ****************************************************************************/
3817 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3818 struct smb_request
*req
,
3819 unsigned int tran_call
,
3820 char **pparams
, int total_params
,
3821 char **ppdata
, int total_data
,
3822 unsigned int max_data_bytes
)
3824 char *params
= *pparams
;
3825 char *pdata
= *ppdata
;
3826 char *dstart
, *dend
;
3830 SMB_OFF_T file_size
=0;
3831 SMB_BIG_UINT allocation_size
=0;
3832 unsigned int data_size
= 0;
3833 unsigned int param_size
= 2;
3834 SMB_STRUCT_STAT sbuf
;
3835 char *dos_fname
= NULL
;
3841 bool delete_pending
= False
;
3843 time_t create_time
, mtime
, atime
;
3844 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3845 struct timespec write_time_ts
;
3846 files_struct
*fsp
= NULL
;
3847 struct file_id fileid
;
3848 struct ea_list
*ea_list
= NULL
;
3849 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3850 char *lock_data
= NULL
;
3851 bool ms_dfs_link
= false;
3852 TALLOC_CTX
*ctx
= talloc_tos();
3855 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3860 ZERO_STRUCT(write_time_ts
);
3862 if (tran_call
== TRANSACT2_QFILEINFO
) {
3863 if (total_params
< 4) {
3864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3869 call_trans2qpipeinfo(conn
, req
, tran_call
,
3870 pparams
, total_params
,
3876 fsp
= file_fsp(req
, SVAL(params
,0));
3877 info_level
= SVAL(params
,2);
3879 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3881 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3882 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3886 /* Initial check for valid fsp ptr. */
3887 if (!check_fsp_open(conn
, req
, fsp
)) {
3891 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3893 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3897 if(fsp
->fake_file_handle
) {
3899 * This is actually for the QUOTA_FAKE_FILE --metze
3902 /* We know this name is ok, it's already passed the checks. */
3904 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3906 * This is actually a QFILEINFO on a directory
3907 * handle (returned from an NT SMB). NT5.0 seems
3908 * to do this call. JRA.
3911 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3912 /* Always do lstat for UNIX calls. */
3913 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3914 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3915 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3918 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3919 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3920 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3924 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3925 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3928 * Original code - this is an open file.
3930 if (!check_fsp(conn
, req
, fsp
)) {
3934 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3935 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3936 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3939 pos
= fsp
->fh
->position_information
;
3940 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3941 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3942 access_mask
= fsp
->access_mask
;
3946 NTSTATUS status
= NT_STATUS_OK
;
3949 if (total_params
< 7) {
3950 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3954 info_level
= SVAL(params
,0);
3956 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3958 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3959 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3963 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3965 STR_TERMINATE
, &status
);
3966 if (!NT_STATUS_IS_OK(status
)) {
3967 reply_nterror(req
, status
);
3971 status
= resolve_dfspath(ctx
,
3973 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3976 if (!NT_STATUS_IS_OK(status
)) {
3977 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3978 reply_botherror(req
,
3979 NT_STATUS_PATH_NOT_COVERED
,
3980 ERRSRV
, ERRbadpath
);
3982 reply_nterror(req
, status
);
3986 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3987 if (!NT_STATUS_IS_OK(status
)) {
3988 reply_nterror(req
, status
);
3991 status
= check_name(conn
, fname
);
3992 if (!NT_STATUS_IS_OK(status
)) {
3993 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3994 reply_nterror(req
, status
);
3998 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3999 /* Always do lstat for UNIX calls. */
4000 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4001 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4002 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4006 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4007 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4010 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4011 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4016 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4017 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4018 if (delete_pending
) {
4019 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4024 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4025 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4029 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4030 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4032 p
= strrchr_m(fname
,'/');
4039 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4041 mode
= dos_mode(conn
,fname
,&sbuf
);
4044 mode
= FILE_ATTRIBUTE_NORMAL
;
4046 nlink
= sbuf
.st_nlink
;
4048 if (nlink
&& (mode
&aDIR
)) {
4052 if ((nlink
> 0) && delete_pending
) {
4056 fullpathname
= fname
;
4058 file_size
= get_file_size(sbuf
);
4060 /* Pull out any data sent here before we realloc. */
4061 switch (info_level
) {
4062 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4064 /* Pull any EA list from the data portion. */
4067 if (total_data
< 4) {
4069 req
, NT_STATUS_INVALID_PARAMETER
);
4072 ea_size
= IVAL(pdata
,0);
4074 if (total_data
> 0 && ea_size
!= total_data
) {
4075 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4076 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4078 req
, NT_STATUS_INVALID_PARAMETER
);
4082 if (!lp_ea_support(SNUM(conn
))) {
4083 reply_doserror(req
, ERRDOS
,
4084 ERReasnotsupported
);
4088 /* Pull out the list of names. */
4089 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4092 req
, NT_STATUS_INVALID_PARAMETER
);
4098 case SMB_QUERY_POSIX_LOCK
:
4100 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4101 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4105 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4107 req
, NT_STATUS_INVALID_PARAMETER
);
4111 /* Copy the lock range data. */
4112 lock_data
= (char *)TALLOC_MEMDUP(
4113 ctx
, pdata
, total_data
);
4115 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4123 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4124 if (*pparams
== NULL
) {
4125 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4130 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4131 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4132 if (*ppdata
== NULL
) {
4133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4138 dend
= dstart
+ data_size
- 1;
4140 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4141 mtime_ts
= get_mtimespec(&sbuf
);
4142 atime_ts
= get_atimespec(&sbuf
);
4144 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
4147 /* Do we have this path open ? */
4149 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4150 fsp1
= file_find_di_first(fileid
);
4151 if (fsp1
&& fsp1
->initial_allocation_size
) {
4152 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
4156 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4157 mtime_ts
= write_time_ts
;
4160 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4161 dos_filetime_timespec(&create_time_ts
);
4162 dos_filetime_timespec(&mtime_ts
);
4163 dos_filetime_timespec(&atime_ts
);
4166 create_time
= convert_timespec_to_time_t(create_time_ts
);
4167 mtime
= convert_timespec_to_time_t(mtime_ts
);
4168 atime
= convert_timespec_to_time_t(atime_ts
);
4170 /* NT expects the name to be in an exact form of the *full*
4171 filename. See the trans2 torture test */
4172 if (ISDOT(base_name
)) {
4173 dos_fname
= talloc_strdup(ctx
, "\\");
4175 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4179 dos_fname
= talloc_asprintf(ctx
,
4183 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4186 string_replace(dos_fname
, '/', '\\');
4189 switch (info_level
) {
4190 case SMB_INFO_STANDARD
:
4191 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4193 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4194 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4195 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4196 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4197 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4198 SSVAL(pdata
,l1_attrFile
,mode
);
4201 case SMB_INFO_QUERY_EA_SIZE
:
4203 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4206 srv_put_dos_date2(pdata
,0,create_time
);
4207 srv_put_dos_date2(pdata
,4,atime
);
4208 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4209 SIVAL(pdata
,12,(uint32
)file_size
);
4210 SIVAL(pdata
,16,(uint32
)allocation_size
);
4211 SSVAL(pdata
,20,mode
);
4212 SIVAL(pdata
,22,ea_size
);
4216 case SMB_INFO_IS_NAME_VALID
:
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4218 if (tran_call
== TRANSACT2_QFILEINFO
) {
4219 /* os/2 needs this ? really ?*/
4220 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4227 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4229 size_t total_ea_len
= 0;
4230 struct ea_list
*ea_file_list
= NULL
;
4232 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4234 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4235 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4237 if (!ea_list
|| (total_ea_len
> data_size
)) {
4239 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4243 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4247 case SMB_INFO_QUERY_ALL_EAS
:
4249 /* We have data_size bytes to put EA's into. */
4250 size_t total_ea_len
= 0;
4252 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4254 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4255 if (!ea_list
|| (total_ea_len
> data_size
)) {
4257 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4261 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4265 case SMB_FILE_BASIC_INFORMATION
:
4266 case SMB_QUERY_FILE_BASIC_INFO
:
4268 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4269 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4270 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4272 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4276 put_long_date_timespec(pdata
,create_time_ts
);
4277 put_long_date_timespec(pdata
+8,atime_ts
);
4278 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4279 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4280 SIVAL(pdata
,32,mode
);
4282 DEBUG(5,("SMB_QFBI - "));
4283 DEBUG(5,("create: %s ", ctime(&create_time
)));
4284 DEBUG(5,("access: %s ", ctime(&atime
)));
4285 DEBUG(5,("write: %s ", ctime(&mtime
)));
4286 DEBUG(5,("change: %s ", ctime(&mtime
)));
4287 DEBUG(5,("mode: %x\n", mode
));
4290 case SMB_FILE_STANDARD_INFORMATION
:
4291 case SMB_QUERY_FILE_STANDARD_INFO
:
4293 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4295 SOFF_T(pdata
,0,allocation_size
);
4296 SOFF_T(pdata
,8,file_size
);
4297 SIVAL(pdata
,16,nlink
);
4298 SCVAL(pdata
,20,delete_pending
?1:0);
4299 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4300 SSVAL(pdata
,22,0); /* Padding. */
4303 case SMB_FILE_EA_INFORMATION
:
4304 case SMB_QUERY_FILE_EA_INFO
:
4306 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4307 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4309 SIVAL(pdata
,0,ea_size
);
4313 /* Get the 8.3 name - used if NT SMB was negotiated. */
4314 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4315 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4317 char mangled_name
[13];
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4319 if (!name_to_8_3(base_name
,mangled_name
,
4320 True
,conn
->params
)) {
4323 NT_STATUS_NO_MEMORY
);
4325 len
= srvstr_push(dstart
, req
->flags2
,
4326 pdata
+4, mangled_name
,
4327 PTR_DIFF(dend
, pdata
+4),
4329 data_size
= 4 + len
;
4334 case SMB_QUERY_FILE_NAME_INFO
:
4336 this must be *exactly* right for ACLs on mapped drives to work
4338 len
= srvstr_push(dstart
, req
->flags2
,
4340 PTR_DIFF(dend
, pdata
+4),
4342 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4343 data_size
= 4 + len
;
4347 case SMB_FILE_ALLOCATION_INFORMATION
:
4348 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4351 SOFF_T(pdata
,0,allocation_size
);
4354 case SMB_FILE_END_OF_FILE_INFORMATION
:
4355 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4356 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4358 SOFF_T(pdata
,0,file_size
);
4361 case SMB_QUERY_FILE_ALL_INFO
:
4362 case SMB_FILE_ALL_INFORMATION
:
4364 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4365 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4366 put_long_date_timespec(pdata
,create_time_ts
);
4367 put_long_date_timespec(pdata
+8,atime_ts
);
4368 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4369 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4370 SIVAL(pdata
,32,mode
);
4371 SIVAL(pdata
,36,0); /* padding. */
4373 SOFF_T(pdata
,0,allocation_size
);
4374 SOFF_T(pdata
,8,file_size
);
4375 SIVAL(pdata
,16,nlink
);
4376 SCVAL(pdata
,20,delete_pending
);
4377 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4380 SIVAL(pdata
,0,ea_size
);
4381 pdata
+= 4; /* EA info */
4382 len
= srvstr_push(dstart
, req
->flags2
,
4384 PTR_DIFF(dend
, pdata
+4),
4388 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4391 case SMB_FILE_INTERNAL_INFORMATION
:
4392 /* This should be an index number - looks like
4395 I think this causes us to fail the IFSKIT
4396 BasicFileInformationTest. -tpot */
4398 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4399 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4400 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4404 case SMB_FILE_ACCESS_INFORMATION
:
4405 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4406 SIVAL(pdata
,0,access_mask
);
4410 case SMB_FILE_NAME_INFORMATION
:
4411 /* Pathname with leading '\'. */
4414 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4415 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4416 SIVAL(pdata
,0,byte_len
);
4417 data_size
= 4 + byte_len
;
4421 case SMB_FILE_DISPOSITION_INFORMATION
:
4422 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4424 SCVAL(pdata
,0,delete_pending
);
4427 case SMB_FILE_POSITION_INFORMATION
:
4428 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4430 SOFF_T(pdata
,0,pos
);
4433 case SMB_FILE_MODE_INFORMATION
:
4434 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4435 SIVAL(pdata
,0,mode
);
4439 case SMB_FILE_ALIGNMENT_INFORMATION
:
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4441 SIVAL(pdata
,0,0); /* No alignment needed. */
4446 * NT4 server just returns "invalid query" to this - if we try
4447 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4450 /* The first statement above is false - verified using Thursby
4451 * client against NT4 -- gcolley.
4453 case SMB_QUERY_FILE_STREAM_INFO
:
4454 case SMB_FILE_STREAM_INFORMATION
: {
4455 unsigned int num_streams
;
4456 struct stream_struct
*streams
;
4459 DEBUG(10,("call_trans2qfilepathinfo: "
4460 "SMB_FILE_STREAM_INFORMATION\n"));
4462 status
= SMB_VFS_STREAMINFO(
4463 conn
, fsp
, fname
, talloc_tos(),
4464 &num_streams
, &streams
);
4466 if (!NT_STATUS_IS_OK(status
)) {
4467 DEBUG(10, ("could not get stream info: %s\n",
4468 nt_errstr(status
)));
4469 reply_nterror(req
, status
);
4473 status
= marshall_stream_info(num_streams
, streams
,
4474 pdata
, max_data_bytes
,
4477 if (!NT_STATUS_IS_OK(status
)) {
4478 DEBUG(10, ("marshall_stream_info failed: %s\n",
4479 nt_errstr(status
)));
4480 reply_nterror(req
, status
);
4484 TALLOC_FREE(streams
);
4488 case SMB_QUERY_COMPRESSION_INFO
:
4489 case SMB_FILE_COMPRESSION_INFORMATION
:
4490 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4491 SOFF_T(pdata
,0,file_size
);
4492 SIVAL(pdata
,8,0); /* ??? */
4493 SIVAL(pdata
,12,0); /* ??? */
4497 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4498 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4499 put_long_date_timespec(pdata
,create_time_ts
);
4500 put_long_date_timespec(pdata
+8,atime_ts
);
4501 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4502 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4503 SOFF_T(pdata
,32,allocation_size
);
4504 SOFF_T(pdata
,40,file_size
);
4505 SIVAL(pdata
,48,mode
);
4506 SIVAL(pdata
,52,0); /* ??? */
4510 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4511 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4512 SIVAL(pdata
,0,mode
);
4518 * CIFS UNIX Extensions.
4521 case SMB_QUERY_FILE_UNIX_BASIC
:
4523 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4524 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4528 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4530 for (i
=0; i
<100; i
++)
4531 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4537 case SMB_QUERY_FILE_UNIX_INFO2
:
4539 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4540 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4544 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4546 for (i
=0; i
<100; i
++)
4547 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4553 case SMB_QUERY_FILE_UNIX_LINK
:
4555 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4558 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4562 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4564 if(!S_ISLNK(sbuf
.st_mode
)) {
4565 reply_unixerror(req
, ERRSRV
,
4570 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4573 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4576 reply_unixerror(req
, ERRDOS
,
4581 len
= srvstr_push(dstart
, req
->flags2
,
4583 PTR_DIFF(dend
, pdata
),
4586 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4591 #if defined(HAVE_POSIX_ACLS)
4592 case SMB_QUERY_POSIX_ACL
:
4594 SMB_ACL_T file_acl
= NULL
;
4595 SMB_ACL_T def_acl
= NULL
;
4596 uint16 num_file_acls
= 0;
4597 uint16 num_def_acls
= 0;
4599 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4600 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4602 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4605 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4606 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4610 NT_STATUS_NOT_IMPLEMENTED
);
4614 if (S_ISDIR(sbuf
.st_mode
)) {
4615 if (fsp
&& fsp
->is_directory
) {
4616 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4618 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4620 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4623 num_file_acls
= count_acl_entries(conn
, file_acl
);
4624 num_def_acls
= count_acl_entries(conn
, def_acl
);
4626 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4627 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4629 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4630 SMB_POSIX_ACL_HEADER_SIZE
) ));
4632 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4639 NT_STATUS_BUFFER_TOO_SMALL
);
4643 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4644 SSVAL(pdata
,2,num_file_acls
);
4645 SSVAL(pdata
,4,num_def_acls
);
4646 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4648 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4651 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4654 req
, NT_STATUS_INTERNAL_ERROR
);
4657 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4659 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4662 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4666 NT_STATUS_INTERNAL_ERROR
);
4671 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4674 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4676 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4682 case SMB_QUERY_POSIX_LOCK
:
4684 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4686 SMB_BIG_UINT offset
;
4688 enum brl_type lock_type
;
4690 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4692 req
, NT_STATUS_INVALID_PARAMETER
);
4696 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4697 case POSIX_LOCK_TYPE_READ
:
4698 lock_type
= READ_LOCK
;
4700 case POSIX_LOCK_TYPE_WRITE
:
4701 lock_type
= WRITE_LOCK
;
4703 case POSIX_LOCK_TYPE_UNLOCK
:
4705 /* There's no point in asking for an unlock... */
4708 NT_STATUS_INVALID_PARAMETER
);
4712 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4713 #if defined(HAVE_LONGLONG)
4714 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4715 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4716 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4717 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4718 #else /* HAVE_LONGLONG */
4719 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4720 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4721 #endif /* HAVE_LONGLONG */
4723 status
= query_lock(fsp
,
4730 if (ERROR_WAS_LOCK_DENIED(status
)) {
4731 /* Here we need to report who has it locked... */
4732 data_size
= POSIX_LOCK_DATA_SIZE
;
4734 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4735 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4736 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4737 #if defined(HAVE_LONGLONG)
4738 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4739 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4740 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4741 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4742 #else /* HAVE_LONGLONG */
4743 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4744 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4745 #endif /* HAVE_LONGLONG */
4747 } else if (NT_STATUS_IS_OK(status
)) {
4748 /* For success we just return a copy of what we sent
4749 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4750 data_size
= POSIX_LOCK_DATA_SIZE
;
4751 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4752 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4754 reply_nterror(req
, status
);
4761 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4765 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4771 /****************************************************************************
4772 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4774 ****************************************************************************/
4776 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4777 connection_struct
*conn
,
4778 const char *oldname_in
,
4779 const char *newname_in
)
4781 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4782 char *last_component_oldname
= NULL
;
4783 char *last_component_newname
= NULL
;
4784 char *oldname
= NULL
;
4785 char *newname
= NULL
;
4786 NTSTATUS status
= NT_STATUS_OK
;
4791 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4792 &last_component_oldname
, &sbuf1
);
4793 if (!NT_STATUS_IS_OK(status
)) {
4797 status
= check_name(conn
, oldname
);
4798 if (!NT_STATUS_IS_OK(status
)) {
4802 /* source must already exist. */
4803 if (!VALID_STAT(sbuf1
)) {
4804 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4807 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4808 &last_component_newname
, &sbuf2
);
4809 if (!NT_STATUS_IS_OK(status
)) {
4813 status
= check_name(conn
, newname
);
4814 if (!NT_STATUS_IS_OK(status
)) {
4818 /* Disallow if newname already exists. */
4819 if (VALID_STAT(sbuf2
)) {
4820 return NT_STATUS_OBJECT_NAME_COLLISION
;
4823 /* No links from a directory. */
4824 if (S_ISDIR(sbuf1
.st_mode
)) {
4825 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4828 /* Ensure this is within the share. */
4829 status
= check_reduced_name(conn
, oldname
);
4830 if (!NT_STATUS_IS_OK(status
)) {
4834 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4836 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4837 status
= map_nt_error_from_unix(errno
);
4838 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4839 nt_errstr(status
), newname
, oldname
));
4845 /****************************************************************************
4846 Deal with setting the time from any of the setfilepathinfo functions.
4847 ****************************************************************************/
4849 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4852 const SMB_STRUCT_STAT
*psbuf
,
4853 struct timespec ts
[2],
4854 bool setting_write_time
)
4857 FILE_NOTIFY_CHANGE_LAST_ACCESS
4858 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4860 if (!VALID_STAT(*psbuf
)) {
4861 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4864 /* get some defaults (no modifications) if any info is zero or -1. */
4865 if (null_timespec(ts
[0])) {
4866 ts
[0] = get_atimespec(psbuf
);
4867 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4870 if (null_timespec(ts
[1])) {
4871 ts
[1] = get_mtimespec(psbuf
);
4872 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4875 if (!setting_write_time
) {
4876 /* ts[1] comes from change time, not write time. */
4877 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4880 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4881 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4884 * Try and set the times of this file if
4885 * they are different from the current values.
4889 struct timespec mts
= get_mtimespec(psbuf
);
4890 struct timespec ats
= get_atimespec(psbuf
);
4891 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4892 return NT_STATUS_OK
;
4896 if (setting_write_time
) {
4898 * This was a setfileinfo on an open file.
4899 * NT does this a lot. We also need to
4900 * set the time here, as it can be read by
4901 * FindFirst/FindNext and with the patch for bug #2045
4902 * in smbd/fileio.c it ensures that this timestamp is
4903 * kept sticky even after a write. We save the request
4904 * away and will set it on file close and after a write. JRA.
4907 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4908 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4911 set_sticky_write_time_fsp(fsp
, ts
[1]);
4913 set_sticky_write_time_path(conn
, fname
,
4914 vfs_file_id_from_sbuf(conn
, psbuf
),
4919 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4921 if(file_ntimes(conn
, fname
, ts
)!=0) {
4922 return map_nt_error_from_unix(errno
);
4924 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4926 return NT_STATUS_OK
;
4929 /****************************************************************************
4930 Deal with setting the dosmode from any of the setfilepathinfo functions.
4931 ****************************************************************************/
4933 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4935 SMB_STRUCT_STAT
*psbuf
,
4938 if (!VALID_STAT(*psbuf
)) {
4939 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4943 if (S_ISDIR(psbuf
->st_mode
)) {
4950 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
4952 /* check the mode isn't different, before changing it */
4953 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
4955 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4956 fname
, (unsigned int)dosmode
));
4958 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
4959 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4960 fname
, strerror(errno
)));
4961 return map_nt_error_from_unix(errno
);
4964 return NT_STATUS_OK
;
4967 /****************************************************************************
4968 Deal with setting the size from any of the setfilepathinfo functions.
4969 ****************************************************************************/
4971 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4972 struct smb_request
*req
,
4975 SMB_STRUCT_STAT
*psbuf
,
4978 NTSTATUS status
= NT_STATUS_OK
;
4979 files_struct
*new_fsp
= NULL
;
4981 if (!VALID_STAT(*psbuf
)) {
4982 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4985 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
4987 if (size
== get_file_size(*psbuf
)) {
4988 return NT_STATUS_OK
;
4991 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4992 fname
, (double)size
));
4994 if (fsp
&& fsp
->fh
->fd
!= -1) {
4995 /* Handle based call. */
4996 if (vfs_set_filelen(fsp
, size
) == -1) {
4997 return map_nt_error_from_unix(errno
);
4999 trigger_write_time_update_immediate(fsp
);
5000 return NT_STATUS_OK
;
5003 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5004 FILE_WRITE_ATTRIBUTES
,
5005 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5008 FILE_ATTRIBUTE_NORMAL
,
5009 FORCE_OPLOCK_BREAK_TO_NONE
,
5012 if (!NT_STATUS_IS_OK(status
)) {
5013 /* NB. We check for open_was_deferred in the caller. */
5017 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5018 status
= map_nt_error_from_unix(errno
);
5019 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5023 trigger_write_time_update_immediate(new_fsp
);
5024 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5025 return NT_STATUS_OK
;
5028 /****************************************************************************
5029 Deal with SMB_INFO_SET_EA.
5030 ****************************************************************************/
5032 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5038 struct ea_list
*ea_list
= NULL
;
5039 TALLOC_CTX
*ctx
= NULL
;
5040 NTSTATUS status
= NT_STATUS_OK
;
5042 if (total_data
< 10) {
5044 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5045 length. They seem to have no effect. Bug #3212. JRA */
5047 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5048 /* We're done. We only get EA info in this call. */
5049 return NT_STATUS_OK
;
5052 return NT_STATUS_INVALID_PARAMETER
;
5055 if (IVAL(pdata
,0) > total_data
) {
5056 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5057 IVAL(pdata
,0), (unsigned int)total_data
));
5058 return NT_STATUS_INVALID_PARAMETER
;
5062 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5064 return NT_STATUS_INVALID_PARAMETER
;
5066 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5071 /****************************************************************************
5072 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5073 ****************************************************************************/
5075 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5080 SMB_STRUCT_STAT
*psbuf
)
5082 NTSTATUS status
= NT_STATUS_OK
;
5083 bool delete_on_close
;
5086 if (total_data
< 1) {
5087 return NT_STATUS_INVALID_PARAMETER
;
5091 return NT_STATUS_INVALID_HANDLE
;
5094 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5095 dosmode
= dos_mode(conn
, fname
, psbuf
);
5097 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5098 "delete_on_close = %u\n",
5100 (unsigned int)dosmode
,
5101 (unsigned int)delete_on_close
));
5103 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5105 if (!NT_STATUS_IS_OK(status
)) {
5109 /* The set is across all open files on this dev/inode pair. */
5110 if (!set_delete_on_close(fsp
, delete_on_close
,
5111 &conn
->server_info
->utok
)) {
5112 return NT_STATUS_ACCESS_DENIED
;
5114 return NT_STATUS_OK
;
5117 /****************************************************************************
5118 Deal with SMB_FILE_POSITION_INFORMATION.
5119 ****************************************************************************/
5121 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5126 SMB_BIG_UINT position_information
;
5128 if (total_data
< 8) {
5129 return NT_STATUS_INVALID_PARAMETER
;
5133 /* Ignore on pathname based set. */
5134 return NT_STATUS_OK
;
5137 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5138 #ifdef LARGE_SMB_OFF_T
5139 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5140 #else /* LARGE_SMB_OFF_T */
5141 if (IVAL(pdata
,4) != 0) {
5142 /* more than 32 bits? */
5143 return NT_STATUS_INVALID_PARAMETER
;
5145 #endif /* LARGE_SMB_OFF_T */
5147 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5148 fsp
->fsp_name
, (double)position_information
));
5149 fsp
->fh
->position_information
= position_information
;
5150 return NT_STATUS_OK
;
5153 /****************************************************************************
5154 Deal with SMB_FILE_MODE_INFORMATION.
5155 ****************************************************************************/
5157 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5163 if (total_data
< 4) {
5164 return NT_STATUS_INVALID_PARAMETER
;
5166 mode
= IVAL(pdata
,0);
5167 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5168 return NT_STATUS_INVALID_PARAMETER
;
5170 return NT_STATUS_OK
;
5173 /****************************************************************************
5174 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5175 ****************************************************************************/
5177 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5178 struct smb_request
*req
,
5183 char *link_target
= NULL
;
5184 const char *newname
= fname
;
5185 NTSTATUS status
= NT_STATUS_OK
;
5186 TALLOC_CTX
*ctx
= talloc_tos();
5188 /* Set a symbolic link. */
5189 /* Don't allow this if follow links is false. */
5191 if (total_data
== 0) {
5192 return NT_STATUS_INVALID_PARAMETER
;
5195 if (!lp_symlinks(SNUM(conn
))) {
5196 return NT_STATUS_ACCESS_DENIED
;
5199 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5200 total_data
, STR_TERMINATE
);
5203 return NT_STATUS_INVALID_PARAMETER
;
5206 /* !widelinks forces the target path to be within the share. */
5207 /* This means we can interpret the target as a pathname. */
5208 if (!lp_widelinks(SNUM(conn
))) {
5209 char *rel_name
= NULL
;
5210 char *last_dirp
= NULL
;
5212 if (*link_target
== '/') {
5213 /* No absolute paths allowed. */
5214 return NT_STATUS_ACCESS_DENIED
;
5216 rel_name
= talloc_strdup(ctx
,newname
);
5218 return NT_STATUS_NO_MEMORY
;
5220 last_dirp
= strrchr_m(rel_name
, '/');
5222 last_dirp
[1] = '\0';
5224 rel_name
= talloc_strdup(ctx
,"./");
5226 return NT_STATUS_NO_MEMORY
;
5229 rel_name
= talloc_asprintf_append(rel_name
,
5233 return NT_STATUS_NO_MEMORY
;
5236 status
= check_name(conn
, rel_name
);
5237 if (!NT_STATUS_IS_OK(status
)) {
5242 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5243 newname
, link_target
));
5245 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5246 return map_nt_error_from_unix(errno
);
5249 return NT_STATUS_OK
;
5252 /****************************************************************************
5253 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5254 ****************************************************************************/
5256 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5257 struct smb_request
*req
,
5258 const char *pdata
, int total_data
,
5261 char *oldname
= NULL
;
5262 TALLOC_CTX
*ctx
= talloc_tos();
5263 NTSTATUS status
= NT_STATUS_OK
;
5265 /* Set a hard link. */
5266 if (total_data
== 0) {
5267 return NT_STATUS_INVALID_PARAMETER
;
5270 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5271 total_data
, STR_TERMINATE
, &status
);
5272 if (!NT_STATUS_IS_OK(status
)) {
5276 status
= resolve_dfspath(ctx
, conn
,
5277 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5280 if (!NT_STATUS_IS_OK(status
)) {
5284 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5287 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5290 /****************************************************************************
5291 Deal with SMB_FILE_RENAME_INFORMATION.
5292 ****************************************************************************/
5294 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5295 struct smb_request
*req
,
5304 char *newname
= NULL
;
5305 char *base_name
= NULL
;
5306 bool dest_has_wcard
= False
;
5307 NTSTATUS status
= NT_STATUS_OK
;
5309 TALLOC_CTX
*ctx
= talloc_tos();
5311 if (total_data
< 13) {
5312 return NT_STATUS_INVALID_PARAMETER
;
5315 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5316 root_fid
= IVAL(pdata
,4);
5317 len
= IVAL(pdata
,8);
5319 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5320 return NT_STATUS_INVALID_PARAMETER
;
5323 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5326 if (!NT_STATUS_IS_OK(status
)) {
5330 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5333 status
= resolve_dfspath_wcard(ctx
, conn
,
5334 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5338 if (!NT_STATUS_IS_OK(status
)) {
5342 /* Check the new name has no '/' characters. */
5343 if (strchr_m(newname
, '/')) {
5344 return NT_STATUS_NOT_SUPPORTED
;
5347 /* Create the base directory. */
5348 base_name
= talloc_strdup(ctx
, fname
);
5350 return NT_STATUS_NO_MEMORY
;
5352 p
= strrchr_m(base_name
, '/');
5356 base_name
= talloc_strdup(ctx
, "./");
5358 return NT_STATUS_NO_MEMORY
;
5361 /* Append the new name. */
5362 base_name
= talloc_asprintf_append(base_name
,
5366 return NT_STATUS_NO_MEMORY
;
5370 SMB_STRUCT_STAT sbuf
;
5371 char *newname_last_component
= NULL
;
5375 status
= unix_convert(ctx
, conn
, newname
, False
,
5377 &newname_last_component
,
5380 /* If an error we expect this to be
5381 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5383 if (!NT_STATUS_IS_OK(status
)
5384 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5389 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5390 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5391 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5392 newname_last_component
, 0,
5395 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5396 fname
, base_name
));
5397 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5398 overwrite
, False
, dest_has_wcard
,
5399 FILE_WRITE_ATTRIBUTES
);
5405 /****************************************************************************
5406 Deal with SMB_SET_POSIX_ACL.
5407 ****************************************************************************/
5409 #if defined(HAVE_POSIX_ACLS)
5410 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5415 SMB_STRUCT_STAT
*psbuf
)
5417 uint16 posix_acl_version
;
5418 uint16 num_file_acls
;
5419 uint16 num_def_acls
;
5420 bool valid_file_acls
= True
;
5421 bool valid_def_acls
= True
;
5423 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5424 return NT_STATUS_INVALID_PARAMETER
;
5426 posix_acl_version
= SVAL(pdata
,0);
5427 num_file_acls
= SVAL(pdata
,2);
5428 num_def_acls
= SVAL(pdata
,4);
5430 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5431 valid_file_acls
= False
;
5435 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5436 valid_def_acls
= False
;
5440 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5441 return NT_STATUS_INVALID_PARAMETER
;
5444 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5445 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5446 return NT_STATUS_INVALID_PARAMETER
;
5449 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5450 fname
? fname
: fsp
->fsp_name
,
5451 (unsigned int)num_file_acls
,
5452 (unsigned int)num_def_acls
));
5454 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5455 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5456 return map_nt_error_from_unix(errno
);
5459 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5460 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5461 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5462 return map_nt_error_from_unix(errno
);
5464 return NT_STATUS_OK
;
5468 /****************************************************************************
5469 Deal with SMB_SET_POSIX_LOCK.
5470 ****************************************************************************/
5472 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5473 const struct smb_request
*req
,
5479 SMB_BIG_UINT offset
;
5481 bool blocking_lock
= False
;
5482 enum brl_type lock_type
;
5484 NTSTATUS status
= NT_STATUS_OK
;
5486 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5487 return NT_STATUS_INVALID_HANDLE
;
5490 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5491 return NT_STATUS_INVALID_PARAMETER
;
5494 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5495 case POSIX_LOCK_TYPE_READ
:
5496 lock_type
= READ_LOCK
;
5498 case POSIX_LOCK_TYPE_WRITE
:
5499 /* Return the right POSIX-mappable error code for files opened read-only. */
5500 if (!fsp
->can_write
) {
5501 return NT_STATUS_INVALID_HANDLE
;
5503 lock_type
= WRITE_LOCK
;
5505 case POSIX_LOCK_TYPE_UNLOCK
:
5506 lock_type
= UNLOCK_LOCK
;
5509 return NT_STATUS_INVALID_PARAMETER
;
5512 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5513 blocking_lock
= False
;
5514 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5515 blocking_lock
= True
;
5517 return NT_STATUS_INVALID_PARAMETER
;
5520 if (!lp_blocking_locks(SNUM(conn
))) {
5521 blocking_lock
= False
;
5524 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5525 #if defined(HAVE_LONGLONG)
5526 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5527 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5528 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5529 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5530 #else /* HAVE_LONGLONG */
5531 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5532 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5533 #endif /* HAVE_LONGLONG */
5535 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5536 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5538 (unsigned int)lock_type
,
5539 (unsigned int)lock_pid
,
5543 if (lock_type
== UNLOCK_LOCK
) {
5544 status
= do_unlock(smbd_messaging_context(),
5551 uint32 block_smbpid
;
5553 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5564 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5566 * A blocking lock was requested. Package up
5567 * this smb into a queued request and push it
5568 * onto the blocking lock queue.
5570 if(push_blocking_lock_request(br_lck
,
5573 -1, /* infinite timeout. */
5581 TALLOC_FREE(br_lck
);
5585 TALLOC_FREE(br_lck
);
5591 /****************************************************************************
5592 Deal with SMB_INFO_STANDARD.
5593 ****************************************************************************/
5595 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5600 const SMB_STRUCT_STAT
*psbuf
)
5602 struct timespec ts
[2];
5604 if (total_data
< 12) {
5605 return NT_STATUS_INVALID_PARAMETER
;
5609 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5611 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5613 DEBUG(10,("smb_set_info_standard: file %s\n",
5614 fname
? fname
: fsp
->fsp_name
));
5616 return smb_set_file_time(conn
,
5624 /****************************************************************************
5625 Deal with SMB_SET_FILE_BASIC_INFO.
5626 ****************************************************************************/
5628 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5633 SMB_STRUCT_STAT
*psbuf
)
5635 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5636 struct timespec write_time
;
5637 struct timespec changed_time
;
5639 struct timespec ts
[2];
5640 NTSTATUS status
= NT_STATUS_OK
;
5641 bool setting_write_time
= true;
5643 if (total_data
< 36) {
5644 return NT_STATUS_INVALID_PARAMETER
;
5647 /* Set the attributes */
5648 dosmode
= IVAL(pdata
,32);
5649 status
= smb_set_file_dosmode(conn
,
5653 if (!NT_STATUS_IS_OK(status
)) {
5657 /* Ignore create time at offset pdata. */
5660 ts
[0] = interpret_long_date(pdata
+8);
5662 write_time
= interpret_long_date(pdata
+16);
5663 changed_time
= interpret_long_date(pdata
+24);
5666 ts
[1] = timespec_min(&write_time
, &changed_time
);
5668 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5672 /* Prefer a defined time to an undefined one. */
5673 if (null_timespec(ts
[1])) {
5674 if (null_timespec(write_time
)) {
5675 ts
[1] = changed_time
;
5676 setting_write_time
= false;
5682 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5683 fname
? fname
: fsp
->fsp_name
));
5685 return smb_set_file_time(conn
,
5690 setting_write_time
);
5693 /****************************************************************************
5694 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5695 ****************************************************************************/
5697 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5698 struct smb_request
*req
,
5703 SMB_STRUCT_STAT
*psbuf
)
5705 SMB_BIG_UINT allocation_size
= 0;
5706 NTSTATUS status
= NT_STATUS_OK
;
5707 files_struct
*new_fsp
= NULL
;
5709 if (!VALID_STAT(*psbuf
)) {
5710 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5713 if (total_data
< 8) {
5714 return NT_STATUS_INVALID_PARAMETER
;
5717 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5718 #ifdef LARGE_SMB_OFF_T
5719 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5720 #else /* LARGE_SMB_OFF_T */
5721 if (IVAL(pdata
,4) != 0) {
5722 /* more than 32 bits? */
5723 return NT_STATUS_INVALID_PARAMETER
;
5725 #endif /* LARGE_SMB_OFF_T */
5727 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5728 fname
, (double)allocation_size
));
5730 if (allocation_size
) {
5731 allocation_size
= smb_roundup(conn
, allocation_size
);
5734 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5735 fname
, (double)allocation_size
));
5737 if (fsp
&& fsp
->fh
->fd
!= -1) {
5738 /* Open file handle. */
5739 /* Only change if needed. */
5740 if (allocation_size
!= get_file_size(*psbuf
)) {
5741 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5742 return map_nt_error_from_unix(errno
);
5745 /* But always update the time. */
5747 * This is equivalent to a write. Ensure it's seen immediately
5748 * if there are no pending writes.
5750 trigger_write_time_update_immediate(fsp
);
5751 return NT_STATUS_OK
;
5754 /* Pathname or stat or directory file. */
5756 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5758 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5761 FILE_ATTRIBUTE_NORMAL
,
5762 FORCE_OPLOCK_BREAK_TO_NONE
,
5765 if (!NT_STATUS_IS_OK(status
)) {
5766 /* NB. We check for open_was_deferred in the caller. */
5770 /* Only change if needed. */
5771 if (allocation_size
!= get_file_size(*psbuf
)) {
5772 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5773 status
= map_nt_error_from_unix(errno
);
5774 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5779 /* Changing the allocation size should set the last mod time. */
5781 * This is equivalent to a write. Ensure it's seen immediately
5782 * if there are no pending writes.
5784 trigger_write_time_update_immediate(new_fsp
);
5786 close_file(req
, new_fsp
, NORMAL_CLOSE
);
5787 return NT_STATUS_OK
;
5790 /****************************************************************************
5791 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5792 ****************************************************************************/
5794 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5795 struct smb_request
*req
,
5800 SMB_STRUCT_STAT
*psbuf
)
5804 if (total_data
< 8) {
5805 return NT_STATUS_INVALID_PARAMETER
;
5808 size
= IVAL(pdata
,0);
5809 #ifdef LARGE_SMB_OFF_T
5810 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5811 #else /* LARGE_SMB_OFF_T */
5812 if (IVAL(pdata
,4) != 0) {
5813 /* more than 32 bits? */
5814 return NT_STATUS_INVALID_PARAMETER
;
5816 #endif /* LARGE_SMB_OFF_T */
5817 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5818 "file %s to %.0f\n", fname
, (double)size
));
5820 return smb_set_file_size(conn
, req
,
5827 /****************************************************************************
5828 Allow a UNIX info mknod.
5829 ****************************************************************************/
5831 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5835 SMB_STRUCT_STAT
*psbuf
)
5837 uint32 file_type
= IVAL(pdata
,56);
5838 #if defined(HAVE_MAKEDEV)
5839 uint32 dev_major
= IVAL(pdata
,60);
5840 uint32 dev_minor
= IVAL(pdata
,68);
5842 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5843 uint32 raw_unixmode
= IVAL(pdata
,84);
5847 if (total_data
< 100) {
5848 return NT_STATUS_INVALID_PARAMETER
;
5851 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5852 if (!NT_STATUS_IS_OK(status
)) {
5856 #if defined(HAVE_MAKEDEV)
5857 dev
= makedev(dev_major
, dev_minor
);
5860 switch (file_type
) {
5861 #if defined(S_IFIFO)
5862 case UNIX_TYPE_FIFO
:
5863 unixmode
|= S_IFIFO
;
5866 #if defined(S_IFSOCK)
5867 case UNIX_TYPE_SOCKET
:
5868 unixmode
|= S_IFSOCK
;
5871 #if defined(S_IFCHR)
5872 case UNIX_TYPE_CHARDEV
:
5873 unixmode
|= S_IFCHR
;
5876 #if defined(S_IFBLK)
5877 case UNIX_TYPE_BLKDEV
:
5878 unixmode
|= S_IFBLK
;
5882 return NT_STATUS_INVALID_PARAMETER
;
5885 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5886 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5888 /* Ok - do the mknod. */
5889 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5890 return map_nt_error_from_unix(errno
);
5893 /* If any of the other "set" calls fail we
5894 * don't want to end up with a half-constructed mknod.
5897 if (lp_inherit_perms(SNUM(conn
))) {
5898 inherit_access_posix_acl(
5899 conn
, parent_dirname(fname
),
5903 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5904 status
= map_nt_error_from_unix(errno
);
5905 SMB_VFS_UNLINK(conn
,fname
);
5908 return NT_STATUS_OK
;
5911 /****************************************************************************
5912 Deal with SMB_SET_FILE_UNIX_BASIC.
5913 ****************************************************************************/
5915 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5916 struct smb_request
*req
,
5921 SMB_STRUCT_STAT
*psbuf
)
5923 struct timespec ts
[2];
5924 uint32 raw_unixmode
;
5927 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5928 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5929 NTSTATUS status
= NT_STATUS_OK
;
5930 bool delete_on_fail
= False
;
5931 enum perm_type ptype
;
5933 if (total_data
< 100) {
5934 return NT_STATUS_INVALID_PARAMETER
;
5937 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5938 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5939 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5940 #ifdef LARGE_SMB_OFF_T
5941 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5942 #else /* LARGE_SMB_OFF_T */
5943 if (IVAL(pdata
,4) != 0) {
5944 /* more than 32 bits? */
5945 return NT_STATUS_INVALID_PARAMETER
;
5947 #endif /* LARGE_SMB_OFF_T */
5950 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
5951 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
5952 set_owner
= (uid_t
)IVAL(pdata
,40);
5953 set_grp
= (gid_t
)IVAL(pdata
,48);
5954 raw_unixmode
= IVAL(pdata
,84);
5956 if (VALID_STAT(*psbuf
)) {
5957 if (S_ISDIR(psbuf
->st_mode
)) {
5958 ptype
= PERM_EXISTING_DIR
;
5960 ptype
= PERM_EXISTING_FILE
;
5963 ptype
= PERM_NEW_FILE
;
5966 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
5967 if (!NT_STATUS_IS_OK(status
)) {
5971 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5972 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5973 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
5975 if (!VALID_STAT(*psbuf
)) {
5977 * The only valid use of this is to create character and block
5978 * devices, and named pipes. This is deprecated (IMHO) and
5979 * a new info level should be used for mknod. JRA.
5982 status
= smb_unix_mknod(conn
,
5987 if (!NT_STATUS_IS_OK(status
)) {
5991 /* Ensure we don't try and change anything else. */
5992 raw_unixmode
= SMB_MODE_NO_CHANGE
;
5993 size
= get_file_size(*psbuf
);
5994 ts
[0] = get_atimespec(psbuf
);
5995 ts
[1] = get_mtimespec(psbuf
);
5997 * We continue here as we might want to change the
6000 delete_on_fail
= True
;
6004 /* Horrible backwards compatibility hack as an old server bug
6005 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6009 size
= get_file_size(*psbuf
);
6014 * Deal with the UNIX specific mode set.
6017 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6018 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6019 (unsigned int)unixmode
, fname
));
6020 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6021 return map_nt_error_from_unix(errno
);
6026 * Deal with the UNIX specific uid set.
6029 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6032 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6033 (unsigned int)set_owner
, fname
));
6035 if (S_ISLNK(psbuf
->st_mode
)) {
6036 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6038 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6042 status
= map_nt_error_from_unix(errno
);
6043 if (delete_on_fail
) {
6044 SMB_VFS_UNLINK(conn
,fname
);
6051 * Deal with the UNIX specific gid set.
6054 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6055 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6056 (unsigned int)set_owner
, fname
));
6057 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6058 status
= map_nt_error_from_unix(errno
);
6059 if (delete_on_fail
) {
6060 SMB_VFS_UNLINK(conn
,fname
);
6066 /* Deal with any size changes. */
6068 status
= smb_set_file_size(conn
, req
,
6073 if (!NT_STATUS_IS_OK(status
)) {
6077 /* Deal with any time changes. */
6079 return smb_set_file_time(conn
,
6087 /****************************************************************************
6088 Deal with SMB_SET_FILE_UNIX_INFO2.
6089 ****************************************************************************/
6091 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6092 struct smb_request
*req
,
6097 SMB_STRUCT_STAT
*psbuf
)
6103 if (total_data
< 116) {
6104 return NT_STATUS_INVALID_PARAMETER
;
6107 /* Start by setting all the fields that are common between UNIX_BASIC
6110 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6112 if (!NT_STATUS_IS_OK(status
)) {
6116 smb_fflags
= IVAL(pdata
, 108);
6117 smb_fmask
= IVAL(pdata
, 112);
6119 /* NB: We should only attempt to alter the file flags if the client
6120 * sends a non-zero mask.
6122 if (smb_fmask
!= 0) {
6123 int stat_fflags
= 0;
6125 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6127 /* Client asked to alter a flag we don't understand. */
6128 return NT_STATUS_INVALID_PARAMETER
;
6131 if (fsp
&& fsp
->fh
->fd
!= -1) {
6132 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6133 return NT_STATUS_NOT_SUPPORTED
;
6135 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6136 return map_nt_error_from_unix(errno
);
6141 /* XXX: need to add support for changing the create_time here. You
6142 * can do this for paths on Darwin with setattrlist(2). The right way
6143 * to hook this up is probably by extending the VFS utimes interface.
6146 return NT_STATUS_OK
;
6149 /****************************************************************************
6150 Create a directory with POSIX semantics.
6151 ****************************************************************************/
6153 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6154 struct smb_request
*req
,
6158 SMB_STRUCT_STAT
*psbuf
,
6159 int *pdata_return_size
)
6161 NTSTATUS status
= NT_STATUS_OK
;
6162 uint32 raw_unixmode
= 0;
6163 uint32 mod_unixmode
= 0;
6164 mode_t unixmode
= (mode_t
)0;
6165 files_struct
*fsp
= NULL
;
6166 uint16 info_level_return
= 0;
6168 char *pdata
= *ppdata
;
6170 if (total_data
< 18) {
6171 return NT_STATUS_INVALID_PARAMETER
;
6174 raw_unixmode
= IVAL(pdata
,8);
6175 /* Next 4 bytes are not yet defined. */
6177 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6178 if (!NT_STATUS_IS_OK(status
)) {
6182 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6184 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6185 fname
, (unsigned int)unixmode
));
6187 status
= open_directory(conn
, req
,
6190 FILE_READ_ATTRIBUTES
, /* Just a stat open */
6191 FILE_SHARE_NONE
, /* Ignored for stat opens */
6198 if (NT_STATUS_IS_OK(status
)) {
6199 close_file(req
, fsp
, NORMAL_CLOSE
);
6202 info_level_return
= SVAL(pdata
,16);
6204 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6205 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6206 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6207 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6209 *pdata_return_size
= 12;
6212 /* Realloc the data size */
6213 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6214 if (*ppdata
== NULL
) {
6215 *pdata_return_size
= 0;
6216 return NT_STATUS_NO_MEMORY
;
6220 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6221 SSVAL(pdata
,2,0); /* No fnum. */
6222 SIVAL(pdata
,4,info
); /* Was directory created. */
6224 switch (info_level_return
) {
6225 case SMB_QUERY_FILE_UNIX_BASIC
:
6226 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6227 SSVAL(pdata
,10,0); /* Padding. */
6228 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6230 case SMB_QUERY_FILE_UNIX_INFO2
:
6231 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6232 SSVAL(pdata
,10,0); /* Padding. */
6233 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6236 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6237 SSVAL(pdata
,10,0); /* Padding. */
6244 /****************************************************************************
6245 Open/Create a file with POSIX semantics.
6246 ****************************************************************************/
6248 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6249 struct smb_request
*req
,
6253 SMB_STRUCT_STAT
*psbuf
,
6254 int *pdata_return_size
)
6256 bool extended_oplock_granted
= False
;
6257 char *pdata
= *ppdata
;
6259 uint32 wire_open_mode
= 0;
6260 uint32 raw_unixmode
= 0;
6261 uint32 mod_unixmode
= 0;
6262 uint32 create_disp
= 0;
6263 uint32 access_mask
= 0;
6264 uint32 create_options
= 0;
6265 NTSTATUS status
= NT_STATUS_OK
;
6266 mode_t unixmode
= (mode_t
)0;
6267 files_struct
*fsp
= NULL
;
6268 int oplock_request
= 0;
6270 uint16 info_level_return
= 0;
6272 if (total_data
< 18) {
6273 return NT_STATUS_INVALID_PARAMETER
;
6276 flags
= IVAL(pdata
,0);
6277 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6278 if (oplock_request
) {
6279 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6282 wire_open_mode
= IVAL(pdata
,4);
6284 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6285 return smb_posix_mkdir(conn
, req
,
6293 switch (wire_open_mode
& SMB_ACCMODE
) {
6295 access_mask
= FILE_READ_DATA
;
6298 access_mask
= FILE_WRITE_DATA
;
6301 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6304 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6305 (unsigned int)wire_open_mode
));
6306 return NT_STATUS_INVALID_PARAMETER
;
6309 wire_open_mode
&= ~SMB_ACCMODE
;
6311 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6312 create_disp
= FILE_CREATE
;
6313 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6314 create_disp
= FILE_OVERWRITE_IF
;
6315 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6316 create_disp
= FILE_OPEN_IF
;
6318 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6319 (unsigned int)wire_open_mode
));
6320 return NT_STATUS_INVALID_PARAMETER
;
6323 raw_unixmode
= IVAL(pdata
,8);
6324 /* Next 4 bytes are not yet defined. */
6326 status
= unix_perms_from_wire(conn
,
6329 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6332 if (!NT_STATUS_IS_OK(status
)) {
6336 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6338 if (wire_open_mode
& SMB_O_SYNC
) {
6339 create_options
|= FILE_WRITE_THROUGH
;
6341 if (wire_open_mode
& SMB_O_APPEND
) {
6342 access_mask
|= FILE_APPEND_DATA
;
6344 if (wire_open_mode
& SMB_O_DIRECT
) {
6345 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6348 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6350 (unsigned int)wire_open_mode
,
6351 (unsigned int)unixmode
));
6353 status
= open_file_ntcreate(conn
, req
,
6357 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6359 0, /* no create options yet. */
6365 if (!NT_STATUS_IS_OK(status
)) {
6369 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6370 extended_oplock_granted
= True
;
6373 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6374 extended_oplock_granted
= True
;
6377 info_level_return
= SVAL(pdata
,16);
6379 /* Allocate the correct return size. */
6381 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6382 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6383 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6384 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6386 *pdata_return_size
= 12;
6389 /* Realloc the data size */
6390 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6391 if (*ppdata
== NULL
) {
6392 close_file(req
, fsp
, ERROR_CLOSE
);
6393 *pdata_return_size
= 0;
6394 return NT_STATUS_NO_MEMORY
;
6398 if (extended_oplock_granted
) {
6399 if (flags
& REQUEST_BATCH_OPLOCK
) {
6400 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6402 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6404 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6405 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6407 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6410 SSVAL(pdata
,2,fsp
->fnum
);
6411 SIVAL(pdata
,4,info
); /* Was file created etc. */
6413 switch (info_level_return
) {
6414 case SMB_QUERY_FILE_UNIX_BASIC
:
6415 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6416 SSVAL(pdata
,10,0); /* padding. */
6417 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6419 case SMB_QUERY_FILE_UNIX_INFO2
:
6420 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6421 SSVAL(pdata
,10,0); /* padding. */
6422 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6425 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6426 SSVAL(pdata
,10,0); /* padding. */
6429 return NT_STATUS_OK
;
6432 /****************************************************************************
6433 Delete a file with POSIX semantics.
6434 ****************************************************************************/
6436 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6437 struct smb_request
*req
,
6441 SMB_STRUCT_STAT
*psbuf
)
6443 NTSTATUS status
= NT_STATUS_OK
;
6444 files_struct
*fsp
= NULL
;
6449 struct share_mode_lock
*lck
= NULL
;
6451 if (total_data
< 2) {
6452 return NT_STATUS_INVALID_PARAMETER
;
6455 flags
= SVAL(pdata
,0);
6457 if (!VALID_STAT(*psbuf
)) {
6458 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6461 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6462 !VALID_STAT_OF_DIR(*psbuf
)) {
6463 return NT_STATUS_NOT_A_DIRECTORY
;
6466 DEBUG(10,("smb_posix_unlink: %s %s\n",
6467 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6470 if (VALID_STAT_OF_DIR(*psbuf
)) {
6471 status
= open_directory(conn
, req
,
6475 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6478 FILE_FLAG_POSIX_SEMANTICS
|0777,
6483 status
= open_file_ntcreate(conn
, req
,
6487 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6490 FILE_FLAG_POSIX_SEMANTICS
|0777,
6491 0, /* No oplock, but break existing ones. */
6496 if (!NT_STATUS_IS_OK(status
)) {
6501 * Don't lie to client. If we can't really delete due to
6502 * non-POSIX opens return SHARING_VIOLATION.
6505 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6508 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6509 "lock for file %s\n", fsp
->fsp_name
));
6510 close_file(req
, fsp
, NORMAL_CLOSE
);
6511 return NT_STATUS_INVALID_PARAMETER
;
6515 * See if others still have the file open. If this is the case, then
6516 * don't delete. If all opens are POSIX delete we can set the delete
6517 * on close disposition.
6519 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6520 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6521 if (is_valid_share_mode_entry(e
)) {
6522 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6525 /* Fail with sharing violation. */
6526 close_file(req
, fsp
, NORMAL_CLOSE
);
6528 return NT_STATUS_SHARING_VIOLATION
;
6533 * Set the delete on close.
6535 status
= smb_set_file_disposition_info(conn
,
6542 if (!NT_STATUS_IS_OK(status
)) {
6543 close_file(req
, fsp
, NORMAL_CLOSE
);
6548 return close_file(req
, fsp
, NORMAL_CLOSE
);
6551 /****************************************************************************
6552 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6553 ****************************************************************************/
6555 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6556 struct smb_request
*req
,
6557 unsigned int tran_call
,
6558 char **pparams
, int total_params
,
6559 char **ppdata
, int total_data
,
6560 unsigned int max_data_bytes
)
6562 char *params
= *pparams
;
6563 char *pdata
= *ppdata
;
6565 SMB_STRUCT_STAT sbuf
;
6567 files_struct
*fsp
= NULL
;
6568 NTSTATUS status
= NT_STATUS_OK
;
6569 int data_return_size
= 0;
6570 TALLOC_CTX
*ctx
= talloc_tos();
6573 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6579 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6580 if (total_params
< 4) {
6581 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6585 fsp
= file_fsp(req
, SVAL(params
,0));
6586 /* Basic check for non-null fsp. */
6587 if (!check_fsp_open(conn
, req
, fsp
)) {
6590 info_level
= SVAL(params
,2);
6592 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6594 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6598 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6600 * This is actually a SETFILEINFO on a directory
6601 * handle (returned from an NT SMB). NT5.0 seems
6602 * to do this call. JRA.
6604 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6605 /* Always do lstat for UNIX calls. */
6606 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6607 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6608 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6612 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6613 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6614 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6618 } else if (fsp
->print_file
) {
6620 * Doing a DELETE_ON_CLOSE should cancel a print job.
6622 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6623 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6625 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6628 send_trans2_replies(conn
, req
, params
, 2,
6633 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6638 * Original code - this is an open file.
6640 if (!check_fsp(conn
, req
, fsp
)) {
6644 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6645 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6646 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6652 if (total_params
< 7) {
6653 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6657 info_level
= SVAL(params
,0);
6658 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6659 total_params
- 6, STR_TERMINATE
,
6661 if (!NT_STATUS_IS_OK(status
)) {
6662 reply_nterror(req
, status
);
6666 status
= resolve_dfspath(ctx
, conn
,
6667 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6670 if (!NT_STATUS_IS_OK(status
)) {
6671 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6672 reply_botherror(req
,
6673 NT_STATUS_PATH_NOT_COVERED
,
6674 ERRSRV
, ERRbadpath
);
6677 reply_nterror(req
, status
);
6681 status
= unix_convert(ctx
, conn
, fname
, False
,
6682 &fname
, NULL
, &sbuf
);
6683 if (!NT_STATUS_IS_OK(status
)) {
6684 reply_nterror(req
, status
);
6688 status
= check_name(conn
, fname
);
6689 if (!NT_STATUS_IS_OK(status
)) {
6690 reply_nterror(req
, status
);
6694 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6696 * For CIFS UNIX extensions the target name may not exist.
6699 /* Always do lstat for UNIX calls. */
6700 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6702 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6703 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6704 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6709 if (!CAN_WRITE(conn
)) {
6710 reply_doserror(req
, ERRSRV
, ERRaccess
);
6714 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6715 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6719 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6720 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6722 /* Realloc the parameter size */
6723 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6724 if (*pparams
== NULL
) {
6725 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6732 switch (info_level
) {
6734 case SMB_INFO_STANDARD
:
6736 status
= smb_set_info_standard(conn
,
6745 case SMB_INFO_SET_EA
:
6747 status
= smb_info_set_ea(conn
,
6755 case SMB_SET_FILE_BASIC_INFO
:
6756 case SMB_FILE_BASIC_INFORMATION
:
6758 status
= smb_set_file_basic_info(conn
,
6767 case SMB_FILE_ALLOCATION_INFORMATION
:
6768 case SMB_SET_FILE_ALLOCATION_INFO
:
6770 status
= smb_set_file_allocation_info(conn
, req
,
6779 case SMB_FILE_END_OF_FILE_INFORMATION
:
6780 case SMB_SET_FILE_END_OF_FILE_INFO
:
6782 status
= smb_set_file_end_of_file_info(conn
, req
,
6791 case SMB_FILE_DISPOSITION_INFORMATION
:
6792 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6795 /* JRA - We used to just ignore this on a path ?
6796 * Shouldn't this be invalid level on a pathname
6799 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6800 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6803 status
= smb_set_file_disposition_info(conn
,
6812 case SMB_FILE_POSITION_INFORMATION
:
6814 status
= smb_file_position_information(conn
,
6821 /* From tridge Samba4 :
6822 * MODE_INFORMATION in setfileinfo (I have no
6823 * idea what "mode information" on a file is - it takes a value of 0,
6824 * 2, 4 or 6. What could it be?).
6827 case SMB_FILE_MODE_INFORMATION
:
6829 status
= smb_file_mode_information(conn
,
6836 * CIFS UNIX extensions.
6839 case SMB_SET_FILE_UNIX_BASIC
:
6841 status
= smb_set_file_unix_basic(conn
, req
,
6850 case SMB_SET_FILE_UNIX_INFO2
:
6852 status
= smb_set_file_unix_info2(conn
, req
,
6861 case SMB_SET_FILE_UNIX_LINK
:
6863 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6864 /* We must have a pathname for this. */
6865 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6868 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6873 case SMB_SET_FILE_UNIX_HLINK
:
6875 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6876 /* We must have a pathname for this. */
6877 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6880 status
= smb_set_file_unix_hlink(conn
, req
,
6886 case SMB_FILE_RENAME_INFORMATION
:
6888 status
= smb_file_rename_information(conn
, req
,
6894 #if defined(HAVE_POSIX_ACLS)
6895 case SMB_SET_POSIX_ACL
:
6897 status
= smb_set_posix_acl(conn
,
6907 case SMB_SET_POSIX_LOCK
:
6909 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6910 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6913 status
= smb_set_posix_lock(conn
, req
,
6914 pdata
, total_data
, fsp
);
6918 case SMB_POSIX_PATH_OPEN
:
6920 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6921 /* We must have a pathname for this. */
6922 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6926 status
= smb_posix_open(conn
, req
,
6935 case SMB_POSIX_PATH_UNLINK
:
6937 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6938 /* We must have a pathname for this. */
6939 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6943 status
= smb_posix_unlink(conn
, req
,
6952 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6957 if (!NT_STATUS_IS_OK(status
)) {
6958 if (open_was_deferred(req
->mid
)) {
6959 /* We have re-scheduled this call. */
6962 if (blocking_lock_was_deferred(req
->mid
)) {
6963 /* We have re-scheduled this call. */
6966 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6967 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6968 ERRSRV
, ERRbadpath
);
6971 if (info_level
== SMB_POSIX_PATH_OPEN
) {
6972 reply_openerror(req
, status
);
6976 reply_nterror(req
, status
);
6981 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
6987 /****************************************************************************
6988 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6989 ****************************************************************************/
6991 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
6992 char **pparams
, int total_params
,
6993 char **ppdata
, int total_data
,
6994 unsigned int max_data_bytes
)
6996 char *params
= *pparams
;
6997 char *pdata
= *ppdata
;
6998 char *directory
= NULL
;
6999 SMB_STRUCT_STAT sbuf
;
7000 NTSTATUS status
= NT_STATUS_OK
;
7001 struct ea_list
*ea_list
= NULL
;
7002 TALLOC_CTX
*ctx
= talloc_tos();
7004 if (!CAN_WRITE(conn
)) {
7005 reply_doserror(req
, ERRSRV
, ERRaccess
);
7009 if (total_params
< 5) {
7010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7014 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7015 total_params
- 4, STR_TERMINATE
,
7017 if (!NT_STATUS_IS_OK(status
)) {
7018 reply_nterror(req
, status
);
7022 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7024 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
7025 if (!NT_STATUS_IS_OK(status
)) {
7026 reply_nterror(req
, status
);
7030 status
= check_name(conn
, directory
);
7031 if (!NT_STATUS_IS_OK(status
)) {
7032 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7033 reply_nterror(req
, status
);
7037 /* Any data in this call is an EA list. */
7038 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7039 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7044 * OS/2 workplace shell seems to send SET_EA requests of "null"
7045 * length (4 bytes containing IVAL 4).
7046 * They seem to have no effect. Bug #3212. JRA.
7049 if (total_data
!= 4) {
7050 if (total_data
< 10) {
7051 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7055 if (IVAL(pdata
,0) > total_data
) {
7056 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7057 IVAL(pdata
,0), (unsigned int)total_data
));
7058 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7062 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7065 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7068 } else if (IVAL(pdata
,0) != 4) {
7069 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7073 status
= create_directory(conn
, req
, directory
);
7075 if (!NT_STATUS_IS_OK(status
)) {
7076 reply_nterror(req
, status
);
7080 /* Try and set any given EA. */
7082 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7083 if (!NT_STATUS_IS_OK(status
)) {
7084 reply_nterror(req
, status
);
7089 /* Realloc the parameter and data sizes */
7090 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7091 if(*pparams
== NULL
) {
7092 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7099 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7104 /****************************************************************************
7105 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7106 We don't actually do this - we just send a null response.
7107 ****************************************************************************/
7109 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7110 struct smb_request
*req
,
7111 char **pparams
, int total_params
,
7112 char **ppdata
, int total_data
,
7113 unsigned int max_data_bytes
)
7115 static uint16 fnf_handle
= 257;
7116 char *params
= *pparams
;
7119 if (total_params
< 6) {
7120 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7124 info_level
= SVAL(params
,4);
7125 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7127 switch (info_level
) {
7132 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7136 /* Realloc the parameter and data sizes */
7137 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7138 if (*pparams
== NULL
) {
7139 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7144 SSVAL(params
,0,fnf_handle
);
7145 SSVAL(params
,2,0); /* No changes */
7146 SSVAL(params
,4,0); /* No EA errors */
7153 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7158 /****************************************************************************
7159 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7160 changes). Currently this does nothing.
7161 ****************************************************************************/
7163 static void call_trans2findnotifynext(connection_struct
*conn
,
7164 struct smb_request
*req
,
7165 char **pparams
, int total_params
,
7166 char **ppdata
, int total_data
,
7167 unsigned int max_data_bytes
)
7169 char *params
= *pparams
;
7171 DEBUG(3,("call_trans2findnotifynext\n"));
7173 /* Realloc the parameter and data sizes */
7174 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7175 if (*pparams
== NULL
) {
7176 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7181 SSVAL(params
,0,0); /* No changes */
7182 SSVAL(params
,2,0); /* No EA errors */
7184 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7189 /****************************************************************************
7190 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7191 ****************************************************************************/
7193 static void call_trans2getdfsreferral(connection_struct
*conn
,
7194 struct smb_request
*req
,
7195 char **pparams
, int total_params
,
7196 char **ppdata
, int total_data
,
7197 unsigned int max_data_bytes
)
7199 char *params
= *pparams
;
7200 char *pathname
= NULL
;
7202 int max_referral_level
;
7203 NTSTATUS status
= NT_STATUS_OK
;
7204 TALLOC_CTX
*ctx
= talloc_tos();
7206 DEBUG(10,("call_trans2getdfsreferral\n"));
7208 if (total_params
< 3) {
7209 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7213 max_referral_level
= SVAL(params
,0);
7215 if(!lp_host_msdfs()) {
7216 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7220 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7221 total_params
- 2, STR_TERMINATE
);
7223 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7226 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7227 ppdata
,&status
)) < 0) {
7228 reply_nterror(req
, status
);
7232 SSVAL(req
->inbuf
, smb_flg2
,
7233 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7234 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7239 #define LMCAT_SPL 0x53
7240 #define LMFUNC_GETJOBID 0x60
7242 /****************************************************************************
7243 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7244 ****************************************************************************/
7246 static void call_trans2ioctl(connection_struct
*conn
,
7247 struct smb_request
*req
,
7248 char **pparams
, int total_params
,
7249 char **ppdata
, int total_data
,
7250 unsigned int max_data_bytes
)
7252 char *pdata
= *ppdata
;
7253 files_struct
*fsp
= file_fsp(req
, SVAL(req
->inbuf
,smb_vwv15
));
7255 /* check for an invalid fid before proceeding */
7258 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7262 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7263 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7264 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7265 if (*ppdata
== NULL
) {
7266 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7271 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7272 CAN ACCEPT THIS IN UNICODE. JRA. */
7274 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7275 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7276 global_myname(), 15,
7277 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7278 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7279 lp_servicename(SNUM(conn
)), 13,
7280 STR_ASCII
|STR_TERMINATE
); /* Service name */
7281 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7286 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7287 reply_doserror(req
, ERRSRV
, ERRerror
);
7290 /****************************************************************************
7291 Reply to a SMBfindclose (stop trans2 directory search).
7292 ****************************************************************************/
7294 void reply_findclose(struct smb_request
*req
)
7298 START_PROFILE(SMBfindclose
);
7301 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7302 END_PROFILE(SMBfindclose
);
7306 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7308 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7310 dptr_close(&dptr_num
);
7312 reply_outbuf(req
, 0, 0);
7314 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7316 END_PROFILE(SMBfindclose
);
7320 /****************************************************************************
7321 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7322 ****************************************************************************/
7324 void reply_findnclose(struct smb_request
*req
)
7328 START_PROFILE(SMBfindnclose
);
7331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7332 END_PROFILE(SMBfindnclose
);
7336 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7338 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7340 /* We never give out valid handles for a
7341 findnotifyfirst - so any dptr_num is ok here.
7344 reply_outbuf(req
, 0, 0);
7346 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7348 END_PROFILE(SMBfindnclose
);
7352 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7353 struct trans_state
*state
)
7355 if (Protocol
>= PROTOCOL_NT1
) {
7356 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7357 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7360 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7361 if (state
->call
!= TRANSACT2_QFSINFO
&&
7362 state
->call
!= TRANSACT2_SETFSINFO
) {
7363 DEBUG(0,("handle_trans2: encryption required "
7365 (unsigned int)state
->call
));
7366 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7371 /* Now we must call the relevant TRANS2 function */
7372 switch(state
->call
) {
7373 case TRANSACT2_OPEN
:
7375 START_PROFILE(Trans2_open
);
7376 call_trans2open(conn
, req
,
7377 &state
->param
, state
->total_param
,
7378 &state
->data
, state
->total_data
,
7379 state
->max_data_return
);
7380 END_PROFILE(Trans2_open
);
7384 case TRANSACT2_FINDFIRST
:
7386 START_PROFILE(Trans2_findfirst
);
7387 call_trans2findfirst(conn
, req
,
7388 &state
->param
, state
->total_param
,
7389 &state
->data
, state
->total_data
,
7390 state
->max_data_return
);
7391 END_PROFILE(Trans2_findfirst
);
7395 case TRANSACT2_FINDNEXT
:
7397 START_PROFILE(Trans2_findnext
);
7398 call_trans2findnext(conn
, req
,
7399 &state
->param
, state
->total_param
,
7400 &state
->data
, state
->total_data
,
7401 state
->max_data_return
);
7402 END_PROFILE(Trans2_findnext
);
7406 case TRANSACT2_QFSINFO
:
7408 START_PROFILE(Trans2_qfsinfo
);
7409 call_trans2qfsinfo(conn
, req
,
7410 &state
->param
, state
->total_param
,
7411 &state
->data
, state
->total_data
,
7412 state
->max_data_return
);
7413 END_PROFILE(Trans2_qfsinfo
);
7417 case TRANSACT2_SETFSINFO
:
7419 START_PROFILE(Trans2_setfsinfo
);
7420 call_trans2setfsinfo(conn
, req
,
7421 &state
->param
, state
->total_param
,
7422 &state
->data
, state
->total_data
,
7423 state
->max_data_return
);
7424 END_PROFILE(Trans2_setfsinfo
);
7428 case TRANSACT2_QPATHINFO
:
7429 case TRANSACT2_QFILEINFO
:
7431 START_PROFILE(Trans2_qpathinfo
);
7432 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7433 &state
->param
, state
->total_param
,
7434 &state
->data
, state
->total_data
,
7435 state
->max_data_return
);
7436 END_PROFILE(Trans2_qpathinfo
);
7440 case TRANSACT2_SETPATHINFO
:
7441 case TRANSACT2_SETFILEINFO
:
7443 START_PROFILE(Trans2_setpathinfo
);
7444 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7445 &state
->param
, state
->total_param
,
7446 &state
->data
, state
->total_data
,
7447 state
->max_data_return
);
7448 END_PROFILE(Trans2_setpathinfo
);
7452 case TRANSACT2_FINDNOTIFYFIRST
:
7454 START_PROFILE(Trans2_findnotifyfirst
);
7455 call_trans2findnotifyfirst(conn
, req
,
7456 &state
->param
, state
->total_param
,
7457 &state
->data
, state
->total_data
,
7458 state
->max_data_return
);
7459 END_PROFILE(Trans2_findnotifyfirst
);
7463 case TRANSACT2_FINDNOTIFYNEXT
:
7465 START_PROFILE(Trans2_findnotifynext
);
7466 call_trans2findnotifynext(conn
, req
,
7467 &state
->param
, state
->total_param
,
7468 &state
->data
, state
->total_data
,
7469 state
->max_data_return
);
7470 END_PROFILE(Trans2_findnotifynext
);
7474 case TRANSACT2_MKDIR
:
7476 START_PROFILE(Trans2_mkdir
);
7477 call_trans2mkdir(conn
, req
,
7478 &state
->param
, state
->total_param
,
7479 &state
->data
, state
->total_data
,
7480 state
->max_data_return
);
7481 END_PROFILE(Trans2_mkdir
);
7485 case TRANSACT2_GET_DFS_REFERRAL
:
7487 START_PROFILE(Trans2_get_dfs_referral
);
7488 call_trans2getdfsreferral(conn
, req
,
7489 &state
->param
, state
->total_param
,
7490 &state
->data
, state
->total_data
,
7491 state
->max_data_return
);
7492 END_PROFILE(Trans2_get_dfs_referral
);
7496 case TRANSACT2_IOCTL
:
7498 START_PROFILE(Trans2_ioctl
);
7499 call_trans2ioctl(conn
, req
,
7500 &state
->param
, state
->total_param
,
7501 &state
->data
, state
->total_data
,
7502 state
->max_data_return
);
7503 END_PROFILE(Trans2_ioctl
);
7508 /* Error in request */
7509 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7510 reply_doserror(req
, ERRSRV
,ERRerror
);
7514 /****************************************************************************
7515 Reply to a SMBtrans2.
7516 ****************************************************************************/
7518 void reply_trans2(struct smb_request
*req
)
7520 connection_struct
*conn
= req
->conn
;
7525 unsigned int tran_call
;
7527 unsigned int av_size
;
7528 struct trans_state
*state
;
7531 START_PROFILE(SMBtrans2
);
7533 if (req
->wct
< 14) {
7534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7535 END_PROFILE(SMBtrans2
);
7539 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7540 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7541 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7542 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7543 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7544 size
= smb_len(req
->inbuf
) + 4;
7545 av_size
= smb_len(req
->inbuf
);
7547 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7548 if (!NT_STATUS_IS_OK(result
)) {
7549 DEBUG(2, ("Got invalid trans2 request: %s\n",
7550 nt_errstr(result
)));
7551 reply_nterror(req
, result
);
7552 END_PROFILE(SMBtrans2
);
7557 switch (tran_call
) {
7558 /* List the allowed trans2 calls on IPC$ */
7559 case TRANSACT2_OPEN
:
7560 case TRANSACT2_GET_DFS_REFERRAL
:
7561 case TRANSACT2_QFILEINFO
:
7562 case TRANSACT2_QFSINFO
:
7563 case TRANSACT2_SETFSINFO
:
7566 reply_doserror(req
, ERRSRV
, ERRaccess
);
7567 END_PROFILE(SMBtrans2
);
7572 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
7573 DEBUG(0, ("talloc failed\n"));
7574 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7575 END_PROFILE(SMBtrans2
);
7579 state
->cmd
= SMBtrans2
;
7581 state
->mid
= req
->mid
;
7582 state
->vuid
= req
->vuid
;
7583 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7584 state
->setup
= NULL
;
7585 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7586 state
->param
= NULL
;
7587 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7589 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7590 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7591 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7592 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7593 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7595 state
->call
= tran_call
;
7597 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7598 is so as a sanity check */
7599 if (state
->setup_count
!= 1) {
7601 * Need to have rc=0 for ioctl to get job id for OS/2.
7602 * Network printing will fail if function is not successful.
7603 * Similar function in reply.c will be used if protocol
7604 * is LANMAN1.0 instead of LM1.2X002.
7605 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7606 * outbuf doesn't have to be set(only job id is used).
7608 if ( (state
->setup_count
== 4)
7609 && (tran_call
== TRANSACT2_IOCTL
)
7610 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7611 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7612 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7614 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7615 DEBUG(2,("Transaction is %d\n",tran_call
));
7617 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7618 END_PROFILE(SMBtrans2
);
7623 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7626 if (state
->total_data
) {
7627 /* Can't use talloc here, the core routines do realloc on the
7628 * params and data. */
7629 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7630 if (state
->data
== NULL
) {
7631 DEBUG(0,("reply_trans2: data malloc fail for %u "
7632 "bytes !\n", (unsigned int)state
->total_data
));
7634 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7635 END_PROFILE(SMBtrans2
);
7639 if (dscnt
> state
->total_data
||
7640 dsoff
+dscnt
< dsoff
) {
7644 if (dsoff
> av_size
||
7646 dsoff
+dscnt
> av_size
) {
7650 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7653 if (state
->total_param
) {
7654 /* Can't use talloc here, the core routines do realloc on the
7655 * params and data. */
7656 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7657 if (state
->param
== NULL
) {
7658 DEBUG(0,("reply_trans: param malloc fail for %u "
7659 "bytes !\n", (unsigned int)state
->total_param
));
7660 SAFE_FREE(state
->data
);
7662 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7663 END_PROFILE(SMBtrans2
);
7667 if (pscnt
> state
->total_param
||
7668 psoff
+pscnt
< psoff
) {
7672 if (psoff
> av_size
||
7674 psoff
+pscnt
> av_size
) {
7678 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7681 state
->received_data
= dscnt
;
7682 state
->received_param
= pscnt
;
7684 if ((state
->received_param
== state
->total_param
) &&
7685 (state
->received_data
== state
->total_data
)) {
7687 handle_trans2(conn
, req
, state
);
7689 SAFE_FREE(state
->data
);
7690 SAFE_FREE(state
->param
);
7692 END_PROFILE(SMBtrans2
);
7696 DLIST_ADD(conn
->pending_trans
, state
);
7698 /* We need to send an interim response then receive the rest
7699 of the parameter/data bytes */
7700 reply_outbuf(req
, 0, 0);
7701 show_msg((char *)req
->outbuf
);
7702 END_PROFILE(SMBtrans2
);
7707 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7708 SAFE_FREE(state
->data
);
7709 SAFE_FREE(state
->param
);
7711 END_PROFILE(SMBtrans2
);
7712 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7716 /****************************************************************************
7717 Reply to a SMBtranss2
7718 ****************************************************************************/
7720 void reply_transs2(struct smb_request
*req
)
7722 connection_struct
*conn
= req
->conn
;
7723 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7724 struct trans_state
*state
;
7726 unsigned int av_size
;
7728 START_PROFILE(SMBtranss2
);
7730 show_msg((char *)req
->inbuf
);
7733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7734 END_PROFILE(SMBtranss2
);
7738 size
= smb_len(req
->inbuf
)+4;
7739 av_size
= smb_len(req
->inbuf
);
7741 for (state
= conn
->pending_trans
; state
!= NULL
;
7742 state
= state
->next
) {
7743 if (state
->mid
== req
->mid
) {
7748 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7750 END_PROFILE(SMBtranss2
);
7754 /* Revise state->total_param and state->total_data in case they have
7755 changed downwards */
7757 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7758 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7759 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7760 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7762 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7763 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7764 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7766 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7767 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7768 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7770 state
->received_param
+= pcnt
;
7771 state
->received_data
+= dcnt
;
7773 if ((state
->received_data
> state
->total_data
) ||
7774 (state
->received_param
> state
->total_param
))
7778 if (pdisp
> state
->total_param
||
7779 pcnt
> state
->total_param
||
7780 pdisp
+pcnt
> state
->total_param
||
7781 pdisp
+pcnt
< pdisp
) {
7785 if (poff
> av_size
||
7787 poff
+pcnt
> av_size
||
7792 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7797 if (ddisp
> state
->total_data
||
7798 dcnt
> state
->total_data
||
7799 ddisp
+dcnt
> state
->total_data
||
7800 ddisp
+dcnt
< ddisp
) {
7804 if (ddisp
> av_size
||
7806 ddisp
+dcnt
> av_size
||
7807 ddisp
+dcnt
< ddisp
) {
7811 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7815 if ((state
->received_param
< state
->total_param
) ||
7816 (state
->received_data
< state
->total_data
)) {
7817 END_PROFILE(SMBtranss2
);
7822 * construct_reply_common will copy smb_com from inbuf to
7823 * outbuf. SMBtranss2 is wrong here.
7825 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7827 handle_trans2(conn
, req
, state
);
7829 DLIST_REMOVE(conn
->pending_trans
, state
);
7830 SAFE_FREE(state
->data
);
7831 SAFE_FREE(state
->param
);
7834 END_PROFILE(SMBtranss2
);
7839 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7840 DLIST_REMOVE(conn
->pending_trans
, state
);
7841 SAFE_FREE(state
->data
);
7842 SAFE_FREE(state
->param
);
7844 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7845 END_PROFILE(SMBtranss2
);