2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol
;
30 extern uint32 global_client_caps
;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
52 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, const SMB_STRUCT_STAT
*sbuf
)
71 if(S_ISDIR(sbuf
->st_mode
)) {
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
78 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
81 if (fsp
&& fsp
->initial_allocation_size
)
82 ret
= MAX(ret
,fsp
->initial_allocation_size
);
84 return smb_roundup(conn
, ret
);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name
)
97 static const char *prohibited_ea_names
[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME
,
99 SAMBA_XATTR_DOS_ATTRIB
,
105 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
106 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
109 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
121 files_struct
*fsp
, const char *fname
,
122 const char *ea_name
, struct ea_struct
*pea
)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size
= 256;
131 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
133 return NT_STATUS_NO_MEMORY
;
136 if (fsp
&& fsp
->fh
->fd
!= -1) {
137 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
139 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
142 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
148 return map_nt_error_from_unix(errno
);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
152 dump_data(10, (uint8
*)val
, sizeret
);
155 if (strnequal(ea_name
, "user.", 5)) {
156 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
158 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
160 if (pea
->name
== NULL
) {
162 return NT_STATUS_NO_MEMORY
;
164 pea
->value
.data
= (unsigned char *)val
;
165 pea
->value
.length
= (size_t)sizeret
;
169 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
170 files_struct
*fsp
, const char *fname
,
171 char ***pnames
, size_t *pnum_names
)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size
= 1024;
175 char *ea_namelist
= NULL
;
180 ssize_t sizeret
= -1;
182 if (!lp_ea_support(SNUM(conn
))) {
189 * TALLOC the result early to get the talloc hierarchy right.
192 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY
;
198 while (ea_namelist_size
<= 65536) {
200 ea_namelist
= TALLOC_REALLOC_ARRAY(
201 names
, ea_namelist
, char, ea_namelist_size
);
202 if (ea_namelist
== NULL
) {
203 DEBUG(0, ("talloc failed\n"));
205 return NT_STATUS_NO_MEMORY
;
208 if (fsp
&& fsp
->fh
->fd
!= -1) {
209 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
212 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
216 if ((sizeret
== -1) && (errno
== ERANGE
)) {
217 ea_namelist_size
*= 2;
226 return map_nt_error_from_unix(errno
);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret
));
240 * Ensure the result is 0-terminated
243 if (ea_namelist
[sizeret
-1] != '\0') {
245 return NT_STATUS_INTERNAL_ERROR
;
253 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
257 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
259 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY
;
267 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
268 names
[num_names
++] = p
;
272 *pnum_names
= num_names
;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
281 const char *fname
, size_t *pea_total_len
)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list
*ea_list_head
= NULL
;
291 if (!lp_ea_support(SNUM(conn
))) {
295 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
298 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
302 for (i
=0; i
<num_names
; i
++) {
303 struct ea_list
*listp
;
306 if (strnequal(names
[i
], "system.", 7)
307 || samba_private_attr_name(names
[i
]))
310 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
321 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
324 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
328 (unsigned int)listp
->ea
.value
.length
));
330 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
334 /* Add on 4 for total length. */
335 if (*pea_total_len
) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len
));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
351 connection_struct
*conn
, struct ea_list
*ea_list
)
353 unsigned int ret_data_size
= 4;
356 SMB_ASSERT(total_data_size
>= 4);
358 if (!lp_ea_support(SNUM(conn
))) {
363 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
366 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
367 dos_namelen
= strlen(dos_ea_name
);
368 if (dos_namelen
> 255 || dos_namelen
== 0) {
371 if (ea_list
->ea
.value
.length
> 65535) {
374 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
378 /* We know we have room. */
379 SCVAL(p
,0,ea_list
->ea
.flags
);
380 SCVAL(p
,1,dos_namelen
);
381 SSVAL(p
,2,ea_list
->ea
.value
.length
);
382 fstrcpy(p
+4, dos_ea_name
);
383 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
385 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
386 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
389 ret_data_size
= PTR_DIFF(p
, pdata
);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
391 SIVAL(pdata
,0,ret_data_size
);
392 return ret_data_size
;
395 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
397 size_t total_ea_len
= 0;
398 TALLOC_CTX
*mem_ctx
= NULL
;
400 if (!lp_ea_support(SNUM(conn
))) {
403 mem_ctx
= talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
415 TALLOC_CTX
*mem_ctx
= talloc_tos();
416 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
418 for (; ea_list
; ea_list
= ea_list
->next
) {
419 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name
[5], ea_list
->ea
.name
));
422 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
434 if (!lp_ea_support(SNUM(conn
))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED
;
438 for (;ea_list
; ea_list
= ea_list
->next
) {
440 fstring unix_ea_name
;
442 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
445 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
449 if (samba_private_attr_name(unix_ea_name
)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
451 return NT_STATUS_ACCESS_DENIED
;
454 if (ea_list
->ea
.value
.length
== 0) {
455 /* Remove the attribute. */
456 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name
, fsp
->fsp_name
));
459 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name
, fname
));
463 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
466 /* Removing a non existent attribute always succeeds. */
467 if (ret
== -1 && errno
== ENOATTR
) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
474 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name
, fsp
->fsp_name
));
477 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
478 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name
, fname
));
482 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
483 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
489 if (errno
== ENOTSUP
) {
490 return NT_STATUS_EAS_NOT_SUPPORTED
;
493 return map_nt_error_from_unix(errno
);
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
505 struct ea_list
*ea_list_head
= NULL
;
506 size_t converted_size
, offset
= 0;
508 while (offset
+ 2 < data_size
) {
509 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
510 unsigned int namelen
= CVAL(pdata
,offset
);
512 offset
++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
516 (offset
> data_size
) || (namelen
> data_size
) ||
517 (offset
+ namelen
>= data_size
)) {
520 /* Ensure the name is null terminated. */
521 if (pdata
[offset
+ namelen
] != '\0') {
524 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno
)));
533 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
547 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
549 unsigned int namelen
;
550 size_t converted_size
;
560 eal
->ea
.flags
= CVAL(pdata
,0);
561 namelen
= CVAL(pdata
,1);
562 val_len
= SVAL(pdata
,2);
564 if (4 + namelen
+ 1 + val_len
> data_size
) {
568 /* Ensure the name is null terminated. */
569 if (pdata
[namelen
+ 4] != '\0') {
572 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
580 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
581 if (!eal
->ea
.value
.data
) {
585 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal
->ea
.value
.data
[val_len
] = '\0';
589 /* But don't count the null. */
590 eal
->ea
.value
.length
--;
593 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
597 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
608 struct ea_list
*ea_list_head
= NULL
;
610 size_t bytes_used
= 0;
612 while (offset
< data_size
) {
613 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
619 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
620 offset
+= bytes_used
;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list
*ealist
)
633 struct ea_list
*listp
;
636 for (listp
= ealist
; listp
; listp
= listp
->next
) {
637 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
638 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
640 /* Add on 4 for total length. */
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
656 struct ea_list
*nlistp
, *flistp
;
658 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
659 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
660 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
666 /* Copy the data from this entry. */
667 nlistp
->ea
.flags
= flistp
->ea
.flags
;
668 nlistp
->ea
.value
= flistp
->ea
.value
;
671 nlistp
->ea
.flags
= 0;
672 ZERO_STRUCT(nlistp
->ea
.value
);
676 *total_ea_len
= ea_list_size(name_list
);
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct
*conn
,
688 struct smb_request
*req
,
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send
= datasize
;
702 int params_to_send
= paramsize
;
704 const char *pp
= params
;
705 const char *pd
= pdata
;
706 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
707 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset
= 0;
709 bool overflow
= False
;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
716 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes
, datasize
));
719 datasize
= data_to_send
= max_data_bytes
;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send
== 0 && data_to_send
== 0) {
726 reply_outbuf(req
, 10, 0);
727 show_msg((char *)req
->outbuf
);
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
736 data_alignment_offset
= 4 - (params_to_send
% 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space
= max_send
- (smb_size
745 + data_alignment_offset
);
747 if (useable_space
< 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space
));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send
|| data_to_send
) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime
= params_to_send
+ data_to_send
;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
768 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
769 + data_alignment_offset
);
771 /* Set total params and data to be sent */
772 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
773 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime
= MIN(params_to_send
,useable_space
);
780 data_sent_thistime
= useable_space
- params_sent_thistime
;
781 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
783 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req
->outbuf
,smb_proff
,
791 ((smb_buf(req
->outbuf
)+alignment_offset
)
792 - smb_base(req
->outbuf
)));
794 if(params_sent_thistime
== 0)
795 SSVAL(req
->outbuf
,smb_prdisp
,0);
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
800 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
801 if(data_sent_thistime
== 0) {
802 SSVAL(req
->outbuf
,smb_droff
,0);
803 SSVAL(req
->outbuf
,smb_drdisp
, 0);
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req
->outbuf
, smb_droff
,
808 ((smb_buf(req
->outbuf
)+alignment_offset
)
809 - smb_base(req
->outbuf
))
810 + params_sent_thistime
+ data_alignment_offset
);
811 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
814 /* Initialize the padding for alignment */
816 if (alignment_offset
!= 0) {
817 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime
) {
823 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
824 params_sent_thistime
);
827 /* Copy in the data bytes */
828 if(data_sent_thistime
) {
829 if (data_alignment_offset
!= 0) {
830 memset((smb_buf(req
->outbuf
)+alignment_offset
+
831 params_sent_thistime
), 0,
832 data_alignment_offset
);
834 memcpy(smb_buf(req
->outbuf
)+alignment_offset
835 +params_sent_thistime
+data_alignment_offset
,
836 pd
,data_sent_thistime
);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime
, data_sent_thistime
, useable_space
));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send
, data_to_send
, paramsize
, datasize
));
845 error_packet_set((char *)req
->outbuf
,
846 ERRDOS
,ERRbufferoverflow
,
847 STATUS_BUFFER_OVERFLOW
,
851 /* Send the packet */
852 show_msg((char *)req
->outbuf
);
853 if (!srv_send_smb(smbd_server_fd(),
855 IS_CONN_ENCRYPTED(conn
)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req
->outbuf
);
860 pp
+= params_sent_thistime
;
861 pd
+= data_sent_thistime
;
863 params_to_send
-= params_sent_thistime
;
864 data_to_send
-= data_sent_thistime
;
867 if(params_to_send
< 0 || data_to_send
< 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send
, data_to_send
));
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct
*conn
,
882 struct smb_request
*req
,
883 char **pparams
, int total_params
,
884 char **ppdata
, int total_data
,
885 unsigned int max_data_bytes
)
887 char *params
= *pparams
;
888 char *pdata
= *ppdata
;
893 bool return_additional_info
;
904 SMB_STRUCT_STAT sbuf
;
907 struct ea_list
*ea_list
= NULL
;
912 uint32 create_disposition
;
913 uint32 create_options
= 0;
914 TALLOC_CTX
*ctx
= talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params
< 29) {
921 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
925 flags
= SVAL(params
, 0);
926 deny_mode
= SVAL(params
, 2);
927 open_attr
= SVAL(params
,6);
928 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
929 if (oplock_request
) {
930 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
934 return_additional_info
= BITSETW(params
,0);
935 open_sattr
= SVAL(params
, 4);
936 open_time
= make_unix_date3(params
+8);
938 open_ofun
= SVAL(params
,12);
939 open_size
= IVAL(params
,14);
943 reply_doserror(req
, ERRSRV
, ERRaccess
);
947 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
948 total_params
- 28, STR_TERMINATE
,
950 if (!NT_STATUS_IS_OK(status
)) {
951 reply_nterror(req
, status
);
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
957 (unsigned int)open_ofun
, open_size
));
959 if (open_ofun
== 0) {
960 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
964 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
969 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
973 /* Any data in this call is an EA list. */
974 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
975 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
979 if (total_data
!= 4) {
980 if (total_data
< 10) {
981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
985 if (IVAL(pdata
,0) > total_data
) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata
,0), (unsigned int)total_data
));
988 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
992 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
995 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
998 } else if (IVAL(pdata
,0) != 4) {
999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1003 status
= create_file(conn
, /* conn */
1005 0, /* root_dir_fid */
1007 access_mask
, /* access_mask */
1008 share_mode
, /* share_access */
1009 create_disposition
, /* create_disposition*/
1010 create_options
, /* create_options */
1011 open_attr
, /* file_attributes */
1012 oplock_request
, /* oplock_request */
1013 open_size
, /* allocation_size */
1015 ea_list
, /* ea_list */
1017 &smb_action
, /* pinfo */
1020 if (!NT_STATUS_IS_OK(status
)) {
1021 if (open_was_deferred(req
->mid
)) {
1022 /* We have re-scheduled this call. */
1025 reply_openerror(req
, status
);
1029 size
= get_file_size(sbuf
);
1030 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1031 mtime
= sbuf
.st_mtime
;
1032 inode
= sbuf
.st_ino
;
1034 close_file(fsp
,ERROR_CLOSE
);
1035 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1041 if(*pparams
== NULL
) {
1042 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1047 SSVAL(params
,0,fsp
->fnum
);
1048 SSVAL(params
,2,fattr
);
1049 srv_put_dos_date2(params
,4, mtime
);
1050 SIVAL(params
,8, (uint32
)size
);
1051 SSVAL(params
,12,deny_mode
);
1052 SSVAL(params
,14,0); /* open_type - file or directory. */
1053 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1056 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1059 SSVAL(params
,18,smb_action
);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params
,20,inode
);
1065 SSVAL(params
,24,0); /* Padding. */
1067 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fsp
->fsp_name
);
1068 SIVAL(params
, 26, ea_size
);
1070 SIVAL(params
, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct
*conn
,
1088 if (mask
[0] == '.' && mask
[1] == 0)
1090 if (dptr_has_wild(conn
->dirptr
)) {
1093 if (conn
->case_sensitive
)
1094 return strcmp(str
,mask
)==0;
1096 return StrCaseCmp(str
,mask
) == 0;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32
unix_filetype(mode_t mode
)
1106 return UNIX_TYPE_FILE
;
1107 else if(S_ISDIR(mode
))
1108 return UNIX_TYPE_DIR
;
1110 else if(S_ISLNK(mode
))
1111 return UNIX_TYPE_SYMLINK
;
1114 else if(S_ISCHR(mode
))
1115 return UNIX_TYPE_CHARDEV
;
1118 else if(S_ISBLK(mode
))
1119 return UNIX_TYPE_BLKDEV
;
1122 else if(S_ISFIFO(mode
))
1123 return UNIX_TYPE_FIFO
;
1126 else if(S_ISSOCK(mode
))
1127 return UNIX_TYPE_SOCKET
;
1130 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1131 return UNIX_TYPE_UNKNOWN
;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1140 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1141 SMB_STRUCT_STAT
*psbuf
,
1143 enum perm_type ptype
,
1148 if (perms
== SMB_MODE_NO_CHANGE
) {
1149 if (!VALID_STAT(*psbuf
)) {
1150 return NT_STATUS_INVALID_PARAMETER
;
1152 *ret_perms
= psbuf
->st_mode
;
1153 return NT_STATUS_OK
;
1157 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1158 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1159 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1160 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1161 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1162 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1163 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1164 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1165 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1167 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1170 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1173 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1178 /* Apply mode mask */
1179 ret
&= lp_create_mask(SNUM(conn
));
1180 /* Add in force bits */
1181 ret
|= lp_force_create_mode(SNUM(conn
));
1184 ret
&= lp_dir_mask(SNUM(conn
));
1185 /* Add in force bits */
1186 ret
|= lp_force_dir_mode(SNUM(conn
));
1188 case PERM_EXISTING_FILE
:
1189 /* Apply mode mask */
1190 ret
&= lp_security_mask(SNUM(conn
));
1191 /* Add in force bits */
1192 ret
|= lp_force_security_mode(SNUM(conn
));
1194 case PERM_EXISTING_DIR
:
1195 /* Apply mode mask */
1196 ret
&= lp_dir_security_mask(SNUM(conn
));
1197 /* Add in force bits */
1198 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1203 return NT_STATUS_OK
;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct
*conn
,
1212 const char *pathname
,
1213 SMB_STRUCT_STAT
*psbuf
)
1215 int saved_errno
= errno
;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn
)) &&
1218 is_msdfs_link(conn
, pathname
, psbuf
)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1223 psbuf
->st_mode
= (psbuf
->st_mode
& 0xFFF) | S_IFDIR
;
1224 errno
= saved_errno
;
1227 errno
= saved_errno
;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1237 connection_struct
*conn
,
1239 const char *path_mask
,
1242 int requires_resume_key
,
1248 int space_remaining
,
1250 bool *got_exact_match
,
1251 int *last_entry_off
,
1252 struct ea_list
*name_list
)
1256 SMB_STRUCT_STAT sbuf
;
1257 const char *mask
= NULL
;
1258 char *pathreal
= NULL
;
1259 const char *fname
= NULL
;
1260 char *p
, *q
, *pdata
= *ppdata
;
1264 SMB_OFF_T file_size
= 0;
1265 SMB_BIG_UINT allocation_size
= 0;
1267 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1268 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1270 char *last_entry_ptr
;
1272 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1273 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1274 bool check_mangled_names
= lp_manglednames(conn
->params
);
1275 char mangled_name
[13]; /* mangled 8.3 name. */
1277 *out_of_space
= False
;
1278 *got_exact_match
= False
;
1280 ZERO_STRUCT(mdate_ts
);
1281 ZERO_STRUCT(adate_ts
);
1282 ZERO_STRUCT(create_date_ts
);
1284 if (!conn
->dirptr
) {
1288 p
= strrchr_m(path_mask
,'/');
1291 mask
= talloc_strdup(ctx
,"*.*");
1301 bool ms_dfs_link
= False
;
1303 /* Needed if we run out of space */
1304 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1305 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1308 * Due to bugs in NT client redirectors we are not using
1309 * resume keys any more - set them to zero.
1310 * Check out the related comments in findfirst/findnext.
1316 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1317 (long)conn
->dirptr
,curr_dirpos
));
1324 * fname may get mangled, dname is never mangled.
1325 * Whenever we're accessing the filesystem we use
1326 * pathreal which is composed from dname.
1332 /* Mangle fname if it's an illegal name. */
1333 if (mangle_must_mangle(dname
,conn
->params
)) {
1334 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1335 continue; /* Error - couldn't mangle. */
1337 fname
= mangled_name
;
1340 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1341 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1344 if(!got_match
&& check_mangled_names
&&
1345 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1347 * It turns out that NT matches wildcards against
1348 * both long *and* short names. This may explain some
1349 * of the wildcard wierdness from old DOS clients
1350 * that some people have been seeing.... JRA.
1352 /* Force the mangling into 8.3. */
1353 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1354 continue; /* Error - couldn't mangle. */
1357 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1358 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1363 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1365 if (dont_descend
&& !isdots
) {
1371 pathreal
= talloc_asprintf(ctx
,
1376 pathreal
= talloc_asprintf(ctx
,
1386 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1387 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal
,strerror(errno
)));
1390 TALLOC_FREE(pathreal
);
1393 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1394 /* Needed to show the msdfs symlinks as
1397 ms_dfs_link
= check_msdfs_link(conn
, pathreal
, &sbuf
);
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1400 pathreal
,strerror(errno
)));
1401 TALLOC_FREE(pathreal
);
1407 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1409 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1412 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1413 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1414 TALLOC_FREE(pathreal
);
1418 if (!(mode
& aDIR
)) {
1419 file_size
= get_file_size(sbuf
);
1421 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1423 mdate_ts
= get_mtimespec(&sbuf
);
1424 adate_ts
= get_atimespec(&sbuf
);
1425 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1427 if (ask_sharemode
) {
1428 struct timespec write_time_ts
;
1429 struct file_id fileid
;
1431 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
1432 get_file_infos(fileid
, NULL
, &write_time_ts
);
1433 if (!null_timespec(write_time_ts
)) {
1434 mdate_ts
= write_time_ts
;
1438 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1439 dos_filetime_timespec(&create_date_ts
);
1440 dos_filetime_timespec(&mdate_ts
);
1441 dos_filetime_timespec(&adate_ts
);
1444 create_date
= convert_timespec_to_time_t(create_date_ts
);
1445 mdate
= convert_timespec_to_time_t(mdate_ts
);
1446 adate
= convert_timespec_to_time_t(adate_ts
);
1448 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1452 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1459 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1461 switch (info_level
) {
1462 case SMB_FIND_INFO_STANDARD
:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key
) {
1468 srv_put_dos_date2(p
,0,create_date
);
1469 srv_put_dos_date2(p
,4,adate
);
1470 srv_put_dos_date2(p
,8,mdate
);
1471 SIVAL(p
,12,(uint32
)file_size
);
1472 SIVAL(p
,16,(uint32
)allocation_size
);
1476 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1477 p
+= ucs2_align(base_data
, p
, 0);
1479 len
= srvstr_push(base_data
, flags2
, p
,
1480 fname
, PTR_DIFF(end_data
, p
),
1482 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1484 SCVAL(nameptr
, -1, len
- 2);
1486 SCVAL(nameptr
, -1, 0);
1490 SCVAL(nameptr
, -1, len
- 1);
1492 SCVAL(nameptr
, -1, 0);
1498 case SMB_FIND_EA_SIZE
:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key
) {
1504 srv_put_dos_date2(p
,0,create_date
);
1505 srv_put_dos_date2(p
,4,adate
);
1506 srv_put_dos_date2(p
,8,mdate
);
1507 SIVAL(p
,12,(uint32
)file_size
);
1508 SIVAL(p
,16,(uint32
)allocation_size
);
1511 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1512 SIVAL(p
,22,ea_size
); /* Extended attributes */
1516 len
= srvstr_push(base_data
, flags2
,
1517 p
, fname
, PTR_DIFF(end_data
, p
),
1518 STR_TERMINATE
| STR_NOALIGN
);
1519 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1532 SCVAL(nameptr
,0,len
);
1534 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1537 case SMB_FIND_EA_LIST
:
1539 struct ea_list
*file_list
= NULL
;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1546 if(requires_resume_key
) {
1550 srv_put_dos_date2(p
,0,create_date
);
1551 srv_put_dos_date2(p
,4,adate
);
1552 srv_put_dos_date2(p
,8,mdate
);
1553 SIVAL(p
,12,(uint32
)file_size
);
1554 SIVAL(p
,16,(uint32
)allocation_size
);
1556 p
+= 22; /* p now points to the EA area. */
1558 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1559 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1566 *out_of_space
= True
;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False
; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1574 len
= srvstr_push(base_data
, flags2
,
1575 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1576 STR_TERMINATE
| STR_NOALIGN
);
1577 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1590 SCVAL(nameptr
,0,len
);
1592 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1600 SIVAL(p
,0,reskey
); p
+= 4;
1601 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1602 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1603 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1604 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1605 SOFF_T(p
,0,file_size
); p
+= 8;
1606 SOFF_T(p
,0,allocation_size
); p
+= 8;
1607 SIVAL(p
,0,nt_extmode
); p
+= 4;
1608 q
= p
; p
+= 4; /* q is placeholder for name length. */
1610 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1611 SIVAL(p
,0,ea_size
); /* Extended attributes */
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3
&& check_mangled_names
) {
1619 if (!name_to_8_3(fname
,mangled_name
,True
,
1621 /* Error - mangle failed ! */
1622 memset(mangled_name
,'\0',12);
1624 mangled_name
[12] = 0;
1625 len
= srvstr_push(base_data
, flags2
,
1626 p
+2, mangled_name
, 24,
1627 STR_UPPER
|STR_UNICODE
);
1629 memset(p
+ 2 + len
,'\0',24 - len
);
1636 len
= srvstr_push(base_data
, flags2
, p
,
1637 fname
, PTR_DIFF(end_data
, p
),
1638 STR_TERMINATE_ASCII
);
1641 SIVAL(p
,0,0); /* Ensure any padding is null. */
1642 len
= PTR_DIFF(p
, pdata
);
1643 len
= (len
+ 3) & ~3;
1648 case SMB_FIND_FILE_DIRECTORY_INFO
:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1651 SIVAL(p
,0,reskey
); p
+= 4;
1652 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1653 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1654 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1655 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1656 SOFF_T(p
,0,file_size
); p
+= 8;
1657 SOFF_T(p
,0,allocation_size
); p
+= 8;
1658 SIVAL(p
,0,nt_extmode
); p
+= 4;
1659 len
= srvstr_push(base_data
, flags2
,
1660 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1661 STR_TERMINATE_ASCII
);
1664 SIVAL(p
,0,0); /* Ensure any padding is null. */
1665 len
= PTR_DIFF(p
, pdata
);
1666 len
= (len
+ 3) & ~3;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1674 SIVAL(p
,0,reskey
); p
+= 4;
1675 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1676 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1677 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1678 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1679 SOFF_T(p
,0,file_size
); p
+= 8;
1680 SOFF_T(p
,0,allocation_size
); p
+= 8;
1681 SIVAL(p
,0,nt_extmode
); p
+= 4;
1682 q
= p
; p
+= 4; /* q is placeholder for name length. */
1684 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1685 SIVAL(p
,0,ea_size
); /* Extended attributes */
1688 len
= srvstr_push(base_data
, flags2
, p
,
1689 fname
, PTR_DIFF(end_data
, p
),
1690 STR_TERMINATE_ASCII
);
1694 SIVAL(p
,0,0); /* Ensure any padding is null. */
1695 len
= PTR_DIFF(p
, pdata
);
1696 len
= (len
+ 3) & ~3;
1701 case SMB_FIND_FILE_NAMES_INFO
:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1704 SIVAL(p
,0,reskey
); p
+= 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len
= srvstr_push(base_data
, flags2
, p
,
1709 fname
, PTR_DIFF(end_data
, p
),
1710 STR_TERMINATE_ASCII
);
1713 SIVAL(p
,0,0); /* Ensure any padding is null. */
1714 len
= PTR_DIFF(p
, pdata
);
1715 len
= (len
+ 3) & ~3;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1723 SIVAL(p
,0,reskey
); p
+= 4;
1724 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1725 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1726 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1727 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1728 SOFF_T(p
,0,file_size
); p
+= 8;
1729 SOFF_T(p
,0,allocation_size
); p
+= 8;
1730 SIVAL(p
,0,nt_extmode
); p
+= 4;
1731 q
= p
; p
+= 4; /* q is placeholder for name length. */
1733 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1734 SIVAL(p
,0,ea_size
); /* Extended attributes */
1737 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1738 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1739 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1740 len
= srvstr_push(base_data
, flags2
, p
,
1741 fname
, PTR_DIFF(end_data
, p
),
1742 STR_TERMINATE_ASCII
);
1745 SIVAL(p
,0,0); /* Ensure any padding is null. */
1746 len
= PTR_DIFF(p
, pdata
);
1747 len
= (len
+ 3) & ~3;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1756 SIVAL(p
,0,reskey
); p
+= 4;
1757 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1758 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1759 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1760 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1761 SOFF_T(p
,0,file_size
); p
+= 8;
1762 SOFF_T(p
,0,allocation_size
); p
+= 8;
1763 SIVAL(p
,0,nt_extmode
); p
+= 4;
1764 q
= p
; p
+= 4; /* q is placeholder for name length */
1766 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1767 SIVAL(p
,0,ea_size
); /* Extended attributes */
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3
&& check_mangled_names
) {
1775 if (!name_to_8_3(fname
,mangled_name
,True
,
1777 /* Error - mangle failed ! */
1778 memset(mangled_name
,'\0',12);
1780 mangled_name
[12] = 0;
1781 len
= srvstr_push(base_data
, flags2
,
1782 p
+2, mangled_name
, 24,
1783 STR_UPPER
|STR_UNICODE
);
1786 memset(p
+ 2 + len
,'\0',24 - len
);
1793 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1794 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1795 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1796 len
= srvstr_push(base_data
, flags2
, p
,
1797 fname
, PTR_DIFF(end_data
, p
),
1798 STR_TERMINATE_ASCII
);
1801 SIVAL(p
,0,0); /* Ensure any padding is null. */
1802 len
= PTR_DIFF(p
, pdata
);
1803 len
= (len
+ 3) & ~3;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX
:
1811 case SMB_FIND_FILE_UNIX_INFO2
:
1813 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level
== SMB_FIND_FILE_UNIX
) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p
= store_file_unix_basic(conn
, p
,
1821 len
= srvstr_push(base_data
, flags2
, p
,
1822 fname
, PTR_DIFF(end_data
, p
),
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p
= store_file_unix_basic_info2(conn
, p
,
1830 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1831 PTR_DIFF(end_data
, p
), 0);
1832 SIVAL(nameptr
, 0, len
);
1836 SIVAL(p
,0,0); /* Ensure any padding is null. */
1838 len
= PTR_DIFF(p
, pdata
);
1839 len
= (len
+ 3) & ~3;
1840 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1851 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1852 /* Move the dirptr back to prev_dirpos */
1853 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1854 *out_of_space
= True
;
1855 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1856 return False
; /* Not finished - just out of space */
1859 /* Setup the last entry pointer, as an offset from base_data */
1860 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1861 /* Advance the data pointer to the next slot */
1867 /****************************************************************************
1868 Reply to a TRANS2_FINDFIRST.
1869 ****************************************************************************/
1871 static void call_trans2findfirst(connection_struct
*conn
,
1872 struct smb_request
*req
,
1873 char **pparams
, int total_params
,
1874 char **ppdata
, int total_data
,
1875 unsigned int max_data_bytes
)
1877 /* We must be careful here that we don't return more than the
1878 allowed number of data bytes. If this means returning fewer than
1879 maxentries then so be it. We assume that the redirector has
1880 enough room for the fixed number of parameter bytes it has
1882 char *params
= *pparams
;
1883 char *pdata
= *ppdata
;
1887 uint16 findfirst_flags
;
1888 bool close_after_first
;
1890 bool requires_resume_key
;
1892 char *directory
= NULL
;
1895 int last_entry_off
=0;
1899 bool finished
= False
;
1900 bool dont_descend
= False
;
1901 bool out_of_space
= False
;
1902 int space_remaining
;
1903 bool mask_contains_wcard
= False
;
1904 SMB_STRUCT_STAT sbuf
;
1905 struct ea_list
*ea_list
= NULL
;
1906 NTSTATUS ntstatus
= NT_STATUS_OK
;
1907 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1908 TALLOC_CTX
*ctx
= talloc_tos();
1910 if (total_params
< 13) {
1911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1915 dirtype
= SVAL(params
,0);
1916 maxentries
= SVAL(params
,2);
1917 findfirst_flags
= SVAL(params
,4);
1918 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1919 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1920 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1921 info_level
= SVAL(params
,6);
1923 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1924 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1925 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1926 info_level
, max_data_bytes
));
1929 /* W2K3 seems to treat zero as 1. */
1933 switch (info_level
) {
1934 case SMB_FIND_INFO_STANDARD
:
1935 case SMB_FIND_EA_SIZE
:
1936 case SMB_FIND_EA_LIST
:
1937 case SMB_FIND_FILE_DIRECTORY_INFO
:
1938 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1939 case SMB_FIND_FILE_NAMES_INFO
:
1940 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1942 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1944 case SMB_FIND_FILE_UNIX
:
1945 case SMB_FIND_FILE_UNIX_INFO2
:
1946 /* Always use filesystem for UNIX mtime query. */
1947 ask_sharemode
= false;
1948 if (!lp_unix_extensions()) {
1949 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1954 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1958 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1959 params
+12, total_params
- 12,
1960 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1961 if (!NT_STATUS_IS_OK(ntstatus
)) {
1962 reply_nterror(req
, ntstatus
);
1966 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1967 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1970 &mask_contains_wcard
);
1971 if (!NT_STATUS_IS_OK(ntstatus
)) {
1972 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1973 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1974 ERRSRV
, ERRbadpath
);
1977 reply_nterror(req
, ntstatus
);
1981 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, &mask
, &sbuf
);
1982 if (!NT_STATUS_IS_OK(ntstatus
)) {
1983 reply_nterror(req
, ntstatus
);
1987 ntstatus
= check_name(conn
, directory
);
1988 if (!NT_STATUS_IS_OK(ntstatus
)) {
1989 reply_nterror(req
, ntstatus
);
1993 p
= strrchr_m(directory
,'/');
1995 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1996 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1997 mask
= talloc_strdup(ctx
,"*");
1999 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2002 mask_contains_wcard
= True
;
2004 directory
= talloc_strdup(talloc_tos(), "./");
2006 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2013 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2015 if (info_level
== SMB_FIND_EA_LIST
) {
2018 if (total_data
< 4) {
2019 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2023 ea_size
= IVAL(pdata
,0);
2024 if (ea_size
!= total_data
) {
2025 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2026 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2027 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2031 if (!lp_ea_support(SNUM(conn
))) {
2032 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2036 /* Pull out the list of names. */
2037 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2039 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2044 *ppdata
= (char *)SMB_REALLOC(
2045 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2046 if(*ppdata
== NULL
) {
2047 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2051 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2053 /* Realloc the params space */
2054 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2055 if (*pparams
== NULL
) {
2056 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2061 /* Save the wildcard match and attribs we are using on this directory -
2062 needed as lanman2 assumes these are being saved between calls */
2064 ntstatus
= dptr_create(conn
,
2070 mask_contains_wcard
,
2074 if (!NT_STATUS_IS_OK(ntstatus
)) {
2075 reply_nterror(req
, ntstatus
);
2079 dptr_num
= dptr_dnum(conn
->dirptr
);
2080 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2082 /* We don't need to check for VOL here as this is returned by
2083 a different TRANS2 call. */
2085 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2086 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2087 dont_descend
= True
;
2090 space_remaining
= max_data_bytes
;
2091 out_of_space
= False
;
2093 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2094 bool got_exact_match
= False
;
2096 /* this is a heuristic to avoid seeking the dirptr except when
2097 absolutely necessary. It allows for a filename of about 40 chars */
2098 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2099 out_of_space
= True
;
2102 finished
= !get_lanman2_dir_entry(ctx
,
2105 mask
,dirtype
,info_level
,
2106 requires_resume_key
,dont_descend
,
2109 space_remaining
, &out_of_space
,
2111 &last_entry_off
, ea_list
);
2114 if (finished
&& out_of_space
)
2117 if (!finished
&& !out_of_space
)
2121 * As an optimisation if we know we aren't looking
2122 * for a wildcard name (ie. the name matches the wildcard exactly)
2123 * then we can finish on any (first) match.
2124 * This speeds up large directory searches. JRA.
2130 /* Ensure space_remaining never goes -ve. */
2131 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2132 space_remaining
= 0;
2133 out_of_space
= true;
2135 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2139 /* Check if we can close the dirptr */
2140 if(close_after_first
|| (finished
&& close_if_end
)) {
2141 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2142 dptr_close(&dptr_num
);
2146 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2147 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2148 * the protocol level is less than NT1. Tested with smbclient. JRA.
2149 * This should fix the OS/2 client bug #2335.
2152 if(numentries
== 0) {
2153 dptr_close(&dptr_num
);
2154 if (Protocol
< PROTOCOL_NT1
) {
2155 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2158 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2159 ERRDOS
, ERRbadfile
);
2164 /* At this point pdata points to numentries directory entries. */
2166 /* Set up the return parameter block */
2167 SSVAL(params
,0,dptr_num
);
2168 SSVAL(params
,2,numentries
);
2169 SSVAL(params
,4,finished
);
2170 SSVAL(params
,6,0); /* Never an EA error */
2171 SSVAL(params
,8,last_entry_off
);
2173 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2176 if ((! *directory
) && dptr_path(dptr_num
)) {
2177 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2179 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2183 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2184 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2185 mask
, directory
, dirtype
, numentries
) );
2188 * Force a name mangle here to ensure that the
2189 * mask as an 8.3 name is top of the mangled cache.
2190 * The reasons for this are subtle. Don't remove
2191 * this code unless you know what you are doing
2192 * (see PR#13758). JRA.
2195 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2196 char mangled_name
[13];
2197 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2203 /****************************************************************************
2204 Reply to a TRANS2_FINDNEXT.
2205 ****************************************************************************/
2207 static void call_trans2findnext(connection_struct
*conn
,
2208 struct smb_request
*req
,
2209 char **pparams
, int total_params
,
2210 char **ppdata
, int total_data
,
2211 unsigned int max_data_bytes
)
2213 /* We must be careful here that we don't return more than the
2214 allowed number of data bytes. If this means returning fewer than
2215 maxentries then so be it. We assume that the redirector has
2216 enough room for the fixed number of parameter bytes it has
2218 char *params
= *pparams
;
2219 char *pdata
= *ppdata
;
2225 uint16 findnext_flags
;
2226 bool close_after_request
;
2228 bool requires_resume_key
;
2230 bool mask_contains_wcard
= False
;
2231 char *resume_name
= NULL
;
2232 const char *mask
= NULL
;
2233 const char *directory
= NULL
;
2237 int i
, last_entry_off
=0;
2238 bool finished
= False
;
2239 bool dont_descend
= False
;
2240 bool out_of_space
= False
;
2241 int space_remaining
;
2242 struct ea_list
*ea_list
= NULL
;
2243 NTSTATUS ntstatus
= NT_STATUS_OK
;
2244 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2245 TALLOC_CTX
*ctx
= talloc_tos();
2247 if (total_params
< 13) {
2248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2252 dptr_num
= SVAL(params
,0);
2253 maxentries
= SVAL(params
,2);
2254 info_level
= SVAL(params
,4);
2255 resume_key
= IVAL(params
,6);
2256 findnext_flags
= SVAL(params
,10);
2257 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2258 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2259 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2260 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2262 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2264 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2265 &mask_contains_wcard
);
2266 if (!NT_STATUS_IS_OK(ntstatus
)) {
2267 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2268 complain (it thinks we're asking for the directory above the shared
2269 path or an invalid name). Catch this as the resume name is only compared, never used in
2270 a file access. JRA. */
2271 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2272 &resume_name
, params
+12,
2276 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2277 reply_nterror(req
, ntstatus
);
2282 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2283 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2284 resume_key = %d resume name = %s continue=%d level = %d\n",
2285 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2286 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2289 /* W2K3 seems to treat zero as 1. */
2293 switch (info_level
) {
2294 case SMB_FIND_INFO_STANDARD
:
2295 case SMB_FIND_EA_SIZE
:
2296 case SMB_FIND_EA_LIST
:
2297 case SMB_FIND_FILE_DIRECTORY_INFO
:
2298 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2299 case SMB_FIND_FILE_NAMES_INFO
:
2300 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2301 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2302 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2304 case SMB_FIND_FILE_UNIX
:
2305 case SMB_FIND_FILE_UNIX_INFO2
:
2306 /* Always use filesystem for UNIX mtime query. */
2307 ask_sharemode
= false;
2308 if (!lp_unix_extensions()) {
2309 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2314 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2318 if (info_level
== SMB_FIND_EA_LIST
) {
2321 if (total_data
< 4) {
2322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2326 ea_size
= IVAL(pdata
,0);
2327 if (ea_size
!= total_data
) {
2328 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2329 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2330 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2334 if (!lp_ea_support(SNUM(conn
))) {
2335 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2339 /* Pull out the list of names. */
2340 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2347 *ppdata
= (char *)SMB_REALLOC(
2348 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2349 if(*ppdata
== NULL
) {
2350 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2355 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2357 /* Realloc the params space */
2358 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2359 if(*pparams
== NULL
) {
2360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2366 /* Check that the dptr is valid */
2367 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2368 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2372 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2374 /* Get the wildcard mask from the dptr */
2375 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2376 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2377 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2382 directory
= conn
->dirpath
;
2384 /* Get the attr mask from the dptr */
2385 dirtype
= dptr_attr(dptr_num
);
2387 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2388 dptr_num
, mask
, dirtype
,
2390 dptr_TellDir(conn
->dirptr
)));
2392 /* We don't need to check for VOL here as this is returned by
2393 a different TRANS2 call. */
2395 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2396 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2397 dont_descend
= True
;
2400 space_remaining
= max_data_bytes
;
2401 out_of_space
= False
;
2404 * Seek to the correct position. We no longer use the resume key but
2405 * depend on the last file name instead.
2408 if(*resume_name
&& !continue_bit
) {
2411 long current_pos
= 0;
2413 * Remember, name_to_8_3 is called by
2414 * get_lanman2_dir_entry(), so the resume name
2415 * could be mangled. Ensure we check the unmangled name.
2418 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2419 char *new_resume_name
= NULL
;
2420 mangle_lookup_name_from_8_3(ctx
,
2424 if (new_resume_name
) {
2425 resume_name
= new_resume_name
;
2430 * Fix for NT redirector problem triggered by resume key indexes
2431 * changing between directory scans. We now return a resume key of 0
2432 * and instead look for the filename to continue from (also given
2433 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2434 * findfirst/findnext (as is usual) then the directory pointer
2435 * should already be at the correct place.
2438 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2439 } /* end if resume_name && !continue_bit */
2441 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2442 bool got_exact_match
= False
;
2444 /* this is a heuristic to avoid seeking the dirptr except when
2445 absolutely necessary. It allows for a filename of about 40 chars */
2446 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2447 out_of_space
= True
;
2450 finished
= !get_lanman2_dir_entry(ctx
,
2453 mask
,dirtype
,info_level
,
2454 requires_resume_key
,dont_descend
,
2457 space_remaining
, &out_of_space
,
2459 &last_entry_off
, ea_list
);
2462 if (finished
&& out_of_space
)
2465 if (!finished
&& !out_of_space
)
2469 * As an optimisation if we know we aren't looking
2470 * for a wildcard name (ie. the name matches the wildcard exactly)
2471 * then we can finish on any (first) match.
2472 * This speeds up large directory searches. JRA.
2478 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2481 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2482 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2483 mask
, directory
, dirtype
, numentries
) );
2485 /* Check if we can close the dirptr */
2486 if(close_after_request
|| (finished
&& close_if_end
)) {
2487 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2488 dptr_close(&dptr_num
); /* This frees up the saved mask */
2491 /* Set up the return parameter block */
2492 SSVAL(params
,0,numentries
);
2493 SSVAL(params
,2,finished
);
2494 SSVAL(params
,4,0); /* Never an EA error */
2495 SSVAL(params
,6,last_entry_off
);
2497 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2503 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2505 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2509 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2511 SMB_ASSERT(extended_info
!= NULL
);
2513 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2514 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2515 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2516 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2517 #ifdef SAMBA_VERSION_REVISION
2518 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2520 extended_info
->samba_subversion
= 0;
2521 #ifdef SAMBA_VERSION_RC_RELEASE
2522 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2524 #ifdef SAMBA_VERSION_PRE_RELEASE
2525 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2528 #ifdef SAMBA_VERSION_VENDOR_PATCH
2529 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2531 extended_info
->samba_gitcommitdate
= 0;
2532 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2533 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2536 memset(extended_info
->samba_version_string
, 0,
2537 sizeof(extended_info
->samba_version_string
));
2539 snprintf (extended_info
->samba_version_string
,
2540 sizeof(extended_info
->samba_version_string
),
2541 "%s", samba_version_string());
2544 /****************************************************************************
2545 Reply to a TRANS2_QFSINFO (query filesystem info).
2546 ****************************************************************************/
2548 static void call_trans2qfsinfo(connection_struct
*conn
,
2549 struct smb_request
*req
,
2550 char **pparams
, int total_params
,
2551 char **ppdata
, int total_data
,
2552 unsigned int max_data_bytes
)
2554 char *pdata
, *end_data
;
2555 char *params
= *pparams
;
2559 const char *vname
= volume_label(SNUM(conn
));
2560 int snum
= SNUM(conn
);
2561 char *fstype
= lp_fstype(SNUM(conn
));
2562 uint32 additional_flags
= 0;
2564 if (total_params
< 2) {
2565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2569 info_level
= SVAL(params
,0);
2572 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2573 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2574 "info level (0x%x) on IPC$.\n",
2575 (unsigned int)info_level
));
2576 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2581 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
2582 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2583 DEBUG(0,("call_trans2qfsinfo: encryption required "
2584 "and info level 0x%x sent.\n",
2585 (unsigned int)info_level
));
2586 exit_server_cleanly("encryption required "
2592 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2594 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2595 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2596 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2600 *ppdata
= (char *)SMB_REALLOC(
2601 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2602 if (*ppdata
== NULL
) {
2603 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2608 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2609 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2611 switch (info_level
) {
2612 case SMB_INFO_ALLOCATION
:
2614 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2616 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2617 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2621 block_size
= lp_block_size(snum
);
2622 if (bsize
< block_size
) {
2623 SMB_BIG_UINT factor
= block_size
/bsize
;
2628 if (bsize
> block_size
) {
2629 SMB_BIG_UINT factor
= bsize
/block_size
;
2634 bytes_per_sector
= 512;
2635 sectors_per_unit
= bsize
/bytes_per_sector
;
2637 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2638 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2639 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2641 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2642 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2643 SIVAL(pdata
,l1_cUnit
,dsize
);
2644 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2645 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2649 case SMB_INFO_VOLUME
:
2650 /* Return volume name */
2652 * Add volume serial number - hash of a combination of
2653 * the called hostname and the service name.
2655 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2657 * Win2k3 and previous mess this up by sending a name length
2658 * one byte short. I believe only older clients (OS/2 Win9x) use
2659 * this call so try fixing this by adding a terminating null to
2660 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2664 pdata
+l2_vol_szVolLabel
, vname
,
2665 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2666 STR_NOALIGN
|STR_TERMINATE
);
2667 SCVAL(pdata
,l2_vol_cch
,len
);
2668 data_len
= l2_vol_szVolLabel
+ len
;
2669 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2670 (unsigned)st
.st_ctime
, len
, vname
));
2673 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2674 case SMB_FS_ATTRIBUTE_INFORMATION
:
2676 additional_flags
= 0;
2677 #if defined(HAVE_SYS_QUOTAS)
2678 additional_flags
|= FILE_VOLUME_QUOTAS
;
2681 if(lp_nt_acl_support(SNUM(conn
))) {
2682 additional_flags
|= FILE_PERSISTENT_ACLS
;
2685 /* Capabilities are filled in at connection time through STATVFS call */
2686 additional_flags
|= conn
->fs_capabilities
;
2688 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2689 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2690 additional_flags
); /* FS ATTRIBUTES */
2692 SIVAL(pdata
,4,255); /* Max filename component length */
2693 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2694 and will think we can't do long filenames */
2695 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2696 PTR_DIFF(end_data
, pdata
+12),
2699 data_len
= 12 + len
;
2702 case SMB_QUERY_FS_LABEL_INFO
:
2703 case SMB_FS_LABEL_INFORMATION
:
2704 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2705 PTR_DIFF(end_data
, pdata
+4), 0);
2710 case SMB_QUERY_FS_VOLUME_INFO
:
2711 case SMB_FS_VOLUME_INFORMATION
:
2714 * Add volume serial number - hash of a combination of
2715 * the called hostname and the service name.
2717 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2718 (str_checksum(get_local_machine_name())<<16));
2720 /* Max label len is 32 characters. */
2721 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2722 PTR_DIFF(end_data
, pdata
+18),
2724 SIVAL(pdata
,12,len
);
2727 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2728 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2731 case SMB_QUERY_FS_SIZE_INFO
:
2732 case SMB_FS_SIZE_INFORMATION
:
2734 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2736 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2737 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2740 block_size
= lp_block_size(snum
);
2741 if (bsize
< block_size
) {
2742 SMB_BIG_UINT factor
= block_size
/bsize
;
2747 if (bsize
> block_size
) {
2748 SMB_BIG_UINT factor
= bsize
/block_size
;
2753 bytes_per_sector
= 512;
2754 sectors_per_unit
= bsize
/bytes_per_sector
;
2755 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2756 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2757 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2758 SBIG_UINT(pdata
,0,dsize
);
2759 SBIG_UINT(pdata
,8,dfree
);
2760 SIVAL(pdata
,16,sectors_per_unit
);
2761 SIVAL(pdata
,20,bytes_per_sector
);
2765 case SMB_FS_FULL_SIZE_INFORMATION
:
2767 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2769 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2770 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2773 block_size
= lp_block_size(snum
);
2774 if (bsize
< block_size
) {
2775 SMB_BIG_UINT factor
= block_size
/bsize
;
2780 if (bsize
> block_size
) {
2781 SMB_BIG_UINT factor
= bsize
/block_size
;
2786 bytes_per_sector
= 512;
2787 sectors_per_unit
= bsize
/bytes_per_sector
;
2788 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2789 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2790 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2791 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2792 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2793 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2794 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2795 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2799 case SMB_QUERY_FS_DEVICE_INFO
:
2800 case SMB_FS_DEVICE_INFORMATION
:
2802 SIVAL(pdata
,0,0); /* dev type */
2803 SIVAL(pdata
,4,0); /* characteristics */
2806 #ifdef HAVE_SYS_QUOTAS
2807 case SMB_FS_QUOTA_INFORMATION
:
2809 * what we have to send --metze:
2811 * Unknown1: 24 NULL bytes
2812 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2813 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2814 * Quota Flags: 2 byte :
2815 * Unknown3: 6 NULL bytes
2819 * details for Quota Flags:
2821 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2822 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2823 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2824 * 0x0001 Enable Quotas: enable quota for this fs
2828 /* we need to fake up a fsp here,
2829 * because its not send in this call
2832 SMB_NTQUOTA_STRUCT quotas
;
2835 ZERO_STRUCT(quotas
);
2841 if (conn
->server_info
->utok
.uid
!= 0) {
2842 DEBUG(0,("set_user_quota: access_denied "
2843 "service [%s] user [%s]\n",
2844 lp_servicename(SNUM(conn
)),
2845 conn
->server_info
->unix_name
));
2846 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2850 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2851 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2852 reply_doserror(req
, ERRSRV
, ERRerror
);
2858 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2860 /* Unknown1 24 NULL bytes*/
2861 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2862 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2863 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2865 /* Default Soft Quota 8 bytes */
2866 SBIG_UINT(pdata
,24,quotas
.softlim
);
2868 /* Default Hard Quota 8 bytes */
2869 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2871 /* Quota flag 2 bytes */
2872 SSVAL(pdata
,40,quotas
.qflags
);
2874 /* Unknown3 6 NULL bytes */
2880 #endif /* HAVE_SYS_QUOTAS */
2881 case SMB_FS_OBJECTID_INFORMATION
:
2883 unsigned char objid
[16];
2884 struct smb_extended_info extended_info
;
2885 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2886 samba_extended_info_version (&extended_info
);
2887 SIVAL(pdata
,16,extended_info
.samba_magic
);
2888 SIVAL(pdata
,20,extended_info
.samba_version
);
2889 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2890 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2891 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2897 * Query the version and capabilities of the CIFS UNIX extensions
2901 case SMB_QUERY_CIFS_UNIX_INFO
:
2903 bool large_write
= lp_min_receive_file_size() &&
2904 !srv_is_signing_active();
2905 bool large_read
= !srv_is_signing_active();
2906 int encrypt_caps
= 0;
2908 if (!lp_unix_extensions()) {
2909 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2913 switch (conn
->encrypt_level
) {
2919 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2922 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2923 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2924 large_write
= false;
2930 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2931 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2933 /* We have POSIX ACLs, pathname, encryption,
2934 * large read/write, and locking capability. */
2936 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2937 CIFS_UNIX_POSIX_ACLS_CAP
|
2938 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2939 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2940 CIFS_UNIX_EXTATTR_CAP
|
2941 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2943 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2945 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2949 case SMB_QUERY_POSIX_FS_INFO
:
2952 vfs_statvfs_struct svfs
;
2954 if (!lp_unix_extensions()) {
2955 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2959 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2963 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2964 SIVAL(pdata
,4,svfs
.BlockSize
);
2965 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2966 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2967 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2968 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2969 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2970 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2971 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2973 } else if (rc
== EOPNOTSUPP
) {
2974 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2976 #endif /* EOPNOTSUPP */
2978 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2979 reply_doserror(req
, ERRSRV
, ERRerror
);
2985 case SMB_QUERY_POSIX_WHOAMI
:
2991 if (!lp_unix_extensions()) {
2992 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2996 if (max_data_bytes
< 40) {
2997 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
3001 /* We ARE guest if global_sid_Builtin_Guests is
3002 * in our list of SIDs.
3004 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3005 conn
->server_info
->ptok
)) {
3006 flags
|= SMB_WHOAMI_GUEST
;
3009 /* We are NOT guest if global_sid_Authenticated_Users
3010 * is in our list of SIDs.
3012 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3013 conn
->server_info
->ptok
)) {
3014 flags
&= ~SMB_WHOAMI_GUEST
;
3017 /* NOTE: 8 bytes for UID/GID, irrespective of native
3018 * platform size. This matches
3019 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3021 data_len
= 4 /* flags */
3028 + 4 /* pad/reserved */
3029 + (conn
->server_info
->utok
.ngroups
* 8)
3031 + (conn
->server_info
->ptok
->num_sids
*
3035 SIVAL(pdata
, 0, flags
);
3036 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3038 (SMB_BIG_UINT
)conn
->server_info
->utok
.uid
);
3039 SBIG_UINT(pdata
, 16,
3040 (SMB_BIG_UINT
)conn
->server_info
->utok
.gid
);
3043 if (data_len
>= max_data_bytes
) {
3044 /* Potential overflow, skip the GIDs and SIDs. */
3046 SIVAL(pdata
, 24, 0); /* num_groups */
3047 SIVAL(pdata
, 28, 0); /* num_sids */
3048 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3049 SIVAL(pdata
, 36, 0); /* reserved */
3055 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3056 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3058 /* We walk the SID list twice, but this call is fairly
3059 * infrequent, and I don't expect that it's performance
3060 * sensitive -- jpeach
3062 for (i
= 0, sid_bytes
= 0;
3063 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3064 sid_bytes
+= ndr_size_dom_sid(
3065 &conn
->server_info
->ptok
->user_sids
[i
],
3069 /* SID list byte count */
3070 SIVAL(pdata
, 32, sid_bytes
);
3072 /* 4 bytes pad/reserved - must be zero */
3073 SIVAL(pdata
, 36, 0);
3077 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3078 SBIG_UINT(pdata
, data_len
,
3079 (SMB_BIG_UINT
)conn
->server_info
->utok
.groups
[i
]);
3085 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3086 int sid_len
= ndr_size_dom_sid(
3087 &conn
->server_info
->ptok
->user_sids
[i
],
3090 sid_linearize(pdata
+ data_len
, sid_len
,
3091 &conn
->server_info
->ptok
->user_sids
[i
]);
3092 data_len
+= sid_len
;
3098 case SMB_MAC_QUERY_FS_INFO
:
3100 * Thursby MAC extension... ONLY on NTFS filesystems
3101 * once we do streams then we don't need this
3103 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3105 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3110 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3115 send_trans2_replies(conn
, req
, params
, 0, pdata
, data_len
,
3118 DEBUG( 4, ( "%s info_level = %d\n",
3119 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
3124 /****************************************************************************
3125 Reply to a TRANS2_SETFSINFO (set filesystem info).
3126 ****************************************************************************/
3128 static void call_trans2setfsinfo(connection_struct
*conn
,
3129 struct smb_request
*req
,
3130 char **pparams
, int total_params
,
3131 char **ppdata
, int total_data
,
3132 unsigned int max_data_bytes
)
3134 char *pdata
= *ppdata
;
3135 char *params
= *pparams
;
3138 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3141 if (total_params
< 4) {
3142 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3144 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3148 info_level
= SVAL(params
,2);
3151 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3152 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3153 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3154 "info level (0x%x) on IPC$.\n",
3155 (unsigned int)info_level
));
3156 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3161 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3162 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3163 DEBUG(0,("call_trans2setfsinfo: encryption required "
3164 "and info level 0x%x sent.\n",
3165 (unsigned int)info_level
));
3166 exit_server_cleanly("encryption required "
3172 switch(info_level
) {
3173 case SMB_SET_CIFS_UNIX_INFO
:
3175 uint16 client_unix_major
;
3176 uint16 client_unix_minor
;
3177 uint32 client_unix_cap_low
;
3178 uint32 client_unix_cap_high
;
3180 if (!lp_unix_extensions()) {
3182 NT_STATUS_INVALID_LEVEL
);
3186 /* There should be 12 bytes of capabilities set. */
3187 if (total_data
< 8) {
3190 NT_STATUS_INVALID_PARAMETER
);
3193 client_unix_major
= SVAL(pdata
,0);
3194 client_unix_minor
= SVAL(pdata
,2);
3195 client_unix_cap_low
= IVAL(pdata
,4);
3196 client_unix_cap_high
= IVAL(pdata
,8);
3197 /* Just print these values for now. */
3198 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3199 cap_low = 0x%x, cap_high = 0x%x\n",
3200 (unsigned int)client_unix_major
,
3201 (unsigned int)client_unix_minor
,
3202 (unsigned int)client_unix_cap_low
,
3203 (unsigned int)client_unix_cap_high
));
3205 /* Here is where we must switch to posix pathname processing... */
3206 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3207 lp_set_posix_pathnames();
3208 mangle_change_to_posix();
3211 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3212 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3213 /* Client that knows how to do posix locks,
3214 * but not posix open/mkdir operations. Set a
3215 * default type for read/write checks. */
3217 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3223 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3226 size_t param_len
= 0;
3227 size_t data_len
= total_data
;
3229 if (!lp_unix_extensions()) {
3232 NT_STATUS_INVALID_LEVEL
);
3236 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3239 NT_STATUS_NOT_SUPPORTED
);
3243 DEBUG( 4,("call_trans2setfsinfo: "
3244 "request transport encryption.\n"));
3246 status
= srv_request_encryption_setup(conn
,
3247 (unsigned char **)ppdata
,
3249 (unsigned char **)pparams
,
3252 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3253 !NT_STATUS_IS_OK(status
)) {
3254 reply_nterror(req
, status
);
3258 send_trans2_replies(conn
, req
,
3265 if (NT_STATUS_IS_OK(status
)) {
3266 /* Server-side transport
3267 * encryption is now *on*. */
3268 status
= srv_encryption_start(conn
);
3269 if (!NT_STATUS_IS_OK(status
)) {
3270 exit_server_cleanly(
3271 "Failure in setting "
3272 "up encrypted transport");
3278 case SMB_FS_QUOTA_INFORMATION
:
3280 files_struct
*fsp
= NULL
;
3281 SMB_NTQUOTA_STRUCT quotas
;
3283 ZERO_STRUCT(quotas
);
3286 if ((conn
->server_info
->utok
.uid
!= 0)
3287 ||!CAN_WRITE(conn
)) {
3288 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3289 lp_servicename(SNUM(conn
)),
3290 conn
->server_info
->unix_name
));
3291 reply_doserror(req
, ERRSRV
, ERRaccess
);
3295 /* note: normaly there're 48 bytes,
3296 * but we didn't use the last 6 bytes for now
3299 fsp
= file_fsp(SVAL(params
,0));
3301 if (!check_fsp_ntquota_handle(conn
, req
,
3303 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3305 req
, NT_STATUS_INVALID_HANDLE
);
3309 if (total_data
< 42) {
3310 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3314 NT_STATUS_INVALID_PARAMETER
);
3318 /* unknown_1 24 NULL bytes in pdata*/
3320 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3321 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3322 #ifdef LARGE_SMB_OFF_T
3323 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3324 #else /* LARGE_SMB_OFF_T */
3325 if ((IVAL(pdata
,28) != 0)&&
3326 ((quotas
.softlim
!= 0xFFFFFFFF)||
3327 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3328 /* more than 32 bits? */
3331 NT_STATUS_INVALID_PARAMETER
);
3334 #endif /* LARGE_SMB_OFF_T */
3336 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3337 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3338 #ifdef LARGE_SMB_OFF_T
3339 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3340 #else /* LARGE_SMB_OFF_T */
3341 if ((IVAL(pdata
,36) != 0)&&
3342 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3343 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3344 /* more than 32 bits? */
3347 NT_STATUS_INVALID_PARAMETER
);
3350 #endif /* LARGE_SMB_OFF_T */
3352 /* quota_flags 2 bytes **/
3353 quotas
.qflags
= SVAL(pdata
,40);
3355 /* unknown_2 6 NULL bytes follow*/
3357 /* now set the quotas */
3358 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3359 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3360 reply_doserror(req
, ERRSRV
, ERRerror
);
3367 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3369 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3375 * sending this reply works fine,
3376 * but I'm not sure it's the same
3377 * like windows do...
3380 reply_outbuf(req
, 10, 0);
3383 #if defined(HAVE_POSIX_ACLS)
3384 /****************************************************************************
3385 Utility function to count the number of entries in a POSIX acl.
3386 ****************************************************************************/
3388 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3390 unsigned int ace_count
= 0;
3391 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3392 SMB_ACL_ENTRY_T entry
;
3394 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3396 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3397 entry_id
= SMB_ACL_NEXT_ENTRY
;
3404 /****************************************************************************
3405 Utility function to marshall a POSIX acl into wire format.
3406 ****************************************************************************/
3408 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3410 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3411 SMB_ACL_ENTRY_T entry
;
3413 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3414 SMB_ACL_TAG_T tagtype
;
3415 SMB_ACL_PERMSET_T permset
;
3416 unsigned char perms
= 0;
3417 unsigned int own_grp
;
3420 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3421 entry_id
= SMB_ACL_NEXT_ENTRY
;
3424 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3425 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3429 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3430 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3434 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3435 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3436 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3438 SCVAL(pdata
,1,perms
);
3441 case SMB_ACL_USER_OBJ
:
3442 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3443 own_grp
= (unsigned int)pst
->st_uid
;
3444 SIVAL(pdata
,2,own_grp
);
3449 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3451 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3454 own_grp
= (unsigned int)*puid
;
3455 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3456 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3457 SIVAL(pdata
,2,own_grp
);
3461 case SMB_ACL_GROUP_OBJ
:
3462 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3463 own_grp
= (unsigned int)pst
->st_gid
;
3464 SIVAL(pdata
,2,own_grp
);
3469 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3471 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3474 own_grp
= (unsigned int)*pgid
;
3475 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3476 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3477 SIVAL(pdata
,2,own_grp
);
3482 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3483 SIVAL(pdata
,2,0xFFFFFFFF);
3484 SIVAL(pdata
,6,0xFFFFFFFF);
3487 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3488 SIVAL(pdata
,2,0xFFFFFFFF);
3489 SIVAL(pdata
,6,0xFFFFFFFF);
3492 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3495 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3502 /****************************************************************************
3503 Store the FILE_UNIX_BASIC info.
3504 ****************************************************************************/
3506 static char *store_file_unix_basic(connection_struct
*conn
,
3509 const SMB_STRUCT_STAT
*psbuf
)
3511 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3512 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3514 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3517 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3520 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3521 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3522 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3525 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3529 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3533 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3536 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3540 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3544 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3547 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3551 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3558 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3559 * the chflags(2) (or equivalent) flags.
3561 * XXX: this really should be behind the VFS interface. To do this, we would
3562 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3563 * Each VFS module could then implement its own mapping as appropriate for the
3564 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3566 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3570 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3574 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3578 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3582 { UF_HIDDEN
, EXT_HIDDEN
},
3585 /* Do not remove. We need to guarantee that this array has at least one
3586 * entry to build on HP-UX.
3592 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3593 uint32
*smb_fflags
, uint32
*smb_fmask
)
3595 #ifdef HAVE_STAT_ST_FLAGS
3598 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3599 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3600 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3601 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3604 #endif /* HAVE_STAT_ST_FLAGS */
3607 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3608 const uint32 smb_fflags
,
3609 const uint32 smb_fmask
,
3612 #ifdef HAVE_STAT_ST_FLAGS
3613 uint32 max_fmask
= 0;
3616 *stat_fflags
= psbuf
->st_flags
;
3618 /* For each flags requested in smb_fmask, check the state of the
3619 * corresponding flag in smb_fflags and set or clear the matching
3623 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3624 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3625 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3626 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3627 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3629 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3634 /* If smb_fmask is asking to set any bits that are not supported by
3635 * our flag mappings, we should fail.
3637 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3644 #endif /* HAVE_STAT_ST_FLAGS */
3648 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3649 * of file flags and birth (create) time.
3651 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3654 const SMB_STRUCT_STAT
*psbuf
)
3656 uint32 file_flags
= 0;
3657 uint32 flags_mask
= 0;
3659 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3661 /* Create (birth) time 64 bit */
3662 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3665 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3666 SIVAL(pdata
, 0, file_flags
); /* flags */
3667 SIVAL(pdata
, 4, flags_mask
); /* mask */
3673 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3674 const struct stream_struct
*streams
,
3676 unsigned int max_data_bytes
,
3677 unsigned int *data_size
)
3680 unsigned int ofs
= 0;
3682 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3683 unsigned int next_offset
;
3685 smb_ucs2_t
*namebuf
;
3687 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3688 streams
[i
].name
, &namelen
) ||
3691 return NT_STATUS_INVALID_PARAMETER
;
3695 * name_buf is now null-terminated, we need to marshall as not
3701 SIVAL(data
, ofs
+4, namelen
);
3702 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3703 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3704 memcpy(data
+ofs
+24, namebuf
, namelen
);
3705 TALLOC_FREE(namebuf
);
3707 next_offset
= ofs
+ 24 + namelen
;
3709 if (i
== num_streams
-1) {
3710 SIVAL(data
, ofs
, 0);
3713 unsigned int align
= ndr_align_size(next_offset
, 8);
3715 memset(data
+next_offset
, 0, align
);
3716 next_offset
+= align
;
3718 SIVAL(data
, ofs
, next_offset
- ofs
);
3727 return NT_STATUS_OK
;
3730 /****************************************************************************
3731 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3732 ****************************************************************************/
3734 static void call_trans2qpipeinfo(connection_struct
*conn
,
3735 struct smb_request
*req
,
3736 unsigned int tran_call
,
3737 char **pparams
, int total_params
,
3738 char **ppdata
, int total_data
,
3739 unsigned int max_data_bytes
)
3741 char *params
= *pparams
;
3742 char *pdata
= *ppdata
;
3743 unsigned int data_size
= 0;
3744 unsigned int param_size
= 2;
3746 smb_np_struct
*p_pipe
= NULL
;
3749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3753 if (total_params
< 4) {
3754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3758 p_pipe
= get_rpc_pipe_p(SVAL(params
,0));
3759 if (p_pipe
== NULL
) {
3760 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3764 info_level
= SVAL(params
,2);
3766 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3767 if (*pparams
== NULL
) {
3768 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3773 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3774 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3775 if (*ppdata
== NULL
) {
3776 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3781 switch (info_level
) {
3782 case SMB_FILE_STANDARD_INFORMATION
:
3784 SOFF_T(pdata
,0,4096LL);
3791 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3795 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3801 /****************************************************************************
3802 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3803 file name or file id).
3804 ****************************************************************************/
3806 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3807 struct smb_request
*req
,
3808 unsigned int tran_call
,
3809 char **pparams
, int total_params
,
3810 char **ppdata
, int total_data
,
3811 unsigned int max_data_bytes
)
3813 char *params
= *pparams
;
3814 char *pdata
= *ppdata
;
3815 char *dstart
, *dend
;
3819 SMB_OFF_T file_size
=0;
3820 SMB_BIG_UINT allocation_size
=0;
3821 unsigned int data_size
= 0;
3822 unsigned int param_size
= 2;
3823 SMB_STRUCT_STAT sbuf
;
3824 char *dos_fname
= NULL
;
3830 bool delete_pending
= False
;
3832 time_t create_time
, mtime
, atime
;
3833 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3834 struct timespec write_time_ts
;
3835 files_struct
*fsp
= NULL
;
3836 struct file_id fileid
;
3837 struct ea_list
*ea_list
= NULL
;
3838 char *lock_data
= NULL
;
3839 bool ms_dfs_link
= false;
3840 TALLOC_CTX
*ctx
= talloc_tos();
3843 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3848 ZERO_STRUCT(write_time_ts
);
3850 if (tran_call
== TRANSACT2_QFILEINFO
) {
3851 if (total_params
< 4) {
3852 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3857 call_trans2qpipeinfo(conn
, req
, tran_call
,
3858 pparams
, total_params
,
3864 fsp
= file_fsp(SVAL(params
,0));
3865 info_level
= SVAL(params
,2);
3867 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3869 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3870 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3874 /* Initial check for valid fsp ptr. */
3875 if (!check_fsp_open(conn
, req
, fsp
)) {
3879 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3881 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3885 if(fsp
->fake_file_handle
) {
3887 * This is actually for the QUOTA_FAKE_FILE --metze
3890 /* We know this name is ok, it's already passed the checks. */
3892 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3894 * This is actually a QFILEINFO on a directory
3895 * handle (returned from an NT SMB). NT5.0 seems
3896 * to do this call. JRA.
3899 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3900 /* Always do lstat for UNIX calls. */
3901 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3902 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3903 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3906 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3907 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3908 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3912 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3913 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3916 * Original code - this is an open file.
3918 if (!check_fsp(conn
, req
, fsp
)) {
3922 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
3923 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3924 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3927 pos
= fsp
->fh
->position_information
;
3928 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3929 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
3933 NTSTATUS status
= NT_STATUS_OK
;
3936 if (total_params
< 7) {
3937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3941 info_level
= SVAL(params
,0);
3943 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3945 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3946 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3950 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3952 STR_TERMINATE
, &status
);
3953 if (!NT_STATUS_IS_OK(status
)) {
3954 reply_nterror(req
, status
);
3958 status
= resolve_dfspath(ctx
,
3960 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3963 if (!NT_STATUS_IS_OK(status
)) {
3964 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3965 reply_botherror(req
,
3966 NT_STATUS_PATH_NOT_COVERED
,
3967 ERRSRV
, ERRbadpath
);
3969 reply_nterror(req
, status
);
3973 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3974 if (!NT_STATUS_IS_OK(status
)) {
3975 reply_nterror(req
, status
);
3978 status
= check_name(conn
, fname
);
3979 if (!NT_STATUS_IS_OK(status
)) {
3980 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3981 reply_nterror(req
, status
);
3985 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
3986 && is_ntfs_stream_name(fname
)) {
3988 SMB_STRUCT_STAT bsbuf
;
3990 status
= split_ntfs_stream_name(talloc_tos(), fname
,
3992 if (!NT_STATUS_IS_OK(status
)) {
3993 DEBUG(10, ("create_file_unixpath: "
3994 "split_ntfs_stream_name failed: %s\n",
3995 nt_errstr(status
)));
3996 reply_nterror(req
, status
);
4000 SMB_ASSERT(!is_ntfs_stream_name(base
)); /* paranoia.. */
4002 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4003 /* Always do lstat for UNIX calls. */
4004 if (SMB_VFS_LSTAT(conn
,base
,&bsbuf
)) {
4005 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base
,strerror(errno
)));
4006 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4010 if (SMB_VFS_STAT(conn
,base
,&bsbuf
) != 0) {
4011 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base
,strerror(errno
)));
4012 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
4017 fileid
= vfs_file_id_from_sbuf(conn
, &bsbuf
);
4018 get_file_infos(fileid
, &delete_pending
, NULL
);
4019 if (delete_pending
) {
4020 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4025 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4026 /* Always do lstat for UNIX calls. */
4027 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
4028 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
4029 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4033 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
4034 ms_dfs_link
= check_msdfs_link(conn
,fname
,&sbuf
);
4037 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
4038 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
4043 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4044 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4045 if (delete_pending
) {
4046 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
4051 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4052 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4056 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4057 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
4059 p
= strrchr_m(fname
,'/');
4066 mode
= dos_mode_msdfs(conn
,fname
,&sbuf
);
4068 mode
= dos_mode(conn
,fname
,&sbuf
);
4071 mode
= FILE_ATTRIBUTE_NORMAL
;
4073 nlink
= sbuf
.st_nlink
;
4075 if (nlink
&& (mode
&aDIR
)) {
4079 if ((nlink
> 0) && delete_pending
) {
4083 fullpathname
= fname
;
4085 file_size
= get_file_size(sbuf
);
4087 /* Pull out any data sent here before we realloc. */
4088 switch (info_level
) {
4089 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4091 /* Pull any EA list from the data portion. */
4094 if (total_data
< 4) {
4096 req
, NT_STATUS_INVALID_PARAMETER
);
4099 ea_size
= IVAL(pdata
,0);
4101 if (total_data
> 0 && ea_size
!= total_data
) {
4102 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4103 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
4105 req
, NT_STATUS_INVALID_PARAMETER
);
4109 if (!lp_ea_support(SNUM(conn
))) {
4110 reply_doserror(req
, ERRDOS
,
4111 ERReasnotsupported
);
4115 /* Pull out the list of names. */
4116 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
4119 req
, NT_STATUS_INVALID_PARAMETER
);
4125 case SMB_QUERY_POSIX_LOCK
:
4127 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4128 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4132 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4134 req
, NT_STATUS_INVALID_PARAMETER
);
4138 /* Copy the lock range data. */
4139 lock_data
= (char *)TALLOC_MEMDUP(
4140 ctx
, pdata
, total_data
);
4142 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4150 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4151 if (*pparams
== NULL
) {
4152 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4157 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4158 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4159 if (*ppdata
== NULL
) {
4160 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4165 dend
= dstart
+ data_size
- 1;
4167 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
4168 mtime_ts
= get_mtimespec(&sbuf
);
4169 atime_ts
= get_atimespec(&sbuf
);
4171 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
4174 /* Do we have this path open ? */
4176 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4177 fsp1
= file_find_di_first(fileid
);
4178 if (fsp1
&& fsp1
->initial_allocation_size
) {
4179 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
4183 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4184 mtime_ts
= write_time_ts
;
4187 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4188 dos_filetime_timespec(&create_time_ts
);
4189 dos_filetime_timespec(&mtime_ts
);
4190 dos_filetime_timespec(&atime_ts
);
4193 create_time
= convert_timespec_to_time_t(create_time_ts
);
4194 mtime
= convert_timespec_to_time_t(mtime_ts
);
4195 atime
= convert_timespec_to_time_t(atime_ts
);
4197 /* NT expects the name to be in an exact form of the *full*
4198 filename. See the trans2 torture test */
4199 if (ISDOT(base_name
)) {
4200 dos_fname
= talloc_strdup(ctx
, "\\");
4202 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4206 dos_fname
= talloc_asprintf(ctx
,
4210 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4213 string_replace(dos_fname
, '/', '\\');
4216 switch (info_level
) {
4217 case SMB_INFO_STANDARD
:
4218 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4220 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4221 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4222 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4223 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4224 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4225 SSVAL(pdata
,l1_attrFile
,mode
);
4228 case SMB_INFO_QUERY_EA_SIZE
:
4230 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4231 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4233 srv_put_dos_date2(pdata
,0,create_time
);
4234 srv_put_dos_date2(pdata
,4,atime
);
4235 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4236 SIVAL(pdata
,12,(uint32
)file_size
);
4237 SIVAL(pdata
,16,(uint32
)allocation_size
);
4238 SSVAL(pdata
,20,mode
);
4239 SIVAL(pdata
,22,ea_size
);
4243 case SMB_INFO_IS_NAME_VALID
:
4244 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4245 if (tran_call
== TRANSACT2_QFILEINFO
) {
4246 /* os/2 needs this ? really ?*/
4247 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
4254 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4256 size_t total_ea_len
= 0;
4257 struct ea_list
*ea_file_list
= NULL
;
4259 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4261 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4262 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4264 if (!ea_list
|| (total_ea_len
> data_size
)) {
4266 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4270 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4274 case SMB_INFO_QUERY_ALL_EAS
:
4276 /* We have data_size bytes to put EA's into. */
4277 size_t total_ea_len
= 0;
4279 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4281 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
4282 if (!ea_list
|| (total_ea_len
> data_size
)) {
4284 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4288 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
4292 case SMB_FILE_BASIC_INFORMATION
:
4293 case SMB_QUERY_FILE_BASIC_INFO
:
4295 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4296 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4297 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4303 put_long_date_timespec(pdata
,create_time_ts
);
4304 put_long_date_timespec(pdata
+8,atime_ts
);
4305 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4306 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4307 SIVAL(pdata
,32,mode
);
4309 DEBUG(5,("SMB_QFBI - "));
4310 DEBUG(5,("create: %s ", ctime(&create_time
)));
4311 DEBUG(5,("access: %s ", ctime(&atime
)));
4312 DEBUG(5,("write: %s ", ctime(&mtime
)));
4313 DEBUG(5,("change: %s ", ctime(&mtime
)));
4314 DEBUG(5,("mode: %x\n", mode
));
4317 case SMB_FILE_STANDARD_INFORMATION
:
4318 case SMB_QUERY_FILE_STANDARD_INFO
:
4320 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4322 SOFF_T(pdata
,0,allocation_size
);
4323 SOFF_T(pdata
,8,file_size
);
4324 SIVAL(pdata
,16,nlink
);
4325 SCVAL(pdata
,20,delete_pending
?1:0);
4326 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4327 SSVAL(pdata
,22,0); /* Padding. */
4330 case SMB_FILE_EA_INFORMATION
:
4331 case SMB_QUERY_FILE_EA_INFO
:
4333 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4334 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4336 SIVAL(pdata
,0,ea_size
);
4340 /* Get the 8.3 name - used if NT SMB was negotiated. */
4341 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4342 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4344 char mangled_name
[13];
4345 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4346 if (!name_to_8_3(base_name
,mangled_name
,
4347 True
,conn
->params
)) {
4350 NT_STATUS_NO_MEMORY
);
4352 len
= srvstr_push(dstart
, req
->flags2
,
4353 pdata
+4, mangled_name
,
4354 PTR_DIFF(dend
, pdata
+4),
4356 data_size
= 4 + len
;
4361 case SMB_QUERY_FILE_NAME_INFO
:
4363 this must be *exactly* right for ACLs on mapped drives to work
4365 len
= srvstr_push(dstart
, req
->flags2
,
4367 PTR_DIFF(dend
, pdata
+4),
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4370 data_size
= 4 + len
;
4374 case SMB_FILE_ALLOCATION_INFORMATION
:
4375 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4378 SOFF_T(pdata
,0,allocation_size
);
4381 case SMB_FILE_END_OF_FILE_INFORMATION
:
4382 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4383 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4385 SOFF_T(pdata
,0,file_size
);
4388 case SMB_QUERY_FILE_ALL_INFO
:
4389 case SMB_FILE_ALL_INFORMATION
:
4391 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4393 put_long_date_timespec(pdata
,create_time_ts
);
4394 put_long_date_timespec(pdata
+8,atime_ts
);
4395 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4396 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4397 SIVAL(pdata
,32,mode
);
4398 SIVAL(pdata
,36,0); /* padding. */
4400 SOFF_T(pdata
,0,allocation_size
);
4401 SOFF_T(pdata
,8,file_size
);
4402 SIVAL(pdata
,16,nlink
);
4403 SCVAL(pdata
,20,delete_pending
);
4404 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4407 SIVAL(pdata
,0,ea_size
);
4408 pdata
+= 4; /* EA info */
4409 len
= srvstr_push(dstart
, req
->flags2
,
4411 PTR_DIFF(dend
, pdata
+4),
4415 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4418 case SMB_FILE_INTERNAL_INFORMATION
:
4419 /* This should be an index number - looks like
4422 I think this causes us to fail the IFSKIT
4423 BasicFileInformationTest. -tpot */
4425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4426 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4427 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4431 case SMB_FILE_ACCESS_INFORMATION
:
4432 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4434 SIVAL(pdata
,0,fsp
->access_mask
);
4436 /* GENERIC_EXECUTE mapping from Windows */
4437 SIVAL(pdata
,0,0x12019F);
4442 case SMB_FILE_NAME_INFORMATION
:
4443 /* Pathname with leading '\'. */
4446 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4448 SIVAL(pdata
,0,byte_len
);
4449 data_size
= 4 + byte_len
;
4453 case SMB_FILE_DISPOSITION_INFORMATION
:
4454 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4456 SCVAL(pdata
,0,delete_pending
);
4459 case SMB_FILE_POSITION_INFORMATION
:
4460 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4462 SOFF_T(pdata
,0,pos
);
4465 case SMB_FILE_MODE_INFORMATION
:
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4467 SIVAL(pdata
,0,mode
);
4471 case SMB_FILE_ALIGNMENT_INFORMATION
:
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4473 SIVAL(pdata
,0,0); /* No alignment needed. */
4478 * NT4 server just returns "invalid query" to this - if we try
4479 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4482 /* The first statement above is false - verified using Thursby
4483 * client against NT4 -- gcolley.
4485 case SMB_QUERY_FILE_STREAM_INFO
:
4486 case SMB_FILE_STREAM_INFORMATION
: {
4487 unsigned int num_streams
;
4488 struct stream_struct
*streams
;
4491 DEBUG(10,("call_trans2qfilepathinfo: "
4492 "SMB_FILE_STREAM_INFORMATION\n"));
4494 status
= SMB_VFS_STREAMINFO(
4495 conn
, fsp
, fname
, talloc_tos(),
4496 &num_streams
, &streams
);
4498 if (!NT_STATUS_IS_OK(status
)) {
4499 DEBUG(10, ("could not get stream info: %s\n",
4500 nt_errstr(status
)));
4501 reply_nterror(req
, status
);
4505 status
= marshall_stream_info(num_streams
, streams
,
4506 pdata
, max_data_bytes
,
4509 if (!NT_STATUS_IS_OK(status
)) {
4510 DEBUG(10, ("marshall_stream_info failed: %s\n",
4511 nt_errstr(status
)));
4512 reply_nterror(req
, status
);
4516 TALLOC_FREE(streams
);
4520 case SMB_QUERY_COMPRESSION_INFO
:
4521 case SMB_FILE_COMPRESSION_INFORMATION
:
4522 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4523 SOFF_T(pdata
,0,file_size
);
4524 SIVAL(pdata
,8,0); /* ??? */
4525 SIVAL(pdata
,12,0); /* ??? */
4529 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4530 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4531 put_long_date_timespec(pdata
,create_time_ts
);
4532 put_long_date_timespec(pdata
+8,atime_ts
);
4533 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4534 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4535 SOFF_T(pdata
,32,allocation_size
);
4536 SOFF_T(pdata
,40,file_size
);
4537 SIVAL(pdata
,48,mode
);
4538 SIVAL(pdata
,52,0); /* ??? */
4542 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4543 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4544 SIVAL(pdata
,0,mode
);
4550 * CIFS UNIX Extensions.
4553 case SMB_QUERY_FILE_UNIX_BASIC
:
4555 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4556 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4560 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4562 for (i
=0; i
<100; i
++)
4563 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4569 case SMB_QUERY_FILE_UNIX_INFO2
:
4571 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4572 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4576 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4578 for (i
=0; i
<100; i
++)
4579 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4585 case SMB_QUERY_FILE_UNIX_LINK
:
4587 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4590 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4594 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4596 if(!S_ISLNK(sbuf
.st_mode
)) {
4597 reply_unixerror(req
, ERRSRV
,
4602 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4605 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4608 reply_unixerror(req
, ERRDOS
,
4613 len
= srvstr_push(dstart
, req
->flags2
,
4615 PTR_DIFF(dend
, pdata
),
4618 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4623 #if defined(HAVE_POSIX_ACLS)
4624 case SMB_QUERY_POSIX_ACL
:
4626 SMB_ACL_T file_acl
= NULL
;
4627 SMB_ACL_T def_acl
= NULL
;
4628 uint16 num_file_acls
= 0;
4629 uint16 num_def_acls
= 0;
4631 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4632 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4634 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4637 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4638 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4642 NT_STATUS_NOT_IMPLEMENTED
);
4646 if (S_ISDIR(sbuf
.st_mode
)) {
4647 if (fsp
&& fsp
->is_directory
) {
4648 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4650 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4652 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4655 num_file_acls
= count_acl_entries(conn
, file_acl
);
4656 num_def_acls
= count_acl_entries(conn
, def_acl
);
4658 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4659 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4661 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4662 SMB_POSIX_ACL_HEADER_SIZE
) ));
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4667 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4671 NT_STATUS_BUFFER_TOO_SMALL
);
4675 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4676 SSVAL(pdata
,2,num_file_acls
);
4677 SSVAL(pdata
,4,num_def_acls
);
4678 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4686 req
, NT_STATUS_INTERNAL_ERROR
);
4689 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4691 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4698 NT_STATUS_INTERNAL_ERROR
);
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4706 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4708 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4714 case SMB_QUERY_POSIX_LOCK
:
4716 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4718 SMB_BIG_UINT offset
;
4720 enum brl_type lock_type
;
4722 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4724 req
, NT_STATUS_INVALID_PARAMETER
);
4728 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4729 case POSIX_LOCK_TYPE_READ
:
4730 lock_type
= READ_LOCK
;
4732 case POSIX_LOCK_TYPE_WRITE
:
4733 lock_type
= WRITE_LOCK
;
4735 case POSIX_LOCK_TYPE_UNLOCK
:
4737 /* There's no point in asking for an unlock... */
4740 NT_STATUS_INVALID_PARAMETER
);
4744 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4745 #if defined(HAVE_LONGLONG)
4746 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4747 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4748 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4749 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4750 #else /* HAVE_LONGLONG */
4751 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4752 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4753 #endif /* HAVE_LONGLONG */
4755 status
= query_lock(fsp
,
4762 if (ERROR_WAS_LOCK_DENIED(status
)) {
4763 /* Here we need to report who has it locked... */
4764 data_size
= POSIX_LOCK_DATA_SIZE
;
4766 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4767 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4768 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4769 #if defined(HAVE_LONGLONG)
4770 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4771 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4772 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4773 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4774 #else /* HAVE_LONGLONG */
4775 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4776 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4777 #endif /* HAVE_LONGLONG */
4779 } else if (NT_STATUS_IS_OK(status
)) {
4780 /* For success we just return a copy of what we sent
4781 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4782 data_size
= POSIX_LOCK_DATA_SIZE
;
4783 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4784 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4786 reply_nterror(req
, status
);
4793 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4797 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4803 /****************************************************************************
4804 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4806 ****************************************************************************/
4808 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4809 connection_struct
*conn
,
4810 const char *oldname_in
,
4811 const char *newname_in
)
4813 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4814 char *last_component_oldname
= NULL
;
4815 char *last_component_newname
= NULL
;
4816 char *oldname
= NULL
;
4817 char *newname
= NULL
;
4818 NTSTATUS status
= NT_STATUS_OK
;
4823 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4824 &last_component_oldname
, &sbuf1
);
4825 if (!NT_STATUS_IS_OK(status
)) {
4829 status
= check_name(conn
, oldname
);
4830 if (!NT_STATUS_IS_OK(status
)) {
4834 /* source must already exist. */
4835 if (!VALID_STAT(sbuf1
)) {
4836 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4839 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4840 &last_component_newname
, &sbuf2
);
4841 if (!NT_STATUS_IS_OK(status
)) {
4845 status
= check_name(conn
, newname
);
4846 if (!NT_STATUS_IS_OK(status
)) {
4850 /* Disallow if newname already exists. */
4851 if (VALID_STAT(sbuf2
)) {
4852 return NT_STATUS_OBJECT_NAME_COLLISION
;
4855 /* No links from a directory. */
4856 if (S_ISDIR(sbuf1
.st_mode
)) {
4857 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4860 /* Ensure this is within the share. */
4861 status
= check_reduced_name(conn
, oldname
);
4862 if (!NT_STATUS_IS_OK(status
)) {
4866 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4868 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4869 status
= map_nt_error_from_unix(errno
);
4870 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4871 nt_errstr(status
), newname
, oldname
));
4877 /****************************************************************************
4878 Deal with setting the time from any of the setfilepathinfo functions.
4879 ****************************************************************************/
4881 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4884 const SMB_STRUCT_STAT
*psbuf
,
4885 struct timespec ts
[2],
4886 bool setting_write_time
)
4889 FILE_NOTIFY_CHANGE_LAST_ACCESS
4890 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4892 if (!VALID_STAT(*psbuf
)) {
4893 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4896 /* get some defaults (no modifications) if any info is zero or -1. */
4897 if (null_timespec(ts
[0])) {
4898 ts
[0] = get_atimespec(psbuf
);
4899 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4902 if (null_timespec(ts
[1])) {
4903 ts
[1] = get_mtimespec(psbuf
);
4904 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4907 if (!setting_write_time
) {
4908 /* ts[1] comes from change time, not write time. */
4909 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4912 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4913 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4916 * Try and set the times of this file if
4917 * they are different from the current values.
4921 struct timespec mts
= get_mtimespec(psbuf
);
4922 struct timespec ats
= get_atimespec(psbuf
);
4923 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4924 return NT_STATUS_OK
;
4928 if (setting_write_time
) {
4930 * This was a setfileinfo on an open file.
4931 * NT does this a lot. We also need to
4932 * set the time here, as it can be read by
4933 * FindFirst/FindNext and with the patch for bug #2045
4934 * in smbd/fileio.c it ensures that this timestamp is
4935 * kept sticky even after a write. We save the request
4936 * away and will set it on file close and after a write. JRA.
4939 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4940 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4943 if (fsp
->base_fsp
) {
4944 set_sticky_write_time_fsp(fsp
->base_fsp
, ts
[1]);
4946 set_sticky_write_time_fsp(fsp
, ts
[1]);
4949 set_sticky_write_time_path(conn
, fname
,
4950 vfs_file_id_from_sbuf(conn
, psbuf
),
4955 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4957 if (fsp
&& fsp
->base_fsp
) {
4958 fname
= fsp
->base_fsp
->fsp_name
;
4961 if(file_ntimes(conn
, fname
, ts
)!=0) {
4962 return map_nt_error_from_unix(errno
);
4964 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4966 return NT_STATUS_OK
;
4969 /****************************************************************************
4970 Deal with setting the dosmode from any of the setfilepathinfo functions.
4971 ****************************************************************************/
4973 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4976 SMB_STRUCT_STAT
*psbuf
,
4979 if (!VALID_STAT(*psbuf
)) {
4980 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4984 if (fsp
->base_fsp
) {
4985 fname
= fsp
->base_fsp
->fsp_name
;
4987 fname
= fsp
->fsp_name
;
4992 if (S_ISDIR(psbuf
->st_mode
)) {
4999 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5001 /* check the mode isn't different, before changing it */
5002 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
5004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5005 fname
, (unsigned int)dosmode
));
5007 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
5008 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5009 fname
, strerror(errno
)));
5010 return map_nt_error_from_unix(errno
);
5013 return NT_STATUS_OK
;
5016 /****************************************************************************
5017 Deal with setting the size from any of the setfilepathinfo functions.
5018 ****************************************************************************/
5020 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5021 struct smb_request
*req
,
5024 SMB_STRUCT_STAT
*psbuf
,
5027 NTSTATUS status
= NT_STATUS_OK
;
5028 files_struct
*new_fsp
= NULL
;
5030 if (!VALID_STAT(*psbuf
)) {
5031 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5034 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5036 if (size
== get_file_size(*psbuf
)) {
5037 return NT_STATUS_OK
;
5040 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5041 fname
, (double)size
));
5043 if (fsp
&& fsp
->fh
->fd
!= -1) {
5044 /* Handle based call. */
5045 if (vfs_set_filelen(fsp
, size
) == -1) {
5046 return map_nt_error_from_unix(errno
);
5048 trigger_write_time_update_immediate(fsp
);
5049 return NT_STATUS_OK
;
5052 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5053 FILE_WRITE_ATTRIBUTES
,
5054 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5057 FILE_ATTRIBUTE_NORMAL
,
5058 FORCE_OPLOCK_BREAK_TO_NONE
,
5061 if (!NT_STATUS_IS_OK(status
)) {
5062 /* NB. We check for open_was_deferred in the caller. */
5066 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5067 status
= map_nt_error_from_unix(errno
);
5068 close_file(new_fsp
,NORMAL_CLOSE
);
5072 trigger_write_time_update_immediate(new_fsp
);
5073 close_file(new_fsp
,NORMAL_CLOSE
);
5074 return NT_STATUS_OK
;
5077 /****************************************************************************
5078 Deal with SMB_INFO_SET_EA.
5079 ****************************************************************************/
5081 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5087 struct ea_list
*ea_list
= NULL
;
5088 TALLOC_CTX
*ctx
= NULL
;
5089 NTSTATUS status
= NT_STATUS_OK
;
5091 if (total_data
< 10) {
5093 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5094 length. They seem to have no effect. Bug #3212. JRA */
5096 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5097 /* We're done. We only get EA info in this call. */
5098 return NT_STATUS_OK
;
5101 return NT_STATUS_INVALID_PARAMETER
;
5104 if (IVAL(pdata
,0) > total_data
) {
5105 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5106 IVAL(pdata
,0), (unsigned int)total_data
));
5107 return NT_STATUS_INVALID_PARAMETER
;
5111 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5113 return NT_STATUS_INVALID_PARAMETER
;
5115 status
= set_ea(conn
, fsp
, fname
, ea_list
);
5120 /****************************************************************************
5121 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5122 ****************************************************************************/
5124 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5129 SMB_STRUCT_STAT
*psbuf
)
5131 NTSTATUS status
= NT_STATUS_OK
;
5132 bool delete_on_close
;
5135 if (total_data
< 1) {
5136 return NT_STATUS_INVALID_PARAMETER
;
5140 return NT_STATUS_INVALID_HANDLE
;
5143 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5144 dosmode
= dos_mode(conn
, fname
, psbuf
);
5146 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5147 "delete_on_close = %u\n",
5149 (unsigned int)dosmode
,
5150 (unsigned int)delete_on_close
));
5152 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5154 if (!NT_STATUS_IS_OK(status
)) {
5158 /* The set is across all open files on this dev/inode pair. */
5159 if (!set_delete_on_close(fsp
, delete_on_close
,
5160 &conn
->server_info
->utok
)) {
5161 return NT_STATUS_ACCESS_DENIED
;
5163 return NT_STATUS_OK
;
5166 /****************************************************************************
5167 Deal with SMB_FILE_POSITION_INFORMATION.
5168 ****************************************************************************/
5170 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5175 SMB_BIG_UINT position_information
;
5177 if (total_data
< 8) {
5178 return NT_STATUS_INVALID_PARAMETER
;
5182 /* Ignore on pathname based set. */
5183 return NT_STATUS_OK
;
5186 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5187 #ifdef LARGE_SMB_OFF_T
5188 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5189 #else /* LARGE_SMB_OFF_T */
5190 if (IVAL(pdata
,4) != 0) {
5191 /* more than 32 bits? */
5192 return NT_STATUS_INVALID_PARAMETER
;
5194 #endif /* LARGE_SMB_OFF_T */
5196 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5197 fsp
->fsp_name
, (double)position_information
));
5198 fsp
->fh
->position_information
= position_information
;
5199 return NT_STATUS_OK
;
5202 /****************************************************************************
5203 Deal with SMB_FILE_MODE_INFORMATION.
5204 ****************************************************************************/
5206 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5212 if (total_data
< 4) {
5213 return NT_STATUS_INVALID_PARAMETER
;
5215 mode
= IVAL(pdata
,0);
5216 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5217 return NT_STATUS_INVALID_PARAMETER
;
5219 return NT_STATUS_OK
;
5222 /****************************************************************************
5223 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5224 ****************************************************************************/
5226 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5227 struct smb_request
*req
,
5232 char *link_target
= NULL
;
5233 const char *newname
= fname
;
5234 NTSTATUS status
= NT_STATUS_OK
;
5235 TALLOC_CTX
*ctx
= talloc_tos();
5237 /* Set a symbolic link. */
5238 /* Don't allow this if follow links is false. */
5240 if (total_data
== 0) {
5241 return NT_STATUS_INVALID_PARAMETER
;
5244 if (!lp_symlinks(SNUM(conn
))) {
5245 return NT_STATUS_ACCESS_DENIED
;
5248 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5249 total_data
, STR_TERMINATE
);
5252 return NT_STATUS_INVALID_PARAMETER
;
5255 /* !widelinks forces the target path to be within the share. */
5256 /* This means we can interpret the target as a pathname. */
5257 if (!lp_widelinks(SNUM(conn
))) {
5258 char *rel_name
= NULL
;
5259 char *last_dirp
= NULL
;
5261 if (*link_target
== '/') {
5262 /* No absolute paths allowed. */
5263 return NT_STATUS_ACCESS_DENIED
;
5265 rel_name
= talloc_strdup(ctx
,newname
);
5267 return NT_STATUS_NO_MEMORY
;
5269 last_dirp
= strrchr_m(rel_name
, '/');
5271 last_dirp
[1] = '\0';
5273 rel_name
= talloc_strdup(ctx
,"./");
5275 return NT_STATUS_NO_MEMORY
;
5278 rel_name
= talloc_asprintf_append(rel_name
,
5282 return NT_STATUS_NO_MEMORY
;
5285 status
= check_name(conn
, rel_name
);
5286 if (!NT_STATUS_IS_OK(status
)) {
5291 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5292 newname
, link_target
));
5294 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5295 return map_nt_error_from_unix(errno
);
5298 return NT_STATUS_OK
;
5301 /****************************************************************************
5302 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5303 ****************************************************************************/
5305 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5306 struct smb_request
*req
,
5307 const char *pdata
, int total_data
,
5310 char *oldname
= NULL
;
5311 TALLOC_CTX
*ctx
= talloc_tos();
5312 NTSTATUS status
= NT_STATUS_OK
;
5314 /* Set a hard link. */
5315 if (total_data
== 0) {
5316 return NT_STATUS_INVALID_PARAMETER
;
5319 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5320 total_data
, STR_TERMINATE
, &status
);
5321 if (!NT_STATUS_IS_OK(status
)) {
5325 status
= resolve_dfspath(ctx
, conn
,
5326 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5329 if (!NT_STATUS_IS_OK(status
)) {
5333 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5336 return hardlink_internals(ctx
, conn
, oldname
, fname
);
5339 /****************************************************************************
5340 Deal with SMB_FILE_RENAME_INFORMATION.
5341 ****************************************************************************/
5343 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5344 struct smb_request
*req
,
5353 char *newname
= NULL
;
5354 char *base_name
= NULL
;
5355 bool dest_has_wcard
= False
;
5356 SMB_STRUCT_STAT sbuf
;
5357 char *newname_last_component
= NULL
;
5358 NTSTATUS status
= NT_STATUS_OK
;
5360 TALLOC_CTX
*ctx
= talloc_tos();
5362 if (total_data
< 13) {
5363 return NT_STATUS_INVALID_PARAMETER
;
5368 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5369 root_fid
= IVAL(pdata
,4);
5370 len
= IVAL(pdata
,8);
5372 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5373 return NT_STATUS_INVALID_PARAMETER
;
5376 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5379 if (!NT_STATUS_IS_OK(status
)) {
5383 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5386 status
= resolve_dfspath_wcard(ctx
, conn
,
5387 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5391 if (!NT_STATUS_IS_OK(status
)) {
5395 /* Check the new name has no '/' characters. */
5396 if (strchr_m(newname
, '/')) {
5397 return NT_STATUS_NOT_SUPPORTED
;
5400 if (fsp
&& fsp
->base_fsp
) {
5401 /* newname must be a stream name. */
5402 if (newname
[0] != ':') {
5403 return NT_STATUS_NOT_SUPPORTED
;
5405 base_name
= talloc_asprintf(ctx
, "%s%s",
5406 fsp
->base_fsp
->fsp_name
,
5409 return NT_STATUS_NO_MEMORY
;
5412 /* newname must *not* be a stream name. */
5413 if (is_ntfs_stream_name(newname
)) {
5414 return NT_STATUS_NOT_SUPPORTED
;
5417 /* Create the base directory. */
5418 base_name
= talloc_strdup(ctx
, fname
);
5420 return NT_STATUS_NO_MEMORY
;
5422 p
= strrchr_m(base_name
, '/');
5426 base_name
= talloc_strdup(ctx
, "./");
5428 return NT_STATUS_NO_MEMORY
;
5431 /* Append the new name. */
5432 base_name
= talloc_asprintf_append(base_name
,
5436 return NT_STATUS_NO_MEMORY
;
5439 status
= unix_convert(ctx
, conn
, newname
, False
,
5441 &newname_last_component
,
5444 /* If an error we expect this to be
5445 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5447 if (!NT_STATUS_IS_OK(status
)
5448 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5455 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5456 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5457 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5458 newname_last_component
, 0,
5461 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5462 fname
, base_name
));
5463 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5464 overwrite
, False
, dest_has_wcard
,
5465 FILE_WRITE_ATTRIBUTES
);
5471 /****************************************************************************
5472 Deal with SMB_SET_POSIX_ACL.
5473 ****************************************************************************/
5475 #if defined(HAVE_POSIX_ACLS)
5476 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5481 SMB_STRUCT_STAT
*psbuf
)
5483 uint16 posix_acl_version
;
5484 uint16 num_file_acls
;
5485 uint16 num_def_acls
;
5486 bool valid_file_acls
= True
;
5487 bool valid_def_acls
= True
;
5489 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5490 return NT_STATUS_INVALID_PARAMETER
;
5492 posix_acl_version
= SVAL(pdata
,0);
5493 num_file_acls
= SVAL(pdata
,2);
5494 num_def_acls
= SVAL(pdata
,4);
5496 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5497 valid_file_acls
= False
;
5501 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5502 valid_def_acls
= False
;
5506 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5507 return NT_STATUS_INVALID_PARAMETER
;
5510 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5511 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5512 return NT_STATUS_INVALID_PARAMETER
;
5515 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5516 fname
? fname
: fsp
->fsp_name
,
5517 (unsigned int)num_file_acls
,
5518 (unsigned int)num_def_acls
));
5520 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5521 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5522 return map_nt_error_from_unix(errno
);
5525 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5526 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5527 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5528 return map_nt_error_from_unix(errno
);
5530 return NT_STATUS_OK
;
5534 /****************************************************************************
5535 Deal with SMB_SET_POSIX_LOCK.
5536 ****************************************************************************/
5538 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5539 const struct smb_request
*req
,
5545 SMB_BIG_UINT offset
;
5547 bool blocking_lock
= False
;
5548 enum brl_type lock_type
;
5550 NTSTATUS status
= NT_STATUS_OK
;
5552 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5553 return NT_STATUS_INVALID_HANDLE
;
5556 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5557 return NT_STATUS_INVALID_PARAMETER
;
5560 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5561 case POSIX_LOCK_TYPE_READ
:
5562 lock_type
= READ_LOCK
;
5564 case POSIX_LOCK_TYPE_WRITE
:
5565 /* Return the right POSIX-mappable error code for files opened read-only. */
5566 if (!fsp
->can_write
) {
5567 return NT_STATUS_INVALID_HANDLE
;
5569 lock_type
= WRITE_LOCK
;
5571 case POSIX_LOCK_TYPE_UNLOCK
:
5572 lock_type
= UNLOCK_LOCK
;
5575 return NT_STATUS_INVALID_PARAMETER
;
5578 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5579 blocking_lock
= False
;
5580 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5581 blocking_lock
= True
;
5583 return NT_STATUS_INVALID_PARAMETER
;
5586 if (!lp_blocking_locks(SNUM(conn
))) {
5587 blocking_lock
= False
;
5590 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5591 #if defined(HAVE_LONGLONG)
5592 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5593 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5594 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5595 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5596 #else /* HAVE_LONGLONG */
5597 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5598 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5599 #endif /* HAVE_LONGLONG */
5601 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5602 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5604 (unsigned int)lock_type
,
5605 (unsigned int)lock_pid
,
5609 if (lock_type
== UNLOCK_LOCK
) {
5610 status
= do_unlock(smbd_messaging_context(),
5617 uint32 block_smbpid
;
5619 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5630 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5632 * A blocking lock was requested. Package up
5633 * this smb into a queued request and push it
5634 * onto the blocking lock queue.
5636 if(push_blocking_lock_request(br_lck
,
5639 -1, /* infinite timeout. */
5647 TALLOC_FREE(br_lck
);
5651 TALLOC_FREE(br_lck
);
5657 /****************************************************************************
5658 Deal with SMB_INFO_STANDARD.
5659 ****************************************************************************/
5661 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5666 const SMB_STRUCT_STAT
*psbuf
)
5668 struct timespec ts
[2];
5670 if (total_data
< 12) {
5671 return NT_STATUS_INVALID_PARAMETER
;
5675 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5677 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5679 DEBUG(10,("smb_set_info_standard: file %s\n",
5680 fname
? fname
: fsp
->fsp_name
));
5682 return smb_set_file_time(conn
,
5690 /****************************************************************************
5691 Deal with SMB_SET_FILE_BASIC_INFO.
5692 ****************************************************************************/
5694 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5699 SMB_STRUCT_STAT
*psbuf
)
5701 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5702 struct timespec write_time
;
5703 struct timespec changed_time
;
5705 struct timespec ts
[2];
5706 NTSTATUS status
= NT_STATUS_OK
;
5707 bool setting_write_time
= true;
5709 if (total_data
< 36) {
5710 return NT_STATUS_INVALID_PARAMETER
;
5713 /* Set the attributes */
5714 dosmode
= IVAL(pdata
,32);
5715 status
= smb_set_file_dosmode(conn
,
5721 if (!NT_STATUS_IS_OK(status
)) {
5725 /* Ignore create time at offset pdata. */
5728 ts
[0] = interpret_long_date(pdata
+8);
5730 write_time
= interpret_long_date(pdata
+16);
5731 changed_time
= interpret_long_date(pdata
+24);
5734 ts
[1] = timespec_min(&write_time
, &changed_time
);
5736 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5740 /* Prefer a defined time to an undefined one. */
5741 if (null_timespec(ts
[1])) {
5742 if (null_timespec(write_time
)) {
5743 ts
[1] = changed_time
;
5744 setting_write_time
= false;
5750 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5751 fname
? fname
: fsp
->fsp_name
));
5753 return smb_set_file_time(conn
,
5758 setting_write_time
);
5761 /****************************************************************************
5762 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5763 ****************************************************************************/
5765 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5766 struct smb_request
*req
,
5771 SMB_STRUCT_STAT
*psbuf
)
5773 SMB_BIG_UINT allocation_size
= 0;
5774 NTSTATUS status
= NT_STATUS_OK
;
5775 files_struct
*new_fsp
= NULL
;
5777 if (!VALID_STAT(*psbuf
)) {
5778 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5781 if (total_data
< 8) {
5782 return NT_STATUS_INVALID_PARAMETER
;
5785 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5786 #ifdef LARGE_SMB_OFF_T
5787 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5788 #else /* LARGE_SMB_OFF_T */
5789 if (IVAL(pdata
,4) != 0) {
5790 /* more than 32 bits? */
5791 return NT_STATUS_INVALID_PARAMETER
;
5793 #endif /* LARGE_SMB_OFF_T */
5795 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5796 fname
, (double)allocation_size
));
5798 if (allocation_size
) {
5799 allocation_size
= smb_roundup(conn
, allocation_size
);
5802 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5803 fname
, (double)allocation_size
));
5805 if (fsp
&& fsp
->fh
->fd
!= -1) {
5806 /* Open file handle. */
5807 /* Only change if needed. */
5808 if (allocation_size
!= get_file_size(*psbuf
)) {
5809 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5810 return map_nt_error_from_unix(errno
);
5813 /* But always update the time. */
5815 * This is equivalent to a write. Ensure it's seen immediately
5816 * if there are no pending writes.
5818 trigger_write_time_update_immediate(fsp
);
5819 return NT_STATUS_OK
;
5822 /* Pathname or stat or directory file. */
5824 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5826 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5829 FILE_ATTRIBUTE_NORMAL
,
5830 FORCE_OPLOCK_BREAK_TO_NONE
,
5833 if (!NT_STATUS_IS_OK(status
)) {
5834 /* NB. We check for open_was_deferred in the caller. */
5838 /* Only change if needed. */
5839 if (allocation_size
!= get_file_size(*psbuf
)) {
5840 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5841 status
= map_nt_error_from_unix(errno
);
5842 close_file(new_fsp
,NORMAL_CLOSE
);
5847 /* Changing the allocation size should set the last mod time. */
5849 * This is equivalent to a write. Ensure it's seen immediately
5850 * if there are no pending writes.
5852 trigger_write_time_update_immediate(new_fsp
);
5854 close_file(new_fsp
,NORMAL_CLOSE
);
5855 return NT_STATUS_OK
;
5858 /****************************************************************************
5859 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5860 ****************************************************************************/
5862 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5863 struct smb_request
*req
,
5868 SMB_STRUCT_STAT
*psbuf
)
5872 if (total_data
< 8) {
5873 return NT_STATUS_INVALID_PARAMETER
;
5876 size
= IVAL(pdata
,0);
5877 #ifdef LARGE_SMB_OFF_T
5878 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5879 #else /* LARGE_SMB_OFF_T */
5880 if (IVAL(pdata
,4) != 0) {
5881 /* more than 32 bits? */
5882 return NT_STATUS_INVALID_PARAMETER
;
5884 #endif /* LARGE_SMB_OFF_T */
5885 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5886 "file %s to %.0f\n", fname
, (double)size
));
5888 return smb_set_file_size(conn
, req
,
5895 /****************************************************************************
5896 Allow a UNIX info mknod.
5897 ****************************************************************************/
5899 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5903 SMB_STRUCT_STAT
*psbuf
)
5905 uint32 file_type
= IVAL(pdata
,56);
5906 #if defined(HAVE_MAKEDEV)
5907 uint32 dev_major
= IVAL(pdata
,60);
5908 uint32 dev_minor
= IVAL(pdata
,68);
5910 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5911 uint32 raw_unixmode
= IVAL(pdata
,84);
5915 if (total_data
< 100) {
5916 return NT_STATUS_INVALID_PARAMETER
;
5919 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5920 if (!NT_STATUS_IS_OK(status
)) {
5924 #if defined(HAVE_MAKEDEV)
5925 dev
= makedev(dev_major
, dev_minor
);
5928 switch (file_type
) {
5929 #if defined(S_IFIFO)
5930 case UNIX_TYPE_FIFO
:
5931 unixmode
|= S_IFIFO
;
5934 #if defined(S_IFSOCK)
5935 case UNIX_TYPE_SOCKET
:
5936 unixmode
|= S_IFSOCK
;
5939 #if defined(S_IFCHR)
5940 case UNIX_TYPE_CHARDEV
:
5941 unixmode
|= S_IFCHR
;
5944 #if defined(S_IFBLK)
5945 case UNIX_TYPE_BLKDEV
:
5946 unixmode
|= S_IFBLK
;
5950 return NT_STATUS_INVALID_PARAMETER
;
5953 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5954 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5956 /* Ok - do the mknod. */
5957 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5958 return map_nt_error_from_unix(errno
);
5961 /* If any of the other "set" calls fail we
5962 * don't want to end up with a half-constructed mknod.
5965 if (lp_inherit_perms(SNUM(conn
))) {
5966 inherit_access_posix_acl(
5967 conn
, parent_dirname(fname
),
5971 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5972 status
= map_nt_error_from_unix(errno
);
5973 SMB_VFS_UNLINK(conn
,fname
);
5976 return NT_STATUS_OK
;
5979 /****************************************************************************
5980 Deal with SMB_SET_FILE_UNIX_BASIC.
5981 ****************************************************************************/
5983 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5984 struct smb_request
*req
,
5989 SMB_STRUCT_STAT
*psbuf
)
5991 struct timespec ts
[2];
5992 uint32 raw_unixmode
;
5995 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5996 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5997 NTSTATUS status
= NT_STATUS_OK
;
5998 bool delete_on_fail
= False
;
5999 enum perm_type ptype
;
6001 if (total_data
< 100) {
6002 return NT_STATUS_INVALID_PARAMETER
;
6005 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6006 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6007 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6008 #ifdef LARGE_SMB_OFF_T
6009 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6010 #else /* LARGE_SMB_OFF_T */
6011 if (IVAL(pdata
,4) != 0) {
6012 /* more than 32 bits? */
6013 return NT_STATUS_INVALID_PARAMETER
;
6015 #endif /* LARGE_SMB_OFF_T */
6018 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
6019 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
6020 set_owner
= (uid_t
)IVAL(pdata
,40);
6021 set_grp
= (gid_t
)IVAL(pdata
,48);
6022 raw_unixmode
= IVAL(pdata
,84);
6024 if (VALID_STAT(*psbuf
)) {
6025 if (S_ISDIR(psbuf
->st_mode
)) {
6026 ptype
= PERM_EXISTING_DIR
;
6028 ptype
= PERM_EXISTING_FILE
;
6031 ptype
= PERM_NEW_FILE
;
6034 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
6035 if (!NT_STATUS_IS_OK(status
)) {
6039 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6040 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6041 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
6043 if (!VALID_STAT(*psbuf
)) {
6045 * The only valid use of this is to create character and block
6046 * devices, and named pipes. This is deprecated (IMHO) and
6047 * a new info level should be used for mknod. JRA.
6050 status
= smb_unix_mknod(conn
,
6055 if (!NT_STATUS_IS_OK(status
)) {
6059 /* Ensure we don't try and change anything else. */
6060 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6061 size
= get_file_size(*psbuf
);
6062 ts
[0] = get_atimespec(psbuf
);
6063 ts
[1] = get_mtimespec(psbuf
);
6065 * We continue here as we might want to change the
6068 delete_on_fail
= True
;
6072 /* Horrible backwards compatibility hack as an old server bug
6073 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6077 size
= get_file_size(*psbuf
);
6082 * Deal with the UNIX specific mode set.
6085 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6086 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6087 (unsigned int)unixmode
, fname
));
6088 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
6089 return map_nt_error_from_unix(errno
);
6094 * Deal with the UNIX specific uid set.
6097 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
6100 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6101 (unsigned int)set_owner
, fname
));
6103 if (S_ISLNK(psbuf
->st_mode
)) {
6104 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6106 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
6110 status
= map_nt_error_from_unix(errno
);
6111 if (delete_on_fail
) {
6112 SMB_VFS_UNLINK(conn
,fname
);
6119 * Deal with the UNIX specific gid set.
6122 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
6123 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6124 (unsigned int)set_owner
, fname
));
6125 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
6126 status
= map_nt_error_from_unix(errno
);
6127 if (delete_on_fail
) {
6128 SMB_VFS_UNLINK(conn
,fname
);
6134 /* Deal with any size changes. */
6136 status
= smb_set_file_size(conn
, req
,
6141 if (!NT_STATUS_IS_OK(status
)) {
6145 /* Deal with any time changes. */
6147 return smb_set_file_time(conn
,
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_UNIX_INFO2.
6157 ****************************************************************************/
6159 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6160 struct smb_request
*req
,
6165 SMB_STRUCT_STAT
*psbuf
)
6171 if (total_data
< 116) {
6172 return NT_STATUS_INVALID_PARAMETER
;
6175 /* Start by setting all the fields that are common between UNIX_BASIC
6178 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6180 if (!NT_STATUS_IS_OK(status
)) {
6184 smb_fflags
= IVAL(pdata
, 108);
6185 smb_fmask
= IVAL(pdata
, 112);
6187 /* NB: We should only attempt to alter the file flags if the client
6188 * sends a non-zero mask.
6190 if (smb_fmask
!= 0) {
6191 int stat_fflags
= 0;
6193 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
6195 /* Client asked to alter a flag we don't understand. */
6196 return NT_STATUS_INVALID_PARAMETER
;
6199 if (fsp
&& fsp
->fh
->fd
!= -1) {
6200 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6201 return NT_STATUS_NOT_SUPPORTED
;
6203 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
6204 return map_nt_error_from_unix(errno
);
6209 /* XXX: need to add support for changing the create_time here. You
6210 * can do this for paths on Darwin with setattrlist(2). The right way
6211 * to hook this up is probably by extending the VFS utimes interface.
6214 return NT_STATUS_OK
;
6217 /****************************************************************************
6218 Create a directory with POSIX semantics.
6219 ****************************************************************************/
6221 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6222 struct smb_request
*req
,
6226 SMB_STRUCT_STAT
*psbuf
,
6227 int *pdata_return_size
)
6229 NTSTATUS status
= NT_STATUS_OK
;
6230 uint32 raw_unixmode
= 0;
6231 uint32 mod_unixmode
= 0;
6232 mode_t unixmode
= (mode_t
)0;
6233 files_struct
*fsp
= NULL
;
6234 uint16 info_level_return
= 0;
6236 char *pdata
= *ppdata
;
6238 if (total_data
< 18) {
6239 return NT_STATUS_INVALID_PARAMETER
;
6242 raw_unixmode
= IVAL(pdata
,8);
6243 /* Next 4 bytes are not yet defined. */
6245 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
6246 if (!NT_STATUS_IS_OK(status
)) {
6250 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6252 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6253 fname
, (unsigned int)unixmode
));
6255 status
= open_directory(conn
, req
,
6258 FILE_READ_ATTRIBUTES
, /* Just a stat open */
6259 FILE_SHARE_NONE
, /* Ignored for stat opens */
6266 if (NT_STATUS_IS_OK(status
)) {
6267 close_file(fsp
, NORMAL_CLOSE
);
6270 info_level_return
= SVAL(pdata
,16);
6272 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6273 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6274 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6275 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6277 *pdata_return_size
= 12;
6280 /* Realloc the data size */
6281 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6282 if (*ppdata
== NULL
) {
6283 *pdata_return_size
= 0;
6284 return NT_STATUS_NO_MEMORY
;
6288 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6289 SSVAL(pdata
,2,0); /* No fnum. */
6290 SIVAL(pdata
,4,info
); /* Was directory created. */
6292 switch (info_level_return
) {
6293 case SMB_QUERY_FILE_UNIX_BASIC
:
6294 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6295 SSVAL(pdata
,10,0); /* Padding. */
6296 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6298 case SMB_QUERY_FILE_UNIX_INFO2
:
6299 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6300 SSVAL(pdata
,10,0); /* Padding. */
6301 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6304 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6305 SSVAL(pdata
,10,0); /* Padding. */
6312 /****************************************************************************
6313 Open/Create a file with POSIX semantics.
6314 ****************************************************************************/
6316 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6317 struct smb_request
*req
,
6321 SMB_STRUCT_STAT
*psbuf
,
6322 int *pdata_return_size
)
6324 bool extended_oplock_granted
= False
;
6325 char *pdata
= *ppdata
;
6327 uint32 wire_open_mode
= 0;
6328 uint32 raw_unixmode
= 0;
6329 uint32 mod_unixmode
= 0;
6330 uint32 create_disp
= 0;
6331 uint32 access_mask
= 0;
6332 uint32 create_options
= 0;
6333 NTSTATUS status
= NT_STATUS_OK
;
6334 mode_t unixmode
= (mode_t
)0;
6335 files_struct
*fsp
= NULL
;
6336 int oplock_request
= 0;
6338 uint16 info_level_return
= 0;
6340 if (total_data
< 18) {
6341 return NT_STATUS_INVALID_PARAMETER
;
6344 flags
= IVAL(pdata
,0);
6345 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6346 if (oplock_request
) {
6347 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6350 wire_open_mode
= IVAL(pdata
,4);
6352 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6353 return smb_posix_mkdir(conn
, req
,
6361 switch (wire_open_mode
& SMB_ACCMODE
) {
6363 access_mask
= FILE_READ_DATA
;
6366 access_mask
= FILE_WRITE_DATA
;
6369 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6372 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6373 (unsigned int)wire_open_mode
));
6374 return NT_STATUS_INVALID_PARAMETER
;
6377 wire_open_mode
&= ~SMB_ACCMODE
;
6379 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6380 create_disp
= FILE_CREATE
;
6381 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6382 create_disp
= FILE_OVERWRITE_IF
;
6383 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6384 create_disp
= FILE_OPEN_IF
;
6385 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
6386 create_disp
= FILE_OPEN
;
6388 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6389 (unsigned int)wire_open_mode
));
6390 return NT_STATUS_INVALID_PARAMETER
;
6393 raw_unixmode
= IVAL(pdata
,8);
6394 /* Next 4 bytes are not yet defined. */
6396 status
= unix_perms_from_wire(conn
,
6399 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6402 if (!NT_STATUS_IS_OK(status
)) {
6406 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6408 if (wire_open_mode
& SMB_O_SYNC
) {
6409 create_options
|= FILE_WRITE_THROUGH
;
6411 if (wire_open_mode
& SMB_O_APPEND
) {
6412 access_mask
|= FILE_APPEND_DATA
;
6414 if (wire_open_mode
& SMB_O_DIRECT
) {
6415 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6418 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6420 (unsigned int)wire_open_mode
,
6421 (unsigned int)unixmode
));
6423 status
= open_file_ntcreate(conn
, req
,
6427 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6429 0, /* no create options yet. */
6435 if (!NT_STATUS_IS_OK(status
)) {
6439 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6440 extended_oplock_granted
= True
;
6443 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6444 extended_oplock_granted
= True
;
6447 info_level_return
= SVAL(pdata
,16);
6449 /* Allocate the correct return size. */
6451 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6452 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6453 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6454 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6456 *pdata_return_size
= 12;
6459 /* Realloc the data size */
6460 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6461 if (*ppdata
== NULL
) {
6462 close_file(fsp
,ERROR_CLOSE
);
6463 *pdata_return_size
= 0;
6464 return NT_STATUS_NO_MEMORY
;
6468 if (extended_oplock_granted
) {
6469 if (flags
& REQUEST_BATCH_OPLOCK
) {
6470 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6472 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6474 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6475 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6477 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6480 SSVAL(pdata
,2,fsp
->fnum
);
6481 SIVAL(pdata
,4,info
); /* Was file created etc. */
6483 switch (info_level_return
) {
6484 case SMB_QUERY_FILE_UNIX_BASIC
:
6485 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6486 SSVAL(pdata
,10,0); /* padding. */
6487 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6489 case SMB_QUERY_FILE_UNIX_INFO2
:
6490 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6491 SSVAL(pdata
,10,0); /* padding. */
6492 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6495 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6496 SSVAL(pdata
,10,0); /* padding. */
6499 return NT_STATUS_OK
;
6502 /****************************************************************************
6503 Delete a file with POSIX semantics.
6504 ****************************************************************************/
6506 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6507 struct smb_request
*req
,
6511 SMB_STRUCT_STAT
*psbuf
)
6513 NTSTATUS status
= NT_STATUS_OK
;
6514 files_struct
*fsp
= NULL
;
6519 struct share_mode_lock
*lck
= NULL
;
6521 if (total_data
< 2) {
6522 return NT_STATUS_INVALID_PARAMETER
;
6525 flags
= SVAL(pdata
,0);
6527 if (!VALID_STAT(*psbuf
)) {
6528 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6531 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6532 !VALID_STAT_OF_DIR(*psbuf
)) {
6533 return NT_STATUS_NOT_A_DIRECTORY
;
6536 DEBUG(10,("smb_posix_unlink: %s %s\n",
6537 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6540 if (VALID_STAT_OF_DIR(*psbuf
)) {
6541 status
= open_directory(conn
, req
,
6545 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6548 FILE_FLAG_POSIX_SEMANTICS
|0777,
6553 status
= open_file_ntcreate(conn
, req
,
6557 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6560 FILE_FLAG_POSIX_SEMANTICS
|0777,
6561 0, /* No oplock, but break existing ones. */
6566 if (!NT_STATUS_IS_OK(status
)) {
6571 * Don't lie to client. If we can't really delete due to
6572 * non-POSIX opens return SHARING_VIOLATION.
6575 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6578 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6579 "lock for file %s\n", fsp
->fsp_name
));
6580 close_file(fsp
, NORMAL_CLOSE
);
6581 return NT_STATUS_INVALID_PARAMETER
;
6585 * See if others still have the file open. If this is the case, then
6586 * don't delete. If all opens are POSIX delete we can set the delete
6587 * on close disposition.
6589 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6590 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6591 if (is_valid_share_mode_entry(e
)) {
6592 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6595 /* Fail with sharing violation. */
6596 close_file(fsp
, NORMAL_CLOSE
);
6598 return NT_STATUS_SHARING_VIOLATION
;
6603 * Set the delete on close.
6605 status
= smb_set_file_disposition_info(conn
,
6612 if (!NT_STATUS_IS_OK(status
)) {
6613 close_file(fsp
, NORMAL_CLOSE
);
6618 return close_file(fsp
, NORMAL_CLOSE
);
6621 /****************************************************************************
6622 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6623 ****************************************************************************/
6625 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6626 struct smb_request
*req
,
6627 unsigned int tran_call
,
6628 char **pparams
, int total_params
,
6629 char **ppdata
, int total_data
,
6630 unsigned int max_data_bytes
)
6632 char *params
= *pparams
;
6633 char *pdata
= *ppdata
;
6635 SMB_STRUCT_STAT sbuf
;
6637 files_struct
*fsp
= NULL
;
6638 NTSTATUS status
= NT_STATUS_OK
;
6639 int data_return_size
= 0;
6640 TALLOC_CTX
*ctx
= talloc_tos();
6643 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6649 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6650 if (total_params
< 4) {
6651 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6655 fsp
= file_fsp(SVAL(params
,0));
6656 /* Basic check for non-null fsp. */
6657 if (!check_fsp_open(conn
, req
, fsp
)) {
6660 info_level
= SVAL(params
,2);
6662 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6664 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6668 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6670 * This is actually a SETFILEINFO on a directory
6671 * handle (returned from an NT SMB). NT5.0 seems
6672 * to do this call. JRA.
6674 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6675 /* Always do lstat for UNIX calls. */
6676 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6677 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6678 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6682 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6683 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6684 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6688 } else if (fsp
->print_file
) {
6690 * Doing a DELETE_ON_CLOSE should cancel a print job.
6692 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6693 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6695 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6698 send_trans2_replies(conn
, req
, params
, 2,
6703 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6708 * Original code - this is an open file.
6710 if (!check_fsp(conn
, req
, fsp
)) {
6714 if (SMB_VFS_FSTAT(fsp
, &sbuf
) != 0) {
6715 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6716 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6722 if (total_params
< 7) {
6723 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6727 info_level
= SVAL(params
,0);
6728 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6729 total_params
- 6, STR_TERMINATE
,
6731 if (!NT_STATUS_IS_OK(status
)) {
6732 reply_nterror(req
, status
);
6736 status
= resolve_dfspath(ctx
, conn
,
6737 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6740 if (!NT_STATUS_IS_OK(status
)) {
6741 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6742 reply_botherror(req
,
6743 NT_STATUS_PATH_NOT_COVERED
,
6744 ERRSRV
, ERRbadpath
);
6747 reply_nterror(req
, status
);
6751 status
= unix_convert(ctx
, conn
, fname
, False
,
6752 &fname
, NULL
, &sbuf
);
6753 if (!NT_STATUS_IS_OK(status
)) {
6754 reply_nterror(req
, status
);
6758 status
= check_name(conn
, fname
);
6759 if (!NT_STATUS_IS_OK(status
)) {
6760 reply_nterror(req
, status
);
6764 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6766 * For CIFS UNIX extensions the target name may not exist.
6769 /* Always do lstat for UNIX calls. */
6770 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6772 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6773 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6774 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6779 if (!CAN_WRITE(conn
)) {
6780 reply_doserror(req
, ERRSRV
, ERRaccess
);
6784 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6785 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6789 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6790 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6792 /* Realloc the parameter size */
6793 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6794 if (*pparams
== NULL
) {
6795 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6802 switch (info_level
) {
6804 case SMB_INFO_STANDARD
:
6806 status
= smb_set_info_standard(conn
,
6815 case SMB_INFO_SET_EA
:
6817 status
= smb_info_set_ea(conn
,
6825 case SMB_SET_FILE_BASIC_INFO
:
6826 case SMB_FILE_BASIC_INFORMATION
:
6828 status
= smb_set_file_basic_info(conn
,
6837 case SMB_FILE_ALLOCATION_INFORMATION
:
6838 case SMB_SET_FILE_ALLOCATION_INFO
:
6840 status
= smb_set_file_allocation_info(conn
, req
,
6849 case SMB_FILE_END_OF_FILE_INFORMATION
:
6850 case SMB_SET_FILE_END_OF_FILE_INFO
:
6852 status
= smb_set_file_end_of_file_info(conn
, req
,
6861 case SMB_FILE_DISPOSITION_INFORMATION
:
6862 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6865 /* JRA - We used to just ignore this on a path ?
6866 * Shouldn't this be invalid level on a pathname
6869 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6870 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6873 status
= smb_set_file_disposition_info(conn
,
6882 case SMB_FILE_POSITION_INFORMATION
:
6884 status
= smb_file_position_information(conn
,
6891 /* From tridge Samba4 :
6892 * MODE_INFORMATION in setfileinfo (I have no
6893 * idea what "mode information" on a file is - it takes a value of 0,
6894 * 2, 4 or 6. What could it be?).
6897 case SMB_FILE_MODE_INFORMATION
:
6899 status
= smb_file_mode_information(conn
,
6906 * CIFS UNIX extensions.
6909 case SMB_SET_FILE_UNIX_BASIC
:
6911 status
= smb_set_file_unix_basic(conn
, req
,
6920 case SMB_SET_FILE_UNIX_INFO2
:
6922 status
= smb_set_file_unix_info2(conn
, req
,
6931 case SMB_SET_FILE_UNIX_LINK
:
6933 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6934 /* We must have a pathname for this. */
6935 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6938 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6943 case SMB_SET_FILE_UNIX_HLINK
:
6945 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6946 /* We must have a pathname for this. */
6947 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6950 status
= smb_set_file_unix_hlink(conn
, req
,
6956 case SMB_FILE_RENAME_INFORMATION
:
6958 status
= smb_file_rename_information(conn
, req
,
6964 #if defined(HAVE_POSIX_ACLS)
6965 case SMB_SET_POSIX_ACL
:
6967 status
= smb_set_posix_acl(conn
,
6977 case SMB_SET_POSIX_LOCK
:
6979 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6980 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6983 status
= smb_set_posix_lock(conn
, req
,
6984 pdata
, total_data
, fsp
);
6988 case SMB_POSIX_PATH_OPEN
:
6990 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6991 /* We must have a pathname for this. */
6992 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6996 status
= smb_posix_open(conn
, req
,
7005 case SMB_POSIX_PATH_UNLINK
:
7007 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
7008 /* We must have a pathname for this. */
7009 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7013 status
= smb_posix_unlink(conn
, req
,
7022 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7027 if (!NT_STATUS_IS_OK(status
)) {
7028 if (open_was_deferred(req
->mid
)) {
7029 /* We have re-scheduled this call. */
7032 if (blocking_lock_was_deferred(req
->mid
)) {
7033 /* We have re-scheduled this call. */
7036 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7037 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7038 ERRSRV
, ERRbadpath
);
7041 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7042 reply_openerror(req
, status
);
7046 reply_nterror(req
, status
);
7051 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7057 /****************************************************************************
7058 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7059 ****************************************************************************/
7061 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7062 char **pparams
, int total_params
,
7063 char **ppdata
, int total_data
,
7064 unsigned int max_data_bytes
)
7066 char *params
= *pparams
;
7067 char *pdata
= *ppdata
;
7068 char *directory
= NULL
;
7069 SMB_STRUCT_STAT sbuf
;
7070 NTSTATUS status
= NT_STATUS_OK
;
7071 struct ea_list
*ea_list
= NULL
;
7072 TALLOC_CTX
*ctx
= talloc_tos();
7074 if (!CAN_WRITE(conn
)) {
7075 reply_doserror(req
, ERRSRV
, ERRaccess
);
7079 if (total_params
< 5) {
7080 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7084 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7085 total_params
- 4, STR_TERMINATE
,
7087 if (!NT_STATUS_IS_OK(status
)) {
7088 reply_nterror(req
, status
);
7092 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7094 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
7095 if (!NT_STATUS_IS_OK(status
)) {
7096 reply_nterror(req
, status
);
7100 status
= check_name(conn
, directory
);
7101 if (!NT_STATUS_IS_OK(status
)) {
7102 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
7103 reply_nterror(req
, status
);
7107 /* Any data in this call is an EA list. */
7108 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7109 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7114 * OS/2 workplace shell seems to send SET_EA requests of "null"
7115 * length (4 bytes containing IVAL 4).
7116 * They seem to have no effect. Bug #3212. JRA.
7119 if (total_data
!= 4) {
7120 if (total_data
< 10) {
7121 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7125 if (IVAL(pdata
,0) > total_data
) {
7126 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7127 IVAL(pdata
,0), (unsigned int)total_data
));
7128 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7132 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7139 /* If total_data == 4 Windows doesn't care what values
7140 * are placed in that field, it just ignores them.
7141 * The System i QNTC IBM SMB client puts bad values here,
7142 * so ignore them. */
7144 status
= create_directory(conn
, req
, directory
);
7146 if (!NT_STATUS_IS_OK(status
)) {
7147 reply_nterror(req
, status
);
7151 /* Try and set any given EA. */
7153 status
= set_ea(conn
, NULL
, directory
, ea_list
);
7154 if (!NT_STATUS_IS_OK(status
)) {
7155 reply_nterror(req
, status
);
7160 /* Realloc the parameter and data sizes */
7161 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7162 if(*pparams
== NULL
) {
7163 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7170 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7175 /****************************************************************************
7176 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7177 We don't actually do this - we just send a null response.
7178 ****************************************************************************/
7180 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7181 struct smb_request
*req
,
7182 char **pparams
, int total_params
,
7183 char **ppdata
, int total_data
,
7184 unsigned int max_data_bytes
)
7186 static uint16 fnf_handle
= 257;
7187 char *params
= *pparams
;
7190 if (total_params
< 6) {
7191 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7195 info_level
= SVAL(params
,4);
7196 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7198 switch (info_level
) {
7203 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7207 /* Realloc the parameter and data sizes */
7208 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7209 if (*pparams
== NULL
) {
7210 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7215 SSVAL(params
,0,fnf_handle
);
7216 SSVAL(params
,2,0); /* No changes */
7217 SSVAL(params
,4,0); /* No EA errors */
7224 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7229 /****************************************************************************
7230 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7231 changes). Currently this does nothing.
7232 ****************************************************************************/
7234 static void call_trans2findnotifynext(connection_struct
*conn
,
7235 struct smb_request
*req
,
7236 char **pparams
, int total_params
,
7237 char **ppdata
, int total_data
,
7238 unsigned int max_data_bytes
)
7240 char *params
= *pparams
;
7242 DEBUG(3,("call_trans2findnotifynext\n"));
7244 /* Realloc the parameter and data sizes */
7245 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7246 if (*pparams
== NULL
) {
7247 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7252 SSVAL(params
,0,0); /* No changes */
7253 SSVAL(params
,2,0); /* No EA errors */
7255 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7260 /****************************************************************************
7261 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7262 ****************************************************************************/
7264 static void call_trans2getdfsreferral(connection_struct
*conn
,
7265 struct smb_request
*req
,
7266 char **pparams
, int total_params
,
7267 char **ppdata
, int total_data
,
7268 unsigned int max_data_bytes
)
7270 char *params
= *pparams
;
7271 char *pathname
= NULL
;
7273 int max_referral_level
;
7274 NTSTATUS status
= NT_STATUS_OK
;
7275 TALLOC_CTX
*ctx
= talloc_tos();
7277 DEBUG(10,("call_trans2getdfsreferral\n"));
7279 if (total_params
< 3) {
7280 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7284 max_referral_level
= SVAL(params
,0);
7286 if(!lp_host_msdfs()) {
7287 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7291 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7292 total_params
- 2, STR_TERMINATE
);
7294 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7297 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7298 ppdata
,&status
)) < 0) {
7299 reply_nterror(req
, status
);
7303 SSVAL(req
->inbuf
, smb_flg2
,
7304 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7305 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7310 #define LMCAT_SPL 0x53
7311 #define LMFUNC_GETJOBID 0x60
7313 /****************************************************************************
7314 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7315 ****************************************************************************/
7317 static void call_trans2ioctl(connection_struct
*conn
,
7318 struct smb_request
*req
,
7319 char **pparams
, int total_params
,
7320 char **ppdata
, int total_data
,
7321 unsigned int max_data_bytes
)
7323 char *pdata
= *ppdata
;
7324 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv15
));
7326 /* check for an invalid fid before proceeding */
7329 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7333 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7334 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7335 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7336 if (*ppdata
== NULL
) {
7337 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7342 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7343 CAN ACCEPT THIS IN UNICODE. JRA. */
7345 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7346 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7347 global_myname(), 15,
7348 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7349 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7350 lp_servicename(SNUM(conn
)), 13,
7351 STR_ASCII
|STR_TERMINATE
); /* Service name */
7352 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7357 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7358 reply_doserror(req
, ERRSRV
, ERRerror
);
7361 /****************************************************************************
7362 Reply to a SMBfindclose (stop trans2 directory search).
7363 ****************************************************************************/
7365 void reply_findclose(struct smb_request
*req
)
7369 START_PROFILE(SMBfindclose
);
7372 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7373 END_PROFILE(SMBfindclose
);
7377 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7379 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7381 dptr_close(&dptr_num
);
7383 reply_outbuf(req
, 0, 0);
7385 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7387 END_PROFILE(SMBfindclose
);
7391 /****************************************************************************
7392 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7393 ****************************************************************************/
7395 void reply_findnclose(struct smb_request
*req
)
7399 START_PROFILE(SMBfindnclose
);
7402 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7403 END_PROFILE(SMBfindnclose
);
7407 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7409 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7411 /* We never give out valid handles for a
7412 findnotifyfirst - so any dptr_num is ok here.
7415 reply_outbuf(req
, 0, 0);
7417 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7419 END_PROFILE(SMBfindnclose
);
7423 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7424 struct trans_state
*state
)
7426 if (Protocol
>= PROTOCOL_NT1
) {
7427 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7428 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7431 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7432 if (state
->call
!= TRANSACT2_QFSINFO
&&
7433 state
->call
!= TRANSACT2_SETFSINFO
) {
7434 DEBUG(0,("handle_trans2: encryption required "
7436 (unsigned int)state
->call
));
7437 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7442 /* Now we must call the relevant TRANS2 function */
7443 switch(state
->call
) {
7444 case TRANSACT2_OPEN
:
7446 START_PROFILE(Trans2_open
);
7447 call_trans2open(conn
, req
,
7448 &state
->param
, state
->total_param
,
7449 &state
->data
, state
->total_data
,
7450 state
->max_data_return
);
7451 END_PROFILE(Trans2_open
);
7455 case TRANSACT2_FINDFIRST
:
7457 START_PROFILE(Trans2_findfirst
);
7458 call_trans2findfirst(conn
, req
,
7459 &state
->param
, state
->total_param
,
7460 &state
->data
, state
->total_data
,
7461 state
->max_data_return
);
7462 END_PROFILE(Trans2_findfirst
);
7466 case TRANSACT2_FINDNEXT
:
7468 START_PROFILE(Trans2_findnext
);
7469 call_trans2findnext(conn
, req
,
7470 &state
->param
, state
->total_param
,
7471 &state
->data
, state
->total_data
,
7472 state
->max_data_return
);
7473 END_PROFILE(Trans2_findnext
);
7477 case TRANSACT2_QFSINFO
:
7479 START_PROFILE(Trans2_qfsinfo
);
7480 call_trans2qfsinfo(conn
, req
,
7481 &state
->param
, state
->total_param
,
7482 &state
->data
, state
->total_data
,
7483 state
->max_data_return
);
7484 END_PROFILE(Trans2_qfsinfo
);
7488 case TRANSACT2_SETFSINFO
:
7490 START_PROFILE(Trans2_setfsinfo
);
7491 call_trans2setfsinfo(conn
, req
,
7492 &state
->param
, state
->total_param
,
7493 &state
->data
, state
->total_data
,
7494 state
->max_data_return
);
7495 END_PROFILE(Trans2_setfsinfo
);
7499 case TRANSACT2_QPATHINFO
:
7500 case TRANSACT2_QFILEINFO
:
7502 START_PROFILE(Trans2_qpathinfo
);
7503 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7504 &state
->param
, state
->total_param
,
7505 &state
->data
, state
->total_data
,
7506 state
->max_data_return
);
7507 END_PROFILE(Trans2_qpathinfo
);
7511 case TRANSACT2_SETPATHINFO
:
7512 case TRANSACT2_SETFILEINFO
:
7514 START_PROFILE(Trans2_setpathinfo
);
7515 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7516 &state
->param
, state
->total_param
,
7517 &state
->data
, state
->total_data
,
7518 state
->max_data_return
);
7519 END_PROFILE(Trans2_setpathinfo
);
7523 case TRANSACT2_FINDNOTIFYFIRST
:
7525 START_PROFILE(Trans2_findnotifyfirst
);
7526 call_trans2findnotifyfirst(conn
, req
,
7527 &state
->param
, state
->total_param
,
7528 &state
->data
, state
->total_data
,
7529 state
->max_data_return
);
7530 END_PROFILE(Trans2_findnotifyfirst
);
7534 case TRANSACT2_FINDNOTIFYNEXT
:
7536 START_PROFILE(Trans2_findnotifynext
);
7537 call_trans2findnotifynext(conn
, req
,
7538 &state
->param
, state
->total_param
,
7539 &state
->data
, state
->total_data
,
7540 state
->max_data_return
);
7541 END_PROFILE(Trans2_findnotifynext
);
7545 case TRANSACT2_MKDIR
:
7547 START_PROFILE(Trans2_mkdir
);
7548 call_trans2mkdir(conn
, req
,
7549 &state
->param
, state
->total_param
,
7550 &state
->data
, state
->total_data
,
7551 state
->max_data_return
);
7552 END_PROFILE(Trans2_mkdir
);
7556 case TRANSACT2_GET_DFS_REFERRAL
:
7558 START_PROFILE(Trans2_get_dfs_referral
);
7559 call_trans2getdfsreferral(conn
, req
,
7560 &state
->param
, state
->total_param
,
7561 &state
->data
, state
->total_data
,
7562 state
->max_data_return
);
7563 END_PROFILE(Trans2_get_dfs_referral
);
7567 case TRANSACT2_IOCTL
:
7569 START_PROFILE(Trans2_ioctl
);
7570 call_trans2ioctl(conn
, req
,
7571 &state
->param
, state
->total_param
,
7572 &state
->data
, state
->total_data
,
7573 state
->max_data_return
);
7574 END_PROFILE(Trans2_ioctl
);
7579 /* Error in request */
7580 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7581 reply_doserror(req
, ERRSRV
,ERRerror
);
7585 /****************************************************************************
7586 Reply to a SMBtrans2.
7587 ****************************************************************************/
7589 void reply_trans2(struct smb_request
*req
)
7591 connection_struct
*conn
= req
->conn
;
7596 unsigned int tran_call
;
7598 unsigned int av_size
;
7599 struct trans_state
*state
;
7602 START_PROFILE(SMBtrans2
);
7604 if (req
->wct
< 14) {
7605 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7606 END_PROFILE(SMBtrans2
);
7610 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7611 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7612 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7613 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7614 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7615 size
= smb_len(req
->inbuf
) + 4;
7616 av_size
= smb_len(req
->inbuf
);
7618 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7619 if (!NT_STATUS_IS_OK(result
)) {
7620 DEBUG(2, ("Got invalid trans2 request: %s\n",
7621 nt_errstr(result
)));
7622 reply_nterror(req
, result
);
7623 END_PROFILE(SMBtrans2
);
7628 switch (tran_call
) {
7629 /* List the allowed trans2 calls on IPC$ */
7630 case TRANSACT2_OPEN
:
7631 case TRANSACT2_GET_DFS_REFERRAL
:
7632 case TRANSACT2_QFILEINFO
:
7633 case TRANSACT2_QFSINFO
:
7634 case TRANSACT2_SETFSINFO
:
7637 reply_doserror(req
, ERRSRV
, ERRaccess
);
7638 END_PROFILE(SMBtrans2
);
7643 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
7644 DEBUG(0, ("talloc failed\n"));
7645 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7646 END_PROFILE(SMBtrans2
);
7650 state
->cmd
= SMBtrans2
;
7652 state
->mid
= req
->mid
;
7653 state
->vuid
= req
->vuid
;
7654 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7655 state
->setup
= NULL
;
7656 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7657 state
->param
= NULL
;
7658 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7660 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7661 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7662 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7663 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7664 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7666 state
->call
= tran_call
;
7668 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7669 is so as a sanity check */
7670 if (state
->setup_count
!= 1) {
7672 * Need to have rc=0 for ioctl to get job id for OS/2.
7673 * Network printing will fail if function is not successful.
7674 * Similar function in reply.c will be used if protocol
7675 * is LANMAN1.0 instead of LM1.2X002.
7676 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7677 * outbuf doesn't have to be set(only job id is used).
7679 if ( (state
->setup_count
== 4)
7680 && (tran_call
== TRANSACT2_IOCTL
)
7681 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7682 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7683 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7685 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7686 DEBUG(2,("Transaction is %d\n",tran_call
));
7688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7689 END_PROFILE(SMBtrans2
);
7694 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7697 if (state
->total_data
) {
7698 /* Can't use talloc here, the core routines do realloc on the
7699 * params and data. */
7700 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7701 if (state
->data
== NULL
) {
7702 DEBUG(0,("reply_trans2: data malloc fail for %u "
7703 "bytes !\n", (unsigned int)state
->total_data
));
7705 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7706 END_PROFILE(SMBtrans2
);
7710 if (dscnt
> state
->total_data
||
7711 dsoff
+dscnt
< dsoff
) {
7715 if (dsoff
> av_size
||
7717 dsoff
+dscnt
> av_size
) {
7721 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7724 if (state
->total_param
) {
7725 /* Can't use talloc here, the core routines do realloc on the
7726 * params and data. */
7727 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7728 if (state
->param
== NULL
) {
7729 DEBUG(0,("reply_trans: param malloc fail for %u "
7730 "bytes !\n", (unsigned int)state
->total_param
));
7731 SAFE_FREE(state
->data
);
7733 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7734 END_PROFILE(SMBtrans2
);
7738 if (pscnt
> state
->total_param
||
7739 psoff
+pscnt
< psoff
) {
7743 if (psoff
> av_size
||
7745 psoff
+pscnt
> av_size
) {
7749 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7752 state
->received_data
= dscnt
;
7753 state
->received_param
= pscnt
;
7755 if ((state
->received_param
== state
->total_param
) &&
7756 (state
->received_data
== state
->total_data
)) {
7758 handle_trans2(conn
, req
, state
);
7760 SAFE_FREE(state
->data
);
7761 SAFE_FREE(state
->param
);
7763 END_PROFILE(SMBtrans2
);
7767 DLIST_ADD(conn
->pending_trans
, state
);
7769 /* We need to send an interim response then receive the rest
7770 of the parameter/data bytes */
7771 reply_outbuf(req
, 0, 0);
7772 show_msg((char *)req
->outbuf
);
7773 END_PROFILE(SMBtrans2
);
7778 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7779 SAFE_FREE(state
->data
);
7780 SAFE_FREE(state
->param
);
7782 END_PROFILE(SMBtrans2
);
7783 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7787 /****************************************************************************
7788 Reply to a SMBtranss2
7789 ****************************************************************************/
7791 void reply_transs2(struct smb_request
*req
)
7793 connection_struct
*conn
= req
->conn
;
7794 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7795 struct trans_state
*state
;
7797 unsigned int av_size
;
7799 START_PROFILE(SMBtranss2
);
7801 show_msg((char *)req
->inbuf
);
7804 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7805 END_PROFILE(SMBtranss2
);
7809 size
= smb_len(req
->inbuf
)+4;
7810 av_size
= smb_len(req
->inbuf
);
7812 for (state
= conn
->pending_trans
; state
!= NULL
;
7813 state
= state
->next
) {
7814 if (state
->mid
== req
->mid
) {
7819 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7820 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7821 END_PROFILE(SMBtranss2
);
7825 /* Revise state->total_param and state->total_data in case they have
7826 changed downwards */
7828 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7829 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7830 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7831 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7833 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7834 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7835 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7837 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7838 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7839 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7841 state
->received_param
+= pcnt
;
7842 state
->received_data
+= dcnt
;
7844 if ((state
->received_data
> state
->total_data
) ||
7845 (state
->received_param
> state
->total_param
))
7849 if (pdisp
> state
->total_param
||
7850 pcnt
> state
->total_param
||
7851 pdisp
+pcnt
> state
->total_param
||
7852 pdisp
+pcnt
< pdisp
) {
7856 if (poff
> av_size
||
7858 poff
+pcnt
> av_size
||
7863 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7868 if (ddisp
> state
->total_data
||
7869 dcnt
> state
->total_data
||
7870 ddisp
+dcnt
> state
->total_data
||
7871 ddisp
+dcnt
< ddisp
) {
7875 if (doff
> av_size
||
7877 doff
+dcnt
> av_size
||
7882 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7886 if ((state
->received_param
< state
->total_param
) ||
7887 (state
->received_data
< state
->total_data
)) {
7888 END_PROFILE(SMBtranss2
);
7893 * construct_reply_common will copy smb_com from inbuf to
7894 * outbuf. SMBtranss2 is wrong here.
7896 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7898 handle_trans2(conn
, req
, state
);
7900 DLIST_REMOVE(conn
->pending_trans
, state
);
7901 SAFE_FREE(state
->data
);
7902 SAFE_FREE(state
->param
);
7905 END_PROFILE(SMBtranss2
);
7910 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7911 DLIST_REMOVE(conn
->pending_trans
, state
);
7912 SAFE_FREE(state
->data
);
7913 SAFE_FREE(state
->param
);
7915 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7916 END_PROFILE(SMBtranss2
);