2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct
*conn
,
36 const SMB_STRUCT_STAT
*psbuf
);
38 static char *store_file_unix_basic_info2(connection_struct
*conn
,
41 const SMB_STRUCT_STAT
*psbuf
);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
50 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type
= get_remote_arch();
54 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
55 val
= SMB_ROUNDUP(val
,rval
);
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
69 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
70 return (uint64_t)psbuf
->st_ex_ino
;
72 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
73 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name
)
87 static const char * const prohibited_ea_names
[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME
,
89 SAMBA_XATTR_DOS_ATTRIB
,
97 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
98 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
101 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
113 files_struct
*fsp
, const char *fname
,
114 const char *ea_name
, struct ea_struct
*pea
)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size
= 256;
123 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
125 return NT_STATUS_NO_MEMORY
;
128 if (fsp
&& fsp
->fh
->fd
!= -1) {
129 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
131 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
134 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
140 return map_nt_error_from_unix(errno
);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
144 dump_data(10, (uint8
*)val
, sizeret
);
147 if (strnequal(ea_name
, "user.", 5)) {
148 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
150 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
152 if (pea
->name
== NULL
) {
154 return NT_STATUS_NO_MEMORY
;
156 pea
->value
.data
= (unsigned char *)val
;
157 pea
->value
.length
= (size_t)sizeret
;
161 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
162 files_struct
*fsp
, const char *fname
,
163 char ***pnames
, size_t *pnum_names
)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size
= 1024;
167 char *ea_namelist
= NULL
;
172 ssize_t sizeret
= -1;
174 if (!lp_ea_support(SNUM(conn
))) {
183 * TALLOC the result early to get the talloc hierarchy right.
186 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY
;
192 while (ea_namelist_size
<= 65536) {
194 ea_namelist
= TALLOC_REALLOC_ARRAY(
195 names
, ea_namelist
, char, ea_namelist_size
);
196 if (ea_namelist
== NULL
) {
197 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY
;
202 if (fsp
&& fsp
->fh
->fd
!= -1) {
203 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
206 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
210 if ((sizeret
== -1) && (errno
== ERANGE
)) {
211 ea_namelist_size
*= 2;
220 return map_nt_error_from_unix(errno
);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret
));
236 * Ensure the result is 0-terminated
239 if (ea_namelist
[sizeret
-1] != '\0') {
241 return NT_STATUS_INTERNAL_ERROR
;
249 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
253 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
255 DEBUG(0, ("talloc failed\n"));
257 return NT_STATUS_NO_MEMORY
;
263 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
264 names
[num_names
++] = p
;
272 *pnum_names
= num_names
;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
281 const char *fname
, size_t *pea_total_len
)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list
*ea_list_head
= NULL
;
291 if (!lp_ea_support(SNUM(conn
))) {
295 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
298 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
302 for (i
=0; i
<num_names
; i
++) {
303 struct ea_list
*listp
;
306 if (strnequal(names
[i
], "system.", 7)
307 || samba_private_attr_name(names
[i
]))
310 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
321 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
324 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
328 (unsigned int)listp
->ea
.value
.length
));
330 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
334 /* Add on 4 for total length. */
335 if (*pea_total_len
) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len
));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
351 connection_struct
*conn
, struct ea_list
*ea_list
)
353 unsigned int ret_data_size
= 4;
356 SMB_ASSERT(total_data_size
>= 4);
358 if (!lp_ea_support(SNUM(conn
))) {
363 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
366 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
367 dos_namelen
= strlen(dos_ea_name
);
368 if (dos_namelen
> 255 || dos_namelen
== 0) {
371 if (ea_list
->ea
.value
.length
> 65535) {
374 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
378 /* We know we have room. */
379 SCVAL(p
,0,ea_list
->ea
.flags
);
380 SCVAL(p
,1,dos_namelen
);
381 SSVAL(p
,2,ea_list
->ea
.value
.length
);
382 fstrcpy(p
+4, dos_ea_name
);
383 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
385 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
386 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
389 ret_data_size
= PTR_DIFF(p
, pdata
);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
391 SIVAL(pdata
,0,ret_data_size
);
392 return ret_data_size
;
395 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
397 unsigned int total_data_size
,
398 unsigned int *ret_data_size
,
399 connection_struct
*conn
,
400 struct ea_list
*ea_list
)
402 uint8_t *p
= (uint8_t *)pdata
;
403 uint8_t *last_start
= NULL
;
407 if (!lp_ea_support(SNUM(conn
))) {
408 return NT_STATUS_NO_EAS_ON_FILE
;
411 for (; ea_list
; ea_list
= ea_list
->next
) {
417 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
421 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
422 dos_namelen
= strlen(dos_ea_name
);
423 if (dos_namelen
> 255 || dos_namelen
== 0) {
424 return NT_STATUS_INTERNAL_ERROR
;
426 if (ea_list
->ea
.value
.length
> 65535) {
427 return NT_STATUS_INTERNAL_ERROR
;
430 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
433 size_t pad
= 4 - (this_size
% 4);
437 if (this_size
> total_data_size
) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH
;
441 /* We know we have room. */
442 SIVAL(p
, 0x00, 0); /* next offset */
443 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
444 SCVAL(p
, 0x05, dos_namelen
);
445 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
446 fstrcpy((char *)(p
+0x08), dos_ea_name
);
447 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
449 total_data_size
-= this_size
;
453 *ret_data_size
= PTR_DIFF(p
, pdata
);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
458 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
460 size_t total_ea_len
= 0;
461 TALLOC_CTX
*mem_ctx
= NULL
;
463 if (!lp_ea_support(SNUM(conn
))) {
466 mem_ctx
= talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
478 TALLOC_CTX
*mem_ctx
= talloc_tos();
479 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
481 for (; ea_list
; ea_list
= ea_list
->next
) {
482 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name
[5], ea_list
->ea
.name
));
485 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
496 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
500 if (!lp_ea_support(SNUM(conn
))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED
;
504 /* For now setting EAs on streams isn't supported. */
505 fname
= smb_fname
->base_name
;
507 for (;ea_list
; ea_list
= ea_list
->next
) {
509 fstring unix_ea_name
;
511 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
514 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
518 if (samba_private_attr_name(unix_ea_name
)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
520 return NT_STATUS_ACCESS_DENIED
;
523 if (ea_list
->ea
.value
.length
== 0) {
524 /* Remove the attribute. */
525 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name
, fsp_str_dbg(fsp
)));
529 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name
, fname
));
533 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
536 /* Removing a non existent attribute always succeeds. */
537 if (ret
== -1 && errno
== ENOATTR
) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
544 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name
, fsp_str_dbg(fsp
)));
548 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
549 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name
, fname
));
553 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
554 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
560 if (errno
== ENOTSUP
) {
561 return NT_STATUS_EAS_NOT_SUPPORTED
;
564 return map_nt_error_from_unix(errno
);
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
576 struct ea_list
*ea_list_head
= NULL
;
577 size_t converted_size
, offset
= 0;
579 while (offset
+ 2 < data_size
) {
580 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
581 unsigned int namelen
= CVAL(pdata
,offset
);
583 offset
++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
587 (offset
> data_size
) || (namelen
> data_size
) ||
588 (offset
+ namelen
>= data_size
)) {
591 /* Ensure the name is null terminated. */
592 if (pdata
[offset
+ namelen
] != '\0') {
595 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno
)));
604 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
618 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
620 unsigned int namelen
;
621 size_t converted_size
;
631 eal
->ea
.flags
= CVAL(pdata
,0);
632 namelen
= CVAL(pdata
,1);
633 val_len
= SVAL(pdata
,2);
635 if (4 + namelen
+ 1 + val_len
> data_size
) {
639 /* Ensure the name is null terminated. */
640 if (pdata
[namelen
+ 4] != '\0') {
643 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
651 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
652 if (!eal
->ea
.value
.data
) {
656 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal
->ea
.value
.data
[val_len
] = '\0';
660 /* But don't count the null. */
661 eal
->ea
.value
.length
--;
664 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
668 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
679 struct ea_list
*ea_list_head
= NULL
;
681 size_t bytes_used
= 0;
683 while (offset
< data_size
) {
684 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
690 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
691 offset
+= bytes_used
;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list
*ealist
)
704 struct ea_list
*listp
;
707 for (listp
= ealist
; listp
; listp
= listp
->next
) {
708 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
709 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
711 /* Add on 4 for total length. */
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
727 struct ea_list
*nlistp
, *flistp
;
729 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
730 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
731 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
737 /* Copy the data from this entry. */
738 nlistp
->ea
.flags
= flistp
->ea
.flags
;
739 nlistp
->ea
.value
= flistp
->ea
.value
;
742 nlistp
->ea
.flags
= 0;
743 ZERO_STRUCT(nlistp
->ea
.value
);
747 *total_ea_len
= ea_list_size(name_list
);
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct
*conn
,
759 struct smb_request
*req
,
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send
= datasize
;
773 int params_to_send
= paramsize
;
775 const char *pp
= params
;
776 const char *pd
= pdata
;
777 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
778 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset
= 0;
780 bool overflow
= False
;
781 struct smbd_server_connection
*sconn
= smbd_server_conn
;
782 int max_send
= sconn
->smb1
.sessions
.max_send
;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
789 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes
, datasize
));
792 datasize
= data_to_send
= max_data_bytes
;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send
== 0 && data_to_send
== 0) {
799 reply_outbuf(req
, 10, 0);
800 show_msg((char *)req
->outbuf
);
801 if (!srv_send_smb(smbd_server_fd(),
804 IS_CONN_ENCRYPTED(conn
),
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req
->outbuf
);
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
817 data_alignment_offset
= 4 - (params_to_send
% 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space
= max_send
- (smb_size
826 + data_alignment_offset
);
828 if (useable_space
< 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space
));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send
|| data_to_send
) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime
= params_to_send
+ data_to_send
;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
849 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
850 + data_alignment_offset
);
853 * We might have SMBtrans2s in req which was transferred to
854 * the outbuf, fix that.
856 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
858 /* Set total params and data to be sent */
859 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
860 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
862 /* Calculate how many parameters and data we can fit into
863 * this packet. Parameters get precedence
866 params_sent_thistime
= MIN(params_to_send
,useable_space
);
867 data_sent_thistime
= useable_space
- params_sent_thistime
;
868 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
870 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
872 /* smb_proff is the offset from the start of the SMB header to the
873 parameter bytes, however the first 4 bytes of outbuf are
874 the Netbios over TCP header. Thus use smb_base() to subtract
875 them from the calculation */
877 SSVAL(req
->outbuf
,smb_proff
,
878 ((smb_buf(req
->outbuf
)+alignment_offset
)
879 - smb_base(req
->outbuf
)));
881 if(params_sent_thistime
== 0)
882 SSVAL(req
->outbuf
,smb_prdisp
,0);
884 /* Absolute displacement of param bytes sent in this packet */
885 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
887 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
888 if(data_sent_thistime
== 0) {
889 SSVAL(req
->outbuf
,smb_droff
,0);
890 SSVAL(req
->outbuf
,smb_drdisp
, 0);
892 /* The offset of the data bytes is the offset of the
893 parameter bytes plus the number of parameters being sent this time */
894 SSVAL(req
->outbuf
, smb_droff
,
895 ((smb_buf(req
->outbuf
)+alignment_offset
)
896 - smb_base(req
->outbuf
))
897 + params_sent_thistime
+ data_alignment_offset
);
898 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
901 /* Initialize the padding for alignment */
903 if (alignment_offset
!= 0) {
904 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
907 /* Copy the param bytes into the packet */
909 if(params_sent_thistime
) {
910 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
911 params_sent_thistime
);
914 /* Copy in the data bytes */
915 if(data_sent_thistime
) {
916 if (data_alignment_offset
!= 0) {
917 memset((smb_buf(req
->outbuf
)+alignment_offset
+
918 params_sent_thistime
), 0,
919 data_alignment_offset
);
921 memcpy(smb_buf(req
->outbuf
)+alignment_offset
922 +params_sent_thistime
+data_alignment_offset
,
923 pd
,data_sent_thistime
);
926 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
927 params_sent_thistime
, data_sent_thistime
, useable_space
));
928 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
929 params_to_send
, data_to_send
, paramsize
, datasize
));
932 error_packet_set((char *)req
->outbuf
,
933 ERRDOS
,ERRbufferoverflow
,
934 STATUS_BUFFER_OVERFLOW
,
938 /* Send the packet */
939 show_msg((char *)req
->outbuf
);
940 if (!srv_send_smb(smbd_server_fd(),
943 IS_CONN_ENCRYPTED(conn
),
945 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
947 TALLOC_FREE(req
->outbuf
);
949 pp
+= params_sent_thistime
;
950 pd
+= data_sent_thistime
;
952 params_to_send
-= params_sent_thistime
;
953 data_to_send
-= data_sent_thistime
;
956 if(params_to_send
< 0 || data_to_send
< 0) {
957 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
958 params_to_send
, data_to_send
));
966 /****************************************************************************
967 Reply to a TRANSACT2_OPEN.
968 ****************************************************************************/
970 static void call_trans2open(connection_struct
*conn
,
971 struct smb_request
*req
,
972 char **pparams
, int total_params
,
973 char **ppdata
, int total_data
,
974 unsigned int max_data_bytes
)
976 struct smb_filename
*smb_fname
= NULL
;
977 char *params
= *pparams
;
978 char *pdata
= *ppdata
;
983 bool return_additional_info
;
996 struct ea_list
*ea_list
= NULL
;
1001 uint32 create_disposition
;
1002 uint32 create_options
= 0;
1003 TALLOC_CTX
*ctx
= talloc_tos();
1006 * Ensure we have enough parameters to perform the operation.
1009 if (total_params
< 29) {
1010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1014 flags
= SVAL(params
, 0);
1015 deny_mode
= SVAL(params
, 2);
1016 open_attr
= SVAL(params
,6);
1017 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1018 if (oplock_request
) {
1019 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1023 return_additional_info
= BITSETW(params
,0);
1024 open_sattr
= SVAL(params
, 4);
1025 open_time
= make_unix_date3(params
+8);
1027 open_ofun
= SVAL(params
,12);
1028 open_size
= IVAL(params
,14);
1029 pname
= ¶ms
[28];
1032 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1036 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1037 total_params
- 28, STR_TERMINATE
,
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 reply_nterror(req
, status
);
1044 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1045 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1046 (unsigned int)open_ofun
, open_size
));
1048 status
= filename_convert(ctx
,
1050 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1055 if (!NT_STATUS_IS_OK(status
)) {
1056 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1057 reply_botherror(req
,
1058 NT_STATUS_PATH_NOT_COVERED
,
1059 ERRSRV
, ERRbadpath
);
1062 reply_nterror(req
, status
);
1066 if (open_ofun
== 0) {
1067 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1071 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1072 &access_mask
, &share_mode
,
1073 &create_disposition
,
1075 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1079 /* Any data in this call is an EA list. */
1080 if (total_data
&& (total_data
!= 4)) {
1081 if (total_data
< 10) {
1082 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1086 if (IVAL(pdata
,0) > total_data
) {
1087 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1088 IVAL(pdata
,0), (unsigned int)total_data
));
1089 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1093 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1096 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1100 if (!lp_ea_support(SNUM(conn
))) {
1101 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1106 status
= SMB_VFS_CREATE_FILE(
1109 0, /* root_dir_fid */
1110 smb_fname
, /* fname */
1111 access_mask
, /* access_mask */
1112 share_mode
, /* share_access */
1113 create_disposition
, /* create_disposition*/
1114 create_options
, /* create_options */
1115 open_attr
, /* file_attributes */
1116 oplock_request
, /* oplock_request */
1117 open_size
, /* allocation_size */
1119 ea_list
, /* ea_list */
1121 &smb_action
); /* psbuf */
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 if (open_was_deferred(req
->mid
)) {
1125 /* We have re-scheduled this call. */
1128 reply_openerror(req
, status
);
1132 size
= get_file_size_stat(&smb_fname
->st
);
1133 fattr
= dos_mode(conn
, smb_fname
);
1134 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1135 inode
= smb_fname
->st
.st_ex_ino
;
1137 close_file(req
, fsp
, ERROR_CLOSE
);
1138 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1142 /* Realloc the size of parameters and data we will return */
1143 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1144 if(*pparams
== NULL
) {
1145 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1150 SSVAL(params
,0,fsp
->fnum
);
1151 SSVAL(params
,2,fattr
);
1152 srv_put_dos_date2(params
,4, mtime
);
1153 SIVAL(params
,8, (uint32
)size
);
1154 SSVAL(params
,12,deny_mode
);
1155 SSVAL(params
,14,0); /* open_type - file or directory. */
1156 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1158 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1159 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1162 SSVAL(params
,18,smb_action
);
1165 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1167 SIVAL(params
,20,inode
);
1168 SSVAL(params
,24,0); /* Padding. */
1170 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1171 fsp
->fsp_name
->base_name
);
1172 SIVAL(params
, 26, ea_size
);
1174 SIVAL(params
, 26, 0);
1177 /* Send the required number of replies */
1178 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1180 TALLOC_FREE(smb_fname
);
1183 /*********************************************************
1184 Routine to check if a given string matches exactly.
1185 as a special case a mask of "." does NOT match. That
1186 is required for correct wildcard semantics
1187 Case can be significant or not.
1188 **********************************************************/
1190 static bool exact_match(bool has_wild
,
1191 bool case_sensitive
,
1195 if (mask
[0] == '.' && mask
[1] == 0) {
1203 if (case_sensitive
) {
1204 return strcmp(str
,mask
)==0;
1206 return StrCaseCmp(str
,mask
) == 0;
1210 /****************************************************************************
1211 Return the filetype for UNIX extensions.
1212 ****************************************************************************/
1214 static uint32
unix_filetype(mode_t mode
)
1217 return UNIX_TYPE_FILE
;
1218 else if(S_ISDIR(mode
))
1219 return UNIX_TYPE_DIR
;
1221 else if(S_ISLNK(mode
))
1222 return UNIX_TYPE_SYMLINK
;
1225 else if(S_ISCHR(mode
))
1226 return UNIX_TYPE_CHARDEV
;
1229 else if(S_ISBLK(mode
))
1230 return UNIX_TYPE_BLKDEV
;
1233 else if(S_ISFIFO(mode
))
1234 return UNIX_TYPE_FIFO
;
1237 else if(S_ISSOCK(mode
))
1238 return UNIX_TYPE_SOCKET
;
1241 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1242 return UNIX_TYPE_UNKNOWN
;
1245 /****************************************************************************
1246 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1247 ****************************************************************************/
1249 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1251 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1252 const SMB_STRUCT_STAT
*psbuf
,
1254 enum perm_type ptype
,
1259 if (perms
== SMB_MODE_NO_CHANGE
) {
1260 if (!VALID_STAT(*psbuf
)) {
1261 return NT_STATUS_INVALID_PARAMETER
;
1263 *ret_perms
= psbuf
->st_ex_mode
;
1264 return NT_STATUS_OK
;
1268 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1269 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1270 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1271 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1272 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1273 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1274 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1275 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1276 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1278 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1281 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1284 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1289 /* Apply mode mask */
1290 ret
&= lp_create_mask(SNUM(conn
));
1291 /* Add in force bits */
1292 ret
|= lp_force_create_mode(SNUM(conn
));
1295 ret
&= lp_dir_mask(SNUM(conn
));
1296 /* Add in force bits */
1297 ret
|= lp_force_dir_mode(SNUM(conn
));
1299 case PERM_EXISTING_FILE
:
1300 /* Apply mode mask */
1301 ret
&= lp_security_mask(SNUM(conn
));
1302 /* Add in force bits */
1303 ret
|= lp_force_security_mode(SNUM(conn
));
1305 case PERM_EXISTING_DIR
:
1306 /* Apply mode mask */
1307 ret
&= lp_dir_security_mask(SNUM(conn
));
1308 /* Add in force bits */
1309 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1314 return NT_STATUS_OK
;
1317 /****************************************************************************
1318 Needed to show the msdfs symlinks as directories. Modifies psbuf
1319 to be a directory if it's a msdfs link.
1320 ****************************************************************************/
1322 static bool check_msdfs_link(connection_struct
*conn
,
1323 const char *pathname
,
1324 SMB_STRUCT_STAT
*psbuf
)
1326 int saved_errno
= errno
;
1327 if(lp_host_msdfs() &&
1328 lp_msdfs_root(SNUM(conn
)) &&
1329 is_msdfs_link(conn
, pathname
, psbuf
)) {
1331 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1334 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1335 errno
= saved_errno
;
1338 errno
= saved_errno
;
1343 /****************************************************************************
1344 Get a level dependent lanman2 dir entry.
1345 ****************************************************************************/
1347 struct smbd_dirptr_lanman2_state
{
1348 connection_struct
*conn
;
1349 uint32_t info_level
;
1350 bool check_mangled_names
;
1352 bool got_exact_match
;
1355 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1361 struct smbd_dirptr_lanman2_state
*state
=
1362 (struct smbd_dirptr_lanman2_state
*)private_data
;
1364 char mangled_name
[13]; /* mangled 8.3 name. */
1368 /* Mangle fname if it's an illegal name. */
1369 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1370 ok
= name_to_8_3(dname
, mangled_name
,
1371 true, state
->conn
->params
);
1375 fname
= mangled_name
;
1380 got_match
= exact_match(state
->has_wild
,
1381 state
->conn
->case_sensitive
,
1383 state
->got_exact_match
= got_match
;
1385 got_match
= mask_match(fname
, mask
,
1386 state
->conn
->case_sensitive
);
1389 if(!got_match
&& state
->check_mangled_names
&&
1390 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1392 * It turns out that NT matches wildcards against
1393 * both long *and* short names. This may explain some
1394 * of the wildcard wierdness from old DOS clients
1395 * that some people have been seeing.... JRA.
1397 /* Force the mangling into 8.3. */
1398 ok
= name_to_8_3(fname
, mangled_name
,
1399 false, state
->conn
->params
);
1404 got_match
= exact_match(state
->has_wild
,
1405 state
->conn
->case_sensitive
,
1406 mangled_name
, mask
);
1407 state
->got_exact_match
= got_match
;
1409 got_match
= mask_match(mangled_name
, mask
,
1410 state
->conn
->case_sensitive
);
1418 *_fname
= talloc_strdup(ctx
, fname
);
1419 if (*_fname
== NULL
) {
1426 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1428 struct smb_filename
*smb_fname
,
1431 struct smbd_dirptr_lanman2_state
*state
=
1432 (struct smbd_dirptr_lanman2_state
*)private_data
;
1433 bool ms_dfs_link
= false;
1436 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1437 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't lstat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname
),
1444 } else if (!VALID_STAT(smb_fname
->st
) &&
1445 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1446 /* Needed to show the msdfs symlinks as
1449 ms_dfs_link
= check_msdfs_link(state
->conn
,
1450 smb_fname
->base_name
,
1453 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1454 "Couldn't stat [%s] (%s)\n",
1455 smb_fname_str_dbg(smb_fname
),
1462 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1464 mode
= dos_mode(state
->conn
, smb_fname
);
1471 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1472 connection_struct
*conn
,
1474 uint32_t info_level
,
1475 struct ea_list
*name_list
,
1476 bool check_mangled_names
,
1477 bool requires_resume_key
,
1480 const struct smb_filename
*smb_fname
,
1481 uint64_t space_remaining
,
1488 uint64_t *last_entry_off
)
1490 char *p
, *q
, *pdata
= *ppdata
;
1492 uint64_t file_size
= 0;
1493 uint64_t allocation_size
= 0;
1494 uint64_t file_index
= 0;
1496 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1497 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1498 time_t c_date
= (time_t)0;
1500 char *last_entry_ptr
;
1505 *out_of_space
= false;
1507 ZERO_STRUCT(mdate_ts
);
1508 ZERO_STRUCT(adate_ts
);
1509 ZERO_STRUCT(create_date_ts
);
1510 ZERO_STRUCT(cdate_ts
);
1512 if (!(mode
& aDIR
)) {
1513 file_size
= get_file_size_stat(&smb_fname
->st
);
1515 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1517 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1519 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1520 adate_ts
= smb_fname
->st
.st_ex_atime
;
1521 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1522 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1524 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1525 dos_filetime_timespec(&create_date_ts
);
1526 dos_filetime_timespec(&mdate_ts
);
1527 dos_filetime_timespec(&adate_ts
);
1528 dos_filetime_timespec(&cdate_ts
);
1531 create_date
= convert_timespec_to_time_t(create_date_ts
);
1532 mdate
= convert_timespec_to_time_t(mdate_ts
);
1533 adate
= convert_timespec_to_time_t(adate_ts
);
1534 c_date
= convert_timespec_to_time_t(cdate_ts
);
1536 /* align the record */
1537 off
= PTR_DIFF(pdata
, base_data
);
1538 pad
= (off
+ (align
-1)) & ~(align
-1);
1541 /* initialize padding to 0 */
1543 memset(pdata
, 0, pad
);
1545 space_remaining
-= pad
;
1554 switch (info_level
) {
1555 case SMB_FIND_INFO_STANDARD
:
1556 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1557 if(requires_resume_key
) {
1561 srv_put_dos_date2(p
,0,create_date
);
1562 srv_put_dos_date2(p
,4,adate
);
1563 srv_put_dos_date2(p
,8,mdate
);
1564 SIVAL(p
,12,(uint32
)file_size
);
1565 SIVAL(p
,16,(uint32
)allocation_size
);
1569 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1570 p
+= ucs2_align(base_data
, p
, 0);
1572 len
= srvstr_push(base_data
, flags2
, p
,
1573 fname
, PTR_DIFF(end_data
, p
),
1575 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1577 SCVAL(nameptr
, -1, len
- 2);
1579 SCVAL(nameptr
, -1, 0);
1583 SCVAL(nameptr
, -1, len
- 1);
1585 SCVAL(nameptr
, -1, 0);
1591 case SMB_FIND_EA_SIZE
:
1592 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1593 if (requires_resume_key
) {
1597 srv_put_dos_date2(p
,0,create_date
);
1598 srv_put_dos_date2(p
,4,adate
);
1599 srv_put_dos_date2(p
,8,mdate
);
1600 SIVAL(p
,12,(uint32
)file_size
);
1601 SIVAL(p
,16,(uint32
)allocation_size
);
1604 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1605 smb_fname
->base_name
);
1606 SIVAL(p
,22,ea_size
); /* Extended attributes */
1610 len
= srvstr_push(base_data
, flags2
,
1611 p
, fname
, PTR_DIFF(end_data
, p
),
1612 STR_TERMINATE
| STR_NOALIGN
);
1613 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1626 SCVAL(nameptr
,0,len
);
1628 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1631 case SMB_FIND_EA_LIST
:
1633 struct ea_list
*file_list
= NULL
;
1636 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1640 if (requires_resume_key
) {
1644 srv_put_dos_date2(p
,0,create_date
);
1645 srv_put_dos_date2(p
,4,adate
);
1646 srv_put_dos_date2(p
,8,mdate
);
1647 SIVAL(p
,12,(uint32
)file_size
);
1648 SIVAL(p
,16,(uint32
)allocation_size
);
1650 p
+= 22; /* p now points to the EA area. */
1652 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1653 smb_fname
->base_name
,
1655 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1657 /* We need to determine if this entry will fit in the space available. */
1658 /* Max string size is 255 bytes. */
1659 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1660 *out_of_space
= true;
1661 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1662 return False
; /* Not finished - just out of space */
1665 /* Push the ea_data followed by the name. */
1666 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1668 len
= srvstr_push(base_data
, flags2
,
1669 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1670 STR_TERMINATE
| STR_NOALIGN
);
1671 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1684 SCVAL(nameptr
,0,len
);
1686 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1690 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1692 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1694 SIVAL(p
,0,reskey
); p
+= 4;
1695 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1696 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1697 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1698 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1699 SOFF_T(p
,0,file_size
); p
+= 8;
1700 SOFF_T(p
,0,allocation_size
); p
+= 8;
1701 SIVAL(p
,0,mode
); p
+= 4;
1702 q
= p
; p
+= 4; /* q is placeholder for name length. */
1704 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1705 smb_fname
->base_name
);
1706 SIVAL(p
,0,ea_size
); /* Extended attributes */
1709 /* Clear the short name buffer. This is
1710 * IMPORTANT as not doing so will trigger
1711 * a Win2k client bug. JRA.
1713 if (!was_8_3
&& check_mangled_names
) {
1714 char mangled_name
[13]; /* mangled 8.3 name. */
1715 if (!name_to_8_3(fname
,mangled_name
,True
,
1717 /* Error - mangle failed ! */
1718 memset(mangled_name
,'\0',12);
1720 mangled_name
[12] = 0;
1721 len
= srvstr_push(base_data
, flags2
,
1722 p
+2, mangled_name
, 24,
1723 STR_UPPER
|STR_UNICODE
);
1725 memset(p
+ 2 + len
,'\0',24 - len
);
1732 len
= srvstr_push(base_data
, flags2
, p
,
1733 fname
, PTR_DIFF(end_data
, p
),
1734 STR_TERMINATE_ASCII
);
1738 len
= PTR_DIFF(p
, pdata
);
1739 pad
= (len
+ (align
-1)) & ~(align
-1);
1741 * offset to the next entry, the caller
1742 * will overwrite it for the last entry
1743 * that's why we always include the padding
1747 * set padding to zero
1750 memset(p
, 0, pad
- len
);
1757 case SMB_FIND_FILE_DIRECTORY_INFO
:
1758 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1760 SIVAL(p
,0,reskey
); p
+= 4;
1761 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1762 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1763 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1764 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1765 SOFF_T(p
,0,file_size
); p
+= 8;
1766 SOFF_T(p
,0,allocation_size
); p
+= 8;
1767 SIVAL(p
,0,mode
); p
+= 4;
1768 len
= srvstr_push(base_data
, flags2
,
1769 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1770 STR_TERMINATE_ASCII
);
1774 len
= PTR_DIFF(p
, pdata
);
1775 pad
= (len
+ (align
-1)) & ~(align
-1);
1777 * offset to the next entry, the caller
1778 * will overwrite it for the last entry
1779 * that's why we always include the padding
1783 * set padding to zero
1786 memset(p
, 0, pad
- len
);
1793 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1794 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1796 SIVAL(p
,0,reskey
); p
+= 4;
1797 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1798 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1799 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1800 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1801 SOFF_T(p
,0,file_size
); p
+= 8;
1802 SOFF_T(p
,0,allocation_size
); p
+= 8;
1803 SIVAL(p
,0,mode
); p
+= 4;
1804 q
= p
; p
+= 4; /* q is placeholder for name length. */
1806 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1807 smb_fname
->base_name
);
1808 SIVAL(p
,0,ea_size
); /* Extended attributes */
1811 len
= srvstr_push(base_data
, flags2
, p
,
1812 fname
, PTR_DIFF(end_data
, p
),
1813 STR_TERMINATE_ASCII
);
1817 len
= PTR_DIFF(p
, pdata
);
1818 pad
= (len
+ (align
-1)) & ~(align
-1);
1820 * offset to the next entry, the caller
1821 * will overwrite it for the last entry
1822 * that's why we always include the padding
1826 * set padding to zero
1829 memset(p
, 0, pad
- len
);
1836 case SMB_FIND_FILE_NAMES_INFO
:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1839 SIVAL(p
,0,reskey
); p
+= 4;
1841 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1842 acl on a dir (tridge) */
1843 len
= srvstr_push(base_data
, flags2
, p
,
1844 fname
, PTR_DIFF(end_data
, p
),
1845 STR_TERMINATE_ASCII
);
1849 len
= PTR_DIFF(p
, pdata
);
1850 pad
= (len
+ (align
-1)) & ~(align
-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1858 * set padding to zero
1861 memset(p
, 0, pad
- len
);
1868 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1871 SIVAL(p
,0,reskey
); p
+= 4;
1872 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1873 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1874 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1876 SOFF_T(p
,0,file_size
); p
+= 8;
1877 SOFF_T(p
,0,allocation_size
); p
+= 8;
1878 SIVAL(p
,0,mode
); p
+= 4;
1879 q
= p
; p
+= 4; /* q is placeholder for name length. */
1881 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1882 smb_fname
->base_name
);
1883 SIVAL(p
,0,ea_size
); /* Extended attributes */
1886 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1887 SBVAL(p
,0,file_index
); p
+= 8;
1888 len
= srvstr_push(base_data
, flags2
, p
,
1889 fname
, PTR_DIFF(end_data
, p
),
1890 STR_TERMINATE_ASCII
);
1894 len
= PTR_DIFF(p
, pdata
);
1895 pad
= (len
+ (align
-1)) & ~(align
-1);
1897 * offset to the next entry, the caller
1898 * will overwrite it for the last entry
1899 * that's why we always include the padding
1903 * set padding to zero
1906 memset(p
, 0, pad
- len
);
1913 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1914 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1915 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1917 SIVAL(p
,0,reskey
); p
+= 4;
1918 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1919 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1920 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1921 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1922 SOFF_T(p
,0,file_size
); p
+= 8;
1923 SOFF_T(p
,0,allocation_size
); p
+= 8;
1924 SIVAL(p
,0,mode
); p
+= 4;
1925 q
= p
; p
+= 4; /* q is placeholder for name length */
1927 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1928 smb_fname
->base_name
);
1929 SIVAL(p
,0,ea_size
); /* Extended attributes */
1932 /* Clear the short name buffer. This is
1933 * IMPORTANT as not doing so will trigger
1934 * a Win2k client bug. JRA.
1936 if (!was_8_3
&& check_mangled_names
) {
1937 char mangled_name
[13]; /* mangled 8.3 name. */
1938 if (!name_to_8_3(fname
,mangled_name
,True
,
1940 /* Error - mangle failed ! */
1941 memset(mangled_name
,'\0',12);
1943 mangled_name
[12] = 0;
1944 len
= srvstr_push(base_data
, flags2
,
1945 p
+2, mangled_name
, 24,
1946 STR_UPPER
|STR_UNICODE
);
1949 memset(p
+ 2 + len
,'\0',24 - len
);
1956 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1957 SBVAL(p
,0,file_index
); p
+= 8;
1958 len
= srvstr_push(base_data
, flags2
, p
,
1959 fname
, PTR_DIFF(end_data
, p
),
1960 STR_TERMINATE_ASCII
);
1964 len
= PTR_DIFF(p
, pdata
);
1965 pad
= (len
+ (align
-1)) & ~(align
-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1973 * set padding to zero
1976 memset(p
, 0, pad
- len
);
1983 /* CIFS UNIX Extension. */
1985 case SMB_FIND_FILE_UNIX
:
1986 case SMB_FIND_FILE_UNIX_INFO2
:
1988 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1990 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1992 if (info_level
== SMB_FIND_FILE_UNIX
) {
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1994 p
= store_file_unix_basic(conn
, p
,
1995 NULL
, &smb_fname
->st
);
1996 len
= srvstr_push(base_data
, flags2
, p
,
1997 fname
, PTR_DIFF(end_data
, p
),
2000 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2001 p
= store_file_unix_basic_info2(conn
, p
,
2002 NULL
, &smb_fname
->st
);
2005 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2006 PTR_DIFF(end_data
, p
), 0);
2007 SIVAL(nameptr
, 0, len
);
2012 len
= PTR_DIFF(p
, pdata
);
2013 pad
= (len
+ (align
-1)) & ~(align
-1);
2015 * offset to the next entry, the caller
2016 * will overwrite it for the last entry
2017 * that's why we always include the padding
2021 * set padding to zero
2024 memset(p
, 0, pad
- len
);
2029 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2037 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2038 *out_of_space
= true;
2039 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2040 return false; /* Not finished - just out of space */
2043 /* Setup the last entry pointer, as an offset from base_data */
2044 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2045 /* Advance the data pointer to the next slot */
2051 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2052 connection_struct
*conn
,
2053 struct dptr_struct
*dirptr
,
2055 const char *path_mask
,
2058 int requires_resume_key
,
2066 int space_remaining
,
2068 bool *got_exact_match
,
2069 int *_last_entry_off
,
2070 struct ea_list
*name_list
)
2073 const char *mask
= NULL
;
2074 long prev_dirpos
= 0;
2077 struct smb_filename
*smb_fname
= NULL
;
2078 struct smbd_dirptr_lanman2_state state
;
2080 uint64_t last_entry_off
= 0;
2084 state
.info_level
= info_level
;
2085 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2086 state
.has_wild
= dptr_has_wild(dirptr
);
2087 state
.got_exact_match
= false;
2089 *out_of_space
= false;
2090 *got_exact_match
= false;
2092 p
= strrchr_m(path_mask
,'/');
2103 ok
= smbd_dirptr_get_entry(ctx
,
2109 smbd_dirptr_lanman2_match_fn
,
2110 smbd_dirptr_lanman2_mode_fn
,
2120 *got_exact_match
= state
.got_exact_match
;
2122 ok
= smbd_marshall_dir_entry(ctx
,
2127 state
.check_mangled_names
,
2128 requires_resume_key
,
2141 TALLOC_FREE(smb_fname
);
2142 if (*out_of_space
) {
2143 dptr_SeekDir(dirptr
, prev_dirpos
);
2150 *_last_entry_off
= last_entry_off
;
2154 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2155 connection_struct
*conn
,
2156 struct dptr_struct
*dirptr
,
2158 const char *path_mask
,
2161 bool requires_resume_key
,
2167 int space_remaining
,
2169 bool *got_exact_match
,
2170 int *last_entry_off
,
2171 struct ea_list
*name_list
)
2174 const bool do_pad
= true;
2176 if (info_level
>= 1 && info_level
<= 3) {
2177 /* No alignment on earlier info levels. */
2181 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2182 path_mask
, dirtype
, info_level
,
2183 requires_resume_key
, dont_descend
, ask_sharemode
,
2185 ppdata
, base_data
, end_data
,
2187 out_of_space
, got_exact_match
,
2188 last_entry_off
, name_list
);
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDFIRST.
2193 ****************************************************************************/
2195 static void call_trans2findfirst(connection_struct
*conn
,
2196 struct smb_request
*req
,
2197 char **pparams
, int total_params
,
2198 char **ppdata
, int total_data
,
2199 unsigned int max_data_bytes
)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2206 struct smb_filename
*smb_dname
= NULL
;
2207 char *params
= *pparams
;
2208 char *pdata
= *ppdata
;
2212 uint16 findfirst_flags
;
2213 bool close_after_first
;
2215 bool requires_resume_key
;
2217 char *directory
= NULL
;
2220 int last_entry_off
=0;
2224 bool finished
= False
;
2225 bool dont_descend
= False
;
2226 bool out_of_space
= False
;
2227 int space_remaining
;
2228 bool mask_contains_wcard
= False
;
2229 struct ea_list
*ea_list
= NULL
;
2230 NTSTATUS ntstatus
= NT_STATUS_OK
;
2231 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2232 TALLOC_CTX
*ctx
= talloc_tos();
2233 struct dptr_struct
*dirptr
= NULL
;
2234 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2236 if (total_params
< 13) {
2237 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2241 dirtype
= SVAL(params
,0);
2242 maxentries
= SVAL(params
,2);
2243 findfirst_flags
= SVAL(params
,4);
2244 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2245 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2246 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2247 info_level
= SVAL(params
,6);
2249 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2250 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2251 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2252 info_level
, max_data_bytes
));
2255 /* W2K3 seems to treat zero as 1. */
2259 switch (info_level
) {
2260 case SMB_FIND_INFO_STANDARD
:
2261 case SMB_FIND_EA_SIZE
:
2262 case SMB_FIND_EA_LIST
:
2263 case SMB_FIND_FILE_DIRECTORY_INFO
:
2264 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2265 case SMB_FIND_FILE_NAMES_INFO
:
2266 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2267 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2268 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2270 case SMB_FIND_FILE_UNIX
:
2271 case SMB_FIND_FILE_UNIX_INFO2
:
2272 /* Always use filesystem for UNIX mtime query. */
2273 ask_sharemode
= false;
2274 if (!lp_unix_extensions()) {
2275 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2280 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2284 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2285 params
+12, total_params
- 12,
2286 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2287 if (!NT_STATUS_IS_OK(ntstatus
)) {
2288 reply_nterror(req
, ntstatus
);
2292 ntstatus
= filename_convert(ctx
, conn
,
2293 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2296 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2297 &mask_contains_wcard
,
2299 if (!NT_STATUS_IS_OK(ntstatus
)) {
2300 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2301 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2302 ERRSRV
, ERRbadpath
);
2305 reply_nterror(req
, ntstatus
);
2309 mask
= smb_dname
->original_lcomp
;
2311 directory
= smb_dname
->base_name
;
2313 p
= strrchr_m(directory
,'/');
2315 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2316 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2317 mask
= talloc_strdup(ctx
,"*");
2319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2322 mask_contains_wcard
= True
;
2324 directory
= talloc_strdup(talloc_tos(), "./");
2326 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2333 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2335 if (info_level
== SMB_FIND_EA_LIST
) {
2338 if (total_data
< 4) {
2339 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2343 ea_size
= IVAL(pdata
,0);
2344 if (ea_size
!= total_data
) {
2345 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2346 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2347 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2351 if (!lp_ea_support(SNUM(conn
))) {
2352 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2356 /* Pull out the list of names. */
2357 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2359 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2364 *ppdata
= (char *)SMB_REALLOC(
2365 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2366 if(*ppdata
== NULL
) {
2367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2371 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2373 /* Realloc the params space */
2374 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2375 if (*pparams
== NULL
) {
2376 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2381 /* Save the wildcard match and attribs we are using on this directory -
2382 needed as lanman2 assumes these are being saved between calls */
2384 ntstatus
= dptr_create(conn
,
2390 mask_contains_wcard
,
2394 if (!NT_STATUS_IS_OK(ntstatus
)) {
2395 reply_nterror(req
, ntstatus
);
2399 dptr_num
= dptr_dnum(dirptr
);
2400 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2402 /* Initialize per TRANS2_FIND_FIRST operation data */
2403 dptr_init_search_op(dirptr
);
2405 /* We don't need to check for VOL here as this is returned by
2406 a different TRANS2 call. */
2408 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2409 directory
,lp_dontdescend(SNUM(conn
))));
2410 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2411 dont_descend
= True
;
2414 space_remaining
= max_data_bytes
;
2415 out_of_space
= False
;
2417 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2418 bool got_exact_match
= False
;
2420 /* this is a heuristic to avoid seeking the dirptr except when
2421 absolutely necessary. It allows for a filename of about 40 chars */
2422 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2423 out_of_space
= True
;
2426 finished
= !get_lanman2_dir_entry(ctx
,
2430 mask
,dirtype
,info_level
,
2431 requires_resume_key
,dont_descend
,
2434 space_remaining
, &out_of_space
,
2436 &last_entry_off
, ea_list
);
2439 if (finished
&& out_of_space
)
2442 if (!finished
&& !out_of_space
)
2446 * As an optimisation if we know we aren't looking
2447 * for a wildcard name (ie. the name matches the wildcard exactly)
2448 * then we can finish on any (first) match.
2449 * This speeds up large directory searches. JRA.
2455 /* Ensure space_remaining never goes -ve. */
2456 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2457 space_remaining
= 0;
2458 out_of_space
= true;
2460 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2464 /* Check if we can close the dirptr */
2465 if(close_after_first
|| (finished
&& close_if_end
)) {
2466 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2467 dptr_close(sconn
, &dptr_num
);
2471 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2472 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2473 * the protocol level is less than NT1. Tested with smbclient. JRA.
2474 * This should fix the OS/2 client bug #2335.
2477 if(numentries
== 0) {
2478 dptr_close(sconn
, &dptr_num
);
2479 if (get_Protocol() < PROTOCOL_NT1
) {
2480 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2483 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2484 ERRDOS
, ERRbadfile
);
2489 /* At this point pdata points to numentries directory entries. */
2491 /* Set up the return parameter block */
2492 SSVAL(params
,0,dptr_num
);
2493 SSVAL(params
,2,numentries
);
2494 SSVAL(params
,4,finished
);
2495 SSVAL(params
,6,0); /* Never an EA error */
2496 SSVAL(params
,8,last_entry_off
);
2498 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2501 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2502 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2504 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2509 smb_fn_name(req
->cmd
),
2510 mask
, directory
, dirtype
, numentries
) );
2513 * Force a name mangle here to ensure that the
2514 * mask as an 8.3 name is top of the mangled cache.
2515 * The reasons for this are subtle. Don't remove
2516 * this code unless you know what you are doing
2517 * (see PR#13758). JRA.
2520 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2521 char mangled_name
[13];
2522 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2525 TALLOC_FREE(smb_dname
);
2529 /****************************************************************************
2530 Reply to a TRANS2_FINDNEXT.
2531 ****************************************************************************/
2533 static void call_trans2findnext(connection_struct
*conn
,
2534 struct smb_request
*req
,
2535 char **pparams
, int total_params
,
2536 char **ppdata
, int total_data
,
2537 unsigned int max_data_bytes
)
2539 /* We must be careful here that we don't return more than the
2540 allowed number of data bytes. If this means returning fewer than
2541 maxentries then so be it. We assume that the redirector has
2542 enough room for the fixed number of parameter bytes it has
2544 char *params
= *pparams
;
2545 char *pdata
= *ppdata
;
2551 uint16 findnext_flags
;
2552 bool close_after_request
;
2554 bool requires_resume_key
;
2556 bool mask_contains_wcard
= False
;
2557 char *resume_name
= NULL
;
2558 const char *mask
= NULL
;
2559 const char *directory
= NULL
;
2563 int i
, last_entry_off
=0;
2564 bool finished
= False
;
2565 bool dont_descend
= False
;
2566 bool out_of_space
= False
;
2567 int space_remaining
;
2568 struct ea_list
*ea_list
= NULL
;
2569 NTSTATUS ntstatus
= NT_STATUS_OK
;
2570 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2571 TALLOC_CTX
*ctx
= talloc_tos();
2572 struct dptr_struct
*dirptr
;
2573 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2575 if (total_params
< 13) {
2576 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2580 dptr_num
= SVAL(params
,0);
2581 maxentries
= SVAL(params
,2);
2582 info_level
= SVAL(params
,4);
2583 resume_key
= IVAL(params
,6);
2584 findnext_flags
= SVAL(params
,10);
2585 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2586 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2587 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2588 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2590 if (!continue_bit
) {
2591 /* We only need resume_name if continue_bit is zero. */
2592 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2594 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2595 &mask_contains_wcard
);
2596 if (!NT_STATUS_IS_OK(ntstatus
)) {
2597 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2598 complain (it thinks we're asking for the directory above the shared
2599 path or an invalid name). Catch this as the resume name is only compared, never used in
2600 a file access. JRA. */
2601 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2602 &resume_name
, params
+12,
2606 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2607 reply_nterror(req
, ntstatus
);
2613 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2614 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2615 resume_key = %d resume name = %s continue=%d level = %d\n",
2616 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2617 requires_resume_key
, resume_key
,
2618 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2621 /* W2K3 seems to treat zero as 1. */
2625 switch (info_level
) {
2626 case SMB_FIND_INFO_STANDARD
:
2627 case SMB_FIND_EA_SIZE
:
2628 case SMB_FIND_EA_LIST
:
2629 case SMB_FIND_FILE_DIRECTORY_INFO
:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2631 case SMB_FIND_FILE_NAMES_INFO
:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2636 case SMB_FIND_FILE_UNIX
:
2637 case SMB_FIND_FILE_UNIX_INFO2
:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode
= false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2646 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2650 if (info_level
== SMB_FIND_EA_LIST
) {
2653 if (total_data
< 4) {
2654 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2658 ea_size
= IVAL(pdata
,0);
2659 if (ea_size
!= total_data
) {
2660 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2661 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2662 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2666 if (!lp_ea_support(SNUM(conn
))) {
2667 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2671 /* Pull out the list of names. */
2672 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2674 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2679 *ppdata
= (char *)SMB_REALLOC(
2680 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2681 if(*ppdata
== NULL
) {
2682 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2687 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2689 /* Realloc the params space */
2690 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2691 if(*pparams
== NULL
) {
2692 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2698 /* Check that the dptr is valid */
2699 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2700 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2704 directory
= dptr_path(sconn
, dptr_num
);
2706 /* Get the wildcard mask from the dptr */
2707 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2708 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2709 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2715 /* Get the attr mask from the dptr */
2716 dirtype
= dptr_attr(sconn
, dptr_num
);
2718 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2719 dptr_num
, mask
, dirtype
,
2721 dptr_TellDir(dirptr
)));
2723 /* Initialize per TRANS2_FIND_NEXT operation data */
2724 dptr_init_search_op(dirptr
);
2726 /* We don't need to check for VOL here as this is returned by
2727 a different TRANS2 call. */
2729 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2730 directory
,lp_dontdescend(SNUM(conn
))));
2731 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2732 dont_descend
= True
;
2735 space_remaining
= max_data_bytes
;
2736 out_of_space
= False
;
2739 * Seek to the correct position. We no longer use the resume key but
2740 * depend on the last file name instead.
2743 if(!continue_bit
&& resume_name
&& *resume_name
) {
2746 long current_pos
= 0;
2748 * Remember, name_to_8_3 is called by
2749 * get_lanman2_dir_entry(), so the resume name
2750 * could be mangled. Ensure we check the unmangled name.
2753 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2754 char *new_resume_name
= NULL
;
2755 mangle_lookup_name_from_8_3(ctx
,
2759 if (new_resume_name
) {
2760 resume_name
= new_resume_name
;
2765 * Fix for NT redirector problem triggered by resume key indexes
2766 * changing between directory scans. We now return a resume key of 0
2767 * and instead look for the filename to continue from (also given
2768 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2769 * findfirst/findnext (as is usual) then the directory pointer
2770 * should already be at the correct place.
2773 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2774 } /* end if resume_name && !continue_bit */
2776 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2777 bool got_exact_match
= False
;
2779 /* this is a heuristic to avoid seeking the dirptr except when
2780 absolutely necessary. It allows for a filename of about 40 chars */
2781 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2782 out_of_space
= True
;
2785 finished
= !get_lanman2_dir_entry(ctx
,
2789 mask
,dirtype
,info_level
,
2790 requires_resume_key
,dont_descend
,
2793 space_remaining
, &out_of_space
,
2795 &last_entry_off
, ea_list
);
2798 if (finished
&& out_of_space
)
2801 if (!finished
&& !out_of_space
)
2805 * As an optimisation if we know we aren't looking
2806 * for a wildcard name (ie. the name matches the wildcard exactly)
2807 * then we can finish on any (first) match.
2808 * This speeds up large directory searches. JRA.
2814 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2817 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2818 smb_fn_name(req
->cmd
),
2819 mask
, directory
, dirtype
, numentries
) );
2821 /* Check if we can close the dirptr */
2822 if(close_after_request
|| (finished
&& close_if_end
)) {
2823 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2824 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2827 /* Set up the return parameter block */
2828 SSVAL(params
,0,numentries
);
2829 SSVAL(params
,2,finished
);
2830 SSVAL(params
,4,0); /* Never an EA error */
2831 SSVAL(params
,6,last_entry_off
);
2833 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2839 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2841 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2845 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2847 SMB_ASSERT(extended_info
!= NULL
);
2849 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2850 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2851 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2852 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2853 #ifdef SAMBA_VERSION_REVISION
2854 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2856 extended_info
->samba_subversion
= 0;
2857 #ifdef SAMBA_VERSION_RC_RELEASE
2858 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2860 #ifdef SAMBA_VERSION_PRE_RELEASE
2861 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2864 #ifdef SAMBA_VERSION_VENDOR_PATCH
2865 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2867 extended_info
->samba_gitcommitdate
= 0;
2868 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2869 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2872 memset(extended_info
->samba_version_string
, 0,
2873 sizeof(extended_info
->samba_version_string
));
2875 snprintf (extended_info
->samba_version_string
,
2876 sizeof(extended_info
->samba_version_string
),
2877 "%s", samba_version_string());
2880 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2881 TALLOC_CTX
*mem_ctx
,
2882 uint16_t info_level
,
2884 unsigned int max_data_bytes
,
2888 char *pdata
, *end_data
;
2889 int data_len
= 0, len
;
2890 const char *vname
= volume_label(SNUM(conn
));
2891 int snum
= SNUM(conn
);
2892 char *fstype
= lp_fstype(SNUM(conn
));
2893 uint32 additional_flags
= 0;
2894 struct smb_filename smb_fname_dot
;
2898 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2899 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2900 "info level (0x%x) on IPC$.\n",
2901 (unsigned int)info_level
));
2902 return NT_STATUS_ACCESS_DENIED
;
2906 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2908 ZERO_STRUCT(smb_fname_dot
);
2909 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2911 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2912 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2913 return map_nt_error_from_unix(errno
);
2916 st
= smb_fname_dot
.st
;
2918 *ppdata
= (char *)SMB_REALLOC(
2919 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2920 if (*ppdata
== NULL
) {
2921 return NT_STATUS_NO_MEMORY
;
2925 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2926 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2928 switch (info_level
) {
2929 case SMB_INFO_ALLOCATION
:
2931 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2933 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2934 return map_nt_error_from_unix(errno
);
2937 block_size
= lp_block_size(snum
);
2938 if (bsize
< block_size
) {
2939 uint64_t factor
= block_size
/bsize
;
2944 if (bsize
> block_size
) {
2945 uint64_t factor
= bsize
/block_size
;
2950 bytes_per_sector
= 512;
2951 sectors_per_unit
= bsize
/bytes_per_sector
;
2953 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2954 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2955 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2957 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2958 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2959 SIVAL(pdata
,l1_cUnit
,dsize
);
2960 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2961 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2965 case SMB_INFO_VOLUME
:
2966 /* Return volume name */
2968 * Add volume serial number - hash of a combination of
2969 * the called hostname and the service name.
2971 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2973 * Win2k3 and previous mess this up by sending a name length
2974 * one byte short. I believe only older clients (OS/2 Win9x) use
2975 * this call so try fixing this by adding a terminating null to
2976 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2980 pdata
+l2_vol_szVolLabel
, vname
,
2981 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2982 STR_NOALIGN
|STR_TERMINATE
);
2983 SCVAL(pdata
,l2_vol_cch
,len
);
2984 data_len
= l2_vol_szVolLabel
+ len
;
2985 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2986 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2990 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2991 case SMB_FS_ATTRIBUTE_INFORMATION
:
2993 additional_flags
= 0;
2994 #if defined(HAVE_SYS_QUOTAS)
2995 additional_flags
|= FILE_VOLUME_QUOTAS
;
2998 if(lp_nt_acl_support(SNUM(conn
))) {
2999 additional_flags
|= FILE_PERSISTENT_ACLS
;
3002 /* Capabilities are filled in at connection time through STATVFS call */
3003 additional_flags
|= conn
->fs_capabilities
;
3004 additional_flags
|= lp_parm_int(conn
->params
->service
,
3005 "share", "fake_fscaps",
3008 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3009 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3010 additional_flags
); /* FS ATTRIBUTES */
3012 SIVAL(pdata
,4,255); /* Max filename component length */
3013 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3014 and will think we can't do long filenames */
3015 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3016 PTR_DIFF(end_data
, pdata
+12),
3019 data_len
= 12 + len
;
3022 case SMB_QUERY_FS_LABEL_INFO
:
3023 case SMB_FS_LABEL_INFORMATION
:
3024 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3025 PTR_DIFF(end_data
, pdata
+4), 0);
3030 case SMB_QUERY_FS_VOLUME_INFO
:
3031 case SMB_FS_VOLUME_INFORMATION
:
3034 * Add volume serial number - hash of a combination of
3035 * the called hostname and the service name.
3037 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3038 (str_checksum(get_local_machine_name())<<16));
3040 /* Max label len is 32 characters. */
3041 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3042 PTR_DIFF(end_data
, pdata
+18),
3044 SIVAL(pdata
,12,len
);
3047 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3048 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3051 case SMB_QUERY_FS_SIZE_INFO
:
3052 case SMB_FS_SIZE_INFORMATION
:
3054 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3056 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3057 return map_nt_error_from_unix(errno
);
3059 block_size
= lp_block_size(snum
);
3060 if (bsize
< block_size
) {
3061 uint64_t factor
= block_size
/bsize
;
3066 if (bsize
> block_size
) {
3067 uint64_t factor
= bsize
/block_size
;
3072 bytes_per_sector
= 512;
3073 sectors_per_unit
= bsize
/bytes_per_sector
;
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3075 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3076 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3077 SBIG_UINT(pdata
,0,dsize
);
3078 SBIG_UINT(pdata
,8,dfree
);
3079 SIVAL(pdata
,16,sectors_per_unit
);
3080 SIVAL(pdata
,20,bytes_per_sector
);
3084 case SMB_FS_FULL_SIZE_INFORMATION
:
3086 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3088 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3089 return map_nt_error_from_unix(errno
);
3091 block_size
= lp_block_size(snum
);
3092 if (bsize
< block_size
) {
3093 uint64_t factor
= block_size
/bsize
;
3098 if (bsize
> block_size
) {
3099 uint64_t factor
= bsize
/block_size
;
3104 bytes_per_sector
= 512;
3105 sectors_per_unit
= bsize
/bytes_per_sector
;
3106 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3107 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3108 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3109 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3110 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3111 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3112 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3113 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3117 case SMB_QUERY_FS_DEVICE_INFO
:
3118 case SMB_FS_DEVICE_INFORMATION
:
3120 SIVAL(pdata
,0,0); /* dev type */
3121 SIVAL(pdata
,4,0); /* characteristics */
3124 #ifdef HAVE_SYS_QUOTAS
3125 case SMB_FS_QUOTA_INFORMATION
:
3127 * what we have to send --metze:
3129 * Unknown1: 24 NULL bytes
3130 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3131 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3132 * Quota Flags: 2 byte :
3133 * Unknown3: 6 NULL bytes
3137 * details for Quota Flags:
3139 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3140 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3141 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3142 * 0x0001 Enable Quotas: enable quota for this fs
3146 /* we need to fake up a fsp here,
3147 * because its not send in this call
3150 SMB_NTQUOTA_STRUCT quotas
;
3153 ZERO_STRUCT(quotas
);
3159 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3160 DEBUG(0,("set_user_quota: access_denied "
3161 "service [%s] user [%s]\n",
3162 lp_servicename(SNUM(conn
)),
3163 conn
->server_info
->unix_name
));
3164 return NT_STATUS_ACCESS_DENIED
;
3167 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3168 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3169 return map_nt_error_from_unix(errno
);
3174 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3175 lp_servicename(SNUM(conn
))));
3177 /* Unknown1 24 NULL bytes*/
3178 SBIG_UINT(pdata
,0,(uint64_t)0);
3179 SBIG_UINT(pdata
,8,(uint64_t)0);
3180 SBIG_UINT(pdata
,16,(uint64_t)0);
3182 /* Default Soft Quota 8 bytes */
3183 SBIG_UINT(pdata
,24,quotas
.softlim
);
3185 /* Default Hard Quota 8 bytes */
3186 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3188 /* Quota flag 2 bytes */
3189 SSVAL(pdata
,40,quotas
.qflags
);
3191 /* Unknown3 6 NULL bytes */
3197 #endif /* HAVE_SYS_QUOTAS */
3198 case SMB_FS_OBJECTID_INFORMATION
:
3200 unsigned char objid
[16];
3201 struct smb_extended_info extended_info
;
3202 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3203 samba_extended_info_version (&extended_info
);
3204 SIVAL(pdata
,16,extended_info
.samba_magic
);
3205 SIVAL(pdata
,20,extended_info
.samba_version
);
3206 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3207 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3208 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3214 * Query the version and capabilities of the CIFS UNIX extensions
3218 case SMB_QUERY_CIFS_UNIX_INFO
:
3220 bool large_write
= lp_min_receive_file_size() &&
3221 !srv_is_signing_active(smbd_server_conn
);
3222 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3223 int encrypt_caps
= 0;
3225 if (!lp_unix_extensions()) {
3226 return NT_STATUS_INVALID_LEVEL
;
3229 switch (conn
->encrypt_level
) {
3235 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3238 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3239 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3240 large_write
= false;
3246 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3247 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3249 /* We have POSIX ACLs, pathname, encryption,
3250 * large read/write, and locking capability. */
3252 SBIG_UINT(pdata
,4,((uint64_t)(
3253 CIFS_UNIX_POSIX_ACLS_CAP
|
3254 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3255 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3256 CIFS_UNIX_EXTATTR_CAP
|
3257 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3259 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3261 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3265 case SMB_QUERY_POSIX_FS_INFO
:
3268 vfs_statvfs_struct svfs
;
3270 if (!lp_unix_extensions()) {
3271 return NT_STATUS_INVALID_LEVEL
;
3274 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3278 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3279 SIVAL(pdata
,4,svfs
.BlockSize
);
3280 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3281 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3282 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3283 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3284 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3285 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3286 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3288 } else if (rc
== EOPNOTSUPP
) {
3289 return NT_STATUS_INVALID_LEVEL
;
3290 #endif /* EOPNOTSUPP */
3292 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3293 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3298 case SMB_QUERY_POSIX_WHOAMI
:
3304 if (!lp_unix_extensions()) {
3305 return NT_STATUS_INVALID_LEVEL
;
3308 if (max_data_bytes
< 40) {
3309 return NT_STATUS_BUFFER_TOO_SMALL
;
3312 /* We ARE guest if global_sid_Builtin_Guests is
3313 * in our list of SIDs.
3315 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3316 conn
->server_info
->ptok
)) {
3317 flags
|= SMB_WHOAMI_GUEST
;
3320 /* We are NOT guest if global_sid_Authenticated_Users
3321 * is in our list of SIDs.
3323 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3324 conn
->server_info
->ptok
)) {
3325 flags
&= ~SMB_WHOAMI_GUEST
;
3328 /* NOTE: 8 bytes for UID/GID, irrespective of native
3329 * platform size. This matches
3330 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3332 data_len
= 4 /* flags */
3339 + 4 /* pad/reserved */
3340 + (conn
->server_info
->utok
.ngroups
* 8)
3342 + (conn
->server_info
->ptok
->num_sids
*
3346 SIVAL(pdata
, 0, flags
);
3347 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3349 (uint64_t)conn
->server_info
->utok
.uid
);
3350 SBIG_UINT(pdata
, 16,
3351 (uint64_t)conn
->server_info
->utok
.gid
);
3354 if (data_len
>= max_data_bytes
) {
3355 /* Potential overflow, skip the GIDs and SIDs. */
3357 SIVAL(pdata
, 24, 0); /* num_groups */
3358 SIVAL(pdata
, 28, 0); /* num_sids */
3359 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3360 SIVAL(pdata
, 36, 0); /* reserved */
3366 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3367 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3369 /* We walk the SID list twice, but this call is fairly
3370 * infrequent, and I don't expect that it's performance
3371 * sensitive -- jpeach
3373 for (i
= 0, sid_bytes
= 0;
3374 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3375 sid_bytes
+= ndr_size_dom_sid(
3376 &conn
->server_info
->ptok
->user_sids
[i
],
3381 /* SID list byte count */
3382 SIVAL(pdata
, 32, sid_bytes
);
3384 /* 4 bytes pad/reserved - must be zero */
3385 SIVAL(pdata
, 36, 0);
3389 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3390 SBIG_UINT(pdata
, data_len
,
3391 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3397 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3398 int sid_len
= ndr_size_dom_sid(
3399 &conn
->server_info
->ptok
->user_sids
[i
],
3403 sid_linearize(pdata
+ data_len
, sid_len
,
3404 &conn
->server_info
->ptok
->user_sids
[i
]);
3405 data_len
+= sid_len
;
3411 case SMB_MAC_QUERY_FS_INFO
:
3413 * Thursby MAC extension... ONLY on NTFS filesystems
3414 * once we do streams then we don't need this
3416 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3418 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3423 return NT_STATUS_INVALID_LEVEL
;
3426 *ret_data_len
= data_len
;
3427 return NT_STATUS_OK
;
3430 /****************************************************************************
3431 Reply to a TRANS2_QFSINFO (query filesystem info).
3432 ****************************************************************************/
3434 static void call_trans2qfsinfo(connection_struct
*conn
,
3435 struct smb_request
*req
,
3436 char **pparams
, int total_params
,
3437 char **ppdata
, int total_data
,
3438 unsigned int max_data_bytes
)
3440 char *params
= *pparams
;
3441 uint16_t info_level
;
3445 if (total_params
< 2) {
3446 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3450 info_level
= SVAL(params
,0);
3452 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3453 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3454 DEBUG(0,("call_trans2qfsinfo: encryption required "
3455 "and info level 0x%x sent.\n",
3456 (unsigned int)info_level
));
3457 exit_server_cleanly("encryption required "
3463 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3465 status
= smbd_do_qfsinfo(conn
, req
,
3470 if (!NT_STATUS_IS_OK(status
)) {
3471 reply_nterror(req
, status
);
3475 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3478 DEBUG( 4, ( "%s info_level = %d\n",
3479 smb_fn_name(req
->cmd
), info_level
) );
3484 /****************************************************************************
3485 Reply to a TRANS2_SETFSINFO (set filesystem info).
3486 ****************************************************************************/
3488 static void call_trans2setfsinfo(connection_struct
*conn
,
3489 struct smb_request
*req
,
3490 char **pparams
, int total_params
,
3491 char **ppdata
, int total_data
,
3492 unsigned int max_data_bytes
)
3494 char *pdata
= *ppdata
;
3495 char *params
= *pparams
;
3498 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3501 if (total_params
< 4) {
3502 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3504 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3508 info_level
= SVAL(params
,2);
3511 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3512 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3513 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3514 "info level (0x%x) on IPC$.\n",
3515 (unsigned int)info_level
));
3516 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3521 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3522 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3523 DEBUG(0,("call_trans2setfsinfo: encryption required "
3524 "and info level 0x%x sent.\n",
3525 (unsigned int)info_level
));
3526 exit_server_cleanly("encryption required "
3532 switch(info_level
) {
3533 case SMB_SET_CIFS_UNIX_INFO
:
3535 uint16 client_unix_major
;
3536 uint16 client_unix_minor
;
3537 uint32 client_unix_cap_low
;
3538 uint32 client_unix_cap_high
;
3540 if (!lp_unix_extensions()) {
3542 NT_STATUS_INVALID_LEVEL
);
3546 /* There should be 12 bytes of capabilities set. */
3547 if (total_data
< 8) {
3550 NT_STATUS_INVALID_PARAMETER
);
3553 client_unix_major
= SVAL(pdata
,0);
3554 client_unix_minor
= SVAL(pdata
,2);
3555 client_unix_cap_low
= IVAL(pdata
,4);
3556 client_unix_cap_high
= IVAL(pdata
,8);
3557 /* Just print these values for now. */
3558 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3559 cap_low = 0x%x, cap_high = 0x%x\n",
3560 (unsigned int)client_unix_major
,
3561 (unsigned int)client_unix_minor
,
3562 (unsigned int)client_unix_cap_low
,
3563 (unsigned int)client_unix_cap_high
));
3565 /* Here is where we must switch to posix pathname processing... */
3566 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3567 lp_set_posix_pathnames();
3568 mangle_change_to_posix();
3571 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3572 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3573 /* Client that knows how to do posix locks,
3574 * but not posix open/mkdir operations. Set a
3575 * default type for read/write checks. */
3577 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3583 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3586 size_t param_len
= 0;
3587 size_t data_len
= total_data
;
3589 if (!lp_unix_extensions()) {
3592 NT_STATUS_INVALID_LEVEL
);
3596 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3599 NT_STATUS_NOT_SUPPORTED
);
3603 DEBUG( 4,("call_trans2setfsinfo: "
3604 "request transport encryption.\n"));
3606 status
= srv_request_encryption_setup(conn
,
3607 (unsigned char **)ppdata
,
3609 (unsigned char **)pparams
,
3612 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3613 !NT_STATUS_IS_OK(status
)) {
3614 reply_nterror(req
, status
);
3618 send_trans2_replies(conn
, req
,
3625 if (NT_STATUS_IS_OK(status
)) {
3626 /* Server-side transport
3627 * encryption is now *on*. */
3628 status
= srv_encryption_start(conn
);
3629 if (!NT_STATUS_IS_OK(status
)) {
3630 exit_server_cleanly(
3631 "Failure in setting "
3632 "up encrypted transport");
3638 case SMB_FS_QUOTA_INFORMATION
:
3640 files_struct
*fsp
= NULL
;
3641 SMB_NTQUOTA_STRUCT quotas
;
3643 ZERO_STRUCT(quotas
);
3646 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3647 ||!CAN_WRITE(conn
)) {
3648 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3649 lp_servicename(SNUM(conn
)),
3650 conn
->server_info
->unix_name
));
3651 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3655 /* note: normaly there're 48 bytes,
3656 * but we didn't use the last 6 bytes for now
3659 fsp
= file_fsp(req
, SVAL(params
,0));
3661 if (!check_fsp_ntquota_handle(conn
, req
,
3663 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3665 req
, NT_STATUS_INVALID_HANDLE
);
3669 if (total_data
< 42) {
3670 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3674 NT_STATUS_INVALID_PARAMETER
);
3678 /* unknown_1 24 NULL bytes in pdata*/
3680 /* the soft quotas 8 bytes (uint64_t)*/
3681 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3682 #ifdef LARGE_SMB_OFF_T
3683 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3684 #else /* LARGE_SMB_OFF_T */
3685 if ((IVAL(pdata
,28) != 0)&&
3686 ((quotas
.softlim
!= 0xFFFFFFFF)||
3687 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3688 /* more than 32 bits? */
3691 NT_STATUS_INVALID_PARAMETER
);
3694 #endif /* LARGE_SMB_OFF_T */
3696 /* the hard quotas 8 bytes (uint64_t)*/
3697 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3698 #ifdef LARGE_SMB_OFF_T
3699 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3700 #else /* LARGE_SMB_OFF_T */
3701 if ((IVAL(pdata
,36) != 0)&&
3702 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3703 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3704 /* more than 32 bits? */
3707 NT_STATUS_INVALID_PARAMETER
);
3710 #endif /* LARGE_SMB_OFF_T */
3712 /* quota_flags 2 bytes **/
3713 quotas
.qflags
= SVAL(pdata
,40);
3715 /* unknown_2 6 NULL bytes follow*/
3717 /* now set the quotas */
3718 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3719 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3720 reply_nterror(req
, map_nt_error_from_unix(errno
));
3727 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3729 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3735 * sending this reply works fine,
3736 * but I'm not sure it's the same
3737 * like windows do...
3740 reply_outbuf(req
, 10, 0);
3743 #if defined(HAVE_POSIX_ACLS)
3744 /****************************************************************************
3745 Utility function to count the number of entries in a POSIX acl.
3746 ****************************************************************************/
3748 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3750 unsigned int ace_count
= 0;
3751 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3752 SMB_ACL_ENTRY_T entry
;
3754 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3756 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3757 entry_id
= SMB_ACL_NEXT_ENTRY
;
3764 /****************************************************************************
3765 Utility function to marshall a POSIX acl into wire format.
3766 ****************************************************************************/
3768 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3770 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3771 SMB_ACL_ENTRY_T entry
;
3773 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3774 SMB_ACL_TAG_T tagtype
;
3775 SMB_ACL_PERMSET_T permset
;
3776 unsigned char perms
= 0;
3777 unsigned int own_grp
;
3780 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3781 entry_id
= SMB_ACL_NEXT_ENTRY
;
3784 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3785 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3789 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3790 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3794 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3795 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3796 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3798 SCVAL(pdata
,1,perms
);
3801 case SMB_ACL_USER_OBJ
:
3802 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3803 own_grp
= (unsigned int)pst
->st_ex_uid
;
3804 SIVAL(pdata
,2,own_grp
);
3809 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3811 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3814 own_grp
= (unsigned int)*puid
;
3815 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3816 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3817 SIVAL(pdata
,2,own_grp
);
3821 case SMB_ACL_GROUP_OBJ
:
3822 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3823 own_grp
= (unsigned int)pst
->st_ex_gid
;
3824 SIVAL(pdata
,2,own_grp
);
3829 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3834 own_grp
= (unsigned int)*pgid
;
3835 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3836 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3837 SIVAL(pdata
,2,own_grp
);
3842 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3843 SIVAL(pdata
,2,0xFFFFFFFF);
3844 SIVAL(pdata
,6,0xFFFFFFFF);
3847 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3848 SIVAL(pdata
,2,0xFFFFFFFF);
3849 SIVAL(pdata
,6,0xFFFFFFFF);
3852 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3855 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3862 /****************************************************************************
3863 Store the FILE_UNIX_BASIC info.
3864 ****************************************************************************/
3866 static char *store_file_unix_basic(connection_struct
*conn
,
3869 const SMB_STRUCT_STAT
*psbuf
)
3871 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3873 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3874 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3876 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3879 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3882 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3883 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3884 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3887 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3891 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3895 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3898 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3902 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3906 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3909 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3913 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3920 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3921 * the chflags(2) (or equivalent) flags.
3923 * XXX: this really should be behind the VFS interface. To do this, we would
3924 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3925 * Each VFS module could then implement its own mapping as appropriate for the
3926 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3928 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3932 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3936 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3940 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3944 { UF_HIDDEN
, EXT_HIDDEN
},
3947 /* Do not remove. We need to guarantee that this array has at least one
3948 * entry to build on HP-UX.
3954 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3955 uint32
*smb_fflags
, uint32
*smb_fmask
)
3959 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3960 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3961 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3962 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3967 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3968 const uint32 smb_fflags
,
3969 const uint32 smb_fmask
,
3972 uint32 max_fmask
= 0;
3975 *stat_fflags
= psbuf
->st_ex_flags
;
3977 /* For each flags requested in smb_fmask, check the state of the
3978 * corresponding flag in smb_fflags and set or clear the matching
3982 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3983 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3984 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3985 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3986 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3988 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3993 /* If smb_fmask is asking to set any bits that are not supported by
3994 * our flag mappings, we should fail.
3996 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4004 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4005 * of file flags and birth (create) time.
4007 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4010 const SMB_STRUCT_STAT
*psbuf
)
4012 uint32 file_flags
= 0;
4013 uint32 flags_mask
= 0;
4015 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4017 /* Create (birth) time 64 bit */
4018 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4021 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4022 SIVAL(pdata
, 0, file_flags
); /* flags */
4023 SIVAL(pdata
, 4, flags_mask
); /* mask */
4029 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4030 const struct stream_struct
*streams
,
4032 unsigned int max_data_bytes
,
4033 unsigned int *data_size
)
4036 unsigned int ofs
= 0;
4038 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4039 unsigned int next_offset
;
4041 smb_ucs2_t
*namebuf
;
4043 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4044 streams
[i
].name
, &namelen
) ||
4047 return NT_STATUS_INVALID_PARAMETER
;
4051 * name_buf is now null-terminated, we need to marshall as not
4057 SIVAL(data
, ofs
+4, namelen
);
4058 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4059 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4060 memcpy(data
+ofs
+24, namebuf
, namelen
);
4061 TALLOC_FREE(namebuf
);
4063 next_offset
= ofs
+ 24 + namelen
;
4065 if (i
== num_streams
-1) {
4066 SIVAL(data
, ofs
, 0);
4069 unsigned int align
= ndr_align_size(next_offset
, 8);
4071 memset(data
+next_offset
, 0, align
);
4072 next_offset
+= align
;
4074 SIVAL(data
, ofs
, next_offset
- ofs
);
4083 return NT_STATUS_OK
;
4086 /****************************************************************************
4087 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4088 ****************************************************************************/
4090 static void call_trans2qpipeinfo(connection_struct
*conn
,
4091 struct smb_request
*req
,
4092 unsigned int tran_call
,
4093 char **pparams
, int total_params
,
4094 char **ppdata
, int total_data
,
4095 unsigned int max_data_bytes
)
4097 char *params
= *pparams
;
4098 char *pdata
= *ppdata
;
4099 unsigned int data_size
= 0;
4100 unsigned int param_size
= 2;
4105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4109 if (total_params
< 4) {
4110 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4114 fsp
= file_fsp(req
, SVAL(params
,0));
4115 if (!fsp_is_np(fsp
)) {
4116 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4120 info_level
= SVAL(params
,2);
4122 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4123 if (*pparams
== NULL
) {
4124 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4129 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4130 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4131 if (*ppdata
== NULL
) {
4132 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4137 switch (info_level
) {
4138 case SMB_FILE_STANDARD_INFORMATION
:
4140 SOFF_T(pdata
,0,4096LL);
4147 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4151 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4157 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4158 TALLOC_CTX
*mem_ctx
,
4159 uint16_t info_level
,
4161 struct smb_filename
*smb_fname
,
4162 bool delete_pending
,
4163 struct timespec write_time_ts
,
4165 struct ea_list
*ea_list
,
4166 int lock_data_count
,
4169 unsigned int max_data_bytes
,
4171 unsigned int *pdata_size
)
4173 char *pdata
= *ppdata
;
4174 char *dstart
, *dend
;
4175 unsigned int data_size
;
4176 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4177 time_t create_time
, mtime
, atime
, c_time
;
4178 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4185 uint64_t file_size
= 0;
4187 uint64_t allocation_size
= 0;
4188 uint64_t file_index
= 0;
4189 uint32_t access_mask
= 0;
4191 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4192 return NT_STATUS_INVALID_LEVEL
;
4195 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4196 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4197 info_level
, max_data_bytes
));
4200 mode
= dos_mode_msdfs(conn
, smb_fname
);
4202 mode
= dos_mode(conn
, smb_fname
);
4205 nlink
= psbuf
->st_ex_nlink
;
4207 if (nlink
&& (mode
&aDIR
)) {
4211 if ((nlink
> 0) && delete_pending
) {
4215 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4216 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4217 if (*ppdata
== NULL
) {
4218 return NT_STATUS_NO_MEMORY
;
4222 dend
= dstart
+ data_size
- 1;
4224 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4225 update_stat_ex_mtime(psbuf
, write_time_ts
);
4228 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4229 mtime_ts
= psbuf
->st_ex_mtime
;
4230 atime_ts
= psbuf
->st_ex_atime
;
4231 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4233 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4234 dos_filetime_timespec(&create_time_ts
);
4235 dos_filetime_timespec(&mtime_ts
);
4236 dos_filetime_timespec(&atime_ts
);
4237 dos_filetime_timespec(&ctime_ts
);
4240 create_time
= convert_timespec_to_time_t(create_time_ts
);
4241 mtime
= convert_timespec_to_time_t(mtime_ts
);
4242 atime
= convert_timespec_to_time_t(atime_ts
);
4243 c_time
= convert_timespec_to_time_t(ctime_ts
);
4245 p
= strrchr_m(smb_fname
->base_name
,'/');
4247 base_name
= smb_fname
->base_name
;
4251 /* NT expects the name to be in an exact form of the *full*
4252 filename. See the trans2 torture test */
4253 if (ISDOT(base_name
)) {
4254 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4256 return NT_STATUS_NO_MEMORY
;
4259 dos_fname
= talloc_asprintf(mem_ctx
,
4261 smb_fname
->base_name
);
4263 return NT_STATUS_NO_MEMORY
;
4265 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4266 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4267 smb_fname
->stream_name
);
4269 return NT_STATUS_NO_MEMORY
;
4273 string_replace(dos_fname
, '/', '\\');
4276 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4279 /* Do we have this path open ? */
4281 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4282 fsp1
= file_find_di_first(fileid
);
4283 if (fsp1
&& fsp1
->initial_allocation_size
) {
4284 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4288 if (!(mode
& aDIR
)) {
4289 file_size
= get_file_size_stat(psbuf
);
4293 pos
= fsp
->fh
->position_information
;
4297 access_mask
= fsp
->access_mask
;
4299 /* GENERIC_EXECUTE mapping from Windows */
4300 access_mask
= 0x12019F;
4303 /* This should be an index number - looks like
4306 I think this causes us to fail the IFSKIT
4307 BasicFileInformationTest. -tpot */
4308 file_index
= get_FileIndex(conn
, psbuf
);
4310 switch (info_level
) {
4311 case SMB_INFO_STANDARD
:
4312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4314 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4315 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4316 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4317 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4318 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4319 SSVAL(pdata
,l1_attrFile
,mode
);
4322 case SMB_INFO_QUERY_EA_SIZE
:
4324 unsigned int ea_size
=
4325 estimate_ea_size(conn
, fsp
,
4326 smb_fname
->base_name
);
4327 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4329 srv_put_dos_date2(pdata
,0,create_time
);
4330 srv_put_dos_date2(pdata
,4,atime
);
4331 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4332 SIVAL(pdata
,12,(uint32
)file_size
);
4333 SIVAL(pdata
,16,(uint32
)allocation_size
);
4334 SSVAL(pdata
,20,mode
);
4335 SIVAL(pdata
,22,ea_size
);
4339 case SMB_INFO_IS_NAME_VALID
:
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4342 /* os/2 needs this ? really ?*/
4343 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4345 /* This is only reached for qpathinfo */
4349 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4351 size_t total_ea_len
= 0;
4352 struct ea_list
*ea_file_list
= NULL
;
4354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4357 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4358 smb_fname
->base_name
,
4360 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4362 if (!ea_list
|| (total_ea_len
> data_size
)) {
4364 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4368 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4372 case SMB_INFO_QUERY_ALL_EAS
:
4374 /* We have data_size bytes to put EA's into. */
4375 size_t total_ea_len
= 0;
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4379 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4380 smb_fname
->base_name
,
4382 if (!ea_list
|| (total_ea_len
> data_size
)) {
4384 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4388 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4392 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4394 /* This is FileFullEaInformation - 0xF which maps to
4395 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4397 /* We have data_size bytes to put EA's into. */
4398 size_t total_ea_len
= 0;
4399 struct ea_list
*ea_file_list
= NULL
;
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4403 /*TODO: add filtering and index handling */
4406 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4407 smb_fname
->base_name
,
4409 if (!ea_file_list
) {
4410 return NT_STATUS_NO_EAS_ON_FILE
;
4413 status
= fill_ea_chained_buffer(mem_ctx
,
4417 conn
, ea_file_list
);
4418 if (!NT_STATUS_IS_OK(status
)) {
4424 case SMB_FILE_BASIC_INFORMATION
:
4425 case SMB_QUERY_FILE_BASIC_INFO
:
4427 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4429 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4435 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4436 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4437 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4438 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4439 SIVAL(pdata
,32,mode
);
4441 DEBUG(5,("SMB_QFBI - "));
4442 DEBUG(5,("create: %s ", ctime(&create_time
)));
4443 DEBUG(5,("access: %s ", ctime(&atime
)));
4444 DEBUG(5,("write: %s ", ctime(&mtime
)));
4445 DEBUG(5,("change: %s ", ctime(&c_time
)));
4446 DEBUG(5,("mode: %x\n", mode
));
4449 case SMB_FILE_STANDARD_INFORMATION
:
4450 case SMB_QUERY_FILE_STANDARD_INFO
:
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4454 SOFF_T(pdata
,0,allocation_size
);
4455 SOFF_T(pdata
,8,file_size
);
4456 SIVAL(pdata
,16,nlink
);
4457 SCVAL(pdata
,20,delete_pending
?1:0);
4458 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4459 SSVAL(pdata
,22,0); /* Padding. */
4462 case SMB_FILE_EA_INFORMATION
:
4463 case SMB_QUERY_FILE_EA_INFO
:
4465 unsigned int ea_size
=
4466 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4467 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4469 SIVAL(pdata
,0,ea_size
);
4473 /* Get the 8.3 name - used if NT SMB was negotiated. */
4474 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4475 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4478 char mangled_name
[13];
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4480 if (!name_to_8_3(base_name
,mangled_name
,
4481 True
,conn
->params
)) {
4482 return NT_STATUS_NO_MEMORY
;
4484 len
= srvstr_push(dstart
, flags2
,
4485 pdata
+4, mangled_name
,
4486 PTR_DIFF(dend
, pdata
+4),
4488 data_size
= 4 + len
;
4493 case SMB_QUERY_FILE_NAME_INFO
:
4497 this must be *exactly* right for ACLs on mapped drives to work
4499 len
= srvstr_push(dstart
, flags2
,
4501 PTR_DIFF(dend
, pdata
+4),
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4504 data_size
= 4 + len
;
4509 case SMB_FILE_ALLOCATION_INFORMATION
:
4510 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4513 SOFF_T(pdata
,0,allocation_size
);
4516 case SMB_FILE_END_OF_FILE_INFORMATION
:
4517 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4520 SOFF_T(pdata
,0,file_size
);
4523 case SMB_QUERY_FILE_ALL_INFO
:
4524 case SMB_FILE_ALL_INFORMATION
:
4527 unsigned int ea_size
=
4528 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4530 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4531 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4532 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4533 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4534 SIVAL(pdata
,32,mode
);
4535 SIVAL(pdata
,36,0); /* padding. */
4537 SOFF_T(pdata
,0,allocation_size
);
4538 SOFF_T(pdata
,8,file_size
);
4539 SIVAL(pdata
,16,nlink
);
4540 SCVAL(pdata
,20,delete_pending
);
4541 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4544 SIVAL(pdata
,0,ea_size
);
4545 pdata
+= 4; /* EA info */
4546 len
= srvstr_push(dstart
, flags2
,
4548 PTR_DIFF(dend
, pdata
+4),
4552 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4556 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4559 unsigned int ea_size
=
4560 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4561 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4562 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4563 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4564 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4565 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4566 SIVAL(pdata
, 0x20, mode
);
4567 SIVAL(pdata
, 0x24, 0); /* padding. */
4568 SBVAL(pdata
, 0x28, allocation_size
);
4569 SBVAL(pdata
, 0x30, file_size
);
4570 SIVAL(pdata
, 0x38, nlink
);
4571 SCVAL(pdata
, 0x3C, delete_pending
);
4572 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4573 SSVAL(pdata
, 0x3E, 0); /* padding */
4574 SBVAL(pdata
, 0x40, file_index
);
4575 SIVAL(pdata
, 0x48, ea_size
);
4576 SIVAL(pdata
, 0x4C, access_mask
);
4577 SBVAL(pdata
, 0x50, pos
);
4578 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4579 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4583 len
= srvstr_push(dstart
, flags2
,
4585 PTR_DIFF(dend
, pdata
+4),
4589 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4592 case SMB_FILE_INTERNAL_INFORMATION
:
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4595 SBVAL(pdata
, 0, file_index
);
4599 case SMB_FILE_ACCESS_INFORMATION
:
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4601 SIVAL(pdata
, 0, access_mask
);
4605 case SMB_FILE_NAME_INFORMATION
:
4606 /* Pathname with leading '\'. */
4609 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4611 SIVAL(pdata
,0,byte_len
);
4612 data_size
= 4 + byte_len
;
4616 case SMB_FILE_DISPOSITION_INFORMATION
:
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4619 SCVAL(pdata
,0,delete_pending
);
4622 case SMB_FILE_POSITION_INFORMATION
:
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4625 SOFF_T(pdata
,0,pos
);
4628 case SMB_FILE_MODE_INFORMATION
:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4630 SIVAL(pdata
,0,mode
);
4634 case SMB_FILE_ALIGNMENT_INFORMATION
:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4636 SIVAL(pdata
,0,0); /* No alignment needed. */
4641 * NT4 server just returns "invalid query" to this - if we try
4642 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4645 /* The first statement above is false - verified using Thursby
4646 * client against NT4 -- gcolley.
4648 case SMB_QUERY_FILE_STREAM_INFO
:
4649 case SMB_FILE_STREAM_INFORMATION
: {
4650 unsigned int num_streams
;
4651 struct stream_struct
*streams
;
4653 DEBUG(10,("smbd_do_qfilepathinfo: "
4654 "SMB_FILE_STREAM_INFORMATION\n"));
4656 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4657 return NT_STATUS_INVALID_PARAMETER
;
4660 status
= SMB_VFS_STREAMINFO(
4661 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4662 &num_streams
, &streams
);
4664 if (!NT_STATUS_IS_OK(status
)) {
4665 DEBUG(10, ("could not get stream info: %s\n",
4666 nt_errstr(status
)));
4670 status
= marshall_stream_info(num_streams
, streams
,
4671 pdata
, max_data_bytes
,
4674 if (!NT_STATUS_IS_OK(status
)) {
4675 DEBUG(10, ("marshall_stream_info failed: %s\n",
4676 nt_errstr(status
)));
4680 TALLOC_FREE(streams
);
4684 case SMB_QUERY_COMPRESSION_INFO
:
4685 case SMB_FILE_COMPRESSION_INFORMATION
:
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4687 SOFF_T(pdata
,0,file_size
);
4688 SIVAL(pdata
,8,0); /* ??? */
4689 SIVAL(pdata
,12,0); /* ??? */
4693 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4695 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4696 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4697 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4698 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4699 SOFF_T(pdata
,32,allocation_size
);
4700 SOFF_T(pdata
,40,file_size
);
4701 SIVAL(pdata
,48,mode
);
4702 SIVAL(pdata
,52,0); /* ??? */
4706 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4708 SIVAL(pdata
,0,mode
);
4714 * CIFS UNIX Extensions.
4717 case SMB_QUERY_FILE_UNIX_BASIC
:
4719 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4720 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4724 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4726 for (i
=0; i
<100; i
++)
4727 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4733 case SMB_QUERY_FILE_UNIX_INFO2
:
4735 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4736 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4740 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4742 for (i
=0; i
<100; i
++)
4743 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4749 case SMB_QUERY_FILE_UNIX_LINK
:
4752 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4755 return NT_STATUS_NO_MEMORY
;
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4760 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4761 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4764 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4766 len
= SMB_VFS_READLINK(conn
,
4767 smb_fname
->base_name
,
4770 return map_nt_error_from_unix(errno
);
4773 len
= srvstr_push(dstart
, flags2
,
4775 PTR_DIFF(dend
, pdata
),
4778 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4783 #if defined(HAVE_POSIX_ACLS)
4784 case SMB_QUERY_POSIX_ACL
:
4786 SMB_ACL_T file_acl
= NULL
;
4787 SMB_ACL_T def_acl
= NULL
;
4788 uint16 num_file_acls
= 0;
4789 uint16 num_def_acls
= 0;
4791 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4792 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4795 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4796 smb_fname
->base_name
,
4797 SMB_ACL_TYPE_ACCESS
);
4800 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4801 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4802 "not implemented on "
4803 "filesystem containing %s\n",
4804 smb_fname
->base_name
));
4805 return NT_STATUS_NOT_IMPLEMENTED
;
4808 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4809 if (fsp
&& fsp
->is_directory
) {
4811 SMB_VFS_SYS_ACL_GET_FILE(
4813 fsp
->fsp_name
->base_name
,
4814 SMB_ACL_TYPE_DEFAULT
);
4817 SMB_VFS_SYS_ACL_GET_FILE(
4819 smb_fname
->base_name
,
4820 SMB_ACL_TYPE_DEFAULT
);
4822 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4825 num_file_acls
= count_acl_entries(conn
, file_acl
);
4826 num_def_acls
= count_acl_entries(conn
, def_acl
);
4828 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4829 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4831 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4832 SMB_POSIX_ACL_HEADER_SIZE
) ));
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4837 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4839 return NT_STATUS_BUFFER_TOO_SMALL
;
4842 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4843 SSVAL(pdata
,2,num_file_acls
);
4844 SSVAL(pdata
,4,num_def_acls
);
4845 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4852 return NT_STATUS_INTERNAL_ERROR
;
4854 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4861 return NT_STATUS_INTERNAL_ERROR
;
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4870 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4876 case SMB_QUERY_POSIX_LOCK
:
4881 enum brl_type lock_type
;
4883 /* We need an open file with a real fd for this. */
4884 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4885 return NT_STATUS_INVALID_LEVEL
;
4888 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4889 return NT_STATUS_INVALID_PARAMETER
;
4892 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4893 case POSIX_LOCK_TYPE_READ
:
4894 lock_type
= READ_LOCK
;
4896 case POSIX_LOCK_TYPE_WRITE
:
4897 lock_type
= WRITE_LOCK
;
4899 case POSIX_LOCK_TYPE_UNLOCK
:
4901 /* There's no point in asking for an unlock... */
4902 return NT_STATUS_INVALID_PARAMETER
;
4905 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4906 #if defined(HAVE_LONGLONG)
4907 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4908 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4909 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4910 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4911 #else /* HAVE_LONGLONG */
4912 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4913 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4914 #endif /* HAVE_LONGLONG */
4916 status
= query_lock(fsp
,
4923 if (ERROR_WAS_LOCK_DENIED(status
)) {
4924 /* Here we need to report who has it locked... */
4925 data_size
= POSIX_LOCK_DATA_SIZE
;
4927 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4928 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4929 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4930 #if defined(HAVE_LONGLONG)
4931 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4932 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4933 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4934 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4935 #else /* HAVE_LONGLONG */
4936 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4937 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4938 #endif /* HAVE_LONGLONG */
4940 } else if (NT_STATUS_IS_OK(status
)) {
4941 /* For success we just return a copy of what we sent
4942 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4943 data_size
= POSIX_LOCK_DATA_SIZE
;
4944 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4945 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4953 return NT_STATUS_INVALID_LEVEL
;
4956 *pdata_size
= data_size
;
4957 return NT_STATUS_OK
;
4960 /****************************************************************************
4961 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4962 file name or file id).
4963 ****************************************************************************/
4965 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4966 struct smb_request
*req
,
4967 unsigned int tran_call
,
4968 char **pparams
, int total_params
,
4969 char **ppdata
, int total_data
,
4970 unsigned int max_data_bytes
)
4972 char *params
= *pparams
;
4973 char *pdata
= *ppdata
;
4975 unsigned int data_size
= 0;
4976 unsigned int param_size
= 2;
4977 struct smb_filename
*smb_fname
= NULL
;
4978 bool delete_pending
= False
;
4979 struct timespec write_time_ts
;
4980 files_struct
*fsp
= NULL
;
4981 struct file_id fileid
;
4982 struct ea_list
*ea_list
= NULL
;
4983 int lock_data_count
= 0;
4984 char *lock_data
= NULL
;
4985 bool ms_dfs_link
= false;
4986 NTSTATUS status
= NT_STATUS_OK
;
4989 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4993 ZERO_STRUCT(write_time_ts
);
4995 if (tran_call
== TRANSACT2_QFILEINFO
) {
4996 if (total_params
< 4) {
4997 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5002 call_trans2qpipeinfo(conn
, req
, tran_call
,
5003 pparams
, total_params
,
5009 fsp
= file_fsp(req
, SVAL(params
,0));
5010 info_level
= SVAL(params
,2);
5012 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5014 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5015 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5019 /* Initial check for valid fsp ptr. */
5020 if (!check_fsp_open(conn
, req
, fsp
)) {
5024 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5026 if (!NT_STATUS_IS_OK(status
)) {
5027 reply_nterror(req
, status
);
5031 if(fsp
->fake_file_handle
) {
5033 * This is actually for the QUOTA_FAKE_FILE --metze
5036 /* We know this name is ok, it's already passed the checks. */
5038 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5040 * This is actually a QFILEINFO on a directory
5041 * handle (returned from an NT SMB). NT5.0 seems
5042 * to do this call. JRA.
5045 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5046 /* Always do lstat for UNIX calls. */
5047 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5048 DEBUG(3,("call_trans2qfilepathinfo: "
5049 "SMB_VFS_LSTAT of %s failed "
5051 smb_fname_str_dbg(smb_fname
),
5054 map_nt_error_from_unix(errno
));
5057 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5058 DEBUG(3,("call_trans2qfilepathinfo: "
5059 "SMB_VFS_STAT of %s failed (%s)\n",
5060 smb_fname_str_dbg(smb_fname
),
5063 map_nt_error_from_unix(errno
));
5067 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5068 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5071 * Original code - this is an open file.
5073 if (!check_fsp(conn
, req
, fsp
)) {
5077 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5078 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5079 fsp
->fnum
, strerror(errno
)));
5081 map_nt_error_from_unix(errno
));
5084 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5085 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5092 if (total_params
< 7) {
5093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5097 info_level
= SVAL(params
,0);
5099 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5101 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5102 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5106 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5108 STR_TERMINATE
, &status
);
5109 if (!NT_STATUS_IS_OK(status
)) {
5110 reply_nterror(req
, status
);
5114 status
= filename_convert(req
,
5116 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5121 if (!NT_STATUS_IS_OK(status
)) {
5122 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5123 reply_botherror(req
,
5124 NT_STATUS_PATH_NOT_COVERED
,
5125 ERRSRV
, ERRbadpath
);
5128 reply_nterror(req
, status
);
5132 /* If this is a stream, check if there is a delete_pending. */
5133 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5134 && is_ntfs_stream_smb_fname(smb_fname
)) {
5135 struct smb_filename
*smb_fname_base
= NULL
;
5137 /* Create an smb_filename with stream_name == NULL. */
5139 create_synthetic_smb_fname(talloc_tos(),
5140 smb_fname
->base_name
,
5143 if (!NT_STATUS_IS_OK(status
)) {
5144 reply_nterror(req
, status
);
5148 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5149 /* Always do lstat for UNIX calls. */
5150 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5151 DEBUG(3,("call_trans2qfilepathinfo: "
5152 "SMB_VFS_LSTAT of %s failed "
5154 smb_fname_str_dbg(smb_fname_base
),
5156 TALLOC_FREE(smb_fname_base
);
5158 map_nt_error_from_unix(errno
));
5162 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5163 DEBUG(3,("call_trans2qfilepathinfo: "
5164 "fileinfo of %s failed "
5166 smb_fname_str_dbg(smb_fname_base
),
5168 TALLOC_FREE(smb_fname_base
);
5170 map_nt_error_from_unix(errno
));
5175 fileid
= vfs_file_id_from_sbuf(conn
,
5176 &smb_fname_base
->st
);
5177 TALLOC_FREE(smb_fname_base
);
5178 get_file_infos(fileid
, &delete_pending
, NULL
);
5179 if (delete_pending
) {
5180 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5185 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5186 /* Always do lstat for UNIX calls. */
5187 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "SMB_VFS_LSTAT of %s failed (%s)\n",
5190 smb_fname_str_dbg(smb_fname
),
5193 map_nt_error_from_unix(errno
));
5197 } else if (!VALID_STAT(smb_fname
->st
) &&
5198 SMB_VFS_STAT(conn
, smb_fname
) &&
5199 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5200 ms_dfs_link
= check_msdfs_link(conn
,
5201 smb_fname
->base_name
,
5205 DEBUG(3,("call_trans2qfilepathinfo: "
5206 "SMB_VFS_STAT of %s failed (%s)\n",
5207 smb_fname_str_dbg(smb_fname
),
5210 map_nt_error_from_unix(errno
));
5215 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5216 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5217 if (delete_pending
) {
5218 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5223 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5224 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5225 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5227 /* Pull out any data sent here before we realloc. */
5228 switch (info_level
) {
5229 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5231 /* Pull any EA list from the data portion. */
5234 if (total_data
< 4) {
5236 req
, NT_STATUS_INVALID_PARAMETER
);
5239 ea_size
= IVAL(pdata
,0);
5241 if (total_data
> 0 && ea_size
!= total_data
) {
5242 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5243 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5245 req
, NT_STATUS_INVALID_PARAMETER
);
5249 if (!lp_ea_support(SNUM(conn
))) {
5250 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5254 /* Pull out the list of names. */
5255 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5258 req
, NT_STATUS_INVALID_PARAMETER
);
5264 case SMB_QUERY_POSIX_LOCK
:
5266 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5267 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5271 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5273 req
, NT_STATUS_INVALID_PARAMETER
);
5277 /* Copy the lock range data. */
5278 lock_data
= (char *)TALLOC_MEMDUP(
5279 req
, pdata
, total_data
);
5281 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5284 lock_data_count
= total_data
;
5290 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5291 if (*pparams
== NULL
) {
5292 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5299 * draft-leach-cifs-v1-spec-02.txt
5300 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5303 * The requested information is placed in the Data portion of the
5304 * transaction response. For the information levels greater than 0x100,
5305 * the transaction response has 1 parameter word which should be
5306 * ignored by the client.
5308 * However Windows only follows this rule for the IS_NAME_VALID call.
5310 switch (info_level
) {
5311 case SMB_INFO_IS_NAME_VALID
:
5316 if ((info_level
& 0xFF00) == 0xFF00) {
5318 * We use levels that start with 0xFF00
5319 * internally to represent SMB2 specific levels
5321 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5325 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5327 delete_pending
, write_time_ts
,
5328 ms_dfs_link
, ea_list
,
5329 lock_data_count
, lock_data
,
5330 req
->flags2
, max_data_bytes
,
5331 ppdata
, &data_size
);
5332 if (!NT_STATUS_IS_OK(status
)) {
5333 reply_nterror(req
, status
);
5337 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5343 /****************************************************************************
5344 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5346 ****************************************************************************/
5348 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5349 connection_struct
*conn
,
5350 const struct smb_filename
*smb_fname_old
,
5351 const struct smb_filename
*smb_fname_new
)
5353 NTSTATUS status
= NT_STATUS_OK
;
5355 /* source must already exist. */
5356 if (!VALID_STAT(smb_fname_old
->st
)) {
5357 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5360 /* Disallow if newname already exists. */
5361 if (VALID_STAT(smb_fname_new
->st
)) {
5362 return NT_STATUS_OBJECT_NAME_COLLISION
;
5365 /* No links from a directory. */
5366 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5367 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5370 /* Setting a hardlink to/from a stream isn't currently supported. */
5371 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5372 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5373 return NT_STATUS_INVALID_PARAMETER
;
5376 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5377 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5379 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5380 smb_fname_new
->base_name
) != 0) {
5381 status
= map_nt_error_from_unix(errno
);
5382 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5383 nt_errstr(status
), smb_fname_old
->base_name
,
5384 smb_fname_new
->base_name
));
5389 /****************************************************************************
5390 Deal with setting the time from any of the setfilepathinfo functions.
5391 ****************************************************************************/
5393 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5395 const struct smb_filename
*smb_fname
,
5396 struct smb_file_time
*ft
,
5397 bool setting_write_time
)
5399 struct smb_filename smb_fname_base
;
5401 FILE_NOTIFY_CHANGE_LAST_ACCESS
5402 |FILE_NOTIFY_CHANGE_LAST_WRITE
5403 |FILE_NOTIFY_CHANGE_CREATION
;
5405 if (!VALID_STAT(smb_fname
->st
)) {
5406 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5409 /* get some defaults (no modifications) if any info is zero or -1. */
5410 if (null_timespec(ft
->create_time
)) {
5411 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5414 if (null_timespec(ft
->atime
)) {
5415 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5418 if (null_timespec(ft
->mtime
)) {
5419 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5422 if (!setting_write_time
) {
5423 /* ft->mtime comes from change time, not write time. */
5424 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5427 /* Ensure the resolution is the correct for
5428 * what we can store on this filesystem. */
5430 round_timespec(conn
->ts_res
, &ft
->create_time
);
5431 round_timespec(conn
->ts_res
, &ft
->ctime
);
5432 round_timespec(conn
->ts_res
, &ft
->atime
);
5433 round_timespec(conn
->ts_res
, &ft
->mtime
);
5435 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5436 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5437 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5438 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5439 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5440 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5441 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5442 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5444 if (setting_write_time
) {
5446 * This was a Windows setfileinfo on an open file.
5447 * NT does this a lot. We also need to
5448 * set the time here, as it can be read by
5449 * FindFirst/FindNext and with the patch for bug #2045
5450 * in smbd/fileio.c it ensures that this timestamp is
5451 * kept sticky even after a write. We save the request
5452 * away and will set it on file close and after a write. JRA.
5455 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5456 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5459 if (fsp
->base_fsp
) {
5460 set_sticky_write_time_fsp(fsp
->base_fsp
,
5463 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5466 set_sticky_write_time_path(
5467 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5472 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5474 /* Always call ntimes on the base, even if a stream was passed in. */
5475 smb_fname_base
= *smb_fname
;
5476 smb_fname_base
.stream_name
= NULL
;
5478 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5479 return map_nt_error_from_unix(errno
);
5482 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5483 smb_fname
->base_name
);
5484 return NT_STATUS_OK
;
5487 /****************************************************************************
5488 Deal with setting the dosmode from any of the setfilepathinfo functions.
5489 ****************************************************************************/
5491 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5492 const struct smb_filename
*smb_fname
,
5495 struct smb_filename
*smb_fname_base
= NULL
;
5498 if (!VALID_STAT(smb_fname
->st
)) {
5499 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5502 /* Always operate on the base_name, even if a stream was passed in. */
5503 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5504 NULL
, &smb_fname
->st
,
5506 if (!NT_STATUS_IS_OK(status
)) {
5511 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5518 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5520 /* check the mode isn't different, before changing it */
5521 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5522 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5523 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5524 (unsigned int)dosmode
));
5526 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5528 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5530 smb_fname_str_dbg(smb_fname_base
),
5532 status
= map_nt_error_from_unix(errno
);
5536 status
= NT_STATUS_OK
;
5538 TALLOC_FREE(smb_fname_base
);
5542 /****************************************************************************
5543 Deal with setting the size from any of the setfilepathinfo functions.
5544 ****************************************************************************/
5546 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5547 struct smb_request
*req
,
5549 const struct smb_filename
*smb_fname
,
5550 const SMB_STRUCT_STAT
*psbuf
,
5552 bool fail_after_createfile
)
5554 NTSTATUS status
= NT_STATUS_OK
;
5555 struct smb_filename
*smb_fname_tmp
= NULL
;
5556 files_struct
*new_fsp
= NULL
;
5558 if (!VALID_STAT(*psbuf
)) {
5559 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5562 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5564 if (size
== get_file_size_stat(psbuf
)) {
5565 return NT_STATUS_OK
;
5568 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5569 smb_fname_str_dbg(smb_fname
), (double)size
));
5571 if (fsp
&& fsp
->fh
->fd
!= -1) {
5572 /* Handle based call. */
5573 if (vfs_set_filelen(fsp
, size
) == -1) {
5574 return map_nt_error_from_unix(errno
);
5576 trigger_write_time_update_immediate(fsp
);
5577 return NT_STATUS_OK
;
5580 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5581 if (!NT_STATUS_IS_OK(status
)) {
5585 smb_fname_tmp
->st
= *psbuf
;
5587 status
= SMB_VFS_CREATE_FILE(
5590 0, /* root_dir_fid */
5591 smb_fname_tmp
, /* fname */
5592 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5593 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5595 FILE_OPEN
, /* create_disposition*/
5596 0, /* create_options */
5597 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5598 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5599 0, /* allocation_size */
5602 &new_fsp
, /* result */
5605 TALLOC_FREE(smb_fname_tmp
);
5607 if (!NT_STATUS_IS_OK(status
)) {
5608 /* NB. We check for open_was_deferred in the caller. */
5612 /* See RAW-SFILEINFO-END-OF-FILE */
5613 if (fail_after_createfile
) {
5614 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5615 return NT_STATUS_INVALID_LEVEL
;
5618 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5619 status
= map_nt_error_from_unix(errno
);
5620 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5624 trigger_write_time_update_immediate(new_fsp
);
5625 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5626 return NT_STATUS_OK
;
5629 /****************************************************************************
5630 Deal with SMB_INFO_SET_EA.
5631 ****************************************************************************/
5633 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5637 const struct smb_filename
*smb_fname
)
5639 struct ea_list
*ea_list
= NULL
;
5640 TALLOC_CTX
*ctx
= NULL
;
5641 NTSTATUS status
= NT_STATUS_OK
;
5643 if (total_data
< 10) {
5645 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5646 length. They seem to have no effect. Bug #3212. JRA */
5648 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5649 /* We're done. We only get EA info in this call. */
5650 return NT_STATUS_OK
;
5653 return NT_STATUS_INVALID_PARAMETER
;
5656 if (IVAL(pdata
,0) > total_data
) {
5657 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5658 IVAL(pdata
,0), (unsigned int)total_data
));
5659 return NT_STATUS_INVALID_PARAMETER
;
5663 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5665 return NT_STATUS_INVALID_PARAMETER
;
5667 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5672 /****************************************************************************
5673 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5674 ****************************************************************************/
5676 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5681 struct ea_list
*ea_list
= NULL
;
5685 return NT_STATUS_INVALID_HANDLE
;
5688 if (!lp_ea_support(SNUM(conn
))) {
5689 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5690 "EA's not supported.\n",
5691 (unsigned int)total_data
));
5692 return NT_STATUS_EAS_NOT_SUPPORTED
;
5695 if (total_data
< 10) {
5696 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5698 (unsigned int)total_data
));
5699 return NT_STATUS_INVALID_PARAMETER
;
5702 ea_list
= read_nttrans_ea_list(talloc_tos(),
5707 return NT_STATUS_INVALID_PARAMETER
;
5709 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5711 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5712 smb_fname_str_dbg(fsp
->fsp_name
),
5713 nt_errstr(status
) ));
5719 /****************************************************************************
5720 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5721 ****************************************************************************/
5723 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5727 struct smb_filename
*smb_fname
)
5729 NTSTATUS status
= NT_STATUS_OK
;
5730 bool delete_on_close
;
5733 if (total_data
< 1) {
5734 return NT_STATUS_INVALID_PARAMETER
;
5738 return NT_STATUS_INVALID_HANDLE
;
5741 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5742 dosmode
= dos_mode(conn
, smb_fname
);
5744 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5745 "delete_on_close = %u\n",
5746 smb_fname_str_dbg(smb_fname
),
5747 (unsigned int)dosmode
,
5748 (unsigned int)delete_on_close
));
5750 if (delete_on_close
) {
5751 status
= can_set_delete_on_close(fsp
, dosmode
);
5752 if (!NT_STATUS_IS_OK(status
)) {
5757 /* The set is across all open files on this dev/inode pair. */
5758 if (!set_delete_on_close(fsp
, delete_on_close
,
5759 &conn
->server_info
->utok
)) {
5760 return NT_STATUS_ACCESS_DENIED
;
5762 return NT_STATUS_OK
;
5765 /****************************************************************************
5766 Deal with SMB_FILE_POSITION_INFORMATION.
5767 ****************************************************************************/
5769 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5774 uint64_t position_information
;
5776 if (total_data
< 8) {
5777 return NT_STATUS_INVALID_PARAMETER
;
5781 /* Ignore on pathname based set. */
5782 return NT_STATUS_OK
;
5785 position_information
= (uint64_t)IVAL(pdata
,0);
5786 #ifdef LARGE_SMB_OFF_T
5787 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5788 #else /* LARGE_SMB_OFF_T */
5789 if (IVAL(pdata
,4) != 0) {
5790 /* more than 32 bits? */
5791 return NT_STATUS_INVALID_PARAMETER
;
5793 #endif /* LARGE_SMB_OFF_T */
5795 DEBUG(10,("smb_file_position_information: Set file position "
5796 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5797 (double)position_information
));
5798 fsp
->fh
->position_information
= position_information
;
5799 return NT_STATUS_OK
;
5802 /****************************************************************************
5803 Deal with SMB_FILE_MODE_INFORMATION.
5804 ****************************************************************************/
5806 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5812 if (total_data
< 4) {
5813 return NT_STATUS_INVALID_PARAMETER
;
5815 mode
= IVAL(pdata
,0);
5816 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5817 return NT_STATUS_INVALID_PARAMETER
;
5819 return NT_STATUS_OK
;
5822 /****************************************************************************
5823 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5824 ****************************************************************************/
5826 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5827 struct smb_request
*req
,
5830 const struct smb_filename
*smb_fname
)
5832 char *link_target
= NULL
;
5833 const char *newname
= smb_fname
->base_name
;
5834 TALLOC_CTX
*ctx
= talloc_tos();
5836 /* Set a symbolic link. */
5837 /* Don't allow this if follow links is false. */
5839 if (total_data
== 0) {
5840 return NT_STATUS_INVALID_PARAMETER
;
5843 if (!lp_symlinks(SNUM(conn
))) {
5844 return NT_STATUS_ACCESS_DENIED
;
5847 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5848 total_data
, STR_TERMINATE
);
5851 return NT_STATUS_INVALID_PARAMETER
;
5854 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5855 newname
, link_target
));
5857 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5858 return map_nt_error_from_unix(errno
);
5861 return NT_STATUS_OK
;
5864 /****************************************************************************
5865 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5866 ****************************************************************************/
5868 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5869 struct smb_request
*req
,
5870 const char *pdata
, int total_data
,
5871 const struct smb_filename
*smb_fname_new
)
5873 char *oldname
= NULL
;
5874 struct smb_filename
*smb_fname_old
= NULL
;
5875 TALLOC_CTX
*ctx
= talloc_tos();
5876 NTSTATUS status
= NT_STATUS_OK
;
5878 /* Set a hard link. */
5879 if (total_data
== 0) {
5880 return NT_STATUS_INVALID_PARAMETER
;
5883 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5884 total_data
, STR_TERMINATE
, &status
);
5885 if (!NT_STATUS_IS_OK(status
)) {
5889 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5890 smb_fname_str_dbg(smb_fname_new
), oldname
));
5892 status
= filename_convert(ctx
,
5894 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5899 if (!NT_STATUS_IS_OK(status
)) {
5903 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5906 /****************************************************************************
5907 Deal with SMB_FILE_RENAME_INFORMATION.
5908 ****************************************************************************/
5910 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5911 struct smb_request
*req
,
5915 struct smb_filename
*smb_fname_src
)
5920 char *newname
= NULL
;
5921 struct smb_filename
*smb_fname_dst
= NULL
;
5922 bool dest_has_wcard
= False
;
5923 NTSTATUS status
= NT_STATUS_OK
;
5925 TALLOC_CTX
*ctx
= talloc_tos();
5927 if (total_data
< 13) {
5928 return NT_STATUS_INVALID_PARAMETER
;
5931 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5932 root_fid
= IVAL(pdata
,4);
5933 len
= IVAL(pdata
,8);
5935 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5936 return NT_STATUS_INVALID_PARAMETER
;
5939 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5942 if (!NT_STATUS_IS_OK(status
)) {
5946 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5949 status
= resolve_dfspath_wcard(ctx
, conn
,
5950 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5955 if (!NT_STATUS_IS_OK(status
)) {
5959 /* Check the new name has no '/' characters. */
5960 if (strchr_m(newname
, '/')) {
5961 return NT_STATUS_NOT_SUPPORTED
;
5964 if (fsp
&& fsp
->base_fsp
) {
5965 /* newname must be a stream name. */
5966 if (newname
[0] != ':') {
5967 return NT_STATUS_NOT_SUPPORTED
;
5970 /* Create an smb_fname to call rename_internals_fsp() with. */
5971 status
= create_synthetic_smb_fname(talloc_tos(),
5972 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
5974 if (!NT_STATUS_IS_OK(status
)) {
5979 * Set the original last component, since
5980 * rename_internals_fsp() requires it.
5982 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
5984 if (smb_fname_dst
->original_lcomp
== NULL
) {
5985 status
= NT_STATUS_NO_MEMORY
;
5991 * Build up an smb_fname_dst based on the filename passed in.
5992 * We basically just strip off the last component, and put on
5993 * the newname instead.
5995 char *base_name
= NULL
;
5997 /* newname must *not* be a stream name. */
5998 if (newname
[0] == ':') {
5999 return NT_STATUS_NOT_SUPPORTED
;
6003 * Strip off the last component (filename) of the path passed
6006 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6008 return NT_STATUS_NO_MEMORY
;
6010 p
= strrchr_m(base_name
, '/');
6014 base_name
= talloc_strdup(ctx
, "./");
6016 return NT_STATUS_NO_MEMORY
;
6019 /* Append the new name. */
6020 base_name
= talloc_asprintf_append(base_name
,
6024 return NT_STATUS_NO_MEMORY
;
6027 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6030 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6033 /* If an error we expect this to be
6034 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6036 if (!NT_STATUS_IS_OK(status
)) {
6037 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6041 /* Create an smb_fname to call rename_internals_fsp() */
6042 status
= create_synthetic_smb_fname(ctx
,
6046 if (!NT_STATUS_IS_OK(status
)) {
6053 DEBUG(10,("smb_file_rename_information: "
6054 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6055 fsp
->fnum
, fsp_str_dbg(fsp
),
6056 smb_fname_str_dbg(smb_fname_dst
)));
6057 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6060 DEBUG(10,("smb_file_rename_information: "
6061 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6062 smb_fname_str_dbg(smb_fname_src
),
6063 smb_fname_str_dbg(smb_fname_dst
)));
6064 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6065 smb_fname_dst
, 0, overwrite
, false,
6067 FILE_WRITE_ATTRIBUTES
);
6070 TALLOC_FREE(smb_fname_dst
);
6074 /****************************************************************************
6075 Deal with SMB_SET_POSIX_ACL.
6076 ****************************************************************************/
6078 #if defined(HAVE_POSIX_ACLS)
6079 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6083 const struct smb_filename
*smb_fname
)
6085 uint16 posix_acl_version
;
6086 uint16 num_file_acls
;
6087 uint16 num_def_acls
;
6088 bool valid_file_acls
= True
;
6089 bool valid_def_acls
= True
;
6091 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6092 return NT_STATUS_INVALID_PARAMETER
;
6094 posix_acl_version
= SVAL(pdata
,0);
6095 num_file_acls
= SVAL(pdata
,2);
6096 num_def_acls
= SVAL(pdata
,4);
6098 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6099 valid_file_acls
= False
;
6103 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6104 valid_def_acls
= False
;
6108 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6109 return NT_STATUS_INVALID_PARAMETER
;
6112 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6113 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6114 return NT_STATUS_INVALID_PARAMETER
;
6117 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6118 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6119 (unsigned int)num_file_acls
,
6120 (unsigned int)num_def_acls
));
6122 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6123 smb_fname
->base_name
, num_file_acls
,
6124 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6125 return map_nt_error_from_unix(errno
);
6128 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6129 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6130 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6131 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6132 return map_nt_error_from_unix(errno
);
6134 return NT_STATUS_OK
;
6138 /****************************************************************************
6139 Deal with SMB_SET_POSIX_LOCK.
6140 ****************************************************************************/
6142 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6143 struct smb_request
*req
,
6151 bool blocking_lock
= False
;
6152 enum brl_type lock_type
;
6154 NTSTATUS status
= NT_STATUS_OK
;
6156 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6157 return NT_STATUS_INVALID_HANDLE
;
6160 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6161 return NT_STATUS_INVALID_PARAMETER
;
6164 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6165 case POSIX_LOCK_TYPE_READ
:
6166 lock_type
= READ_LOCK
;
6168 case POSIX_LOCK_TYPE_WRITE
:
6169 /* Return the right POSIX-mappable error code for files opened read-only. */
6170 if (!fsp
->can_write
) {
6171 return NT_STATUS_INVALID_HANDLE
;
6173 lock_type
= WRITE_LOCK
;
6175 case POSIX_LOCK_TYPE_UNLOCK
:
6176 lock_type
= UNLOCK_LOCK
;
6179 return NT_STATUS_INVALID_PARAMETER
;
6182 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6183 blocking_lock
= False
;
6184 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6185 blocking_lock
= True
;
6187 return NT_STATUS_INVALID_PARAMETER
;
6190 if (!lp_blocking_locks(SNUM(conn
))) {
6191 blocking_lock
= False
;
6194 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6195 #if defined(HAVE_LONGLONG)
6196 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6197 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6198 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6199 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6200 #else /* HAVE_LONGLONG */
6201 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6202 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6203 #endif /* HAVE_LONGLONG */
6205 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6206 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6208 (unsigned int)lock_type
,
6209 (unsigned int)lock_pid
,
6213 if (lock_type
== UNLOCK_LOCK
) {
6214 status
= do_unlock(smbd_messaging_context(),
6221 uint32 block_smbpid
;
6223 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6235 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6237 * A blocking lock was requested. Package up
6238 * this smb into a queued request and push it
6239 * onto the blocking lock queue.
6241 if(push_blocking_lock_request(br_lck
,
6244 -1, /* infinite timeout. */
6252 TALLOC_FREE(br_lck
);
6256 TALLOC_FREE(br_lck
);
6262 /****************************************************************************
6263 Deal with SMB_SET_FILE_BASIC_INFO.
6264 ****************************************************************************/
6266 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6270 const struct smb_filename
*smb_fname
)
6272 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6273 struct smb_file_time ft
;
6275 NTSTATUS status
= NT_STATUS_OK
;
6279 if (total_data
< 36) {
6280 return NT_STATUS_INVALID_PARAMETER
;
6283 /* Set the attributes */
6284 dosmode
= IVAL(pdata
,32);
6285 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6286 if (!NT_STATUS_IS_OK(status
)) {
6291 ft
.create_time
= interpret_long_date(pdata
);
6294 ft
.atime
= interpret_long_date(pdata
+8);
6297 ft
.mtime
= interpret_long_date(pdata
+16);
6300 ft
.ctime
= interpret_long_date(pdata
+24);
6302 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6303 smb_fname_str_dbg(smb_fname
)));
6305 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6309 /****************************************************************************
6310 Deal with SMB_INFO_STANDARD.
6311 ****************************************************************************/
6313 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6317 const struct smb_filename
*smb_fname
)
6319 struct smb_file_time ft
;
6323 if (total_data
< 12) {
6324 return NT_STATUS_INVALID_PARAMETER
;
6328 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6330 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6332 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6334 DEBUG(10,("smb_set_info_standard: file %s\n",
6335 smb_fname_str_dbg(smb_fname
)));
6337 return smb_set_file_time(conn
,
6344 /****************************************************************************
6345 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6346 ****************************************************************************/
6348 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6349 struct smb_request
*req
,
6353 struct smb_filename
*smb_fname
)
6355 uint64_t allocation_size
= 0;
6356 NTSTATUS status
= NT_STATUS_OK
;
6357 files_struct
*new_fsp
= NULL
;
6359 if (!VALID_STAT(smb_fname
->st
)) {
6360 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6363 if (total_data
< 8) {
6364 return NT_STATUS_INVALID_PARAMETER
;
6367 allocation_size
= (uint64_t)IVAL(pdata
,0);
6368 #ifdef LARGE_SMB_OFF_T
6369 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6370 #else /* LARGE_SMB_OFF_T */
6371 if (IVAL(pdata
,4) != 0) {
6372 /* more than 32 bits? */
6373 return NT_STATUS_INVALID_PARAMETER
;
6375 #endif /* LARGE_SMB_OFF_T */
6377 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6378 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6379 (double)allocation_size
));
6381 if (allocation_size
) {
6382 allocation_size
= smb_roundup(conn
, allocation_size
);
6385 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6386 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6387 (double)allocation_size
));
6389 if (fsp
&& fsp
->fh
->fd
!= -1) {
6390 /* Open file handle. */
6391 /* Only change if needed. */
6392 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6393 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6394 return map_nt_error_from_unix(errno
);
6397 /* But always update the time. */
6399 * This is equivalent to a write. Ensure it's seen immediately
6400 * if there are no pending writes.
6402 trigger_write_time_update_immediate(fsp
);
6403 return NT_STATUS_OK
;
6406 /* Pathname or stat or directory file. */
6407 status
= SMB_VFS_CREATE_FILE(
6410 0, /* root_dir_fid */
6411 smb_fname
, /* fname */
6412 FILE_WRITE_DATA
, /* access_mask */
6413 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6415 FILE_OPEN
, /* create_disposition*/
6416 0, /* create_options */
6417 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6418 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6419 0, /* allocation_size */
6422 &new_fsp
, /* result */
6425 if (!NT_STATUS_IS_OK(status
)) {
6426 /* NB. We check for open_was_deferred in the caller. */
6430 /* Only change if needed. */
6431 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6432 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6433 status
= map_nt_error_from_unix(errno
);
6434 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6439 /* Changing the allocation size should set the last mod time. */
6441 * This is equivalent to a write. Ensure it's seen immediately
6442 * if there are no pending writes.
6444 trigger_write_time_update_immediate(new_fsp
);
6446 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6447 return NT_STATUS_OK
;
6450 /****************************************************************************
6451 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6452 ****************************************************************************/
6454 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6455 struct smb_request
*req
,
6459 const struct smb_filename
*smb_fname
,
6460 bool fail_after_createfile
)
6464 if (total_data
< 8) {
6465 return NT_STATUS_INVALID_PARAMETER
;
6468 size
= IVAL(pdata
,0);
6469 #ifdef LARGE_SMB_OFF_T
6470 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6471 #else /* LARGE_SMB_OFF_T */
6472 if (IVAL(pdata
,4) != 0) {
6473 /* more than 32 bits? */
6474 return NT_STATUS_INVALID_PARAMETER
;
6476 #endif /* LARGE_SMB_OFF_T */
6477 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6478 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6481 return smb_set_file_size(conn
, req
,
6486 fail_after_createfile
);
6489 /****************************************************************************
6490 Allow a UNIX info mknod.
6491 ****************************************************************************/
6493 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6496 const struct smb_filename
*smb_fname
)
6498 uint32 file_type
= IVAL(pdata
,56);
6499 #if defined(HAVE_MAKEDEV)
6500 uint32 dev_major
= IVAL(pdata
,60);
6501 uint32 dev_minor
= IVAL(pdata
,68);
6503 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6504 uint32 raw_unixmode
= IVAL(pdata
,84);
6508 if (total_data
< 100) {
6509 return NT_STATUS_INVALID_PARAMETER
;
6512 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6513 PERM_NEW_FILE
, &unixmode
);
6514 if (!NT_STATUS_IS_OK(status
)) {
6518 #if defined(HAVE_MAKEDEV)
6519 dev
= makedev(dev_major
, dev_minor
);
6522 switch (file_type
) {
6523 #if defined(S_IFIFO)
6524 case UNIX_TYPE_FIFO
:
6525 unixmode
|= S_IFIFO
;
6528 #if defined(S_IFSOCK)
6529 case UNIX_TYPE_SOCKET
:
6530 unixmode
|= S_IFSOCK
;
6533 #if defined(S_IFCHR)
6534 case UNIX_TYPE_CHARDEV
:
6535 unixmode
|= S_IFCHR
;
6538 #if defined(S_IFBLK)
6539 case UNIX_TYPE_BLKDEV
:
6540 unixmode
|= S_IFBLK
;
6544 return NT_STATUS_INVALID_PARAMETER
;
6547 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6548 "%.0f mode 0%o for file %s\n", (double)dev
,
6549 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6551 /* Ok - do the mknod. */
6552 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6553 return map_nt_error_from_unix(errno
);
6556 /* If any of the other "set" calls fail we
6557 * don't want to end up with a half-constructed mknod.
6560 if (lp_inherit_perms(SNUM(conn
))) {
6562 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6564 return NT_STATUS_NO_MEMORY
;
6566 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6568 TALLOC_FREE(parent
);
6571 return NT_STATUS_OK
;
6574 /****************************************************************************
6575 Deal with SMB_SET_FILE_UNIX_BASIC.
6576 ****************************************************************************/
6578 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6579 struct smb_request
*req
,
6583 const struct smb_filename
*smb_fname
)
6585 struct smb_file_time ft
;
6586 uint32 raw_unixmode
;
6589 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6590 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6591 NTSTATUS status
= NT_STATUS_OK
;
6592 bool delete_on_fail
= False
;
6593 enum perm_type ptype
;
6594 files_struct
*all_fsps
= NULL
;
6595 bool modify_mtime
= true;
6597 struct smb_filename
*smb_fname_tmp
= NULL
;
6598 SMB_STRUCT_STAT sbuf
;
6602 if (total_data
< 100) {
6603 return NT_STATUS_INVALID_PARAMETER
;
6606 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6607 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6608 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6609 #ifdef LARGE_SMB_OFF_T
6610 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6611 #else /* LARGE_SMB_OFF_T */
6612 if (IVAL(pdata
,4) != 0) {
6613 /* more than 32 bits? */
6614 return NT_STATUS_INVALID_PARAMETER
;
6616 #endif /* LARGE_SMB_OFF_T */
6619 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6620 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6621 set_owner
= (uid_t
)IVAL(pdata
,40);
6622 set_grp
= (gid_t
)IVAL(pdata
,48);
6623 raw_unixmode
= IVAL(pdata
,84);
6625 if (VALID_STAT(smb_fname
->st
)) {
6626 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6627 ptype
= PERM_EXISTING_DIR
;
6629 ptype
= PERM_EXISTING_FILE
;
6632 ptype
= PERM_NEW_FILE
;
6635 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6637 if (!NT_STATUS_IS_OK(status
)) {
6641 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6642 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6643 smb_fname_str_dbg(smb_fname
), (double)size
,
6644 (unsigned int)set_owner
, (unsigned int)set_grp
,
6645 (int)raw_unixmode
));
6647 sbuf
= smb_fname
->st
;
6649 if (!VALID_STAT(sbuf
)) {
6651 * The only valid use of this is to create character and block
6652 * devices, and named pipes. This is deprecated (IMHO) and
6653 * a new info level should be used for mknod. JRA.
6656 status
= smb_unix_mknod(conn
,
6660 if (!NT_STATUS_IS_OK(status
)) {
6664 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6666 if (!NT_STATUS_IS_OK(status
)) {
6670 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6671 status
= map_nt_error_from_unix(errno
);
6672 TALLOC_FREE(smb_fname_tmp
);
6673 SMB_VFS_UNLINK(conn
, smb_fname
);
6677 sbuf
= smb_fname_tmp
->st
;
6678 smb_fname
= smb_fname_tmp
;
6680 /* Ensure we don't try and change anything else. */
6681 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6682 size
= get_file_size_stat(&sbuf
);
6683 ft
.atime
= sbuf
.st_ex_atime
;
6684 ft
.mtime
= sbuf
.st_ex_mtime
;
6686 * We continue here as we might want to change the
6689 delete_on_fail
= True
;
6693 /* Horrible backwards compatibility hack as an old server bug
6694 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6698 size
= get_file_size_stat(&sbuf
);
6703 * Deal with the UNIX specific mode set.
6706 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6707 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6708 "setting mode 0%o for file %s\n",
6709 (unsigned int)unixmode
,
6710 smb_fname_str_dbg(smb_fname
)));
6711 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6712 return map_nt_error_from_unix(errno
);
6717 * Deal with the UNIX specific uid set.
6720 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6721 (sbuf
.st_ex_uid
!= set_owner
)) {
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6725 "changing owner %u for path %s\n",
6726 (unsigned int)set_owner
,
6727 smb_fname_str_dbg(smb_fname
)));
6729 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6730 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6731 set_owner
, (gid_t
)-1);
6733 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6734 set_owner
, (gid_t
)-1);
6738 status
= map_nt_error_from_unix(errno
);
6739 if (delete_on_fail
) {
6740 SMB_VFS_UNLINK(conn
, smb_fname
);
6747 * Deal with the UNIX specific gid set.
6750 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6751 (sbuf
.st_ex_gid
!= set_grp
)) {
6752 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6753 "changing group %u for file %s\n",
6754 (unsigned int)set_owner
,
6755 smb_fname_str_dbg(smb_fname
)));
6756 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6758 status
= map_nt_error_from_unix(errno
);
6759 if (delete_on_fail
) {
6760 SMB_VFS_UNLINK(conn
, smb_fname
);
6766 /* Deal with any size changes. */
6768 status
= smb_set_file_size(conn
, req
,
6774 if (!NT_STATUS_IS_OK(status
)) {
6778 /* Deal with any time changes. */
6779 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6780 /* No change, don't cancel anything. */
6784 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6785 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6786 all_fsps
= file_find_di_next(all_fsps
)) {
6788 * We're setting the time explicitly for UNIX.
6789 * Cancel any pending changes over all handles.
6791 all_fsps
->update_write_time_on_close
= false;
6792 TALLOC_FREE(all_fsps
->update_write_time_event
);
6796 * Override the "setting_write_time"
6797 * parameter here as it almost does what
6798 * we need. Just remember if we modified
6799 * mtime and send the notify ourselves.
6801 if (null_timespec(ft
.mtime
)) {
6802 modify_mtime
= false;
6805 status
= smb_set_file_time(conn
,
6811 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6812 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_UNIX_INFO2.
6819 ****************************************************************************/
6821 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6822 struct smb_request
*req
,
6826 const struct smb_filename
*smb_fname
)
6832 if (total_data
< 116) {
6833 return NT_STATUS_INVALID_PARAMETER
;
6836 /* Start by setting all the fields that are common between UNIX_BASIC
6839 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6841 if (!NT_STATUS_IS_OK(status
)) {
6845 smb_fflags
= IVAL(pdata
, 108);
6846 smb_fmask
= IVAL(pdata
, 112);
6848 /* NB: We should only attempt to alter the file flags if the client
6849 * sends a non-zero mask.
6851 if (smb_fmask
!= 0) {
6852 int stat_fflags
= 0;
6854 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6855 smb_fmask
, &stat_fflags
)) {
6856 /* Client asked to alter a flag we don't understand. */
6857 return NT_STATUS_INVALID_PARAMETER
;
6860 if (fsp
&& fsp
->fh
->fd
!= -1) {
6861 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6862 return NT_STATUS_NOT_SUPPORTED
;
6864 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6865 stat_fflags
) != 0) {
6866 return map_nt_error_from_unix(errno
);
6871 /* XXX: need to add support for changing the create_time here. You
6872 * can do this for paths on Darwin with setattrlist(2). The right way
6873 * to hook this up is probably by extending the VFS utimes interface.
6876 return NT_STATUS_OK
;
6879 /****************************************************************************
6880 Create a directory with POSIX semantics.
6881 ****************************************************************************/
6883 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6884 struct smb_request
*req
,
6887 struct smb_filename
*smb_fname
,
6888 int *pdata_return_size
)
6890 NTSTATUS status
= NT_STATUS_OK
;
6891 uint32 raw_unixmode
= 0;
6892 uint32 mod_unixmode
= 0;
6893 mode_t unixmode
= (mode_t
)0;
6894 files_struct
*fsp
= NULL
;
6895 uint16 info_level_return
= 0;
6897 char *pdata
= *ppdata
;
6899 if (total_data
< 18) {
6900 return NT_STATUS_INVALID_PARAMETER
;
6903 raw_unixmode
= IVAL(pdata
,8);
6904 /* Next 4 bytes are not yet defined. */
6906 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6907 PERM_NEW_DIR
, &unixmode
);
6908 if (!NT_STATUS_IS_OK(status
)) {
6912 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6914 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6915 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6917 status
= SMB_VFS_CREATE_FILE(
6920 0, /* root_dir_fid */
6921 smb_fname
, /* fname */
6922 FILE_READ_ATTRIBUTES
, /* access_mask */
6923 FILE_SHARE_NONE
, /* share_access */
6924 FILE_CREATE
, /* create_disposition*/
6925 FILE_DIRECTORY_FILE
, /* create_options */
6926 mod_unixmode
, /* file_attributes */
6927 0, /* oplock_request */
6928 0, /* allocation_size */
6934 if (NT_STATUS_IS_OK(status
)) {
6935 close_file(req
, fsp
, NORMAL_CLOSE
);
6938 info_level_return
= SVAL(pdata
,16);
6940 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6941 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6942 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6943 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6945 *pdata_return_size
= 12;
6948 /* Realloc the data size */
6949 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6950 if (*ppdata
== NULL
) {
6951 *pdata_return_size
= 0;
6952 return NT_STATUS_NO_MEMORY
;
6956 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6957 SSVAL(pdata
,2,0); /* No fnum. */
6958 SIVAL(pdata
,4,info
); /* Was directory created. */
6960 switch (info_level_return
) {
6961 case SMB_QUERY_FILE_UNIX_BASIC
:
6962 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6963 SSVAL(pdata
,10,0); /* Padding. */
6964 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6967 case SMB_QUERY_FILE_UNIX_INFO2
:
6968 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6969 SSVAL(pdata
,10,0); /* Padding. */
6970 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6974 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6975 SSVAL(pdata
,10,0); /* Padding. */
6982 /****************************************************************************
6983 Open/Create a file with POSIX semantics.
6984 ****************************************************************************/
6986 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6987 struct smb_request
*req
,
6990 struct smb_filename
*smb_fname
,
6991 int *pdata_return_size
)
6993 bool extended_oplock_granted
= False
;
6994 char *pdata
= *ppdata
;
6996 uint32 wire_open_mode
= 0;
6997 uint32 raw_unixmode
= 0;
6998 uint32 mod_unixmode
= 0;
6999 uint32 create_disp
= 0;
7000 uint32 access_mask
= 0;
7001 uint32 create_options
= 0;
7002 NTSTATUS status
= NT_STATUS_OK
;
7003 mode_t unixmode
= (mode_t
)0;
7004 files_struct
*fsp
= NULL
;
7005 int oplock_request
= 0;
7007 uint16 info_level_return
= 0;
7009 if (total_data
< 18) {
7010 return NT_STATUS_INVALID_PARAMETER
;
7013 flags
= IVAL(pdata
,0);
7014 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7015 if (oplock_request
) {
7016 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7019 wire_open_mode
= IVAL(pdata
,4);
7021 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7022 return smb_posix_mkdir(conn
, req
,
7029 switch (wire_open_mode
& SMB_ACCMODE
) {
7031 access_mask
= FILE_READ_DATA
;
7034 access_mask
= FILE_WRITE_DATA
;
7037 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7040 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7041 (unsigned int)wire_open_mode
));
7042 return NT_STATUS_INVALID_PARAMETER
;
7045 wire_open_mode
&= ~SMB_ACCMODE
;
7047 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7048 create_disp
= FILE_CREATE
;
7049 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7050 create_disp
= FILE_OVERWRITE_IF
;
7051 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7052 create_disp
= FILE_OPEN_IF
;
7053 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7054 create_disp
= FILE_OPEN
;
7056 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7057 (unsigned int)wire_open_mode
));
7058 return NT_STATUS_INVALID_PARAMETER
;
7061 raw_unixmode
= IVAL(pdata
,8);
7062 /* Next 4 bytes are not yet defined. */
7064 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7065 (VALID_STAT(smb_fname
->st
) ?
7066 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7069 if (!NT_STATUS_IS_OK(status
)) {
7073 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7075 if (wire_open_mode
& SMB_O_SYNC
) {
7076 create_options
|= FILE_WRITE_THROUGH
;
7078 if (wire_open_mode
& SMB_O_APPEND
) {
7079 access_mask
|= FILE_APPEND_DATA
;
7081 if (wire_open_mode
& SMB_O_DIRECT
) {
7082 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7085 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7086 smb_fname_str_dbg(smb_fname
),
7087 (unsigned int)wire_open_mode
,
7088 (unsigned int)unixmode
));
7090 status
= SMB_VFS_CREATE_FILE(
7093 0, /* root_dir_fid */
7094 smb_fname
, /* fname */
7095 access_mask
, /* access_mask */
7096 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7098 create_disp
, /* create_disposition*/
7099 FILE_NON_DIRECTORY_FILE
, /* create_options */
7100 mod_unixmode
, /* file_attributes */
7101 oplock_request
, /* oplock_request */
7102 0, /* allocation_size */
7108 if (!NT_STATUS_IS_OK(status
)) {
7112 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7113 extended_oplock_granted
= True
;
7116 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7117 extended_oplock_granted
= True
;
7120 info_level_return
= SVAL(pdata
,16);
7122 /* Allocate the correct return size. */
7124 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7125 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7126 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7127 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7129 *pdata_return_size
= 12;
7132 /* Realloc the data size */
7133 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7134 if (*ppdata
== NULL
) {
7135 close_file(req
, fsp
, ERROR_CLOSE
);
7136 *pdata_return_size
= 0;
7137 return NT_STATUS_NO_MEMORY
;
7141 if (extended_oplock_granted
) {
7142 if (flags
& REQUEST_BATCH_OPLOCK
) {
7143 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7145 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7147 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7148 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7150 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7153 SSVAL(pdata
,2,fsp
->fnum
);
7154 SIVAL(pdata
,4,info
); /* Was file created etc. */
7156 switch (info_level_return
) {
7157 case SMB_QUERY_FILE_UNIX_BASIC
:
7158 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7159 SSVAL(pdata
,10,0); /* padding. */
7160 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7163 case SMB_QUERY_FILE_UNIX_INFO2
:
7164 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7165 SSVAL(pdata
,10,0); /* padding. */
7166 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7170 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7171 SSVAL(pdata
,10,0); /* padding. */
7174 return NT_STATUS_OK
;
7177 /****************************************************************************
7178 Delete a file with POSIX semantics.
7179 ****************************************************************************/
7181 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7182 struct smb_request
*req
,
7185 struct smb_filename
*smb_fname
)
7187 NTSTATUS status
= NT_STATUS_OK
;
7188 files_struct
*fsp
= NULL
;
7192 int create_options
= 0;
7194 struct share_mode_lock
*lck
= NULL
;
7196 if (total_data
< 2) {
7197 return NT_STATUS_INVALID_PARAMETER
;
7200 flags
= SVAL(pdata
,0);
7202 if (!VALID_STAT(smb_fname
->st
)) {
7203 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7206 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7207 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7208 return NT_STATUS_NOT_A_DIRECTORY
;
7211 DEBUG(10,("smb_posix_unlink: %s %s\n",
7212 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7213 smb_fname_str_dbg(smb_fname
)));
7215 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7216 create_options
|= FILE_DIRECTORY_FILE
;
7219 status
= SMB_VFS_CREATE_FILE(
7222 0, /* root_dir_fid */
7223 smb_fname
, /* fname */
7224 DELETE_ACCESS
, /* access_mask */
7225 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7227 FILE_OPEN
, /* create_disposition*/
7228 create_options
, /* create_options */
7229 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7230 0, /* oplock_request */
7231 0, /* allocation_size */
7237 if (!NT_STATUS_IS_OK(status
)) {
7242 * Don't lie to client. If we can't really delete due to
7243 * non-POSIX opens return SHARING_VIOLATION.
7246 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7249 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7250 "lock for file %s\n", fsp_str_dbg(fsp
)));
7251 close_file(req
, fsp
, NORMAL_CLOSE
);
7252 return NT_STATUS_INVALID_PARAMETER
;
7256 * See if others still have the file open. If this is the case, then
7257 * don't delete. If all opens are POSIX delete we can set the delete
7258 * on close disposition.
7260 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7261 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7262 if (is_valid_share_mode_entry(e
)) {
7263 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7266 /* Fail with sharing violation. */
7267 close_file(req
, fsp
, NORMAL_CLOSE
);
7269 return NT_STATUS_SHARING_VIOLATION
;
7274 * Set the delete on close.
7276 status
= smb_set_file_disposition_info(conn
,
7282 if (!NT_STATUS_IS_OK(status
)) {
7283 close_file(req
, fsp
, NORMAL_CLOSE
);
7288 return close_file(req
, fsp
, NORMAL_CLOSE
);
7291 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7292 struct smb_request
*req
,
7293 TALLOC_CTX
*mem_ctx
,
7294 uint16_t info_level
,
7296 struct smb_filename
*smb_fname
,
7297 char **ppdata
, int total_data
,
7300 char *pdata
= *ppdata
;
7301 NTSTATUS status
= NT_STATUS_OK
;
7302 int data_return_size
= 0;
7306 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7307 return NT_STATUS_INVALID_LEVEL
;
7310 if (!CAN_WRITE(conn
)) {
7311 /* Allow POSIX opens. The open path will deny
7312 * any non-readonly opens. */
7313 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7314 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7318 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7319 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7320 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7322 switch (info_level
) {
7324 case SMB_INFO_STANDARD
:
7326 status
= smb_set_info_standard(conn
,
7334 case SMB_INFO_SET_EA
:
7336 status
= smb_info_set_ea(conn
,
7344 case SMB_SET_FILE_BASIC_INFO
:
7345 case SMB_FILE_BASIC_INFORMATION
:
7347 status
= smb_set_file_basic_info(conn
,
7355 case SMB_FILE_ALLOCATION_INFORMATION
:
7356 case SMB_SET_FILE_ALLOCATION_INFO
:
7358 status
= smb_set_file_allocation_info(conn
, req
,
7366 case SMB_FILE_END_OF_FILE_INFORMATION
:
7367 case SMB_SET_FILE_END_OF_FILE_INFO
:
7370 * XP/Win7 both fail after the createfile with
7371 * SMB_SET_FILE_END_OF_FILE_INFO but not
7372 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7373 * The level is known here, so pass it down
7377 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7379 status
= smb_set_file_end_of_file_info(conn
, req
,
7388 case SMB_FILE_DISPOSITION_INFORMATION
:
7389 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7392 /* JRA - We used to just ignore this on a path ?
7393 * Shouldn't this be invalid level on a pathname
7396 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7397 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7400 status
= smb_set_file_disposition_info(conn
,
7408 case SMB_FILE_POSITION_INFORMATION
:
7410 status
= smb_file_position_information(conn
,
7417 case SMB_FILE_FULL_EA_INFORMATION
:
7419 status
= smb_set_file_full_ea_info(conn
,
7426 /* From tridge Samba4 :
7427 * MODE_INFORMATION in setfileinfo (I have no
7428 * idea what "mode information" on a file is - it takes a value of 0,
7429 * 2, 4 or 6. What could it be?).
7432 case SMB_FILE_MODE_INFORMATION
:
7434 status
= smb_file_mode_information(conn
,
7441 * CIFS UNIX extensions.
7444 case SMB_SET_FILE_UNIX_BASIC
:
7446 status
= smb_set_file_unix_basic(conn
, req
,
7454 case SMB_SET_FILE_UNIX_INFO2
:
7456 status
= smb_set_file_unix_info2(conn
, req
,
7464 case SMB_SET_FILE_UNIX_LINK
:
7467 /* We must have a pathname for this. */
7468 return NT_STATUS_INVALID_LEVEL
;
7470 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7471 total_data
, smb_fname
);
7475 case SMB_SET_FILE_UNIX_HLINK
:
7478 /* We must have a pathname for this. */
7479 return NT_STATUS_INVALID_LEVEL
;
7481 status
= smb_set_file_unix_hlink(conn
, req
,
7487 case SMB_FILE_RENAME_INFORMATION
:
7489 status
= smb_file_rename_information(conn
, req
,
7495 #if defined(HAVE_POSIX_ACLS)
7496 case SMB_SET_POSIX_ACL
:
7498 status
= smb_set_posix_acl(conn
,
7507 case SMB_SET_POSIX_LOCK
:
7510 return NT_STATUS_INVALID_LEVEL
;
7512 status
= smb_set_posix_lock(conn
, req
,
7513 pdata
, total_data
, fsp
);
7517 case SMB_POSIX_PATH_OPEN
:
7520 /* We must have a pathname for this. */
7521 return NT_STATUS_INVALID_LEVEL
;
7524 status
= smb_posix_open(conn
, req
,
7532 case SMB_POSIX_PATH_UNLINK
:
7535 /* We must have a pathname for this. */
7536 return NT_STATUS_INVALID_LEVEL
;
7539 status
= smb_posix_unlink(conn
, req
,
7547 return NT_STATUS_INVALID_LEVEL
;
7550 if (!NT_STATUS_IS_OK(status
)) {
7554 *ret_data_size
= data_return_size
;
7555 return NT_STATUS_OK
;
7558 /****************************************************************************
7559 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7560 ****************************************************************************/
7562 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7563 struct smb_request
*req
,
7564 unsigned int tran_call
,
7565 char **pparams
, int total_params
,
7566 char **ppdata
, int total_data
,
7567 unsigned int max_data_bytes
)
7569 char *params
= *pparams
;
7570 char *pdata
= *ppdata
;
7572 struct smb_filename
*smb_fname
= NULL
;
7573 files_struct
*fsp
= NULL
;
7574 NTSTATUS status
= NT_STATUS_OK
;
7575 int data_return_size
= 0;
7578 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7582 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7583 if (total_params
< 4) {
7584 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7588 fsp
= file_fsp(req
, SVAL(params
,0));
7589 /* Basic check for non-null fsp. */
7590 if (!check_fsp_open(conn
, req
, fsp
)) {
7593 info_level
= SVAL(params
,2);
7595 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7597 if (!NT_STATUS_IS_OK(status
)) {
7598 reply_nterror(req
, status
);
7602 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7604 * This is actually a SETFILEINFO on a directory
7605 * handle (returned from an NT SMB). NT5.0 seems
7606 * to do this call. JRA.
7608 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7609 /* Always do lstat for UNIX calls. */
7610 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7611 DEBUG(3,("call_trans2setfilepathinfo: "
7612 "SMB_VFS_LSTAT of %s failed "
7614 smb_fname_str_dbg(smb_fname
),
7616 reply_nterror(req
, map_nt_error_from_unix(errno
));
7620 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7621 DEBUG(3,("call_trans2setfilepathinfo: "
7622 "fileinfo of %s failed (%s)\n",
7623 smb_fname_str_dbg(smb_fname
),
7625 reply_nterror(req
, map_nt_error_from_unix(errno
));
7629 } else if (fsp
->print_file
) {
7631 * Doing a DELETE_ON_CLOSE should cancel a print job.
7633 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7634 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7636 DEBUG(3,("call_trans2setfilepathinfo: "
7637 "Cancelling print job (%s)\n",
7641 send_trans2_replies(conn
, req
, params
, 2,
7647 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7652 * Original code - this is an open file.
7654 if (!check_fsp(conn
, req
, fsp
)) {
7658 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7659 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7660 "of fnum %d failed (%s)\n", fsp
->fnum
,
7662 reply_nterror(req
, map_nt_error_from_unix(errno
));
7670 if (total_params
< 7) {
7671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7675 info_level
= SVAL(params
,0);
7676 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7677 total_params
- 6, STR_TERMINATE
,
7679 if (!NT_STATUS_IS_OK(status
)) {
7680 reply_nterror(req
, status
);
7684 status
= filename_convert(req
, conn
,
7685 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7690 if (!NT_STATUS_IS_OK(status
)) {
7691 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7692 reply_botherror(req
,
7693 NT_STATUS_PATH_NOT_COVERED
,
7694 ERRSRV
, ERRbadpath
);
7697 reply_nterror(req
, status
);
7701 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7703 * For CIFS UNIX extensions the target name may not exist.
7706 /* Always do lstat for UNIX calls. */
7707 SMB_VFS_LSTAT(conn
, smb_fname
);
7709 } else if (!VALID_STAT(smb_fname
->st
) &&
7710 SMB_VFS_STAT(conn
, smb_fname
)) {
7711 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7713 smb_fname_str_dbg(smb_fname
),
7715 reply_nterror(req
, map_nt_error_from_unix(errno
));
7720 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7721 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7722 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7724 /* Realloc the parameter size */
7725 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7726 if (*pparams
== NULL
) {
7727 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7734 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7740 if (!NT_STATUS_IS_OK(status
)) {
7741 if (open_was_deferred(req
->mid
)) {
7742 /* We have re-scheduled this call. */
7745 if (blocking_lock_was_deferred(req
->mid
)) {
7746 /* We have re-scheduled this call. */
7749 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7750 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7751 ERRSRV
, ERRbadpath
);
7754 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7755 reply_openerror(req
, status
);
7759 reply_nterror(req
, status
);
7763 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7769 /****************************************************************************
7770 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7771 ****************************************************************************/
7773 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7774 char **pparams
, int total_params
,
7775 char **ppdata
, int total_data
,
7776 unsigned int max_data_bytes
)
7778 struct smb_filename
*smb_dname
= NULL
;
7779 char *params
= *pparams
;
7780 char *pdata
= *ppdata
;
7781 char *directory
= NULL
;
7782 NTSTATUS status
= NT_STATUS_OK
;
7783 struct ea_list
*ea_list
= NULL
;
7784 TALLOC_CTX
*ctx
= talloc_tos();
7786 if (!CAN_WRITE(conn
)) {
7787 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7791 if (total_params
< 5) {
7792 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7796 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7797 total_params
- 4, STR_TERMINATE
,
7799 if (!NT_STATUS_IS_OK(status
)) {
7800 reply_nterror(req
, status
);
7804 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7806 status
= filename_convert(ctx
,
7808 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7814 if (!NT_STATUS_IS_OK(status
)) {
7815 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7816 reply_botherror(req
,
7817 NT_STATUS_PATH_NOT_COVERED
,
7818 ERRSRV
, ERRbadpath
);
7821 reply_nterror(req
, status
);
7826 * OS/2 workplace shell seems to send SET_EA requests of "null"
7827 * length (4 bytes containing IVAL 4).
7828 * They seem to have no effect. Bug #3212. JRA.
7831 if (total_data
&& (total_data
!= 4)) {
7832 /* Any data in this call is an EA list. */
7833 if (total_data
< 10) {
7834 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7838 if (IVAL(pdata
,0) > total_data
) {
7839 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7840 IVAL(pdata
,0), (unsigned int)total_data
));
7841 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7845 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7852 if (!lp_ea_support(SNUM(conn
))) {
7853 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7857 /* If total_data == 4 Windows doesn't care what values
7858 * are placed in that field, it just ignores them.
7859 * The System i QNTC IBM SMB client puts bad values here,
7860 * so ignore them. */
7862 status
= create_directory(conn
, req
, smb_dname
);
7864 if (!NT_STATUS_IS_OK(status
)) {
7865 reply_nterror(req
, status
);
7869 /* Try and set any given EA. */
7871 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7872 if (!NT_STATUS_IS_OK(status
)) {
7873 reply_nterror(req
, status
);
7878 /* Realloc the parameter and data sizes */
7879 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7880 if(*pparams
== NULL
) {
7881 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7888 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7891 TALLOC_FREE(smb_dname
);
7895 /****************************************************************************
7896 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7897 We don't actually do this - we just send a null response.
7898 ****************************************************************************/
7900 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7901 struct smb_request
*req
,
7902 char **pparams
, int total_params
,
7903 char **ppdata
, int total_data
,
7904 unsigned int max_data_bytes
)
7906 char *params
= *pparams
;
7909 if (total_params
< 6) {
7910 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7914 info_level
= SVAL(params
,4);
7915 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7917 switch (info_level
) {
7922 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7926 /* Realloc the parameter and data sizes */
7927 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7928 if (*pparams
== NULL
) {
7929 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7934 SSVAL(params
,0,fnf_handle
);
7935 SSVAL(params
,2,0); /* No changes */
7936 SSVAL(params
,4,0); /* No EA errors */
7943 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7948 /****************************************************************************
7949 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7950 changes). Currently this does nothing.
7951 ****************************************************************************/
7953 static void call_trans2findnotifynext(connection_struct
*conn
,
7954 struct smb_request
*req
,
7955 char **pparams
, int total_params
,
7956 char **ppdata
, int total_data
,
7957 unsigned int max_data_bytes
)
7959 char *params
= *pparams
;
7961 DEBUG(3,("call_trans2findnotifynext\n"));
7963 /* Realloc the parameter and data sizes */
7964 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7965 if (*pparams
== NULL
) {
7966 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7971 SSVAL(params
,0,0); /* No changes */
7972 SSVAL(params
,2,0); /* No EA errors */
7974 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7979 /****************************************************************************
7980 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7981 ****************************************************************************/
7983 static void call_trans2getdfsreferral(connection_struct
*conn
,
7984 struct smb_request
*req
,
7985 char **pparams
, int total_params
,
7986 char **ppdata
, int total_data
,
7987 unsigned int max_data_bytes
)
7989 char *params
= *pparams
;
7990 char *pathname
= NULL
;
7992 int max_referral_level
;
7993 NTSTATUS status
= NT_STATUS_OK
;
7994 TALLOC_CTX
*ctx
= talloc_tos();
7996 DEBUG(10,("call_trans2getdfsreferral\n"));
7998 if (total_params
< 3) {
7999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8003 max_referral_level
= SVAL(params
,0);
8005 if(!lp_host_msdfs()) {
8006 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8010 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8011 total_params
- 2, STR_TERMINATE
);
8013 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8016 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8017 ppdata
,&status
)) < 0) {
8018 reply_nterror(req
, status
);
8022 SSVAL(req
->inbuf
, smb_flg2
,
8023 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8024 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8029 #define LMCAT_SPL 0x53
8030 #define LMFUNC_GETJOBID 0x60
8032 /****************************************************************************
8033 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8034 ****************************************************************************/
8036 static void call_trans2ioctl(connection_struct
*conn
,
8037 struct smb_request
*req
,
8038 char **pparams
, int total_params
,
8039 char **ppdata
, int total_data
,
8040 unsigned int max_data_bytes
)
8042 char *pdata
= *ppdata
;
8043 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8045 /* check for an invalid fid before proceeding */
8048 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8052 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8053 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8054 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8055 if (*ppdata
== NULL
) {
8056 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8061 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8062 CAN ACCEPT THIS IN UNICODE. JRA. */
8064 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8065 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8066 global_myname(), 15,
8067 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8068 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8069 lp_servicename(SNUM(conn
)), 13,
8070 STR_ASCII
|STR_TERMINATE
); /* Service name */
8071 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8076 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8077 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8080 /****************************************************************************
8081 Reply to a SMBfindclose (stop trans2 directory search).
8082 ****************************************************************************/
8084 void reply_findclose(struct smb_request
*req
)
8087 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8089 START_PROFILE(SMBfindclose
);
8092 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8093 END_PROFILE(SMBfindclose
);
8097 dptr_num
= SVALS(req
->vwv
+0, 0);
8099 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8101 dptr_close(sconn
, &dptr_num
);
8103 reply_outbuf(req
, 0, 0);
8105 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8107 END_PROFILE(SMBfindclose
);
8111 /****************************************************************************
8112 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8113 ****************************************************************************/
8115 void reply_findnclose(struct smb_request
*req
)
8119 START_PROFILE(SMBfindnclose
);
8122 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8123 END_PROFILE(SMBfindnclose
);
8127 dptr_num
= SVAL(req
->vwv
+0, 0);
8129 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8131 /* We never give out valid handles for a
8132 findnotifyfirst - so any dptr_num is ok here.
8135 reply_outbuf(req
, 0, 0);
8137 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8139 END_PROFILE(SMBfindnclose
);
8143 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8144 struct trans_state
*state
)
8146 if (get_Protocol() >= PROTOCOL_NT1
) {
8147 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8148 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8151 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8152 if (state
->call
!= TRANSACT2_QFSINFO
&&
8153 state
->call
!= TRANSACT2_SETFSINFO
) {
8154 DEBUG(0,("handle_trans2: encryption required "
8156 (unsigned int)state
->call
));
8157 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8162 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8164 /* Now we must call the relevant TRANS2 function */
8165 switch(state
->call
) {
8166 case TRANSACT2_OPEN
:
8168 START_PROFILE(Trans2_open
);
8169 call_trans2open(conn
, req
,
8170 &state
->param
, state
->total_param
,
8171 &state
->data
, state
->total_data
,
8172 state
->max_data_return
);
8173 END_PROFILE(Trans2_open
);
8177 case TRANSACT2_FINDFIRST
:
8179 START_PROFILE(Trans2_findfirst
);
8180 call_trans2findfirst(conn
, req
,
8181 &state
->param
, state
->total_param
,
8182 &state
->data
, state
->total_data
,
8183 state
->max_data_return
);
8184 END_PROFILE(Trans2_findfirst
);
8188 case TRANSACT2_FINDNEXT
:
8190 START_PROFILE(Trans2_findnext
);
8191 call_trans2findnext(conn
, req
,
8192 &state
->param
, state
->total_param
,
8193 &state
->data
, state
->total_data
,
8194 state
->max_data_return
);
8195 END_PROFILE(Trans2_findnext
);
8199 case TRANSACT2_QFSINFO
:
8201 START_PROFILE(Trans2_qfsinfo
);
8202 call_trans2qfsinfo(conn
, req
,
8203 &state
->param
, state
->total_param
,
8204 &state
->data
, state
->total_data
,
8205 state
->max_data_return
);
8206 END_PROFILE(Trans2_qfsinfo
);
8210 case TRANSACT2_SETFSINFO
:
8212 START_PROFILE(Trans2_setfsinfo
);
8213 call_trans2setfsinfo(conn
, req
,
8214 &state
->param
, state
->total_param
,
8215 &state
->data
, state
->total_data
,
8216 state
->max_data_return
);
8217 END_PROFILE(Trans2_setfsinfo
);
8221 case TRANSACT2_QPATHINFO
:
8222 case TRANSACT2_QFILEINFO
:
8224 START_PROFILE(Trans2_qpathinfo
);
8225 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8226 &state
->param
, state
->total_param
,
8227 &state
->data
, state
->total_data
,
8228 state
->max_data_return
);
8229 END_PROFILE(Trans2_qpathinfo
);
8233 case TRANSACT2_SETPATHINFO
:
8234 case TRANSACT2_SETFILEINFO
:
8236 START_PROFILE(Trans2_setpathinfo
);
8237 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8238 &state
->param
, state
->total_param
,
8239 &state
->data
, state
->total_data
,
8240 state
->max_data_return
);
8241 END_PROFILE(Trans2_setpathinfo
);
8245 case TRANSACT2_FINDNOTIFYFIRST
:
8247 START_PROFILE(Trans2_findnotifyfirst
);
8248 call_trans2findnotifyfirst(conn
, req
,
8249 &state
->param
, state
->total_param
,
8250 &state
->data
, state
->total_data
,
8251 state
->max_data_return
);
8252 END_PROFILE(Trans2_findnotifyfirst
);
8256 case TRANSACT2_FINDNOTIFYNEXT
:
8258 START_PROFILE(Trans2_findnotifynext
);
8259 call_trans2findnotifynext(conn
, req
,
8260 &state
->param
, state
->total_param
,
8261 &state
->data
, state
->total_data
,
8262 state
->max_data_return
);
8263 END_PROFILE(Trans2_findnotifynext
);
8267 case TRANSACT2_MKDIR
:
8269 START_PROFILE(Trans2_mkdir
);
8270 call_trans2mkdir(conn
, req
,
8271 &state
->param
, state
->total_param
,
8272 &state
->data
, state
->total_data
,
8273 state
->max_data_return
);
8274 END_PROFILE(Trans2_mkdir
);
8278 case TRANSACT2_GET_DFS_REFERRAL
:
8280 START_PROFILE(Trans2_get_dfs_referral
);
8281 call_trans2getdfsreferral(conn
, req
,
8282 &state
->param
, state
->total_param
,
8283 &state
->data
, state
->total_data
,
8284 state
->max_data_return
);
8285 END_PROFILE(Trans2_get_dfs_referral
);
8289 case TRANSACT2_IOCTL
:
8291 START_PROFILE(Trans2_ioctl
);
8292 call_trans2ioctl(conn
, req
,
8293 &state
->param
, state
->total_param
,
8294 &state
->data
, state
->total_data
,
8295 state
->max_data_return
);
8296 END_PROFILE(Trans2_ioctl
);
8301 /* Error in request */
8302 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8303 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8307 /****************************************************************************
8308 Reply to a SMBtrans2.
8309 ****************************************************************************/
8311 void reply_trans2(struct smb_request
*req
)
8313 connection_struct
*conn
= req
->conn
;
8318 unsigned int tran_call
;
8319 struct trans_state
*state
;
8322 START_PROFILE(SMBtrans2
);
8324 if (req
->wct
< 14) {
8325 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8326 END_PROFILE(SMBtrans2
);
8330 dsoff
= SVAL(req
->vwv
+12, 0);
8331 dscnt
= SVAL(req
->vwv
+11, 0);
8332 psoff
= SVAL(req
->vwv
+10, 0);
8333 pscnt
= SVAL(req
->vwv
+9, 0);
8334 tran_call
= SVAL(req
->vwv
+14, 0);
8336 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8337 if (!NT_STATUS_IS_OK(result
)) {
8338 DEBUG(2, ("Got invalid trans2 request: %s\n",
8339 nt_errstr(result
)));
8340 reply_nterror(req
, result
);
8341 END_PROFILE(SMBtrans2
);
8346 switch (tran_call
) {
8347 /* List the allowed trans2 calls on IPC$ */
8348 case TRANSACT2_OPEN
:
8349 case TRANSACT2_GET_DFS_REFERRAL
:
8350 case TRANSACT2_QFILEINFO
:
8351 case TRANSACT2_QFSINFO
:
8352 case TRANSACT2_SETFSINFO
:
8355 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8356 END_PROFILE(SMBtrans2
);
8361 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8362 DEBUG(0, ("talloc failed\n"));
8363 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8364 END_PROFILE(SMBtrans2
);
8368 state
->cmd
= SMBtrans2
;
8370 state
->mid
= req
->mid
;
8371 state
->vuid
= req
->vuid
;
8372 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8373 state
->setup
= NULL
;
8374 state
->total_param
= SVAL(req
->vwv
+0, 0);
8375 state
->param
= NULL
;
8376 state
->total_data
= SVAL(req
->vwv
+1, 0);
8378 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8379 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8380 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8381 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8382 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8384 state
->call
= tran_call
;
8386 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8387 is so as a sanity check */
8388 if (state
->setup_count
!= 1) {
8390 * Need to have rc=0 for ioctl to get job id for OS/2.
8391 * Network printing will fail if function is not successful.
8392 * Similar function in reply.c will be used if protocol
8393 * is LANMAN1.0 instead of LM1.2X002.
8394 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8395 * outbuf doesn't have to be set(only job id is used).
8397 if ( (state
->setup_count
== 4)
8398 && (tran_call
== TRANSACT2_IOCTL
)
8399 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8400 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8401 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8403 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8404 DEBUG(2,("Transaction is %d\n",tran_call
));
8406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8407 END_PROFILE(SMBtrans2
);
8412 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8415 if (state
->total_data
) {
8417 if (trans_oob(state
->total_data
, 0, dscnt
)
8418 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8422 /* Can't use talloc here, the core routines do realloc on the
8423 * params and data. */
8424 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8425 if (state
->data
== NULL
) {
8426 DEBUG(0,("reply_trans2: data malloc fail for %u "
8427 "bytes !\n", (unsigned int)state
->total_data
));
8429 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8430 END_PROFILE(SMBtrans2
);
8434 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8437 if (state
->total_param
) {
8439 if (trans_oob(state
->total_param
, 0, pscnt
)
8440 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8444 /* Can't use talloc here, the core routines do realloc on the
8445 * params and data. */
8446 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8447 if (state
->param
== NULL
) {
8448 DEBUG(0,("reply_trans: param malloc fail for %u "
8449 "bytes !\n", (unsigned int)state
->total_param
));
8450 SAFE_FREE(state
->data
);
8452 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8453 END_PROFILE(SMBtrans2
);
8457 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8460 state
->received_data
= dscnt
;
8461 state
->received_param
= pscnt
;
8463 if ((state
->received_param
== state
->total_param
) &&
8464 (state
->received_data
== state
->total_data
)) {
8466 handle_trans2(conn
, req
, state
);
8468 SAFE_FREE(state
->data
);
8469 SAFE_FREE(state
->param
);
8471 END_PROFILE(SMBtrans2
);
8475 DLIST_ADD(conn
->pending_trans
, state
);
8477 /* We need to send an interim response then receive the rest
8478 of the parameter/data bytes */
8479 reply_outbuf(req
, 0, 0);
8480 show_msg((char *)req
->outbuf
);
8481 END_PROFILE(SMBtrans2
);
8486 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8487 SAFE_FREE(state
->data
);
8488 SAFE_FREE(state
->param
);
8490 END_PROFILE(SMBtrans2
);
8491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8495 /****************************************************************************
8496 Reply to a SMBtranss2
8497 ****************************************************************************/
8499 void reply_transs2(struct smb_request
*req
)
8501 connection_struct
*conn
= req
->conn
;
8502 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8503 struct trans_state
*state
;
8505 START_PROFILE(SMBtranss2
);
8507 show_msg((char *)req
->inbuf
);
8510 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8511 END_PROFILE(SMBtranss2
);
8515 for (state
= conn
->pending_trans
; state
!= NULL
;
8516 state
= state
->next
) {
8517 if (state
->mid
== req
->mid
) {
8522 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8523 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8524 END_PROFILE(SMBtranss2
);
8528 /* Revise state->total_param and state->total_data in case they have
8529 changed downwards */
8531 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8532 state
->total_param
= SVAL(req
->vwv
+0, 0);
8533 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8534 state
->total_data
= SVAL(req
->vwv
+1, 0);
8536 pcnt
= SVAL(req
->vwv
+2, 0);
8537 poff
= SVAL(req
->vwv
+3, 0);
8538 pdisp
= SVAL(req
->vwv
+4, 0);
8540 dcnt
= SVAL(req
->vwv
+5, 0);
8541 doff
= SVAL(req
->vwv
+6, 0);
8542 ddisp
= SVAL(req
->vwv
+7, 0);
8544 state
->received_param
+= pcnt
;
8545 state
->received_data
+= dcnt
;
8547 if ((state
->received_data
> state
->total_data
) ||
8548 (state
->received_param
> state
->total_param
))
8552 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8553 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8556 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8560 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8561 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8564 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8567 if ((state
->received_param
< state
->total_param
) ||
8568 (state
->received_data
< state
->total_data
)) {
8569 END_PROFILE(SMBtranss2
);
8573 handle_trans2(conn
, req
, state
);
8575 DLIST_REMOVE(conn
->pending_trans
, state
);
8576 SAFE_FREE(state
->data
);
8577 SAFE_FREE(state
->param
);
8580 END_PROFILE(SMBtranss2
);
8585 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8586 DLIST_REMOVE(conn
->pending_trans
, state
);
8587 SAFE_FREE(state
->data
);
8588 SAFE_FREE(state
->param
);
8590 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8591 END_PROFILE(SMBtranss2
);