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
);
853 * We might have SMBtrans2s in req which was transferred to
854 * the outbuf, fix that.
856 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
858 /* Set total params and data to be sent */
859 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
860 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
862 /* Calculate how many parameters and data we can fit into
863 * this packet. Parameters get precedence
866 params_sent_thistime
= MIN(params_to_send
,useable_space
);
867 data_sent_thistime
= useable_space
- params_sent_thistime
;
868 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
870 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
872 /* smb_proff is the offset from the start of the SMB header to the
873 parameter bytes, however the first 4 bytes of outbuf are
874 the Netbios over TCP header. Thus use smb_base() to subtract
875 them from the calculation */
877 SSVAL(req
->outbuf
,smb_proff
,
878 ((smb_buf(req
->outbuf
)+alignment_offset
)
879 - smb_base(req
->outbuf
)));
881 if(params_sent_thistime
== 0)
882 SSVAL(req
->outbuf
,smb_prdisp
,0);
884 /* Absolute displacement of param bytes sent in this packet */
885 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
887 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
888 if(data_sent_thistime
== 0) {
889 SSVAL(req
->outbuf
,smb_droff
,0);
890 SSVAL(req
->outbuf
,smb_drdisp
, 0);
892 /* The offset of the data bytes is the offset of the
893 parameter bytes plus the number of parameters being sent this time */
894 SSVAL(req
->outbuf
, smb_droff
,
895 ((smb_buf(req
->outbuf
)+alignment_offset
)
896 - smb_base(req
->outbuf
))
897 + params_sent_thistime
+ data_alignment_offset
);
898 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
901 /* Initialize the padding for alignment */
903 if (alignment_offset
!= 0) {
904 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
907 /* Copy the param bytes into the packet */
909 if(params_sent_thistime
) {
910 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
911 params_sent_thistime
);
914 /* Copy in the data bytes */
915 if(data_sent_thistime
) {
916 if (data_alignment_offset
!= 0) {
917 memset((smb_buf(req
->outbuf
)+alignment_offset
+
918 params_sent_thistime
), 0,
919 data_alignment_offset
);
921 memcpy(smb_buf(req
->outbuf
)+alignment_offset
922 +params_sent_thistime
+data_alignment_offset
,
923 pd
,data_sent_thistime
);
926 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
927 params_sent_thistime
, data_sent_thistime
, useable_space
));
928 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
929 params_to_send
, data_to_send
, paramsize
, datasize
));
932 error_packet_set((char *)req
->outbuf
,
933 ERRDOS
,ERRbufferoverflow
,
934 STATUS_BUFFER_OVERFLOW
,
938 /* Send the packet */
939 show_msg((char *)req
->outbuf
);
940 if (!srv_send_smb(smbd_server_fd(),
943 IS_CONN_ENCRYPTED(conn
),
945 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
947 TALLOC_FREE(req
->outbuf
);
949 pp
+= params_sent_thistime
;
950 pd
+= data_sent_thistime
;
952 params_to_send
-= params_sent_thistime
;
953 data_to_send
-= data_sent_thistime
;
956 if(params_to_send
< 0 || data_to_send
< 0) {
957 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
958 params_to_send
, data_to_send
));
966 /****************************************************************************
967 Reply to a TRANSACT2_OPEN.
968 ****************************************************************************/
970 static void call_trans2open(connection_struct
*conn
,
971 struct smb_request
*req
,
972 char **pparams
, int total_params
,
973 char **ppdata
, int total_data
,
974 unsigned int max_data_bytes
)
976 struct smb_filename
*smb_fname
= NULL
;
977 char *params
= *pparams
;
978 char *pdata
= *ppdata
;
983 bool return_additional_info
;
996 struct ea_list
*ea_list
= NULL
;
1001 uint32 create_disposition
;
1002 uint32 create_options
= 0;
1003 TALLOC_CTX
*ctx
= talloc_tos();
1006 * Ensure we have enough parameters to perform the operation.
1009 if (total_params
< 29) {
1010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1014 flags
= SVAL(params
, 0);
1015 deny_mode
= SVAL(params
, 2);
1016 open_attr
= SVAL(params
,6);
1017 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1018 if (oplock_request
) {
1019 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1023 return_additional_info
= BITSETW(params
,0);
1024 open_sattr
= SVAL(params
, 4);
1025 open_time
= make_unix_date3(params
+8);
1027 open_ofun
= SVAL(params
,12);
1028 open_size
= IVAL(params
,14);
1029 pname
= ¶ms
[28];
1032 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1036 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1037 total_params
- 28, STR_TERMINATE
,
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 reply_nterror(req
, status
);
1044 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1045 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1046 (unsigned int)open_ofun
, open_size
));
1048 status
= filename_convert(ctx
,
1050 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1055 if (!NT_STATUS_IS_OK(status
)) {
1056 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1057 reply_botherror(req
,
1058 NT_STATUS_PATH_NOT_COVERED
,
1059 ERRSRV
, ERRbadpath
);
1062 reply_nterror(req
, status
);
1066 if (open_ofun
== 0) {
1067 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1071 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1072 &access_mask
, &share_mode
,
1073 &create_disposition
,
1075 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1079 /* Any data in this call is an EA list. */
1080 if (total_data
&& (total_data
!= 4)) {
1081 if (total_data
< 10) {
1082 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1086 if (IVAL(pdata
,0) > total_data
) {
1087 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1088 IVAL(pdata
,0), (unsigned int)total_data
));
1089 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1093 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1096 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1100 if (!lp_ea_support(SNUM(conn
))) {
1101 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1106 status
= SMB_VFS_CREATE_FILE(
1109 0, /* root_dir_fid */
1110 smb_fname
, /* fname */
1111 access_mask
, /* access_mask */
1112 share_mode
, /* share_access */
1113 create_disposition
, /* create_disposition*/
1114 create_options
, /* create_options */
1115 open_attr
, /* file_attributes */
1116 oplock_request
, /* oplock_request */
1117 open_size
, /* allocation_size */
1119 ea_list
, /* ea_list */
1121 &smb_action
); /* psbuf */
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 if (open_was_deferred(req
->mid
)) {
1125 /* We have re-scheduled this call. */
1128 reply_openerror(req
, status
);
1132 size
= get_file_size_stat(&smb_fname
->st
);
1133 fattr
= dos_mode(conn
, smb_fname
);
1134 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1135 inode
= smb_fname
->st
.st_ex_ino
;
1137 close_file(req
, fsp
, ERROR_CLOSE
);
1138 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1142 /* Realloc the size of parameters and data we will return */
1143 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1144 if(*pparams
== NULL
) {
1145 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1150 SSVAL(params
,0,fsp
->fnum
);
1151 SSVAL(params
,2,fattr
);
1152 srv_put_dos_date2(params
,4, mtime
);
1153 SIVAL(params
,8, (uint32
)size
);
1154 SSVAL(params
,12,deny_mode
);
1155 SSVAL(params
,14,0); /* open_type - file or directory. */
1156 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1158 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1159 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1162 SSVAL(params
,18,smb_action
);
1165 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1167 SIVAL(params
,20,inode
);
1168 SSVAL(params
,24,0); /* Padding. */
1170 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1171 fsp
->fsp_name
->base_name
);
1172 SIVAL(params
, 26, ea_size
);
1174 SIVAL(params
, 26, 0);
1177 /* Send the required number of replies */
1178 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1180 TALLOC_FREE(smb_fname
);
1183 /*********************************************************
1184 Routine to check if a given string matches exactly.
1185 as a special case a mask of "." does NOT match. That
1186 is required for correct wildcard semantics
1187 Case can be significant or not.
1188 **********************************************************/
1190 static bool exact_match(bool has_wild
,
1191 bool case_sensitive
,
1195 if (mask
[0] == '.' && mask
[1] == 0) {
1203 if (case_sensitive
) {
1204 return strcmp(str
,mask
)==0;
1206 return StrCaseCmp(str
,mask
) == 0;
1210 /****************************************************************************
1211 Return the filetype for UNIX extensions.
1212 ****************************************************************************/
1214 static uint32
unix_filetype(mode_t mode
)
1217 return UNIX_TYPE_FILE
;
1218 else if(S_ISDIR(mode
))
1219 return UNIX_TYPE_DIR
;
1221 else if(S_ISLNK(mode
))
1222 return UNIX_TYPE_SYMLINK
;
1225 else if(S_ISCHR(mode
))
1226 return UNIX_TYPE_CHARDEV
;
1229 else if(S_ISBLK(mode
))
1230 return UNIX_TYPE_BLKDEV
;
1233 else if(S_ISFIFO(mode
))
1234 return UNIX_TYPE_FIFO
;
1237 else if(S_ISSOCK(mode
))
1238 return UNIX_TYPE_SOCKET
;
1241 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1242 return UNIX_TYPE_UNKNOWN
;
1245 /****************************************************************************
1246 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1247 ****************************************************************************/
1249 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1251 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1252 const SMB_STRUCT_STAT
*psbuf
,
1254 enum perm_type ptype
,
1259 if (perms
== SMB_MODE_NO_CHANGE
) {
1260 if (!VALID_STAT(*psbuf
)) {
1261 return NT_STATUS_INVALID_PARAMETER
;
1263 *ret_perms
= psbuf
->st_ex_mode
;
1264 return NT_STATUS_OK
;
1268 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1269 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1270 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1271 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1272 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1273 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1274 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1275 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1276 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1278 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1281 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1284 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1289 /* Apply mode mask */
1290 ret
&= lp_create_mask(SNUM(conn
));
1291 /* Add in force bits */
1292 ret
|= lp_force_create_mode(SNUM(conn
));
1295 ret
&= lp_dir_mask(SNUM(conn
));
1296 /* Add in force bits */
1297 ret
|= lp_force_dir_mode(SNUM(conn
));
1299 case PERM_EXISTING_FILE
:
1300 /* Apply mode mask */
1301 ret
&= lp_security_mask(SNUM(conn
));
1302 /* Add in force bits */
1303 ret
|= lp_force_security_mode(SNUM(conn
));
1305 case PERM_EXISTING_DIR
:
1306 /* Apply mode mask */
1307 ret
&= lp_dir_security_mask(SNUM(conn
));
1308 /* Add in force bits */
1309 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1314 return NT_STATUS_OK
;
1317 /****************************************************************************
1318 Needed to show the msdfs symlinks as directories. Modifies psbuf
1319 to be a directory if it's a msdfs link.
1320 ****************************************************************************/
1322 static bool check_msdfs_link(connection_struct
*conn
,
1323 const char *pathname
,
1324 SMB_STRUCT_STAT
*psbuf
)
1326 int saved_errno
= errno
;
1327 if(lp_host_msdfs() &&
1328 lp_msdfs_root(SNUM(conn
)) &&
1329 is_msdfs_link(conn
, pathname
, psbuf
)) {
1331 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1334 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1335 errno
= saved_errno
;
1338 errno
= saved_errno
;
1343 /****************************************************************************
1344 Get a level dependent lanman2 dir entry.
1345 ****************************************************************************/
1347 struct smbd_dirptr_lanman2_state
{
1348 connection_struct
*conn
;
1349 uint32_t info_level
;
1350 bool check_mangled_names
;
1352 bool got_exact_match
;
1355 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1361 struct smbd_dirptr_lanman2_state
*state
=
1362 (struct smbd_dirptr_lanman2_state
*)private_data
;
1364 char mangled_name
[13]; /* mangled 8.3 name. */
1368 /* Mangle fname if it's an illegal name. */
1369 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1370 ok
= name_to_8_3(dname
, mangled_name
,
1371 true, state
->conn
->params
);
1375 fname
= mangled_name
;
1380 got_match
= exact_match(state
->has_wild
,
1381 state
->conn
->case_sensitive
,
1383 state
->got_exact_match
= got_match
;
1385 got_match
= mask_match(fname
, mask
,
1386 state
->conn
->case_sensitive
);
1389 if(!got_match
&& state
->check_mangled_names
&&
1390 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1392 * It turns out that NT matches wildcards against
1393 * both long *and* short names. This may explain some
1394 * of the wildcard wierdness from old DOS clients
1395 * that some people have been seeing.... JRA.
1397 /* Force the mangling into 8.3. */
1398 ok
= name_to_8_3(fname
, mangled_name
,
1399 false, state
->conn
->params
);
1404 got_match
= exact_match(state
->has_wild
,
1405 state
->conn
->case_sensitive
,
1406 mangled_name
, mask
);
1407 state
->got_exact_match
= got_match
;
1409 got_match
= mask_match(mangled_name
, mask
,
1410 state
->conn
->case_sensitive
);
1418 *_fname
= talloc_strdup(ctx
, fname
);
1419 if (*_fname
== NULL
) {
1426 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1428 struct smb_filename
*smb_fname
,
1431 struct smbd_dirptr_lanman2_state
*state
=
1432 (struct smbd_dirptr_lanman2_state
*)private_data
;
1433 bool ms_dfs_link
= false;
1436 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1437 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't lstat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname
),
1444 } else if (!VALID_STAT(smb_fname
->st
) &&
1445 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1446 /* Needed to show the msdfs symlinks as
1449 ms_dfs_link
= check_msdfs_link(state
->conn
,
1450 smb_fname
->base_name
,
1453 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1454 "Couldn't stat [%s] (%s)\n",
1455 smb_fname_str_dbg(smb_fname
),
1462 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1464 mode
= dos_mode(state
->conn
, smb_fname
);
1471 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1472 connection_struct
*conn
,
1474 uint32_t info_level
,
1475 struct ea_list
*name_list
,
1476 bool check_mangled_names
,
1477 bool requires_resume_key
,
1480 const struct smb_filename
*smb_fname
,
1481 uint64_t space_remaining
,
1488 uint64_t *last_entry_off
)
1490 char *p
, *q
, *pdata
= *ppdata
;
1492 uint64_t file_size
= 0;
1493 uint64_t allocation_size
= 0;
1494 uint64_t file_index
= 0;
1496 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1497 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1498 time_t c_date
= (time_t)0;
1500 char *last_entry_ptr
;
1505 *out_of_space
= false;
1507 ZERO_STRUCT(mdate_ts
);
1508 ZERO_STRUCT(adate_ts
);
1509 ZERO_STRUCT(create_date_ts
);
1510 ZERO_STRUCT(cdate_ts
);
1512 if (!(mode
& aDIR
)) {
1513 file_size
= get_file_size_stat(&smb_fname
->st
);
1515 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1517 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1519 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1520 adate_ts
= smb_fname
->st
.st_ex_atime
;
1521 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1522 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1524 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1525 dos_filetime_timespec(&create_date_ts
);
1526 dos_filetime_timespec(&mdate_ts
);
1527 dos_filetime_timespec(&adate_ts
);
1528 dos_filetime_timespec(&cdate_ts
);
1531 create_date
= convert_timespec_to_time_t(create_date_ts
);
1532 mdate
= convert_timespec_to_time_t(mdate_ts
);
1533 adate
= convert_timespec_to_time_t(adate_ts
);
1534 c_date
= convert_timespec_to_time_t(cdate_ts
);
1536 /* align the record */
1537 off
= PTR_DIFF(pdata
, base_data
);
1538 pad
= (off
+ (align
-1)) & ~(align
-1);
1541 /* initialize padding to 0 */
1543 memset(pdata
, 0, pad
);
1545 space_remaining
-= pad
;
1554 switch (info_level
) {
1555 case SMB_FIND_INFO_STANDARD
:
1556 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1557 if(requires_resume_key
) {
1561 srv_put_dos_date2(p
,0,create_date
);
1562 srv_put_dos_date2(p
,4,adate
);
1563 srv_put_dos_date2(p
,8,mdate
);
1564 SIVAL(p
,12,(uint32
)file_size
);
1565 SIVAL(p
,16,(uint32
)allocation_size
);
1569 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1570 p
+= ucs2_align(base_data
, p
, 0);
1572 len
= srvstr_push(base_data
, flags2
, p
,
1573 fname
, PTR_DIFF(end_data
, p
),
1575 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1577 SCVAL(nameptr
, -1, len
- 2);
1579 SCVAL(nameptr
, -1, 0);
1583 SCVAL(nameptr
, -1, len
- 1);
1585 SCVAL(nameptr
, -1, 0);
1591 case SMB_FIND_EA_SIZE
:
1592 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1593 if (requires_resume_key
) {
1597 srv_put_dos_date2(p
,0,create_date
);
1598 srv_put_dos_date2(p
,4,adate
);
1599 srv_put_dos_date2(p
,8,mdate
);
1600 SIVAL(p
,12,(uint32
)file_size
);
1601 SIVAL(p
,16,(uint32
)allocation_size
);
1604 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1605 smb_fname
->base_name
);
1606 SIVAL(p
,22,ea_size
); /* Extended attributes */
1610 len
= srvstr_push(base_data
, flags2
,
1611 p
, fname
, PTR_DIFF(end_data
, p
),
1612 STR_TERMINATE
| STR_NOALIGN
);
1613 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1626 SCVAL(nameptr
,0,len
);
1628 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1631 case SMB_FIND_EA_LIST
:
1633 struct ea_list
*file_list
= NULL
;
1636 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1640 if (requires_resume_key
) {
1644 srv_put_dos_date2(p
,0,create_date
);
1645 srv_put_dos_date2(p
,4,adate
);
1646 srv_put_dos_date2(p
,8,mdate
);
1647 SIVAL(p
,12,(uint32
)file_size
);
1648 SIVAL(p
,16,(uint32
)allocation_size
);
1650 p
+= 22; /* p now points to the EA area. */
1652 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1653 smb_fname
->base_name
,
1655 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1657 /* We need to determine if this entry will fit in the space available. */
1658 /* Max string size is 255 bytes. */
1659 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1660 *out_of_space
= true;
1661 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1662 return False
; /* Not finished - just out of space */
1665 /* Push the ea_data followed by the name. */
1666 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1668 len
= srvstr_push(base_data
, flags2
,
1669 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1670 STR_TERMINATE
| STR_NOALIGN
);
1671 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1684 SCVAL(nameptr
,0,len
);
1686 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1690 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1692 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1694 SIVAL(p
,0,reskey
); p
+= 4;
1695 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1696 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1697 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1698 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1699 SOFF_T(p
,0,file_size
); p
+= 8;
1700 SOFF_T(p
,0,allocation_size
); p
+= 8;
1701 SIVAL(p
,0,mode
); p
+= 4;
1702 q
= p
; p
+= 4; /* q is placeholder for name length. */
1704 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1705 smb_fname
->base_name
);
1706 SIVAL(p
,0,ea_size
); /* Extended attributes */
1709 /* Clear the short name buffer. This is
1710 * IMPORTANT as not doing so will trigger
1711 * a Win2k client bug. JRA.
1713 if (!was_8_3
&& check_mangled_names
) {
1714 char mangled_name
[13]; /* mangled 8.3 name. */
1715 if (!name_to_8_3(fname
,mangled_name
,True
,
1717 /* Error - mangle failed ! */
1718 memset(mangled_name
,'\0',12);
1720 mangled_name
[12] = 0;
1721 len
= srvstr_push(base_data
, flags2
,
1722 p
+2, mangled_name
, 24,
1723 STR_UPPER
|STR_UNICODE
);
1725 memset(p
+ 2 + len
,'\0',24 - len
);
1732 len
= srvstr_push(base_data
, flags2
, p
,
1733 fname
, PTR_DIFF(end_data
, p
),
1734 STR_TERMINATE_ASCII
);
1738 len
= PTR_DIFF(p
, pdata
);
1739 pad
= (len
+ (align
-1)) & ~(align
-1);
1741 * offset to the next entry, the caller
1742 * will overwrite it for the last entry
1743 * that's why we always include the padding
1747 * set padding to zero
1750 memset(p
, 0, pad
- len
);
1757 case SMB_FIND_FILE_DIRECTORY_INFO
:
1758 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1760 SIVAL(p
,0,reskey
); p
+= 4;
1761 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1762 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1763 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1764 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1765 SOFF_T(p
,0,file_size
); p
+= 8;
1766 SOFF_T(p
,0,allocation_size
); p
+= 8;
1767 SIVAL(p
,0,mode
); p
+= 4;
1768 len
= srvstr_push(base_data
, flags2
,
1769 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1770 STR_TERMINATE_ASCII
);
1774 len
= PTR_DIFF(p
, pdata
);
1775 pad
= (len
+ (align
-1)) & ~(align
-1);
1777 * offset to the next entry, the caller
1778 * will overwrite it for the last entry
1779 * that's why we always include the padding
1783 * set padding to zero
1786 memset(p
, 0, pad
- len
);
1793 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1794 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1796 SIVAL(p
,0,reskey
); p
+= 4;
1797 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1798 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1799 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1800 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1801 SOFF_T(p
,0,file_size
); p
+= 8;
1802 SOFF_T(p
,0,allocation_size
); p
+= 8;
1803 SIVAL(p
,0,mode
); p
+= 4;
1804 q
= p
; p
+= 4; /* q is placeholder for name length. */
1806 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1807 smb_fname
->base_name
);
1808 SIVAL(p
,0,ea_size
); /* Extended attributes */
1811 len
= srvstr_push(base_data
, flags2
, p
,
1812 fname
, PTR_DIFF(end_data
, p
),
1813 STR_TERMINATE_ASCII
);
1817 len
= PTR_DIFF(p
, pdata
);
1818 pad
= (len
+ (align
-1)) & ~(align
-1);
1820 * offset to the next entry, the caller
1821 * will overwrite it for the last entry
1822 * that's why we always include the padding
1826 * set padding to zero
1829 memset(p
, 0, pad
- len
);
1836 case SMB_FIND_FILE_NAMES_INFO
:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1839 SIVAL(p
,0,reskey
); p
+= 4;
1841 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1842 acl on a dir (tridge) */
1843 len
= srvstr_push(base_data
, flags2
, p
,
1844 fname
, PTR_DIFF(end_data
, p
),
1845 STR_TERMINATE_ASCII
);
1849 len
= PTR_DIFF(p
, pdata
);
1850 pad
= (len
+ (align
-1)) & ~(align
-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1858 * set padding to zero
1861 memset(p
, 0, pad
- len
);
1868 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1871 SIVAL(p
,0,reskey
); p
+= 4;
1872 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1873 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1874 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1876 SOFF_T(p
,0,file_size
); p
+= 8;
1877 SOFF_T(p
,0,allocation_size
); p
+= 8;
1878 SIVAL(p
,0,mode
); p
+= 4;
1879 q
= p
; p
+= 4; /* q is placeholder for name length. */
1881 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1882 smb_fname
->base_name
);
1883 SIVAL(p
,0,ea_size
); /* Extended attributes */
1886 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1887 SBVAL(p
,0,file_index
); p
+= 8;
1888 len
= srvstr_push(base_data
, flags2
, p
,
1889 fname
, PTR_DIFF(end_data
, p
),
1890 STR_TERMINATE_ASCII
);
1894 len
= PTR_DIFF(p
, pdata
);
1895 pad
= (len
+ (align
-1)) & ~(align
-1);
1897 * offset to the next entry, the caller
1898 * will overwrite it for the last entry
1899 * that's why we always include the padding
1903 * set padding to zero
1906 memset(p
, 0, pad
- len
);
1913 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1914 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1915 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1917 SIVAL(p
,0,reskey
); p
+= 4;
1918 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1919 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1920 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1921 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1922 SOFF_T(p
,0,file_size
); p
+= 8;
1923 SOFF_T(p
,0,allocation_size
); p
+= 8;
1924 SIVAL(p
,0,mode
); p
+= 4;
1925 q
= p
; p
+= 4; /* q is placeholder for name length */
1927 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1928 smb_fname
->base_name
);
1929 SIVAL(p
,0,ea_size
); /* Extended attributes */
1932 /* Clear the short name buffer. This is
1933 * IMPORTANT as not doing so will trigger
1934 * a Win2k client bug. JRA.
1936 if (!was_8_3
&& check_mangled_names
) {
1937 char mangled_name
[13]; /* mangled 8.3 name. */
1938 if (!name_to_8_3(fname
,mangled_name
,True
,
1940 /* Error - mangle failed ! */
1941 memset(mangled_name
,'\0',12);
1943 mangled_name
[12] = 0;
1944 len
= srvstr_push(base_data
, flags2
,
1945 p
+2, mangled_name
, 24,
1946 STR_UPPER
|STR_UNICODE
);
1949 memset(p
+ 2 + len
,'\0',24 - len
);
1956 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1957 SBVAL(p
,0,file_index
); p
+= 8;
1958 len
= srvstr_push(base_data
, flags2
, p
,
1959 fname
, PTR_DIFF(end_data
, p
),
1960 STR_TERMINATE_ASCII
);
1964 len
= PTR_DIFF(p
, pdata
);
1965 pad
= (len
+ (align
-1)) & ~(align
-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1973 * set padding to zero
1976 memset(p
, 0, pad
- len
);
1983 /* CIFS UNIX Extension. */
1985 case SMB_FIND_FILE_UNIX
:
1986 case SMB_FIND_FILE_UNIX_INFO2
:
1988 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1990 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1992 if (info_level
== SMB_FIND_FILE_UNIX
) {
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1994 p
= store_file_unix_basic(conn
, p
,
1995 NULL
, &smb_fname
->st
);
1996 len
= srvstr_push(base_data
, flags2
, p
,
1997 fname
, PTR_DIFF(end_data
, p
),
2000 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2001 p
= store_file_unix_basic_info2(conn
, p
,
2002 NULL
, &smb_fname
->st
);
2005 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2006 PTR_DIFF(end_data
, p
), 0);
2007 SIVAL(nameptr
, 0, len
);
2012 len
= PTR_DIFF(p
, pdata
);
2013 pad
= (len
+ (align
-1)) & ~(align
-1);
2015 * offset to the next entry, the caller
2016 * will overwrite it for the last entry
2017 * that's why we always include the padding
2021 * set padding to zero
2024 memset(p
, 0, pad
- len
);
2029 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2037 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2038 *out_of_space
= true;
2039 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2040 return false; /* Not finished - just out of space */
2043 /* Setup the last entry pointer, as an offset from base_data */
2044 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2045 /* Advance the data pointer to the next slot */
2051 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2052 connection_struct
*conn
,
2053 struct dptr_struct
*dirptr
,
2055 const char *path_mask
,
2058 int requires_resume_key
,
2066 int space_remaining
,
2068 bool *got_exact_match
,
2069 int *_last_entry_off
,
2070 struct ea_list
*name_list
)
2073 const char *mask
= NULL
;
2074 long prev_dirpos
= 0;
2077 struct smb_filename
*smb_fname
= NULL
;
2078 struct smbd_dirptr_lanman2_state state
;
2080 uint64_t last_entry_off
= 0;
2084 state
.info_level
= info_level
;
2085 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2086 state
.has_wild
= dptr_has_wild(dirptr
);
2087 state
.got_exact_match
= false;
2089 *out_of_space
= false;
2090 *got_exact_match
= false;
2092 p
= strrchr_m(path_mask
,'/');
2103 ok
= smbd_dirptr_get_entry(ctx
,
2109 smbd_dirptr_lanman2_match_fn
,
2110 smbd_dirptr_lanman2_mode_fn
,
2120 *got_exact_match
= state
.got_exact_match
;
2122 ok
= smbd_marshall_dir_entry(ctx
,
2127 state
.check_mangled_names
,
2128 requires_resume_key
,
2141 TALLOC_FREE(smb_fname
);
2142 if (*out_of_space
) {
2143 dptr_SeekDir(dirptr
, prev_dirpos
);
2150 *_last_entry_off
= last_entry_off
;
2154 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2155 connection_struct
*conn
,
2156 struct dptr_struct
*dirptr
,
2158 const char *path_mask
,
2161 bool requires_resume_key
,
2167 int space_remaining
,
2169 bool *got_exact_match
,
2170 int *last_entry_off
,
2171 struct ea_list
*name_list
)
2174 const bool do_pad
= true;
2176 if (info_level
>= 1 && info_level
<= 3) {
2177 /* No alignment on earlier info levels. */
2181 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2182 path_mask
, dirtype
, info_level
,
2183 requires_resume_key
, dont_descend
, ask_sharemode
,
2185 ppdata
, base_data
, end_data
,
2187 out_of_space
, got_exact_match
,
2188 last_entry_off
, name_list
);
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDFIRST.
2193 ****************************************************************************/
2195 static void call_trans2findfirst(connection_struct
*conn
,
2196 struct smb_request
*req
,
2197 char **pparams
, int total_params
,
2198 char **ppdata
, int total_data
,
2199 unsigned int max_data_bytes
)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2206 struct smb_filename
*smb_dname
= NULL
;
2207 char *params
= *pparams
;
2208 char *pdata
= *ppdata
;
2212 uint16 findfirst_flags
;
2213 bool close_after_first
;
2215 bool requires_resume_key
;
2217 char *directory
= NULL
;
2220 int last_entry_off
=0;
2224 bool finished
= False
;
2225 bool dont_descend
= False
;
2226 bool out_of_space
= False
;
2227 int space_remaining
;
2228 bool mask_contains_wcard
= False
;
2229 struct ea_list
*ea_list
= NULL
;
2230 NTSTATUS ntstatus
= NT_STATUS_OK
;
2231 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2232 TALLOC_CTX
*ctx
= talloc_tos();
2233 struct dptr_struct
*dirptr
= NULL
;
2234 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2236 if (total_params
< 13) {
2237 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2241 dirtype
= SVAL(params
,0);
2242 maxentries
= SVAL(params
,2);
2243 findfirst_flags
= SVAL(params
,4);
2244 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2245 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2246 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2247 info_level
= SVAL(params
,6);
2249 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2250 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2251 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2252 info_level
, max_data_bytes
));
2255 /* W2K3 seems to treat zero as 1. */
2259 switch (info_level
) {
2260 case SMB_FIND_INFO_STANDARD
:
2261 case SMB_FIND_EA_SIZE
:
2262 case SMB_FIND_EA_LIST
:
2263 case SMB_FIND_FILE_DIRECTORY_INFO
:
2264 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2265 case SMB_FIND_FILE_NAMES_INFO
:
2266 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2267 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2268 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2270 case SMB_FIND_FILE_UNIX
:
2271 case SMB_FIND_FILE_UNIX_INFO2
:
2272 /* Always use filesystem for UNIX mtime query. */
2273 ask_sharemode
= false;
2274 if (!lp_unix_extensions()) {
2275 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2280 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2284 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2285 params
+12, total_params
- 12,
2286 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2287 if (!NT_STATUS_IS_OK(ntstatus
)) {
2288 reply_nterror(req
, ntstatus
);
2292 ntstatus
= filename_convert(ctx
, conn
,
2293 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2296 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2297 &mask_contains_wcard
,
2299 if (!NT_STATUS_IS_OK(ntstatus
)) {
2300 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2301 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2302 ERRSRV
, ERRbadpath
);
2305 reply_nterror(req
, ntstatus
);
2309 mask
= smb_dname
->original_lcomp
;
2311 directory
= smb_dname
->base_name
;
2313 p
= strrchr_m(directory
,'/');
2315 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2316 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2317 mask
= talloc_strdup(ctx
,"*");
2319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2322 mask_contains_wcard
= True
;
2324 directory
= talloc_strdup(talloc_tos(), "./");
2326 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2333 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2335 if (info_level
== SMB_FIND_EA_LIST
) {
2338 if (total_data
< 4) {
2339 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2343 ea_size
= IVAL(pdata
,0);
2344 if (ea_size
!= total_data
) {
2345 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2346 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2347 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2351 if (!lp_ea_support(SNUM(conn
))) {
2352 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2356 /* Pull out the list of names. */
2357 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2359 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2364 *ppdata
= (char *)SMB_REALLOC(
2365 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2366 if(*ppdata
== NULL
) {
2367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2371 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2373 /* Realloc the params space */
2374 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2375 if (*pparams
== NULL
) {
2376 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2381 /* Save the wildcard match and attribs we are using on this directory -
2382 needed as lanman2 assumes these are being saved between calls */
2384 ntstatus
= dptr_create(conn
,
2390 mask_contains_wcard
,
2394 if (!NT_STATUS_IS_OK(ntstatus
)) {
2395 reply_nterror(req
, ntstatus
);
2399 dptr_num
= dptr_dnum(dirptr
);
2400 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2402 /* Initialize per TRANS2_FIND_FIRST operation data */
2403 dptr_init_search_op(dirptr
);
2405 /* We don't need to check for VOL here as this is returned by
2406 a different TRANS2 call. */
2408 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2409 directory
,lp_dontdescend(SNUM(conn
))));
2410 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2411 dont_descend
= True
;
2414 space_remaining
= max_data_bytes
;
2415 out_of_space
= False
;
2417 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2418 bool got_exact_match
= False
;
2420 /* this is a heuristic to avoid seeking the dirptr except when
2421 absolutely necessary. It allows for a filename of about 40 chars */
2422 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2423 out_of_space
= True
;
2426 finished
= !get_lanman2_dir_entry(ctx
,
2430 mask
,dirtype
,info_level
,
2431 requires_resume_key
,dont_descend
,
2434 space_remaining
, &out_of_space
,
2436 &last_entry_off
, ea_list
);
2439 if (finished
&& out_of_space
)
2442 if (!finished
&& !out_of_space
)
2446 * As an optimisation if we know we aren't looking
2447 * for a wildcard name (ie. the name matches the wildcard exactly)
2448 * then we can finish on any (first) match.
2449 * This speeds up large directory searches. JRA.
2455 /* Ensure space_remaining never goes -ve. */
2456 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2457 space_remaining
= 0;
2458 out_of_space
= true;
2460 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2464 /* Check if we can close the dirptr */
2465 if(close_after_first
|| (finished
&& close_if_end
)) {
2466 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2467 dptr_close(sconn
, &dptr_num
);
2471 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2472 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2473 * the protocol level is less than NT1. Tested with smbclient. JRA.
2474 * This should fix the OS/2 client bug #2335.
2477 if(numentries
== 0) {
2478 dptr_close(sconn
, &dptr_num
);
2479 if (get_Protocol() < PROTOCOL_NT1
) {
2480 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2483 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2484 ERRDOS
, ERRbadfile
);
2489 /* At this point pdata points to numentries directory entries. */
2491 /* Set up the return parameter block */
2492 SSVAL(params
,0,dptr_num
);
2493 SSVAL(params
,2,numentries
);
2494 SSVAL(params
,4,finished
);
2495 SSVAL(params
,6,0); /* Never an EA error */
2496 SSVAL(params
,8,last_entry_off
);
2498 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2501 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2502 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2504 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2509 smb_fn_name(req
->cmd
),
2510 mask
, directory
, dirtype
, numentries
) );
2513 * Force a name mangle here to ensure that the
2514 * mask as an 8.3 name is top of the mangled cache.
2515 * The reasons for this are subtle. Don't remove
2516 * this code unless you know what you are doing
2517 * (see PR#13758). JRA.
2520 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2521 char mangled_name
[13];
2522 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2525 TALLOC_FREE(smb_dname
);
2529 /****************************************************************************
2530 Reply to a TRANS2_FINDNEXT.
2531 ****************************************************************************/
2533 static void call_trans2findnext(connection_struct
*conn
,
2534 struct smb_request
*req
,
2535 char **pparams
, int total_params
,
2536 char **ppdata
, int total_data
,
2537 unsigned int max_data_bytes
)
2539 /* We must be careful here that we don't return more than the
2540 allowed number of data bytes. If this means returning fewer than
2541 maxentries then so be it. We assume that the redirector has
2542 enough room for the fixed number of parameter bytes it has
2544 char *params
= *pparams
;
2545 char *pdata
= *ppdata
;
2551 uint16 findnext_flags
;
2552 bool close_after_request
;
2554 bool requires_resume_key
;
2556 bool mask_contains_wcard
= False
;
2557 char *resume_name
= NULL
;
2558 const char *mask
= NULL
;
2559 const char *directory
= NULL
;
2563 int i
, last_entry_off
=0;
2564 bool finished
= False
;
2565 bool dont_descend
= False
;
2566 bool out_of_space
= False
;
2567 int space_remaining
;
2568 struct ea_list
*ea_list
= NULL
;
2569 NTSTATUS ntstatus
= NT_STATUS_OK
;
2570 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2571 TALLOC_CTX
*ctx
= talloc_tos();
2572 struct dptr_struct
*dirptr
;
2573 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2575 if (total_params
< 13) {
2576 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2580 dptr_num
= SVAL(params
,0);
2581 maxentries
= SVAL(params
,2);
2582 info_level
= SVAL(params
,4);
2583 resume_key
= IVAL(params
,6);
2584 findnext_flags
= SVAL(params
,10);
2585 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2586 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2587 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2588 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2590 if (!continue_bit
) {
2591 /* We only need resume_name if continue_bit is zero. */
2592 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2594 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2595 &mask_contains_wcard
);
2596 if (!NT_STATUS_IS_OK(ntstatus
)) {
2597 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2598 complain (it thinks we're asking for the directory above the shared
2599 path or an invalid name). Catch this as the resume name is only compared, never used in
2600 a file access. JRA. */
2601 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2602 &resume_name
, params
+12,
2606 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2607 reply_nterror(req
, ntstatus
);
2613 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2614 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2615 resume_key = %d resume name = %s continue=%d level = %d\n",
2616 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2617 requires_resume_key
, resume_key
,
2618 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2621 /* W2K3 seems to treat zero as 1. */
2625 switch (info_level
) {
2626 case SMB_FIND_INFO_STANDARD
:
2627 case SMB_FIND_EA_SIZE
:
2628 case SMB_FIND_EA_LIST
:
2629 case SMB_FIND_FILE_DIRECTORY_INFO
:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2631 case SMB_FIND_FILE_NAMES_INFO
:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2636 case SMB_FIND_FILE_UNIX
:
2637 case SMB_FIND_FILE_UNIX_INFO2
:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode
= false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2646 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2650 if (info_level
== SMB_FIND_EA_LIST
) {
2653 if (total_data
< 4) {
2654 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2658 ea_size
= IVAL(pdata
,0);
2659 if (ea_size
!= total_data
) {
2660 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2661 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2662 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2666 if (!lp_ea_support(SNUM(conn
))) {
2667 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2671 /* Pull out the list of names. */
2672 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2674 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2679 *ppdata
= (char *)SMB_REALLOC(
2680 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2681 if(*ppdata
== NULL
) {
2682 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2687 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2689 /* Realloc the params space */
2690 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2691 if(*pparams
== NULL
) {
2692 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2698 /* Check that the dptr is valid */
2699 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2700 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2704 directory
= dptr_path(sconn
, dptr_num
);
2706 /* Get the wildcard mask from the dptr */
2707 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2708 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2709 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2715 /* Get the attr mask from the dptr */
2716 dirtype
= dptr_attr(sconn
, dptr_num
);
2718 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2719 dptr_num
, mask
, dirtype
,
2721 dptr_TellDir(dirptr
)));
2723 /* Initialize per TRANS2_FIND_NEXT operation data */
2724 dptr_init_search_op(dirptr
);
2726 /* We don't need to check for VOL here as this is returned by
2727 a different TRANS2 call. */
2729 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2730 directory
,lp_dontdescend(SNUM(conn
))));
2731 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2732 dont_descend
= True
;
2735 space_remaining
= max_data_bytes
;
2736 out_of_space
= False
;
2739 * Seek to the correct position. We no longer use the resume key but
2740 * depend on the last file name instead.
2743 if(!continue_bit
&& resume_name
&& *resume_name
) {
2746 long current_pos
= 0;
2748 * Remember, name_to_8_3 is called by
2749 * get_lanman2_dir_entry(), so the resume name
2750 * could be mangled. Ensure we check the unmangled name.
2753 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2754 char *new_resume_name
= NULL
;
2755 mangle_lookup_name_from_8_3(ctx
,
2759 if (new_resume_name
) {
2760 resume_name
= new_resume_name
;
2765 * Fix for NT redirector problem triggered by resume key indexes
2766 * changing between directory scans. We now return a resume key of 0
2767 * and instead look for the filename to continue from (also given
2768 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2769 * findfirst/findnext (as is usual) then the directory pointer
2770 * should already be at the correct place.
2773 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2774 } /* end if resume_name && !continue_bit */
2776 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2777 bool got_exact_match
= False
;
2779 /* this is a heuristic to avoid seeking the dirptr except when
2780 absolutely necessary. It allows for a filename of about 40 chars */
2781 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2782 out_of_space
= True
;
2785 finished
= !get_lanman2_dir_entry(ctx
,
2789 mask
,dirtype
,info_level
,
2790 requires_resume_key
,dont_descend
,
2793 space_remaining
, &out_of_space
,
2795 &last_entry_off
, ea_list
);
2798 if (finished
&& out_of_space
)
2801 if (!finished
&& !out_of_space
)
2805 * As an optimisation if we know we aren't looking
2806 * for a wildcard name (ie. the name matches the wildcard exactly)
2807 * then we can finish on any (first) match.
2808 * This speeds up large directory searches. JRA.
2814 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2817 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2818 smb_fn_name(req
->cmd
),
2819 mask
, directory
, dirtype
, numentries
) );
2821 /* Check if we can close the dirptr */
2822 if(close_after_request
|| (finished
&& close_if_end
)) {
2823 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2824 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2827 /* Set up the return parameter block */
2828 SSVAL(params
,0,numentries
);
2829 SSVAL(params
,2,finished
);
2830 SSVAL(params
,4,0); /* Never an EA error */
2831 SSVAL(params
,6,last_entry_off
);
2833 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2839 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2841 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2845 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2847 SMB_ASSERT(extended_info
!= NULL
);
2849 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2850 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2851 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2852 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2853 #ifdef SAMBA_VERSION_REVISION
2854 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2856 extended_info
->samba_subversion
= 0;
2857 #ifdef SAMBA_VERSION_RC_RELEASE
2858 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2860 #ifdef SAMBA_VERSION_PRE_RELEASE
2861 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2864 #ifdef SAMBA_VERSION_VENDOR_PATCH
2865 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2867 extended_info
->samba_gitcommitdate
= 0;
2868 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2869 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2872 memset(extended_info
->samba_version_string
, 0,
2873 sizeof(extended_info
->samba_version_string
));
2875 snprintf (extended_info
->samba_version_string
,
2876 sizeof(extended_info
->samba_version_string
),
2877 "%s", samba_version_string());
2880 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2881 TALLOC_CTX
*mem_ctx
,
2882 uint16_t info_level
,
2884 unsigned int max_data_bytes
,
2888 char *pdata
, *end_data
;
2889 int data_len
= 0, len
;
2890 const char *vname
= volume_label(SNUM(conn
));
2891 int snum
= SNUM(conn
);
2892 char *fstype
= lp_fstype(SNUM(conn
));
2893 uint32 additional_flags
= 0;
2894 struct smb_filename smb_fname_dot
;
2898 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2899 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2900 "info level (0x%x) on IPC$.\n",
2901 (unsigned int)info_level
));
2902 return NT_STATUS_ACCESS_DENIED
;
2906 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2908 ZERO_STRUCT(smb_fname_dot
);
2909 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2911 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2912 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2913 return map_nt_error_from_unix(errno
);
2916 st
= smb_fname_dot
.st
;
2918 *ppdata
= (char *)SMB_REALLOC(
2919 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2920 if (*ppdata
== NULL
) {
2921 return NT_STATUS_NO_MEMORY
;
2925 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2926 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2928 switch (info_level
) {
2929 case SMB_INFO_ALLOCATION
:
2931 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2933 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2934 return map_nt_error_from_unix(errno
);
2937 block_size
= lp_block_size(snum
);
2938 if (bsize
< block_size
) {
2939 uint64_t factor
= block_size
/bsize
;
2944 if (bsize
> block_size
) {
2945 uint64_t factor
= bsize
/block_size
;
2950 bytes_per_sector
= 512;
2951 sectors_per_unit
= bsize
/bytes_per_sector
;
2953 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2954 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2955 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2957 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2958 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2959 SIVAL(pdata
,l1_cUnit
,dsize
);
2960 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2961 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2965 case SMB_INFO_VOLUME
:
2966 /* Return volume name */
2968 * Add volume serial number - hash of a combination of
2969 * the called hostname and the service name.
2971 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2973 * Win2k3 and previous mess this up by sending a name length
2974 * one byte short. I believe only older clients (OS/2 Win9x) use
2975 * this call so try fixing this by adding a terminating null to
2976 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2980 pdata
+l2_vol_szVolLabel
, vname
,
2981 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2982 STR_NOALIGN
|STR_TERMINATE
);
2983 SCVAL(pdata
,l2_vol_cch
,len
);
2984 data_len
= l2_vol_szVolLabel
+ len
;
2985 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2986 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2990 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2991 case SMB_FS_ATTRIBUTE_INFORMATION
:
2993 additional_flags
= 0;
2994 #if defined(HAVE_SYS_QUOTAS)
2995 additional_flags
|= FILE_VOLUME_QUOTAS
;
2998 if(lp_nt_acl_support(SNUM(conn
))) {
2999 additional_flags
|= FILE_PERSISTENT_ACLS
;
3002 /* Capabilities are filled in at connection time through STATVFS call */
3003 additional_flags
|= conn
->fs_capabilities
;
3004 additional_flags
|= lp_parm_int(conn
->params
->service
,
3005 "share", "fake_fscaps",
3008 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3009 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3010 additional_flags
); /* FS ATTRIBUTES */
3012 SIVAL(pdata
,4,255); /* Max filename component length */
3013 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3014 and will think we can't do long filenames */
3015 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3016 PTR_DIFF(end_data
, pdata
+12),
3019 data_len
= 12 + len
;
3022 case SMB_QUERY_FS_LABEL_INFO
:
3023 case SMB_FS_LABEL_INFORMATION
:
3024 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3025 PTR_DIFF(end_data
, pdata
+4), 0);
3030 case SMB_QUERY_FS_VOLUME_INFO
:
3031 case SMB_FS_VOLUME_INFORMATION
:
3034 * Add volume serial number - hash of a combination of
3035 * the called hostname and the service name.
3037 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3038 (str_checksum(get_local_machine_name())<<16));
3040 /* Max label len is 32 characters. */
3041 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3042 PTR_DIFF(end_data
, pdata
+18),
3044 SIVAL(pdata
,12,len
);
3047 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3048 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3051 case SMB_QUERY_FS_SIZE_INFO
:
3052 case SMB_FS_SIZE_INFORMATION
:
3054 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3056 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3057 return map_nt_error_from_unix(errno
);
3059 block_size
= lp_block_size(snum
);
3060 if (bsize
< block_size
) {
3061 uint64_t factor
= block_size
/bsize
;
3066 if (bsize
> block_size
) {
3067 uint64_t factor
= bsize
/block_size
;
3072 bytes_per_sector
= 512;
3073 sectors_per_unit
= bsize
/bytes_per_sector
;
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3075 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3076 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3077 SBIG_UINT(pdata
,0,dsize
);
3078 SBIG_UINT(pdata
,8,dfree
);
3079 SIVAL(pdata
,16,sectors_per_unit
);
3080 SIVAL(pdata
,20,bytes_per_sector
);
3084 case SMB_FS_FULL_SIZE_INFORMATION
:
3086 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3088 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3089 return map_nt_error_from_unix(errno
);
3091 block_size
= lp_block_size(snum
);
3092 if (bsize
< block_size
) {
3093 uint64_t factor
= block_size
/bsize
;
3098 if (bsize
> block_size
) {
3099 uint64_t factor
= bsize
/block_size
;
3104 bytes_per_sector
= 512;
3105 sectors_per_unit
= bsize
/bytes_per_sector
;
3106 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3107 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3108 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3109 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3110 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3111 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3112 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3113 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3117 case SMB_QUERY_FS_DEVICE_INFO
:
3118 case SMB_FS_DEVICE_INFORMATION
:
3120 SIVAL(pdata
,0,0); /* dev type */
3121 SIVAL(pdata
,4,0); /* characteristics */
3124 #ifdef HAVE_SYS_QUOTAS
3125 case SMB_FS_QUOTA_INFORMATION
:
3127 * what we have to send --metze:
3129 * Unknown1: 24 NULL bytes
3130 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3131 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3132 * Quota Flags: 2 byte :
3133 * Unknown3: 6 NULL bytes
3137 * details for Quota Flags:
3139 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3140 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3141 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3142 * 0x0001 Enable Quotas: enable quota for this fs
3146 /* we need to fake up a fsp here,
3147 * because its not send in this call
3150 SMB_NTQUOTA_STRUCT quotas
;
3153 ZERO_STRUCT(quotas
);
3159 if (conn
->server_info
->utok
.uid
!= sec_initial_uid() &&
3160 !conn
->admin_user
) {
3161 DEBUG(0,("set_user_quota: access_denied "
3162 "service [%s] user [%s]\n",
3163 lp_servicename(SNUM(conn
)),
3164 conn
->server_info
->unix_name
));
3165 return NT_STATUS_ACCESS_DENIED
;
3168 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3169 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3170 return map_nt_error_from_unix(errno
);
3175 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3176 lp_servicename(SNUM(conn
))));
3178 /* Unknown1 24 NULL bytes*/
3179 SBIG_UINT(pdata
,0,(uint64_t)0);
3180 SBIG_UINT(pdata
,8,(uint64_t)0);
3181 SBIG_UINT(pdata
,16,(uint64_t)0);
3183 /* Default Soft Quota 8 bytes */
3184 SBIG_UINT(pdata
,24,quotas
.softlim
);
3186 /* Default Hard Quota 8 bytes */
3187 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3189 /* Quota flag 2 bytes */
3190 SSVAL(pdata
,40,quotas
.qflags
);
3192 /* Unknown3 6 NULL bytes */
3198 #endif /* HAVE_SYS_QUOTAS */
3199 case SMB_FS_OBJECTID_INFORMATION
:
3201 unsigned char objid
[16];
3202 struct smb_extended_info extended_info
;
3203 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3204 samba_extended_info_version (&extended_info
);
3205 SIVAL(pdata
,16,extended_info
.samba_magic
);
3206 SIVAL(pdata
,20,extended_info
.samba_version
);
3207 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3208 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3209 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3215 * Query the version and capabilities of the CIFS UNIX extensions
3219 case SMB_QUERY_CIFS_UNIX_INFO
:
3221 bool large_write
= lp_min_receive_file_size() &&
3222 !srv_is_signing_active(smbd_server_conn
);
3223 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3224 int encrypt_caps
= 0;
3226 if (!lp_unix_extensions()) {
3227 return NT_STATUS_INVALID_LEVEL
;
3230 switch (conn
->encrypt_level
) {
3236 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3239 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3240 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3241 large_write
= false;
3247 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3248 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3250 /* We have POSIX ACLs, pathname, encryption,
3251 * large read/write, and locking capability. */
3253 SBIG_UINT(pdata
,4,((uint64_t)(
3254 CIFS_UNIX_POSIX_ACLS_CAP
|
3255 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3256 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3257 CIFS_UNIX_EXTATTR_CAP
|
3258 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3260 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3262 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3266 case SMB_QUERY_POSIX_FS_INFO
:
3269 vfs_statvfs_struct svfs
;
3271 if (!lp_unix_extensions()) {
3272 return NT_STATUS_INVALID_LEVEL
;
3275 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3279 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3280 SIVAL(pdata
,4,svfs
.BlockSize
);
3281 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3282 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3283 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3284 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3285 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3286 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3289 } else if (rc
== EOPNOTSUPP
) {
3290 return NT_STATUS_INVALID_LEVEL
;
3291 #endif /* EOPNOTSUPP */
3293 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3294 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3299 case SMB_QUERY_POSIX_WHOAMI
:
3305 if (!lp_unix_extensions()) {
3306 return NT_STATUS_INVALID_LEVEL
;
3309 if (max_data_bytes
< 40) {
3310 return NT_STATUS_BUFFER_TOO_SMALL
;
3313 /* We ARE guest if global_sid_Builtin_Guests is
3314 * in our list of SIDs.
3316 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3317 conn
->server_info
->ptok
)) {
3318 flags
|= SMB_WHOAMI_GUEST
;
3321 /* We are NOT guest if global_sid_Authenticated_Users
3322 * is in our list of SIDs.
3324 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3325 conn
->server_info
->ptok
)) {
3326 flags
&= ~SMB_WHOAMI_GUEST
;
3329 /* NOTE: 8 bytes for UID/GID, irrespective of native
3330 * platform size. This matches
3331 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3333 data_len
= 4 /* flags */
3340 + 4 /* pad/reserved */
3341 + (conn
->server_info
->utok
.ngroups
* 8)
3343 + (conn
->server_info
->ptok
->num_sids
*
3347 SIVAL(pdata
, 0, flags
);
3348 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3350 (uint64_t)conn
->server_info
->utok
.uid
);
3351 SBIG_UINT(pdata
, 16,
3352 (uint64_t)conn
->server_info
->utok
.gid
);
3355 if (data_len
>= max_data_bytes
) {
3356 /* Potential overflow, skip the GIDs and SIDs. */
3358 SIVAL(pdata
, 24, 0); /* num_groups */
3359 SIVAL(pdata
, 28, 0); /* num_sids */
3360 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3361 SIVAL(pdata
, 36, 0); /* reserved */
3367 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3368 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3370 /* We walk the SID list twice, but this call is fairly
3371 * infrequent, and I don't expect that it's performance
3372 * sensitive -- jpeach
3374 for (i
= 0, sid_bytes
= 0;
3375 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3376 sid_bytes
+= ndr_size_dom_sid(
3377 &conn
->server_info
->ptok
->user_sids
[i
],
3382 /* SID list byte count */
3383 SIVAL(pdata
, 32, sid_bytes
);
3385 /* 4 bytes pad/reserved - must be zero */
3386 SIVAL(pdata
, 36, 0);
3390 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3391 SBIG_UINT(pdata
, data_len
,
3392 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3398 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3399 int sid_len
= ndr_size_dom_sid(
3400 &conn
->server_info
->ptok
->user_sids
[i
],
3404 sid_linearize(pdata
+ data_len
, sid_len
,
3405 &conn
->server_info
->ptok
->user_sids
[i
]);
3406 data_len
+= sid_len
;
3412 case SMB_MAC_QUERY_FS_INFO
:
3414 * Thursby MAC extension... ONLY on NTFS filesystems
3415 * once we do streams then we don't need this
3417 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3419 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3424 return NT_STATUS_INVALID_LEVEL
;
3427 *ret_data_len
= data_len
;
3428 return NT_STATUS_OK
;
3431 /****************************************************************************
3432 Reply to a TRANS2_QFSINFO (query filesystem info).
3433 ****************************************************************************/
3435 static void call_trans2qfsinfo(connection_struct
*conn
,
3436 struct smb_request
*req
,
3437 char **pparams
, int total_params
,
3438 char **ppdata
, int total_data
,
3439 unsigned int max_data_bytes
)
3441 char *params
= *pparams
;
3442 uint16_t info_level
;
3446 if (total_params
< 2) {
3447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3451 info_level
= SVAL(params
,0);
3453 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3454 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3455 DEBUG(0,("call_trans2qfsinfo: encryption required "
3456 "and info level 0x%x sent.\n",
3457 (unsigned int)info_level
));
3458 exit_server_cleanly("encryption required "
3464 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3466 status
= smbd_do_qfsinfo(conn
, req
,
3471 if (!NT_STATUS_IS_OK(status
)) {
3472 reply_nterror(req
, status
);
3476 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3479 DEBUG( 4, ( "%s info_level = %d\n",
3480 smb_fn_name(req
->cmd
), info_level
) );
3485 /****************************************************************************
3486 Reply to a TRANS2_SETFSINFO (set filesystem info).
3487 ****************************************************************************/
3489 static void call_trans2setfsinfo(connection_struct
*conn
,
3490 struct smb_request
*req
,
3491 char **pparams
, int total_params
,
3492 char **ppdata
, int total_data
,
3493 unsigned int max_data_bytes
)
3495 char *pdata
= *ppdata
;
3496 char *params
= *pparams
;
3499 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3502 if (total_params
< 4) {
3503 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3505 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3509 info_level
= SVAL(params
,2);
3512 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3513 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3514 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3515 "info level (0x%x) on IPC$.\n",
3516 (unsigned int)info_level
));
3517 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3522 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3523 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3524 DEBUG(0,("call_trans2setfsinfo: encryption required "
3525 "and info level 0x%x sent.\n",
3526 (unsigned int)info_level
));
3527 exit_server_cleanly("encryption required "
3533 switch(info_level
) {
3534 case SMB_SET_CIFS_UNIX_INFO
:
3536 uint16 client_unix_major
;
3537 uint16 client_unix_minor
;
3538 uint32 client_unix_cap_low
;
3539 uint32 client_unix_cap_high
;
3541 if (!lp_unix_extensions()) {
3543 NT_STATUS_INVALID_LEVEL
);
3547 /* There should be 12 bytes of capabilities set. */
3548 if (total_data
< 8) {
3551 NT_STATUS_INVALID_PARAMETER
);
3554 client_unix_major
= SVAL(pdata
,0);
3555 client_unix_minor
= SVAL(pdata
,2);
3556 client_unix_cap_low
= IVAL(pdata
,4);
3557 client_unix_cap_high
= IVAL(pdata
,8);
3558 /* Just print these values for now. */
3559 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3560 cap_low = 0x%x, cap_high = 0x%x\n",
3561 (unsigned int)client_unix_major
,
3562 (unsigned int)client_unix_minor
,
3563 (unsigned int)client_unix_cap_low
,
3564 (unsigned int)client_unix_cap_high
));
3566 /* Here is where we must switch to posix pathname processing... */
3567 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3568 lp_set_posix_pathnames();
3569 mangle_change_to_posix();
3572 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3573 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3574 /* Client that knows how to do posix locks,
3575 * but not posix open/mkdir operations. Set a
3576 * default type for read/write checks. */
3578 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3584 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3587 size_t param_len
= 0;
3588 size_t data_len
= total_data
;
3590 if (!lp_unix_extensions()) {
3593 NT_STATUS_INVALID_LEVEL
);
3597 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3600 NT_STATUS_NOT_SUPPORTED
);
3604 DEBUG( 4,("call_trans2setfsinfo: "
3605 "request transport encryption.\n"));
3607 status
= srv_request_encryption_setup(conn
,
3608 (unsigned char **)ppdata
,
3610 (unsigned char **)pparams
,
3613 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3614 !NT_STATUS_IS_OK(status
)) {
3615 reply_nterror(req
, status
);
3619 send_trans2_replies(conn
, req
,
3626 if (NT_STATUS_IS_OK(status
)) {
3627 /* Server-side transport
3628 * encryption is now *on*. */
3629 status
= srv_encryption_start(conn
);
3630 if (!NT_STATUS_IS_OK(status
)) {
3631 exit_server_cleanly(
3632 "Failure in setting "
3633 "up encrypted transport");
3639 case SMB_FS_QUOTA_INFORMATION
:
3641 files_struct
*fsp
= NULL
;
3642 SMB_NTQUOTA_STRUCT quotas
;
3644 ZERO_STRUCT(quotas
);
3647 if (((conn
->server_info
->utok
.uid
!= sec_initial_uid()) && !conn
->admin_user
)
3648 ||!CAN_WRITE(conn
)) {
3649 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3650 lp_servicename(SNUM(conn
)),
3651 conn
->server_info
->unix_name
));
3652 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3656 /* note: normaly there're 48 bytes,
3657 * but we didn't use the last 6 bytes for now
3660 fsp
= file_fsp(req
, SVAL(params
,0));
3662 if (!check_fsp_ntquota_handle(conn
, req
,
3664 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3666 req
, NT_STATUS_INVALID_HANDLE
);
3670 if (total_data
< 42) {
3671 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3675 NT_STATUS_INVALID_PARAMETER
);
3679 /* unknown_1 24 NULL bytes in pdata*/
3681 /* the soft quotas 8 bytes (uint64_t)*/
3682 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3683 #ifdef LARGE_SMB_OFF_T
3684 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3685 #else /* LARGE_SMB_OFF_T */
3686 if ((IVAL(pdata
,28) != 0)&&
3687 ((quotas
.softlim
!= 0xFFFFFFFF)||
3688 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3689 /* more than 32 bits? */
3692 NT_STATUS_INVALID_PARAMETER
);
3695 #endif /* LARGE_SMB_OFF_T */
3697 /* the hard quotas 8 bytes (uint64_t)*/
3698 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3699 #ifdef LARGE_SMB_OFF_T
3700 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3701 #else /* LARGE_SMB_OFF_T */
3702 if ((IVAL(pdata
,36) != 0)&&
3703 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3704 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3705 /* more than 32 bits? */
3708 NT_STATUS_INVALID_PARAMETER
);
3711 #endif /* LARGE_SMB_OFF_T */
3713 /* quota_flags 2 bytes **/
3714 quotas
.qflags
= SVAL(pdata
,40);
3716 /* unknown_2 6 NULL bytes follow*/
3718 /* now set the quotas */
3719 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3720 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3721 reply_nterror(req
, map_nt_error_from_unix(errno
));
3728 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3730 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3736 * sending this reply works fine,
3737 * but I'm not sure it's the same
3738 * like windows do...
3741 reply_outbuf(req
, 10, 0);
3744 #if defined(HAVE_POSIX_ACLS)
3745 /****************************************************************************
3746 Utility function to count the number of entries in a POSIX acl.
3747 ****************************************************************************/
3749 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3751 unsigned int ace_count
= 0;
3752 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3753 SMB_ACL_ENTRY_T entry
;
3755 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3757 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3758 entry_id
= SMB_ACL_NEXT_ENTRY
;
3765 /****************************************************************************
3766 Utility function to marshall a POSIX acl into wire format.
3767 ****************************************************************************/
3769 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3771 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3772 SMB_ACL_ENTRY_T entry
;
3774 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3775 SMB_ACL_TAG_T tagtype
;
3776 SMB_ACL_PERMSET_T permset
;
3777 unsigned char perms
= 0;
3778 unsigned int own_grp
;
3781 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3782 entry_id
= SMB_ACL_NEXT_ENTRY
;
3785 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3786 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3790 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3791 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3795 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3796 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3797 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3799 SCVAL(pdata
,1,perms
);
3802 case SMB_ACL_USER_OBJ
:
3803 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3804 own_grp
= (unsigned int)pst
->st_ex_uid
;
3805 SIVAL(pdata
,2,own_grp
);
3810 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3815 own_grp
= (unsigned int)*puid
;
3816 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3817 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3818 SIVAL(pdata
,2,own_grp
);
3822 case SMB_ACL_GROUP_OBJ
:
3823 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3824 own_grp
= (unsigned int)pst
->st_ex_gid
;
3825 SIVAL(pdata
,2,own_grp
);
3830 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3832 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3835 own_grp
= (unsigned int)*pgid
;
3836 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3837 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3838 SIVAL(pdata
,2,own_grp
);
3843 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3844 SIVAL(pdata
,2,0xFFFFFFFF);
3845 SIVAL(pdata
,6,0xFFFFFFFF);
3848 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3849 SIVAL(pdata
,2,0xFFFFFFFF);
3850 SIVAL(pdata
,6,0xFFFFFFFF);
3853 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3856 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3863 /****************************************************************************
3864 Store the FILE_UNIX_BASIC info.
3865 ****************************************************************************/
3867 static char *store_file_unix_basic(connection_struct
*conn
,
3870 const SMB_STRUCT_STAT
*psbuf
)
3872 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3874 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3875 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3877 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3880 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3883 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3884 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3885 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3888 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3892 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3896 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3899 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3903 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3907 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3910 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3914 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3921 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3922 * the chflags(2) (or equivalent) flags.
3924 * XXX: this really should be behind the VFS interface. To do this, we would
3925 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3926 * Each VFS module could then implement its own mapping as appropriate for the
3927 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3929 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3933 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3937 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3941 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3945 { UF_HIDDEN
, EXT_HIDDEN
},
3948 /* Do not remove. We need to guarantee that this array has at least one
3949 * entry to build on HP-UX.
3955 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3956 uint32
*smb_fflags
, uint32
*smb_fmask
)
3960 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3961 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3962 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3963 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3968 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3969 const uint32 smb_fflags
,
3970 const uint32 smb_fmask
,
3973 uint32 max_fmask
= 0;
3976 *stat_fflags
= psbuf
->st_ex_flags
;
3978 /* For each flags requested in smb_fmask, check the state of the
3979 * corresponding flag in smb_fflags and set or clear the matching
3983 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3984 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3985 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3986 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3987 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3989 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3994 /* If smb_fmask is asking to set any bits that are not supported by
3995 * our flag mappings, we should fail.
3997 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4005 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4006 * of file flags and birth (create) time.
4008 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4011 const SMB_STRUCT_STAT
*psbuf
)
4013 uint32 file_flags
= 0;
4014 uint32 flags_mask
= 0;
4016 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4018 /* Create (birth) time 64 bit */
4019 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4022 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4023 SIVAL(pdata
, 0, file_flags
); /* flags */
4024 SIVAL(pdata
, 4, flags_mask
); /* mask */
4030 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4031 const struct stream_struct
*streams
,
4033 unsigned int max_data_bytes
,
4034 unsigned int *data_size
)
4037 unsigned int ofs
= 0;
4039 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4040 unsigned int next_offset
;
4042 smb_ucs2_t
*namebuf
;
4044 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4045 streams
[i
].name
, &namelen
) ||
4048 return NT_STATUS_INVALID_PARAMETER
;
4052 * name_buf is now null-terminated, we need to marshall as not
4058 SIVAL(data
, ofs
+4, namelen
);
4059 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4060 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4061 memcpy(data
+ofs
+24, namebuf
, namelen
);
4062 TALLOC_FREE(namebuf
);
4064 next_offset
= ofs
+ 24 + namelen
;
4066 if (i
== num_streams
-1) {
4067 SIVAL(data
, ofs
, 0);
4070 unsigned int align
= ndr_align_size(next_offset
, 8);
4072 memset(data
+next_offset
, 0, align
);
4073 next_offset
+= align
;
4075 SIVAL(data
, ofs
, next_offset
- ofs
);
4084 return NT_STATUS_OK
;
4087 /****************************************************************************
4088 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4089 ****************************************************************************/
4091 static void call_trans2qpipeinfo(connection_struct
*conn
,
4092 struct smb_request
*req
,
4093 unsigned int tran_call
,
4094 char **pparams
, int total_params
,
4095 char **ppdata
, int total_data
,
4096 unsigned int max_data_bytes
)
4098 char *params
= *pparams
;
4099 char *pdata
= *ppdata
;
4100 unsigned int data_size
= 0;
4101 unsigned int param_size
= 2;
4106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4110 if (total_params
< 4) {
4111 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4115 fsp
= file_fsp(req
, SVAL(params
,0));
4116 if (!fsp_is_np(fsp
)) {
4117 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4121 info_level
= SVAL(params
,2);
4123 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4124 if (*pparams
== NULL
) {
4125 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4130 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4131 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4132 if (*ppdata
== NULL
) {
4133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4138 switch (info_level
) {
4139 case SMB_FILE_STANDARD_INFORMATION
:
4141 SOFF_T(pdata
,0,4096LL);
4148 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4152 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4158 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4159 TALLOC_CTX
*mem_ctx
,
4160 uint16_t info_level
,
4162 struct smb_filename
*smb_fname
,
4163 bool delete_pending
,
4164 struct timespec write_time_ts
,
4166 struct ea_list
*ea_list
,
4167 int lock_data_count
,
4170 unsigned int max_data_bytes
,
4172 unsigned int *pdata_size
)
4174 char *pdata
= *ppdata
;
4175 char *dstart
, *dend
;
4176 unsigned int data_size
;
4177 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4178 time_t create_time
, mtime
, atime
, c_time
;
4179 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4186 uint64_t file_size
= 0;
4188 uint64_t allocation_size
= 0;
4189 uint64_t file_index
= 0;
4190 uint32_t access_mask
= 0;
4192 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4193 return NT_STATUS_INVALID_LEVEL
;
4196 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4197 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4198 info_level
, max_data_bytes
));
4201 mode
= dos_mode_msdfs(conn
, smb_fname
);
4203 mode
= dos_mode(conn
, smb_fname
);
4206 nlink
= psbuf
->st_ex_nlink
;
4208 if (nlink
&& (mode
&aDIR
)) {
4212 if ((nlink
> 0) && delete_pending
) {
4216 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4217 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4218 if (*ppdata
== NULL
) {
4219 return NT_STATUS_NO_MEMORY
;
4223 dend
= dstart
+ data_size
- 1;
4225 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4226 update_stat_ex_mtime(psbuf
, write_time_ts
);
4229 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4230 mtime_ts
= psbuf
->st_ex_mtime
;
4231 atime_ts
= psbuf
->st_ex_atime
;
4232 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4234 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4235 dos_filetime_timespec(&create_time_ts
);
4236 dos_filetime_timespec(&mtime_ts
);
4237 dos_filetime_timespec(&atime_ts
);
4238 dos_filetime_timespec(&ctime_ts
);
4241 create_time
= convert_timespec_to_time_t(create_time_ts
);
4242 mtime
= convert_timespec_to_time_t(mtime_ts
);
4243 atime
= convert_timespec_to_time_t(atime_ts
);
4244 c_time
= convert_timespec_to_time_t(ctime_ts
);
4246 p
= strrchr_m(smb_fname
->base_name
,'/');
4248 base_name
= smb_fname
->base_name
;
4252 /* NT expects the name to be in an exact form of the *full*
4253 filename. See the trans2 torture test */
4254 if (ISDOT(base_name
)) {
4255 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4257 return NT_STATUS_NO_MEMORY
;
4260 dos_fname
= talloc_asprintf(mem_ctx
,
4262 smb_fname
->base_name
);
4264 return NT_STATUS_NO_MEMORY
;
4266 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4267 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4268 smb_fname
->stream_name
);
4270 return NT_STATUS_NO_MEMORY
;
4274 string_replace(dos_fname
, '/', '\\');
4277 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4280 /* Do we have this path open ? */
4282 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4283 fsp1
= file_find_di_first(fileid
);
4284 if (fsp1
&& fsp1
->initial_allocation_size
) {
4285 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4289 if (!(mode
& aDIR
)) {
4290 file_size
= get_file_size_stat(psbuf
);
4294 pos
= fsp
->fh
->position_information
;
4298 access_mask
= fsp
->access_mask
;
4300 /* GENERIC_EXECUTE mapping from Windows */
4301 access_mask
= 0x12019F;
4304 /* This should be an index number - looks like
4307 I think this causes us to fail the IFSKIT
4308 BasicFileInformationTest. -tpot */
4309 file_index
= get_FileIndex(conn
, psbuf
);
4311 switch (info_level
) {
4312 case SMB_INFO_STANDARD
:
4313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4315 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4316 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4317 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4318 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4319 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4320 SSVAL(pdata
,l1_attrFile
,mode
);
4323 case SMB_INFO_QUERY_EA_SIZE
:
4325 unsigned int ea_size
=
4326 estimate_ea_size(conn
, fsp
,
4327 smb_fname
->base_name
);
4328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4330 srv_put_dos_date2(pdata
,0,create_time
);
4331 srv_put_dos_date2(pdata
,4,atime
);
4332 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4333 SIVAL(pdata
,12,(uint32
)file_size
);
4334 SIVAL(pdata
,16,(uint32
)allocation_size
);
4335 SSVAL(pdata
,20,mode
);
4336 SIVAL(pdata
,22,ea_size
);
4340 case SMB_INFO_IS_NAME_VALID
:
4341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4343 /* os/2 needs this ? really ?*/
4344 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4346 /* This is only reached for qpathinfo */
4350 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4352 size_t total_ea_len
= 0;
4353 struct ea_list
*ea_file_list
= NULL
;
4355 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4358 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4359 smb_fname
->base_name
,
4361 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4363 if (!ea_list
|| (total_ea_len
> data_size
)) {
4365 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4369 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4373 case SMB_INFO_QUERY_ALL_EAS
:
4375 /* We have data_size bytes to put EA's into. */
4376 size_t total_ea_len
= 0;
4378 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4380 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4381 smb_fname
->base_name
,
4383 if (!ea_list
|| (total_ea_len
> data_size
)) {
4385 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4389 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4393 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4395 /* This is FileFullEaInformation - 0xF which maps to
4396 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4398 /* We have data_size bytes to put EA's into. */
4399 size_t total_ea_len
= 0;
4400 struct ea_list
*ea_file_list
= NULL
;
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4404 /*TODO: add filtering and index handling */
4407 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4408 smb_fname
->base_name
,
4410 if (!ea_file_list
) {
4411 return NT_STATUS_NO_EAS_ON_FILE
;
4414 status
= fill_ea_chained_buffer(mem_ctx
,
4418 conn
, ea_file_list
);
4419 if (!NT_STATUS_IS_OK(status
)) {
4425 case SMB_FILE_BASIC_INFORMATION
:
4426 case SMB_QUERY_FILE_BASIC_INFO
:
4428 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4430 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4432 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4436 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4437 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4438 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4439 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4440 SIVAL(pdata
,32,mode
);
4442 DEBUG(5,("SMB_QFBI - "));
4443 DEBUG(5,("create: %s ", ctime(&create_time
)));
4444 DEBUG(5,("access: %s ", ctime(&atime
)));
4445 DEBUG(5,("write: %s ", ctime(&mtime
)));
4446 DEBUG(5,("change: %s ", ctime(&c_time
)));
4447 DEBUG(5,("mode: %x\n", mode
));
4450 case SMB_FILE_STANDARD_INFORMATION
:
4451 case SMB_QUERY_FILE_STANDARD_INFO
:
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4455 SOFF_T(pdata
,0,allocation_size
);
4456 SOFF_T(pdata
,8,file_size
);
4457 SIVAL(pdata
,16,nlink
);
4458 SCVAL(pdata
,20,delete_pending
?1:0);
4459 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4460 SSVAL(pdata
,22,0); /* Padding. */
4463 case SMB_FILE_EA_INFORMATION
:
4464 case SMB_QUERY_FILE_EA_INFO
:
4466 unsigned int ea_size
=
4467 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4470 SIVAL(pdata
,0,ea_size
);
4474 /* Get the 8.3 name - used if NT SMB was negotiated. */
4475 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4476 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4479 char mangled_name
[13];
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4481 if (!name_to_8_3(base_name
,mangled_name
,
4482 True
,conn
->params
)) {
4483 return NT_STATUS_NO_MEMORY
;
4485 len
= srvstr_push(dstart
, flags2
,
4486 pdata
+4, mangled_name
,
4487 PTR_DIFF(dend
, pdata
+4),
4489 data_size
= 4 + len
;
4494 case SMB_QUERY_FILE_NAME_INFO
:
4498 this must be *exactly* right for ACLs on mapped drives to work
4500 len
= srvstr_push(dstart
, flags2
,
4502 PTR_DIFF(dend
, pdata
+4),
4504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4505 data_size
= 4 + len
;
4510 case SMB_FILE_ALLOCATION_INFORMATION
:
4511 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4514 SOFF_T(pdata
,0,allocation_size
);
4517 case SMB_FILE_END_OF_FILE_INFORMATION
:
4518 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4521 SOFF_T(pdata
,0,file_size
);
4524 case SMB_QUERY_FILE_ALL_INFO
:
4525 case SMB_FILE_ALL_INFORMATION
:
4528 unsigned int ea_size
=
4529 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4531 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4532 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4533 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4534 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4535 SIVAL(pdata
,32,mode
);
4536 SIVAL(pdata
,36,0); /* padding. */
4538 SOFF_T(pdata
,0,allocation_size
);
4539 SOFF_T(pdata
,8,file_size
);
4540 SIVAL(pdata
,16,nlink
);
4541 SCVAL(pdata
,20,delete_pending
);
4542 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4545 SIVAL(pdata
,0,ea_size
);
4546 pdata
+= 4; /* EA info */
4547 len
= srvstr_push(dstart
, flags2
,
4549 PTR_DIFF(dend
, pdata
+4),
4553 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4557 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4560 unsigned int ea_size
=
4561 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4562 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4563 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4564 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4565 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4566 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4567 SIVAL(pdata
, 0x20, mode
);
4568 SIVAL(pdata
, 0x24, 0); /* padding. */
4569 SBVAL(pdata
, 0x28, allocation_size
);
4570 SBVAL(pdata
, 0x30, file_size
);
4571 SIVAL(pdata
, 0x38, nlink
);
4572 SCVAL(pdata
, 0x3C, delete_pending
);
4573 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4574 SSVAL(pdata
, 0x3E, 0); /* padding */
4575 SBVAL(pdata
, 0x40, file_index
);
4576 SIVAL(pdata
, 0x48, ea_size
);
4577 SIVAL(pdata
, 0x4C, access_mask
);
4578 SBVAL(pdata
, 0x50, pos
);
4579 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4580 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4584 len
= srvstr_push(dstart
, flags2
,
4586 PTR_DIFF(dend
, pdata
+4),
4590 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4593 case SMB_FILE_INTERNAL_INFORMATION
:
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4596 SBVAL(pdata
, 0, file_index
);
4600 case SMB_FILE_ACCESS_INFORMATION
:
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4602 SIVAL(pdata
, 0, access_mask
);
4606 case SMB_FILE_NAME_INFORMATION
:
4607 /* Pathname with leading '\'. */
4610 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4612 SIVAL(pdata
,0,byte_len
);
4613 data_size
= 4 + byte_len
;
4617 case SMB_FILE_DISPOSITION_INFORMATION
:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4620 SCVAL(pdata
,0,delete_pending
);
4623 case SMB_FILE_POSITION_INFORMATION
:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4626 SOFF_T(pdata
,0,pos
);
4629 case SMB_FILE_MODE_INFORMATION
:
4630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4631 SIVAL(pdata
,0,mode
);
4635 case SMB_FILE_ALIGNMENT_INFORMATION
:
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4637 SIVAL(pdata
,0,0); /* No alignment needed. */
4642 * NT4 server just returns "invalid query" to this - if we try
4643 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4646 /* The first statement above is false - verified using Thursby
4647 * client against NT4 -- gcolley.
4649 case SMB_QUERY_FILE_STREAM_INFO
:
4650 case SMB_FILE_STREAM_INFORMATION
: {
4651 unsigned int num_streams
;
4652 struct stream_struct
*streams
;
4654 DEBUG(10,("smbd_do_qfilepathinfo: "
4655 "SMB_FILE_STREAM_INFORMATION\n"));
4657 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4658 return NT_STATUS_INVALID_PARAMETER
;
4661 status
= SMB_VFS_STREAMINFO(
4662 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4663 &num_streams
, &streams
);
4665 if (!NT_STATUS_IS_OK(status
)) {
4666 DEBUG(10, ("could not get stream info: %s\n",
4667 nt_errstr(status
)));
4671 status
= marshall_stream_info(num_streams
, streams
,
4672 pdata
, max_data_bytes
,
4675 if (!NT_STATUS_IS_OK(status
)) {
4676 DEBUG(10, ("marshall_stream_info failed: %s\n",
4677 nt_errstr(status
)));
4681 TALLOC_FREE(streams
);
4685 case SMB_QUERY_COMPRESSION_INFO
:
4686 case SMB_FILE_COMPRESSION_INFORMATION
:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4688 SOFF_T(pdata
,0,file_size
);
4689 SIVAL(pdata
,8,0); /* ??? */
4690 SIVAL(pdata
,12,0); /* ??? */
4694 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4696 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4697 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4698 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4699 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4700 SOFF_T(pdata
,32,allocation_size
);
4701 SOFF_T(pdata
,40,file_size
);
4702 SIVAL(pdata
,48,mode
);
4703 SIVAL(pdata
,52,0); /* ??? */
4707 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4709 SIVAL(pdata
,0,mode
);
4715 * CIFS UNIX Extensions.
4718 case SMB_QUERY_FILE_UNIX_BASIC
:
4720 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4721 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4725 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4727 for (i
=0; i
<100; i
++)
4728 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4734 case SMB_QUERY_FILE_UNIX_INFO2
:
4736 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4737 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4741 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4743 for (i
=0; i
<100; i
++)
4744 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4750 case SMB_QUERY_FILE_UNIX_LINK
:
4753 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4756 return NT_STATUS_NO_MEMORY
;
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4761 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4762 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4765 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4767 len
= SMB_VFS_READLINK(conn
,
4768 smb_fname
->base_name
,
4771 return map_nt_error_from_unix(errno
);
4774 len
= srvstr_push(dstart
, flags2
,
4776 PTR_DIFF(dend
, pdata
),
4779 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4784 #if defined(HAVE_POSIX_ACLS)
4785 case SMB_QUERY_POSIX_ACL
:
4787 SMB_ACL_T file_acl
= NULL
;
4788 SMB_ACL_T def_acl
= NULL
;
4789 uint16 num_file_acls
= 0;
4790 uint16 num_def_acls
= 0;
4792 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4793 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4796 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4797 smb_fname
->base_name
,
4798 SMB_ACL_TYPE_ACCESS
);
4801 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4802 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4803 "not implemented on "
4804 "filesystem containing %s\n",
4805 smb_fname
->base_name
));
4806 return NT_STATUS_NOT_IMPLEMENTED
;
4809 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4810 if (fsp
&& fsp
->is_directory
) {
4812 SMB_VFS_SYS_ACL_GET_FILE(
4814 fsp
->fsp_name
->base_name
,
4815 SMB_ACL_TYPE_DEFAULT
);
4818 SMB_VFS_SYS_ACL_GET_FILE(
4820 smb_fname
->base_name
,
4821 SMB_ACL_TYPE_DEFAULT
);
4823 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4826 num_file_acls
= count_acl_entries(conn
, file_acl
);
4827 num_def_acls
= count_acl_entries(conn
, def_acl
);
4829 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4830 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4832 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4833 SMB_POSIX_ACL_HEADER_SIZE
) ));
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4838 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4840 return NT_STATUS_BUFFER_TOO_SMALL
;
4843 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4844 SSVAL(pdata
,2,num_file_acls
);
4845 SSVAL(pdata
,4,num_def_acls
);
4846 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4848 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4851 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4853 return NT_STATUS_INTERNAL_ERROR
;
4855 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4862 return NT_STATUS_INTERNAL_ERROR
;
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4871 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4877 case SMB_QUERY_POSIX_LOCK
:
4882 enum brl_type lock_type
;
4884 /* We need an open file with a real fd for this. */
4885 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4886 return NT_STATUS_INVALID_LEVEL
;
4889 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4890 return NT_STATUS_INVALID_PARAMETER
;
4893 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4894 case POSIX_LOCK_TYPE_READ
:
4895 lock_type
= READ_LOCK
;
4897 case POSIX_LOCK_TYPE_WRITE
:
4898 lock_type
= WRITE_LOCK
;
4900 case POSIX_LOCK_TYPE_UNLOCK
:
4902 /* There's no point in asking for an unlock... */
4903 return NT_STATUS_INVALID_PARAMETER
;
4906 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4907 #if defined(HAVE_LONGLONG)
4908 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4909 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4910 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4911 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4912 #else /* HAVE_LONGLONG */
4913 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4914 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4915 #endif /* HAVE_LONGLONG */
4917 status
= query_lock(fsp
,
4924 if (ERROR_WAS_LOCK_DENIED(status
)) {
4925 /* Here we need to report who has it locked... */
4926 data_size
= POSIX_LOCK_DATA_SIZE
;
4928 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4929 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4930 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4931 #if defined(HAVE_LONGLONG)
4932 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4933 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4934 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4935 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4936 #else /* HAVE_LONGLONG */
4937 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4938 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4939 #endif /* HAVE_LONGLONG */
4941 } else if (NT_STATUS_IS_OK(status
)) {
4942 /* For success we just return a copy of what we sent
4943 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4944 data_size
= POSIX_LOCK_DATA_SIZE
;
4945 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4946 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4954 return NT_STATUS_INVALID_LEVEL
;
4957 *pdata_size
= data_size
;
4958 return NT_STATUS_OK
;
4961 /****************************************************************************
4962 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4963 file name or file id).
4964 ****************************************************************************/
4966 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4967 struct smb_request
*req
,
4968 unsigned int tran_call
,
4969 char **pparams
, int total_params
,
4970 char **ppdata
, int total_data
,
4971 unsigned int max_data_bytes
)
4973 char *params
= *pparams
;
4974 char *pdata
= *ppdata
;
4976 unsigned int data_size
= 0;
4977 unsigned int param_size
= 2;
4978 struct smb_filename
*smb_fname
= NULL
;
4979 bool delete_pending
= False
;
4980 struct timespec write_time_ts
;
4981 files_struct
*fsp
= NULL
;
4982 struct file_id fileid
;
4983 struct ea_list
*ea_list
= NULL
;
4984 int lock_data_count
= 0;
4985 char *lock_data
= NULL
;
4986 bool ms_dfs_link
= false;
4987 NTSTATUS status
= NT_STATUS_OK
;
4990 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4994 ZERO_STRUCT(write_time_ts
);
4996 if (tran_call
== TRANSACT2_QFILEINFO
) {
4997 if (total_params
< 4) {
4998 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5003 call_trans2qpipeinfo(conn
, req
, tran_call
,
5004 pparams
, total_params
,
5010 fsp
= file_fsp(req
, SVAL(params
,0));
5011 info_level
= SVAL(params
,2);
5013 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5015 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5016 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5020 /* Initial check for valid fsp ptr. */
5021 if (!check_fsp_open(conn
, req
, fsp
)) {
5025 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5027 if (!NT_STATUS_IS_OK(status
)) {
5028 reply_nterror(req
, status
);
5032 if(fsp
->fake_file_handle
) {
5034 * This is actually for the QUOTA_FAKE_FILE --metze
5037 /* We know this name is ok, it's already passed the checks. */
5039 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5041 * This is actually a QFILEINFO on a directory
5042 * handle (returned from an NT SMB). NT5.0 seems
5043 * to do this call. JRA.
5046 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5047 /* Always do lstat for UNIX calls. */
5048 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5049 DEBUG(3,("call_trans2qfilepathinfo: "
5050 "SMB_VFS_LSTAT of %s failed "
5052 smb_fname_str_dbg(smb_fname
),
5055 map_nt_error_from_unix(errno
));
5058 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5059 DEBUG(3,("call_trans2qfilepathinfo: "
5060 "SMB_VFS_STAT of %s failed (%s)\n",
5061 smb_fname_str_dbg(smb_fname
),
5064 map_nt_error_from_unix(errno
));
5068 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5069 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5072 * Original code - this is an open file.
5074 if (!check_fsp(conn
, req
, fsp
)) {
5078 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5079 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5080 fsp
->fnum
, strerror(errno
)));
5082 map_nt_error_from_unix(errno
));
5085 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5086 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5093 if (total_params
< 7) {
5094 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5098 info_level
= SVAL(params
,0);
5100 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5102 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5103 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5107 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5109 STR_TERMINATE
, &status
);
5110 if (!NT_STATUS_IS_OK(status
)) {
5111 reply_nterror(req
, status
);
5115 status
= filename_convert(req
,
5117 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5122 if (!NT_STATUS_IS_OK(status
)) {
5123 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5124 reply_botherror(req
,
5125 NT_STATUS_PATH_NOT_COVERED
,
5126 ERRSRV
, ERRbadpath
);
5129 reply_nterror(req
, status
);
5133 /* If this is a stream, check if there is a delete_pending. */
5134 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5135 && is_ntfs_stream_smb_fname(smb_fname
)) {
5136 struct smb_filename
*smb_fname_base
= NULL
;
5138 /* Create an smb_filename with stream_name == NULL. */
5140 create_synthetic_smb_fname(talloc_tos(),
5141 smb_fname
->base_name
,
5144 if (!NT_STATUS_IS_OK(status
)) {
5145 reply_nterror(req
, status
);
5149 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5150 /* Always do lstat for UNIX calls. */
5151 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5152 DEBUG(3,("call_trans2qfilepathinfo: "
5153 "SMB_VFS_LSTAT of %s failed "
5155 smb_fname_str_dbg(smb_fname_base
),
5157 TALLOC_FREE(smb_fname_base
);
5159 map_nt_error_from_unix(errno
));
5163 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5164 DEBUG(3,("call_trans2qfilepathinfo: "
5165 "fileinfo of %s failed "
5167 smb_fname_str_dbg(smb_fname_base
),
5169 TALLOC_FREE(smb_fname_base
);
5171 map_nt_error_from_unix(errno
));
5176 fileid
= vfs_file_id_from_sbuf(conn
,
5177 &smb_fname_base
->st
);
5178 TALLOC_FREE(smb_fname_base
);
5179 get_file_infos(fileid
, &delete_pending
, NULL
);
5180 if (delete_pending
) {
5181 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5186 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5187 /* Always do lstat for UNIX calls. */
5188 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_LSTAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname
),
5194 map_nt_error_from_unix(errno
));
5198 } else if (!VALID_STAT(smb_fname
->st
) &&
5199 SMB_VFS_STAT(conn
, smb_fname
) &&
5200 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5201 ms_dfs_link
= check_msdfs_link(conn
,
5202 smb_fname
->base_name
,
5206 DEBUG(3,("call_trans2qfilepathinfo: "
5207 "SMB_VFS_STAT of %s failed (%s)\n",
5208 smb_fname_str_dbg(smb_fname
),
5211 map_nt_error_from_unix(errno
));
5216 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5217 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5218 if (delete_pending
) {
5219 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5224 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5225 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5226 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5228 /* Pull out any data sent here before we realloc. */
5229 switch (info_level
) {
5230 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5232 /* Pull any EA list from the data portion. */
5235 if (total_data
< 4) {
5237 req
, NT_STATUS_INVALID_PARAMETER
);
5240 ea_size
= IVAL(pdata
,0);
5242 if (total_data
> 0 && ea_size
!= total_data
) {
5243 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5244 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5246 req
, NT_STATUS_INVALID_PARAMETER
);
5250 if (!lp_ea_support(SNUM(conn
))) {
5251 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5255 /* Pull out the list of names. */
5256 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5259 req
, NT_STATUS_INVALID_PARAMETER
);
5265 case SMB_QUERY_POSIX_LOCK
:
5267 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5268 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5272 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5274 req
, NT_STATUS_INVALID_PARAMETER
);
5278 /* Copy the lock range data. */
5279 lock_data
= (char *)TALLOC_MEMDUP(
5280 req
, pdata
, total_data
);
5282 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5285 lock_data_count
= total_data
;
5291 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5292 if (*pparams
== NULL
) {
5293 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5300 * draft-leach-cifs-v1-spec-02.txt
5301 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5304 * The requested information is placed in the Data portion of the
5305 * transaction response. For the information levels greater than 0x100,
5306 * the transaction response has 1 parameter word which should be
5307 * ignored by the client.
5309 * However Windows only follows this rule for the IS_NAME_VALID call.
5311 switch (info_level
) {
5312 case SMB_INFO_IS_NAME_VALID
:
5317 if ((info_level
& 0xFF00) == 0xFF00) {
5319 * We use levels that start with 0xFF00
5320 * internally to represent SMB2 specific levels
5322 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5326 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5328 delete_pending
, write_time_ts
,
5329 ms_dfs_link
, ea_list
,
5330 lock_data_count
, lock_data
,
5331 req
->flags2
, max_data_bytes
,
5332 ppdata
, &data_size
);
5333 if (!NT_STATUS_IS_OK(status
)) {
5334 reply_nterror(req
, status
);
5338 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5344 /****************************************************************************
5345 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5347 ****************************************************************************/
5349 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5350 connection_struct
*conn
,
5351 const struct smb_filename
*smb_fname_old
,
5352 const struct smb_filename
*smb_fname_new
)
5354 NTSTATUS status
= NT_STATUS_OK
;
5356 /* source must already exist. */
5357 if (!VALID_STAT(smb_fname_old
->st
)) {
5358 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5361 /* Disallow if newname already exists. */
5362 if (VALID_STAT(smb_fname_new
->st
)) {
5363 return NT_STATUS_OBJECT_NAME_COLLISION
;
5366 /* No links from a directory. */
5367 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5368 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5371 /* Setting a hardlink to/from a stream isn't currently supported. */
5372 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5373 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5374 return NT_STATUS_INVALID_PARAMETER
;
5377 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5378 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5380 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5381 smb_fname_new
->base_name
) != 0) {
5382 status
= map_nt_error_from_unix(errno
);
5383 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5384 nt_errstr(status
), smb_fname_old
->base_name
,
5385 smb_fname_new
->base_name
));
5390 /****************************************************************************
5391 Deal with setting the time from any of the setfilepathinfo functions.
5392 ****************************************************************************/
5394 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5396 const struct smb_filename
*smb_fname
,
5397 struct smb_file_time
*ft
,
5398 bool setting_write_time
)
5400 struct smb_filename smb_fname_base
;
5402 FILE_NOTIFY_CHANGE_LAST_ACCESS
5403 |FILE_NOTIFY_CHANGE_LAST_WRITE
5404 |FILE_NOTIFY_CHANGE_CREATION
;
5406 if (!VALID_STAT(smb_fname
->st
)) {
5407 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5410 /* get some defaults (no modifications) if any info is zero or -1. */
5411 if (null_timespec(ft
->create_time
)) {
5412 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5415 if (null_timespec(ft
->atime
)) {
5416 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5419 if (null_timespec(ft
->mtime
)) {
5420 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5423 if (!setting_write_time
) {
5424 /* ft->mtime comes from change time, not write time. */
5425 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5428 /* Ensure the resolution is the correct for
5429 * what we can store on this filesystem. */
5431 round_timespec(conn
->ts_res
, &ft
->create_time
);
5432 round_timespec(conn
->ts_res
, &ft
->ctime
);
5433 round_timespec(conn
->ts_res
, &ft
->atime
);
5434 round_timespec(conn
->ts_res
, &ft
->mtime
);
5436 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5437 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5438 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5440 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5442 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5443 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5445 if (setting_write_time
) {
5447 * This was a Windows setfileinfo on an open file.
5448 * NT does this a lot. We also need to
5449 * set the time here, as it can be read by
5450 * FindFirst/FindNext and with the patch for bug #2045
5451 * in smbd/fileio.c it ensures that this timestamp is
5452 * kept sticky even after a write. We save the request
5453 * away and will set it on file close and after a write. JRA.
5456 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5457 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5460 if (fsp
->base_fsp
) {
5461 set_sticky_write_time_fsp(fsp
->base_fsp
,
5464 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5467 set_sticky_write_time_path(
5468 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5473 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5475 /* Always call ntimes on the base, even if a stream was passed in. */
5476 smb_fname_base
= *smb_fname
;
5477 smb_fname_base
.stream_name
= NULL
;
5479 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5480 return map_nt_error_from_unix(errno
);
5483 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5484 smb_fname
->base_name
);
5485 return NT_STATUS_OK
;
5488 /****************************************************************************
5489 Deal with setting the dosmode from any of the setfilepathinfo functions.
5490 ****************************************************************************/
5492 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5493 const struct smb_filename
*smb_fname
,
5496 struct smb_filename
*smb_fname_base
= NULL
;
5499 if (!VALID_STAT(smb_fname
->st
)) {
5500 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5503 /* Always operate on the base_name, even if a stream was passed in. */
5504 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5505 NULL
, &smb_fname
->st
,
5507 if (!NT_STATUS_IS_OK(status
)) {
5512 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5519 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5521 /* check the mode isn't different, before changing it */
5522 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5523 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5524 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5525 (unsigned int)dosmode
));
5527 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5529 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5531 smb_fname_str_dbg(smb_fname_base
),
5533 status
= map_nt_error_from_unix(errno
);
5537 status
= NT_STATUS_OK
;
5539 TALLOC_FREE(smb_fname_base
);
5543 /****************************************************************************
5544 Deal with setting the size from any of the setfilepathinfo functions.
5545 ****************************************************************************/
5547 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5548 struct smb_request
*req
,
5550 const struct smb_filename
*smb_fname
,
5551 const SMB_STRUCT_STAT
*psbuf
,
5553 bool fail_after_createfile
)
5555 NTSTATUS status
= NT_STATUS_OK
;
5556 struct smb_filename
*smb_fname_tmp
= NULL
;
5557 files_struct
*new_fsp
= NULL
;
5559 if (!VALID_STAT(*psbuf
)) {
5560 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5563 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5565 if (size
== get_file_size_stat(psbuf
)) {
5566 return NT_STATUS_OK
;
5569 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5570 smb_fname_str_dbg(smb_fname
), (double)size
));
5572 if (fsp
&& fsp
->fh
->fd
!= -1) {
5573 /* Handle based call. */
5574 if (vfs_set_filelen(fsp
, size
) == -1) {
5575 return map_nt_error_from_unix(errno
);
5577 trigger_write_time_update_immediate(fsp
);
5578 return NT_STATUS_OK
;
5581 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5582 if (!NT_STATUS_IS_OK(status
)) {
5586 smb_fname_tmp
->st
= *psbuf
;
5588 status
= SMB_VFS_CREATE_FILE(
5591 0, /* root_dir_fid */
5592 smb_fname_tmp
, /* fname */
5593 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5594 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5596 FILE_OPEN
, /* create_disposition*/
5597 0, /* create_options */
5598 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5599 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5600 0, /* allocation_size */
5603 &new_fsp
, /* result */
5606 TALLOC_FREE(smb_fname_tmp
);
5608 if (!NT_STATUS_IS_OK(status
)) {
5609 /* NB. We check for open_was_deferred in the caller. */
5613 /* See RAW-SFILEINFO-END-OF-FILE */
5614 if (fail_after_createfile
) {
5615 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5616 return NT_STATUS_INVALID_LEVEL
;
5619 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5620 status
= map_nt_error_from_unix(errno
);
5621 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5625 trigger_write_time_update_immediate(new_fsp
);
5626 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5627 return NT_STATUS_OK
;
5630 /****************************************************************************
5631 Deal with SMB_INFO_SET_EA.
5632 ****************************************************************************/
5634 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5638 const struct smb_filename
*smb_fname
)
5640 struct ea_list
*ea_list
= NULL
;
5641 TALLOC_CTX
*ctx
= NULL
;
5642 NTSTATUS status
= NT_STATUS_OK
;
5644 if (total_data
< 10) {
5646 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5647 length. They seem to have no effect. Bug #3212. JRA */
5649 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5650 /* We're done. We only get EA info in this call. */
5651 return NT_STATUS_OK
;
5654 return NT_STATUS_INVALID_PARAMETER
;
5657 if (IVAL(pdata
,0) > total_data
) {
5658 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5659 IVAL(pdata
,0), (unsigned int)total_data
));
5660 return NT_STATUS_INVALID_PARAMETER
;
5664 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5666 return NT_STATUS_INVALID_PARAMETER
;
5668 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5673 /****************************************************************************
5674 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5675 ****************************************************************************/
5677 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5682 struct ea_list
*ea_list
= NULL
;
5686 return NT_STATUS_INVALID_HANDLE
;
5689 if (!lp_ea_support(SNUM(conn
))) {
5690 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5691 "EA's not supported.\n",
5692 (unsigned int)total_data
));
5693 return NT_STATUS_EAS_NOT_SUPPORTED
;
5696 if (total_data
< 10) {
5697 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5699 (unsigned int)total_data
));
5700 return NT_STATUS_INVALID_PARAMETER
;
5703 ea_list
= read_nttrans_ea_list(talloc_tos(),
5708 return NT_STATUS_INVALID_PARAMETER
;
5710 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5712 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5713 smb_fname_str_dbg(fsp
->fsp_name
),
5714 nt_errstr(status
) ));
5720 /****************************************************************************
5721 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5722 ****************************************************************************/
5724 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5728 struct smb_filename
*smb_fname
)
5730 NTSTATUS status
= NT_STATUS_OK
;
5731 bool delete_on_close
;
5734 if (total_data
< 1) {
5735 return NT_STATUS_INVALID_PARAMETER
;
5739 return NT_STATUS_INVALID_HANDLE
;
5742 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5743 dosmode
= dos_mode(conn
, smb_fname
);
5745 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5746 "delete_on_close = %u\n",
5747 smb_fname_str_dbg(smb_fname
),
5748 (unsigned int)dosmode
,
5749 (unsigned int)delete_on_close
));
5751 if (delete_on_close
) {
5752 status
= can_set_delete_on_close(fsp
, dosmode
);
5753 if (!NT_STATUS_IS_OK(status
)) {
5758 /* The set is across all open files on this dev/inode pair. */
5759 if (!set_delete_on_close(fsp
, delete_on_close
,
5760 &conn
->server_info
->utok
)) {
5761 return NT_STATUS_ACCESS_DENIED
;
5763 return NT_STATUS_OK
;
5766 /****************************************************************************
5767 Deal with SMB_FILE_POSITION_INFORMATION.
5768 ****************************************************************************/
5770 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5775 uint64_t position_information
;
5777 if (total_data
< 8) {
5778 return NT_STATUS_INVALID_PARAMETER
;
5782 /* Ignore on pathname based set. */
5783 return NT_STATUS_OK
;
5786 position_information
= (uint64_t)IVAL(pdata
,0);
5787 #ifdef LARGE_SMB_OFF_T
5788 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5789 #else /* LARGE_SMB_OFF_T */
5790 if (IVAL(pdata
,4) != 0) {
5791 /* more than 32 bits? */
5792 return NT_STATUS_INVALID_PARAMETER
;
5794 #endif /* LARGE_SMB_OFF_T */
5796 DEBUG(10,("smb_file_position_information: Set file position "
5797 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5798 (double)position_information
));
5799 fsp
->fh
->position_information
= position_information
;
5800 return NT_STATUS_OK
;
5803 /****************************************************************************
5804 Deal with SMB_FILE_MODE_INFORMATION.
5805 ****************************************************************************/
5807 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5813 if (total_data
< 4) {
5814 return NT_STATUS_INVALID_PARAMETER
;
5816 mode
= IVAL(pdata
,0);
5817 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5818 return NT_STATUS_INVALID_PARAMETER
;
5820 return NT_STATUS_OK
;
5823 /****************************************************************************
5824 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5825 ****************************************************************************/
5827 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5828 struct smb_request
*req
,
5831 const struct smb_filename
*smb_fname
)
5833 char *link_target
= NULL
;
5834 const char *newname
= smb_fname
->base_name
;
5835 TALLOC_CTX
*ctx
= talloc_tos();
5837 /* Set a symbolic link. */
5838 /* Don't allow this if follow links is false. */
5840 if (total_data
== 0) {
5841 return NT_STATUS_INVALID_PARAMETER
;
5844 if (!lp_symlinks(SNUM(conn
))) {
5845 return NT_STATUS_ACCESS_DENIED
;
5848 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5849 total_data
, STR_TERMINATE
);
5852 return NT_STATUS_INVALID_PARAMETER
;
5855 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5856 newname
, link_target
));
5858 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5859 return map_nt_error_from_unix(errno
);
5862 return NT_STATUS_OK
;
5865 /****************************************************************************
5866 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5867 ****************************************************************************/
5869 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5870 struct smb_request
*req
,
5871 const char *pdata
, int total_data
,
5872 const struct smb_filename
*smb_fname_new
)
5874 char *oldname
= NULL
;
5875 struct smb_filename
*smb_fname_old
= NULL
;
5876 TALLOC_CTX
*ctx
= talloc_tos();
5877 NTSTATUS status
= NT_STATUS_OK
;
5879 /* Set a hard link. */
5880 if (total_data
== 0) {
5881 return NT_STATUS_INVALID_PARAMETER
;
5884 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5885 total_data
, STR_TERMINATE
, &status
);
5886 if (!NT_STATUS_IS_OK(status
)) {
5890 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5891 smb_fname_str_dbg(smb_fname_new
), oldname
));
5893 status
= filename_convert(ctx
,
5895 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5900 if (!NT_STATUS_IS_OK(status
)) {
5904 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5907 /****************************************************************************
5908 Deal with SMB_FILE_RENAME_INFORMATION.
5909 ****************************************************************************/
5911 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5912 struct smb_request
*req
,
5916 struct smb_filename
*smb_fname_src
)
5921 char *newname
= NULL
;
5922 struct smb_filename
*smb_fname_dst
= NULL
;
5923 bool dest_has_wcard
= False
;
5924 NTSTATUS status
= NT_STATUS_OK
;
5926 TALLOC_CTX
*ctx
= talloc_tos();
5928 if (total_data
< 13) {
5929 return NT_STATUS_INVALID_PARAMETER
;
5932 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5933 root_fid
= IVAL(pdata
,4);
5934 len
= IVAL(pdata
,8);
5936 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5937 return NT_STATUS_INVALID_PARAMETER
;
5940 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5943 if (!NT_STATUS_IS_OK(status
)) {
5947 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5950 status
= resolve_dfspath_wcard(ctx
, conn
,
5951 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5956 if (!NT_STATUS_IS_OK(status
)) {
5960 /* Check the new name has no '/' characters. */
5961 if (strchr_m(newname
, '/')) {
5962 return NT_STATUS_NOT_SUPPORTED
;
5965 if (fsp
&& fsp
->base_fsp
) {
5966 /* newname must be a stream name. */
5967 if (newname
[0] != ':') {
5968 return NT_STATUS_NOT_SUPPORTED
;
5971 /* Create an smb_fname to call rename_internals_fsp() with. */
5972 status
= create_synthetic_smb_fname(talloc_tos(),
5973 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
5975 if (!NT_STATUS_IS_OK(status
)) {
5980 * Set the original last component, since
5981 * rename_internals_fsp() requires it.
5983 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
5985 if (smb_fname_dst
->original_lcomp
== NULL
) {
5986 status
= NT_STATUS_NO_MEMORY
;
5992 * Build up an smb_fname_dst based on the filename passed in.
5993 * We basically just strip off the last component, and put on
5994 * the newname instead.
5996 char *base_name
= NULL
;
5998 /* newname must *not* be a stream name. */
5999 if (newname
[0] == ':') {
6000 return NT_STATUS_NOT_SUPPORTED
;
6004 * Strip off the last component (filename) of the path passed
6007 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6009 return NT_STATUS_NO_MEMORY
;
6011 p
= strrchr_m(base_name
, '/');
6015 base_name
= talloc_strdup(ctx
, "./");
6017 return NT_STATUS_NO_MEMORY
;
6020 /* Append the new name. */
6021 base_name
= talloc_asprintf_append(base_name
,
6025 return NT_STATUS_NO_MEMORY
;
6028 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6031 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6034 /* If an error we expect this to be
6035 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6037 if (!NT_STATUS_IS_OK(status
)) {
6038 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6042 /* Create an smb_fname to call rename_internals_fsp() */
6043 status
= create_synthetic_smb_fname(ctx
,
6047 if (!NT_STATUS_IS_OK(status
)) {
6054 DEBUG(10,("smb_file_rename_information: "
6055 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6056 fsp
->fnum
, fsp_str_dbg(fsp
),
6057 smb_fname_str_dbg(smb_fname_dst
)));
6058 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6061 DEBUG(10,("smb_file_rename_information: "
6062 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6063 smb_fname_str_dbg(smb_fname_src
),
6064 smb_fname_str_dbg(smb_fname_dst
)));
6065 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6066 smb_fname_dst
, 0, overwrite
, false,
6068 FILE_WRITE_ATTRIBUTES
);
6071 TALLOC_FREE(smb_fname_dst
);
6075 /****************************************************************************
6076 Deal with SMB_SET_POSIX_ACL.
6077 ****************************************************************************/
6079 #if defined(HAVE_POSIX_ACLS)
6080 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6084 const struct smb_filename
*smb_fname
)
6086 uint16 posix_acl_version
;
6087 uint16 num_file_acls
;
6088 uint16 num_def_acls
;
6089 bool valid_file_acls
= True
;
6090 bool valid_def_acls
= True
;
6092 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6093 return NT_STATUS_INVALID_PARAMETER
;
6095 posix_acl_version
= SVAL(pdata
,0);
6096 num_file_acls
= SVAL(pdata
,2);
6097 num_def_acls
= SVAL(pdata
,4);
6099 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6100 valid_file_acls
= False
;
6104 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6105 valid_def_acls
= False
;
6109 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6110 return NT_STATUS_INVALID_PARAMETER
;
6113 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6114 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6115 return NT_STATUS_INVALID_PARAMETER
;
6118 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6119 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6120 (unsigned int)num_file_acls
,
6121 (unsigned int)num_def_acls
));
6123 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6124 smb_fname
->base_name
, num_file_acls
,
6125 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6126 return map_nt_error_from_unix(errno
);
6129 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6130 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6131 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6132 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6133 return map_nt_error_from_unix(errno
);
6135 return NT_STATUS_OK
;
6139 /****************************************************************************
6140 Deal with SMB_SET_POSIX_LOCK.
6141 ****************************************************************************/
6143 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6144 struct smb_request
*req
,
6152 bool blocking_lock
= False
;
6153 enum brl_type lock_type
;
6155 NTSTATUS status
= NT_STATUS_OK
;
6157 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6158 return NT_STATUS_INVALID_HANDLE
;
6161 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6162 return NT_STATUS_INVALID_PARAMETER
;
6165 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6166 case POSIX_LOCK_TYPE_READ
:
6167 lock_type
= READ_LOCK
;
6169 case POSIX_LOCK_TYPE_WRITE
:
6170 /* Return the right POSIX-mappable error code for files opened read-only. */
6171 if (!fsp
->can_write
) {
6172 return NT_STATUS_INVALID_HANDLE
;
6174 lock_type
= WRITE_LOCK
;
6176 case POSIX_LOCK_TYPE_UNLOCK
:
6177 lock_type
= UNLOCK_LOCK
;
6180 return NT_STATUS_INVALID_PARAMETER
;
6183 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6184 blocking_lock
= False
;
6185 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6186 blocking_lock
= True
;
6188 return NT_STATUS_INVALID_PARAMETER
;
6191 if (!lp_blocking_locks(SNUM(conn
))) {
6192 blocking_lock
= False
;
6195 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6196 #if defined(HAVE_LONGLONG)
6197 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6198 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6199 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6200 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6201 #else /* HAVE_LONGLONG */
6202 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6203 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6204 #endif /* HAVE_LONGLONG */
6206 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6207 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6209 (unsigned int)lock_type
,
6210 (unsigned int)lock_pid
,
6214 if (lock_type
== UNLOCK_LOCK
) {
6215 status
= do_unlock(smbd_messaging_context(),
6222 uint32 block_smbpid
;
6224 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6236 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6238 * A blocking lock was requested. Package up
6239 * this smb into a queued request and push it
6240 * onto the blocking lock queue.
6242 if(push_blocking_lock_request(br_lck
,
6245 -1, /* infinite timeout. */
6253 TALLOC_FREE(br_lck
);
6257 TALLOC_FREE(br_lck
);
6263 /****************************************************************************
6264 Deal with SMB_SET_FILE_BASIC_INFO.
6265 ****************************************************************************/
6267 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6271 const struct smb_filename
*smb_fname
)
6273 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6274 struct smb_file_time ft
;
6276 NTSTATUS status
= NT_STATUS_OK
;
6280 if (total_data
< 36) {
6281 return NT_STATUS_INVALID_PARAMETER
;
6284 /* Set the attributes */
6285 dosmode
= IVAL(pdata
,32);
6286 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6287 if (!NT_STATUS_IS_OK(status
)) {
6292 ft
.create_time
= interpret_long_date(pdata
);
6295 ft
.atime
= interpret_long_date(pdata
+8);
6298 ft
.mtime
= interpret_long_date(pdata
+16);
6301 ft
.ctime
= interpret_long_date(pdata
+24);
6303 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6304 smb_fname_str_dbg(smb_fname
)));
6306 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6310 /****************************************************************************
6311 Deal with SMB_INFO_STANDARD.
6312 ****************************************************************************/
6314 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6318 const struct smb_filename
*smb_fname
)
6320 struct smb_file_time ft
;
6324 if (total_data
< 12) {
6325 return NT_STATUS_INVALID_PARAMETER
;
6329 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6331 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6333 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6335 DEBUG(10,("smb_set_info_standard: file %s\n",
6336 smb_fname_str_dbg(smb_fname
)));
6338 return smb_set_file_time(conn
,
6345 /****************************************************************************
6346 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6347 ****************************************************************************/
6349 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6350 struct smb_request
*req
,
6354 struct smb_filename
*smb_fname
)
6356 uint64_t allocation_size
= 0;
6357 NTSTATUS status
= NT_STATUS_OK
;
6358 files_struct
*new_fsp
= NULL
;
6360 if (!VALID_STAT(smb_fname
->st
)) {
6361 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6364 if (total_data
< 8) {
6365 return NT_STATUS_INVALID_PARAMETER
;
6368 allocation_size
= (uint64_t)IVAL(pdata
,0);
6369 #ifdef LARGE_SMB_OFF_T
6370 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6371 #else /* LARGE_SMB_OFF_T */
6372 if (IVAL(pdata
,4) != 0) {
6373 /* more than 32 bits? */
6374 return NT_STATUS_INVALID_PARAMETER
;
6376 #endif /* LARGE_SMB_OFF_T */
6378 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6379 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6380 (double)allocation_size
));
6382 if (allocation_size
) {
6383 allocation_size
= smb_roundup(conn
, allocation_size
);
6386 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6387 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6388 (double)allocation_size
));
6390 if (fsp
&& fsp
->fh
->fd
!= -1) {
6391 /* Open file handle. */
6392 /* Only change if needed. */
6393 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6394 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6395 return map_nt_error_from_unix(errno
);
6398 /* But always update the time. */
6400 * This is equivalent to a write. Ensure it's seen immediately
6401 * if there are no pending writes.
6403 trigger_write_time_update_immediate(fsp
);
6404 return NT_STATUS_OK
;
6407 /* Pathname or stat or directory file. */
6408 status
= SMB_VFS_CREATE_FILE(
6411 0, /* root_dir_fid */
6412 smb_fname
, /* fname */
6413 FILE_WRITE_DATA
, /* access_mask */
6414 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6416 FILE_OPEN
, /* create_disposition*/
6417 0, /* create_options */
6418 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6419 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6420 0, /* allocation_size */
6423 &new_fsp
, /* result */
6426 if (!NT_STATUS_IS_OK(status
)) {
6427 /* NB. We check for open_was_deferred in the caller. */
6431 /* Only change if needed. */
6432 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6433 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6434 status
= map_nt_error_from_unix(errno
);
6435 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6440 /* Changing the allocation size should set the last mod time. */
6442 * This is equivalent to a write. Ensure it's seen immediately
6443 * if there are no pending writes.
6445 trigger_write_time_update_immediate(new_fsp
);
6447 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6448 return NT_STATUS_OK
;
6451 /****************************************************************************
6452 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6453 ****************************************************************************/
6455 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6456 struct smb_request
*req
,
6460 const struct smb_filename
*smb_fname
,
6461 bool fail_after_createfile
)
6465 if (total_data
< 8) {
6466 return NT_STATUS_INVALID_PARAMETER
;
6469 size
= IVAL(pdata
,0);
6470 #ifdef LARGE_SMB_OFF_T
6471 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6472 #else /* LARGE_SMB_OFF_T */
6473 if (IVAL(pdata
,4) != 0) {
6474 /* more than 32 bits? */
6475 return NT_STATUS_INVALID_PARAMETER
;
6477 #endif /* LARGE_SMB_OFF_T */
6478 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6479 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6482 return smb_set_file_size(conn
, req
,
6487 fail_after_createfile
);
6490 /****************************************************************************
6491 Allow a UNIX info mknod.
6492 ****************************************************************************/
6494 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6497 const struct smb_filename
*smb_fname
)
6499 uint32 file_type
= IVAL(pdata
,56);
6500 #if defined(HAVE_MAKEDEV)
6501 uint32 dev_major
= IVAL(pdata
,60);
6502 uint32 dev_minor
= IVAL(pdata
,68);
6504 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6505 uint32 raw_unixmode
= IVAL(pdata
,84);
6509 if (total_data
< 100) {
6510 return NT_STATUS_INVALID_PARAMETER
;
6513 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6514 PERM_NEW_FILE
, &unixmode
);
6515 if (!NT_STATUS_IS_OK(status
)) {
6519 #if defined(HAVE_MAKEDEV)
6520 dev
= makedev(dev_major
, dev_minor
);
6523 switch (file_type
) {
6524 #if defined(S_IFIFO)
6525 case UNIX_TYPE_FIFO
:
6526 unixmode
|= S_IFIFO
;
6529 #if defined(S_IFSOCK)
6530 case UNIX_TYPE_SOCKET
:
6531 unixmode
|= S_IFSOCK
;
6534 #if defined(S_IFCHR)
6535 case UNIX_TYPE_CHARDEV
:
6536 unixmode
|= S_IFCHR
;
6539 #if defined(S_IFBLK)
6540 case UNIX_TYPE_BLKDEV
:
6541 unixmode
|= S_IFBLK
;
6545 return NT_STATUS_INVALID_PARAMETER
;
6548 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6549 "%.0f mode 0%o for file %s\n", (double)dev
,
6550 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6552 /* Ok - do the mknod. */
6553 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6554 return map_nt_error_from_unix(errno
);
6557 /* If any of the other "set" calls fail we
6558 * don't want to end up with a half-constructed mknod.
6561 if (lp_inherit_perms(SNUM(conn
))) {
6563 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6565 return NT_STATUS_NO_MEMORY
;
6567 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6569 TALLOC_FREE(parent
);
6572 return NT_STATUS_OK
;
6575 /****************************************************************************
6576 Deal with SMB_SET_FILE_UNIX_BASIC.
6577 ****************************************************************************/
6579 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6580 struct smb_request
*req
,
6584 const struct smb_filename
*smb_fname
)
6586 struct smb_file_time ft
;
6587 uint32 raw_unixmode
;
6590 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6591 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6592 NTSTATUS status
= NT_STATUS_OK
;
6593 bool delete_on_fail
= False
;
6594 enum perm_type ptype
;
6595 files_struct
*all_fsps
= NULL
;
6596 bool modify_mtime
= true;
6598 struct smb_filename
*smb_fname_tmp
= NULL
;
6599 SMB_STRUCT_STAT sbuf
;
6603 if (total_data
< 100) {
6604 return NT_STATUS_INVALID_PARAMETER
;
6607 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6608 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6609 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6610 #ifdef LARGE_SMB_OFF_T
6611 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6612 #else /* LARGE_SMB_OFF_T */
6613 if (IVAL(pdata
,4) != 0) {
6614 /* more than 32 bits? */
6615 return NT_STATUS_INVALID_PARAMETER
;
6617 #endif /* LARGE_SMB_OFF_T */
6620 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6621 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6622 set_owner
= (uid_t
)IVAL(pdata
,40);
6623 set_grp
= (gid_t
)IVAL(pdata
,48);
6624 raw_unixmode
= IVAL(pdata
,84);
6626 if (VALID_STAT(smb_fname
->st
)) {
6627 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6628 ptype
= PERM_EXISTING_DIR
;
6630 ptype
= PERM_EXISTING_FILE
;
6633 ptype
= PERM_NEW_FILE
;
6636 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6638 if (!NT_STATUS_IS_OK(status
)) {
6642 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6643 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6644 smb_fname_str_dbg(smb_fname
), (double)size
,
6645 (unsigned int)set_owner
, (unsigned int)set_grp
,
6646 (int)raw_unixmode
));
6648 sbuf
= smb_fname
->st
;
6650 if (!VALID_STAT(sbuf
)) {
6652 * The only valid use of this is to create character and block
6653 * devices, and named pipes. This is deprecated (IMHO) and
6654 * a new info level should be used for mknod. JRA.
6657 status
= smb_unix_mknod(conn
,
6661 if (!NT_STATUS_IS_OK(status
)) {
6665 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6667 if (!NT_STATUS_IS_OK(status
)) {
6671 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6672 status
= map_nt_error_from_unix(errno
);
6673 TALLOC_FREE(smb_fname_tmp
);
6674 SMB_VFS_UNLINK(conn
, smb_fname
);
6678 sbuf
= smb_fname_tmp
->st
;
6679 smb_fname
= smb_fname_tmp
;
6681 /* Ensure we don't try and change anything else. */
6682 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6683 size
= get_file_size_stat(&sbuf
);
6684 ft
.atime
= sbuf
.st_ex_atime
;
6685 ft
.mtime
= sbuf
.st_ex_mtime
;
6687 * We continue here as we might want to change the
6690 delete_on_fail
= True
;
6694 /* Horrible backwards compatibility hack as an old server bug
6695 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6699 size
= get_file_size_stat(&sbuf
);
6704 * Deal with the UNIX specific mode set.
6707 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6708 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6709 "setting mode 0%o for file %s\n",
6710 (unsigned int)unixmode
,
6711 smb_fname_str_dbg(smb_fname
)));
6712 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6713 return map_nt_error_from_unix(errno
);
6718 * Deal with the UNIX specific uid set.
6721 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6722 (sbuf
.st_ex_uid
!= set_owner
)) {
6725 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6726 "changing owner %u for path %s\n",
6727 (unsigned int)set_owner
,
6728 smb_fname_str_dbg(smb_fname
)));
6730 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6731 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6732 set_owner
, (gid_t
)-1);
6734 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6735 set_owner
, (gid_t
)-1);
6739 status
= map_nt_error_from_unix(errno
);
6740 if (delete_on_fail
) {
6741 SMB_VFS_UNLINK(conn
, smb_fname
);
6748 * Deal with the UNIX specific gid set.
6751 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6752 (sbuf
.st_ex_gid
!= set_grp
)) {
6753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6754 "changing group %u for file %s\n",
6755 (unsigned int)set_owner
,
6756 smb_fname_str_dbg(smb_fname
)));
6757 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6759 status
= map_nt_error_from_unix(errno
);
6760 if (delete_on_fail
) {
6761 SMB_VFS_UNLINK(conn
, smb_fname
);
6767 /* Deal with any size changes. */
6769 status
= smb_set_file_size(conn
, req
,
6775 if (!NT_STATUS_IS_OK(status
)) {
6779 /* Deal with any time changes. */
6780 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6781 /* No change, don't cancel anything. */
6785 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6786 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6787 all_fsps
= file_find_di_next(all_fsps
)) {
6789 * We're setting the time explicitly for UNIX.
6790 * Cancel any pending changes over all handles.
6792 all_fsps
->update_write_time_on_close
= false;
6793 TALLOC_FREE(all_fsps
->update_write_time_event
);
6797 * Override the "setting_write_time"
6798 * parameter here as it almost does what
6799 * we need. Just remember if we modified
6800 * mtime and send the notify ourselves.
6802 if (null_timespec(ft
.mtime
)) {
6803 modify_mtime
= false;
6806 status
= smb_set_file_time(conn
,
6812 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6813 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6818 /****************************************************************************
6819 Deal with SMB_SET_FILE_UNIX_INFO2.
6820 ****************************************************************************/
6822 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6823 struct smb_request
*req
,
6827 const struct smb_filename
*smb_fname
)
6833 if (total_data
< 116) {
6834 return NT_STATUS_INVALID_PARAMETER
;
6837 /* Start by setting all the fields that are common between UNIX_BASIC
6840 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6842 if (!NT_STATUS_IS_OK(status
)) {
6846 smb_fflags
= IVAL(pdata
, 108);
6847 smb_fmask
= IVAL(pdata
, 112);
6849 /* NB: We should only attempt to alter the file flags if the client
6850 * sends a non-zero mask.
6852 if (smb_fmask
!= 0) {
6853 int stat_fflags
= 0;
6855 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6856 smb_fmask
, &stat_fflags
)) {
6857 /* Client asked to alter a flag we don't understand. */
6858 return NT_STATUS_INVALID_PARAMETER
;
6861 if (fsp
&& fsp
->fh
->fd
!= -1) {
6862 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6863 return NT_STATUS_NOT_SUPPORTED
;
6865 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6866 stat_fflags
) != 0) {
6867 return map_nt_error_from_unix(errno
);
6872 /* XXX: need to add support for changing the create_time here. You
6873 * can do this for paths on Darwin with setattrlist(2). The right way
6874 * to hook this up is probably by extending the VFS utimes interface.
6877 return NT_STATUS_OK
;
6880 /****************************************************************************
6881 Create a directory with POSIX semantics.
6882 ****************************************************************************/
6884 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6885 struct smb_request
*req
,
6888 struct smb_filename
*smb_fname
,
6889 int *pdata_return_size
)
6891 NTSTATUS status
= NT_STATUS_OK
;
6892 uint32 raw_unixmode
= 0;
6893 uint32 mod_unixmode
= 0;
6894 mode_t unixmode
= (mode_t
)0;
6895 files_struct
*fsp
= NULL
;
6896 uint16 info_level_return
= 0;
6898 char *pdata
= *ppdata
;
6900 if (total_data
< 18) {
6901 return NT_STATUS_INVALID_PARAMETER
;
6904 raw_unixmode
= IVAL(pdata
,8);
6905 /* Next 4 bytes are not yet defined. */
6907 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6908 PERM_NEW_DIR
, &unixmode
);
6909 if (!NT_STATUS_IS_OK(status
)) {
6913 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6915 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6916 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6918 status
= SMB_VFS_CREATE_FILE(
6921 0, /* root_dir_fid */
6922 smb_fname
, /* fname */
6923 FILE_READ_ATTRIBUTES
, /* access_mask */
6924 FILE_SHARE_NONE
, /* share_access */
6925 FILE_CREATE
, /* create_disposition*/
6926 FILE_DIRECTORY_FILE
, /* create_options */
6927 mod_unixmode
, /* file_attributes */
6928 0, /* oplock_request */
6929 0, /* allocation_size */
6935 if (NT_STATUS_IS_OK(status
)) {
6936 close_file(req
, fsp
, NORMAL_CLOSE
);
6939 info_level_return
= SVAL(pdata
,16);
6941 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6942 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6943 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6944 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6946 *pdata_return_size
= 12;
6949 /* Realloc the data size */
6950 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6951 if (*ppdata
== NULL
) {
6952 *pdata_return_size
= 0;
6953 return NT_STATUS_NO_MEMORY
;
6957 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6958 SSVAL(pdata
,2,0); /* No fnum. */
6959 SIVAL(pdata
,4,info
); /* Was directory created. */
6961 switch (info_level_return
) {
6962 case SMB_QUERY_FILE_UNIX_BASIC
:
6963 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6964 SSVAL(pdata
,10,0); /* Padding. */
6965 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6968 case SMB_QUERY_FILE_UNIX_INFO2
:
6969 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6970 SSVAL(pdata
,10,0); /* Padding. */
6971 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6975 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6976 SSVAL(pdata
,10,0); /* Padding. */
6983 /****************************************************************************
6984 Open/Create a file with POSIX semantics.
6985 ****************************************************************************/
6987 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6988 struct smb_request
*req
,
6991 struct smb_filename
*smb_fname
,
6992 int *pdata_return_size
)
6994 bool extended_oplock_granted
= False
;
6995 char *pdata
= *ppdata
;
6997 uint32 wire_open_mode
= 0;
6998 uint32 raw_unixmode
= 0;
6999 uint32 mod_unixmode
= 0;
7000 uint32 create_disp
= 0;
7001 uint32 access_mask
= 0;
7002 uint32 create_options
= 0;
7003 NTSTATUS status
= NT_STATUS_OK
;
7004 mode_t unixmode
= (mode_t
)0;
7005 files_struct
*fsp
= NULL
;
7006 int oplock_request
= 0;
7008 uint16 info_level_return
= 0;
7010 if (total_data
< 18) {
7011 return NT_STATUS_INVALID_PARAMETER
;
7014 flags
= IVAL(pdata
,0);
7015 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7016 if (oplock_request
) {
7017 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7020 wire_open_mode
= IVAL(pdata
,4);
7022 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7023 return smb_posix_mkdir(conn
, req
,
7030 switch (wire_open_mode
& SMB_ACCMODE
) {
7032 access_mask
= FILE_READ_DATA
;
7035 access_mask
= FILE_WRITE_DATA
;
7038 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7041 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7042 (unsigned int)wire_open_mode
));
7043 return NT_STATUS_INVALID_PARAMETER
;
7046 wire_open_mode
&= ~SMB_ACCMODE
;
7048 /* First take care of O_CREAT|O_EXCL interactions. */
7049 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7050 case (SMB_O_CREAT
| SMB_O_EXCL
):
7051 /* File exists fail. File not exist create. */
7052 create_disp
= FILE_CREATE
;
7055 /* File exists open. File not exist create. */
7056 create_disp
= FILE_OPEN_IF
;
7059 /* File exists open. File not exist fail. */
7060 create_disp
= FILE_OPEN
;
7063 /* O_EXCL on its own without O_CREAT is undefined. */
7065 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7066 (unsigned int)wire_open_mode
));
7067 return NT_STATUS_INVALID_PARAMETER
;
7070 /* Next factor in the effects of O_TRUNC. */
7071 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7073 if (wire_open_mode
& SMB_O_TRUNC
) {
7074 switch (create_disp
) {
7076 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7077 /* Leave create_disp alone as
7078 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7080 /* File exists fail. File not exist create. */
7083 /* SMB_O_CREAT | SMB_O_TRUNC */
7084 /* File exists overwrite. File not exist create. */
7085 create_disp
= FILE_OVERWRITE_IF
;
7089 /* File exists overwrite. File not exist fail. */
7090 create_disp
= FILE_OVERWRITE
;
7093 /* Cannot get here. */
7094 smb_panic("smb_posix_open: logic error");
7095 return NT_STATUS_INVALID_PARAMETER
;
7099 raw_unixmode
= IVAL(pdata
,8);
7100 /* Next 4 bytes are not yet defined. */
7102 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7103 (VALID_STAT(smb_fname
->st
) ?
7104 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7107 if (!NT_STATUS_IS_OK(status
)) {
7111 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7113 if (wire_open_mode
& SMB_O_SYNC
) {
7114 create_options
|= FILE_WRITE_THROUGH
;
7116 if (wire_open_mode
& SMB_O_APPEND
) {
7117 access_mask
|= FILE_APPEND_DATA
;
7119 if (wire_open_mode
& SMB_O_DIRECT
) {
7120 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7123 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7124 smb_fname_str_dbg(smb_fname
),
7125 (unsigned int)wire_open_mode
,
7126 (unsigned int)unixmode
));
7128 status
= SMB_VFS_CREATE_FILE(
7131 0, /* root_dir_fid */
7132 smb_fname
, /* fname */
7133 access_mask
, /* access_mask */
7134 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7136 create_disp
, /* create_disposition*/
7137 FILE_NON_DIRECTORY_FILE
, /* create_options */
7138 mod_unixmode
, /* file_attributes */
7139 oplock_request
, /* oplock_request */
7140 0, /* allocation_size */
7146 if (!NT_STATUS_IS_OK(status
)) {
7150 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7151 extended_oplock_granted
= True
;
7154 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7155 extended_oplock_granted
= True
;
7158 info_level_return
= SVAL(pdata
,16);
7160 /* Allocate the correct return size. */
7162 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7163 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7164 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7165 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7167 *pdata_return_size
= 12;
7170 /* Realloc the data size */
7171 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7172 if (*ppdata
== NULL
) {
7173 close_file(req
, fsp
, ERROR_CLOSE
);
7174 *pdata_return_size
= 0;
7175 return NT_STATUS_NO_MEMORY
;
7179 if (extended_oplock_granted
) {
7180 if (flags
& REQUEST_BATCH_OPLOCK
) {
7181 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7183 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7185 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7186 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7188 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7191 SSVAL(pdata
,2,fsp
->fnum
);
7192 SIVAL(pdata
,4,info
); /* Was file created etc. */
7194 switch (info_level_return
) {
7195 case SMB_QUERY_FILE_UNIX_BASIC
:
7196 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7197 SSVAL(pdata
,10,0); /* padding. */
7198 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7201 case SMB_QUERY_FILE_UNIX_INFO2
:
7202 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7203 SSVAL(pdata
,10,0); /* padding. */
7204 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7208 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7209 SSVAL(pdata
,10,0); /* padding. */
7212 return NT_STATUS_OK
;
7215 /****************************************************************************
7216 Delete a file with POSIX semantics.
7217 ****************************************************************************/
7219 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7220 struct smb_request
*req
,
7223 struct smb_filename
*smb_fname
)
7225 NTSTATUS status
= NT_STATUS_OK
;
7226 files_struct
*fsp
= NULL
;
7230 int create_options
= 0;
7232 struct share_mode_lock
*lck
= NULL
;
7234 if (total_data
< 2) {
7235 return NT_STATUS_INVALID_PARAMETER
;
7238 flags
= SVAL(pdata
,0);
7240 if (!VALID_STAT(smb_fname
->st
)) {
7241 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7244 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7245 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7246 return NT_STATUS_NOT_A_DIRECTORY
;
7249 DEBUG(10,("smb_posix_unlink: %s %s\n",
7250 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7251 smb_fname_str_dbg(smb_fname
)));
7253 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7254 create_options
|= FILE_DIRECTORY_FILE
;
7257 status
= SMB_VFS_CREATE_FILE(
7260 0, /* root_dir_fid */
7261 smb_fname
, /* fname */
7262 DELETE_ACCESS
, /* access_mask */
7263 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7265 FILE_OPEN
, /* create_disposition*/
7266 create_options
, /* create_options */
7267 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7268 0, /* oplock_request */
7269 0, /* allocation_size */
7275 if (!NT_STATUS_IS_OK(status
)) {
7280 * Don't lie to client. If we can't really delete due to
7281 * non-POSIX opens return SHARING_VIOLATION.
7284 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7287 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7288 "lock for file %s\n", fsp_str_dbg(fsp
)));
7289 close_file(req
, fsp
, NORMAL_CLOSE
);
7290 return NT_STATUS_INVALID_PARAMETER
;
7294 * See if others still have the file open. If this is the case, then
7295 * don't delete. If all opens are POSIX delete we can set the delete
7296 * on close disposition.
7298 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7299 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7300 if (is_valid_share_mode_entry(e
)) {
7301 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7304 /* Fail with sharing violation. */
7305 close_file(req
, fsp
, NORMAL_CLOSE
);
7307 return NT_STATUS_SHARING_VIOLATION
;
7312 * Set the delete on close.
7314 status
= smb_set_file_disposition_info(conn
,
7320 if (!NT_STATUS_IS_OK(status
)) {
7321 close_file(req
, fsp
, NORMAL_CLOSE
);
7326 return close_file(req
, fsp
, NORMAL_CLOSE
);
7329 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7330 struct smb_request
*req
,
7331 TALLOC_CTX
*mem_ctx
,
7332 uint16_t info_level
,
7334 struct smb_filename
*smb_fname
,
7335 char **ppdata
, int total_data
,
7338 char *pdata
= *ppdata
;
7339 NTSTATUS status
= NT_STATUS_OK
;
7340 int data_return_size
= 0;
7344 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7345 return NT_STATUS_INVALID_LEVEL
;
7348 if (!CAN_WRITE(conn
)) {
7349 /* Allow POSIX opens. The open path will deny
7350 * any non-readonly opens. */
7351 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7352 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7356 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7357 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7358 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7360 switch (info_level
) {
7362 case SMB_INFO_STANDARD
:
7364 status
= smb_set_info_standard(conn
,
7372 case SMB_INFO_SET_EA
:
7374 status
= smb_info_set_ea(conn
,
7382 case SMB_SET_FILE_BASIC_INFO
:
7383 case SMB_FILE_BASIC_INFORMATION
:
7385 status
= smb_set_file_basic_info(conn
,
7393 case SMB_FILE_ALLOCATION_INFORMATION
:
7394 case SMB_SET_FILE_ALLOCATION_INFO
:
7396 status
= smb_set_file_allocation_info(conn
, req
,
7404 case SMB_FILE_END_OF_FILE_INFORMATION
:
7405 case SMB_SET_FILE_END_OF_FILE_INFO
:
7408 * XP/Win7 both fail after the createfile with
7409 * SMB_SET_FILE_END_OF_FILE_INFO but not
7410 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7411 * The level is known here, so pass it down
7415 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7417 status
= smb_set_file_end_of_file_info(conn
, req
,
7426 case SMB_FILE_DISPOSITION_INFORMATION
:
7427 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7430 /* JRA - We used to just ignore this on a path ?
7431 * Shouldn't this be invalid level on a pathname
7434 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7435 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7438 status
= smb_set_file_disposition_info(conn
,
7446 case SMB_FILE_POSITION_INFORMATION
:
7448 status
= smb_file_position_information(conn
,
7455 case SMB_FILE_FULL_EA_INFORMATION
:
7457 status
= smb_set_file_full_ea_info(conn
,
7464 /* From tridge Samba4 :
7465 * MODE_INFORMATION in setfileinfo (I have no
7466 * idea what "mode information" on a file is - it takes a value of 0,
7467 * 2, 4 or 6. What could it be?).
7470 case SMB_FILE_MODE_INFORMATION
:
7472 status
= smb_file_mode_information(conn
,
7479 * CIFS UNIX extensions.
7482 case SMB_SET_FILE_UNIX_BASIC
:
7484 status
= smb_set_file_unix_basic(conn
, req
,
7492 case SMB_SET_FILE_UNIX_INFO2
:
7494 status
= smb_set_file_unix_info2(conn
, req
,
7502 case SMB_SET_FILE_UNIX_LINK
:
7505 /* We must have a pathname for this. */
7506 return NT_STATUS_INVALID_LEVEL
;
7508 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7509 total_data
, smb_fname
);
7513 case SMB_SET_FILE_UNIX_HLINK
:
7516 /* We must have a pathname for this. */
7517 return NT_STATUS_INVALID_LEVEL
;
7519 status
= smb_set_file_unix_hlink(conn
, req
,
7525 case SMB_FILE_RENAME_INFORMATION
:
7527 status
= smb_file_rename_information(conn
, req
,
7533 #if defined(HAVE_POSIX_ACLS)
7534 case SMB_SET_POSIX_ACL
:
7536 status
= smb_set_posix_acl(conn
,
7545 case SMB_SET_POSIX_LOCK
:
7548 return NT_STATUS_INVALID_LEVEL
;
7550 status
= smb_set_posix_lock(conn
, req
,
7551 pdata
, total_data
, fsp
);
7555 case SMB_POSIX_PATH_OPEN
:
7558 /* We must have a pathname for this. */
7559 return NT_STATUS_INVALID_LEVEL
;
7562 status
= smb_posix_open(conn
, req
,
7570 case SMB_POSIX_PATH_UNLINK
:
7573 /* We must have a pathname for this. */
7574 return NT_STATUS_INVALID_LEVEL
;
7577 status
= smb_posix_unlink(conn
, req
,
7585 return NT_STATUS_INVALID_LEVEL
;
7588 if (!NT_STATUS_IS_OK(status
)) {
7592 *ret_data_size
= data_return_size
;
7593 return NT_STATUS_OK
;
7596 /****************************************************************************
7597 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7598 ****************************************************************************/
7600 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7601 struct smb_request
*req
,
7602 unsigned int tran_call
,
7603 char **pparams
, int total_params
,
7604 char **ppdata
, int total_data
,
7605 unsigned int max_data_bytes
)
7607 char *params
= *pparams
;
7608 char *pdata
= *ppdata
;
7610 struct smb_filename
*smb_fname
= NULL
;
7611 files_struct
*fsp
= NULL
;
7612 NTSTATUS status
= NT_STATUS_OK
;
7613 int data_return_size
= 0;
7616 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7620 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7621 if (total_params
< 4) {
7622 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7626 fsp
= file_fsp(req
, SVAL(params
,0));
7627 /* Basic check for non-null fsp. */
7628 if (!check_fsp_open(conn
, req
, fsp
)) {
7631 info_level
= SVAL(params
,2);
7633 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7635 if (!NT_STATUS_IS_OK(status
)) {
7636 reply_nterror(req
, status
);
7640 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7642 * This is actually a SETFILEINFO on a directory
7643 * handle (returned from an NT SMB). NT5.0 seems
7644 * to do this call. JRA.
7646 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7647 /* Always do lstat for UNIX calls. */
7648 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7649 DEBUG(3,("call_trans2setfilepathinfo: "
7650 "SMB_VFS_LSTAT of %s failed "
7652 smb_fname_str_dbg(smb_fname
),
7654 reply_nterror(req
, map_nt_error_from_unix(errno
));
7658 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7659 DEBUG(3,("call_trans2setfilepathinfo: "
7660 "fileinfo of %s failed (%s)\n",
7661 smb_fname_str_dbg(smb_fname
),
7663 reply_nterror(req
, map_nt_error_from_unix(errno
));
7667 } else if (fsp
->print_file
) {
7669 * Doing a DELETE_ON_CLOSE should cancel a print job.
7671 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7672 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7674 DEBUG(3,("call_trans2setfilepathinfo: "
7675 "Cancelling print job (%s)\n",
7679 send_trans2_replies(conn
, req
, params
, 2,
7685 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7690 * Original code - this is an open file.
7692 if (!check_fsp(conn
, req
, fsp
)) {
7696 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7697 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7698 "of fnum %d failed (%s)\n", fsp
->fnum
,
7700 reply_nterror(req
, map_nt_error_from_unix(errno
));
7708 if (total_params
< 7) {
7709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7713 info_level
= SVAL(params
,0);
7714 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7715 total_params
- 6, STR_TERMINATE
,
7717 if (!NT_STATUS_IS_OK(status
)) {
7718 reply_nterror(req
, status
);
7722 status
= filename_convert(req
, conn
,
7723 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7728 if (!NT_STATUS_IS_OK(status
)) {
7729 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7730 reply_botherror(req
,
7731 NT_STATUS_PATH_NOT_COVERED
,
7732 ERRSRV
, ERRbadpath
);
7735 reply_nterror(req
, status
);
7739 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7741 * For CIFS UNIX extensions the target name may not exist.
7744 /* Always do lstat for UNIX calls. */
7745 SMB_VFS_LSTAT(conn
, smb_fname
);
7747 } else if (!VALID_STAT(smb_fname
->st
) &&
7748 SMB_VFS_STAT(conn
, smb_fname
)) {
7749 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7751 smb_fname_str_dbg(smb_fname
),
7753 reply_nterror(req
, map_nt_error_from_unix(errno
));
7758 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7759 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7760 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7762 /* Realloc the parameter size */
7763 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7764 if (*pparams
== NULL
) {
7765 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7772 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7778 if (!NT_STATUS_IS_OK(status
)) {
7779 if (open_was_deferred(req
->mid
)) {
7780 /* We have re-scheduled this call. */
7783 if (blocking_lock_was_deferred(req
->mid
)) {
7784 /* We have re-scheduled this call. */
7787 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7788 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7789 ERRSRV
, ERRbadpath
);
7792 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7793 reply_openerror(req
, status
);
7797 reply_nterror(req
, status
);
7801 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7807 /****************************************************************************
7808 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7809 ****************************************************************************/
7811 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7812 char **pparams
, int total_params
,
7813 char **ppdata
, int total_data
,
7814 unsigned int max_data_bytes
)
7816 struct smb_filename
*smb_dname
= NULL
;
7817 char *params
= *pparams
;
7818 char *pdata
= *ppdata
;
7819 char *directory
= NULL
;
7820 NTSTATUS status
= NT_STATUS_OK
;
7821 struct ea_list
*ea_list
= NULL
;
7822 TALLOC_CTX
*ctx
= talloc_tos();
7824 if (!CAN_WRITE(conn
)) {
7825 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7829 if (total_params
< 5) {
7830 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7834 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7835 total_params
- 4, STR_TERMINATE
,
7837 if (!NT_STATUS_IS_OK(status
)) {
7838 reply_nterror(req
, status
);
7842 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7844 status
= filename_convert(ctx
,
7846 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7852 if (!NT_STATUS_IS_OK(status
)) {
7853 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7854 reply_botherror(req
,
7855 NT_STATUS_PATH_NOT_COVERED
,
7856 ERRSRV
, ERRbadpath
);
7859 reply_nterror(req
, status
);
7864 * OS/2 workplace shell seems to send SET_EA requests of "null"
7865 * length (4 bytes containing IVAL 4).
7866 * They seem to have no effect. Bug #3212. JRA.
7869 if (total_data
&& (total_data
!= 4)) {
7870 /* Any data in this call is an EA list. */
7871 if (total_data
< 10) {
7872 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7876 if (IVAL(pdata
,0) > total_data
) {
7877 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7878 IVAL(pdata
,0), (unsigned int)total_data
));
7879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7883 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7886 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7890 if (!lp_ea_support(SNUM(conn
))) {
7891 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7895 /* If total_data == 4 Windows doesn't care what values
7896 * are placed in that field, it just ignores them.
7897 * The System i QNTC IBM SMB client puts bad values here,
7898 * so ignore them. */
7900 status
= create_directory(conn
, req
, smb_dname
);
7902 if (!NT_STATUS_IS_OK(status
)) {
7903 reply_nterror(req
, status
);
7907 /* Try and set any given EA. */
7909 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7910 if (!NT_STATUS_IS_OK(status
)) {
7911 reply_nterror(req
, status
);
7916 /* Realloc the parameter and data sizes */
7917 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7918 if(*pparams
== NULL
) {
7919 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7926 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7929 TALLOC_FREE(smb_dname
);
7933 /****************************************************************************
7934 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7935 We don't actually do this - we just send a null response.
7936 ****************************************************************************/
7938 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7939 struct smb_request
*req
,
7940 char **pparams
, int total_params
,
7941 char **ppdata
, int total_data
,
7942 unsigned int max_data_bytes
)
7944 char *params
= *pparams
;
7947 if (total_params
< 6) {
7948 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7952 info_level
= SVAL(params
,4);
7953 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7955 switch (info_level
) {
7960 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7964 /* Realloc the parameter and data sizes */
7965 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7966 if (*pparams
== NULL
) {
7967 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7972 SSVAL(params
,0,fnf_handle
);
7973 SSVAL(params
,2,0); /* No changes */
7974 SSVAL(params
,4,0); /* No EA errors */
7981 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7986 /****************************************************************************
7987 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7988 changes). Currently this does nothing.
7989 ****************************************************************************/
7991 static void call_trans2findnotifynext(connection_struct
*conn
,
7992 struct smb_request
*req
,
7993 char **pparams
, int total_params
,
7994 char **ppdata
, int total_data
,
7995 unsigned int max_data_bytes
)
7997 char *params
= *pparams
;
7999 DEBUG(3,("call_trans2findnotifynext\n"));
8001 /* Realloc the parameter and data sizes */
8002 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8003 if (*pparams
== NULL
) {
8004 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8009 SSVAL(params
,0,0); /* No changes */
8010 SSVAL(params
,2,0); /* No EA errors */
8012 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8017 /****************************************************************************
8018 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8019 ****************************************************************************/
8021 static void call_trans2getdfsreferral(connection_struct
*conn
,
8022 struct smb_request
*req
,
8023 char **pparams
, int total_params
,
8024 char **ppdata
, int total_data
,
8025 unsigned int max_data_bytes
)
8027 char *params
= *pparams
;
8028 char *pathname
= NULL
;
8030 int max_referral_level
;
8031 NTSTATUS status
= NT_STATUS_OK
;
8032 TALLOC_CTX
*ctx
= talloc_tos();
8034 DEBUG(10,("call_trans2getdfsreferral\n"));
8036 if (total_params
< 3) {
8037 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8041 max_referral_level
= SVAL(params
,0);
8043 if(!lp_host_msdfs()) {
8044 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8048 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8049 total_params
- 2, STR_TERMINATE
);
8051 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8054 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8055 ppdata
,&status
)) < 0) {
8056 reply_nterror(req
, status
);
8060 SSVAL(req
->inbuf
, smb_flg2
,
8061 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8062 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8067 #define LMCAT_SPL 0x53
8068 #define LMFUNC_GETJOBID 0x60
8070 /****************************************************************************
8071 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8072 ****************************************************************************/
8074 static void call_trans2ioctl(connection_struct
*conn
,
8075 struct smb_request
*req
,
8076 char **pparams
, int total_params
,
8077 char **ppdata
, int total_data
,
8078 unsigned int max_data_bytes
)
8080 char *pdata
= *ppdata
;
8081 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8083 /* check for an invalid fid before proceeding */
8086 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8090 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8091 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8092 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8093 if (*ppdata
== NULL
) {
8094 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8099 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8100 CAN ACCEPT THIS IN UNICODE. JRA. */
8102 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8103 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8104 global_myname(), 15,
8105 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8106 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8107 lp_servicename(SNUM(conn
)), 13,
8108 STR_ASCII
|STR_TERMINATE
); /* Service name */
8109 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8114 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8115 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8118 /****************************************************************************
8119 Reply to a SMBfindclose (stop trans2 directory search).
8120 ****************************************************************************/
8122 void reply_findclose(struct smb_request
*req
)
8125 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8127 START_PROFILE(SMBfindclose
);
8130 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8131 END_PROFILE(SMBfindclose
);
8135 dptr_num
= SVALS(req
->vwv
+0, 0);
8137 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8139 dptr_close(sconn
, &dptr_num
);
8141 reply_outbuf(req
, 0, 0);
8143 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8145 END_PROFILE(SMBfindclose
);
8149 /****************************************************************************
8150 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8151 ****************************************************************************/
8153 void reply_findnclose(struct smb_request
*req
)
8157 START_PROFILE(SMBfindnclose
);
8160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8161 END_PROFILE(SMBfindnclose
);
8165 dptr_num
= SVAL(req
->vwv
+0, 0);
8167 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8169 /* We never give out valid handles for a
8170 findnotifyfirst - so any dptr_num is ok here.
8173 reply_outbuf(req
, 0, 0);
8175 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8177 END_PROFILE(SMBfindnclose
);
8181 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8182 struct trans_state
*state
)
8184 if (get_Protocol() >= PROTOCOL_NT1
) {
8185 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8186 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8189 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8190 if (state
->call
!= TRANSACT2_QFSINFO
&&
8191 state
->call
!= TRANSACT2_SETFSINFO
) {
8192 DEBUG(0,("handle_trans2: encryption required "
8194 (unsigned int)state
->call
));
8195 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8200 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8202 /* Now we must call the relevant TRANS2 function */
8203 switch(state
->call
) {
8204 case TRANSACT2_OPEN
:
8206 START_PROFILE(Trans2_open
);
8207 call_trans2open(conn
, req
,
8208 &state
->param
, state
->total_param
,
8209 &state
->data
, state
->total_data
,
8210 state
->max_data_return
);
8211 END_PROFILE(Trans2_open
);
8215 case TRANSACT2_FINDFIRST
:
8217 START_PROFILE(Trans2_findfirst
);
8218 call_trans2findfirst(conn
, req
,
8219 &state
->param
, state
->total_param
,
8220 &state
->data
, state
->total_data
,
8221 state
->max_data_return
);
8222 END_PROFILE(Trans2_findfirst
);
8226 case TRANSACT2_FINDNEXT
:
8228 START_PROFILE(Trans2_findnext
);
8229 call_trans2findnext(conn
, req
,
8230 &state
->param
, state
->total_param
,
8231 &state
->data
, state
->total_data
,
8232 state
->max_data_return
);
8233 END_PROFILE(Trans2_findnext
);
8237 case TRANSACT2_QFSINFO
:
8239 START_PROFILE(Trans2_qfsinfo
);
8240 call_trans2qfsinfo(conn
, req
,
8241 &state
->param
, state
->total_param
,
8242 &state
->data
, state
->total_data
,
8243 state
->max_data_return
);
8244 END_PROFILE(Trans2_qfsinfo
);
8248 case TRANSACT2_SETFSINFO
:
8250 START_PROFILE(Trans2_setfsinfo
);
8251 call_trans2setfsinfo(conn
, req
,
8252 &state
->param
, state
->total_param
,
8253 &state
->data
, state
->total_data
,
8254 state
->max_data_return
);
8255 END_PROFILE(Trans2_setfsinfo
);
8259 case TRANSACT2_QPATHINFO
:
8260 case TRANSACT2_QFILEINFO
:
8262 START_PROFILE(Trans2_qpathinfo
);
8263 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8264 &state
->param
, state
->total_param
,
8265 &state
->data
, state
->total_data
,
8266 state
->max_data_return
);
8267 END_PROFILE(Trans2_qpathinfo
);
8271 case TRANSACT2_SETPATHINFO
:
8272 case TRANSACT2_SETFILEINFO
:
8274 START_PROFILE(Trans2_setpathinfo
);
8275 call_trans2setfilepathinfo(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_setpathinfo
);
8283 case TRANSACT2_FINDNOTIFYFIRST
:
8285 START_PROFILE(Trans2_findnotifyfirst
);
8286 call_trans2findnotifyfirst(conn
, req
,
8287 &state
->param
, state
->total_param
,
8288 &state
->data
, state
->total_data
,
8289 state
->max_data_return
);
8290 END_PROFILE(Trans2_findnotifyfirst
);
8294 case TRANSACT2_FINDNOTIFYNEXT
:
8296 START_PROFILE(Trans2_findnotifynext
);
8297 call_trans2findnotifynext(conn
, req
,
8298 &state
->param
, state
->total_param
,
8299 &state
->data
, state
->total_data
,
8300 state
->max_data_return
);
8301 END_PROFILE(Trans2_findnotifynext
);
8305 case TRANSACT2_MKDIR
:
8307 START_PROFILE(Trans2_mkdir
);
8308 call_trans2mkdir(conn
, req
,
8309 &state
->param
, state
->total_param
,
8310 &state
->data
, state
->total_data
,
8311 state
->max_data_return
);
8312 END_PROFILE(Trans2_mkdir
);
8316 case TRANSACT2_GET_DFS_REFERRAL
:
8318 START_PROFILE(Trans2_get_dfs_referral
);
8319 call_trans2getdfsreferral(conn
, req
,
8320 &state
->param
, state
->total_param
,
8321 &state
->data
, state
->total_data
,
8322 state
->max_data_return
);
8323 END_PROFILE(Trans2_get_dfs_referral
);
8327 case TRANSACT2_IOCTL
:
8329 START_PROFILE(Trans2_ioctl
);
8330 call_trans2ioctl(conn
, req
,
8331 &state
->param
, state
->total_param
,
8332 &state
->data
, state
->total_data
,
8333 state
->max_data_return
);
8334 END_PROFILE(Trans2_ioctl
);
8339 /* Error in request */
8340 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8341 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8345 /****************************************************************************
8346 Reply to a SMBtrans2.
8347 ****************************************************************************/
8349 void reply_trans2(struct smb_request
*req
)
8351 connection_struct
*conn
= req
->conn
;
8356 unsigned int tran_call
;
8357 struct trans_state
*state
;
8360 START_PROFILE(SMBtrans2
);
8362 if (req
->wct
< 14) {
8363 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8364 END_PROFILE(SMBtrans2
);
8368 dsoff
= SVAL(req
->vwv
+12, 0);
8369 dscnt
= SVAL(req
->vwv
+11, 0);
8370 psoff
= SVAL(req
->vwv
+10, 0);
8371 pscnt
= SVAL(req
->vwv
+9, 0);
8372 tran_call
= SVAL(req
->vwv
+14, 0);
8374 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8375 if (!NT_STATUS_IS_OK(result
)) {
8376 DEBUG(2, ("Got invalid trans2 request: %s\n",
8377 nt_errstr(result
)));
8378 reply_nterror(req
, result
);
8379 END_PROFILE(SMBtrans2
);
8384 switch (tran_call
) {
8385 /* List the allowed trans2 calls on IPC$ */
8386 case TRANSACT2_OPEN
:
8387 case TRANSACT2_GET_DFS_REFERRAL
:
8388 case TRANSACT2_QFILEINFO
:
8389 case TRANSACT2_QFSINFO
:
8390 case TRANSACT2_SETFSINFO
:
8393 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8394 END_PROFILE(SMBtrans2
);
8399 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8400 DEBUG(0, ("talloc failed\n"));
8401 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8402 END_PROFILE(SMBtrans2
);
8406 state
->cmd
= SMBtrans2
;
8408 state
->mid
= req
->mid
;
8409 state
->vuid
= req
->vuid
;
8410 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8411 state
->setup
= NULL
;
8412 state
->total_param
= SVAL(req
->vwv
+0, 0);
8413 state
->param
= NULL
;
8414 state
->total_data
= SVAL(req
->vwv
+1, 0);
8416 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8417 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8418 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8419 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8420 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8422 state
->call
= tran_call
;
8424 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8425 is so as a sanity check */
8426 if (state
->setup_count
!= 1) {
8428 * Need to have rc=0 for ioctl to get job id for OS/2.
8429 * Network printing will fail if function is not successful.
8430 * Similar function in reply.c will be used if protocol
8431 * is LANMAN1.0 instead of LM1.2X002.
8432 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8433 * outbuf doesn't have to be set(only job id is used).
8435 if ( (state
->setup_count
== 4)
8436 && (tran_call
== TRANSACT2_IOCTL
)
8437 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8438 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8439 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8441 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8442 DEBUG(2,("Transaction is %d\n",tran_call
));
8444 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8445 END_PROFILE(SMBtrans2
);
8450 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8453 if (state
->total_data
) {
8455 if (trans_oob(state
->total_data
, 0, dscnt
)
8456 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8460 /* Can't use talloc here, the core routines do realloc on the
8461 * params and data. */
8462 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8463 if (state
->data
== NULL
) {
8464 DEBUG(0,("reply_trans2: data malloc fail for %u "
8465 "bytes !\n", (unsigned int)state
->total_data
));
8467 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8468 END_PROFILE(SMBtrans2
);
8472 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8475 if (state
->total_param
) {
8477 if (trans_oob(state
->total_param
, 0, pscnt
)
8478 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8482 /* Can't use talloc here, the core routines do realloc on the
8483 * params and data. */
8484 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8485 if (state
->param
== NULL
) {
8486 DEBUG(0,("reply_trans: param malloc fail for %u "
8487 "bytes !\n", (unsigned int)state
->total_param
));
8488 SAFE_FREE(state
->data
);
8490 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8491 END_PROFILE(SMBtrans2
);
8495 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8498 state
->received_data
= dscnt
;
8499 state
->received_param
= pscnt
;
8501 if ((state
->received_param
== state
->total_param
) &&
8502 (state
->received_data
== state
->total_data
)) {
8504 handle_trans2(conn
, req
, state
);
8506 SAFE_FREE(state
->data
);
8507 SAFE_FREE(state
->param
);
8509 END_PROFILE(SMBtrans2
);
8513 DLIST_ADD(conn
->pending_trans
, state
);
8515 /* We need to send an interim response then receive the rest
8516 of the parameter/data bytes */
8517 reply_outbuf(req
, 0, 0);
8518 show_msg((char *)req
->outbuf
);
8519 END_PROFILE(SMBtrans2
);
8524 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8525 SAFE_FREE(state
->data
);
8526 SAFE_FREE(state
->param
);
8528 END_PROFILE(SMBtrans2
);
8529 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8533 /****************************************************************************
8534 Reply to a SMBtranss2
8535 ****************************************************************************/
8537 void reply_transs2(struct smb_request
*req
)
8539 connection_struct
*conn
= req
->conn
;
8540 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8541 struct trans_state
*state
;
8543 START_PROFILE(SMBtranss2
);
8545 show_msg((char *)req
->inbuf
);
8548 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8549 END_PROFILE(SMBtranss2
);
8553 for (state
= conn
->pending_trans
; state
!= NULL
;
8554 state
= state
->next
) {
8555 if (state
->mid
== req
->mid
) {
8560 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8561 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8562 END_PROFILE(SMBtranss2
);
8566 /* Revise state->total_param and state->total_data in case they have
8567 changed downwards */
8569 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8570 state
->total_param
= SVAL(req
->vwv
+0, 0);
8571 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8572 state
->total_data
= SVAL(req
->vwv
+1, 0);
8574 pcnt
= SVAL(req
->vwv
+2, 0);
8575 poff
= SVAL(req
->vwv
+3, 0);
8576 pdisp
= SVAL(req
->vwv
+4, 0);
8578 dcnt
= SVAL(req
->vwv
+5, 0);
8579 doff
= SVAL(req
->vwv
+6, 0);
8580 ddisp
= SVAL(req
->vwv
+7, 0);
8582 state
->received_param
+= pcnt
;
8583 state
->received_data
+= dcnt
;
8585 if ((state
->received_data
> state
->total_data
) ||
8586 (state
->received_param
> state
->total_param
))
8590 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8591 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8594 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8598 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8599 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8602 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8605 if ((state
->received_param
< state
->total_param
) ||
8606 (state
->received_data
< state
->total_data
)) {
8607 END_PROFILE(SMBtranss2
);
8611 handle_trans2(conn
, req
, state
);
8613 DLIST_REMOVE(conn
->pending_trans
, state
);
8614 SAFE_FREE(state
->data
);
8615 SAFE_FREE(state
->param
);
8618 END_PROFILE(SMBtranss2
);
8623 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8624 DLIST_REMOVE(conn
->pending_trans
, state
);
8625 SAFE_FREE(state
->data
);
8626 SAFE_FREE(state
->param
);
8628 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8629 END_PROFILE(SMBtranss2
);