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
->base_name
, deny_mode
,
1073 &access_mask
, &share_mode
,
1074 &create_disposition
,
1076 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1080 /* Any data in this call is an EA list. */
1081 if (total_data
&& (total_data
!= 4)) {
1082 if (total_data
< 10) {
1083 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1087 if (IVAL(pdata
,0) > total_data
) {
1088 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1089 IVAL(pdata
,0), (unsigned int)total_data
));
1090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1094 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1101 if (!lp_ea_support(SNUM(conn
))) {
1102 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1107 status
= SMB_VFS_CREATE_FILE(
1110 0, /* root_dir_fid */
1111 smb_fname
, /* fname */
1112 access_mask
, /* access_mask */
1113 share_mode
, /* share_access */
1114 create_disposition
, /* create_disposition*/
1115 create_options
, /* create_options */
1116 open_attr
, /* file_attributes */
1117 oplock_request
, /* oplock_request */
1118 open_size
, /* allocation_size */
1120 ea_list
, /* ea_list */
1122 &smb_action
); /* psbuf */
1124 if (!NT_STATUS_IS_OK(status
)) {
1125 if (open_was_deferred(req
->mid
)) {
1126 /* We have re-scheduled this call. */
1129 reply_openerror(req
, status
);
1133 size
= get_file_size_stat(&smb_fname
->st
);
1134 fattr
= dos_mode(conn
, smb_fname
);
1135 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1136 inode
= smb_fname
->st
.st_ex_ino
;
1138 close_file(req
, fsp
, ERROR_CLOSE
);
1139 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1143 /* Realloc the size of parameters and data we will return */
1144 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1145 if(*pparams
== NULL
) {
1146 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1151 SSVAL(params
,0,fsp
->fnum
);
1152 SSVAL(params
,2,fattr
);
1153 srv_put_dos_date2(params
,4, mtime
);
1154 SIVAL(params
,8, (uint32
)size
);
1155 SSVAL(params
,12,deny_mode
);
1156 SSVAL(params
,14,0); /* open_type - file or directory. */
1157 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1159 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1160 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1163 SSVAL(params
,18,smb_action
);
1166 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1168 SIVAL(params
,20,inode
);
1169 SSVAL(params
,24,0); /* Padding. */
1171 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1172 fsp
->fsp_name
->base_name
);
1173 SIVAL(params
, 26, ea_size
);
1175 SIVAL(params
, 26, 0);
1178 /* Send the required number of replies */
1179 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1181 TALLOC_FREE(smb_fname
);
1184 /*********************************************************
1185 Routine to check if a given string matches exactly.
1186 as a special case a mask of "." does NOT match. That
1187 is required for correct wildcard semantics
1188 Case can be significant or not.
1189 **********************************************************/
1191 static bool exact_match(bool has_wild
,
1192 bool case_sensitive
,
1196 if (mask
[0] == '.' && mask
[1] == 0) {
1204 if (case_sensitive
) {
1205 return strcmp(str
,mask
)==0;
1207 return StrCaseCmp(str
,mask
) == 0;
1211 /****************************************************************************
1212 Return the filetype for UNIX extensions.
1213 ****************************************************************************/
1215 static uint32
unix_filetype(mode_t mode
)
1218 return UNIX_TYPE_FILE
;
1219 else if(S_ISDIR(mode
))
1220 return UNIX_TYPE_DIR
;
1222 else if(S_ISLNK(mode
))
1223 return UNIX_TYPE_SYMLINK
;
1226 else if(S_ISCHR(mode
))
1227 return UNIX_TYPE_CHARDEV
;
1230 else if(S_ISBLK(mode
))
1231 return UNIX_TYPE_BLKDEV
;
1234 else if(S_ISFIFO(mode
))
1235 return UNIX_TYPE_FIFO
;
1238 else if(S_ISSOCK(mode
))
1239 return UNIX_TYPE_SOCKET
;
1242 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1243 return UNIX_TYPE_UNKNOWN
;
1246 /****************************************************************************
1247 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1248 ****************************************************************************/
1250 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1252 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1253 const SMB_STRUCT_STAT
*psbuf
,
1255 enum perm_type ptype
,
1260 if (perms
== SMB_MODE_NO_CHANGE
) {
1261 if (!VALID_STAT(*psbuf
)) {
1262 return NT_STATUS_INVALID_PARAMETER
;
1264 *ret_perms
= psbuf
->st_ex_mode
;
1265 return NT_STATUS_OK
;
1269 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1270 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1271 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1272 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1273 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1274 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1275 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1276 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1277 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1279 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1282 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1285 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1290 /* Apply mode mask */
1291 ret
&= lp_create_mask(SNUM(conn
));
1292 /* Add in force bits */
1293 ret
|= lp_force_create_mode(SNUM(conn
));
1296 ret
&= lp_dir_mask(SNUM(conn
));
1297 /* Add in force bits */
1298 ret
|= lp_force_dir_mode(SNUM(conn
));
1300 case PERM_EXISTING_FILE
:
1301 /* Apply mode mask */
1302 ret
&= lp_security_mask(SNUM(conn
));
1303 /* Add in force bits */
1304 ret
|= lp_force_security_mode(SNUM(conn
));
1306 case PERM_EXISTING_DIR
:
1307 /* Apply mode mask */
1308 ret
&= lp_dir_security_mask(SNUM(conn
));
1309 /* Add in force bits */
1310 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1315 return NT_STATUS_OK
;
1318 /****************************************************************************
1319 Needed to show the msdfs symlinks as directories. Modifies psbuf
1320 to be a directory if it's a msdfs link.
1321 ****************************************************************************/
1323 static bool check_msdfs_link(connection_struct
*conn
,
1324 const char *pathname
,
1325 SMB_STRUCT_STAT
*psbuf
)
1327 int saved_errno
= errno
;
1328 if(lp_host_msdfs() &&
1329 lp_msdfs_root(SNUM(conn
)) &&
1330 is_msdfs_link(conn
, pathname
, psbuf
)) {
1332 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1335 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1336 errno
= saved_errno
;
1339 errno
= saved_errno
;
1344 /****************************************************************************
1345 Get a level dependent lanman2 dir entry.
1346 ****************************************************************************/
1348 struct smbd_dirptr_lanman2_state
{
1349 connection_struct
*conn
;
1350 uint32_t info_level
;
1351 bool check_mangled_names
;
1353 bool got_exact_match
;
1356 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1362 struct smbd_dirptr_lanman2_state
*state
=
1363 (struct smbd_dirptr_lanman2_state
*)private_data
;
1365 char mangled_name
[13]; /* mangled 8.3 name. */
1369 /* Mangle fname if it's an illegal name. */
1370 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1371 ok
= name_to_8_3(dname
, mangled_name
,
1372 true, state
->conn
->params
);
1376 fname
= mangled_name
;
1381 got_match
= exact_match(state
->has_wild
,
1382 state
->conn
->case_sensitive
,
1384 state
->got_exact_match
= got_match
;
1386 got_match
= mask_match(fname
, mask
,
1387 state
->conn
->case_sensitive
);
1390 if(!got_match
&& state
->check_mangled_names
&&
1391 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1393 * It turns out that NT matches wildcards against
1394 * both long *and* short names. This may explain some
1395 * of the wildcard wierdness from old DOS clients
1396 * that some people have been seeing.... JRA.
1398 /* Force the mangling into 8.3. */
1399 ok
= name_to_8_3(fname
, mangled_name
,
1400 false, state
->conn
->params
);
1405 got_match
= exact_match(state
->has_wild
,
1406 state
->conn
->case_sensitive
,
1407 mangled_name
, mask
);
1408 state
->got_exact_match
= got_match
;
1410 got_match
= mask_match(mangled_name
, mask
,
1411 state
->conn
->case_sensitive
);
1419 *_fname
= talloc_strdup(ctx
, fname
);
1420 if (*_fname
== NULL
) {
1427 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1429 struct smb_filename
*smb_fname
,
1432 struct smbd_dirptr_lanman2_state
*state
=
1433 (struct smbd_dirptr_lanman2_state
*)private_data
;
1434 bool ms_dfs_link
= false;
1437 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1438 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't lstat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname
),
1445 } else if (!VALID_STAT(smb_fname
->st
) &&
1446 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1447 /* Needed to show the msdfs symlinks as
1450 ms_dfs_link
= check_msdfs_link(state
->conn
,
1451 smb_fname
->base_name
,
1454 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1455 "Couldn't stat [%s] (%s)\n",
1456 smb_fname_str_dbg(smb_fname
),
1463 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1465 mode
= dos_mode(state
->conn
, smb_fname
);
1472 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1473 connection_struct
*conn
,
1475 uint32_t info_level
,
1476 struct ea_list
*name_list
,
1477 bool check_mangled_names
,
1478 bool requires_resume_key
,
1481 const struct smb_filename
*smb_fname
,
1482 uint64_t space_remaining
,
1489 uint64_t *last_entry_off
)
1491 char *p
, *q
, *pdata
= *ppdata
;
1493 uint64_t file_size
= 0;
1494 uint64_t allocation_size
= 0;
1495 uint64_t file_index
= 0;
1497 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1498 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1499 time_t c_date
= (time_t)0;
1501 char *last_entry_ptr
;
1506 *out_of_space
= false;
1508 ZERO_STRUCT(mdate_ts
);
1509 ZERO_STRUCT(adate_ts
);
1510 ZERO_STRUCT(create_date_ts
);
1511 ZERO_STRUCT(cdate_ts
);
1513 if (!(mode
& aDIR
)) {
1514 file_size
= get_file_size_stat(&smb_fname
->st
);
1516 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1518 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1520 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1521 adate_ts
= smb_fname
->st
.st_ex_atime
;
1522 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1523 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1525 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1526 dos_filetime_timespec(&create_date_ts
);
1527 dos_filetime_timespec(&mdate_ts
);
1528 dos_filetime_timespec(&adate_ts
);
1529 dos_filetime_timespec(&cdate_ts
);
1532 create_date
= convert_timespec_to_time_t(create_date_ts
);
1533 mdate
= convert_timespec_to_time_t(mdate_ts
);
1534 adate
= convert_timespec_to_time_t(adate_ts
);
1535 c_date
= convert_timespec_to_time_t(cdate_ts
);
1537 /* align the record */
1538 off
= PTR_DIFF(pdata
, base_data
);
1539 pad
= (off
+ (align
-1)) & ~(align
-1);
1542 /* initialize padding to 0 */
1544 memset(pdata
, 0, pad
);
1546 space_remaining
-= pad
;
1555 switch (info_level
) {
1556 case SMB_FIND_INFO_STANDARD
:
1557 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1558 if(requires_resume_key
) {
1562 srv_put_dos_date2(p
,0,create_date
);
1563 srv_put_dos_date2(p
,4,adate
);
1564 srv_put_dos_date2(p
,8,mdate
);
1565 SIVAL(p
,12,(uint32
)file_size
);
1566 SIVAL(p
,16,(uint32
)allocation_size
);
1570 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1571 p
+= ucs2_align(base_data
, p
, 0);
1573 len
= srvstr_push(base_data
, flags2
, p
,
1574 fname
, PTR_DIFF(end_data
, p
),
1576 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1578 SCVAL(nameptr
, -1, len
- 2);
1580 SCVAL(nameptr
, -1, 0);
1584 SCVAL(nameptr
, -1, len
- 1);
1586 SCVAL(nameptr
, -1, 0);
1592 case SMB_FIND_EA_SIZE
:
1593 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1594 if (requires_resume_key
) {
1598 srv_put_dos_date2(p
,0,create_date
);
1599 srv_put_dos_date2(p
,4,adate
);
1600 srv_put_dos_date2(p
,8,mdate
);
1601 SIVAL(p
,12,(uint32
)file_size
);
1602 SIVAL(p
,16,(uint32
)allocation_size
);
1605 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1606 smb_fname
->base_name
);
1607 SIVAL(p
,22,ea_size
); /* Extended attributes */
1611 len
= srvstr_push(base_data
, flags2
,
1612 p
, fname
, PTR_DIFF(end_data
, p
),
1613 STR_TERMINATE
| STR_NOALIGN
);
1614 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1627 SCVAL(nameptr
,0,len
);
1629 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1632 case SMB_FIND_EA_LIST
:
1634 struct ea_list
*file_list
= NULL
;
1637 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1641 if (requires_resume_key
) {
1645 srv_put_dos_date2(p
,0,create_date
);
1646 srv_put_dos_date2(p
,4,adate
);
1647 srv_put_dos_date2(p
,8,mdate
);
1648 SIVAL(p
,12,(uint32
)file_size
);
1649 SIVAL(p
,16,(uint32
)allocation_size
);
1651 p
+= 22; /* p now points to the EA area. */
1653 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1654 smb_fname
->base_name
,
1656 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1658 /* We need to determine if this entry will fit in the space available. */
1659 /* Max string size is 255 bytes. */
1660 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1661 *out_of_space
= true;
1662 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1663 return False
; /* Not finished - just out of space */
1666 /* Push the ea_data followed by the name. */
1667 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1669 len
= srvstr_push(base_data
, flags2
,
1670 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1671 STR_TERMINATE
| STR_NOALIGN
);
1672 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1685 SCVAL(nameptr
,0,len
);
1687 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1691 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1692 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1693 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1695 SIVAL(p
,0,reskey
); p
+= 4;
1696 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1697 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1698 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1699 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1700 SOFF_T(p
,0,file_size
); p
+= 8;
1701 SOFF_T(p
,0,allocation_size
); p
+= 8;
1702 SIVAL(p
,0,mode
); p
+= 4;
1703 q
= p
; p
+= 4; /* q is placeholder for name length. */
1705 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1706 smb_fname
->base_name
);
1707 SIVAL(p
,0,ea_size
); /* Extended attributes */
1710 /* Clear the short name buffer. This is
1711 * IMPORTANT as not doing so will trigger
1712 * a Win2k client bug. JRA.
1714 if (!was_8_3
&& check_mangled_names
) {
1715 char mangled_name
[13]; /* mangled 8.3 name. */
1716 if (!name_to_8_3(fname
,mangled_name
,True
,
1718 /* Error - mangle failed ! */
1719 memset(mangled_name
,'\0',12);
1721 mangled_name
[12] = 0;
1722 len
= srvstr_push(base_data
, flags2
,
1723 p
+2, mangled_name
, 24,
1724 STR_UPPER
|STR_UNICODE
);
1726 memset(p
+ 2 + len
,'\0',24 - len
);
1733 len
= srvstr_push(base_data
, flags2
, p
,
1734 fname
, PTR_DIFF(end_data
, p
),
1735 STR_TERMINATE_ASCII
);
1739 len
= PTR_DIFF(p
, pdata
);
1740 pad
= (len
+ (align
-1)) & ~(align
-1);
1742 * offset to the next entry, the caller
1743 * will overwrite it for the last entry
1744 * that's why we always include the padding
1748 * set padding to zero
1751 memset(p
, 0, pad
- len
);
1758 case SMB_FIND_FILE_DIRECTORY_INFO
:
1759 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1761 SIVAL(p
,0,reskey
); p
+= 4;
1762 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1763 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1764 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1765 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1766 SOFF_T(p
,0,file_size
); p
+= 8;
1767 SOFF_T(p
,0,allocation_size
); p
+= 8;
1768 SIVAL(p
,0,mode
); p
+= 4;
1769 len
= srvstr_push(base_data
, flags2
,
1770 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1771 STR_TERMINATE_ASCII
);
1775 len
= PTR_DIFF(p
, pdata
);
1776 pad
= (len
+ (align
-1)) & ~(align
-1);
1778 * offset to the next entry, the caller
1779 * will overwrite it for the last entry
1780 * that's why we always include the padding
1784 * set padding to zero
1787 memset(p
, 0, pad
- len
);
1794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1795 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1797 SIVAL(p
,0,reskey
); p
+= 4;
1798 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1799 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1800 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1801 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1802 SOFF_T(p
,0,file_size
); p
+= 8;
1803 SOFF_T(p
,0,allocation_size
); p
+= 8;
1804 SIVAL(p
,0,mode
); p
+= 4;
1805 q
= p
; p
+= 4; /* q is placeholder for name length. */
1807 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1808 smb_fname
->base_name
);
1809 SIVAL(p
,0,ea_size
); /* Extended attributes */
1812 len
= srvstr_push(base_data
, flags2
, p
,
1813 fname
, PTR_DIFF(end_data
, p
),
1814 STR_TERMINATE_ASCII
);
1818 len
= PTR_DIFF(p
, pdata
);
1819 pad
= (len
+ (align
-1)) & ~(align
-1);
1821 * offset to the next entry, the caller
1822 * will overwrite it for the last entry
1823 * that's why we always include the padding
1827 * set padding to zero
1830 memset(p
, 0, pad
- len
);
1837 case SMB_FIND_FILE_NAMES_INFO
:
1838 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1840 SIVAL(p
,0,reskey
); p
+= 4;
1842 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1843 acl on a dir (tridge) */
1844 len
= srvstr_push(base_data
, flags2
, p
,
1845 fname
, PTR_DIFF(end_data
, p
),
1846 STR_TERMINATE_ASCII
);
1850 len
= PTR_DIFF(p
, pdata
);
1851 pad
= (len
+ (align
-1)) & ~(align
-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1859 * set padding to zero
1862 memset(p
, 0, pad
- len
);
1869 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1872 SIVAL(p
,0,reskey
); p
+= 4;
1873 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1874 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1876 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1877 SOFF_T(p
,0,file_size
); p
+= 8;
1878 SOFF_T(p
,0,allocation_size
); p
+= 8;
1879 SIVAL(p
,0,mode
); p
+= 4;
1880 q
= p
; p
+= 4; /* q is placeholder for name length. */
1882 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1883 smb_fname
->base_name
);
1884 SIVAL(p
,0,ea_size
); /* Extended attributes */
1887 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1888 SBVAL(p
,0,file_index
); p
+= 8;
1889 len
= srvstr_push(base_data
, flags2
, p
,
1890 fname
, PTR_DIFF(end_data
, p
),
1891 STR_TERMINATE_ASCII
);
1895 len
= PTR_DIFF(p
, pdata
);
1896 pad
= (len
+ (align
-1)) & ~(align
-1);
1898 * offset to the next entry, the caller
1899 * will overwrite it for the last entry
1900 * that's why we always include the padding
1904 * set padding to zero
1907 memset(p
, 0, pad
- len
);
1914 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1915 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1916 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1918 SIVAL(p
,0,reskey
); p
+= 4;
1919 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1920 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1921 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1922 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1923 SOFF_T(p
,0,file_size
); p
+= 8;
1924 SOFF_T(p
,0,allocation_size
); p
+= 8;
1925 SIVAL(p
,0,mode
); p
+= 4;
1926 q
= p
; p
+= 4; /* q is placeholder for name length */
1928 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1929 smb_fname
->base_name
);
1930 SIVAL(p
,0,ea_size
); /* Extended attributes */
1933 /* Clear the short name buffer. This is
1934 * IMPORTANT as not doing so will trigger
1935 * a Win2k client bug. JRA.
1937 if (!was_8_3
&& check_mangled_names
) {
1938 char mangled_name
[13]; /* mangled 8.3 name. */
1939 if (!name_to_8_3(fname
,mangled_name
,True
,
1941 /* Error - mangle failed ! */
1942 memset(mangled_name
,'\0',12);
1944 mangled_name
[12] = 0;
1945 len
= srvstr_push(base_data
, flags2
,
1946 p
+2, mangled_name
, 24,
1947 STR_UPPER
|STR_UNICODE
);
1950 memset(p
+ 2 + len
,'\0',24 - len
);
1957 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1958 SBVAL(p
,0,file_index
); p
+= 8;
1959 len
= srvstr_push(base_data
, flags2
, p
,
1960 fname
, PTR_DIFF(end_data
, p
),
1961 STR_TERMINATE_ASCII
);
1965 len
= PTR_DIFF(p
, pdata
);
1966 pad
= (len
+ (align
-1)) & ~(align
-1);
1968 * offset to the next entry, the caller
1969 * will overwrite it for the last entry
1970 * that's why we always include the padding
1974 * set padding to zero
1977 memset(p
, 0, pad
- len
);
1984 /* CIFS UNIX Extension. */
1986 case SMB_FIND_FILE_UNIX
:
1987 case SMB_FIND_FILE_UNIX_INFO2
:
1989 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1991 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1993 if (info_level
== SMB_FIND_FILE_UNIX
) {
1994 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1995 p
= store_file_unix_basic(conn
, p
,
1996 NULL
, &smb_fname
->st
);
1997 len
= srvstr_push(base_data
, flags2
, p
,
1998 fname
, PTR_DIFF(end_data
, p
),
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2002 p
= store_file_unix_basic_info2(conn
, p
,
2003 NULL
, &smb_fname
->st
);
2006 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2007 PTR_DIFF(end_data
, p
), 0);
2008 SIVAL(nameptr
, 0, len
);
2013 len
= PTR_DIFF(p
, pdata
);
2014 pad
= (len
+ (align
-1)) & ~(align
-1);
2016 * offset to the next entry, the caller
2017 * will overwrite it for the last entry
2018 * that's why we always include the padding
2022 * set padding to zero
2025 memset(p
, 0, pad
- len
);
2030 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2038 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2039 *out_of_space
= true;
2040 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2041 return false; /* Not finished - just out of space */
2044 /* Setup the last entry pointer, as an offset from base_data */
2045 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2046 /* Advance the data pointer to the next slot */
2052 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2053 connection_struct
*conn
,
2054 struct dptr_struct
*dirptr
,
2056 const char *path_mask
,
2059 int requires_resume_key
,
2067 int space_remaining
,
2069 bool *got_exact_match
,
2070 int *_last_entry_off
,
2071 struct ea_list
*name_list
)
2074 const char *mask
= NULL
;
2075 long prev_dirpos
= 0;
2078 struct smb_filename
*smb_fname
= NULL
;
2079 struct smbd_dirptr_lanman2_state state
;
2081 uint64_t last_entry_off
= 0;
2085 state
.info_level
= info_level
;
2086 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2087 state
.has_wild
= dptr_has_wild(dirptr
);
2088 state
.got_exact_match
= false;
2090 *out_of_space
= false;
2091 *got_exact_match
= false;
2093 p
= strrchr_m(path_mask
,'/');
2104 ok
= smbd_dirptr_get_entry(ctx
,
2110 smbd_dirptr_lanman2_match_fn
,
2111 smbd_dirptr_lanman2_mode_fn
,
2121 *got_exact_match
= state
.got_exact_match
;
2123 ok
= smbd_marshall_dir_entry(ctx
,
2128 state
.check_mangled_names
,
2129 requires_resume_key
,
2142 TALLOC_FREE(smb_fname
);
2143 if (*out_of_space
) {
2144 dptr_SeekDir(dirptr
, prev_dirpos
);
2151 *_last_entry_off
= last_entry_off
;
2155 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2156 connection_struct
*conn
,
2157 struct dptr_struct
*dirptr
,
2159 const char *path_mask
,
2162 bool requires_resume_key
,
2168 int space_remaining
,
2170 bool *got_exact_match
,
2171 int *last_entry_off
,
2172 struct ea_list
*name_list
)
2175 const bool do_pad
= true;
2177 if (info_level
>= 1 && info_level
<= 3) {
2178 /* No alignment on earlier info levels. */
2182 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2183 path_mask
, dirtype
, info_level
,
2184 requires_resume_key
, dont_descend
, ask_sharemode
,
2186 ppdata
, base_data
, end_data
,
2188 out_of_space
, got_exact_match
,
2189 last_entry_off
, name_list
);
2192 /****************************************************************************
2193 Reply to a TRANS2_FINDFIRST.
2194 ****************************************************************************/
2196 static void call_trans2findfirst(connection_struct
*conn
,
2197 struct smb_request
*req
,
2198 char **pparams
, int total_params
,
2199 char **ppdata
, int total_data
,
2200 unsigned int max_data_bytes
)
2202 /* We must be careful here that we don't return more than the
2203 allowed number of data bytes. If this means returning fewer than
2204 maxentries then so be it. We assume that the redirector has
2205 enough room for the fixed number of parameter bytes it has
2207 struct smb_filename
*smb_dname
= NULL
;
2208 char *params
= *pparams
;
2209 char *pdata
= *ppdata
;
2213 uint16 findfirst_flags
;
2214 bool close_after_first
;
2216 bool requires_resume_key
;
2218 char *directory
= NULL
;
2221 int last_entry_off
=0;
2225 bool finished
= False
;
2226 bool dont_descend
= False
;
2227 bool out_of_space
= False
;
2228 int space_remaining
;
2229 bool mask_contains_wcard
= False
;
2230 struct ea_list
*ea_list
= NULL
;
2231 NTSTATUS ntstatus
= NT_STATUS_OK
;
2232 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2233 TALLOC_CTX
*ctx
= talloc_tos();
2234 struct dptr_struct
*dirptr
= NULL
;
2235 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2237 if (total_params
< 13) {
2238 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2242 dirtype
= SVAL(params
,0);
2243 maxentries
= SVAL(params
,2);
2244 findfirst_flags
= SVAL(params
,4);
2245 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2246 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2247 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2248 info_level
= SVAL(params
,6);
2250 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2251 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2252 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2253 info_level
, max_data_bytes
));
2256 /* W2K3 seems to treat zero as 1. */
2260 switch (info_level
) {
2261 case SMB_FIND_INFO_STANDARD
:
2262 case SMB_FIND_EA_SIZE
:
2263 case SMB_FIND_EA_LIST
:
2264 case SMB_FIND_FILE_DIRECTORY_INFO
:
2265 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2266 case SMB_FIND_FILE_NAMES_INFO
:
2267 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2268 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2269 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2271 case SMB_FIND_FILE_UNIX
:
2272 case SMB_FIND_FILE_UNIX_INFO2
:
2273 /* Always use filesystem for UNIX mtime query. */
2274 ask_sharemode
= false;
2275 if (!lp_unix_extensions()) {
2276 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2281 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2285 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2286 params
+12, total_params
- 12,
2287 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2288 if (!NT_STATUS_IS_OK(ntstatus
)) {
2289 reply_nterror(req
, ntstatus
);
2293 ntstatus
= filename_convert(ctx
, conn
,
2294 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2297 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2298 &mask_contains_wcard
,
2300 if (!NT_STATUS_IS_OK(ntstatus
)) {
2301 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2302 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2303 ERRSRV
, ERRbadpath
);
2306 reply_nterror(req
, ntstatus
);
2310 mask
= smb_dname
->original_lcomp
;
2312 directory
= smb_dname
->base_name
;
2314 p
= strrchr_m(directory
,'/');
2316 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2317 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2318 mask
= talloc_strdup(ctx
,"*");
2320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2323 mask_contains_wcard
= True
;
2325 directory
= talloc_strdup(talloc_tos(), "./");
2327 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2334 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2336 if (info_level
== SMB_FIND_EA_LIST
) {
2339 if (total_data
< 4) {
2340 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2344 ea_size
= IVAL(pdata
,0);
2345 if (ea_size
!= total_data
) {
2346 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2347 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2352 if (!lp_ea_support(SNUM(conn
))) {
2353 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2357 /* Pull out the list of names. */
2358 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2360 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2365 *ppdata
= (char *)SMB_REALLOC(
2366 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2367 if(*ppdata
== NULL
) {
2368 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2372 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2374 /* Realloc the params space */
2375 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2376 if (*pparams
== NULL
) {
2377 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2382 /* Save the wildcard match and attribs we are using on this directory -
2383 needed as lanman2 assumes these are being saved between calls */
2385 ntstatus
= dptr_create(conn
,
2391 mask_contains_wcard
,
2395 if (!NT_STATUS_IS_OK(ntstatus
)) {
2396 reply_nterror(req
, ntstatus
);
2400 dptr_num
= dptr_dnum(dirptr
);
2401 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2403 /* Initialize per TRANS2_FIND_FIRST operation data */
2404 dptr_init_search_op(dirptr
);
2406 /* We don't need to check for VOL here as this is returned by
2407 a different TRANS2 call. */
2409 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2410 directory
,lp_dontdescend(SNUM(conn
))));
2411 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2412 dont_descend
= True
;
2415 space_remaining
= max_data_bytes
;
2416 out_of_space
= False
;
2418 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2419 bool got_exact_match
= False
;
2421 /* this is a heuristic to avoid seeking the dirptr except when
2422 absolutely necessary. It allows for a filename of about 40 chars */
2423 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2424 out_of_space
= True
;
2427 finished
= !get_lanman2_dir_entry(ctx
,
2431 mask
,dirtype
,info_level
,
2432 requires_resume_key
,dont_descend
,
2435 space_remaining
, &out_of_space
,
2437 &last_entry_off
, ea_list
);
2440 if (finished
&& out_of_space
)
2443 if (!finished
&& !out_of_space
)
2447 * As an optimisation if we know we aren't looking
2448 * for a wildcard name (ie. the name matches the wildcard exactly)
2449 * then we can finish on any (first) match.
2450 * This speeds up large directory searches. JRA.
2456 /* Ensure space_remaining never goes -ve. */
2457 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2458 space_remaining
= 0;
2459 out_of_space
= true;
2461 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2465 /* Check if we can close the dirptr */
2466 if(close_after_first
|| (finished
&& close_if_end
)) {
2467 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2468 dptr_close(sconn
, &dptr_num
);
2472 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2473 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2474 * the protocol level is less than NT1. Tested with smbclient. JRA.
2475 * This should fix the OS/2 client bug #2335.
2478 if(numentries
== 0) {
2479 dptr_close(sconn
, &dptr_num
);
2480 if (get_Protocol() < PROTOCOL_NT1
) {
2481 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2484 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2485 ERRDOS
, ERRbadfile
);
2490 /* At this point pdata points to numentries directory entries. */
2492 /* Set up the return parameter block */
2493 SSVAL(params
,0,dptr_num
);
2494 SSVAL(params
,2,numentries
);
2495 SSVAL(params
,4,finished
);
2496 SSVAL(params
,6,0); /* Never an EA error */
2497 SSVAL(params
,8,last_entry_off
);
2499 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2502 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2503 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2505 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2509 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2510 smb_fn_name(req
->cmd
),
2511 mask
, directory
, dirtype
, numentries
) );
2514 * Force a name mangle here to ensure that the
2515 * mask as an 8.3 name is top of the mangled cache.
2516 * The reasons for this are subtle. Don't remove
2517 * this code unless you know what you are doing
2518 * (see PR#13758). JRA.
2521 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2522 char mangled_name
[13];
2523 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2526 TALLOC_FREE(smb_dname
);
2530 /****************************************************************************
2531 Reply to a TRANS2_FINDNEXT.
2532 ****************************************************************************/
2534 static void call_trans2findnext(connection_struct
*conn
,
2535 struct smb_request
*req
,
2536 char **pparams
, int total_params
,
2537 char **ppdata
, int total_data
,
2538 unsigned int max_data_bytes
)
2540 /* We must be careful here that we don't return more than the
2541 allowed number of data bytes. If this means returning fewer than
2542 maxentries then so be it. We assume that the redirector has
2543 enough room for the fixed number of parameter bytes it has
2545 char *params
= *pparams
;
2546 char *pdata
= *ppdata
;
2552 uint16 findnext_flags
;
2553 bool close_after_request
;
2555 bool requires_resume_key
;
2557 bool mask_contains_wcard
= False
;
2558 char *resume_name
= NULL
;
2559 const char *mask
= NULL
;
2560 const char *directory
= NULL
;
2564 int i
, last_entry_off
=0;
2565 bool finished
= False
;
2566 bool dont_descend
= False
;
2567 bool out_of_space
= False
;
2568 int space_remaining
;
2569 struct ea_list
*ea_list
= NULL
;
2570 NTSTATUS ntstatus
= NT_STATUS_OK
;
2571 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2572 TALLOC_CTX
*ctx
= talloc_tos();
2573 struct dptr_struct
*dirptr
;
2574 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2576 if (total_params
< 13) {
2577 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2581 dptr_num
= SVAL(params
,0);
2582 maxentries
= SVAL(params
,2);
2583 info_level
= SVAL(params
,4);
2584 resume_key
= IVAL(params
,6);
2585 findnext_flags
= SVAL(params
,10);
2586 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2587 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2588 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2589 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2591 if (!continue_bit
) {
2592 /* We only need resume_name if continue_bit is zero. */
2593 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2595 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2596 &mask_contains_wcard
);
2597 if (!NT_STATUS_IS_OK(ntstatus
)) {
2598 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2599 complain (it thinks we're asking for the directory above the shared
2600 path or an invalid name). Catch this as the resume name is only compared, never used in
2601 a file access. JRA. */
2602 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2603 &resume_name
, params
+12,
2607 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2608 reply_nterror(req
, ntstatus
);
2614 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2615 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2616 resume_key = %d resume name = %s continue=%d level = %d\n",
2617 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2618 requires_resume_key
, resume_key
,
2619 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2622 /* W2K3 seems to treat zero as 1. */
2626 switch (info_level
) {
2627 case SMB_FIND_INFO_STANDARD
:
2628 case SMB_FIND_EA_SIZE
:
2629 case SMB_FIND_EA_LIST
:
2630 case SMB_FIND_FILE_DIRECTORY_INFO
:
2631 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2632 case SMB_FIND_FILE_NAMES_INFO
:
2633 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2634 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2635 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2637 case SMB_FIND_FILE_UNIX
:
2638 case SMB_FIND_FILE_UNIX_INFO2
:
2639 /* Always use filesystem for UNIX mtime query. */
2640 ask_sharemode
= false;
2641 if (!lp_unix_extensions()) {
2642 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2647 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2651 if (info_level
== SMB_FIND_EA_LIST
) {
2654 if (total_data
< 4) {
2655 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2659 ea_size
= IVAL(pdata
,0);
2660 if (ea_size
!= total_data
) {
2661 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2662 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2663 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2667 if (!lp_ea_support(SNUM(conn
))) {
2668 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2672 /* Pull out the list of names. */
2673 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2675 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2680 *ppdata
= (char *)SMB_REALLOC(
2681 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2682 if(*ppdata
== NULL
) {
2683 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2688 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2690 /* Realloc the params space */
2691 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2692 if(*pparams
== NULL
) {
2693 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2699 /* Check that the dptr is valid */
2700 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2701 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2705 directory
= dptr_path(sconn
, dptr_num
);
2707 /* Get the wildcard mask from the dptr */
2708 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2709 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2710 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2716 /* Get the attr mask from the dptr */
2717 dirtype
= dptr_attr(sconn
, dptr_num
);
2719 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2720 dptr_num
, mask
, dirtype
,
2722 dptr_TellDir(dirptr
)));
2724 /* Initialize per TRANS2_FIND_NEXT operation data */
2725 dptr_init_search_op(dirptr
);
2727 /* We don't need to check for VOL here as this is returned by
2728 a different TRANS2 call. */
2730 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2731 directory
,lp_dontdescend(SNUM(conn
))));
2732 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2733 dont_descend
= True
;
2736 space_remaining
= max_data_bytes
;
2737 out_of_space
= False
;
2740 * Seek to the correct position. We no longer use the resume key but
2741 * depend on the last file name instead.
2744 if(!continue_bit
&& resume_name
&& *resume_name
) {
2747 long current_pos
= 0;
2749 * Remember, name_to_8_3 is called by
2750 * get_lanman2_dir_entry(), so the resume name
2751 * could be mangled. Ensure we check the unmangled name.
2754 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2755 char *new_resume_name
= NULL
;
2756 mangle_lookup_name_from_8_3(ctx
,
2760 if (new_resume_name
) {
2761 resume_name
= new_resume_name
;
2766 * Fix for NT redirector problem triggered by resume key indexes
2767 * changing between directory scans. We now return a resume key of 0
2768 * and instead look for the filename to continue from (also given
2769 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2770 * findfirst/findnext (as is usual) then the directory pointer
2771 * should already be at the correct place.
2774 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2775 } /* end if resume_name && !continue_bit */
2777 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2778 bool got_exact_match
= False
;
2780 /* this is a heuristic to avoid seeking the dirptr except when
2781 absolutely necessary. It allows for a filename of about 40 chars */
2782 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2783 out_of_space
= True
;
2786 finished
= !get_lanman2_dir_entry(ctx
,
2790 mask
,dirtype
,info_level
,
2791 requires_resume_key
,dont_descend
,
2794 space_remaining
, &out_of_space
,
2796 &last_entry_off
, ea_list
);
2799 if (finished
&& out_of_space
)
2802 if (!finished
&& !out_of_space
)
2806 * As an optimisation if we know we aren't looking
2807 * for a wildcard name (ie. the name matches the wildcard exactly)
2808 * then we can finish on any (first) match.
2809 * This speeds up large directory searches. JRA.
2815 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2818 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2819 smb_fn_name(req
->cmd
),
2820 mask
, directory
, dirtype
, numentries
) );
2822 /* Check if we can close the dirptr */
2823 if(close_after_request
|| (finished
&& close_if_end
)) {
2824 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2825 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2828 /* Set up the return parameter block */
2829 SSVAL(params
,0,numentries
);
2830 SSVAL(params
,2,finished
);
2831 SSVAL(params
,4,0); /* Never an EA error */
2832 SSVAL(params
,6,last_entry_off
);
2834 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2840 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2842 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2846 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2848 SMB_ASSERT(extended_info
!= NULL
);
2850 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2851 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2852 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2853 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2854 #ifdef SAMBA_VERSION_REVISION
2855 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2857 extended_info
->samba_subversion
= 0;
2858 #ifdef SAMBA_VERSION_RC_RELEASE
2859 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2861 #ifdef SAMBA_VERSION_PRE_RELEASE
2862 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2865 #ifdef SAMBA_VERSION_VENDOR_PATCH
2866 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2868 extended_info
->samba_gitcommitdate
= 0;
2869 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2870 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2873 memset(extended_info
->samba_version_string
, 0,
2874 sizeof(extended_info
->samba_version_string
));
2876 snprintf (extended_info
->samba_version_string
,
2877 sizeof(extended_info
->samba_version_string
),
2878 "%s", samba_version_string());
2881 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2882 TALLOC_CTX
*mem_ctx
,
2883 uint16_t info_level
,
2885 unsigned int max_data_bytes
,
2889 char *pdata
, *end_data
;
2890 int data_len
= 0, len
;
2891 const char *vname
= volume_label(SNUM(conn
));
2892 int snum
= SNUM(conn
);
2893 char *fstype
= lp_fstype(SNUM(conn
));
2894 uint32 additional_flags
= 0;
2895 struct smb_filename smb_fname_dot
;
2899 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2900 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2901 "info level (0x%x) on IPC$.\n",
2902 (unsigned int)info_level
));
2903 return NT_STATUS_ACCESS_DENIED
;
2907 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2909 ZERO_STRUCT(smb_fname_dot
);
2910 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2912 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2913 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2914 return map_nt_error_from_unix(errno
);
2917 st
= smb_fname_dot
.st
;
2919 *ppdata
= (char *)SMB_REALLOC(
2920 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2921 if (*ppdata
== NULL
) {
2922 return NT_STATUS_NO_MEMORY
;
2926 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2927 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2929 switch (info_level
) {
2930 case SMB_INFO_ALLOCATION
:
2932 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2934 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2935 return map_nt_error_from_unix(errno
);
2938 block_size
= lp_block_size(snum
);
2939 if (bsize
< block_size
) {
2940 uint64_t factor
= block_size
/bsize
;
2945 if (bsize
> block_size
) {
2946 uint64_t factor
= bsize
/block_size
;
2951 bytes_per_sector
= 512;
2952 sectors_per_unit
= bsize
/bytes_per_sector
;
2954 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2955 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2956 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2958 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2959 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2960 SIVAL(pdata
,l1_cUnit
,dsize
);
2961 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2962 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2966 case SMB_INFO_VOLUME
:
2967 /* Return volume name */
2969 * Add volume serial number - hash of a combination of
2970 * the called hostname and the service name.
2972 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2974 * Win2k3 and previous mess this up by sending a name length
2975 * one byte short. I believe only older clients (OS/2 Win9x) use
2976 * this call so try fixing this by adding a terminating null to
2977 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2981 pdata
+l2_vol_szVolLabel
, vname
,
2982 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2983 STR_NOALIGN
|STR_TERMINATE
);
2984 SCVAL(pdata
,l2_vol_cch
,len
);
2985 data_len
= l2_vol_szVolLabel
+ len
;
2986 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2987 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2991 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2992 case SMB_FS_ATTRIBUTE_INFORMATION
:
2994 additional_flags
= 0;
2995 #if defined(HAVE_SYS_QUOTAS)
2996 additional_flags
|= FILE_VOLUME_QUOTAS
;
2999 if(lp_nt_acl_support(SNUM(conn
))) {
3000 additional_flags
|= FILE_PERSISTENT_ACLS
;
3003 /* Capabilities are filled in at connection time through STATVFS call */
3004 additional_flags
|= conn
->fs_capabilities
;
3005 additional_flags
|= lp_parm_int(conn
->params
->service
,
3006 "share", "fake_fscaps",
3009 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3010 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3011 additional_flags
); /* FS ATTRIBUTES */
3013 SIVAL(pdata
,4,255); /* Max filename component length */
3014 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3015 and will think we can't do long filenames */
3016 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3017 PTR_DIFF(end_data
, pdata
+12),
3020 data_len
= 12 + len
;
3023 case SMB_QUERY_FS_LABEL_INFO
:
3024 case SMB_FS_LABEL_INFORMATION
:
3025 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3026 PTR_DIFF(end_data
, pdata
+4), 0);
3031 case SMB_QUERY_FS_VOLUME_INFO
:
3032 case SMB_FS_VOLUME_INFORMATION
:
3035 * Add volume serial number - hash of a combination of
3036 * the called hostname and the service name.
3038 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3039 (str_checksum(get_local_machine_name())<<16));
3041 /* Max label len is 32 characters. */
3042 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3043 PTR_DIFF(end_data
, pdata
+18),
3045 SIVAL(pdata
,12,len
);
3048 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3049 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3052 case SMB_QUERY_FS_SIZE_INFO
:
3053 case SMB_FS_SIZE_INFORMATION
:
3055 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3057 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3058 return map_nt_error_from_unix(errno
);
3060 block_size
= lp_block_size(snum
);
3061 if (bsize
< block_size
) {
3062 uint64_t factor
= block_size
/bsize
;
3067 if (bsize
> block_size
) {
3068 uint64_t factor
= bsize
/block_size
;
3073 bytes_per_sector
= 512;
3074 sectors_per_unit
= bsize
/bytes_per_sector
;
3075 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3076 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3077 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3078 SBIG_UINT(pdata
,0,dsize
);
3079 SBIG_UINT(pdata
,8,dfree
);
3080 SIVAL(pdata
,16,sectors_per_unit
);
3081 SIVAL(pdata
,20,bytes_per_sector
);
3085 case SMB_FS_FULL_SIZE_INFORMATION
:
3087 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3089 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3090 return map_nt_error_from_unix(errno
);
3092 block_size
= lp_block_size(snum
);
3093 if (bsize
< block_size
) {
3094 uint64_t factor
= block_size
/bsize
;
3099 if (bsize
> block_size
) {
3100 uint64_t factor
= bsize
/block_size
;
3105 bytes_per_sector
= 512;
3106 sectors_per_unit
= bsize
/bytes_per_sector
;
3107 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3108 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3109 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3110 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3111 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3112 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3113 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3114 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3118 case SMB_QUERY_FS_DEVICE_INFO
:
3119 case SMB_FS_DEVICE_INFORMATION
:
3121 SIVAL(pdata
,0,0); /* dev type */
3122 SIVAL(pdata
,4,0); /* characteristics */
3125 #ifdef HAVE_SYS_QUOTAS
3126 case SMB_FS_QUOTA_INFORMATION
:
3128 * what we have to send --metze:
3130 * Unknown1: 24 NULL bytes
3131 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3132 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3133 * Quota Flags: 2 byte :
3134 * Unknown3: 6 NULL bytes
3138 * details for Quota Flags:
3140 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3141 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3142 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3143 * 0x0001 Enable Quotas: enable quota for this fs
3147 /* we need to fake up a fsp here,
3148 * because its not send in this call
3151 SMB_NTQUOTA_STRUCT quotas
;
3154 ZERO_STRUCT(quotas
);
3160 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
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())
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 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7049 create_disp
= FILE_CREATE
;
7050 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7051 create_disp
= FILE_OVERWRITE_IF
;
7052 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7053 create_disp
= FILE_OPEN_IF
;
7054 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7055 create_disp
= FILE_OPEN
;
7057 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7058 (unsigned int)wire_open_mode
));
7059 return NT_STATUS_INVALID_PARAMETER
;
7062 raw_unixmode
= IVAL(pdata
,8);
7063 /* Next 4 bytes are not yet defined. */
7065 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7066 (VALID_STAT(smb_fname
->st
) ?
7067 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7070 if (!NT_STATUS_IS_OK(status
)) {
7074 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7076 if (wire_open_mode
& SMB_O_SYNC
) {
7077 create_options
|= FILE_WRITE_THROUGH
;
7079 if (wire_open_mode
& SMB_O_APPEND
) {
7080 access_mask
|= FILE_APPEND_DATA
;
7082 if (wire_open_mode
& SMB_O_DIRECT
) {
7083 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7086 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7087 smb_fname_str_dbg(smb_fname
),
7088 (unsigned int)wire_open_mode
,
7089 (unsigned int)unixmode
));
7091 status
= SMB_VFS_CREATE_FILE(
7094 0, /* root_dir_fid */
7095 smb_fname
, /* fname */
7096 access_mask
, /* access_mask */
7097 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7099 create_disp
, /* create_disposition*/
7100 FILE_NON_DIRECTORY_FILE
, /* create_options */
7101 mod_unixmode
, /* file_attributes */
7102 oplock_request
, /* oplock_request */
7103 0, /* allocation_size */
7109 if (!NT_STATUS_IS_OK(status
)) {
7113 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7114 extended_oplock_granted
= True
;
7117 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7118 extended_oplock_granted
= True
;
7121 info_level_return
= SVAL(pdata
,16);
7123 /* Allocate the correct return size. */
7125 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7126 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7127 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7128 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7130 *pdata_return_size
= 12;
7133 /* Realloc the data size */
7134 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7135 if (*ppdata
== NULL
) {
7136 close_file(req
, fsp
, ERROR_CLOSE
);
7137 *pdata_return_size
= 0;
7138 return NT_STATUS_NO_MEMORY
;
7142 if (extended_oplock_granted
) {
7143 if (flags
& REQUEST_BATCH_OPLOCK
) {
7144 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7146 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7148 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7149 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7151 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7154 SSVAL(pdata
,2,fsp
->fnum
);
7155 SIVAL(pdata
,4,info
); /* Was file created etc. */
7157 switch (info_level_return
) {
7158 case SMB_QUERY_FILE_UNIX_BASIC
:
7159 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7160 SSVAL(pdata
,10,0); /* padding. */
7161 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7164 case SMB_QUERY_FILE_UNIX_INFO2
:
7165 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7166 SSVAL(pdata
,10,0); /* padding. */
7167 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7171 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7172 SSVAL(pdata
,10,0); /* padding. */
7175 return NT_STATUS_OK
;
7178 /****************************************************************************
7179 Delete a file with POSIX semantics.
7180 ****************************************************************************/
7182 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7183 struct smb_request
*req
,
7186 struct smb_filename
*smb_fname
)
7188 NTSTATUS status
= NT_STATUS_OK
;
7189 files_struct
*fsp
= NULL
;
7193 int create_options
= 0;
7195 struct share_mode_lock
*lck
= NULL
;
7197 if (total_data
< 2) {
7198 return NT_STATUS_INVALID_PARAMETER
;
7201 flags
= SVAL(pdata
,0);
7203 if (!VALID_STAT(smb_fname
->st
)) {
7204 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7207 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7208 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7209 return NT_STATUS_NOT_A_DIRECTORY
;
7212 DEBUG(10,("smb_posix_unlink: %s %s\n",
7213 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7214 smb_fname_str_dbg(smb_fname
)));
7216 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7217 create_options
|= FILE_DIRECTORY_FILE
;
7220 status
= SMB_VFS_CREATE_FILE(
7223 0, /* root_dir_fid */
7224 smb_fname
, /* fname */
7225 DELETE_ACCESS
, /* access_mask */
7226 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7228 FILE_OPEN
, /* create_disposition*/
7229 create_options
, /* create_options */
7230 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7231 0, /* oplock_request */
7232 0, /* allocation_size */
7238 if (!NT_STATUS_IS_OK(status
)) {
7243 * Don't lie to client. If we can't really delete due to
7244 * non-POSIX opens return SHARING_VIOLATION.
7247 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7250 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7251 "lock for file %s\n", fsp_str_dbg(fsp
)));
7252 close_file(req
, fsp
, NORMAL_CLOSE
);
7253 return NT_STATUS_INVALID_PARAMETER
;
7257 * See if others still have the file open. If this is the case, then
7258 * don't delete. If all opens are POSIX delete we can set the delete
7259 * on close disposition.
7261 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7262 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7263 if (is_valid_share_mode_entry(e
)) {
7264 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7267 /* Fail with sharing violation. */
7268 close_file(req
, fsp
, NORMAL_CLOSE
);
7270 return NT_STATUS_SHARING_VIOLATION
;
7275 * Set the delete on close.
7277 status
= smb_set_file_disposition_info(conn
,
7283 if (!NT_STATUS_IS_OK(status
)) {
7284 close_file(req
, fsp
, NORMAL_CLOSE
);
7289 return close_file(req
, fsp
, NORMAL_CLOSE
);
7292 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7293 struct smb_request
*req
,
7294 TALLOC_CTX
*mem_ctx
,
7295 uint16_t info_level
,
7297 struct smb_filename
*smb_fname
,
7298 char **ppdata
, int total_data
,
7301 char *pdata
= *ppdata
;
7302 NTSTATUS status
= NT_STATUS_OK
;
7303 int data_return_size
= 0;
7307 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7308 return NT_STATUS_INVALID_LEVEL
;
7311 if (!CAN_WRITE(conn
)) {
7312 /* Allow POSIX opens. The open path will deny
7313 * any non-readonly opens. */
7314 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7315 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7319 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7320 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7321 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7323 switch (info_level
) {
7325 case SMB_INFO_STANDARD
:
7327 status
= smb_set_info_standard(conn
,
7335 case SMB_INFO_SET_EA
:
7337 status
= smb_info_set_ea(conn
,
7345 case SMB_SET_FILE_BASIC_INFO
:
7346 case SMB_FILE_BASIC_INFORMATION
:
7348 status
= smb_set_file_basic_info(conn
,
7356 case SMB_FILE_ALLOCATION_INFORMATION
:
7357 case SMB_SET_FILE_ALLOCATION_INFO
:
7359 status
= smb_set_file_allocation_info(conn
, req
,
7367 case SMB_FILE_END_OF_FILE_INFORMATION
:
7368 case SMB_SET_FILE_END_OF_FILE_INFO
:
7371 * XP/Win7 both fail after the createfile with
7372 * SMB_SET_FILE_END_OF_FILE_INFO but not
7373 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7374 * The level is known here, so pass it down
7378 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7380 status
= smb_set_file_end_of_file_info(conn
, req
,
7389 case SMB_FILE_DISPOSITION_INFORMATION
:
7390 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7393 /* JRA - We used to just ignore this on a path ?
7394 * Shouldn't this be invalid level on a pathname
7397 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7398 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7401 status
= smb_set_file_disposition_info(conn
,
7409 case SMB_FILE_POSITION_INFORMATION
:
7411 status
= smb_file_position_information(conn
,
7418 case SMB_FILE_FULL_EA_INFORMATION
:
7420 status
= smb_set_file_full_ea_info(conn
,
7427 /* From tridge Samba4 :
7428 * MODE_INFORMATION in setfileinfo (I have no
7429 * idea what "mode information" on a file is - it takes a value of 0,
7430 * 2, 4 or 6. What could it be?).
7433 case SMB_FILE_MODE_INFORMATION
:
7435 status
= smb_file_mode_information(conn
,
7442 * CIFS UNIX extensions.
7445 case SMB_SET_FILE_UNIX_BASIC
:
7447 status
= smb_set_file_unix_basic(conn
, req
,
7455 case SMB_SET_FILE_UNIX_INFO2
:
7457 status
= smb_set_file_unix_info2(conn
, req
,
7465 case SMB_SET_FILE_UNIX_LINK
:
7468 /* We must have a pathname for this. */
7469 return NT_STATUS_INVALID_LEVEL
;
7471 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7472 total_data
, smb_fname
);
7476 case SMB_SET_FILE_UNIX_HLINK
:
7479 /* We must have a pathname for this. */
7480 return NT_STATUS_INVALID_LEVEL
;
7482 status
= smb_set_file_unix_hlink(conn
, req
,
7488 case SMB_FILE_RENAME_INFORMATION
:
7490 status
= smb_file_rename_information(conn
, req
,
7496 #if defined(HAVE_POSIX_ACLS)
7497 case SMB_SET_POSIX_ACL
:
7499 status
= smb_set_posix_acl(conn
,
7508 case SMB_SET_POSIX_LOCK
:
7511 return NT_STATUS_INVALID_LEVEL
;
7513 status
= smb_set_posix_lock(conn
, req
,
7514 pdata
, total_data
, fsp
);
7518 case SMB_POSIX_PATH_OPEN
:
7521 /* We must have a pathname for this. */
7522 return NT_STATUS_INVALID_LEVEL
;
7525 status
= smb_posix_open(conn
, req
,
7533 case SMB_POSIX_PATH_UNLINK
:
7536 /* We must have a pathname for this. */
7537 return NT_STATUS_INVALID_LEVEL
;
7540 status
= smb_posix_unlink(conn
, req
,
7548 return NT_STATUS_INVALID_LEVEL
;
7551 if (!NT_STATUS_IS_OK(status
)) {
7555 *ret_data_size
= data_return_size
;
7556 return NT_STATUS_OK
;
7559 /****************************************************************************
7560 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7561 ****************************************************************************/
7563 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7564 struct smb_request
*req
,
7565 unsigned int tran_call
,
7566 char **pparams
, int total_params
,
7567 char **ppdata
, int total_data
,
7568 unsigned int max_data_bytes
)
7570 char *params
= *pparams
;
7571 char *pdata
= *ppdata
;
7573 struct smb_filename
*smb_fname
= NULL
;
7574 files_struct
*fsp
= NULL
;
7575 NTSTATUS status
= NT_STATUS_OK
;
7576 int data_return_size
= 0;
7579 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7583 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7584 if (total_params
< 4) {
7585 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7589 fsp
= file_fsp(req
, SVAL(params
,0));
7590 /* Basic check for non-null fsp. */
7591 if (!check_fsp_open(conn
, req
, fsp
)) {
7594 info_level
= SVAL(params
,2);
7596 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7598 if (!NT_STATUS_IS_OK(status
)) {
7599 reply_nterror(req
, status
);
7603 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7605 * This is actually a SETFILEINFO on a directory
7606 * handle (returned from an NT SMB). NT5.0 seems
7607 * to do this call. JRA.
7609 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7610 /* Always do lstat for UNIX calls. */
7611 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7612 DEBUG(3,("call_trans2setfilepathinfo: "
7613 "SMB_VFS_LSTAT of %s failed "
7615 smb_fname_str_dbg(smb_fname
),
7617 reply_nterror(req
, map_nt_error_from_unix(errno
));
7621 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7622 DEBUG(3,("call_trans2setfilepathinfo: "
7623 "fileinfo of %s failed (%s)\n",
7624 smb_fname_str_dbg(smb_fname
),
7626 reply_nterror(req
, map_nt_error_from_unix(errno
));
7630 } else if (fsp
->print_file
) {
7632 * Doing a DELETE_ON_CLOSE should cancel a print job.
7634 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7635 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7637 DEBUG(3,("call_trans2setfilepathinfo: "
7638 "Cancelling print job (%s)\n",
7642 send_trans2_replies(conn
, req
, params
, 2,
7648 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7653 * Original code - this is an open file.
7655 if (!check_fsp(conn
, req
, fsp
)) {
7659 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7660 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7661 "of fnum %d failed (%s)\n", fsp
->fnum
,
7663 reply_nterror(req
, map_nt_error_from_unix(errno
));
7671 if (total_params
< 7) {
7672 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7676 info_level
= SVAL(params
,0);
7677 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7678 total_params
- 6, STR_TERMINATE
,
7680 if (!NT_STATUS_IS_OK(status
)) {
7681 reply_nterror(req
, status
);
7685 status
= filename_convert(req
, conn
,
7686 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7691 if (!NT_STATUS_IS_OK(status
)) {
7692 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7693 reply_botherror(req
,
7694 NT_STATUS_PATH_NOT_COVERED
,
7695 ERRSRV
, ERRbadpath
);
7698 reply_nterror(req
, status
);
7702 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7704 * For CIFS UNIX extensions the target name may not exist.
7707 /* Always do lstat for UNIX calls. */
7708 SMB_VFS_LSTAT(conn
, smb_fname
);
7710 } else if (!VALID_STAT(smb_fname
->st
) &&
7711 SMB_VFS_STAT(conn
, smb_fname
)) {
7712 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7714 smb_fname_str_dbg(smb_fname
),
7716 reply_nterror(req
, map_nt_error_from_unix(errno
));
7721 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7722 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7723 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7725 /* Realloc the parameter size */
7726 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7727 if (*pparams
== NULL
) {
7728 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7735 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7741 if (!NT_STATUS_IS_OK(status
)) {
7742 if (open_was_deferred(req
->mid
)) {
7743 /* We have re-scheduled this call. */
7746 if (blocking_lock_was_deferred(req
->mid
)) {
7747 /* We have re-scheduled this call. */
7750 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7751 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7752 ERRSRV
, ERRbadpath
);
7755 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7756 reply_openerror(req
, status
);
7760 reply_nterror(req
, status
);
7764 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7770 /****************************************************************************
7771 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7772 ****************************************************************************/
7774 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7775 char **pparams
, int total_params
,
7776 char **ppdata
, int total_data
,
7777 unsigned int max_data_bytes
)
7779 struct smb_filename
*smb_dname
= NULL
;
7780 char *params
= *pparams
;
7781 char *pdata
= *ppdata
;
7782 char *directory
= NULL
;
7783 NTSTATUS status
= NT_STATUS_OK
;
7784 struct ea_list
*ea_list
= NULL
;
7785 TALLOC_CTX
*ctx
= talloc_tos();
7787 if (!CAN_WRITE(conn
)) {
7788 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7792 if (total_params
< 5) {
7793 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7797 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7798 total_params
- 4, STR_TERMINATE
,
7800 if (!NT_STATUS_IS_OK(status
)) {
7801 reply_nterror(req
, status
);
7805 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7807 status
= filename_convert(ctx
,
7809 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7815 if (!NT_STATUS_IS_OK(status
)) {
7816 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7817 reply_botherror(req
,
7818 NT_STATUS_PATH_NOT_COVERED
,
7819 ERRSRV
, ERRbadpath
);
7822 reply_nterror(req
, status
);
7827 * OS/2 workplace shell seems to send SET_EA requests of "null"
7828 * length (4 bytes containing IVAL 4).
7829 * They seem to have no effect. Bug #3212. JRA.
7832 if (total_data
&& (total_data
!= 4)) {
7833 /* Any data in this call is an EA list. */
7834 if (total_data
< 10) {
7835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7839 if (IVAL(pdata
,0) > total_data
) {
7840 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7841 IVAL(pdata
,0), (unsigned int)total_data
));
7842 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7846 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7849 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7853 if (!lp_ea_support(SNUM(conn
))) {
7854 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7858 /* If total_data == 4 Windows doesn't care what values
7859 * are placed in that field, it just ignores them.
7860 * The System i QNTC IBM SMB client puts bad values here,
7861 * so ignore them. */
7863 status
= create_directory(conn
, req
, smb_dname
);
7865 if (!NT_STATUS_IS_OK(status
)) {
7866 reply_nterror(req
, status
);
7870 /* Try and set any given EA. */
7872 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7873 if (!NT_STATUS_IS_OK(status
)) {
7874 reply_nterror(req
, status
);
7879 /* Realloc the parameter and data sizes */
7880 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7881 if(*pparams
== NULL
) {
7882 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7889 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7892 TALLOC_FREE(smb_dname
);
7896 /****************************************************************************
7897 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7898 We don't actually do this - we just send a null response.
7899 ****************************************************************************/
7901 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7902 struct smb_request
*req
,
7903 char **pparams
, int total_params
,
7904 char **ppdata
, int total_data
,
7905 unsigned int max_data_bytes
)
7907 char *params
= *pparams
;
7910 if (total_params
< 6) {
7911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7915 info_level
= SVAL(params
,4);
7916 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7918 switch (info_level
) {
7923 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7927 /* Realloc the parameter and data sizes */
7928 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7929 if (*pparams
== NULL
) {
7930 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7935 SSVAL(params
,0,fnf_handle
);
7936 SSVAL(params
,2,0); /* No changes */
7937 SSVAL(params
,4,0); /* No EA errors */
7944 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7949 /****************************************************************************
7950 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7951 changes). Currently this does nothing.
7952 ****************************************************************************/
7954 static void call_trans2findnotifynext(connection_struct
*conn
,
7955 struct smb_request
*req
,
7956 char **pparams
, int total_params
,
7957 char **ppdata
, int total_data
,
7958 unsigned int max_data_bytes
)
7960 char *params
= *pparams
;
7962 DEBUG(3,("call_trans2findnotifynext\n"));
7964 /* Realloc the parameter and data sizes */
7965 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7966 if (*pparams
== NULL
) {
7967 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7972 SSVAL(params
,0,0); /* No changes */
7973 SSVAL(params
,2,0); /* No EA errors */
7975 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7980 /****************************************************************************
7981 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7982 ****************************************************************************/
7984 static void call_trans2getdfsreferral(connection_struct
*conn
,
7985 struct smb_request
*req
,
7986 char **pparams
, int total_params
,
7987 char **ppdata
, int total_data
,
7988 unsigned int max_data_bytes
)
7990 char *params
= *pparams
;
7991 char *pathname
= NULL
;
7993 int max_referral_level
;
7994 NTSTATUS status
= NT_STATUS_OK
;
7995 TALLOC_CTX
*ctx
= talloc_tos();
7997 DEBUG(10,("call_trans2getdfsreferral\n"));
7999 if (total_params
< 3) {
8000 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8004 max_referral_level
= SVAL(params
,0);
8006 if(!lp_host_msdfs()) {
8007 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8011 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8012 total_params
- 2, STR_TERMINATE
);
8014 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8017 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8018 ppdata
,&status
)) < 0) {
8019 reply_nterror(req
, status
);
8023 SSVAL(req
->inbuf
, smb_flg2
,
8024 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8025 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8030 #define LMCAT_SPL 0x53
8031 #define LMFUNC_GETJOBID 0x60
8033 /****************************************************************************
8034 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8035 ****************************************************************************/
8037 static void call_trans2ioctl(connection_struct
*conn
,
8038 struct smb_request
*req
,
8039 char **pparams
, int total_params
,
8040 char **ppdata
, int total_data
,
8041 unsigned int max_data_bytes
)
8043 char *pdata
= *ppdata
;
8044 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8046 /* check for an invalid fid before proceeding */
8049 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8053 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8054 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8055 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8056 if (*ppdata
== NULL
) {
8057 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8062 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8063 CAN ACCEPT THIS IN UNICODE. JRA. */
8065 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8066 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8067 global_myname(), 15,
8068 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8069 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8070 lp_servicename(SNUM(conn
)), 13,
8071 STR_ASCII
|STR_TERMINATE
); /* Service name */
8072 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8077 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8078 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8081 /****************************************************************************
8082 Reply to a SMBfindclose (stop trans2 directory search).
8083 ****************************************************************************/
8085 void reply_findclose(struct smb_request
*req
)
8088 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8090 START_PROFILE(SMBfindclose
);
8093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8094 END_PROFILE(SMBfindclose
);
8098 dptr_num
= SVALS(req
->vwv
+0, 0);
8100 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8102 dptr_close(sconn
, &dptr_num
);
8104 reply_outbuf(req
, 0, 0);
8106 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8108 END_PROFILE(SMBfindclose
);
8112 /****************************************************************************
8113 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8114 ****************************************************************************/
8116 void reply_findnclose(struct smb_request
*req
)
8120 START_PROFILE(SMBfindnclose
);
8123 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8124 END_PROFILE(SMBfindnclose
);
8128 dptr_num
= SVAL(req
->vwv
+0, 0);
8130 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8132 /* We never give out valid handles for a
8133 findnotifyfirst - so any dptr_num is ok here.
8136 reply_outbuf(req
, 0, 0);
8138 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8140 END_PROFILE(SMBfindnclose
);
8144 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8145 struct trans_state
*state
)
8147 if (get_Protocol() >= PROTOCOL_NT1
) {
8148 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8149 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8152 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8153 if (state
->call
!= TRANSACT2_QFSINFO
&&
8154 state
->call
!= TRANSACT2_SETFSINFO
) {
8155 DEBUG(0,("handle_trans2: encryption required "
8157 (unsigned int)state
->call
));
8158 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8163 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8165 /* Now we must call the relevant TRANS2 function */
8166 switch(state
->call
) {
8167 case TRANSACT2_OPEN
:
8169 START_PROFILE(Trans2_open
);
8170 call_trans2open(conn
, req
,
8171 &state
->param
, state
->total_param
,
8172 &state
->data
, state
->total_data
,
8173 state
->max_data_return
);
8174 END_PROFILE(Trans2_open
);
8178 case TRANSACT2_FINDFIRST
:
8180 START_PROFILE(Trans2_findfirst
);
8181 call_trans2findfirst(conn
, req
,
8182 &state
->param
, state
->total_param
,
8183 &state
->data
, state
->total_data
,
8184 state
->max_data_return
);
8185 END_PROFILE(Trans2_findfirst
);
8189 case TRANSACT2_FINDNEXT
:
8191 START_PROFILE(Trans2_findnext
);
8192 call_trans2findnext(conn
, req
,
8193 &state
->param
, state
->total_param
,
8194 &state
->data
, state
->total_data
,
8195 state
->max_data_return
);
8196 END_PROFILE(Trans2_findnext
);
8200 case TRANSACT2_QFSINFO
:
8202 START_PROFILE(Trans2_qfsinfo
);
8203 call_trans2qfsinfo(conn
, req
,
8204 &state
->param
, state
->total_param
,
8205 &state
->data
, state
->total_data
,
8206 state
->max_data_return
);
8207 END_PROFILE(Trans2_qfsinfo
);
8211 case TRANSACT2_SETFSINFO
:
8213 START_PROFILE(Trans2_setfsinfo
);
8214 call_trans2setfsinfo(conn
, req
,
8215 &state
->param
, state
->total_param
,
8216 &state
->data
, state
->total_data
,
8217 state
->max_data_return
);
8218 END_PROFILE(Trans2_setfsinfo
);
8222 case TRANSACT2_QPATHINFO
:
8223 case TRANSACT2_QFILEINFO
:
8225 START_PROFILE(Trans2_qpathinfo
);
8226 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8227 &state
->param
, state
->total_param
,
8228 &state
->data
, state
->total_data
,
8229 state
->max_data_return
);
8230 END_PROFILE(Trans2_qpathinfo
);
8234 case TRANSACT2_SETPATHINFO
:
8235 case TRANSACT2_SETFILEINFO
:
8237 START_PROFILE(Trans2_setpathinfo
);
8238 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8239 &state
->param
, state
->total_param
,
8240 &state
->data
, state
->total_data
,
8241 state
->max_data_return
);
8242 END_PROFILE(Trans2_setpathinfo
);
8246 case TRANSACT2_FINDNOTIFYFIRST
:
8248 START_PROFILE(Trans2_findnotifyfirst
);
8249 call_trans2findnotifyfirst(conn
, req
,
8250 &state
->param
, state
->total_param
,
8251 &state
->data
, state
->total_data
,
8252 state
->max_data_return
);
8253 END_PROFILE(Trans2_findnotifyfirst
);
8257 case TRANSACT2_FINDNOTIFYNEXT
:
8259 START_PROFILE(Trans2_findnotifynext
);
8260 call_trans2findnotifynext(conn
, req
,
8261 &state
->param
, state
->total_param
,
8262 &state
->data
, state
->total_data
,
8263 state
->max_data_return
);
8264 END_PROFILE(Trans2_findnotifynext
);
8268 case TRANSACT2_MKDIR
:
8270 START_PROFILE(Trans2_mkdir
);
8271 call_trans2mkdir(conn
, req
,
8272 &state
->param
, state
->total_param
,
8273 &state
->data
, state
->total_data
,
8274 state
->max_data_return
);
8275 END_PROFILE(Trans2_mkdir
);
8279 case TRANSACT2_GET_DFS_REFERRAL
:
8281 START_PROFILE(Trans2_get_dfs_referral
);
8282 call_trans2getdfsreferral(conn
, req
,
8283 &state
->param
, state
->total_param
,
8284 &state
->data
, state
->total_data
,
8285 state
->max_data_return
);
8286 END_PROFILE(Trans2_get_dfs_referral
);
8290 case TRANSACT2_IOCTL
:
8292 START_PROFILE(Trans2_ioctl
);
8293 call_trans2ioctl(conn
, req
,
8294 &state
->param
, state
->total_param
,
8295 &state
->data
, state
->total_data
,
8296 state
->max_data_return
);
8297 END_PROFILE(Trans2_ioctl
);
8302 /* Error in request */
8303 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8304 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8308 /****************************************************************************
8309 Reply to a SMBtrans2.
8310 ****************************************************************************/
8312 void reply_trans2(struct smb_request
*req
)
8314 connection_struct
*conn
= req
->conn
;
8319 unsigned int tran_call
;
8320 struct trans_state
*state
;
8323 START_PROFILE(SMBtrans2
);
8325 if (req
->wct
< 14) {
8326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8327 END_PROFILE(SMBtrans2
);
8331 dsoff
= SVAL(req
->vwv
+12, 0);
8332 dscnt
= SVAL(req
->vwv
+11, 0);
8333 psoff
= SVAL(req
->vwv
+10, 0);
8334 pscnt
= SVAL(req
->vwv
+9, 0);
8335 tran_call
= SVAL(req
->vwv
+14, 0);
8337 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8338 if (!NT_STATUS_IS_OK(result
)) {
8339 DEBUG(2, ("Got invalid trans2 request: %s\n",
8340 nt_errstr(result
)));
8341 reply_nterror(req
, result
);
8342 END_PROFILE(SMBtrans2
);
8347 switch (tran_call
) {
8348 /* List the allowed trans2 calls on IPC$ */
8349 case TRANSACT2_OPEN
:
8350 case TRANSACT2_GET_DFS_REFERRAL
:
8351 case TRANSACT2_QFILEINFO
:
8352 case TRANSACT2_QFSINFO
:
8353 case TRANSACT2_SETFSINFO
:
8356 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8357 END_PROFILE(SMBtrans2
);
8362 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8363 DEBUG(0, ("talloc failed\n"));
8364 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8365 END_PROFILE(SMBtrans2
);
8369 state
->cmd
= SMBtrans2
;
8371 state
->mid
= req
->mid
;
8372 state
->vuid
= req
->vuid
;
8373 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8374 state
->setup
= NULL
;
8375 state
->total_param
= SVAL(req
->vwv
+0, 0);
8376 state
->param
= NULL
;
8377 state
->total_data
= SVAL(req
->vwv
+1, 0);
8379 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8380 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8381 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8382 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8383 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8385 state
->call
= tran_call
;
8387 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8388 is so as a sanity check */
8389 if (state
->setup_count
!= 1) {
8391 * Need to have rc=0 for ioctl to get job id for OS/2.
8392 * Network printing will fail if function is not successful.
8393 * Similar function in reply.c will be used if protocol
8394 * is LANMAN1.0 instead of LM1.2X002.
8395 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8396 * outbuf doesn't have to be set(only job id is used).
8398 if ( (state
->setup_count
== 4)
8399 && (tran_call
== TRANSACT2_IOCTL
)
8400 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8401 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8402 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8404 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8405 DEBUG(2,("Transaction is %d\n",tran_call
));
8407 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8408 END_PROFILE(SMBtrans2
);
8413 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8416 if (state
->total_data
) {
8418 if (trans_oob(state
->total_data
, 0, dscnt
)
8419 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8423 /* Can't use talloc here, the core routines do realloc on the
8424 * params and data. */
8425 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8426 if (state
->data
== NULL
) {
8427 DEBUG(0,("reply_trans2: data malloc fail for %u "
8428 "bytes !\n", (unsigned int)state
->total_data
));
8430 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8431 END_PROFILE(SMBtrans2
);
8435 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8438 if (state
->total_param
) {
8440 if (trans_oob(state
->total_param
, 0, pscnt
)
8441 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8445 /* Can't use talloc here, the core routines do realloc on the
8446 * params and data. */
8447 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8448 if (state
->param
== NULL
) {
8449 DEBUG(0,("reply_trans: param malloc fail for %u "
8450 "bytes !\n", (unsigned int)state
->total_param
));
8451 SAFE_FREE(state
->data
);
8453 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8454 END_PROFILE(SMBtrans2
);
8458 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8461 state
->received_data
= dscnt
;
8462 state
->received_param
= pscnt
;
8464 if ((state
->received_param
== state
->total_param
) &&
8465 (state
->received_data
== state
->total_data
)) {
8467 handle_trans2(conn
, req
, state
);
8469 SAFE_FREE(state
->data
);
8470 SAFE_FREE(state
->param
);
8472 END_PROFILE(SMBtrans2
);
8476 DLIST_ADD(conn
->pending_trans
, state
);
8478 /* We need to send an interim response then receive the rest
8479 of the parameter/data bytes */
8480 reply_outbuf(req
, 0, 0);
8481 show_msg((char *)req
->outbuf
);
8482 END_PROFILE(SMBtrans2
);
8487 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8488 SAFE_FREE(state
->data
);
8489 SAFE_FREE(state
->param
);
8491 END_PROFILE(SMBtrans2
);
8492 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8496 /****************************************************************************
8497 Reply to a SMBtranss2
8498 ****************************************************************************/
8500 void reply_transs2(struct smb_request
*req
)
8502 connection_struct
*conn
= req
->conn
;
8503 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8504 struct trans_state
*state
;
8506 START_PROFILE(SMBtranss2
);
8508 show_msg((char *)req
->inbuf
);
8511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8512 END_PROFILE(SMBtranss2
);
8516 for (state
= conn
->pending_trans
; state
!= NULL
;
8517 state
= state
->next
) {
8518 if (state
->mid
== req
->mid
) {
8523 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8524 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8525 END_PROFILE(SMBtranss2
);
8529 /* Revise state->total_param and state->total_data in case they have
8530 changed downwards */
8532 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8533 state
->total_param
= SVAL(req
->vwv
+0, 0);
8534 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8535 state
->total_data
= SVAL(req
->vwv
+1, 0);
8537 pcnt
= SVAL(req
->vwv
+2, 0);
8538 poff
= SVAL(req
->vwv
+3, 0);
8539 pdisp
= SVAL(req
->vwv
+4, 0);
8541 dcnt
= SVAL(req
->vwv
+5, 0);
8542 doff
= SVAL(req
->vwv
+6, 0);
8543 ddisp
= SVAL(req
->vwv
+7, 0);
8545 state
->received_param
+= pcnt
;
8546 state
->received_data
+= dcnt
;
8548 if ((state
->received_data
> state
->total_data
) ||
8549 (state
->received_param
> state
->total_param
))
8553 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8554 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8557 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8561 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8562 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8565 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8568 if ((state
->received_param
< state
->total_param
) ||
8569 (state
->received_data
< state
->total_data
)) {
8570 END_PROFILE(SMBtranss2
);
8574 handle_trans2(conn
, req
, state
);
8576 DLIST_REMOVE(conn
->pending_trans
, state
);
8577 SAFE_FREE(state
->data
);
8578 SAFE_FREE(state
->param
);
8581 END_PROFILE(SMBtranss2
);
8586 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8587 DLIST_REMOVE(conn
->pending_trans
, state
);
8588 SAFE_FREE(state
->data
);
8589 SAFE_FREE(state
->param
);
8591 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8592 END_PROFILE(SMBtranss2
);