2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct
*conn
,
36 const SMB_STRUCT_STAT
*psbuf
);
38 static char *store_file_unix_basic_info2(connection_struct
*conn
,
41 const SMB_STRUCT_STAT
*psbuf
);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
50 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type
= get_remote_arch();
54 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
55 val
= SMB_ROUNDUP(val
,rval
);
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
69 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
70 return (uint64_t)psbuf
->st_ex_ino
;
72 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
73 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name
)
87 static const char * const prohibited_ea_names
[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME
,
89 SAMBA_XATTR_DOS_ATTRIB
,
97 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
98 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
101 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
113 files_struct
*fsp
, const char *fname
,
114 const char *ea_name
, struct ea_struct
*pea
)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size
= 256;
123 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
125 return NT_STATUS_NO_MEMORY
;
128 if (fsp
&& fsp
->fh
->fd
!= -1) {
129 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
131 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
134 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
140 return map_nt_error_from_unix(errno
);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
144 dump_data(10, (uint8
*)val
, sizeret
);
147 if (strnequal(ea_name
, "user.", 5)) {
148 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
150 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
152 if (pea
->name
== NULL
) {
154 return NT_STATUS_NO_MEMORY
;
156 pea
->value
.data
= (unsigned char *)val
;
157 pea
->value
.length
= (size_t)sizeret
;
161 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
162 files_struct
*fsp
, const char *fname
,
163 char ***pnames
, size_t *pnum_names
)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size
= 1024;
167 char *ea_namelist
= NULL
;
172 ssize_t sizeret
= -1;
174 if (!lp_ea_support(SNUM(conn
))) {
183 * TALLOC the result early to get the talloc hierarchy right.
186 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY
;
192 while (ea_namelist_size
<= 65536) {
194 ea_namelist
= TALLOC_REALLOC_ARRAY(
195 names
, ea_namelist
, char, ea_namelist_size
);
196 if (ea_namelist
== NULL
) {
197 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY
;
202 if (fsp
&& fsp
->fh
->fd
!= -1) {
203 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
206 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
210 if ((sizeret
== -1) && (errno
== ERANGE
)) {
211 ea_namelist_size
*= 2;
220 return map_nt_error_from_unix(errno
);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret
));
236 * Ensure the result is 0-terminated
239 if (ea_namelist
[sizeret
-1] != '\0') {
241 return NT_STATUS_INTERNAL_ERROR
;
249 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
253 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
255 DEBUG(0, ("talloc failed\n"));
257 return NT_STATUS_NO_MEMORY
;
263 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
264 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 NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
397 unsigned int total_data_size
,
398 unsigned int *ret_data_size
,
399 connection_struct
*conn
,
400 struct ea_list
*ea_list
)
402 uint8_t *p
= (uint8_t *)pdata
;
403 uint8_t *last_start
= NULL
;
407 if (!lp_ea_support(SNUM(conn
))) {
408 return NT_STATUS_NO_EAS_ON_FILE
;
411 for (; ea_list
; ea_list
= ea_list
->next
) {
417 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
421 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
422 dos_namelen
= strlen(dos_ea_name
);
423 if (dos_namelen
> 255 || dos_namelen
== 0) {
424 return NT_STATUS_INTERNAL_ERROR
;
426 if (ea_list
->ea
.value
.length
> 65535) {
427 return NT_STATUS_INTERNAL_ERROR
;
430 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
433 size_t pad
= 4 - (this_size
% 4);
437 if (this_size
> total_data_size
) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH
;
441 /* We know we have room. */
442 SIVAL(p
, 0x00, 0); /* next offset */
443 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
444 SCVAL(p
, 0x05, dos_namelen
);
445 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
446 fstrcpy((char *)(p
+0x08), dos_ea_name
);
447 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
449 total_data_size
-= this_size
;
453 *ret_data_size
= PTR_DIFF(p
, pdata
);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
458 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
460 size_t total_ea_len
= 0;
461 TALLOC_CTX
*mem_ctx
= NULL
;
463 if (!lp_ea_support(SNUM(conn
))) {
466 mem_ctx
= talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
478 TALLOC_CTX
*mem_ctx
= talloc_tos();
479 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
481 for (; ea_list
; ea_list
= ea_list
->next
) {
482 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name
[5], ea_list
->ea
.name
));
485 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
496 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
500 if (!lp_ea_support(SNUM(conn
))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED
;
504 /* For now setting EAs on streams isn't supported. */
505 fname
= smb_fname
->base_name
;
507 for (;ea_list
; ea_list
= ea_list
->next
) {
509 fstring unix_ea_name
;
511 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
514 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
518 if (samba_private_attr_name(unix_ea_name
)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
520 return NT_STATUS_ACCESS_DENIED
;
523 if (ea_list
->ea
.value
.length
== 0) {
524 /* Remove the attribute. */
525 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name
, fsp_str_dbg(fsp
)));
529 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name
, fname
));
533 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
536 /* Removing a non existent attribute always succeeds. */
537 if (ret
== -1 && errno
== ENOATTR
) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
544 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name
, fsp_str_dbg(fsp
)));
548 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
549 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name
, fname
));
553 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
554 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
560 if (errno
== ENOTSUP
) {
561 return NT_STATUS_EAS_NOT_SUPPORTED
;
564 return map_nt_error_from_unix(errno
);
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
576 struct ea_list
*ea_list_head
= NULL
;
577 size_t converted_size
, offset
= 0;
579 while (offset
+ 2 < data_size
) {
580 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
581 unsigned int namelen
= CVAL(pdata
,offset
);
583 offset
++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
587 (offset
> data_size
) || (namelen
> data_size
) ||
588 (offset
+ namelen
>= data_size
)) {
591 /* Ensure the name is null terminated. */
592 if (pdata
[offset
+ namelen
] != '\0') {
595 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno
)));
604 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
618 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
620 unsigned int namelen
;
621 size_t converted_size
;
631 eal
->ea
.flags
= CVAL(pdata
,0);
632 namelen
= CVAL(pdata
,1);
633 val_len
= SVAL(pdata
,2);
635 if (4 + namelen
+ 1 + val_len
> data_size
) {
639 /* Ensure the name is null terminated. */
640 if (pdata
[namelen
+ 4] != '\0') {
643 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
651 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
652 if (!eal
->ea
.value
.data
) {
656 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal
->ea
.value
.data
[val_len
] = '\0';
660 /* But don't count the null. */
661 eal
->ea
.value
.length
--;
664 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
668 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
679 struct ea_list
*ea_list_head
= NULL
;
681 size_t bytes_used
= 0;
683 while (offset
< data_size
) {
684 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
690 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
691 offset
+= bytes_used
;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list
*ealist
)
704 struct ea_list
*listp
;
707 for (listp
= ealist
; listp
; listp
= listp
->next
) {
708 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
709 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
711 /* Add on 4 for total length. */
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
727 struct ea_list
*nlistp
, *flistp
;
729 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
730 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
731 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
737 /* Copy the data from this entry. */
738 nlistp
->ea
.flags
= flistp
->ea
.flags
;
739 nlistp
->ea
.value
= flistp
->ea
.value
;
742 nlistp
->ea
.flags
= 0;
743 ZERO_STRUCT(nlistp
->ea
.value
);
747 *total_ea_len
= ea_list_size(name_list
);
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct
*conn
,
759 struct smb_request
*req
,
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send
= datasize
;
773 int params_to_send
= paramsize
;
775 const char *pp
= params
;
776 const char *pd
= pdata
;
777 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
778 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset
= 0;
780 bool overflow
= False
;
781 struct smbd_server_connection
*sconn
= smbd_server_conn
;
782 int max_send
= sconn
->smb1
.sessions
.max_send
;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
789 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes
, datasize
));
792 datasize
= data_to_send
= max_data_bytes
;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send
== 0 && data_to_send
== 0) {
799 reply_outbuf(req
, 10, 0);
800 show_msg((char *)req
->outbuf
);
801 if (!srv_send_smb(smbd_server_fd(),
804 IS_CONN_ENCRYPTED(conn
),
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req
->outbuf
);
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
817 data_alignment_offset
= 4 - (params_to_send
% 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space
= max_send
- (smb_size
826 + data_alignment_offset
);
828 if (useable_space
< 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space
));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send
|| data_to_send
) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime
= params_to_send
+ data_to_send
;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
849 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
850 + data_alignment_offset
);
852 /* Set total params and data to be sent */
853 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
854 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
856 /* Calculate how many parameters and data we can fit into
857 * this packet. Parameters get precedence
860 params_sent_thistime
= MIN(params_to_send
,useable_space
);
861 data_sent_thistime
= useable_space
- params_sent_thistime
;
862 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
864 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
866 /* smb_proff is the offset from the start of the SMB header to the
867 parameter bytes, however the first 4 bytes of outbuf are
868 the Netbios over TCP header. Thus use smb_base() to subtract
869 them from the calculation */
871 SSVAL(req
->outbuf
,smb_proff
,
872 ((smb_buf(req
->outbuf
)+alignment_offset
)
873 - smb_base(req
->outbuf
)));
875 if(params_sent_thistime
== 0)
876 SSVAL(req
->outbuf
,smb_prdisp
,0);
878 /* Absolute displacement of param bytes sent in this packet */
879 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
881 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
882 if(data_sent_thistime
== 0) {
883 SSVAL(req
->outbuf
,smb_droff
,0);
884 SSVAL(req
->outbuf
,smb_drdisp
, 0);
886 /* The offset of the data bytes is the offset of the
887 parameter bytes plus the number of parameters being sent this time */
888 SSVAL(req
->outbuf
, smb_droff
,
889 ((smb_buf(req
->outbuf
)+alignment_offset
)
890 - smb_base(req
->outbuf
))
891 + params_sent_thistime
+ data_alignment_offset
);
892 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
895 /* Initialize the padding for alignment */
897 if (alignment_offset
!= 0) {
898 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
901 /* Copy the param bytes into the packet */
903 if(params_sent_thistime
) {
904 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
905 params_sent_thistime
);
908 /* Copy in the data bytes */
909 if(data_sent_thistime
) {
910 if (data_alignment_offset
!= 0) {
911 memset((smb_buf(req
->outbuf
)+alignment_offset
+
912 params_sent_thistime
), 0,
913 data_alignment_offset
);
915 memcpy(smb_buf(req
->outbuf
)+alignment_offset
916 +params_sent_thistime
+data_alignment_offset
,
917 pd
,data_sent_thistime
);
920 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
921 params_sent_thistime
, data_sent_thistime
, useable_space
));
922 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
923 params_to_send
, data_to_send
, paramsize
, datasize
));
926 error_packet_set((char *)req
->outbuf
,
927 ERRDOS
,ERRbufferoverflow
,
928 STATUS_BUFFER_OVERFLOW
,
932 /* Send the packet */
933 show_msg((char *)req
->outbuf
);
934 if (!srv_send_smb(smbd_server_fd(),
937 IS_CONN_ENCRYPTED(conn
),
939 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
941 TALLOC_FREE(req
->outbuf
);
943 pp
+= params_sent_thistime
;
944 pd
+= data_sent_thistime
;
946 params_to_send
-= params_sent_thistime
;
947 data_to_send
-= data_sent_thistime
;
950 if(params_to_send
< 0 || data_to_send
< 0) {
951 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
952 params_to_send
, data_to_send
));
960 /****************************************************************************
961 Reply to a TRANSACT2_OPEN.
962 ****************************************************************************/
964 static void call_trans2open(connection_struct
*conn
,
965 struct smb_request
*req
,
966 char **pparams
, int total_params
,
967 char **ppdata
, int total_data
,
968 unsigned int max_data_bytes
)
970 struct smb_filename
*smb_fname
= NULL
;
971 char *params
= *pparams
;
972 char *pdata
= *ppdata
;
977 bool return_additional_info
;
990 struct ea_list
*ea_list
= NULL
;
995 uint32 create_disposition
;
996 uint32 create_options
= 0;
997 TALLOC_CTX
*ctx
= talloc_tos();
1000 * Ensure we have enough parameters to perform the operation.
1003 if (total_params
< 29) {
1004 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1008 flags
= SVAL(params
, 0);
1009 deny_mode
= SVAL(params
, 2);
1010 open_attr
= SVAL(params
,6);
1011 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1012 if (oplock_request
) {
1013 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1017 return_additional_info
= BITSETW(params
,0);
1018 open_sattr
= SVAL(params
, 4);
1019 open_time
= make_unix_date3(params
+8);
1021 open_ofun
= SVAL(params
,12);
1022 open_size
= IVAL(params
,14);
1023 pname
= ¶ms
[28];
1026 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1030 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1031 total_params
- 28, STR_TERMINATE
,
1033 if (!NT_STATUS_IS_OK(status
)) {
1034 reply_nterror(req
, status
);
1038 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1039 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1040 (unsigned int)open_ofun
, open_size
));
1042 status
= filename_convert(ctx
,
1044 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1049 if (!NT_STATUS_IS_OK(status
)) {
1050 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1051 reply_botherror(req
,
1052 NT_STATUS_PATH_NOT_COVERED
,
1053 ERRSRV
, ERRbadpath
);
1056 reply_nterror(req
, status
);
1060 if (open_ofun
== 0) {
1061 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1065 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1067 &access_mask
, &share_mode
,
1068 &create_disposition
,
1070 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1074 /* Any data in this call is an EA list. */
1075 if (total_data
&& (total_data
!= 4)) {
1076 if (total_data
< 10) {
1077 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1081 if (IVAL(pdata
,0) > total_data
) {
1082 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1083 IVAL(pdata
,0), (unsigned int)total_data
));
1084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1088 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1091 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1095 if (!lp_ea_support(SNUM(conn
))) {
1096 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1101 status
= SMB_VFS_CREATE_FILE(
1104 0, /* root_dir_fid */
1105 smb_fname
, /* fname */
1106 access_mask
, /* access_mask */
1107 share_mode
, /* share_access */
1108 create_disposition
, /* create_disposition*/
1109 create_options
, /* create_options */
1110 open_attr
, /* file_attributes */
1111 oplock_request
, /* oplock_request */
1112 open_size
, /* allocation_size */
1114 ea_list
, /* ea_list */
1116 &smb_action
); /* psbuf */
1118 if (!NT_STATUS_IS_OK(status
)) {
1119 if (open_was_deferred(req
->mid
)) {
1120 /* We have re-scheduled this call. */
1123 reply_openerror(req
, status
);
1127 size
= get_file_size_stat(&smb_fname
->st
);
1128 fattr
= dos_mode(conn
, smb_fname
);
1129 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1130 inode
= smb_fname
->st
.st_ex_ino
;
1132 close_file(req
, fsp
, ERROR_CLOSE
);
1133 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1137 /* Realloc the size of parameters and data we will return */
1138 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1139 if(*pparams
== NULL
) {
1140 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1145 SSVAL(params
,0,fsp
->fnum
);
1146 SSVAL(params
,2,fattr
);
1147 srv_put_dos_date2(params
,4, mtime
);
1148 SIVAL(params
,8, (uint32
)size
);
1149 SSVAL(params
,12,deny_mode
);
1150 SSVAL(params
,14,0); /* open_type - file or directory. */
1151 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1153 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1154 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1157 SSVAL(params
,18,smb_action
);
1160 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1162 SIVAL(params
,20,inode
);
1163 SSVAL(params
,24,0); /* Padding. */
1165 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1166 fsp
->fsp_name
->base_name
);
1167 SIVAL(params
, 26, ea_size
);
1169 SIVAL(params
, 26, 0);
1172 /* Send the required number of replies */
1173 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1175 TALLOC_FREE(smb_fname
);
1178 /*********************************************************
1179 Routine to check if a given string matches exactly.
1180 as a special case a mask of "." does NOT match. That
1181 is required for correct wildcard semantics
1182 Case can be significant or not.
1183 **********************************************************/
1185 static bool exact_match(bool has_wild
,
1186 bool case_sensitive
,
1190 if (mask
[0] == '.' && mask
[1] == 0) {
1198 if (case_sensitive
) {
1199 return strcmp(str
,mask
)==0;
1201 return StrCaseCmp(str
,mask
) == 0;
1205 /****************************************************************************
1206 Return the filetype for UNIX extensions.
1207 ****************************************************************************/
1209 static uint32
unix_filetype(mode_t mode
)
1212 return UNIX_TYPE_FILE
;
1213 else if(S_ISDIR(mode
))
1214 return UNIX_TYPE_DIR
;
1216 else if(S_ISLNK(mode
))
1217 return UNIX_TYPE_SYMLINK
;
1220 else if(S_ISCHR(mode
))
1221 return UNIX_TYPE_CHARDEV
;
1224 else if(S_ISBLK(mode
))
1225 return UNIX_TYPE_BLKDEV
;
1228 else if(S_ISFIFO(mode
))
1229 return UNIX_TYPE_FIFO
;
1232 else if(S_ISSOCK(mode
))
1233 return UNIX_TYPE_SOCKET
;
1236 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1237 return UNIX_TYPE_UNKNOWN
;
1240 /****************************************************************************
1241 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1242 ****************************************************************************/
1244 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1246 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1247 const SMB_STRUCT_STAT
*psbuf
,
1249 enum perm_type ptype
,
1254 if (perms
== SMB_MODE_NO_CHANGE
) {
1255 if (!VALID_STAT(*psbuf
)) {
1256 return NT_STATUS_INVALID_PARAMETER
;
1258 *ret_perms
= psbuf
->st_ex_mode
;
1259 return NT_STATUS_OK
;
1263 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1264 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1265 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1266 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1267 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1268 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1269 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1270 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1271 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1273 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1276 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1279 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1284 /* Apply mode mask */
1285 ret
&= lp_create_mask(SNUM(conn
));
1286 /* Add in force bits */
1287 ret
|= lp_force_create_mode(SNUM(conn
));
1290 ret
&= lp_dir_mask(SNUM(conn
));
1291 /* Add in force bits */
1292 ret
|= lp_force_dir_mode(SNUM(conn
));
1294 case PERM_EXISTING_FILE
:
1295 /* Apply mode mask */
1296 ret
&= lp_security_mask(SNUM(conn
));
1297 /* Add in force bits */
1298 ret
|= lp_force_security_mode(SNUM(conn
));
1300 case PERM_EXISTING_DIR
:
1301 /* Apply mode mask */
1302 ret
&= lp_dir_security_mask(SNUM(conn
));
1303 /* Add in force bits */
1304 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1309 return NT_STATUS_OK
;
1312 /****************************************************************************
1313 Needed to show the msdfs symlinks as directories. Modifies psbuf
1314 to be a directory if it's a msdfs link.
1315 ****************************************************************************/
1317 static bool check_msdfs_link(connection_struct
*conn
,
1318 const char *pathname
,
1319 SMB_STRUCT_STAT
*psbuf
)
1321 int saved_errno
= errno
;
1322 if(lp_host_msdfs() &&
1323 lp_msdfs_root(SNUM(conn
)) &&
1324 is_msdfs_link(conn
, pathname
, psbuf
)) {
1326 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1329 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1330 errno
= saved_errno
;
1333 errno
= saved_errno
;
1338 /****************************************************************************
1339 Get a level dependent lanman2 dir entry.
1340 ****************************************************************************/
1342 struct smbd_dirptr_lanman2_state
{
1343 connection_struct
*conn
;
1344 uint32_t info_level
;
1345 bool check_mangled_names
;
1347 bool got_exact_match
;
1350 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1356 struct smbd_dirptr_lanman2_state
*state
=
1357 (struct smbd_dirptr_lanman2_state
*)private_data
;
1359 char mangled_name
[13]; /* mangled 8.3 name. */
1363 /* Mangle fname if it's an illegal name. */
1364 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1365 ok
= name_to_8_3(dname
, mangled_name
,
1366 true, state
->conn
->params
);
1370 fname
= mangled_name
;
1375 got_match
= exact_match(state
->has_wild
,
1376 state
->conn
->case_sensitive
,
1378 state
->got_exact_match
= got_match
;
1380 got_match
= mask_match(fname
, mask
,
1381 state
->conn
->case_sensitive
);
1384 if(!got_match
&& state
->check_mangled_names
&&
1385 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1387 * It turns out that NT matches wildcards against
1388 * both long *and* short names. This may explain some
1389 * of the wildcard wierdness from old DOS clients
1390 * that some people have been seeing.... JRA.
1392 /* Force the mangling into 8.3. */
1393 ok
= name_to_8_3(fname
, mangled_name
,
1394 false, state
->conn
->params
);
1399 got_match
= exact_match(state
->has_wild
,
1400 state
->conn
->case_sensitive
,
1401 mangled_name
, mask
);
1402 state
->got_exact_match
= got_match
;
1404 got_match
= mask_match(mangled_name
, mask
,
1405 state
->conn
->case_sensitive
);
1413 *_fname
= talloc_strdup(ctx
, fname
);
1414 if (*_fname
== NULL
) {
1421 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1423 struct smb_filename
*smb_fname
,
1426 struct smbd_dirptr_lanman2_state
*state
=
1427 (struct smbd_dirptr_lanman2_state
*)private_data
;
1428 bool ms_dfs_link
= false;
1431 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1432 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1433 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1434 "Couldn't lstat [%s] (%s)\n",
1435 smb_fname_str_dbg(smb_fname
),
1439 } else if (!VALID_STAT(smb_fname
->st
) &&
1440 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1441 /* Needed to show the msdfs symlinks as
1444 ms_dfs_link
= check_msdfs_link(state
->conn
,
1445 smb_fname
->base_name
,
1448 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1449 "Couldn't stat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname
),
1457 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1459 mode
= dos_mode(state
->conn
, smb_fname
);
1466 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1467 connection_struct
*conn
,
1469 uint32_t info_level
,
1470 struct ea_list
*name_list
,
1471 bool check_mangled_names
,
1472 bool requires_resume_key
,
1475 const struct smb_filename
*smb_fname
,
1476 uint64_t space_remaining
,
1483 uint64_t *last_entry_off
)
1485 char *p
, *q
, *pdata
= *ppdata
;
1487 uint64_t file_size
= 0;
1488 uint64_t allocation_size
= 0;
1489 uint64_t file_index
= 0;
1491 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1492 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1493 time_t c_date
= (time_t)0;
1495 char *last_entry_ptr
;
1500 *out_of_space
= false;
1502 ZERO_STRUCT(mdate_ts
);
1503 ZERO_STRUCT(adate_ts
);
1504 ZERO_STRUCT(create_date_ts
);
1505 ZERO_STRUCT(cdate_ts
);
1507 if (!(mode
& aDIR
)) {
1508 file_size
= get_file_size_stat(&smb_fname
->st
);
1510 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1512 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1514 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1515 adate_ts
= smb_fname
->st
.st_ex_atime
;
1516 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1517 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1519 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1520 dos_filetime_timespec(&create_date_ts
);
1521 dos_filetime_timespec(&mdate_ts
);
1522 dos_filetime_timespec(&adate_ts
);
1523 dos_filetime_timespec(&cdate_ts
);
1526 create_date
= convert_timespec_to_time_t(create_date_ts
);
1527 mdate
= convert_timespec_to_time_t(mdate_ts
);
1528 adate
= convert_timespec_to_time_t(adate_ts
);
1529 c_date
= convert_timespec_to_time_t(cdate_ts
);
1531 /* align the record */
1532 off
= PTR_DIFF(pdata
, base_data
);
1533 pad
= (off
+ (align
-1)) & ~(align
-1);
1536 /* initialize padding to 0 */
1538 memset(pdata
, 0, pad
);
1540 space_remaining
-= pad
;
1549 switch (info_level
) {
1550 case SMB_FIND_INFO_STANDARD
:
1551 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1552 if(requires_resume_key
) {
1556 srv_put_dos_date2(p
,0,create_date
);
1557 srv_put_dos_date2(p
,4,adate
);
1558 srv_put_dos_date2(p
,8,mdate
);
1559 SIVAL(p
,12,(uint32
)file_size
);
1560 SIVAL(p
,16,(uint32
)allocation_size
);
1564 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1565 p
+= ucs2_align(base_data
, p
, 0);
1567 len
= srvstr_push(base_data
, flags2
, p
,
1568 fname
, PTR_DIFF(end_data
, p
),
1570 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1572 SCVAL(nameptr
, -1, len
- 2);
1574 SCVAL(nameptr
, -1, 0);
1578 SCVAL(nameptr
, -1, len
- 1);
1580 SCVAL(nameptr
, -1, 0);
1586 case SMB_FIND_EA_SIZE
:
1587 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1588 if (requires_resume_key
) {
1592 srv_put_dos_date2(p
,0,create_date
);
1593 srv_put_dos_date2(p
,4,adate
);
1594 srv_put_dos_date2(p
,8,mdate
);
1595 SIVAL(p
,12,(uint32
)file_size
);
1596 SIVAL(p
,16,(uint32
)allocation_size
);
1599 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1600 smb_fname
->base_name
);
1601 SIVAL(p
,22,ea_size
); /* Extended attributes */
1605 len
= srvstr_push(base_data
, flags2
,
1606 p
, fname
, PTR_DIFF(end_data
, p
),
1607 STR_TERMINATE
| STR_NOALIGN
);
1608 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1621 SCVAL(nameptr
,0,len
);
1623 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1626 case SMB_FIND_EA_LIST
:
1628 struct ea_list
*file_list
= NULL
;
1631 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1635 if (requires_resume_key
) {
1639 srv_put_dos_date2(p
,0,create_date
);
1640 srv_put_dos_date2(p
,4,adate
);
1641 srv_put_dos_date2(p
,8,mdate
);
1642 SIVAL(p
,12,(uint32
)file_size
);
1643 SIVAL(p
,16,(uint32
)allocation_size
);
1645 p
+= 22; /* p now points to the EA area. */
1647 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1648 smb_fname
->base_name
,
1650 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1652 /* We need to determine if this entry will fit in the space available. */
1653 /* Max string size is 255 bytes. */
1654 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1655 *out_of_space
= true;
1656 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1657 return False
; /* Not finished - just out of space */
1660 /* Push the ea_data followed by the name. */
1661 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1663 len
= srvstr_push(base_data
, flags2
,
1664 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1665 STR_TERMINATE
| STR_NOALIGN
);
1666 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1679 SCVAL(nameptr
,0,len
);
1681 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1685 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1686 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1687 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1689 SIVAL(p
,0,reskey
); p
+= 4;
1690 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1691 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1692 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1693 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1694 SOFF_T(p
,0,file_size
); p
+= 8;
1695 SOFF_T(p
,0,allocation_size
); p
+= 8;
1696 SIVAL(p
,0,mode
); p
+= 4;
1697 q
= p
; p
+= 4; /* q is placeholder for name length. */
1699 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1700 smb_fname
->base_name
);
1701 SIVAL(p
,0,ea_size
); /* Extended attributes */
1704 /* Clear the short name buffer. This is
1705 * IMPORTANT as not doing so will trigger
1706 * a Win2k client bug. JRA.
1708 if (!was_8_3
&& check_mangled_names
) {
1709 char mangled_name
[13]; /* mangled 8.3 name. */
1710 if (!name_to_8_3(fname
,mangled_name
,True
,
1712 /* Error - mangle failed ! */
1713 memset(mangled_name
,'\0',12);
1715 mangled_name
[12] = 0;
1716 len
= srvstr_push(base_data
, flags2
,
1717 p
+2, mangled_name
, 24,
1718 STR_UPPER
|STR_UNICODE
);
1720 memset(p
+ 2 + len
,'\0',24 - len
);
1727 len
= srvstr_push(base_data
, flags2
, p
,
1728 fname
, PTR_DIFF(end_data
, p
),
1729 STR_TERMINATE_ASCII
);
1733 len
= PTR_DIFF(p
, pdata
);
1734 pad
= (len
+ (align
-1)) & ~(align
-1);
1736 * offset to the next entry, the caller
1737 * will overwrite it for the last entry
1738 * that's why we always include the padding
1742 * set padding to zero
1745 memset(p
, 0, pad
- len
);
1752 case SMB_FIND_FILE_DIRECTORY_INFO
:
1753 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1755 SIVAL(p
,0,reskey
); p
+= 4;
1756 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1757 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1758 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1759 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1760 SOFF_T(p
,0,file_size
); p
+= 8;
1761 SOFF_T(p
,0,allocation_size
); p
+= 8;
1762 SIVAL(p
,0,mode
); p
+= 4;
1763 len
= srvstr_push(base_data
, flags2
,
1764 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1765 STR_TERMINATE_ASCII
);
1769 len
= PTR_DIFF(p
, pdata
);
1770 pad
= (len
+ (align
-1)) & ~(align
-1);
1772 * offset to the next entry, the caller
1773 * will overwrite it for the last entry
1774 * that's why we always include the padding
1778 * set padding to zero
1781 memset(p
, 0, pad
- len
);
1788 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1789 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1791 SIVAL(p
,0,reskey
); p
+= 4;
1792 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1793 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1794 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1795 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1796 SOFF_T(p
,0,file_size
); p
+= 8;
1797 SOFF_T(p
,0,allocation_size
); p
+= 8;
1798 SIVAL(p
,0,mode
); p
+= 4;
1799 q
= p
; p
+= 4; /* q is placeholder for name length. */
1801 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1802 smb_fname
->base_name
);
1803 SIVAL(p
,0,ea_size
); /* Extended attributes */
1806 len
= srvstr_push(base_data
, flags2
, p
,
1807 fname
, PTR_DIFF(end_data
, p
),
1808 STR_TERMINATE_ASCII
);
1812 len
= PTR_DIFF(p
, pdata
);
1813 pad
= (len
+ (align
-1)) & ~(align
-1);
1815 * offset to the next entry, the caller
1816 * will overwrite it for the last entry
1817 * that's why we always include the padding
1821 * set padding to zero
1824 memset(p
, 0, pad
- len
);
1831 case SMB_FIND_FILE_NAMES_INFO
:
1832 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1834 SIVAL(p
,0,reskey
); p
+= 4;
1836 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1837 acl on a dir (tridge) */
1838 len
= srvstr_push(base_data
, flags2
, p
,
1839 fname
, PTR_DIFF(end_data
, p
),
1840 STR_TERMINATE_ASCII
);
1844 len
= PTR_DIFF(p
, pdata
);
1845 pad
= (len
+ (align
-1)) & ~(align
-1);
1847 * offset to the next entry, the caller
1848 * will overwrite it for the last entry
1849 * that's why we always include the padding
1853 * set padding to zero
1856 memset(p
, 0, pad
- len
);
1863 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1864 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1866 SIVAL(p
,0,reskey
); p
+= 4;
1867 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1868 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1869 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1870 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1871 SOFF_T(p
,0,file_size
); p
+= 8;
1872 SOFF_T(p
,0,allocation_size
); p
+= 8;
1873 SIVAL(p
,0,mode
); p
+= 4;
1874 q
= p
; p
+= 4; /* q is placeholder for name length. */
1876 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1877 smb_fname
->base_name
);
1878 SIVAL(p
,0,ea_size
); /* Extended attributes */
1881 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1882 SBVAL(p
,0,file_index
); p
+= 8;
1883 len
= srvstr_push(base_data
, flags2
, p
,
1884 fname
, PTR_DIFF(end_data
, p
),
1885 STR_TERMINATE_ASCII
);
1889 len
= PTR_DIFF(p
, pdata
);
1890 pad
= (len
+ (align
-1)) & ~(align
-1);
1892 * offset to the next entry, the caller
1893 * will overwrite it for the last entry
1894 * that's why we always include the padding
1898 * set padding to zero
1901 memset(p
, 0, pad
- len
);
1908 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1909 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1910 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1912 SIVAL(p
,0,reskey
); p
+= 4;
1913 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1914 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1915 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1916 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1917 SOFF_T(p
,0,file_size
); p
+= 8;
1918 SOFF_T(p
,0,allocation_size
); p
+= 8;
1919 SIVAL(p
,0,mode
); p
+= 4;
1920 q
= p
; p
+= 4; /* q is placeholder for name length */
1922 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1923 smb_fname
->base_name
);
1924 SIVAL(p
,0,ea_size
); /* Extended attributes */
1927 /* Clear the short name buffer. This is
1928 * IMPORTANT as not doing so will trigger
1929 * a Win2k client bug. JRA.
1931 if (!was_8_3
&& check_mangled_names
) {
1932 char mangled_name
[13]; /* mangled 8.3 name. */
1933 if (!name_to_8_3(fname
,mangled_name
,True
,
1935 /* Error - mangle failed ! */
1936 memset(mangled_name
,'\0',12);
1938 mangled_name
[12] = 0;
1939 len
= srvstr_push(base_data
, flags2
,
1940 p
+2, mangled_name
, 24,
1941 STR_UPPER
|STR_UNICODE
);
1944 memset(p
+ 2 + len
,'\0',24 - len
);
1951 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1952 SBVAL(p
,0,file_index
); p
+= 8;
1953 len
= srvstr_push(base_data
, flags2
, p
,
1954 fname
, PTR_DIFF(end_data
, p
),
1955 STR_TERMINATE_ASCII
);
1959 len
= PTR_DIFF(p
, pdata
);
1960 pad
= (len
+ (align
-1)) & ~(align
-1);
1962 * offset to the next entry, the caller
1963 * will overwrite it for the last entry
1964 * that's why we always include the padding
1968 * set padding to zero
1971 memset(p
, 0, pad
- len
);
1978 /* CIFS UNIX Extension. */
1980 case SMB_FIND_FILE_UNIX
:
1981 case SMB_FIND_FILE_UNIX_INFO2
:
1983 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1985 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1987 if (info_level
== SMB_FIND_FILE_UNIX
) {
1988 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1989 p
= store_file_unix_basic(conn
, p
,
1990 NULL
, &smb_fname
->st
);
1991 len
= srvstr_push(base_data
, flags2
, p
,
1992 fname
, PTR_DIFF(end_data
, p
),
1995 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1996 p
= store_file_unix_basic_info2(conn
, p
,
1997 NULL
, &smb_fname
->st
);
2000 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2001 PTR_DIFF(end_data
, p
), 0);
2002 SIVAL(nameptr
, 0, len
);
2007 len
= PTR_DIFF(p
, pdata
);
2008 pad
= (len
+ (align
-1)) & ~(align
-1);
2010 * offset to the next entry, the caller
2011 * will overwrite it for the last entry
2012 * that's why we always include the padding
2016 * set padding to zero
2019 memset(p
, 0, pad
- len
);
2024 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2032 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2033 *out_of_space
= true;
2034 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2035 return false; /* Not finished - just out of space */
2038 /* Setup the last entry pointer, as an offset from base_data */
2039 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2040 /* Advance the data pointer to the next slot */
2046 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2047 connection_struct
*conn
,
2048 struct dptr_struct
*dirptr
,
2050 const char *path_mask
,
2053 int requires_resume_key
,
2061 int space_remaining
,
2063 bool *got_exact_match
,
2064 int *_last_entry_off
,
2065 struct ea_list
*name_list
)
2068 const char *mask
= NULL
;
2069 long prev_dirpos
= 0;
2072 struct smb_filename
*smb_fname
= NULL
;
2073 struct smbd_dirptr_lanman2_state state
;
2075 uint64_t last_entry_off
= 0;
2079 state
.info_level
= info_level
;
2080 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2081 state
.has_wild
= dptr_has_wild(dirptr
);
2082 state
.got_exact_match
= false;
2084 *out_of_space
= false;
2085 *got_exact_match
= false;
2087 p
= strrchr_m(path_mask
,'/');
2098 ok
= smbd_dirptr_get_entry(ctx
,
2104 smbd_dirptr_lanman2_match_fn
,
2105 smbd_dirptr_lanman2_mode_fn
,
2115 *got_exact_match
= state
.got_exact_match
;
2117 ok
= smbd_marshall_dir_entry(ctx
,
2122 state
.check_mangled_names
,
2123 requires_resume_key
,
2136 TALLOC_FREE(smb_fname
);
2137 if (*out_of_space
) {
2138 dptr_SeekDir(dirptr
, prev_dirpos
);
2145 *_last_entry_off
= last_entry_off
;
2149 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2150 connection_struct
*conn
,
2151 struct dptr_struct
*dirptr
,
2153 const char *path_mask
,
2156 bool requires_resume_key
,
2162 int space_remaining
,
2164 bool *got_exact_match
,
2165 int *last_entry_off
,
2166 struct ea_list
*name_list
)
2169 const bool do_pad
= true;
2171 if (info_level
>= 1 && info_level
<= 3) {
2172 /* No alignment on earlier info levels. */
2176 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2177 path_mask
, dirtype
, info_level
,
2178 requires_resume_key
, dont_descend
, ask_sharemode
,
2180 ppdata
, base_data
, end_data
,
2182 out_of_space
, got_exact_match
,
2183 last_entry_off
, name_list
);
2186 /****************************************************************************
2187 Reply to a TRANS2_FINDFIRST.
2188 ****************************************************************************/
2190 static void call_trans2findfirst(connection_struct
*conn
,
2191 struct smb_request
*req
,
2192 char **pparams
, int total_params
,
2193 char **ppdata
, int total_data
,
2194 unsigned int max_data_bytes
)
2196 /* We must be careful here that we don't return more than the
2197 allowed number of data bytes. If this means returning fewer than
2198 maxentries then so be it. We assume that the redirector has
2199 enough room for the fixed number of parameter bytes it has
2201 struct smb_filename
*smb_dname
= NULL
;
2202 char *params
= *pparams
;
2203 char *pdata
= *ppdata
;
2207 uint16 findfirst_flags
;
2208 bool close_after_first
;
2210 bool requires_resume_key
;
2212 char *directory
= NULL
;
2215 int last_entry_off
=0;
2219 bool finished
= False
;
2220 bool dont_descend
= False
;
2221 bool out_of_space
= False
;
2222 int space_remaining
;
2223 bool mask_contains_wcard
= False
;
2224 struct ea_list
*ea_list
= NULL
;
2225 NTSTATUS ntstatus
= NT_STATUS_OK
;
2226 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2227 TALLOC_CTX
*ctx
= talloc_tos();
2228 struct dptr_struct
*dirptr
= NULL
;
2229 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2230 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2232 if (total_params
< 13) {
2233 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2237 dirtype
= SVAL(params
,0);
2238 maxentries
= SVAL(params
,2);
2239 findfirst_flags
= SVAL(params
,4);
2240 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2241 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2242 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2243 info_level
= SVAL(params
,6);
2245 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2246 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2247 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2248 info_level
, max_data_bytes
));
2251 /* W2K3 seems to treat zero as 1. */
2255 switch (info_level
) {
2256 case SMB_FIND_INFO_STANDARD
:
2257 case SMB_FIND_EA_SIZE
:
2258 case SMB_FIND_EA_LIST
:
2259 case SMB_FIND_FILE_DIRECTORY_INFO
:
2260 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2261 case SMB_FIND_FILE_NAMES_INFO
:
2262 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2263 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2264 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2266 case SMB_FIND_FILE_UNIX
:
2267 case SMB_FIND_FILE_UNIX_INFO2
:
2268 /* Always use filesystem for UNIX mtime query. */
2269 ask_sharemode
= false;
2270 if (!lp_unix_extensions()) {
2271 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2274 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2277 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2281 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2282 params
+12, total_params
- 12,
2283 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2284 if (!NT_STATUS_IS_OK(ntstatus
)) {
2285 reply_nterror(req
, ntstatus
);
2289 ntstatus
= filename_convert(ctx
, conn
,
2290 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2293 &mask_contains_wcard
,
2295 if (!NT_STATUS_IS_OK(ntstatus
)) {
2296 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2297 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2298 ERRSRV
, ERRbadpath
);
2301 reply_nterror(req
, ntstatus
);
2305 mask
= smb_dname
->original_lcomp
;
2307 directory
= smb_dname
->base_name
;
2309 p
= strrchr_m(directory
,'/');
2311 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2312 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2313 mask
= talloc_strdup(ctx
,"*");
2315 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2318 mask_contains_wcard
= True
;
2320 directory
= talloc_strdup(talloc_tos(), "./");
2322 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2329 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2331 if (info_level
== SMB_FIND_EA_LIST
) {
2334 if (total_data
< 4) {
2335 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2339 ea_size
= IVAL(pdata
,0);
2340 if (ea_size
!= total_data
) {
2341 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2342 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2343 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2347 if (!lp_ea_support(SNUM(conn
))) {
2348 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2352 /* Pull out the list of names. */
2353 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2355 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2360 *ppdata
= (char *)SMB_REALLOC(
2361 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2362 if(*ppdata
== NULL
) {
2363 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2367 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2369 /* Realloc the params space */
2370 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2371 if (*pparams
== NULL
) {
2372 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2377 /* Save the wildcard match and attribs we are using on this directory -
2378 needed as lanman2 assumes these are being saved between calls */
2380 ntstatus
= dptr_create(conn
,
2386 mask_contains_wcard
,
2390 if (!NT_STATUS_IS_OK(ntstatus
)) {
2391 reply_nterror(req
, ntstatus
);
2395 dptr_num
= dptr_dnum(dirptr
);
2396 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2398 /* Initialize per TRANS2_FIND_FIRST operation data */
2399 dptr_init_search_op(dirptr
);
2401 /* We don't need to check for VOL here as this is returned by
2402 a different TRANS2 call. */
2404 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2405 directory
,lp_dontdescend(SNUM(conn
))));
2406 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2407 dont_descend
= True
;
2410 space_remaining
= max_data_bytes
;
2411 out_of_space
= False
;
2413 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2414 bool got_exact_match
= False
;
2416 /* this is a heuristic to avoid seeking the dirptr except when
2417 absolutely necessary. It allows for a filename of about 40 chars */
2418 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2419 out_of_space
= True
;
2422 finished
= !get_lanman2_dir_entry(ctx
,
2426 mask
,dirtype
,info_level
,
2427 requires_resume_key
,dont_descend
,
2430 space_remaining
, &out_of_space
,
2432 &last_entry_off
, ea_list
);
2435 if (finished
&& out_of_space
)
2438 if (!finished
&& !out_of_space
)
2442 * As an optimisation if we know we aren't looking
2443 * for a wildcard name (ie. the name matches the wildcard exactly)
2444 * then we can finish on any (first) match.
2445 * This speeds up large directory searches. JRA.
2451 /* Ensure space_remaining never goes -ve. */
2452 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2453 space_remaining
= 0;
2454 out_of_space
= true;
2456 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2460 /* Check if we can close the dirptr */
2461 if(close_after_first
|| (finished
&& close_if_end
)) {
2462 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2463 dptr_close(sconn
, &dptr_num
);
2467 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2468 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2469 * the protocol level is less than NT1. Tested with smbclient. JRA.
2470 * This should fix the OS/2 client bug #2335.
2473 if(numentries
== 0) {
2474 dptr_close(sconn
, &dptr_num
);
2475 if (get_Protocol() < PROTOCOL_NT1
) {
2476 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2479 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2480 ERRDOS
, ERRbadfile
);
2485 /* At this point pdata points to numentries directory entries. */
2487 /* Set up the return parameter block */
2488 SSVAL(params
,0,dptr_num
);
2489 SSVAL(params
,2,numentries
);
2490 SSVAL(params
,4,finished
);
2491 SSVAL(params
,6,0); /* Never an EA error */
2492 SSVAL(params
,8,last_entry_off
);
2494 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2497 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2498 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2504 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2505 smb_fn_name(req
->cmd
),
2506 mask
, directory
, dirtype
, numentries
) );
2509 * Force a name mangle here to ensure that the
2510 * mask as an 8.3 name is top of the mangled cache.
2511 * The reasons for this are subtle. Don't remove
2512 * this code unless you know what you are doing
2513 * (see PR#13758). JRA.
2516 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2517 char mangled_name
[13];
2518 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2521 TALLOC_FREE(smb_dname
);
2525 /****************************************************************************
2526 Reply to a TRANS2_FINDNEXT.
2527 ****************************************************************************/
2529 static void call_trans2findnext(connection_struct
*conn
,
2530 struct smb_request
*req
,
2531 char **pparams
, int total_params
,
2532 char **ppdata
, int total_data
,
2533 unsigned int max_data_bytes
)
2535 /* We must be careful here that we don't return more than the
2536 allowed number of data bytes. If this means returning fewer than
2537 maxentries then so be it. We assume that the redirector has
2538 enough room for the fixed number of parameter bytes it has
2540 char *params
= *pparams
;
2541 char *pdata
= *ppdata
;
2547 uint16 findnext_flags
;
2548 bool close_after_request
;
2550 bool requires_resume_key
;
2552 bool mask_contains_wcard
= False
;
2553 char *resume_name
= NULL
;
2554 const char *mask
= NULL
;
2555 const char *directory
= NULL
;
2559 int i
, last_entry_off
=0;
2560 bool finished
= False
;
2561 bool dont_descend
= False
;
2562 bool out_of_space
= False
;
2563 int space_remaining
;
2564 struct ea_list
*ea_list
= NULL
;
2565 NTSTATUS ntstatus
= NT_STATUS_OK
;
2566 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2567 TALLOC_CTX
*ctx
= talloc_tos();
2568 struct dptr_struct
*dirptr
;
2569 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2571 if (total_params
< 13) {
2572 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2576 dptr_num
= SVAL(params
,0);
2577 maxentries
= SVAL(params
,2);
2578 info_level
= SVAL(params
,4);
2579 resume_key
= IVAL(params
,6);
2580 findnext_flags
= SVAL(params
,10);
2581 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2582 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2583 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2584 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2586 if (!continue_bit
) {
2587 /* We only need resume_name if continue_bit is zero. */
2588 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2590 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2591 &mask_contains_wcard
);
2592 if (!NT_STATUS_IS_OK(ntstatus
)) {
2593 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2594 complain (it thinks we're asking for the directory above the shared
2595 path or an invalid name). Catch this as the resume name is only compared, never used in
2596 a file access. JRA. */
2597 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2598 &resume_name
, params
+12,
2602 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2603 reply_nterror(req
, ntstatus
);
2609 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2610 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2611 resume_key = %d resume name = %s continue=%d level = %d\n",
2612 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2613 requires_resume_key
, resume_key
,
2614 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2617 /* W2K3 seems to treat zero as 1. */
2621 switch (info_level
) {
2622 case SMB_FIND_INFO_STANDARD
:
2623 case SMB_FIND_EA_SIZE
:
2624 case SMB_FIND_EA_LIST
:
2625 case SMB_FIND_FILE_DIRECTORY_INFO
:
2626 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2627 case SMB_FIND_FILE_NAMES_INFO
:
2628 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2629 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2630 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2632 case SMB_FIND_FILE_UNIX
:
2633 case SMB_FIND_FILE_UNIX_INFO2
:
2634 /* Always use filesystem for UNIX mtime query. */
2635 ask_sharemode
= false;
2636 if (!lp_unix_extensions()) {
2637 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2642 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2646 if (info_level
== SMB_FIND_EA_LIST
) {
2649 if (total_data
< 4) {
2650 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2654 ea_size
= IVAL(pdata
,0);
2655 if (ea_size
!= total_data
) {
2656 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2657 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2658 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2662 if (!lp_ea_support(SNUM(conn
))) {
2663 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2667 /* Pull out the list of names. */
2668 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2670 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2675 *ppdata
= (char *)SMB_REALLOC(
2676 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2677 if(*ppdata
== NULL
) {
2678 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2683 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2685 /* Realloc the params space */
2686 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2687 if(*pparams
== NULL
) {
2688 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2694 /* Check that the dptr is valid */
2695 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2696 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2700 directory
= dptr_path(sconn
, dptr_num
);
2702 /* Get the wildcard mask from the dptr */
2703 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2704 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2705 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2711 /* Get the attr mask from the dptr */
2712 dirtype
= dptr_attr(sconn
, dptr_num
);
2714 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2715 dptr_num
, mask
, dirtype
,
2717 dptr_TellDir(dirptr
)));
2719 /* Initialize per TRANS2_FIND_NEXT operation data */
2720 dptr_init_search_op(dirptr
);
2722 /* We don't need to check for VOL here as this is returned by
2723 a different TRANS2 call. */
2725 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2726 directory
,lp_dontdescend(SNUM(conn
))));
2727 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2728 dont_descend
= True
;
2731 space_remaining
= max_data_bytes
;
2732 out_of_space
= False
;
2735 * Seek to the correct position. We no longer use the resume key but
2736 * depend on the last file name instead.
2739 if(!continue_bit
&& resume_name
&& *resume_name
) {
2742 long current_pos
= 0;
2744 * Remember, name_to_8_3 is called by
2745 * get_lanman2_dir_entry(), so the resume name
2746 * could be mangled. Ensure we check the unmangled name.
2749 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2750 char *new_resume_name
= NULL
;
2751 mangle_lookup_name_from_8_3(ctx
,
2755 if (new_resume_name
) {
2756 resume_name
= new_resume_name
;
2761 * Fix for NT redirector problem triggered by resume key indexes
2762 * changing between directory scans. We now return a resume key of 0
2763 * and instead look for the filename to continue from (also given
2764 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2765 * findfirst/findnext (as is usual) then the directory pointer
2766 * should already be at the correct place.
2769 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2770 } /* end if resume_name && !continue_bit */
2772 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2773 bool got_exact_match
= False
;
2775 /* this is a heuristic to avoid seeking the dirptr except when
2776 absolutely necessary. It allows for a filename of about 40 chars */
2777 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2778 out_of_space
= True
;
2781 finished
= !get_lanman2_dir_entry(ctx
,
2785 mask
,dirtype
,info_level
,
2786 requires_resume_key
,dont_descend
,
2789 space_remaining
, &out_of_space
,
2791 &last_entry_off
, ea_list
);
2794 if (finished
&& out_of_space
)
2797 if (!finished
&& !out_of_space
)
2801 * As an optimisation if we know we aren't looking
2802 * for a wildcard name (ie. the name matches the wildcard exactly)
2803 * then we can finish on any (first) match.
2804 * This speeds up large directory searches. JRA.
2810 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2813 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2814 smb_fn_name(req
->cmd
),
2815 mask
, directory
, dirtype
, numentries
) );
2817 /* Check if we can close the dirptr */
2818 if(close_after_request
|| (finished
&& close_if_end
)) {
2819 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2820 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2823 /* Set up the return parameter block */
2824 SSVAL(params
,0,numentries
);
2825 SSVAL(params
,2,finished
);
2826 SSVAL(params
,4,0); /* Never an EA error */
2827 SSVAL(params
,6,last_entry_off
);
2829 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2835 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2837 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2841 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2843 SMB_ASSERT(extended_info
!= NULL
);
2845 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2846 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2847 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2848 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2849 #ifdef SAMBA_VERSION_REVISION
2850 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2852 extended_info
->samba_subversion
= 0;
2853 #ifdef SAMBA_VERSION_RC_RELEASE
2854 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2856 #ifdef SAMBA_VERSION_PRE_RELEASE
2857 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2860 #ifdef SAMBA_VERSION_VENDOR_PATCH
2861 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2863 extended_info
->samba_gitcommitdate
= 0;
2864 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2865 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2868 memset(extended_info
->samba_version_string
, 0,
2869 sizeof(extended_info
->samba_version_string
));
2871 snprintf (extended_info
->samba_version_string
,
2872 sizeof(extended_info
->samba_version_string
),
2873 "%s", samba_version_string());
2876 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2877 TALLOC_CTX
*mem_ctx
,
2878 uint16_t info_level
,
2880 unsigned int max_data_bytes
,
2884 char *pdata
, *end_data
;
2885 int data_len
= 0, len
;
2886 const char *vname
= volume_label(SNUM(conn
));
2887 int snum
= SNUM(conn
);
2888 char *fstype
= lp_fstype(SNUM(conn
));
2889 uint32 additional_flags
= 0;
2890 struct smb_filename smb_fname_dot
;
2894 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2895 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2896 "info level (0x%x) on IPC$.\n",
2897 (unsigned int)info_level
));
2898 return NT_STATUS_ACCESS_DENIED
;
2902 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2904 ZERO_STRUCT(smb_fname_dot
);
2905 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2907 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2908 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2909 return map_nt_error_from_unix(errno
);
2912 st
= smb_fname_dot
.st
;
2914 *ppdata
= (char *)SMB_REALLOC(
2915 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2916 if (*ppdata
== NULL
) {
2917 return NT_STATUS_NO_MEMORY
;
2921 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2922 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2924 switch (info_level
) {
2925 case SMB_INFO_ALLOCATION
:
2927 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2929 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2930 return map_nt_error_from_unix(errno
);
2933 block_size
= lp_block_size(snum
);
2934 if (bsize
< block_size
) {
2935 uint64_t factor
= block_size
/bsize
;
2940 if (bsize
> block_size
) {
2941 uint64_t factor
= bsize
/block_size
;
2946 bytes_per_sector
= 512;
2947 sectors_per_unit
= bsize
/bytes_per_sector
;
2949 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2950 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2951 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2953 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2954 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2955 SIVAL(pdata
,l1_cUnit
,dsize
);
2956 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2957 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2961 case SMB_INFO_VOLUME
:
2962 /* Return volume name */
2964 * Add volume serial number - hash of a combination of
2965 * the called hostname and the service name.
2967 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2969 * Win2k3 and previous mess this up by sending a name length
2970 * one byte short. I believe only older clients (OS/2 Win9x) use
2971 * this call so try fixing this by adding a terminating null to
2972 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2976 pdata
+l2_vol_szVolLabel
, vname
,
2977 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2978 STR_NOALIGN
|STR_TERMINATE
);
2979 SCVAL(pdata
,l2_vol_cch
,len
);
2980 data_len
= l2_vol_szVolLabel
+ len
;
2981 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2982 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2986 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2987 case SMB_FS_ATTRIBUTE_INFORMATION
:
2989 additional_flags
= 0;
2990 #if defined(HAVE_SYS_QUOTAS)
2991 additional_flags
|= FILE_VOLUME_QUOTAS
;
2994 if(lp_nt_acl_support(SNUM(conn
))) {
2995 additional_flags
|= FILE_PERSISTENT_ACLS
;
2998 /* Capabilities are filled in at connection time through STATVFS call */
2999 additional_flags
|= conn
->fs_capabilities
;
3000 additional_flags
|= lp_parm_int(conn
->params
->service
,
3001 "share", "fake_fscaps",
3004 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3005 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3006 additional_flags
); /* FS ATTRIBUTES */
3008 SIVAL(pdata
,4,255); /* Max filename component length */
3009 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3010 and will think we can't do long filenames */
3011 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3012 PTR_DIFF(end_data
, pdata
+12),
3015 data_len
= 12 + len
;
3018 case SMB_QUERY_FS_LABEL_INFO
:
3019 case SMB_FS_LABEL_INFORMATION
:
3020 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3021 PTR_DIFF(end_data
, pdata
+4), 0);
3026 case SMB_QUERY_FS_VOLUME_INFO
:
3027 case SMB_FS_VOLUME_INFORMATION
:
3030 * Add volume serial number - hash of a combination of
3031 * the called hostname and the service name.
3033 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3034 (str_checksum(get_local_machine_name())<<16));
3036 /* Max label len is 32 characters. */
3037 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3038 PTR_DIFF(end_data
, pdata
+18),
3040 SIVAL(pdata
,12,len
);
3043 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3044 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3047 case SMB_QUERY_FS_SIZE_INFO
:
3048 case SMB_FS_SIZE_INFORMATION
:
3050 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3052 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3053 return map_nt_error_from_unix(errno
);
3055 block_size
= lp_block_size(snum
);
3056 if (bsize
< block_size
) {
3057 uint64_t factor
= block_size
/bsize
;
3062 if (bsize
> block_size
) {
3063 uint64_t factor
= bsize
/block_size
;
3068 bytes_per_sector
= 512;
3069 sectors_per_unit
= bsize
/bytes_per_sector
;
3070 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3071 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3072 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3073 SBIG_UINT(pdata
,0,dsize
);
3074 SBIG_UINT(pdata
,8,dfree
);
3075 SIVAL(pdata
,16,sectors_per_unit
);
3076 SIVAL(pdata
,20,bytes_per_sector
);
3080 case SMB_FS_FULL_SIZE_INFORMATION
:
3082 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3084 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno
);
3087 block_size
= lp_block_size(snum
);
3088 if (bsize
< block_size
) {
3089 uint64_t factor
= block_size
/bsize
;
3094 if (bsize
> block_size
) {
3095 uint64_t factor
= bsize
/block_size
;
3100 bytes_per_sector
= 512;
3101 sectors_per_unit
= bsize
/bytes_per_sector
;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3104 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3105 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3106 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3107 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3108 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3109 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3113 case SMB_QUERY_FS_DEVICE_INFO
:
3114 case SMB_FS_DEVICE_INFORMATION
:
3116 SIVAL(pdata
,0,0); /* dev type */
3117 SIVAL(pdata
,4,0); /* characteristics */
3120 #ifdef HAVE_SYS_QUOTAS
3121 case SMB_FS_QUOTA_INFORMATION
:
3123 * what we have to send --metze:
3125 * Unknown1: 24 NULL bytes
3126 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3127 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3128 * Quota Flags: 2 byte :
3129 * Unknown3: 6 NULL bytes
3133 * details for Quota Flags:
3135 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3136 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3137 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3138 * 0x0001 Enable Quotas: enable quota for this fs
3142 /* we need to fake up a fsp here,
3143 * because its not send in this call
3146 SMB_NTQUOTA_STRUCT quotas
;
3149 ZERO_STRUCT(quotas
);
3155 if (conn
->server_info
->utok
.uid
!= sec_initial_uid() &&
3156 !conn
->admin_user
) {
3157 DEBUG(0,("set_user_quota: access_denied "
3158 "service [%s] user [%s]\n",
3159 lp_servicename(SNUM(conn
)),
3160 conn
->server_info
->unix_name
));
3161 return NT_STATUS_ACCESS_DENIED
;
3164 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3165 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3166 return map_nt_error_from_unix(errno
);
3171 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3172 lp_servicename(SNUM(conn
))));
3174 /* Unknown1 24 NULL bytes*/
3175 SBIG_UINT(pdata
,0,(uint64_t)0);
3176 SBIG_UINT(pdata
,8,(uint64_t)0);
3177 SBIG_UINT(pdata
,16,(uint64_t)0);
3179 /* Default Soft Quota 8 bytes */
3180 SBIG_UINT(pdata
,24,quotas
.softlim
);
3182 /* Default Hard Quota 8 bytes */
3183 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3185 /* Quota flag 2 bytes */
3186 SSVAL(pdata
,40,quotas
.qflags
);
3188 /* Unknown3 6 NULL bytes */
3194 #endif /* HAVE_SYS_QUOTAS */
3195 case SMB_FS_OBJECTID_INFORMATION
:
3197 unsigned char objid
[16];
3198 struct smb_extended_info extended_info
;
3199 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3200 samba_extended_info_version (&extended_info
);
3201 SIVAL(pdata
,16,extended_info
.samba_magic
);
3202 SIVAL(pdata
,20,extended_info
.samba_version
);
3203 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3204 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3205 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3211 * Query the version and capabilities of the CIFS UNIX extensions
3215 case SMB_QUERY_CIFS_UNIX_INFO
:
3217 bool large_write
= lp_min_receive_file_size() &&
3218 !srv_is_signing_active(smbd_server_conn
);
3219 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3220 int encrypt_caps
= 0;
3222 if (!lp_unix_extensions()) {
3223 return NT_STATUS_INVALID_LEVEL
;
3226 switch (conn
->encrypt_level
) {
3232 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3235 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3236 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3237 large_write
= false;
3243 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3244 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3246 /* We have POSIX ACLs, pathname, encryption,
3247 * large read/write, and locking capability. */
3249 SBIG_UINT(pdata
,4,((uint64_t)(
3250 CIFS_UNIX_POSIX_ACLS_CAP
|
3251 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3252 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3253 CIFS_UNIX_EXTATTR_CAP
|
3254 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3256 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3258 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3262 case SMB_QUERY_POSIX_FS_INFO
:
3265 vfs_statvfs_struct svfs
;
3267 if (!lp_unix_extensions()) {
3268 return NT_STATUS_INVALID_LEVEL
;
3271 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3275 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3276 SIVAL(pdata
,4,svfs
.BlockSize
);
3277 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3278 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3279 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3280 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3281 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3282 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3283 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3285 } else if (rc
== EOPNOTSUPP
) {
3286 return NT_STATUS_INVALID_LEVEL
;
3287 #endif /* EOPNOTSUPP */
3289 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3290 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3295 case SMB_QUERY_POSIX_WHOAMI
:
3301 if (!lp_unix_extensions()) {
3302 return NT_STATUS_INVALID_LEVEL
;
3305 if (max_data_bytes
< 40) {
3306 return NT_STATUS_BUFFER_TOO_SMALL
;
3309 /* We ARE guest if global_sid_Builtin_Guests is
3310 * in our list of SIDs.
3312 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3313 conn
->server_info
->ptok
)) {
3314 flags
|= SMB_WHOAMI_GUEST
;
3317 /* We are NOT guest if global_sid_Authenticated_Users
3318 * is in our list of SIDs.
3320 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3321 conn
->server_info
->ptok
)) {
3322 flags
&= ~SMB_WHOAMI_GUEST
;
3325 /* NOTE: 8 bytes for UID/GID, irrespective of native
3326 * platform size. This matches
3327 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3329 data_len
= 4 /* flags */
3336 + 4 /* pad/reserved */
3337 + (conn
->server_info
->utok
.ngroups
* 8)
3339 + (conn
->server_info
->ptok
->num_sids
*
3343 SIVAL(pdata
, 0, flags
);
3344 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3346 (uint64_t)conn
->server_info
->utok
.uid
);
3347 SBIG_UINT(pdata
, 16,
3348 (uint64_t)conn
->server_info
->utok
.gid
);
3351 if (data_len
>= max_data_bytes
) {
3352 /* Potential overflow, skip the GIDs and SIDs. */
3354 SIVAL(pdata
, 24, 0); /* num_groups */
3355 SIVAL(pdata
, 28, 0); /* num_sids */
3356 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3357 SIVAL(pdata
, 36, 0); /* reserved */
3363 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3364 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3366 /* We walk the SID list twice, but this call is fairly
3367 * infrequent, and I don't expect that it's performance
3368 * sensitive -- jpeach
3370 for (i
= 0, sid_bytes
= 0;
3371 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3372 sid_bytes
+= ndr_size_dom_sid(
3373 &conn
->server_info
->ptok
->user_sids
[i
],
3378 /* SID list byte count */
3379 SIVAL(pdata
, 32, sid_bytes
);
3381 /* 4 bytes pad/reserved - must be zero */
3382 SIVAL(pdata
, 36, 0);
3386 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3387 SBIG_UINT(pdata
, data_len
,
3388 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3394 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3395 int sid_len
= ndr_size_dom_sid(
3396 &conn
->server_info
->ptok
->user_sids
[i
],
3400 sid_linearize(pdata
+ data_len
, sid_len
,
3401 &conn
->server_info
->ptok
->user_sids
[i
]);
3402 data_len
+= sid_len
;
3408 case SMB_MAC_QUERY_FS_INFO
:
3410 * Thursby MAC extension... ONLY on NTFS filesystems
3411 * once we do streams then we don't need this
3413 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3415 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3420 return NT_STATUS_INVALID_LEVEL
;
3423 *ret_data_len
= data_len
;
3424 return NT_STATUS_OK
;
3427 /****************************************************************************
3428 Reply to a TRANS2_QFSINFO (query filesystem info).
3429 ****************************************************************************/
3431 static void call_trans2qfsinfo(connection_struct
*conn
,
3432 struct smb_request
*req
,
3433 char **pparams
, int total_params
,
3434 char **ppdata
, int total_data
,
3435 unsigned int max_data_bytes
)
3437 char *params
= *pparams
;
3438 uint16_t info_level
;
3442 if (total_params
< 2) {
3443 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3447 info_level
= SVAL(params
,0);
3449 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3450 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3451 DEBUG(0,("call_trans2qfsinfo: encryption required "
3452 "and info level 0x%x sent.\n",
3453 (unsigned int)info_level
));
3454 exit_server_cleanly("encryption required "
3460 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3462 status
= smbd_do_qfsinfo(conn
, req
,
3467 if (!NT_STATUS_IS_OK(status
)) {
3468 reply_nterror(req
, status
);
3472 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3475 DEBUG( 4, ( "%s info_level = %d\n",
3476 smb_fn_name(req
->cmd
), info_level
) );
3481 /****************************************************************************
3482 Reply to a TRANS2_SETFSINFO (set filesystem info).
3483 ****************************************************************************/
3485 static void call_trans2setfsinfo(connection_struct
*conn
,
3486 struct smb_request
*req
,
3487 char **pparams
, int total_params
,
3488 char **ppdata
, int total_data
,
3489 unsigned int max_data_bytes
)
3491 char *pdata
= *ppdata
;
3492 char *params
= *pparams
;
3495 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3498 if (total_params
< 4) {
3499 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3505 info_level
= SVAL(params
,2);
3508 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3509 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3510 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3511 "info level (0x%x) on IPC$.\n",
3512 (unsigned int)info_level
));
3513 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3518 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3519 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3520 DEBUG(0,("call_trans2setfsinfo: encryption required "
3521 "and info level 0x%x sent.\n",
3522 (unsigned int)info_level
));
3523 exit_server_cleanly("encryption required "
3529 switch(info_level
) {
3530 case SMB_SET_CIFS_UNIX_INFO
:
3532 uint16 client_unix_major
;
3533 uint16 client_unix_minor
;
3534 uint32 client_unix_cap_low
;
3535 uint32 client_unix_cap_high
;
3537 if (!lp_unix_extensions()) {
3539 NT_STATUS_INVALID_LEVEL
);
3543 /* There should be 12 bytes of capabilities set. */
3544 if (total_data
< 8) {
3547 NT_STATUS_INVALID_PARAMETER
);
3550 client_unix_major
= SVAL(pdata
,0);
3551 client_unix_minor
= SVAL(pdata
,2);
3552 client_unix_cap_low
= IVAL(pdata
,4);
3553 client_unix_cap_high
= IVAL(pdata
,8);
3554 /* Just print these values for now. */
3555 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3556 cap_low = 0x%x, cap_high = 0x%x\n",
3557 (unsigned int)client_unix_major
,
3558 (unsigned int)client_unix_minor
,
3559 (unsigned int)client_unix_cap_low
,
3560 (unsigned int)client_unix_cap_high
));
3562 /* Here is where we must switch to posix pathname processing... */
3563 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3564 lp_set_posix_pathnames();
3565 mangle_change_to_posix();
3568 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3569 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3570 /* Client that knows how to do posix locks,
3571 * but not posix open/mkdir operations. Set a
3572 * default type for read/write checks. */
3574 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3580 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3583 size_t param_len
= 0;
3584 size_t data_len
= total_data
;
3586 if (!lp_unix_extensions()) {
3589 NT_STATUS_INVALID_LEVEL
);
3593 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3596 NT_STATUS_NOT_SUPPORTED
);
3600 DEBUG( 4,("call_trans2setfsinfo: "
3601 "request transport encryption.\n"));
3603 status
= srv_request_encryption_setup(conn
,
3604 (unsigned char **)ppdata
,
3606 (unsigned char **)pparams
,
3609 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3610 !NT_STATUS_IS_OK(status
)) {
3611 reply_nterror(req
, status
);
3615 send_trans2_replies(conn
, req
,
3622 if (NT_STATUS_IS_OK(status
)) {
3623 /* Server-side transport
3624 * encryption is now *on*. */
3625 status
= srv_encryption_start(conn
);
3626 if (!NT_STATUS_IS_OK(status
)) {
3627 exit_server_cleanly(
3628 "Failure in setting "
3629 "up encrypted transport");
3635 case SMB_FS_QUOTA_INFORMATION
:
3637 files_struct
*fsp
= NULL
;
3638 SMB_NTQUOTA_STRUCT quotas
;
3640 ZERO_STRUCT(quotas
);
3643 if (((conn
->server_info
->utok
.uid
!= sec_initial_uid()) && !conn
->admin_user
)
3644 ||!CAN_WRITE(conn
)) {
3645 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3646 lp_servicename(SNUM(conn
)),
3647 conn
->server_info
->unix_name
));
3648 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3652 /* note: normaly there're 48 bytes,
3653 * but we didn't use the last 6 bytes for now
3656 fsp
= file_fsp(req
, SVAL(params
,0));
3658 if (!check_fsp_ntquota_handle(conn
, req
,
3660 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3662 req
, NT_STATUS_INVALID_HANDLE
);
3666 if (total_data
< 42) {
3667 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3671 NT_STATUS_INVALID_PARAMETER
);
3675 /* unknown_1 24 NULL bytes in pdata*/
3677 /* the soft quotas 8 bytes (uint64_t)*/
3678 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3679 #ifdef LARGE_SMB_OFF_T
3680 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3681 #else /* LARGE_SMB_OFF_T */
3682 if ((IVAL(pdata
,28) != 0)&&
3683 ((quotas
.softlim
!= 0xFFFFFFFF)||
3684 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3685 /* more than 32 bits? */
3688 NT_STATUS_INVALID_PARAMETER
);
3691 #endif /* LARGE_SMB_OFF_T */
3693 /* the hard quotas 8 bytes (uint64_t)*/
3694 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3695 #ifdef LARGE_SMB_OFF_T
3696 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3697 #else /* LARGE_SMB_OFF_T */
3698 if ((IVAL(pdata
,36) != 0)&&
3699 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3700 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3701 /* more than 32 bits? */
3704 NT_STATUS_INVALID_PARAMETER
);
3707 #endif /* LARGE_SMB_OFF_T */
3709 /* quota_flags 2 bytes **/
3710 quotas
.qflags
= SVAL(pdata
,40);
3712 /* unknown_2 6 NULL bytes follow*/
3714 /* now set the quotas */
3715 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3716 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3717 reply_nterror(req
, map_nt_error_from_unix(errno
));
3724 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3726 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3732 * sending this reply works fine,
3733 * but I'm not sure it's the same
3734 * like windows do...
3737 reply_outbuf(req
, 10, 0);
3740 #if defined(HAVE_POSIX_ACLS)
3741 /****************************************************************************
3742 Utility function to count the number of entries in a POSIX acl.
3743 ****************************************************************************/
3745 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3747 unsigned int ace_count
= 0;
3748 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3749 SMB_ACL_ENTRY_T entry
;
3751 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3753 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3754 entry_id
= SMB_ACL_NEXT_ENTRY
;
3761 /****************************************************************************
3762 Utility function to marshall a POSIX acl into wire format.
3763 ****************************************************************************/
3765 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3767 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3768 SMB_ACL_ENTRY_T entry
;
3770 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3771 SMB_ACL_TAG_T tagtype
;
3772 SMB_ACL_PERMSET_T permset
;
3773 unsigned char perms
= 0;
3774 unsigned int own_grp
;
3777 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3778 entry_id
= SMB_ACL_NEXT_ENTRY
;
3781 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3782 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3786 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3787 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3791 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3792 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3793 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3795 SCVAL(pdata
,1,perms
);
3798 case SMB_ACL_USER_OBJ
:
3799 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3800 own_grp
= (unsigned int)pst
->st_ex_uid
;
3801 SIVAL(pdata
,2,own_grp
);
3806 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3808 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3811 own_grp
= (unsigned int)*puid
;
3812 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3813 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3814 SIVAL(pdata
,2,own_grp
);
3818 case SMB_ACL_GROUP_OBJ
:
3819 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3820 own_grp
= (unsigned int)pst
->st_ex_gid
;
3821 SIVAL(pdata
,2,own_grp
);
3826 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3828 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3831 own_grp
= (unsigned int)*pgid
;
3832 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3833 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3834 SIVAL(pdata
,2,own_grp
);
3839 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3840 SIVAL(pdata
,2,0xFFFFFFFF);
3841 SIVAL(pdata
,6,0xFFFFFFFF);
3844 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3845 SIVAL(pdata
,2,0xFFFFFFFF);
3846 SIVAL(pdata
,6,0xFFFFFFFF);
3849 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3852 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3859 /****************************************************************************
3860 Store the FILE_UNIX_BASIC info.
3861 ****************************************************************************/
3863 static char *store_file_unix_basic(connection_struct
*conn
,
3866 const SMB_STRUCT_STAT
*psbuf
)
3868 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3870 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3871 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3873 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3876 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3879 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3880 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3881 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3884 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3888 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3892 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3895 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3899 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3903 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3906 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3910 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3917 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3918 * the chflags(2) (or equivalent) flags.
3920 * XXX: this really should be behind the VFS interface. To do this, we would
3921 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3922 * Each VFS module could then implement its own mapping as appropriate for the
3923 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3925 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3929 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3933 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3937 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3941 { UF_HIDDEN
, EXT_HIDDEN
},
3944 /* Do not remove. We need to guarantee that this array has at least one
3945 * entry to build on HP-UX.
3951 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3952 uint32
*smb_fflags
, uint32
*smb_fmask
)
3956 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3957 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3958 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3959 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3964 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3965 const uint32 smb_fflags
,
3966 const uint32 smb_fmask
,
3969 uint32 max_fmask
= 0;
3972 *stat_fflags
= psbuf
->st_ex_flags
;
3974 /* For each flags requested in smb_fmask, check the state of the
3975 * corresponding flag in smb_fflags and set or clear the matching
3979 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3980 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3981 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3982 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3983 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3985 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3990 /* If smb_fmask is asking to set any bits that are not supported by
3991 * our flag mappings, we should fail.
3993 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4001 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4002 * of file flags and birth (create) time.
4004 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4007 const SMB_STRUCT_STAT
*psbuf
)
4009 uint32 file_flags
= 0;
4010 uint32 flags_mask
= 0;
4012 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4014 /* Create (birth) time 64 bit */
4015 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4018 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4019 SIVAL(pdata
, 0, file_flags
); /* flags */
4020 SIVAL(pdata
, 4, flags_mask
); /* mask */
4026 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4027 const struct stream_struct
*streams
,
4029 unsigned int max_data_bytes
,
4030 unsigned int *data_size
)
4033 unsigned int ofs
= 0;
4035 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4036 unsigned int next_offset
;
4038 smb_ucs2_t
*namebuf
;
4040 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4041 streams
[i
].name
, &namelen
) ||
4044 return NT_STATUS_INVALID_PARAMETER
;
4048 * name_buf is now null-terminated, we need to marshall as not
4054 SIVAL(data
, ofs
+4, namelen
);
4055 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4056 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4057 memcpy(data
+ofs
+24, namebuf
, namelen
);
4058 TALLOC_FREE(namebuf
);
4060 next_offset
= ofs
+ 24 + namelen
;
4062 if (i
== num_streams
-1) {
4063 SIVAL(data
, ofs
, 0);
4066 unsigned int align
= ndr_align_size(next_offset
, 8);
4068 memset(data
+next_offset
, 0, align
);
4069 next_offset
+= align
;
4071 SIVAL(data
, ofs
, next_offset
- ofs
);
4080 return NT_STATUS_OK
;
4083 /****************************************************************************
4084 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4085 ****************************************************************************/
4087 static void call_trans2qpipeinfo(connection_struct
*conn
,
4088 struct smb_request
*req
,
4089 unsigned int tran_call
,
4090 char **pparams
, int total_params
,
4091 char **ppdata
, int total_data
,
4092 unsigned int max_data_bytes
)
4094 char *params
= *pparams
;
4095 char *pdata
= *ppdata
;
4096 unsigned int data_size
= 0;
4097 unsigned int param_size
= 2;
4102 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4106 if (total_params
< 4) {
4107 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4111 fsp
= file_fsp(req
, SVAL(params
,0));
4112 if (!fsp_is_np(fsp
)) {
4113 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4117 info_level
= SVAL(params
,2);
4119 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4120 if (*pparams
== NULL
) {
4121 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4126 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4127 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4128 if (*ppdata
== NULL
) {
4129 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4134 switch (info_level
) {
4135 case SMB_FILE_STANDARD_INFORMATION
:
4137 SOFF_T(pdata
,0,4096LL);
4144 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4148 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4154 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4155 TALLOC_CTX
*mem_ctx
,
4156 uint16_t info_level
,
4158 struct smb_filename
*smb_fname
,
4159 bool delete_pending
,
4160 struct timespec write_time_ts
,
4162 struct ea_list
*ea_list
,
4163 int lock_data_count
,
4166 unsigned int max_data_bytes
,
4168 unsigned int *pdata_size
)
4170 char *pdata
= *ppdata
;
4171 char *dstart
, *dend
;
4172 unsigned int data_size
;
4173 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4174 time_t create_time
, mtime
, atime
, c_time
;
4175 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4182 uint64_t file_size
= 0;
4184 uint64_t allocation_size
= 0;
4185 uint64_t file_index
= 0;
4186 uint32_t access_mask
= 0;
4188 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4189 return NT_STATUS_INVALID_LEVEL
;
4192 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4193 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4194 info_level
, max_data_bytes
));
4197 mode
= dos_mode_msdfs(conn
, smb_fname
);
4199 mode
= dos_mode(conn
, smb_fname
);
4202 nlink
= psbuf
->st_ex_nlink
;
4204 if (nlink
&& (mode
&aDIR
)) {
4208 if ((nlink
> 0) && delete_pending
) {
4212 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4213 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4214 if (*ppdata
== NULL
) {
4215 return NT_STATUS_NO_MEMORY
;
4219 dend
= dstart
+ data_size
- 1;
4221 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4222 update_stat_ex_mtime(psbuf
, write_time_ts
);
4225 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4226 mtime_ts
= psbuf
->st_ex_mtime
;
4227 atime_ts
= psbuf
->st_ex_atime
;
4228 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4230 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4231 dos_filetime_timespec(&create_time_ts
);
4232 dos_filetime_timespec(&mtime_ts
);
4233 dos_filetime_timespec(&atime_ts
);
4234 dos_filetime_timespec(&ctime_ts
);
4237 create_time
= convert_timespec_to_time_t(create_time_ts
);
4238 mtime
= convert_timespec_to_time_t(mtime_ts
);
4239 atime
= convert_timespec_to_time_t(atime_ts
);
4240 c_time
= convert_timespec_to_time_t(ctime_ts
);
4242 p
= strrchr_m(smb_fname
->base_name
,'/');
4244 base_name
= smb_fname
->base_name
;
4248 /* NT expects the name to be in an exact form of the *full*
4249 filename. See the trans2 torture test */
4250 if (ISDOT(base_name
)) {
4251 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4253 return NT_STATUS_NO_MEMORY
;
4256 dos_fname
= talloc_asprintf(mem_ctx
,
4258 smb_fname
->base_name
);
4260 return NT_STATUS_NO_MEMORY
;
4262 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4263 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4264 smb_fname
->stream_name
);
4266 return NT_STATUS_NO_MEMORY
;
4270 string_replace(dos_fname
, '/', '\\');
4273 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4276 /* Do we have this path open ? */
4278 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4279 fsp1
= file_find_di_first(fileid
);
4280 if (fsp1
&& fsp1
->initial_allocation_size
) {
4281 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4285 if (!(mode
& aDIR
)) {
4286 file_size
= get_file_size_stat(psbuf
);
4290 pos
= fsp
->fh
->position_information
;
4294 access_mask
= fsp
->access_mask
;
4296 /* GENERIC_EXECUTE mapping from Windows */
4297 access_mask
= 0x12019F;
4300 /* This should be an index number - looks like
4303 I think this causes us to fail the IFSKIT
4304 BasicFileInformationTest. -tpot */
4305 file_index
= get_FileIndex(conn
, psbuf
);
4307 switch (info_level
) {
4308 case SMB_INFO_STANDARD
:
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4311 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4312 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4313 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4314 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4315 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4316 SSVAL(pdata
,l1_attrFile
,mode
);
4319 case SMB_INFO_QUERY_EA_SIZE
:
4321 unsigned int ea_size
=
4322 estimate_ea_size(conn
, fsp
,
4323 smb_fname
->base_name
);
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4326 srv_put_dos_date2(pdata
,0,create_time
);
4327 srv_put_dos_date2(pdata
,4,atime
);
4328 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4329 SIVAL(pdata
,12,(uint32
)file_size
);
4330 SIVAL(pdata
,16,(uint32
)allocation_size
);
4331 SSVAL(pdata
,20,mode
);
4332 SIVAL(pdata
,22,ea_size
);
4336 case SMB_INFO_IS_NAME_VALID
:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4339 /* os/2 needs this ? really ?*/
4340 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4342 /* This is only reached for qpathinfo */
4346 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4348 size_t total_ea_len
= 0;
4349 struct ea_list
*ea_file_list
= NULL
;
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4354 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4355 smb_fname
->base_name
,
4357 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4359 if (!ea_list
|| (total_ea_len
> data_size
)) {
4361 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4365 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4369 case SMB_INFO_QUERY_ALL_EAS
:
4371 /* We have data_size bytes to put EA's into. */
4372 size_t total_ea_len
= 0;
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4376 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4377 smb_fname
->base_name
,
4379 if (!ea_list
|| (total_ea_len
> data_size
)) {
4381 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4385 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4389 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4391 /* This is FileFullEaInformation - 0xF which maps to
4392 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4394 /* We have data_size bytes to put EA's into. */
4395 size_t total_ea_len
= 0;
4396 struct ea_list
*ea_file_list
= NULL
;
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4400 /*TODO: add filtering and index handling */
4403 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4404 smb_fname
->base_name
,
4406 if (!ea_file_list
) {
4407 return NT_STATUS_NO_EAS_ON_FILE
;
4410 status
= fill_ea_chained_buffer(mem_ctx
,
4414 conn
, ea_file_list
);
4415 if (!NT_STATUS_IS_OK(status
)) {
4421 case SMB_FILE_BASIC_INFORMATION
:
4422 case SMB_QUERY_FILE_BASIC_INFO
:
4424 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4426 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4432 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4433 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4434 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4435 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4436 SIVAL(pdata
,32,mode
);
4438 DEBUG(5,("SMB_QFBI - "));
4439 DEBUG(5,("create: %s ", ctime(&create_time
)));
4440 DEBUG(5,("access: %s ", ctime(&atime
)));
4441 DEBUG(5,("write: %s ", ctime(&mtime
)));
4442 DEBUG(5,("change: %s ", ctime(&c_time
)));
4443 DEBUG(5,("mode: %x\n", mode
));
4446 case SMB_FILE_STANDARD_INFORMATION
:
4447 case SMB_QUERY_FILE_STANDARD_INFO
:
4449 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4451 SOFF_T(pdata
,0,allocation_size
);
4452 SOFF_T(pdata
,8,file_size
);
4453 SIVAL(pdata
,16,nlink
);
4454 SCVAL(pdata
,20,delete_pending
?1:0);
4455 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4456 SSVAL(pdata
,22,0); /* Padding. */
4459 case SMB_FILE_EA_INFORMATION
:
4460 case SMB_QUERY_FILE_EA_INFO
:
4462 unsigned int ea_size
=
4463 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4466 SIVAL(pdata
,0,ea_size
);
4470 /* Get the 8.3 name - used if NT SMB was negotiated. */
4471 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4472 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4475 char mangled_name
[13];
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4477 if (!name_to_8_3(base_name
,mangled_name
,
4478 True
,conn
->params
)) {
4479 return NT_STATUS_NO_MEMORY
;
4481 len
= srvstr_push(dstart
, flags2
,
4482 pdata
+4, mangled_name
,
4483 PTR_DIFF(dend
, pdata
+4),
4485 data_size
= 4 + len
;
4490 case SMB_QUERY_FILE_NAME_INFO
:
4494 this must be *exactly* right for ACLs on mapped drives to work
4496 len
= srvstr_push(dstart
, flags2
,
4498 PTR_DIFF(dend
, pdata
+4),
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4501 data_size
= 4 + len
;
4506 case SMB_FILE_ALLOCATION_INFORMATION
:
4507 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4510 SOFF_T(pdata
,0,allocation_size
);
4513 case SMB_FILE_END_OF_FILE_INFORMATION
:
4514 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4517 SOFF_T(pdata
,0,file_size
);
4520 case SMB_QUERY_FILE_ALL_INFO
:
4521 case SMB_FILE_ALL_INFORMATION
:
4524 unsigned int ea_size
=
4525 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4527 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4528 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4529 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4530 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4531 SIVAL(pdata
,32,mode
);
4532 SIVAL(pdata
,36,0); /* padding. */
4534 SOFF_T(pdata
,0,allocation_size
);
4535 SOFF_T(pdata
,8,file_size
);
4536 SIVAL(pdata
,16,nlink
);
4537 SCVAL(pdata
,20,delete_pending
);
4538 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4541 SIVAL(pdata
,0,ea_size
);
4542 pdata
+= 4; /* EA info */
4543 len
= srvstr_push(dstart
, flags2
,
4545 PTR_DIFF(dend
, pdata
+4),
4549 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4553 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4556 unsigned int ea_size
=
4557 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4559 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4560 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4561 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4562 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4563 SIVAL(pdata
, 0x20, mode
);
4564 SIVAL(pdata
, 0x24, 0); /* padding. */
4565 SBVAL(pdata
, 0x28, allocation_size
);
4566 SBVAL(pdata
, 0x30, file_size
);
4567 SIVAL(pdata
, 0x38, nlink
);
4568 SCVAL(pdata
, 0x3C, delete_pending
);
4569 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4570 SSVAL(pdata
, 0x3E, 0); /* padding */
4571 SBVAL(pdata
, 0x40, file_index
);
4572 SIVAL(pdata
, 0x48, ea_size
);
4573 SIVAL(pdata
, 0x4C, access_mask
);
4574 SBVAL(pdata
, 0x50, pos
);
4575 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4576 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4580 len
= srvstr_push(dstart
, flags2
,
4582 PTR_DIFF(dend
, pdata
+4),
4586 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4589 case SMB_FILE_INTERNAL_INFORMATION
:
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4592 SBVAL(pdata
, 0, file_index
);
4596 case SMB_FILE_ACCESS_INFORMATION
:
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4598 SIVAL(pdata
, 0, access_mask
);
4602 case SMB_FILE_NAME_INFORMATION
:
4603 /* Pathname with leading '\'. */
4606 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4608 SIVAL(pdata
,0,byte_len
);
4609 data_size
= 4 + byte_len
;
4613 case SMB_FILE_DISPOSITION_INFORMATION
:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4616 SCVAL(pdata
,0,delete_pending
);
4619 case SMB_FILE_POSITION_INFORMATION
:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4622 SOFF_T(pdata
,0,pos
);
4625 case SMB_FILE_MODE_INFORMATION
:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4627 SIVAL(pdata
,0,mode
);
4631 case SMB_FILE_ALIGNMENT_INFORMATION
:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4633 SIVAL(pdata
,0,0); /* No alignment needed. */
4638 * NT4 server just returns "invalid query" to this - if we try
4639 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4642 /* The first statement above is false - verified using Thursby
4643 * client against NT4 -- gcolley.
4645 case SMB_QUERY_FILE_STREAM_INFO
:
4646 case SMB_FILE_STREAM_INFORMATION
: {
4647 unsigned int num_streams
;
4648 struct stream_struct
*streams
;
4650 DEBUG(10,("smbd_do_qfilepathinfo: "
4651 "SMB_FILE_STREAM_INFORMATION\n"));
4653 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4654 return NT_STATUS_INVALID_PARAMETER
;
4657 status
= SMB_VFS_STREAMINFO(
4658 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4659 &num_streams
, &streams
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4662 DEBUG(10, ("could not get stream info: %s\n",
4663 nt_errstr(status
)));
4667 status
= marshall_stream_info(num_streams
, streams
,
4668 pdata
, max_data_bytes
,
4671 if (!NT_STATUS_IS_OK(status
)) {
4672 DEBUG(10, ("marshall_stream_info failed: %s\n",
4673 nt_errstr(status
)));
4677 TALLOC_FREE(streams
);
4681 case SMB_QUERY_COMPRESSION_INFO
:
4682 case SMB_FILE_COMPRESSION_INFORMATION
:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4684 SOFF_T(pdata
,0,file_size
);
4685 SIVAL(pdata
,8,0); /* ??? */
4686 SIVAL(pdata
,12,0); /* ??? */
4690 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4692 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4693 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4694 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4695 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4696 SOFF_T(pdata
,32,allocation_size
);
4697 SOFF_T(pdata
,40,file_size
);
4698 SIVAL(pdata
,48,mode
);
4699 SIVAL(pdata
,52,0); /* ??? */
4703 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4705 SIVAL(pdata
,0,mode
);
4711 * CIFS UNIX Extensions.
4714 case SMB_QUERY_FILE_UNIX_BASIC
:
4716 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4717 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4721 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4723 for (i
=0; i
<100; i
++)
4724 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4730 case SMB_QUERY_FILE_UNIX_INFO2
:
4732 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4733 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4737 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4739 for (i
=0; i
<100; i
++)
4740 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4746 case SMB_QUERY_FILE_UNIX_LINK
:
4749 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4752 return NT_STATUS_NO_MEMORY
;
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4757 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4758 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4761 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4763 len
= SMB_VFS_READLINK(conn
,
4764 smb_fname
->base_name
,
4767 return map_nt_error_from_unix(errno
);
4770 len
= srvstr_push(dstart
, flags2
,
4772 PTR_DIFF(dend
, pdata
),
4775 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4780 #if defined(HAVE_POSIX_ACLS)
4781 case SMB_QUERY_POSIX_ACL
:
4783 SMB_ACL_T file_acl
= NULL
;
4784 SMB_ACL_T def_acl
= NULL
;
4785 uint16 num_file_acls
= 0;
4786 uint16 num_def_acls
= 0;
4788 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4789 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4792 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4793 smb_fname
->base_name
,
4794 SMB_ACL_TYPE_ACCESS
);
4797 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4798 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4799 "not implemented on "
4800 "filesystem containing %s\n",
4801 smb_fname
->base_name
));
4802 return NT_STATUS_NOT_IMPLEMENTED
;
4805 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4806 if (fsp
&& fsp
->is_directory
) {
4808 SMB_VFS_SYS_ACL_GET_FILE(
4810 fsp
->fsp_name
->base_name
,
4811 SMB_ACL_TYPE_DEFAULT
);
4814 SMB_VFS_SYS_ACL_GET_FILE(
4816 smb_fname
->base_name
,
4817 SMB_ACL_TYPE_DEFAULT
);
4819 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4822 num_file_acls
= count_acl_entries(conn
, file_acl
);
4823 num_def_acls
= count_acl_entries(conn
, def_acl
);
4825 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4826 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4828 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4829 SMB_POSIX_ACL_HEADER_SIZE
) ));
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4836 return NT_STATUS_BUFFER_TOO_SMALL
;
4839 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4840 SSVAL(pdata
,2,num_file_acls
);
4841 SSVAL(pdata
,4,num_def_acls
);
4842 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4849 return NT_STATUS_INTERNAL_ERROR
;
4851 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4858 return NT_STATUS_INTERNAL_ERROR
;
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4867 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4873 case SMB_QUERY_POSIX_LOCK
:
4878 enum brl_type lock_type
;
4880 /* We need an open file with a real fd for this. */
4881 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4882 return NT_STATUS_INVALID_LEVEL
;
4885 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4886 return NT_STATUS_INVALID_PARAMETER
;
4889 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4890 case POSIX_LOCK_TYPE_READ
:
4891 lock_type
= READ_LOCK
;
4893 case POSIX_LOCK_TYPE_WRITE
:
4894 lock_type
= WRITE_LOCK
;
4896 case POSIX_LOCK_TYPE_UNLOCK
:
4898 /* There's no point in asking for an unlock... */
4899 return NT_STATUS_INVALID_PARAMETER
;
4902 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4903 #if defined(HAVE_LONGLONG)
4904 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4905 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4906 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4907 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4908 #else /* HAVE_LONGLONG */
4909 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4910 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4911 #endif /* HAVE_LONGLONG */
4913 status
= query_lock(fsp
,
4920 if (ERROR_WAS_LOCK_DENIED(status
)) {
4921 /* Here we need to report who has it locked... */
4922 data_size
= POSIX_LOCK_DATA_SIZE
;
4924 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4925 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4926 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4927 #if defined(HAVE_LONGLONG)
4928 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4929 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4930 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4931 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4932 #else /* HAVE_LONGLONG */
4933 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4934 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4935 #endif /* HAVE_LONGLONG */
4937 } else if (NT_STATUS_IS_OK(status
)) {
4938 /* For success we just return a copy of what we sent
4939 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4940 data_size
= POSIX_LOCK_DATA_SIZE
;
4941 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4942 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4950 return NT_STATUS_INVALID_LEVEL
;
4953 *pdata_size
= data_size
;
4954 return NT_STATUS_OK
;
4957 /****************************************************************************
4958 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4959 file name or file id).
4960 ****************************************************************************/
4962 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4963 struct smb_request
*req
,
4964 unsigned int tran_call
,
4965 char **pparams
, int total_params
,
4966 char **ppdata
, int total_data
,
4967 unsigned int max_data_bytes
)
4969 char *params
= *pparams
;
4970 char *pdata
= *ppdata
;
4972 unsigned int data_size
= 0;
4973 unsigned int param_size
= 2;
4974 struct smb_filename
*smb_fname
= NULL
;
4975 bool delete_pending
= False
;
4976 struct timespec write_time_ts
;
4977 files_struct
*fsp
= NULL
;
4978 struct file_id fileid
;
4979 struct ea_list
*ea_list
= NULL
;
4980 int lock_data_count
= 0;
4981 char *lock_data
= NULL
;
4982 bool ms_dfs_link
= false;
4983 NTSTATUS status
= NT_STATUS_OK
;
4986 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4990 ZERO_STRUCT(write_time_ts
);
4992 if (tran_call
== TRANSACT2_QFILEINFO
) {
4993 if (total_params
< 4) {
4994 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4999 call_trans2qpipeinfo(conn
, req
, tran_call
,
5000 pparams
, total_params
,
5006 fsp
= file_fsp(req
, SVAL(params
,0));
5007 info_level
= SVAL(params
,2);
5009 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5011 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5012 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5016 /* Initial check for valid fsp ptr. */
5017 if (!check_fsp_open(conn
, req
, fsp
)) {
5021 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5023 if (!NT_STATUS_IS_OK(status
)) {
5024 reply_nterror(req
, status
);
5028 if(fsp
->fake_file_handle
) {
5030 * This is actually for the QUOTA_FAKE_FILE --metze
5033 /* We know this name is ok, it's already passed the checks. */
5035 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5037 * This is actually a QFILEINFO on a directory
5038 * handle (returned from an NT SMB). NT5.0 seems
5039 * to do this call. JRA.
5042 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5043 /* Always do lstat for UNIX calls. */
5044 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5045 DEBUG(3,("call_trans2qfilepathinfo: "
5046 "SMB_VFS_LSTAT of %s failed "
5048 smb_fname_str_dbg(smb_fname
),
5051 map_nt_error_from_unix(errno
));
5054 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5055 DEBUG(3,("call_trans2qfilepathinfo: "
5056 "SMB_VFS_STAT of %s failed (%s)\n",
5057 smb_fname_str_dbg(smb_fname
),
5060 map_nt_error_from_unix(errno
));
5064 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5065 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5068 * Original code - this is an open file.
5070 if (!check_fsp(conn
, req
, fsp
)) {
5074 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5075 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5076 fsp
->fnum
, strerror(errno
)));
5078 map_nt_error_from_unix(errno
));
5081 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5082 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5087 uint32_t ucf_flags
= 0;
5090 if (total_params
< 7) {
5091 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5095 info_level
= SVAL(params
,0);
5097 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5099 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5100 if (!lp_unix_extensions()) {
5101 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5104 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5105 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5106 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5107 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5111 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5113 STR_TERMINATE
, &status
);
5114 if (!NT_STATUS_IS_OK(status
)) {
5115 reply_nterror(req
, status
);
5119 status
= filename_convert(req
,
5121 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5126 if (!NT_STATUS_IS_OK(status
)) {
5127 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5128 reply_botherror(req
,
5129 NT_STATUS_PATH_NOT_COVERED
,
5130 ERRSRV
, ERRbadpath
);
5133 reply_nterror(req
, status
);
5137 /* If this is a stream, check if there is a delete_pending. */
5138 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5139 && is_ntfs_stream_smb_fname(smb_fname
)) {
5140 struct smb_filename
*smb_fname_base
= NULL
;
5142 /* Create an smb_filename with stream_name == NULL. */
5144 create_synthetic_smb_fname(talloc_tos(),
5145 smb_fname
->base_name
,
5148 if (!NT_STATUS_IS_OK(status
)) {
5149 reply_nterror(req
, status
);
5153 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5154 /* Always do lstat for UNIX calls. */
5155 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5156 DEBUG(3,("call_trans2qfilepathinfo: "
5157 "SMB_VFS_LSTAT of %s failed "
5159 smb_fname_str_dbg(smb_fname_base
),
5161 TALLOC_FREE(smb_fname_base
);
5163 map_nt_error_from_unix(errno
));
5167 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5168 DEBUG(3,("call_trans2qfilepathinfo: "
5169 "fileinfo of %s failed "
5171 smb_fname_str_dbg(smb_fname_base
),
5173 TALLOC_FREE(smb_fname_base
);
5175 map_nt_error_from_unix(errno
));
5180 fileid
= vfs_file_id_from_sbuf(conn
,
5181 &smb_fname_base
->st
);
5182 TALLOC_FREE(smb_fname_base
);
5183 get_file_infos(fileid
, &delete_pending
, NULL
);
5184 if (delete_pending
) {
5185 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5190 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5191 /* Always do lstat for UNIX calls. */
5192 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5193 DEBUG(3,("call_trans2qfilepathinfo: "
5194 "SMB_VFS_LSTAT of %s failed (%s)\n",
5195 smb_fname_str_dbg(smb_fname
),
5198 map_nt_error_from_unix(errno
));
5202 } else if (!VALID_STAT(smb_fname
->st
) &&
5203 SMB_VFS_STAT(conn
, smb_fname
) &&
5204 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5205 ms_dfs_link
= check_msdfs_link(conn
,
5206 smb_fname
->base_name
,
5210 DEBUG(3,("call_trans2qfilepathinfo: "
5211 "SMB_VFS_STAT of %s failed (%s)\n",
5212 smb_fname_str_dbg(smb_fname
),
5215 map_nt_error_from_unix(errno
));
5220 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5221 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5222 if (delete_pending
) {
5223 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5228 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5229 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5230 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5232 /* Pull out any data sent here before we realloc. */
5233 switch (info_level
) {
5234 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5236 /* Pull any EA list from the data portion. */
5239 if (total_data
< 4) {
5241 req
, NT_STATUS_INVALID_PARAMETER
);
5244 ea_size
= IVAL(pdata
,0);
5246 if (total_data
> 0 && ea_size
!= total_data
) {
5247 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5248 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5250 req
, NT_STATUS_INVALID_PARAMETER
);
5254 if (!lp_ea_support(SNUM(conn
))) {
5255 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5259 /* Pull out the list of names. */
5260 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5263 req
, NT_STATUS_INVALID_PARAMETER
);
5269 case SMB_QUERY_POSIX_LOCK
:
5271 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5272 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5276 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5278 req
, NT_STATUS_INVALID_PARAMETER
);
5282 /* Copy the lock range data. */
5283 lock_data
= (char *)TALLOC_MEMDUP(
5284 req
, pdata
, total_data
);
5286 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5289 lock_data_count
= total_data
;
5295 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5296 if (*pparams
== NULL
) {
5297 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5304 * draft-leach-cifs-v1-spec-02.txt
5305 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5308 * The requested information is placed in the Data portion of the
5309 * transaction response. For the information levels greater than 0x100,
5310 * the transaction response has 1 parameter word which should be
5311 * ignored by the client.
5313 * However Windows only follows this rule for the IS_NAME_VALID call.
5315 switch (info_level
) {
5316 case SMB_INFO_IS_NAME_VALID
:
5321 if ((info_level
& 0xFF00) == 0xFF00) {
5323 * We use levels that start with 0xFF00
5324 * internally to represent SMB2 specific levels
5326 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5330 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5332 delete_pending
, write_time_ts
,
5333 ms_dfs_link
, ea_list
,
5334 lock_data_count
, lock_data
,
5335 req
->flags2
, max_data_bytes
,
5336 ppdata
, &data_size
);
5337 if (!NT_STATUS_IS_OK(status
)) {
5338 reply_nterror(req
, status
);
5342 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5348 /****************************************************************************
5349 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5351 ****************************************************************************/
5353 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5354 connection_struct
*conn
,
5355 const struct smb_filename
*smb_fname_old
,
5356 const struct smb_filename
*smb_fname_new
)
5358 NTSTATUS status
= NT_STATUS_OK
;
5360 /* source must already exist. */
5361 if (!VALID_STAT(smb_fname_old
->st
)) {
5362 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5365 /* Disallow if newname already exists. */
5366 if (VALID_STAT(smb_fname_new
->st
)) {
5367 return NT_STATUS_OBJECT_NAME_COLLISION
;
5370 /* No links from a directory. */
5371 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5372 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5375 /* Setting a hardlink to/from a stream isn't currently supported. */
5376 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5377 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5378 return NT_STATUS_INVALID_PARAMETER
;
5381 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5382 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5384 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5385 smb_fname_new
->base_name
) != 0) {
5386 status
= map_nt_error_from_unix(errno
);
5387 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5388 nt_errstr(status
), smb_fname_old
->base_name
,
5389 smb_fname_new
->base_name
));
5394 /****************************************************************************
5395 Deal with setting the time from any of the setfilepathinfo functions.
5396 ****************************************************************************/
5398 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5400 const struct smb_filename
*smb_fname
,
5401 struct smb_file_time
*ft
,
5402 bool setting_write_time
)
5404 struct smb_filename smb_fname_base
;
5406 FILE_NOTIFY_CHANGE_LAST_ACCESS
5407 |FILE_NOTIFY_CHANGE_LAST_WRITE
5408 |FILE_NOTIFY_CHANGE_CREATION
;
5410 if (!VALID_STAT(smb_fname
->st
)) {
5411 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5414 /* get some defaults (no modifications) if any info is zero or -1. */
5415 if (null_timespec(ft
->create_time
)) {
5416 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5419 if (null_timespec(ft
->atime
)) {
5420 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5423 if (null_timespec(ft
->mtime
)) {
5424 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5427 if (!setting_write_time
) {
5428 /* ft->mtime comes from change time, not write time. */
5429 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5432 /* Ensure the resolution is the correct for
5433 * what we can store on this filesystem. */
5435 round_timespec(conn
->ts_res
, &ft
->create_time
);
5436 round_timespec(conn
->ts_res
, &ft
->ctime
);
5437 round_timespec(conn
->ts_res
, &ft
->atime
);
5438 round_timespec(conn
->ts_res
, &ft
->mtime
);
5440 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5442 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5443 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5444 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5445 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5446 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5447 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5449 if (setting_write_time
) {
5451 * This was a Windows setfileinfo on an open file.
5452 * NT does this a lot. We also need to
5453 * set the time here, as it can be read by
5454 * FindFirst/FindNext and with the patch for bug #2045
5455 * in smbd/fileio.c it ensures that this timestamp is
5456 * kept sticky even after a write. We save the request
5457 * away and will set it on file close and after a write. JRA.
5460 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5461 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5464 if (fsp
->base_fsp
) {
5465 set_sticky_write_time_fsp(fsp
->base_fsp
,
5468 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5471 set_sticky_write_time_path(
5472 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5477 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5479 /* Always call ntimes on the base, even if a stream was passed in. */
5480 smb_fname_base
= *smb_fname
;
5481 smb_fname_base
.stream_name
= NULL
;
5483 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5484 return map_nt_error_from_unix(errno
);
5487 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5488 smb_fname
->base_name
);
5489 return NT_STATUS_OK
;
5492 /****************************************************************************
5493 Deal with setting the dosmode from any of the setfilepathinfo functions.
5494 ****************************************************************************/
5496 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5497 const struct smb_filename
*smb_fname
,
5500 struct smb_filename
*smb_fname_base
= NULL
;
5503 if (!VALID_STAT(smb_fname
->st
)) {
5504 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5507 /* Always operate on the base_name, even if a stream was passed in. */
5508 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5509 NULL
, &smb_fname
->st
,
5511 if (!NT_STATUS_IS_OK(status
)) {
5516 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5523 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5525 /* check the mode isn't different, before changing it */
5526 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5527 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5528 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5529 (unsigned int)dosmode
));
5531 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5533 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5535 smb_fname_str_dbg(smb_fname_base
),
5537 status
= map_nt_error_from_unix(errno
);
5541 status
= NT_STATUS_OK
;
5543 TALLOC_FREE(smb_fname_base
);
5547 /****************************************************************************
5548 Deal with setting the size from any of the setfilepathinfo functions.
5549 ****************************************************************************/
5551 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5552 struct smb_request
*req
,
5554 const struct smb_filename
*smb_fname
,
5555 const SMB_STRUCT_STAT
*psbuf
,
5557 bool fail_after_createfile
)
5559 NTSTATUS status
= NT_STATUS_OK
;
5560 struct smb_filename
*smb_fname_tmp
= NULL
;
5561 files_struct
*new_fsp
= NULL
;
5563 if (!VALID_STAT(*psbuf
)) {
5564 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5567 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5569 if (size
== get_file_size_stat(psbuf
)) {
5570 return NT_STATUS_OK
;
5573 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5574 smb_fname_str_dbg(smb_fname
), (double)size
));
5576 if (fsp
&& fsp
->fh
->fd
!= -1) {
5577 /* Handle based call. */
5578 if (vfs_set_filelen(fsp
, size
) == -1) {
5579 return map_nt_error_from_unix(errno
);
5581 trigger_write_time_update_immediate(fsp
);
5582 return NT_STATUS_OK
;
5585 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5586 if (!NT_STATUS_IS_OK(status
)) {
5590 smb_fname_tmp
->st
= *psbuf
;
5592 status
= SMB_VFS_CREATE_FILE(
5595 0, /* root_dir_fid */
5596 smb_fname_tmp
, /* fname */
5597 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5598 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5600 FILE_OPEN
, /* create_disposition*/
5601 0, /* create_options */
5602 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5603 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5604 0, /* allocation_size */
5607 &new_fsp
, /* result */
5610 TALLOC_FREE(smb_fname_tmp
);
5612 if (!NT_STATUS_IS_OK(status
)) {
5613 /* NB. We check for open_was_deferred in the caller. */
5617 /* See RAW-SFILEINFO-END-OF-FILE */
5618 if (fail_after_createfile
) {
5619 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5620 return NT_STATUS_INVALID_LEVEL
;
5623 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5624 status
= map_nt_error_from_unix(errno
);
5625 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5629 trigger_write_time_update_immediate(new_fsp
);
5630 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5631 return NT_STATUS_OK
;
5634 /****************************************************************************
5635 Deal with SMB_INFO_SET_EA.
5636 ****************************************************************************/
5638 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5642 const struct smb_filename
*smb_fname
)
5644 struct ea_list
*ea_list
= NULL
;
5645 TALLOC_CTX
*ctx
= NULL
;
5646 NTSTATUS status
= NT_STATUS_OK
;
5648 if (total_data
< 10) {
5650 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5651 length. They seem to have no effect. Bug #3212. JRA */
5653 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5654 /* We're done. We only get EA info in this call. */
5655 return NT_STATUS_OK
;
5658 return NT_STATUS_INVALID_PARAMETER
;
5661 if (IVAL(pdata
,0) > total_data
) {
5662 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5663 IVAL(pdata
,0), (unsigned int)total_data
));
5664 return NT_STATUS_INVALID_PARAMETER
;
5668 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5670 return NT_STATUS_INVALID_PARAMETER
;
5672 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5677 /****************************************************************************
5678 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5679 ****************************************************************************/
5681 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5686 struct ea_list
*ea_list
= NULL
;
5690 return NT_STATUS_INVALID_HANDLE
;
5693 if (!lp_ea_support(SNUM(conn
))) {
5694 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5695 "EA's not supported.\n",
5696 (unsigned int)total_data
));
5697 return NT_STATUS_EAS_NOT_SUPPORTED
;
5700 if (total_data
< 10) {
5701 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5703 (unsigned int)total_data
));
5704 return NT_STATUS_INVALID_PARAMETER
;
5707 ea_list
= read_nttrans_ea_list(talloc_tos(),
5712 return NT_STATUS_INVALID_PARAMETER
;
5714 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5716 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5717 smb_fname_str_dbg(fsp
->fsp_name
),
5718 nt_errstr(status
) ));
5724 /****************************************************************************
5725 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5726 ****************************************************************************/
5728 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5732 struct smb_filename
*smb_fname
)
5734 NTSTATUS status
= NT_STATUS_OK
;
5735 bool delete_on_close
;
5738 if (total_data
< 1) {
5739 return NT_STATUS_INVALID_PARAMETER
;
5743 return NT_STATUS_INVALID_HANDLE
;
5746 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5747 dosmode
= dos_mode(conn
, smb_fname
);
5749 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5750 "delete_on_close = %u\n",
5751 smb_fname_str_dbg(smb_fname
),
5752 (unsigned int)dosmode
,
5753 (unsigned int)delete_on_close
));
5755 if (delete_on_close
) {
5756 status
= can_set_delete_on_close(fsp
, dosmode
);
5757 if (!NT_STATUS_IS_OK(status
)) {
5762 /* The set is across all open files on this dev/inode pair. */
5763 if (!set_delete_on_close(fsp
, delete_on_close
,
5764 &conn
->server_info
->utok
)) {
5765 return NT_STATUS_ACCESS_DENIED
;
5767 return NT_STATUS_OK
;
5770 /****************************************************************************
5771 Deal with SMB_FILE_POSITION_INFORMATION.
5772 ****************************************************************************/
5774 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5779 uint64_t position_information
;
5781 if (total_data
< 8) {
5782 return NT_STATUS_INVALID_PARAMETER
;
5786 /* Ignore on pathname based set. */
5787 return NT_STATUS_OK
;
5790 position_information
= (uint64_t)IVAL(pdata
,0);
5791 #ifdef LARGE_SMB_OFF_T
5792 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5793 #else /* LARGE_SMB_OFF_T */
5794 if (IVAL(pdata
,4) != 0) {
5795 /* more than 32 bits? */
5796 return NT_STATUS_INVALID_PARAMETER
;
5798 #endif /* LARGE_SMB_OFF_T */
5800 DEBUG(10,("smb_file_position_information: Set file position "
5801 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5802 (double)position_information
));
5803 fsp
->fh
->position_information
= position_information
;
5804 return NT_STATUS_OK
;
5807 /****************************************************************************
5808 Deal with SMB_FILE_MODE_INFORMATION.
5809 ****************************************************************************/
5811 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5817 if (total_data
< 4) {
5818 return NT_STATUS_INVALID_PARAMETER
;
5820 mode
= IVAL(pdata
,0);
5821 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5822 return NT_STATUS_INVALID_PARAMETER
;
5824 return NT_STATUS_OK
;
5827 /****************************************************************************
5828 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5829 ****************************************************************************/
5831 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5832 struct smb_request
*req
,
5835 const struct smb_filename
*smb_fname
)
5837 char *link_target
= NULL
;
5838 const char *newname
= smb_fname
->base_name
;
5839 TALLOC_CTX
*ctx
= talloc_tos();
5841 /* Set a symbolic link. */
5842 /* Don't allow this if follow links is false. */
5844 if (total_data
== 0) {
5845 return NT_STATUS_INVALID_PARAMETER
;
5848 if (!lp_symlinks(SNUM(conn
))) {
5849 return NT_STATUS_ACCESS_DENIED
;
5852 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5853 total_data
, STR_TERMINATE
);
5856 return NT_STATUS_INVALID_PARAMETER
;
5859 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5860 newname
, link_target
));
5862 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5863 return map_nt_error_from_unix(errno
);
5866 return NT_STATUS_OK
;
5869 /****************************************************************************
5870 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5871 ****************************************************************************/
5873 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5874 struct smb_request
*req
,
5875 const char *pdata
, int total_data
,
5876 const struct smb_filename
*smb_fname_new
)
5878 char *oldname
= NULL
;
5879 struct smb_filename
*smb_fname_old
= NULL
;
5880 TALLOC_CTX
*ctx
= talloc_tos();
5881 NTSTATUS status
= NT_STATUS_OK
;
5883 /* Set a hard link. */
5884 if (total_data
== 0) {
5885 return NT_STATUS_INVALID_PARAMETER
;
5888 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5889 total_data
, STR_TERMINATE
, &status
);
5890 if (!NT_STATUS_IS_OK(status
)) {
5894 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5895 smb_fname_str_dbg(smb_fname_new
), oldname
));
5897 status
= filename_convert(ctx
,
5899 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5904 if (!NT_STATUS_IS_OK(status
)) {
5908 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5911 /****************************************************************************
5912 Deal with SMB_FILE_RENAME_INFORMATION.
5913 ****************************************************************************/
5915 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5916 struct smb_request
*req
,
5920 struct smb_filename
*smb_fname_src
)
5925 char *newname
= NULL
;
5926 struct smb_filename
*smb_fname_dst
= NULL
;
5927 bool dest_has_wcard
= False
;
5928 NTSTATUS status
= NT_STATUS_OK
;
5930 TALLOC_CTX
*ctx
= talloc_tos();
5932 if (total_data
< 13) {
5933 return NT_STATUS_INVALID_PARAMETER
;
5936 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5937 root_fid
= IVAL(pdata
,4);
5938 len
= IVAL(pdata
,8);
5940 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5941 return NT_STATUS_INVALID_PARAMETER
;
5944 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5947 if (!NT_STATUS_IS_OK(status
)) {
5951 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5954 status
= resolve_dfspath_wcard(ctx
, conn
,
5955 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5960 if (!NT_STATUS_IS_OK(status
)) {
5964 /* Check the new name has no '/' characters. */
5965 if (strchr_m(newname
, '/')) {
5966 return NT_STATUS_NOT_SUPPORTED
;
5969 if (fsp
&& fsp
->base_fsp
) {
5970 /* newname must be a stream name. */
5971 if (newname
[0] != ':') {
5972 return NT_STATUS_NOT_SUPPORTED
;
5975 /* Create an smb_fname to call rename_internals_fsp() with. */
5976 status
= create_synthetic_smb_fname(talloc_tos(),
5977 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
5979 if (!NT_STATUS_IS_OK(status
)) {
5984 * Set the original last component, since
5985 * rename_internals_fsp() requires it.
5987 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
5989 if (smb_fname_dst
->original_lcomp
== NULL
) {
5990 status
= NT_STATUS_NO_MEMORY
;
5996 * Build up an smb_fname_dst based on the filename passed in.
5997 * We basically just strip off the last component, and put on
5998 * the newname instead.
6000 char *base_name
= NULL
;
6002 /* newname must *not* be a stream name. */
6003 if (newname
[0] == ':') {
6004 return NT_STATUS_NOT_SUPPORTED
;
6008 * Strip off the last component (filename) of the path passed
6011 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6013 return NT_STATUS_NO_MEMORY
;
6015 p
= strrchr_m(base_name
, '/');
6019 base_name
= talloc_strdup(ctx
, "./");
6021 return NT_STATUS_NO_MEMORY
;
6024 /* Append the new name. */
6025 base_name
= talloc_asprintf_append(base_name
,
6029 return NT_STATUS_NO_MEMORY
;
6032 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6035 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6038 /* If an error we expect this to be
6039 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6041 if (!NT_STATUS_IS_OK(status
)) {
6042 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6046 /* Create an smb_fname to call rename_internals_fsp() */
6047 status
= create_synthetic_smb_fname(ctx
,
6051 if (!NT_STATUS_IS_OK(status
)) {
6058 DEBUG(10,("smb_file_rename_information: "
6059 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6060 fsp
->fnum
, fsp_str_dbg(fsp
),
6061 smb_fname_str_dbg(smb_fname_dst
)));
6062 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6065 DEBUG(10,("smb_file_rename_information: "
6066 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6067 smb_fname_str_dbg(smb_fname_src
),
6068 smb_fname_str_dbg(smb_fname_dst
)));
6069 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6070 smb_fname_dst
, 0, overwrite
, false,
6072 FILE_WRITE_ATTRIBUTES
);
6075 TALLOC_FREE(smb_fname_dst
);
6079 /****************************************************************************
6080 Deal with SMB_SET_POSIX_ACL.
6081 ****************************************************************************/
6083 #if defined(HAVE_POSIX_ACLS)
6084 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6088 const struct smb_filename
*smb_fname
)
6090 uint16 posix_acl_version
;
6091 uint16 num_file_acls
;
6092 uint16 num_def_acls
;
6093 bool valid_file_acls
= True
;
6094 bool valid_def_acls
= True
;
6096 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6097 return NT_STATUS_INVALID_PARAMETER
;
6099 posix_acl_version
= SVAL(pdata
,0);
6100 num_file_acls
= SVAL(pdata
,2);
6101 num_def_acls
= SVAL(pdata
,4);
6103 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6104 valid_file_acls
= False
;
6108 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6109 valid_def_acls
= False
;
6113 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6114 return NT_STATUS_INVALID_PARAMETER
;
6117 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6118 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6119 return NT_STATUS_INVALID_PARAMETER
;
6122 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6123 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6124 (unsigned int)num_file_acls
,
6125 (unsigned int)num_def_acls
));
6127 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6128 smb_fname
->base_name
, num_file_acls
,
6129 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6130 return map_nt_error_from_unix(errno
);
6133 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6134 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6135 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6136 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6137 return map_nt_error_from_unix(errno
);
6139 return NT_STATUS_OK
;
6143 /****************************************************************************
6144 Deal with SMB_SET_POSIX_LOCK.
6145 ****************************************************************************/
6147 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6148 struct smb_request
*req
,
6156 bool blocking_lock
= False
;
6157 enum brl_type lock_type
;
6159 NTSTATUS status
= NT_STATUS_OK
;
6161 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6162 return NT_STATUS_INVALID_HANDLE
;
6165 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6166 return NT_STATUS_INVALID_PARAMETER
;
6169 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6170 case POSIX_LOCK_TYPE_READ
:
6171 lock_type
= READ_LOCK
;
6173 case POSIX_LOCK_TYPE_WRITE
:
6174 /* Return the right POSIX-mappable error code for files opened read-only. */
6175 if (!fsp
->can_write
) {
6176 return NT_STATUS_INVALID_HANDLE
;
6178 lock_type
= WRITE_LOCK
;
6180 case POSIX_LOCK_TYPE_UNLOCK
:
6181 lock_type
= UNLOCK_LOCK
;
6184 return NT_STATUS_INVALID_PARAMETER
;
6187 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6188 blocking_lock
= False
;
6189 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6190 blocking_lock
= True
;
6192 return NT_STATUS_INVALID_PARAMETER
;
6195 if (!lp_blocking_locks(SNUM(conn
))) {
6196 blocking_lock
= False
;
6199 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6200 #if defined(HAVE_LONGLONG)
6201 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6202 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6203 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6204 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6205 #else /* HAVE_LONGLONG */
6206 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6207 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6208 #endif /* HAVE_LONGLONG */
6210 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6211 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6213 (unsigned int)lock_type
,
6214 (unsigned int)lock_pid
,
6218 if (lock_type
== UNLOCK_LOCK
) {
6219 status
= do_unlock(smbd_messaging_context(),
6226 uint32 block_smbpid
;
6228 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6240 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6242 * A blocking lock was requested. Package up
6243 * this smb into a queued request and push it
6244 * onto the blocking lock queue.
6246 if(push_blocking_lock_request(br_lck
,
6249 -1, /* infinite timeout. */
6257 TALLOC_FREE(br_lck
);
6261 TALLOC_FREE(br_lck
);
6267 /****************************************************************************
6268 Deal with SMB_SET_FILE_BASIC_INFO.
6269 ****************************************************************************/
6271 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6275 const struct smb_filename
*smb_fname
)
6277 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6278 struct smb_file_time ft
;
6280 NTSTATUS status
= NT_STATUS_OK
;
6284 if (total_data
< 36) {
6285 return NT_STATUS_INVALID_PARAMETER
;
6288 /* Set the attributes */
6289 dosmode
= IVAL(pdata
,32);
6290 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6291 if (!NT_STATUS_IS_OK(status
)) {
6296 ft
.create_time
= interpret_long_date(pdata
);
6299 ft
.atime
= interpret_long_date(pdata
+8);
6302 ft
.mtime
= interpret_long_date(pdata
+16);
6305 ft
.ctime
= interpret_long_date(pdata
+24);
6307 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6308 smb_fname_str_dbg(smb_fname
)));
6310 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6314 /****************************************************************************
6315 Deal with SMB_INFO_STANDARD.
6316 ****************************************************************************/
6318 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6322 const struct smb_filename
*smb_fname
)
6324 struct smb_file_time ft
;
6328 if (total_data
< 12) {
6329 return NT_STATUS_INVALID_PARAMETER
;
6333 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6335 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6337 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6339 DEBUG(10,("smb_set_info_standard: file %s\n",
6340 smb_fname_str_dbg(smb_fname
)));
6342 return smb_set_file_time(conn
,
6349 /****************************************************************************
6350 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6351 ****************************************************************************/
6353 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6354 struct smb_request
*req
,
6358 struct smb_filename
*smb_fname
)
6360 uint64_t allocation_size
= 0;
6361 NTSTATUS status
= NT_STATUS_OK
;
6362 files_struct
*new_fsp
= NULL
;
6364 if (!VALID_STAT(smb_fname
->st
)) {
6365 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6368 if (total_data
< 8) {
6369 return NT_STATUS_INVALID_PARAMETER
;
6372 allocation_size
= (uint64_t)IVAL(pdata
,0);
6373 #ifdef LARGE_SMB_OFF_T
6374 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6375 #else /* LARGE_SMB_OFF_T */
6376 if (IVAL(pdata
,4) != 0) {
6377 /* more than 32 bits? */
6378 return NT_STATUS_INVALID_PARAMETER
;
6380 #endif /* LARGE_SMB_OFF_T */
6382 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6383 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6384 (double)allocation_size
));
6386 if (allocation_size
) {
6387 allocation_size
= smb_roundup(conn
, allocation_size
);
6390 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6391 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6392 (double)allocation_size
));
6394 if (fsp
&& fsp
->fh
->fd
!= -1) {
6395 /* Open file handle. */
6396 /* Only change if needed. */
6397 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6398 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6399 return map_nt_error_from_unix(errno
);
6402 /* But always update the time. */
6404 * This is equivalent to a write. Ensure it's seen immediately
6405 * if there are no pending writes.
6407 trigger_write_time_update_immediate(fsp
);
6408 return NT_STATUS_OK
;
6411 /* Pathname or stat or directory file. */
6412 status
= SMB_VFS_CREATE_FILE(
6415 0, /* root_dir_fid */
6416 smb_fname
, /* fname */
6417 FILE_WRITE_DATA
, /* access_mask */
6418 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6420 FILE_OPEN
, /* create_disposition*/
6421 0, /* create_options */
6422 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6423 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6424 0, /* allocation_size */
6427 &new_fsp
, /* result */
6430 if (!NT_STATUS_IS_OK(status
)) {
6431 /* NB. We check for open_was_deferred in the caller. */
6435 /* Only change if needed. */
6436 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6437 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6438 status
= map_nt_error_from_unix(errno
);
6439 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6444 /* Changing the allocation size should set the last mod time. */
6446 * This is equivalent to a write. Ensure it's seen immediately
6447 * if there are no pending writes.
6449 trigger_write_time_update_immediate(new_fsp
);
6451 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6452 return NT_STATUS_OK
;
6455 /****************************************************************************
6456 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6457 ****************************************************************************/
6459 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6460 struct smb_request
*req
,
6464 const struct smb_filename
*smb_fname
,
6465 bool fail_after_createfile
)
6469 if (total_data
< 8) {
6470 return NT_STATUS_INVALID_PARAMETER
;
6473 size
= IVAL(pdata
,0);
6474 #ifdef LARGE_SMB_OFF_T
6475 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6476 #else /* LARGE_SMB_OFF_T */
6477 if (IVAL(pdata
,4) != 0) {
6478 /* more than 32 bits? */
6479 return NT_STATUS_INVALID_PARAMETER
;
6481 #endif /* LARGE_SMB_OFF_T */
6482 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6483 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6486 return smb_set_file_size(conn
, req
,
6491 fail_after_createfile
);
6494 /****************************************************************************
6495 Allow a UNIX info mknod.
6496 ****************************************************************************/
6498 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6501 const struct smb_filename
*smb_fname
)
6503 uint32 file_type
= IVAL(pdata
,56);
6504 #if defined(HAVE_MAKEDEV)
6505 uint32 dev_major
= IVAL(pdata
,60);
6506 uint32 dev_minor
= IVAL(pdata
,68);
6508 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6509 uint32 raw_unixmode
= IVAL(pdata
,84);
6513 if (total_data
< 100) {
6514 return NT_STATUS_INVALID_PARAMETER
;
6517 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6518 PERM_NEW_FILE
, &unixmode
);
6519 if (!NT_STATUS_IS_OK(status
)) {
6523 #if defined(HAVE_MAKEDEV)
6524 dev
= makedev(dev_major
, dev_minor
);
6527 switch (file_type
) {
6528 #if defined(S_IFIFO)
6529 case UNIX_TYPE_FIFO
:
6530 unixmode
|= S_IFIFO
;
6533 #if defined(S_IFSOCK)
6534 case UNIX_TYPE_SOCKET
:
6535 unixmode
|= S_IFSOCK
;
6538 #if defined(S_IFCHR)
6539 case UNIX_TYPE_CHARDEV
:
6540 unixmode
|= S_IFCHR
;
6543 #if defined(S_IFBLK)
6544 case UNIX_TYPE_BLKDEV
:
6545 unixmode
|= S_IFBLK
;
6549 return NT_STATUS_INVALID_PARAMETER
;
6552 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6553 "%.0f mode 0%o for file %s\n", (double)dev
,
6554 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6556 /* Ok - do the mknod. */
6557 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6558 return map_nt_error_from_unix(errno
);
6561 /* If any of the other "set" calls fail we
6562 * don't want to end up with a half-constructed mknod.
6565 if (lp_inherit_perms(SNUM(conn
))) {
6567 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6569 return NT_STATUS_NO_MEMORY
;
6571 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6573 TALLOC_FREE(parent
);
6576 return NT_STATUS_OK
;
6579 /****************************************************************************
6580 Deal with SMB_SET_FILE_UNIX_BASIC.
6581 ****************************************************************************/
6583 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6584 struct smb_request
*req
,
6588 const struct smb_filename
*smb_fname
)
6590 struct smb_file_time ft
;
6591 uint32 raw_unixmode
;
6594 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6595 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6596 NTSTATUS status
= NT_STATUS_OK
;
6597 bool delete_on_fail
= False
;
6598 enum perm_type ptype
;
6599 files_struct
*all_fsps
= NULL
;
6600 bool modify_mtime
= true;
6602 struct smb_filename
*smb_fname_tmp
= NULL
;
6603 SMB_STRUCT_STAT sbuf
;
6607 if (total_data
< 100) {
6608 return NT_STATUS_INVALID_PARAMETER
;
6611 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6612 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6613 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6614 #ifdef LARGE_SMB_OFF_T
6615 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6616 #else /* LARGE_SMB_OFF_T */
6617 if (IVAL(pdata
,4) != 0) {
6618 /* more than 32 bits? */
6619 return NT_STATUS_INVALID_PARAMETER
;
6621 #endif /* LARGE_SMB_OFF_T */
6624 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6625 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6626 set_owner
= (uid_t
)IVAL(pdata
,40);
6627 set_grp
= (gid_t
)IVAL(pdata
,48);
6628 raw_unixmode
= IVAL(pdata
,84);
6630 if (VALID_STAT(smb_fname
->st
)) {
6631 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6632 ptype
= PERM_EXISTING_DIR
;
6634 ptype
= PERM_EXISTING_FILE
;
6637 ptype
= PERM_NEW_FILE
;
6640 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6642 if (!NT_STATUS_IS_OK(status
)) {
6646 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6647 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6648 smb_fname_str_dbg(smb_fname
), (double)size
,
6649 (unsigned int)set_owner
, (unsigned int)set_grp
,
6650 (int)raw_unixmode
));
6652 sbuf
= smb_fname
->st
;
6654 if (!VALID_STAT(sbuf
)) {
6656 * The only valid use of this is to create character and block
6657 * devices, and named pipes. This is deprecated (IMHO) and
6658 * a new info level should be used for mknod. JRA.
6661 status
= smb_unix_mknod(conn
,
6665 if (!NT_STATUS_IS_OK(status
)) {
6669 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6671 if (!NT_STATUS_IS_OK(status
)) {
6675 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6676 status
= map_nt_error_from_unix(errno
);
6677 TALLOC_FREE(smb_fname_tmp
);
6678 SMB_VFS_UNLINK(conn
, smb_fname
);
6682 sbuf
= smb_fname_tmp
->st
;
6683 smb_fname
= smb_fname_tmp
;
6685 /* Ensure we don't try and change anything else. */
6686 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6687 size
= get_file_size_stat(&sbuf
);
6688 ft
.atime
= sbuf
.st_ex_atime
;
6689 ft
.mtime
= sbuf
.st_ex_mtime
;
6691 * We continue here as we might want to change the
6694 delete_on_fail
= True
;
6698 /* Horrible backwards compatibility hack as an old server bug
6699 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6703 size
= get_file_size_stat(&sbuf
);
6708 * Deal with the UNIX specific mode set.
6711 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6712 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6713 "setting mode 0%o for file %s\n",
6714 (unsigned int)unixmode
,
6715 smb_fname_str_dbg(smb_fname
)));
6716 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6717 return map_nt_error_from_unix(errno
);
6722 * Deal with the UNIX specific uid set.
6725 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6726 (sbuf
.st_ex_uid
!= set_owner
)) {
6729 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6730 "changing owner %u for path %s\n",
6731 (unsigned int)set_owner
,
6732 smb_fname_str_dbg(smb_fname
)));
6734 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6735 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6736 set_owner
, (gid_t
)-1);
6738 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6739 set_owner
, (gid_t
)-1);
6743 status
= map_nt_error_from_unix(errno
);
6744 if (delete_on_fail
) {
6745 SMB_VFS_UNLINK(conn
, smb_fname
);
6752 * Deal with the UNIX specific gid set.
6755 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6756 (sbuf
.st_ex_gid
!= set_grp
)) {
6757 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6758 "changing group %u for file %s\n",
6759 (unsigned int)set_owner
,
6760 smb_fname_str_dbg(smb_fname
)));
6761 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6763 status
= map_nt_error_from_unix(errno
);
6764 if (delete_on_fail
) {
6765 SMB_VFS_UNLINK(conn
, smb_fname
);
6771 /* Deal with any size changes. */
6773 status
= smb_set_file_size(conn
, req
,
6779 if (!NT_STATUS_IS_OK(status
)) {
6783 /* Deal with any time changes. */
6784 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6785 /* No change, don't cancel anything. */
6789 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6790 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6791 all_fsps
= file_find_di_next(all_fsps
)) {
6793 * We're setting the time explicitly for UNIX.
6794 * Cancel any pending changes over all handles.
6796 all_fsps
->update_write_time_on_close
= false;
6797 TALLOC_FREE(all_fsps
->update_write_time_event
);
6801 * Override the "setting_write_time"
6802 * parameter here as it almost does what
6803 * we need. Just remember if we modified
6804 * mtime and send the notify ourselves.
6806 if (null_timespec(ft
.mtime
)) {
6807 modify_mtime
= false;
6810 status
= smb_set_file_time(conn
,
6816 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6817 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6822 /****************************************************************************
6823 Deal with SMB_SET_FILE_UNIX_INFO2.
6824 ****************************************************************************/
6826 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6827 struct smb_request
*req
,
6831 const struct smb_filename
*smb_fname
)
6837 if (total_data
< 116) {
6838 return NT_STATUS_INVALID_PARAMETER
;
6841 /* Start by setting all the fields that are common between UNIX_BASIC
6844 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6846 if (!NT_STATUS_IS_OK(status
)) {
6850 smb_fflags
= IVAL(pdata
, 108);
6851 smb_fmask
= IVAL(pdata
, 112);
6853 /* NB: We should only attempt to alter the file flags if the client
6854 * sends a non-zero mask.
6856 if (smb_fmask
!= 0) {
6857 int stat_fflags
= 0;
6859 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6860 smb_fmask
, &stat_fflags
)) {
6861 /* Client asked to alter a flag we don't understand. */
6862 return NT_STATUS_INVALID_PARAMETER
;
6865 if (fsp
&& fsp
->fh
->fd
!= -1) {
6866 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6867 return NT_STATUS_NOT_SUPPORTED
;
6869 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6870 stat_fflags
) != 0) {
6871 return map_nt_error_from_unix(errno
);
6876 /* XXX: need to add support for changing the create_time here. You
6877 * can do this for paths on Darwin with setattrlist(2). The right way
6878 * to hook this up is probably by extending the VFS utimes interface.
6881 return NT_STATUS_OK
;
6884 /****************************************************************************
6885 Create a directory with POSIX semantics.
6886 ****************************************************************************/
6888 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6889 struct smb_request
*req
,
6892 struct smb_filename
*smb_fname
,
6893 int *pdata_return_size
)
6895 NTSTATUS status
= NT_STATUS_OK
;
6896 uint32 raw_unixmode
= 0;
6897 uint32 mod_unixmode
= 0;
6898 mode_t unixmode
= (mode_t
)0;
6899 files_struct
*fsp
= NULL
;
6900 uint16 info_level_return
= 0;
6902 char *pdata
= *ppdata
;
6904 if (total_data
< 18) {
6905 return NT_STATUS_INVALID_PARAMETER
;
6908 raw_unixmode
= IVAL(pdata
,8);
6909 /* Next 4 bytes are not yet defined. */
6911 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6912 PERM_NEW_DIR
, &unixmode
);
6913 if (!NT_STATUS_IS_OK(status
)) {
6917 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6919 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6920 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6922 status
= SMB_VFS_CREATE_FILE(
6925 0, /* root_dir_fid */
6926 smb_fname
, /* fname */
6927 FILE_READ_ATTRIBUTES
, /* access_mask */
6928 FILE_SHARE_NONE
, /* share_access */
6929 FILE_CREATE
, /* create_disposition*/
6930 FILE_DIRECTORY_FILE
, /* create_options */
6931 mod_unixmode
, /* file_attributes */
6932 0, /* oplock_request */
6933 0, /* allocation_size */
6939 if (NT_STATUS_IS_OK(status
)) {
6940 close_file(req
, fsp
, NORMAL_CLOSE
);
6943 info_level_return
= SVAL(pdata
,16);
6945 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6946 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6947 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6948 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6950 *pdata_return_size
= 12;
6953 /* Realloc the data size */
6954 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6955 if (*ppdata
== NULL
) {
6956 *pdata_return_size
= 0;
6957 return NT_STATUS_NO_MEMORY
;
6961 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6962 SSVAL(pdata
,2,0); /* No fnum. */
6963 SIVAL(pdata
,4,info
); /* Was directory created. */
6965 switch (info_level_return
) {
6966 case SMB_QUERY_FILE_UNIX_BASIC
:
6967 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6968 SSVAL(pdata
,10,0); /* Padding. */
6969 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6972 case SMB_QUERY_FILE_UNIX_INFO2
:
6973 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6974 SSVAL(pdata
,10,0); /* Padding. */
6975 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6979 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6980 SSVAL(pdata
,10,0); /* Padding. */
6987 /****************************************************************************
6988 Open/Create a file with POSIX semantics.
6989 ****************************************************************************/
6991 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6992 struct smb_request
*req
,
6995 struct smb_filename
*smb_fname
,
6996 int *pdata_return_size
)
6998 bool extended_oplock_granted
= False
;
6999 char *pdata
= *ppdata
;
7001 uint32 wire_open_mode
= 0;
7002 uint32 raw_unixmode
= 0;
7003 uint32 mod_unixmode
= 0;
7004 uint32 create_disp
= 0;
7005 uint32 access_mask
= 0;
7006 uint32 create_options
= 0;
7007 NTSTATUS status
= NT_STATUS_OK
;
7008 mode_t unixmode
= (mode_t
)0;
7009 files_struct
*fsp
= NULL
;
7010 int oplock_request
= 0;
7012 uint16 info_level_return
= 0;
7014 if (total_data
< 18) {
7015 return NT_STATUS_INVALID_PARAMETER
;
7018 flags
= IVAL(pdata
,0);
7019 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7020 if (oplock_request
) {
7021 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7024 wire_open_mode
= IVAL(pdata
,4);
7026 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7027 return smb_posix_mkdir(conn
, req
,
7034 switch (wire_open_mode
& SMB_ACCMODE
) {
7036 access_mask
= FILE_READ_DATA
;
7039 access_mask
= FILE_WRITE_DATA
;
7042 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7045 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7046 (unsigned int)wire_open_mode
));
7047 return NT_STATUS_INVALID_PARAMETER
;
7050 wire_open_mode
&= ~SMB_ACCMODE
;
7052 /* First take care of O_CREAT|O_EXCL interactions. */
7053 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7054 case (SMB_O_CREAT
| SMB_O_EXCL
):
7055 /* File exists fail. File not exist create. */
7056 create_disp
= FILE_CREATE
;
7059 /* File exists open. File not exist create. */
7060 create_disp
= FILE_OPEN_IF
;
7063 /* File exists open. File not exist fail. */
7064 create_disp
= FILE_OPEN
;
7067 /* O_EXCL on its own without O_CREAT is undefined. */
7069 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7070 (unsigned int)wire_open_mode
));
7071 return NT_STATUS_INVALID_PARAMETER
;
7074 /* Next factor in the effects of O_TRUNC. */
7075 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7077 if (wire_open_mode
& SMB_O_TRUNC
) {
7078 switch (create_disp
) {
7080 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7081 /* Leave create_disp alone as
7082 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7084 /* File exists fail. File not exist create. */
7087 /* SMB_O_CREAT | SMB_O_TRUNC */
7088 /* File exists overwrite. File not exist create. */
7089 create_disp
= FILE_OVERWRITE_IF
;
7093 /* File exists overwrite. File not exist fail. */
7094 create_disp
= FILE_OVERWRITE
;
7097 /* Cannot get here. */
7098 smb_panic("smb_posix_open: logic error");
7099 return NT_STATUS_INVALID_PARAMETER
;
7103 raw_unixmode
= IVAL(pdata
,8);
7104 /* Next 4 bytes are not yet defined. */
7106 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7107 (VALID_STAT(smb_fname
->st
) ?
7108 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7111 if (!NT_STATUS_IS_OK(status
)) {
7115 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7117 if (wire_open_mode
& SMB_O_SYNC
) {
7118 create_options
|= FILE_WRITE_THROUGH
;
7120 if (wire_open_mode
& SMB_O_APPEND
) {
7121 access_mask
|= FILE_APPEND_DATA
;
7123 if (wire_open_mode
& SMB_O_DIRECT
) {
7124 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7127 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7128 smb_fname_str_dbg(smb_fname
),
7129 (unsigned int)wire_open_mode
,
7130 (unsigned int)unixmode
));
7132 status
= SMB_VFS_CREATE_FILE(
7135 0, /* root_dir_fid */
7136 smb_fname
, /* fname */
7137 access_mask
, /* access_mask */
7138 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7140 create_disp
, /* create_disposition*/
7141 FILE_NON_DIRECTORY_FILE
, /* create_options */
7142 mod_unixmode
, /* file_attributes */
7143 oplock_request
, /* oplock_request */
7144 0, /* allocation_size */
7150 if (!NT_STATUS_IS_OK(status
)) {
7154 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7155 extended_oplock_granted
= True
;
7158 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7159 extended_oplock_granted
= True
;
7162 info_level_return
= SVAL(pdata
,16);
7164 /* Allocate the correct return size. */
7166 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7167 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7168 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7169 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7171 *pdata_return_size
= 12;
7174 /* Realloc the data size */
7175 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7176 if (*ppdata
== NULL
) {
7177 close_file(req
, fsp
, ERROR_CLOSE
);
7178 *pdata_return_size
= 0;
7179 return NT_STATUS_NO_MEMORY
;
7183 if (extended_oplock_granted
) {
7184 if (flags
& REQUEST_BATCH_OPLOCK
) {
7185 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7187 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7189 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7190 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7192 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7195 SSVAL(pdata
,2,fsp
->fnum
);
7196 SIVAL(pdata
,4,info
); /* Was file created etc. */
7198 switch (info_level_return
) {
7199 case SMB_QUERY_FILE_UNIX_BASIC
:
7200 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7201 SSVAL(pdata
,10,0); /* padding. */
7202 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7205 case SMB_QUERY_FILE_UNIX_INFO2
:
7206 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7207 SSVAL(pdata
,10,0); /* padding. */
7208 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7212 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7213 SSVAL(pdata
,10,0); /* padding. */
7216 return NT_STATUS_OK
;
7219 /****************************************************************************
7220 Delete a file with POSIX semantics.
7221 ****************************************************************************/
7223 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7224 struct smb_request
*req
,
7227 struct smb_filename
*smb_fname
)
7229 NTSTATUS status
= NT_STATUS_OK
;
7230 files_struct
*fsp
= NULL
;
7234 int create_options
= 0;
7236 struct share_mode_lock
*lck
= NULL
;
7238 if (total_data
< 2) {
7239 return NT_STATUS_INVALID_PARAMETER
;
7242 flags
= SVAL(pdata
,0);
7244 if (!VALID_STAT(smb_fname
->st
)) {
7245 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7248 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7249 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7250 return NT_STATUS_NOT_A_DIRECTORY
;
7253 DEBUG(10,("smb_posix_unlink: %s %s\n",
7254 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7255 smb_fname_str_dbg(smb_fname
)));
7257 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7258 create_options
|= FILE_DIRECTORY_FILE
;
7261 status
= SMB_VFS_CREATE_FILE(
7264 0, /* root_dir_fid */
7265 smb_fname
, /* fname */
7266 DELETE_ACCESS
, /* access_mask */
7267 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7269 FILE_OPEN
, /* create_disposition*/
7270 create_options
, /* create_options */
7271 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7272 0, /* oplock_request */
7273 0, /* allocation_size */
7279 if (!NT_STATUS_IS_OK(status
)) {
7284 * Don't lie to client. If we can't really delete due to
7285 * non-POSIX opens return SHARING_VIOLATION.
7288 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7291 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7292 "lock for file %s\n", fsp_str_dbg(fsp
)));
7293 close_file(req
, fsp
, NORMAL_CLOSE
);
7294 return NT_STATUS_INVALID_PARAMETER
;
7298 * See if others still have the file open. If this is the case, then
7299 * don't delete. If all opens are POSIX delete we can set the delete
7300 * on close disposition.
7302 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7303 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7304 if (is_valid_share_mode_entry(e
)) {
7305 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7308 /* Fail with sharing violation. */
7309 close_file(req
, fsp
, NORMAL_CLOSE
);
7311 return NT_STATUS_SHARING_VIOLATION
;
7316 * Set the delete on close.
7318 status
= smb_set_file_disposition_info(conn
,
7324 if (!NT_STATUS_IS_OK(status
)) {
7325 close_file(req
, fsp
, NORMAL_CLOSE
);
7330 return close_file(req
, fsp
, NORMAL_CLOSE
);
7333 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7334 struct smb_request
*req
,
7335 TALLOC_CTX
*mem_ctx
,
7336 uint16_t info_level
,
7338 struct smb_filename
*smb_fname
,
7339 char **ppdata
, int total_data
,
7342 char *pdata
= *ppdata
;
7343 NTSTATUS status
= NT_STATUS_OK
;
7344 int data_return_size
= 0;
7348 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7349 return NT_STATUS_INVALID_LEVEL
;
7352 if (!CAN_WRITE(conn
)) {
7353 /* Allow POSIX opens. The open path will deny
7354 * any non-readonly opens. */
7355 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7356 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7360 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7361 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7362 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7364 switch (info_level
) {
7366 case SMB_INFO_STANDARD
:
7368 status
= smb_set_info_standard(conn
,
7376 case SMB_INFO_SET_EA
:
7378 status
= smb_info_set_ea(conn
,
7386 case SMB_SET_FILE_BASIC_INFO
:
7387 case SMB_FILE_BASIC_INFORMATION
:
7389 status
= smb_set_file_basic_info(conn
,
7397 case SMB_FILE_ALLOCATION_INFORMATION
:
7398 case SMB_SET_FILE_ALLOCATION_INFO
:
7400 status
= smb_set_file_allocation_info(conn
, req
,
7408 case SMB_FILE_END_OF_FILE_INFORMATION
:
7409 case SMB_SET_FILE_END_OF_FILE_INFO
:
7412 * XP/Win7 both fail after the createfile with
7413 * SMB_SET_FILE_END_OF_FILE_INFO but not
7414 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7415 * The level is known here, so pass it down
7419 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7421 status
= smb_set_file_end_of_file_info(conn
, req
,
7430 case SMB_FILE_DISPOSITION_INFORMATION
:
7431 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7434 /* JRA - We used to just ignore this on a path ?
7435 * Shouldn't this be invalid level on a pathname
7438 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7439 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7442 status
= smb_set_file_disposition_info(conn
,
7450 case SMB_FILE_POSITION_INFORMATION
:
7452 status
= smb_file_position_information(conn
,
7459 case SMB_FILE_FULL_EA_INFORMATION
:
7461 status
= smb_set_file_full_ea_info(conn
,
7468 /* From tridge Samba4 :
7469 * MODE_INFORMATION in setfileinfo (I have no
7470 * idea what "mode information" on a file is - it takes a value of 0,
7471 * 2, 4 or 6. What could it be?).
7474 case SMB_FILE_MODE_INFORMATION
:
7476 status
= smb_file_mode_information(conn
,
7483 * CIFS UNIX extensions.
7486 case SMB_SET_FILE_UNIX_BASIC
:
7488 status
= smb_set_file_unix_basic(conn
, req
,
7496 case SMB_SET_FILE_UNIX_INFO2
:
7498 status
= smb_set_file_unix_info2(conn
, req
,
7506 case SMB_SET_FILE_UNIX_LINK
:
7509 /* We must have a pathname for this. */
7510 return NT_STATUS_INVALID_LEVEL
;
7512 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7513 total_data
, smb_fname
);
7517 case SMB_SET_FILE_UNIX_HLINK
:
7520 /* We must have a pathname for this. */
7521 return NT_STATUS_INVALID_LEVEL
;
7523 status
= smb_set_file_unix_hlink(conn
, req
,
7529 case SMB_FILE_RENAME_INFORMATION
:
7531 status
= smb_file_rename_information(conn
, req
,
7537 #if defined(HAVE_POSIX_ACLS)
7538 case SMB_SET_POSIX_ACL
:
7540 status
= smb_set_posix_acl(conn
,
7549 case SMB_SET_POSIX_LOCK
:
7552 return NT_STATUS_INVALID_LEVEL
;
7554 status
= smb_set_posix_lock(conn
, req
,
7555 pdata
, total_data
, fsp
);
7559 case SMB_POSIX_PATH_OPEN
:
7562 /* We must have a pathname for this. */
7563 return NT_STATUS_INVALID_LEVEL
;
7566 status
= smb_posix_open(conn
, req
,
7574 case SMB_POSIX_PATH_UNLINK
:
7577 /* We must have a pathname for this. */
7578 return NT_STATUS_INVALID_LEVEL
;
7581 status
= smb_posix_unlink(conn
, req
,
7589 return NT_STATUS_INVALID_LEVEL
;
7592 if (!NT_STATUS_IS_OK(status
)) {
7596 *ret_data_size
= data_return_size
;
7597 return NT_STATUS_OK
;
7600 /****************************************************************************
7601 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7602 ****************************************************************************/
7604 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7605 struct smb_request
*req
,
7606 unsigned int tran_call
,
7607 char **pparams
, int total_params
,
7608 char **ppdata
, int total_data
,
7609 unsigned int max_data_bytes
)
7611 char *params
= *pparams
;
7612 char *pdata
= *ppdata
;
7614 struct smb_filename
*smb_fname
= NULL
;
7615 files_struct
*fsp
= NULL
;
7616 NTSTATUS status
= NT_STATUS_OK
;
7617 int data_return_size
= 0;
7620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7624 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7625 if (total_params
< 4) {
7626 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7630 fsp
= file_fsp(req
, SVAL(params
,0));
7631 /* Basic check for non-null fsp. */
7632 if (!check_fsp_open(conn
, req
, fsp
)) {
7635 info_level
= SVAL(params
,2);
7637 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7639 if (!NT_STATUS_IS_OK(status
)) {
7640 reply_nterror(req
, status
);
7644 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7646 * This is actually a SETFILEINFO on a directory
7647 * handle (returned from an NT SMB). NT5.0 seems
7648 * to do this call. JRA.
7650 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7651 /* Always do lstat for UNIX calls. */
7652 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7653 DEBUG(3,("call_trans2setfilepathinfo: "
7654 "SMB_VFS_LSTAT of %s failed "
7656 smb_fname_str_dbg(smb_fname
),
7658 reply_nterror(req
, map_nt_error_from_unix(errno
));
7662 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7663 DEBUG(3,("call_trans2setfilepathinfo: "
7664 "fileinfo of %s failed (%s)\n",
7665 smb_fname_str_dbg(smb_fname
),
7667 reply_nterror(req
, map_nt_error_from_unix(errno
));
7671 } else if (fsp
->print_file
) {
7673 * Doing a DELETE_ON_CLOSE should cancel a print job.
7675 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7676 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7678 DEBUG(3,("call_trans2setfilepathinfo: "
7679 "Cancelling print job (%s)\n",
7683 send_trans2_replies(conn
, req
, params
, 2,
7689 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7694 * Original code - this is an open file.
7696 if (!check_fsp(conn
, req
, fsp
)) {
7700 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7701 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7702 "of fnum %d failed (%s)\n", fsp
->fnum
,
7704 reply_nterror(req
, map_nt_error_from_unix(errno
));
7710 uint32_t ucf_flags
= 0;
7713 if (total_params
< 7) {
7714 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7718 info_level
= SVAL(params
,0);
7719 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7720 total_params
- 6, STR_TERMINATE
,
7722 if (!NT_STATUS_IS_OK(status
)) {
7723 reply_nterror(req
, status
);
7727 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
7728 info_level
== SMB_SET_FILE_UNIX_INFO2
||
7729 info_level
== SMB_FILE_RENAME_INFORMATION
||
7730 info_level
== SMB_POSIX_PATH_UNLINK
) {
7731 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
7734 status
= filename_convert(req
, conn
,
7735 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7740 if (!NT_STATUS_IS_OK(status
)) {
7741 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7742 reply_botherror(req
,
7743 NT_STATUS_PATH_NOT_COVERED
,
7744 ERRSRV
, ERRbadpath
);
7747 reply_nterror(req
, status
);
7751 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7753 * For CIFS UNIX extensions the target name may not exist.
7756 /* Always do lstat for UNIX calls. */
7757 SMB_VFS_LSTAT(conn
, smb_fname
);
7759 } else if (!VALID_STAT(smb_fname
->st
) &&
7760 SMB_VFS_STAT(conn
, smb_fname
)) {
7761 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7763 smb_fname_str_dbg(smb_fname
),
7765 reply_nterror(req
, map_nt_error_from_unix(errno
));
7770 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7771 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7772 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7774 /* Realloc the parameter size */
7775 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7776 if (*pparams
== NULL
) {
7777 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7784 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7790 if (!NT_STATUS_IS_OK(status
)) {
7791 if (open_was_deferred(req
->mid
)) {
7792 /* We have re-scheduled this call. */
7795 if (blocking_lock_was_deferred(req
->mid
)) {
7796 /* We have re-scheduled this call. */
7799 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7800 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7801 ERRSRV
, ERRbadpath
);
7804 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7805 reply_openerror(req
, status
);
7809 reply_nterror(req
, status
);
7813 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7819 /****************************************************************************
7820 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7821 ****************************************************************************/
7823 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7824 char **pparams
, int total_params
,
7825 char **ppdata
, int total_data
,
7826 unsigned int max_data_bytes
)
7828 struct smb_filename
*smb_dname
= NULL
;
7829 char *params
= *pparams
;
7830 char *pdata
= *ppdata
;
7831 char *directory
= NULL
;
7832 NTSTATUS status
= NT_STATUS_OK
;
7833 struct ea_list
*ea_list
= NULL
;
7834 TALLOC_CTX
*ctx
= talloc_tos();
7836 if (!CAN_WRITE(conn
)) {
7837 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7841 if (total_params
< 5) {
7842 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7846 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7847 total_params
- 4, STR_TERMINATE
,
7849 if (!NT_STATUS_IS_OK(status
)) {
7850 reply_nterror(req
, status
);
7854 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7856 status
= filename_convert(ctx
,
7858 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7864 if (!NT_STATUS_IS_OK(status
)) {
7865 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7866 reply_botherror(req
,
7867 NT_STATUS_PATH_NOT_COVERED
,
7868 ERRSRV
, ERRbadpath
);
7871 reply_nterror(req
, status
);
7876 * OS/2 workplace shell seems to send SET_EA requests of "null"
7877 * length (4 bytes containing IVAL 4).
7878 * They seem to have no effect. Bug #3212. JRA.
7881 if (total_data
&& (total_data
!= 4)) {
7882 /* Any data in this call is an EA list. */
7883 if (total_data
< 10) {
7884 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7888 if (IVAL(pdata
,0) > total_data
) {
7889 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7890 IVAL(pdata
,0), (unsigned int)total_data
));
7891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7895 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7898 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7902 if (!lp_ea_support(SNUM(conn
))) {
7903 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7907 /* If total_data == 4 Windows doesn't care what values
7908 * are placed in that field, it just ignores them.
7909 * The System i QNTC IBM SMB client puts bad values here,
7910 * so ignore them. */
7912 status
= create_directory(conn
, req
, smb_dname
);
7914 if (!NT_STATUS_IS_OK(status
)) {
7915 reply_nterror(req
, status
);
7919 /* Try and set any given EA. */
7921 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7922 if (!NT_STATUS_IS_OK(status
)) {
7923 reply_nterror(req
, status
);
7928 /* Realloc the parameter and data sizes */
7929 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7930 if(*pparams
== NULL
) {
7931 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7938 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7941 TALLOC_FREE(smb_dname
);
7945 /****************************************************************************
7946 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7947 We don't actually do this - we just send a null response.
7948 ****************************************************************************/
7950 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7951 struct smb_request
*req
,
7952 char **pparams
, int total_params
,
7953 char **ppdata
, int total_data
,
7954 unsigned int max_data_bytes
)
7956 char *params
= *pparams
;
7959 if (total_params
< 6) {
7960 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7964 info_level
= SVAL(params
,4);
7965 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7967 switch (info_level
) {
7972 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7976 /* Realloc the parameter and data sizes */
7977 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7978 if (*pparams
== NULL
) {
7979 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7984 SSVAL(params
,0,fnf_handle
);
7985 SSVAL(params
,2,0); /* No changes */
7986 SSVAL(params
,4,0); /* No EA errors */
7993 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7998 /****************************************************************************
7999 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8000 changes). Currently this does nothing.
8001 ****************************************************************************/
8003 static void call_trans2findnotifynext(connection_struct
*conn
,
8004 struct smb_request
*req
,
8005 char **pparams
, int total_params
,
8006 char **ppdata
, int total_data
,
8007 unsigned int max_data_bytes
)
8009 char *params
= *pparams
;
8011 DEBUG(3,("call_trans2findnotifynext\n"));
8013 /* Realloc the parameter and data sizes */
8014 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8015 if (*pparams
== NULL
) {
8016 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8021 SSVAL(params
,0,0); /* No changes */
8022 SSVAL(params
,2,0); /* No EA errors */
8024 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8029 /****************************************************************************
8030 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8031 ****************************************************************************/
8033 static void call_trans2getdfsreferral(connection_struct
*conn
,
8034 struct smb_request
*req
,
8035 char **pparams
, int total_params
,
8036 char **ppdata
, int total_data
,
8037 unsigned int max_data_bytes
)
8039 char *params
= *pparams
;
8040 char *pathname
= NULL
;
8042 int max_referral_level
;
8043 NTSTATUS status
= NT_STATUS_OK
;
8044 TALLOC_CTX
*ctx
= talloc_tos();
8046 DEBUG(10,("call_trans2getdfsreferral\n"));
8048 if (total_params
< 3) {
8049 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8053 max_referral_level
= SVAL(params
,0);
8055 if(!lp_host_msdfs()) {
8056 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8060 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8061 total_params
- 2, STR_TERMINATE
);
8063 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8066 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8067 ppdata
,&status
)) < 0) {
8068 reply_nterror(req
, status
);
8072 SSVAL(req
->inbuf
, smb_flg2
,
8073 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8074 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8079 #define LMCAT_SPL 0x53
8080 #define LMFUNC_GETJOBID 0x60
8082 /****************************************************************************
8083 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8084 ****************************************************************************/
8086 static void call_trans2ioctl(connection_struct
*conn
,
8087 struct smb_request
*req
,
8088 char **pparams
, int total_params
,
8089 char **ppdata
, int total_data
,
8090 unsigned int max_data_bytes
)
8092 char *pdata
= *ppdata
;
8093 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8095 /* check for an invalid fid before proceeding */
8098 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8102 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8103 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8104 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8105 if (*ppdata
== NULL
) {
8106 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8111 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8112 CAN ACCEPT THIS IN UNICODE. JRA. */
8114 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8115 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8116 global_myname(), 15,
8117 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8118 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8119 lp_servicename(SNUM(conn
)), 13,
8120 STR_ASCII
|STR_TERMINATE
); /* Service name */
8121 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8126 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8127 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8130 /****************************************************************************
8131 Reply to a SMBfindclose (stop trans2 directory search).
8132 ****************************************************************************/
8134 void reply_findclose(struct smb_request
*req
)
8137 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8139 START_PROFILE(SMBfindclose
);
8142 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8143 END_PROFILE(SMBfindclose
);
8147 dptr_num
= SVALS(req
->vwv
+0, 0);
8149 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8151 dptr_close(sconn
, &dptr_num
);
8153 reply_outbuf(req
, 0, 0);
8155 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8157 END_PROFILE(SMBfindclose
);
8161 /****************************************************************************
8162 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8163 ****************************************************************************/
8165 void reply_findnclose(struct smb_request
*req
)
8169 START_PROFILE(SMBfindnclose
);
8172 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8173 END_PROFILE(SMBfindnclose
);
8177 dptr_num
= SVAL(req
->vwv
+0, 0);
8179 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8181 /* We never give out valid handles for a
8182 findnotifyfirst - so any dptr_num is ok here.
8185 reply_outbuf(req
, 0, 0);
8187 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8189 END_PROFILE(SMBfindnclose
);
8193 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8194 struct trans_state
*state
)
8196 if (get_Protocol() >= PROTOCOL_NT1
) {
8197 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8198 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8201 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8202 if (state
->call
!= TRANSACT2_QFSINFO
&&
8203 state
->call
!= TRANSACT2_SETFSINFO
) {
8204 DEBUG(0,("handle_trans2: encryption required "
8206 (unsigned int)state
->call
));
8207 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8212 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8214 /* Now we must call the relevant TRANS2 function */
8215 switch(state
->call
) {
8216 case TRANSACT2_OPEN
:
8218 START_PROFILE(Trans2_open
);
8219 call_trans2open(conn
, req
,
8220 &state
->param
, state
->total_param
,
8221 &state
->data
, state
->total_data
,
8222 state
->max_data_return
);
8223 END_PROFILE(Trans2_open
);
8227 case TRANSACT2_FINDFIRST
:
8229 START_PROFILE(Trans2_findfirst
);
8230 call_trans2findfirst(conn
, req
,
8231 &state
->param
, state
->total_param
,
8232 &state
->data
, state
->total_data
,
8233 state
->max_data_return
);
8234 END_PROFILE(Trans2_findfirst
);
8238 case TRANSACT2_FINDNEXT
:
8240 START_PROFILE(Trans2_findnext
);
8241 call_trans2findnext(conn
, req
,
8242 &state
->param
, state
->total_param
,
8243 &state
->data
, state
->total_data
,
8244 state
->max_data_return
);
8245 END_PROFILE(Trans2_findnext
);
8249 case TRANSACT2_QFSINFO
:
8251 START_PROFILE(Trans2_qfsinfo
);
8252 call_trans2qfsinfo(conn
, req
,
8253 &state
->param
, state
->total_param
,
8254 &state
->data
, state
->total_data
,
8255 state
->max_data_return
);
8256 END_PROFILE(Trans2_qfsinfo
);
8260 case TRANSACT2_SETFSINFO
:
8262 START_PROFILE(Trans2_setfsinfo
);
8263 call_trans2setfsinfo(conn
, req
,
8264 &state
->param
, state
->total_param
,
8265 &state
->data
, state
->total_data
,
8266 state
->max_data_return
);
8267 END_PROFILE(Trans2_setfsinfo
);
8271 case TRANSACT2_QPATHINFO
:
8272 case TRANSACT2_QFILEINFO
:
8274 START_PROFILE(Trans2_qpathinfo
);
8275 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8276 &state
->param
, state
->total_param
,
8277 &state
->data
, state
->total_data
,
8278 state
->max_data_return
);
8279 END_PROFILE(Trans2_qpathinfo
);
8283 case TRANSACT2_SETPATHINFO
:
8284 case TRANSACT2_SETFILEINFO
:
8286 START_PROFILE(Trans2_setpathinfo
);
8287 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8288 &state
->param
, state
->total_param
,
8289 &state
->data
, state
->total_data
,
8290 state
->max_data_return
);
8291 END_PROFILE(Trans2_setpathinfo
);
8295 case TRANSACT2_FINDNOTIFYFIRST
:
8297 START_PROFILE(Trans2_findnotifyfirst
);
8298 call_trans2findnotifyfirst(conn
, req
,
8299 &state
->param
, state
->total_param
,
8300 &state
->data
, state
->total_data
,
8301 state
->max_data_return
);
8302 END_PROFILE(Trans2_findnotifyfirst
);
8306 case TRANSACT2_FINDNOTIFYNEXT
:
8308 START_PROFILE(Trans2_findnotifynext
);
8309 call_trans2findnotifynext(conn
, req
,
8310 &state
->param
, state
->total_param
,
8311 &state
->data
, state
->total_data
,
8312 state
->max_data_return
);
8313 END_PROFILE(Trans2_findnotifynext
);
8317 case TRANSACT2_MKDIR
:
8319 START_PROFILE(Trans2_mkdir
);
8320 call_trans2mkdir(conn
, req
,
8321 &state
->param
, state
->total_param
,
8322 &state
->data
, state
->total_data
,
8323 state
->max_data_return
);
8324 END_PROFILE(Trans2_mkdir
);
8328 case TRANSACT2_GET_DFS_REFERRAL
:
8330 START_PROFILE(Trans2_get_dfs_referral
);
8331 call_trans2getdfsreferral(conn
, req
,
8332 &state
->param
, state
->total_param
,
8333 &state
->data
, state
->total_data
,
8334 state
->max_data_return
);
8335 END_PROFILE(Trans2_get_dfs_referral
);
8339 case TRANSACT2_IOCTL
:
8341 START_PROFILE(Trans2_ioctl
);
8342 call_trans2ioctl(conn
, req
,
8343 &state
->param
, state
->total_param
,
8344 &state
->data
, state
->total_data
,
8345 state
->max_data_return
);
8346 END_PROFILE(Trans2_ioctl
);
8351 /* Error in request */
8352 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8353 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8357 /****************************************************************************
8358 Reply to a SMBtrans2.
8359 ****************************************************************************/
8361 void reply_trans2(struct smb_request
*req
)
8363 connection_struct
*conn
= req
->conn
;
8368 unsigned int tran_call
;
8369 struct trans_state
*state
;
8372 START_PROFILE(SMBtrans2
);
8374 if (req
->wct
< 14) {
8375 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8376 END_PROFILE(SMBtrans2
);
8380 dsoff
= SVAL(req
->vwv
+12, 0);
8381 dscnt
= SVAL(req
->vwv
+11, 0);
8382 psoff
= SVAL(req
->vwv
+10, 0);
8383 pscnt
= SVAL(req
->vwv
+9, 0);
8384 tran_call
= SVAL(req
->vwv
+14, 0);
8386 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8387 if (!NT_STATUS_IS_OK(result
)) {
8388 DEBUG(2, ("Got invalid trans2 request: %s\n",
8389 nt_errstr(result
)));
8390 reply_nterror(req
, result
);
8391 END_PROFILE(SMBtrans2
);
8396 switch (tran_call
) {
8397 /* List the allowed trans2 calls on IPC$ */
8398 case TRANSACT2_OPEN
:
8399 case TRANSACT2_GET_DFS_REFERRAL
:
8400 case TRANSACT2_QFILEINFO
:
8401 case TRANSACT2_QFSINFO
:
8402 case TRANSACT2_SETFSINFO
:
8405 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8406 END_PROFILE(SMBtrans2
);
8411 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8412 DEBUG(0, ("talloc failed\n"));
8413 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8414 END_PROFILE(SMBtrans2
);
8418 state
->cmd
= SMBtrans2
;
8420 state
->mid
= req
->mid
;
8421 state
->vuid
= req
->vuid
;
8422 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8423 state
->setup
= NULL
;
8424 state
->total_param
= SVAL(req
->vwv
+0, 0);
8425 state
->param
= NULL
;
8426 state
->total_data
= SVAL(req
->vwv
+1, 0);
8428 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8429 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8430 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8431 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8432 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8434 state
->call
= tran_call
;
8436 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8437 is so as a sanity check */
8438 if (state
->setup_count
!= 1) {
8440 * Need to have rc=0 for ioctl to get job id for OS/2.
8441 * Network printing will fail if function is not successful.
8442 * Similar function in reply.c will be used if protocol
8443 * is LANMAN1.0 instead of LM1.2X002.
8444 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8445 * outbuf doesn't have to be set(only job id is used).
8447 if ( (state
->setup_count
== 4)
8448 && (tran_call
== TRANSACT2_IOCTL
)
8449 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8450 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8451 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8453 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8454 DEBUG(2,("Transaction is %d\n",tran_call
));
8456 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8457 END_PROFILE(SMBtrans2
);
8462 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8465 if (state
->total_data
) {
8467 if (trans_oob(state
->total_data
, 0, dscnt
)
8468 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8472 /* Can't use talloc here, the core routines do realloc on the
8473 * params and data. */
8474 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8475 if (state
->data
== NULL
) {
8476 DEBUG(0,("reply_trans2: data malloc fail for %u "
8477 "bytes !\n", (unsigned int)state
->total_data
));
8479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8480 END_PROFILE(SMBtrans2
);
8484 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8487 if (state
->total_param
) {
8489 if (trans_oob(state
->total_param
, 0, pscnt
)
8490 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8494 /* Can't use talloc here, the core routines do realloc on the
8495 * params and data. */
8496 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8497 if (state
->param
== NULL
) {
8498 DEBUG(0,("reply_trans: param malloc fail for %u "
8499 "bytes !\n", (unsigned int)state
->total_param
));
8500 SAFE_FREE(state
->data
);
8502 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8503 END_PROFILE(SMBtrans2
);
8507 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8510 state
->received_data
= dscnt
;
8511 state
->received_param
= pscnt
;
8513 if ((state
->received_param
== state
->total_param
) &&
8514 (state
->received_data
== state
->total_data
)) {
8516 handle_trans2(conn
, req
, state
);
8518 SAFE_FREE(state
->data
);
8519 SAFE_FREE(state
->param
);
8521 END_PROFILE(SMBtrans2
);
8525 DLIST_ADD(conn
->pending_trans
, state
);
8527 /* We need to send an interim response then receive the rest
8528 of the parameter/data bytes */
8529 reply_outbuf(req
, 0, 0);
8530 show_msg((char *)req
->outbuf
);
8531 END_PROFILE(SMBtrans2
);
8536 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8537 SAFE_FREE(state
->data
);
8538 SAFE_FREE(state
->param
);
8540 END_PROFILE(SMBtrans2
);
8541 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8545 /****************************************************************************
8546 Reply to a SMBtranss2
8547 ****************************************************************************/
8549 void reply_transs2(struct smb_request
*req
)
8551 connection_struct
*conn
= req
->conn
;
8552 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8553 struct trans_state
*state
;
8555 START_PROFILE(SMBtranss2
);
8557 show_msg((char *)req
->inbuf
);
8559 /* Windows clients expect all replies to
8560 a transact secondary (SMBtranss2 0x33)
8561 to have a command code of transact
8562 (SMBtrans2 0x32). See bug #8989
8563 and also [MS-CIFS] section 2.2.4.47.2
8566 req
->cmd
= SMBtrans2
;
8569 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8570 END_PROFILE(SMBtranss2
);
8574 for (state
= conn
->pending_trans
; state
!= NULL
;
8575 state
= state
->next
) {
8576 if (state
->mid
== req
->mid
) {
8581 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8582 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8583 END_PROFILE(SMBtranss2
);
8587 /* Revise state->total_param and state->total_data in case they have
8588 changed downwards */
8590 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8591 state
->total_param
= SVAL(req
->vwv
+0, 0);
8592 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8593 state
->total_data
= SVAL(req
->vwv
+1, 0);
8595 pcnt
= SVAL(req
->vwv
+2, 0);
8596 poff
= SVAL(req
->vwv
+3, 0);
8597 pdisp
= SVAL(req
->vwv
+4, 0);
8599 dcnt
= SVAL(req
->vwv
+5, 0);
8600 doff
= SVAL(req
->vwv
+6, 0);
8601 ddisp
= SVAL(req
->vwv
+7, 0);
8603 state
->received_param
+= pcnt
;
8604 state
->received_data
+= dcnt
;
8606 if ((state
->received_data
> state
->total_data
) ||
8607 (state
->received_param
> state
->total_param
))
8611 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8612 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8615 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8619 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8620 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8623 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8626 if ((state
->received_param
< state
->total_param
) ||
8627 (state
->received_data
< state
->total_data
)) {
8628 END_PROFILE(SMBtranss2
);
8632 handle_trans2(conn
, req
, state
);
8634 DLIST_REMOVE(conn
->pending_trans
, state
);
8635 SAFE_FREE(state
->data
);
8636 SAFE_FREE(state
->param
);
8639 END_PROFILE(SMBtranss2
);
8644 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8645 DLIST_REMOVE(conn
->pending_trans
, state
);
8646 SAFE_FREE(state
->data
);
8647 SAFE_FREE(state
->param
);
8649 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8650 END_PROFILE(SMBtranss2
);