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 extern enum protocol_types Protocol
;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
52 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name
)
72 static const char * const prohibited_ea_names
[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME
,
74 SAMBA_XATTR_DOS_ATTRIB
,
75 SAMBA_XATTR_DOSTIMESTAMPS
,
82 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
83 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
86 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
87 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
93 /****************************************************************************
94 Get one EA value. Fill in a struct ea_struct.
95 ****************************************************************************/
97 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
98 files_struct
*fsp
, const char *fname
,
99 const char *ea_name
, struct ea_struct
*pea
)
101 /* Get the value of this xattr. Max size is 64k. */
102 size_t attr_size
= 256;
108 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
110 return NT_STATUS_NO_MEMORY
;
113 if (fsp
&& fsp
->fh
->fd
!= -1) {
114 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
116 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
119 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
125 return map_nt_error_from_unix(errno
);
128 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
129 dump_data(10, (uint8
*)val
, sizeret
);
132 if (strnequal(ea_name
, "user.", 5)) {
133 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
135 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
137 if (pea
->name
== NULL
) {
139 return NT_STATUS_NO_MEMORY
;
141 pea
->value
.data
= (unsigned char *)val
;
142 pea
->value
.length
= (size_t)sizeret
;
146 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
147 files_struct
*fsp
, const char *fname
,
148 char ***pnames
, size_t *pnum_names
)
150 /* Get a list of all xattrs. Max namesize is 64k. */
151 size_t ea_namelist_size
= 1024;
152 char *ea_namelist
= NULL
;
157 ssize_t sizeret
= -1;
159 if (!lp_ea_support(SNUM(conn
))) {
168 * TALLOC the result early to get the talloc hierarchy right.
171 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
173 DEBUG(0, ("talloc failed\n"));
174 return NT_STATUS_NO_MEMORY
;
177 while (ea_namelist_size
<= 65536) {
179 ea_namelist
= TALLOC_REALLOC_ARRAY(
180 names
, ea_namelist
, char, ea_namelist_size
);
181 if (ea_namelist
== NULL
) {
182 DEBUG(0, ("talloc failed\n"));
184 return NT_STATUS_NO_MEMORY
;
187 if (fsp
&& fsp
->fh
->fd
!= -1) {
188 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
191 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
195 if ((sizeret
== -1) && (errno
== ERANGE
)) {
196 ea_namelist_size
*= 2;
205 return map_nt_error_from_unix(errno
);
208 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
209 (unsigned int)sizeret
));
221 * Ensure the result is 0-terminated
224 if (ea_namelist
[sizeret
-1] != '\0') {
226 return NT_STATUS_INTERNAL_ERROR
;
234 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
238 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
240 DEBUG(0, ("talloc failed\n"));
242 return NT_STATUS_NO_MEMORY
;
248 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
249 names
[num_names
++] = p
;
257 *pnum_names
= num_names
;
261 /****************************************************************************
262 Return a linked list of the total EA's. Plus the total size
263 ****************************************************************************/
265 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
266 const char *fname
, size_t *pea_total_len
)
268 /* Get a list of all xattrs. Max namesize is 64k. */
271 struct ea_list
*ea_list_head
= NULL
;
276 if (!lp_ea_support(SNUM(conn
))) {
280 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
283 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
287 for (i
=0; i
<num_names
; i
++) {
288 struct ea_list
*listp
;
291 if (strnequal(names
[i
], "system.", 7)
292 || samba_private_attr_name(names
[i
]))
295 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
300 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
306 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
309 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
311 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
312 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
313 (unsigned int)listp
->ea
.value
.length
));
315 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
319 /* Add on 4 for total length. */
320 if (*pea_total_len
) {
324 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
325 (unsigned int)*pea_total_len
));
330 /****************************************************************************
331 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
333 ****************************************************************************/
335 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
336 connection_struct
*conn
, struct ea_list
*ea_list
)
338 unsigned int ret_data_size
= 4;
341 SMB_ASSERT(total_data_size
>= 4);
343 if (!lp_ea_support(SNUM(conn
))) {
348 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
351 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
352 dos_namelen
= strlen(dos_ea_name
);
353 if (dos_namelen
> 255 || dos_namelen
== 0) {
356 if (ea_list
->ea
.value
.length
> 65535) {
359 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
363 /* We know we have room. */
364 SCVAL(p
,0,ea_list
->ea
.flags
);
365 SCVAL(p
,1,dos_namelen
);
366 SSVAL(p
,2,ea_list
->ea
.value
.length
);
367 fstrcpy(p
+4, dos_ea_name
);
368 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
370 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
371 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
374 ret_data_size
= PTR_DIFF(p
, pdata
);
375 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
376 SIVAL(pdata
,0,ret_data_size
);
377 return ret_data_size
;
380 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
382 unsigned int total_data_size
,
383 unsigned int *ret_data_size
,
384 connection_struct
*conn
,
385 struct ea_list
*ea_list
)
387 uint8_t *p
= (uint8_t *)pdata
;
388 uint8_t *last_start
= NULL
;
392 if (!lp_ea_support(SNUM(conn
))) {
393 return NT_STATUS_NO_EAS_ON_FILE
;
396 for (; ea_list
; ea_list
= ea_list
->next
) {
402 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
406 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
407 dos_namelen
= strlen(dos_ea_name
);
408 if (dos_namelen
> 255 || dos_namelen
== 0) {
409 return NT_STATUS_INTERNAL_ERROR
;
411 if (ea_list
->ea
.value
.length
> 65535) {
412 return NT_STATUS_INTERNAL_ERROR
;
415 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
418 size_t pad
= 4 - (this_size
% 4);
422 if (this_size
> total_data_size
) {
423 return NT_STATUS_INFO_LENGTH_MISMATCH
;
426 /* We know we have room. */
427 SIVAL(p
, 0x00, 0); /* next offset */
428 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
429 SCVAL(p
, 0x05, dos_namelen
);
430 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
431 fstrcpy((char *)(p
+0x08), dos_ea_name
);
432 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
434 total_data_size
-= this_size
;
438 *ret_data_size
= PTR_DIFF(p
, pdata
);
439 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
443 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
445 size_t total_ea_len
= 0;
446 TALLOC_CTX
*mem_ctx
= NULL
;
448 if (!lp_ea_support(SNUM(conn
))) {
451 mem_ctx
= talloc_tos();
452 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
456 /****************************************************************************
457 Ensure the EA name is case insensitive by matching any existing EA name.
458 ****************************************************************************/
460 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
463 TALLOC_CTX
*mem_ctx
= talloc_tos();
464 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
466 for (; ea_list
; ea_list
= ea_list
->next
) {
467 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
468 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
469 &unix_ea_name
[5], ea_list
->ea
.name
));
470 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
476 /****************************************************************************
477 Set or delete an extended attribute.
478 ****************************************************************************/
480 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
481 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
485 if (!lp_ea_support(SNUM(conn
))) {
486 return NT_STATUS_EAS_NOT_SUPPORTED
;
489 /* For now setting EAs on streams isn't supported. */
490 fname
= smb_fname
->base_name
;
492 for (;ea_list
; ea_list
= ea_list
->next
) {
494 fstring unix_ea_name
;
496 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
497 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
499 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
501 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
503 if (samba_private_attr_name(unix_ea_name
)) {
504 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
505 return NT_STATUS_ACCESS_DENIED
;
508 if (ea_list
->ea
.value
.length
== 0) {
509 /* Remove the attribute. */
510 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
511 DEBUG(10,("set_ea: deleting ea name %s on "
512 "file %s by file descriptor.\n",
513 unix_ea_name
, fsp_str_dbg(fsp
)));
514 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
516 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
517 unix_ea_name
, fname
));
518 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
521 /* Removing a non existent attribute always succeeds. */
522 if (ret
== -1 && errno
== ENOATTR
) {
523 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
529 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
530 DEBUG(10,("set_ea: setting ea name %s on file "
531 "%s by file descriptor.\n",
532 unix_ea_name
, fsp_str_dbg(fsp
)));
533 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
534 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
536 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
537 unix_ea_name
, fname
));
538 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
539 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
545 if (errno
== ENOTSUP
) {
546 return NT_STATUS_EAS_NOT_SUPPORTED
;
549 return map_nt_error_from_unix(errno
);
555 /****************************************************************************
556 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
557 ****************************************************************************/
559 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
561 struct ea_list
*ea_list_head
= NULL
;
562 size_t converted_size
, offset
= 0;
564 while (offset
+ 2 < data_size
) {
565 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
566 unsigned int namelen
= CVAL(pdata
,offset
);
568 offset
++; /* Go past the namelen byte. */
570 /* integer wrap paranioa. */
571 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
572 (offset
> data_size
) || (namelen
> data_size
) ||
573 (offset
+ namelen
>= data_size
)) {
576 /* Ensure the name is null terminated. */
577 if (pdata
[offset
+ namelen
] != '\0') {
580 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
582 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
583 "failed: %s", strerror(errno
)));
589 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
590 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
591 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
597 /****************************************************************************
598 Read one EA list entry from the buffer.
599 ****************************************************************************/
601 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
603 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
605 unsigned int namelen
;
606 size_t converted_size
;
616 eal
->ea
.flags
= CVAL(pdata
,0);
617 namelen
= CVAL(pdata
,1);
618 val_len
= SVAL(pdata
,2);
620 if (4 + namelen
+ 1 + val_len
> data_size
) {
624 /* Ensure the name is null terminated. */
625 if (pdata
[namelen
+ 4] != '\0') {
628 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
629 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
636 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
637 if (!eal
->ea
.value
.data
) {
641 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
643 /* Ensure we're null terminated just in case we print the value. */
644 eal
->ea
.value
.data
[val_len
] = '\0';
645 /* But don't count the null. */
646 eal
->ea
.value
.length
--;
649 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
652 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
653 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
658 /****************************************************************************
659 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
660 ****************************************************************************/
662 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
664 struct ea_list
*ea_list_head
= NULL
;
666 size_t bytes_used
= 0;
668 while (offset
< data_size
) {
669 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
675 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
676 offset
+= bytes_used
;
682 /****************************************************************************
683 Count the total EA size needed.
684 ****************************************************************************/
686 static size_t ea_list_size(struct ea_list
*ealist
)
689 struct ea_list
*listp
;
692 for (listp
= ealist
; listp
; listp
= listp
->next
) {
693 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
694 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
696 /* Add on 4 for total length. */
704 /****************************************************************************
705 Return a union of EA's from a file list and a list of names.
706 The TALLOC context for the two lists *MUST* be identical as we steal
707 memory from one list to add to another. JRA.
708 ****************************************************************************/
710 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
712 struct ea_list
*nlistp
, *flistp
;
714 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
715 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
716 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
722 /* Copy the data from this entry. */
723 nlistp
->ea
.flags
= flistp
->ea
.flags
;
724 nlistp
->ea
.value
= flistp
->ea
.value
;
727 nlistp
->ea
.flags
= 0;
728 ZERO_STRUCT(nlistp
->ea
.value
);
732 *total_ea_len
= ea_list_size(name_list
);
736 /****************************************************************************
737 Send the required number of replies back.
738 We assume all fields other than the data fields are
739 set correctly for the type of call.
740 HACK ! Always assumes smb_setup field is zero.
741 ****************************************************************************/
743 void send_trans2_replies(connection_struct
*conn
,
744 struct smb_request
*req
,
751 /* As we are using a protocol > LANMAN1 then the max_send
752 variable must have been set in the sessetupX call.
753 This takes precedence over the max_xmit field in the
754 global struct. These different max_xmit variables should
755 be merged as this is now too confusing */
757 int data_to_send
= datasize
;
758 int params_to_send
= paramsize
;
760 const char *pp
= params
;
761 const char *pd
= pdata
;
762 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
763 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
764 int data_alignment_offset
= 0;
765 bool overflow
= False
;
766 struct smbd_server_connection
*sconn
= smbd_server_conn
;
767 int max_send
= sconn
->smb1
.sessions
.max_send
;
769 /* Modify the data_to_send and datasize and set the error if
770 we're trying to send more than max_data_bytes. We still send
771 the part of the packet(s) that fit. Strange, but needed
774 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
775 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
776 max_data_bytes
, datasize
));
777 datasize
= data_to_send
= max_data_bytes
;
781 /* If there genuinely are no parameters or data to send just send the empty packet */
783 if(params_to_send
== 0 && data_to_send
== 0) {
784 reply_outbuf(req
, 10, 0);
785 show_msg((char *)req
->outbuf
);
786 if (!srv_send_smb(smbd_server_fd(),
789 IS_CONN_ENCRYPTED(conn
),
791 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
793 TALLOC_FREE(req
->outbuf
);
797 /* When sending params and data ensure that both are nicely aligned */
798 /* Only do this alignment when there is also data to send - else
799 can cause NT redirector problems. */
801 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
802 data_alignment_offset
= 4 - (params_to_send
% 4);
804 /* Space is bufsize minus Netbios over TCP header minus SMB header */
805 /* The alignment_offset is to align the param bytes on an even byte
806 boundary. NT 4.0 Beta needs this to work correctly. */
808 useable_space
= max_send
- (smb_size
811 + data_alignment_offset
);
813 if (useable_space
< 0) {
814 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
815 "= %d!!!", useable_space
));
816 exit_server_cleanly("send_trans2_replies: Not enough space");
819 while (params_to_send
|| data_to_send
) {
820 /* Calculate whether we will totally or partially fill this packet */
822 total_sent_thistime
= params_to_send
+ data_to_send
;
824 /* We can never send more than useable_space */
826 * Note that 'useable_space' does not include the alignment offsets,
827 * but we must include the alignment offsets in the calculation of
828 * the length of the data we send over the wire, as the alignment offsets
829 * are sent here. Fix from Marc_Jacobsen@hp.com.
832 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
834 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
835 + data_alignment_offset
);
838 * We might have SMBtrans2s in req which was transferred to
839 * the outbuf, fix that.
841 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
843 /* Set total params and data to be sent */
844 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
845 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
847 /* Calculate how many parameters and data we can fit into
848 * this packet. Parameters get precedence
851 params_sent_thistime
= MIN(params_to_send
,useable_space
);
852 data_sent_thistime
= useable_space
- params_sent_thistime
;
853 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
855 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
857 /* smb_proff is the offset from the start of the SMB header to the
858 parameter bytes, however the first 4 bytes of outbuf are
859 the Netbios over TCP header. Thus use smb_base() to subtract
860 them from the calculation */
862 SSVAL(req
->outbuf
,smb_proff
,
863 ((smb_buf(req
->outbuf
)+alignment_offset
)
864 - smb_base(req
->outbuf
)));
866 if(params_sent_thistime
== 0)
867 SSVAL(req
->outbuf
,smb_prdisp
,0);
869 /* Absolute displacement of param bytes sent in this packet */
870 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
872 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
873 if(data_sent_thistime
== 0) {
874 SSVAL(req
->outbuf
,smb_droff
,0);
875 SSVAL(req
->outbuf
,smb_drdisp
, 0);
877 /* The offset of the data bytes is the offset of the
878 parameter bytes plus the number of parameters being sent this time */
879 SSVAL(req
->outbuf
, smb_droff
,
880 ((smb_buf(req
->outbuf
)+alignment_offset
)
881 - smb_base(req
->outbuf
))
882 + params_sent_thistime
+ data_alignment_offset
);
883 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
886 /* Initialize the padding for alignment */
888 if (alignment_offset
!= 0) {
889 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
892 /* Copy the param bytes into the packet */
894 if(params_sent_thistime
) {
895 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
896 params_sent_thistime
);
899 /* Copy in the data bytes */
900 if(data_sent_thistime
) {
901 if (data_alignment_offset
!= 0) {
902 memset((smb_buf(req
->outbuf
)+alignment_offset
+
903 params_sent_thistime
), 0,
904 data_alignment_offset
);
906 memcpy(smb_buf(req
->outbuf
)+alignment_offset
907 +params_sent_thistime
+data_alignment_offset
,
908 pd
,data_sent_thistime
);
911 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
912 params_sent_thistime
, data_sent_thistime
, useable_space
));
913 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
914 params_to_send
, data_to_send
, paramsize
, datasize
));
917 error_packet_set((char *)req
->outbuf
,
918 ERRDOS
,ERRbufferoverflow
,
919 STATUS_BUFFER_OVERFLOW
,
923 /* Send the packet */
924 show_msg((char *)req
->outbuf
);
925 if (!srv_send_smb(smbd_server_fd(),
928 IS_CONN_ENCRYPTED(conn
),
930 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
932 TALLOC_FREE(req
->outbuf
);
934 pp
+= params_sent_thistime
;
935 pd
+= data_sent_thistime
;
937 params_to_send
-= params_sent_thistime
;
938 data_to_send
-= data_sent_thistime
;
941 if(params_to_send
< 0 || data_to_send
< 0) {
942 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
943 params_to_send
, data_to_send
));
951 /****************************************************************************
952 Reply to a TRANSACT2_OPEN.
953 ****************************************************************************/
955 static void call_trans2open(connection_struct
*conn
,
956 struct smb_request
*req
,
957 char **pparams
, int total_params
,
958 char **ppdata
, int total_data
,
959 unsigned int max_data_bytes
)
961 struct smb_filename
*smb_fname
= NULL
;
962 char *params
= *pparams
;
963 char *pdata
= *ppdata
;
968 bool return_additional_info
;
981 struct ea_list
*ea_list
= NULL
;
986 uint32 create_disposition
;
987 uint32 create_options
= 0;
988 TALLOC_CTX
*ctx
= talloc_tos();
991 * Ensure we have enough parameters to perform the operation.
994 if (total_params
< 29) {
995 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
999 flags
= SVAL(params
, 0);
1000 deny_mode
= SVAL(params
, 2);
1001 open_attr
= SVAL(params
,6);
1002 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1003 if (oplock_request
) {
1004 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1008 return_additional_info
= BITSETW(params
,0);
1009 open_sattr
= SVAL(params
, 4);
1010 open_time
= make_unix_date3(params
+8);
1012 open_ofun
= SVAL(params
,12);
1013 open_size
= IVAL(params
,14);
1014 pname
= ¶ms
[28];
1017 reply_doserror(req
, ERRSRV
, ERRaccess
);
1021 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1022 total_params
- 28, STR_TERMINATE
,
1024 if (!NT_STATUS_IS_OK(status
)) {
1025 reply_nterror(req
, status
);
1029 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1030 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1031 (unsigned int)open_ofun
, open_size
));
1033 status
= filename_convert(ctx
,
1035 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1040 if (!NT_STATUS_IS_OK(status
)) {
1041 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1042 reply_botherror(req
,
1043 NT_STATUS_PATH_NOT_COVERED
,
1044 ERRSRV
, ERRbadpath
);
1047 reply_nterror(req
, status
);
1051 if (open_ofun
== 0) {
1052 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1056 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1057 &access_mask
, &share_mode
,
1058 &create_disposition
,
1060 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
1064 /* Any data in this call is an EA list. */
1065 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
1066 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1070 if (total_data
!= 4) {
1071 if (total_data
< 10) {
1072 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1076 if (IVAL(pdata
,0) > total_data
) {
1077 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1078 IVAL(pdata
,0), (unsigned int)total_data
));
1079 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1083 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1086 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1089 } else if (IVAL(pdata
,0) != 4) {
1090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1094 status
= SMB_VFS_CREATE_FILE(
1097 0, /* root_dir_fid */
1098 smb_fname
, /* fname */
1099 access_mask
, /* access_mask */
1100 share_mode
, /* share_access */
1101 create_disposition
, /* create_disposition*/
1102 create_options
, /* create_options */
1103 open_attr
, /* file_attributes */
1104 oplock_request
, /* oplock_request */
1105 open_size
, /* allocation_size */
1107 ea_list
, /* ea_list */
1109 &smb_action
); /* psbuf */
1111 if (!NT_STATUS_IS_OK(status
)) {
1112 if (open_was_deferred(req
->mid
)) {
1113 /* We have re-scheduled this call. */
1116 reply_openerror(req
, status
);
1120 size
= get_file_size_stat(&smb_fname
->st
);
1121 fattr
= dos_mode(conn
, smb_fname
);
1122 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1123 inode
= smb_fname
->st
.st_ex_ino
;
1125 close_file(req
, fsp
, ERROR_CLOSE
);
1126 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1130 /* Realloc the size of parameters and data we will return */
1131 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1132 if(*pparams
== NULL
) {
1133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1138 SSVAL(params
,0,fsp
->fnum
);
1139 SSVAL(params
,2,fattr
);
1140 srv_put_dos_date2(params
,4, mtime
);
1141 SIVAL(params
,8, (uint32
)size
);
1142 SSVAL(params
,12,deny_mode
);
1143 SSVAL(params
,14,0); /* open_type - file or directory. */
1144 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1146 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1147 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1150 SSVAL(params
,18,smb_action
);
1153 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1155 SIVAL(params
,20,inode
);
1156 SSVAL(params
,24,0); /* Padding. */
1158 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1159 fsp
->fsp_name
->base_name
);
1160 SIVAL(params
, 26, ea_size
);
1162 SIVAL(params
, 26, 0);
1165 /* Send the required number of replies */
1166 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1168 TALLOC_FREE(smb_fname
);
1171 /*********************************************************
1172 Routine to check if a given string matches exactly.
1173 as a special case a mask of "." does NOT match. That
1174 is required for correct wildcard semantics
1175 Case can be significant or not.
1176 **********************************************************/
1178 static bool exact_match(bool has_wild
,
1179 bool case_sensitive
,
1183 if (mask
[0] == '.' && mask
[1] == 0) {
1191 if (case_sensitive
) {
1192 return strcmp(str
,mask
)==0;
1194 return StrCaseCmp(str
,mask
) == 0;
1198 /****************************************************************************
1199 Return the filetype for UNIX extensions.
1200 ****************************************************************************/
1202 static uint32
unix_filetype(mode_t mode
)
1205 return UNIX_TYPE_FILE
;
1206 else if(S_ISDIR(mode
))
1207 return UNIX_TYPE_DIR
;
1209 else if(S_ISLNK(mode
))
1210 return UNIX_TYPE_SYMLINK
;
1213 else if(S_ISCHR(mode
))
1214 return UNIX_TYPE_CHARDEV
;
1217 else if(S_ISBLK(mode
))
1218 return UNIX_TYPE_BLKDEV
;
1221 else if(S_ISFIFO(mode
))
1222 return UNIX_TYPE_FIFO
;
1225 else if(S_ISSOCK(mode
))
1226 return UNIX_TYPE_SOCKET
;
1229 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1230 return UNIX_TYPE_UNKNOWN
;
1233 /****************************************************************************
1234 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1235 ****************************************************************************/
1237 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1239 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1240 const SMB_STRUCT_STAT
*psbuf
,
1242 enum perm_type ptype
,
1247 if (perms
== SMB_MODE_NO_CHANGE
) {
1248 if (!VALID_STAT(*psbuf
)) {
1249 return NT_STATUS_INVALID_PARAMETER
;
1251 *ret_perms
= psbuf
->st_ex_mode
;
1252 return NT_STATUS_OK
;
1256 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1257 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1258 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1259 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1260 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1261 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1262 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1263 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1264 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1266 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1269 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1272 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1277 /* Apply mode mask */
1278 ret
&= lp_create_mask(SNUM(conn
));
1279 /* Add in force bits */
1280 ret
|= lp_force_create_mode(SNUM(conn
));
1283 ret
&= lp_dir_mask(SNUM(conn
));
1284 /* Add in force bits */
1285 ret
|= lp_force_dir_mode(SNUM(conn
));
1287 case PERM_EXISTING_FILE
:
1288 /* Apply mode mask */
1289 ret
&= lp_security_mask(SNUM(conn
));
1290 /* Add in force bits */
1291 ret
|= lp_force_security_mode(SNUM(conn
));
1293 case PERM_EXISTING_DIR
:
1294 /* Apply mode mask */
1295 ret
&= lp_dir_security_mask(SNUM(conn
));
1296 /* Add in force bits */
1297 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1302 return NT_STATUS_OK
;
1305 /****************************************************************************
1306 Needed to show the msdfs symlinks as directories. Modifies psbuf
1307 to be a directory if it's a msdfs link.
1308 ****************************************************************************/
1310 static bool check_msdfs_link(connection_struct
*conn
,
1311 const char *pathname
,
1312 SMB_STRUCT_STAT
*psbuf
)
1314 int saved_errno
= errno
;
1315 if(lp_host_msdfs() &&
1316 lp_msdfs_root(SNUM(conn
)) &&
1317 is_msdfs_link(conn
, pathname
, psbuf
)) {
1319 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1322 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1323 errno
= saved_errno
;
1326 errno
= saved_errno
;
1331 /****************************************************************************
1332 Get a level dependent lanman2 dir entry.
1333 ****************************************************************************/
1335 struct smbd_dirptr_lanman2_state
{
1336 connection_struct
*conn
;
1337 uint32_t info_level
;
1338 bool check_mangled_names
;
1340 bool got_exact_match
;
1343 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1349 struct smbd_dirptr_lanman2_state
*state
=
1350 (struct smbd_dirptr_lanman2_state
*)private_data
;
1352 char mangled_name
[13]; /* mangled 8.3 name. */
1356 /* Mangle fname if it's an illegal name. */
1357 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1358 ok
= name_to_8_3(dname
, mangled_name
,
1359 true, state
->conn
->params
);
1363 fname
= mangled_name
;
1368 got_match
= exact_match(state
->has_wild
,
1369 state
->conn
->case_sensitive
,
1371 state
->got_exact_match
= got_match
;
1373 got_match
= mask_match(fname
, mask
,
1374 state
->conn
->case_sensitive
);
1377 if(!got_match
&& state
->check_mangled_names
&&
1378 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1380 * It turns out that NT matches wildcards against
1381 * both long *and* short names. This may explain some
1382 * of the wildcard wierdness from old DOS clients
1383 * that some people have been seeing.... JRA.
1385 /* Force the mangling into 8.3. */
1386 ok
= name_to_8_3(fname
, mangled_name
,
1387 false, state
->conn
->params
);
1392 got_match
= exact_match(state
->has_wild
,
1393 state
->conn
->case_sensitive
,
1394 mangled_name
, mask
);
1395 state
->got_exact_match
= got_match
;
1397 got_match
= mask_match(mangled_name
, mask
,
1398 state
->conn
->case_sensitive
);
1406 *_fname
= talloc_strdup(ctx
, fname
);
1407 if (*_fname
== NULL
) {
1414 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1416 struct smb_filename
*smb_fname
,
1419 struct smbd_dirptr_lanman2_state
*state
=
1420 (struct smbd_dirptr_lanman2_state
*)private_data
;
1421 bool ms_dfs_link
= false;
1424 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1425 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1426 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1427 "Couldn't lstat [%s] (%s)\n",
1428 smb_fname_str_dbg(smb_fname
),
1432 } else if (!VALID_STAT(smb_fname
->st
) &&
1433 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1434 /* Needed to show the msdfs symlinks as
1437 ms_dfs_link
= check_msdfs_link(state
->conn
,
1438 smb_fname
->base_name
,
1441 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1442 "Couldn't stat [%s] (%s)\n",
1443 smb_fname_str_dbg(smb_fname
),
1450 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1452 mode
= dos_mode(state
->conn
, smb_fname
);
1459 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1460 connection_struct
*conn
,
1462 uint32_t info_level
,
1463 struct ea_list
*name_list
,
1464 bool check_mangled_names
,
1465 bool requires_resume_key
,
1468 const struct smb_filename
*smb_fname
,
1469 uint64_t space_remaining
,
1476 uint64_t *last_entry_off
)
1478 char *p
, *q
, *pdata
= *ppdata
;
1480 uint64_t file_size
= 0;
1481 uint64_t allocation_size
= 0;
1483 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1484 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1485 time_t c_date
= (time_t)0;
1487 char *last_entry_ptr
;
1489 uint32_t nt_extmode
; /* Used for NT connections instead of mode */
1493 *out_of_space
= false;
1495 ZERO_STRUCT(mdate_ts
);
1496 ZERO_STRUCT(adate_ts
);
1497 ZERO_STRUCT(create_date_ts
);
1498 ZERO_STRUCT(cdate_ts
);
1500 if (!(mode
& aDIR
)) {
1501 file_size
= get_file_size_stat(&smb_fname
->st
);
1503 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1505 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1506 adate_ts
= smb_fname
->st
.st_ex_atime
;
1507 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1508 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1510 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1511 dos_filetime_timespec(&create_date_ts
);
1512 dos_filetime_timespec(&mdate_ts
);
1513 dos_filetime_timespec(&adate_ts
);
1514 dos_filetime_timespec(&cdate_ts
);
1517 create_date
= convert_timespec_to_time_t(create_date_ts
);
1518 mdate
= convert_timespec_to_time_t(mdate_ts
);
1519 adate
= convert_timespec_to_time_t(adate_ts
);
1520 c_date
= convert_timespec_to_time_t(cdate_ts
);
1522 /* align the record */
1523 off
= PTR_DIFF(pdata
, base_data
);
1524 pad
= (off
+ (align
-1)) & ~(align
-1);
1527 /* initialize padding to 0 */
1528 memset(pdata
, 0, pad
);
1529 space_remaining
-= pad
;
1538 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1540 switch (info_level
) {
1541 case SMB_FIND_INFO_STANDARD
:
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1543 if(requires_resume_key
) {
1547 srv_put_dos_date2(p
,0,create_date
);
1548 srv_put_dos_date2(p
,4,adate
);
1549 srv_put_dos_date2(p
,8,mdate
);
1550 SIVAL(p
,12,(uint32
)file_size
);
1551 SIVAL(p
,16,(uint32
)allocation_size
);
1555 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1556 p
+= ucs2_align(base_data
, p
, 0);
1558 len
= srvstr_push(base_data
, flags2
, p
,
1559 fname
, PTR_DIFF(end_data
, p
),
1561 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1563 SCVAL(nameptr
, -1, len
- 2);
1565 SCVAL(nameptr
, -1, 0);
1569 SCVAL(nameptr
, -1, len
- 1);
1571 SCVAL(nameptr
, -1, 0);
1577 case SMB_FIND_EA_SIZE
:
1578 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1579 if (requires_resume_key
) {
1583 srv_put_dos_date2(p
,0,create_date
);
1584 srv_put_dos_date2(p
,4,adate
);
1585 srv_put_dos_date2(p
,8,mdate
);
1586 SIVAL(p
,12,(uint32
)file_size
);
1587 SIVAL(p
,16,(uint32
)allocation_size
);
1590 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1591 smb_fname
->base_name
);
1592 SIVAL(p
,22,ea_size
); /* Extended attributes */
1596 len
= srvstr_push(base_data
, flags2
,
1597 p
, fname
, PTR_DIFF(end_data
, p
),
1598 STR_TERMINATE
| STR_NOALIGN
);
1599 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1612 SCVAL(nameptr
,0,len
);
1614 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1617 case SMB_FIND_EA_LIST
:
1619 struct ea_list
*file_list
= NULL
;
1622 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1626 if (requires_resume_key
) {
1630 srv_put_dos_date2(p
,0,create_date
);
1631 srv_put_dos_date2(p
,4,adate
);
1632 srv_put_dos_date2(p
,8,mdate
);
1633 SIVAL(p
,12,(uint32
)file_size
);
1634 SIVAL(p
,16,(uint32
)allocation_size
);
1636 p
+= 22; /* p now points to the EA area. */
1638 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1639 smb_fname
->base_name
,
1641 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1643 /* We need to determine if this entry will fit in the space available. */
1644 /* Max string size is 255 bytes. */
1645 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1646 *out_of_space
= true;
1647 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1648 return False
; /* Not finished - just out of space */
1651 /* Push the ea_data followed by the name. */
1652 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1654 len
= srvstr_push(base_data
, flags2
,
1655 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1656 STR_TERMINATE
| STR_NOALIGN
);
1657 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1670 SCVAL(nameptr
,0,len
);
1672 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1677 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1678 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1680 SIVAL(p
,0,reskey
); p
+= 4;
1681 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1682 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1683 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1684 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1685 SOFF_T(p
,0,file_size
); p
+= 8;
1686 SOFF_T(p
,0,allocation_size
); p
+= 8;
1687 SIVAL(p
,0,nt_extmode
); p
+= 4;
1688 q
= p
; p
+= 4; /* q is placeholder for name length. */
1690 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1691 smb_fname
->base_name
);
1692 SIVAL(p
,0,ea_size
); /* Extended attributes */
1695 /* Clear the short name buffer. This is
1696 * IMPORTANT as not doing so will trigger
1697 * a Win2k client bug. JRA.
1699 if (!was_8_3
&& check_mangled_names
) {
1700 char mangled_name
[13]; /* mangled 8.3 name. */
1701 if (!name_to_8_3(fname
,mangled_name
,True
,
1703 /* Error - mangle failed ! */
1704 memset(mangled_name
,'\0',12);
1706 mangled_name
[12] = 0;
1707 len
= srvstr_push(base_data
, flags2
,
1708 p
+2, mangled_name
, 24,
1709 STR_UPPER
|STR_UNICODE
);
1711 memset(p
+ 2 + len
,'\0',24 - len
);
1718 len
= srvstr_push(base_data
, flags2
, p
,
1719 fname
, PTR_DIFF(end_data
, p
),
1720 STR_TERMINATE_ASCII
);
1724 len
= PTR_DIFF(p
, pdata
);
1725 pad
= (len
+ (align
-1)) & ~(align
-1);
1727 * offset to the next entry, the caller
1728 * will overwrite it for the last entry
1729 * that's why we always include the padding
1733 * set padding to zero
1736 memset(p
, 0, pad
- len
);
1743 case SMB_FIND_FILE_DIRECTORY_INFO
:
1744 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1746 SIVAL(p
,0,reskey
); p
+= 4;
1747 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1748 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1749 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1750 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1751 SOFF_T(p
,0,file_size
); p
+= 8;
1752 SOFF_T(p
,0,allocation_size
); p
+= 8;
1753 SIVAL(p
,0,nt_extmode
); p
+= 4;
1754 len
= srvstr_push(base_data
, flags2
,
1755 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1756 STR_TERMINATE_ASCII
);
1760 len
= PTR_DIFF(p
, pdata
);
1761 pad
= (len
+ (align
-1)) & ~(align
-1);
1763 * offset to the next entry, the caller
1764 * will overwrite it for the last entry
1765 * that's why we always include the padding
1769 * set padding to zero
1772 memset(p
, 0, pad
- len
);
1779 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1780 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1782 SIVAL(p
,0,reskey
); p
+= 4;
1783 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1784 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1787 SOFF_T(p
,0,file_size
); p
+= 8;
1788 SOFF_T(p
,0,allocation_size
); p
+= 8;
1789 SIVAL(p
,0,nt_extmode
); p
+= 4;
1790 q
= p
; p
+= 4; /* q is placeholder for name length. */
1792 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1793 smb_fname
->base_name
);
1794 SIVAL(p
,0,ea_size
); /* Extended attributes */
1797 len
= srvstr_push(base_data
, flags2
, p
,
1798 fname
, PTR_DIFF(end_data
, p
),
1799 STR_TERMINATE_ASCII
);
1803 len
= PTR_DIFF(p
, pdata
);
1804 pad
= (len
+ (align
-1)) & ~(align
-1);
1806 * offset to the next entry, the caller
1807 * will overwrite it for the last entry
1808 * that's why we always include the padding
1812 * set padding to zero
1815 memset(p
, 0, pad
- len
);
1822 case SMB_FIND_FILE_NAMES_INFO
:
1823 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1825 SIVAL(p
,0,reskey
); p
+= 4;
1827 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1828 acl on a dir (tridge) */
1829 len
= srvstr_push(base_data
, flags2
, p
,
1830 fname
, PTR_DIFF(end_data
, p
),
1831 STR_TERMINATE_ASCII
);
1835 len
= PTR_DIFF(p
, pdata
);
1836 pad
= (len
+ (align
-1)) & ~(align
-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1844 * set padding to zero
1847 memset(p
, 0, pad
- len
);
1854 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1855 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1857 SIVAL(p
,0,reskey
); p
+= 4;
1858 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1859 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1862 SOFF_T(p
,0,file_size
); p
+= 8;
1863 SOFF_T(p
,0,allocation_size
); p
+= 8;
1864 SIVAL(p
,0,nt_extmode
); p
+= 4;
1865 q
= p
; p
+= 4; /* q is placeholder for name length. */
1867 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1868 smb_fname
->base_name
);
1869 SIVAL(p
,0,ea_size
); /* Extended attributes */
1872 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1873 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1874 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1875 len
= srvstr_push(base_data
, flags2
, p
,
1876 fname
, PTR_DIFF(end_data
, p
),
1877 STR_TERMINATE_ASCII
);
1881 len
= PTR_DIFF(p
, pdata
);
1882 pad
= (len
+ (align
-1)) & ~(align
-1);
1884 * offset to the next entry, the caller
1885 * will overwrite it for the last entry
1886 * that's why we always include the padding
1890 * set padding to zero
1893 memset(p
, 0, pad
- len
);
1900 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1901 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1902 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1904 SIVAL(p
,0,reskey
); p
+= 4;
1905 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1906 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1907 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1908 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1909 SOFF_T(p
,0,file_size
); p
+= 8;
1910 SOFF_T(p
,0,allocation_size
); p
+= 8;
1911 SIVAL(p
,0,nt_extmode
); p
+= 4;
1912 q
= p
; p
+= 4; /* q is placeholder for name length */
1914 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1915 smb_fname
->base_name
);
1916 SIVAL(p
,0,ea_size
); /* Extended attributes */
1919 /* Clear the short name buffer. This is
1920 * IMPORTANT as not doing so will trigger
1921 * a Win2k client bug. JRA.
1923 if (!was_8_3
&& check_mangled_names
) {
1924 char mangled_name
[13]; /* mangled 8.3 name. */
1925 if (!name_to_8_3(fname
,mangled_name
,True
,
1927 /* Error - mangle failed ! */
1928 memset(mangled_name
,'\0',12);
1930 mangled_name
[12] = 0;
1931 len
= srvstr_push(base_data
, flags2
,
1932 p
+2, mangled_name
, 24,
1933 STR_UPPER
|STR_UNICODE
);
1936 memset(p
+ 2 + len
,'\0',24 - len
);
1943 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1944 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1945 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1946 len
= srvstr_push(base_data
, flags2
, p
,
1947 fname
, PTR_DIFF(end_data
, p
),
1948 STR_TERMINATE_ASCII
);
1952 len
= PTR_DIFF(p
, pdata
);
1953 pad
= (len
+ (align
-1)) & ~(align
-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1961 * set padding to zero
1964 memset(p
, 0, pad
- len
);
1971 /* CIFS UNIX Extension. */
1973 case SMB_FIND_FILE_UNIX
:
1974 case SMB_FIND_FILE_UNIX_INFO2
:
1976 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1978 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1980 if (info_level
== SMB_FIND_FILE_UNIX
) {
1981 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1982 p
= store_file_unix_basic(conn
, p
,
1983 NULL
, &smb_fname
->st
);
1984 len
= srvstr_push(base_data
, flags2
, p
,
1985 fname
, PTR_DIFF(end_data
, p
),
1988 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1989 p
= store_file_unix_basic_info2(conn
, p
,
1990 NULL
, &smb_fname
->st
);
1993 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1994 PTR_DIFF(end_data
, p
), 0);
1995 SIVAL(nameptr
, 0, len
);
2000 len
= PTR_DIFF(p
, pdata
);
2001 pad
= (len
+ (align
-1)) & ~(align
-1);
2003 * offset to the next entry, the caller
2004 * will overwrite it for the last entry
2005 * that's why we always include the padding
2009 * set padding to zero
2012 memset(p
, 0, pad
- len
);
2017 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2025 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2026 *out_of_space
= true;
2027 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2028 return false; /* Not finished - just out of space */
2031 /* Setup the last entry pointer, as an offset from base_data */
2032 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2033 /* Advance the data pointer to the next slot */
2039 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2040 connection_struct
*conn
,
2041 struct dptr_struct
*dirptr
,
2043 const char *path_mask
,
2046 int requires_resume_key
,
2054 int space_remaining
,
2056 bool *got_exact_match
,
2057 int *_last_entry_off
,
2058 struct ea_list
*name_list
)
2061 const char *mask
= NULL
;
2062 long prev_dirpos
= 0;
2065 struct smb_filename
*smb_fname
= NULL
;
2066 struct smbd_dirptr_lanman2_state state
;
2068 uint64_t last_entry_off
= 0;
2072 state
.info_level
= info_level
;
2073 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2074 state
.has_wild
= dptr_has_wild(dirptr
);
2075 state
.got_exact_match
= false;
2077 *out_of_space
= false;
2078 *got_exact_match
= false;
2080 p
= strrchr_m(path_mask
,'/');
2091 ok
= smbd_dirptr_get_entry(ctx
,
2097 smbd_dirptr_lanman2_match_fn
,
2098 smbd_dirptr_lanman2_mode_fn
,
2108 *got_exact_match
= state
.got_exact_match
;
2110 ok
= smbd_marshall_dir_entry(ctx
,
2115 state
.check_mangled_names
,
2116 requires_resume_key
,
2129 TALLOC_FREE(smb_fname
);
2130 if (*out_of_space
) {
2131 dptr_SeekDir(dirptr
, prev_dirpos
);
2138 *_last_entry_off
= last_entry_off
;
2142 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2143 connection_struct
*conn
,
2144 struct dptr_struct
*dirptr
,
2146 const char *path_mask
,
2149 int requires_resume_key
,
2155 int space_remaining
,
2157 bool *got_exact_match
,
2158 int *last_entry_off
,
2159 struct ea_list
*name_list
)
2161 bool resume_key
= false;
2162 const uint8_t align
= 4;
2163 const bool do_pad
= true;
2165 if (requires_resume_key
) {
2169 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2170 path_mask
, dirtype
, info_level
,
2171 resume_key
, dont_descend
, ask_sharemode
,
2173 ppdata
, base_data
, end_data
,
2175 out_of_space
, got_exact_match
,
2176 last_entry_off
, name_list
);
2179 /****************************************************************************
2180 Reply to a TRANS2_FINDFIRST.
2181 ****************************************************************************/
2183 static void call_trans2findfirst(connection_struct
*conn
,
2184 struct smb_request
*req
,
2185 char **pparams
, int total_params
,
2186 char **ppdata
, int total_data
,
2187 unsigned int max_data_bytes
)
2189 /* We must be careful here that we don't return more than the
2190 allowed number of data bytes. If this means returning fewer than
2191 maxentries then so be it. We assume that the redirector has
2192 enough room for the fixed number of parameter bytes it has
2194 struct smb_filename
*smb_dname
= NULL
;
2195 char *params
= *pparams
;
2196 char *pdata
= *ppdata
;
2200 uint16 findfirst_flags
;
2201 bool close_after_first
;
2203 bool requires_resume_key
;
2205 char *directory
= NULL
;
2208 int last_entry_off
=0;
2212 bool finished
= False
;
2213 bool dont_descend
= False
;
2214 bool out_of_space
= False
;
2215 int space_remaining
;
2216 bool mask_contains_wcard
= False
;
2217 struct ea_list
*ea_list
= NULL
;
2218 NTSTATUS ntstatus
= NT_STATUS_OK
;
2219 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2220 TALLOC_CTX
*ctx
= talloc_tos();
2221 struct dptr_struct
*dirptr
= NULL
;
2222 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2224 if (total_params
< 13) {
2225 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2229 dirtype
= SVAL(params
,0);
2230 maxentries
= SVAL(params
,2);
2231 findfirst_flags
= SVAL(params
,4);
2232 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2233 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2234 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2235 info_level
= SVAL(params
,6);
2237 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2238 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2239 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2240 info_level
, max_data_bytes
));
2243 /* W2K3 seems to treat zero as 1. */
2247 switch (info_level
) {
2248 case SMB_FIND_INFO_STANDARD
:
2249 case SMB_FIND_EA_SIZE
:
2250 case SMB_FIND_EA_LIST
:
2251 case SMB_FIND_FILE_DIRECTORY_INFO
:
2252 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2253 case SMB_FIND_FILE_NAMES_INFO
:
2254 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2255 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2256 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2258 case SMB_FIND_FILE_UNIX
:
2259 case SMB_FIND_FILE_UNIX_INFO2
:
2260 /* Always use filesystem for UNIX mtime query. */
2261 ask_sharemode
= false;
2262 if (!lp_unix_extensions()) {
2263 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2268 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2272 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2273 params
+12, total_params
- 12,
2274 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2275 if (!NT_STATUS_IS_OK(ntstatus
)) {
2276 reply_nterror(req
, ntstatus
);
2280 ntstatus
= filename_convert(ctx
, conn
,
2281 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2284 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2285 &mask_contains_wcard
,
2287 if (!NT_STATUS_IS_OK(ntstatus
)) {
2288 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2289 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2290 ERRSRV
, ERRbadpath
);
2293 reply_nterror(req
, ntstatus
);
2297 mask
= smb_dname
->original_lcomp
;
2299 directory
= smb_dname
->base_name
;
2301 p
= strrchr_m(directory
,'/');
2303 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2304 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2305 mask
= talloc_strdup(ctx
,"*");
2307 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2310 mask_contains_wcard
= True
;
2312 directory
= talloc_strdup(talloc_tos(), "./");
2314 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2321 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2323 if (info_level
== SMB_FIND_EA_LIST
) {
2326 if (total_data
< 4) {
2327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2331 ea_size
= IVAL(pdata
,0);
2332 if (ea_size
!= total_data
) {
2333 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2334 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2335 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2339 if (!lp_ea_support(SNUM(conn
))) {
2340 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2344 /* Pull out the list of names. */
2345 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2347 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2352 *ppdata
= (char *)SMB_REALLOC(
2353 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2354 if(*ppdata
== NULL
) {
2355 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2359 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2361 /* Realloc the params space */
2362 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2363 if (*pparams
== NULL
) {
2364 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2369 /* Save the wildcard match and attribs we are using on this directory -
2370 needed as lanman2 assumes these are being saved between calls */
2372 ntstatus
= dptr_create(conn
,
2378 mask_contains_wcard
,
2382 if (!NT_STATUS_IS_OK(ntstatus
)) {
2383 reply_nterror(req
, ntstatus
);
2387 dptr_num
= dptr_dnum(dirptr
);
2388 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2390 /* Initialize per TRANS2_FIND_FIRST operation data */
2391 dptr_init_search_op(dirptr
);
2393 /* We don't need to check for VOL here as this is returned by
2394 a different TRANS2 call. */
2396 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2397 directory
,lp_dontdescend(SNUM(conn
))));
2398 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2399 dont_descend
= True
;
2402 space_remaining
= max_data_bytes
;
2403 out_of_space
= False
;
2405 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2406 bool got_exact_match
= False
;
2408 /* this is a heuristic to avoid seeking the dirptr except when
2409 absolutely necessary. It allows for a filename of about 40 chars */
2410 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2411 out_of_space
= True
;
2414 finished
= !get_lanman2_dir_entry(ctx
,
2418 mask
,dirtype
,info_level
,
2419 requires_resume_key
,dont_descend
,
2422 space_remaining
, &out_of_space
,
2424 &last_entry_off
, ea_list
);
2427 if (finished
&& out_of_space
)
2430 if (!finished
&& !out_of_space
)
2434 * As an optimisation if we know we aren't looking
2435 * for a wildcard name (ie. the name matches the wildcard exactly)
2436 * then we can finish on any (first) match.
2437 * This speeds up large directory searches. JRA.
2443 /* Ensure space_remaining never goes -ve. */
2444 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2445 space_remaining
= 0;
2446 out_of_space
= true;
2448 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2452 /* Check if we can close the dirptr */
2453 if(close_after_first
|| (finished
&& close_if_end
)) {
2454 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2455 dptr_close(sconn
, &dptr_num
);
2459 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2460 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2461 * the protocol level is less than NT1. Tested with smbclient. JRA.
2462 * This should fix the OS/2 client bug #2335.
2465 if(numentries
== 0) {
2466 dptr_close(sconn
, &dptr_num
);
2467 if (Protocol
< PROTOCOL_NT1
) {
2468 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2471 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2472 ERRDOS
, ERRbadfile
);
2477 /* At this point pdata points to numentries directory entries. */
2479 /* Set up the return parameter block */
2480 SSVAL(params
,0,dptr_num
);
2481 SSVAL(params
,2,numentries
);
2482 SSVAL(params
,4,finished
);
2483 SSVAL(params
,6,0); /* Never an EA error */
2484 SSVAL(params
,8,last_entry_off
);
2486 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2489 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2490 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2492 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2496 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2497 smb_fn_name(req
->cmd
),
2498 mask
, directory
, dirtype
, numentries
) );
2501 * Force a name mangle here to ensure that the
2502 * mask as an 8.3 name is top of the mangled cache.
2503 * The reasons for this are subtle. Don't remove
2504 * this code unless you know what you are doing
2505 * (see PR#13758). JRA.
2508 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2509 char mangled_name
[13];
2510 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2513 TALLOC_FREE(smb_dname
);
2517 /****************************************************************************
2518 Reply to a TRANS2_FINDNEXT.
2519 ****************************************************************************/
2521 static void call_trans2findnext(connection_struct
*conn
,
2522 struct smb_request
*req
,
2523 char **pparams
, int total_params
,
2524 char **ppdata
, int total_data
,
2525 unsigned int max_data_bytes
)
2527 /* We must be careful here that we don't return more than the
2528 allowed number of data bytes. If this means returning fewer than
2529 maxentries then so be it. We assume that the redirector has
2530 enough room for the fixed number of parameter bytes it has
2532 char *params
= *pparams
;
2533 char *pdata
= *ppdata
;
2539 uint16 findnext_flags
;
2540 bool close_after_request
;
2542 bool requires_resume_key
;
2544 bool mask_contains_wcard
= False
;
2545 char *resume_name
= NULL
;
2546 const char *mask
= NULL
;
2547 const char *directory
= NULL
;
2551 int i
, last_entry_off
=0;
2552 bool finished
= False
;
2553 bool dont_descend
= False
;
2554 bool out_of_space
= False
;
2555 int space_remaining
;
2556 struct ea_list
*ea_list
= NULL
;
2557 NTSTATUS ntstatus
= NT_STATUS_OK
;
2558 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2559 TALLOC_CTX
*ctx
= talloc_tos();
2560 struct dptr_struct
*dirptr
;
2561 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2563 if (total_params
< 13) {
2564 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2568 dptr_num
= SVAL(params
,0);
2569 maxentries
= SVAL(params
,2);
2570 info_level
= SVAL(params
,4);
2571 resume_key
= IVAL(params
,6);
2572 findnext_flags
= SVAL(params
,10);
2573 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2574 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2575 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2576 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2578 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2580 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2581 &mask_contains_wcard
);
2582 if (!NT_STATUS_IS_OK(ntstatus
)) {
2583 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2584 complain (it thinks we're asking for the directory above the shared
2585 path or an invalid name). Catch this as the resume name is only compared, never used in
2586 a file access. JRA. */
2587 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2588 &resume_name
, params
+12,
2592 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2593 reply_nterror(req
, ntstatus
);
2598 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2599 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2600 resume_key = %d resume name = %s continue=%d level = %d\n",
2601 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2602 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2605 /* W2K3 seems to treat zero as 1. */
2609 switch (info_level
) {
2610 case SMB_FIND_INFO_STANDARD
:
2611 case SMB_FIND_EA_SIZE
:
2612 case SMB_FIND_EA_LIST
:
2613 case SMB_FIND_FILE_DIRECTORY_INFO
:
2614 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2615 case SMB_FIND_FILE_NAMES_INFO
:
2616 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2617 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2618 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2620 case SMB_FIND_FILE_UNIX
:
2621 case SMB_FIND_FILE_UNIX_INFO2
:
2622 /* Always use filesystem for UNIX mtime query. */
2623 ask_sharemode
= false;
2624 if (!lp_unix_extensions()) {
2625 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2630 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2634 if (info_level
== SMB_FIND_EA_LIST
) {
2637 if (total_data
< 4) {
2638 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2642 ea_size
= IVAL(pdata
,0);
2643 if (ea_size
!= total_data
) {
2644 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2645 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2650 if (!lp_ea_support(SNUM(conn
))) {
2651 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2655 /* Pull out the list of names. */
2656 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2658 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2663 *ppdata
= (char *)SMB_REALLOC(
2664 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2665 if(*ppdata
== NULL
) {
2666 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2671 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2673 /* Realloc the params space */
2674 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2675 if(*pparams
== NULL
) {
2676 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2682 /* Check that the dptr is valid */
2683 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2684 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2688 directory
= dptr_path(sconn
, dptr_num
);
2690 /* Get the wildcard mask from the dptr */
2691 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2692 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2693 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2699 /* Get the attr mask from the dptr */
2700 dirtype
= dptr_attr(sconn
, dptr_num
);
2702 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2703 dptr_num
, mask
, dirtype
,
2705 dptr_TellDir(dirptr
)));
2707 /* Initialize per TRANS2_FIND_NEXT operation data */
2708 dptr_init_search_op(dirptr
);
2710 /* We don't need to check for VOL here as this is returned by
2711 a different TRANS2 call. */
2713 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2714 directory
,lp_dontdescend(SNUM(conn
))));
2715 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2716 dont_descend
= True
;
2719 space_remaining
= max_data_bytes
;
2720 out_of_space
= False
;
2723 * Seek to the correct position. We no longer use the resume key but
2724 * depend on the last file name instead.
2727 if(*resume_name
&& !continue_bit
) {
2730 long current_pos
= 0;
2732 * Remember, name_to_8_3 is called by
2733 * get_lanman2_dir_entry(), so the resume name
2734 * could be mangled. Ensure we check the unmangled name.
2737 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2738 char *new_resume_name
= NULL
;
2739 mangle_lookup_name_from_8_3(ctx
,
2743 if (new_resume_name
) {
2744 resume_name
= new_resume_name
;
2749 * Fix for NT redirector problem triggered by resume key indexes
2750 * changing between directory scans. We now return a resume key of 0
2751 * and instead look for the filename to continue from (also given
2752 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2753 * findfirst/findnext (as is usual) then the directory pointer
2754 * should already be at the correct place.
2757 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2758 } /* end if resume_name && !continue_bit */
2760 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2761 bool got_exact_match
= False
;
2763 /* this is a heuristic to avoid seeking the dirptr except when
2764 absolutely necessary. It allows for a filename of about 40 chars */
2765 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2766 out_of_space
= True
;
2769 finished
= !get_lanman2_dir_entry(ctx
,
2773 mask
,dirtype
,info_level
,
2774 requires_resume_key
,dont_descend
,
2777 space_remaining
, &out_of_space
,
2779 &last_entry_off
, ea_list
);
2782 if (finished
&& out_of_space
)
2785 if (!finished
&& !out_of_space
)
2789 * As an optimisation if we know we aren't looking
2790 * for a wildcard name (ie. the name matches the wildcard exactly)
2791 * then we can finish on any (first) match.
2792 * This speeds up large directory searches. JRA.
2798 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2801 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2802 smb_fn_name(req
->cmd
),
2803 mask
, directory
, dirtype
, numentries
) );
2805 /* Check if we can close the dirptr */
2806 if(close_after_request
|| (finished
&& close_if_end
)) {
2807 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2808 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2811 /* Set up the return parameter block */
2812 SSVAL(params
,0,numentries
);
2813 SSVAL(params
,2,finished
);
2814 SSVAL(params
,4,0); /* Never an EA error */
2815 SSVAL(params
,6,last_entry_off
);
2817 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2823 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2825 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2829 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2831 SMB_ASSERT(extended_info
!= NULL
);
2833 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2834 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2835 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2836 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2837 #ifdef SAMBA_VERSION_REVISION
2838 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2840 extended_info
->samba_subversion
= 0;
2841 #ifdef SAMBA_VERSION_RC_RELEASE
2842 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2844 #ifdef SAMBA_VERSION_PRE_RELEASE
2845 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2848 #ifdef SAMBA_VERSION_VENDOR_PATCH
2849 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2851 extended_info
->samba_gitcommitdate
= 0;
2852 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2853 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2856 memset(extended_info
->samba_version_string
, 0,
2857 sizeof(extended_info
->samba_version_string
));
2859 snprintf (extended_info
->samba_version_string
,
2860 sizeof(extended_info
->samba_version_string
),
2861 "%s", samba_version_string());
2864 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2865 TALLOC_CTX
*mem_ctx
,
2866 uint16_t info_level
,
2868 unsigned int max_data_bytes
,
2872 char *pdata
, *end_data
;
2873 int data_len
= 0, len
;
2874 const char *vname
= volume_label(SNUM(conn
));
2875 int snum
= SNUM(conn
);
2876 char *fstype
= lp_fstype(SNUM(conn
));
2877 uint32 additional_flags
= 0;
2878 struct smb_filename
*smb_fname_dot
= NULL
;
2883 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2884 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2885 "info level (0x%x) on IPC$.\n",
2886 (unsigned int)info_level
));
2887 return NT_STATUS_ACCESS_DENIED
;
2891 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2893 status
= create_synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
,
2895 if (!NT_STATUS_IS_OK(status
)) {
2899 if(SMB_VFS_STAT(conn
, smb_fname_dot
) != 0) {
2900 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2901 TALLOC_FREE(smb_fname_dot
);
2902 return map_nt_error_from_unix(errno
);
2905 st
= smb_fname_dot
->st
;
2906 TALLOC_FREE(smb_fname_dot
);
2908 *ppdata
= (char *)SMB_REALLOC(
2909 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2910 if (*ppdata
== NULL
) {
2911 return NT_STATUS_NO_MEMORY
;
2915 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2916 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2918 switch (info_level
) {
2919 case SMB_INFO_ALLOCATION
:
2921 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2923 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2924 return map_nt_error_from_unix(errno
);
2927 block_size
= lp_block_size(snum
);
2928 if (bsize
< block_size
) {
2929 uint64_t factor
= block_size
/bsize
;
2934 if (bsize
> block_size
) {
2935 uint64_t factor
= bsize
/block_size
;
2940 bytes_per_sector
= 512;
2941 sectors_per_unit
= bsize
/bytes_per_sector
;
2943 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2944 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2945 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2947 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2948 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2949 SIVAL(pdata
,l1_cUnit
,dsize
);
2950 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2951 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2955 case SMB_INFO_VOLUME
:
2956 /* Return volume name */
2958 * Add volume serial number - hash of a combination of
2959 * the called hostname and the service name.
2961 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2963 * Win2k3 and previous mess this up by sending a name length
2964 * one byte short. I believe only older clients (OS/2 Win9x) use
2965 * this call so try fixing this by adding a terminating null to
2966 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2970 pdata
+l2_vol_szVolLabel
, vname
,
2971 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2972 STR_NOALIGN
|STR_TERMINATE
);
2973 SCVAL(pdata
,l2_vol_cch
,len
);
2974 data_len
= l2_vol_szVolLabel
+ len
;
2975 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2976 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2980 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2981 case SMB_FS_ATTRIBUTE_INFORMATION
:
2983 additional_flags
= 0;
2984 #if defined(HAVE_SYS_QUOTAS)
2985 additional_flags
|= FILE_VOLUME_QUOTAS
;
2988 if(lp_nt_acl_support(SNUM(conn
))) {
2989 additional_flags
|= FILE_PERSISTENT_ACLS
;
2992 /* Capabilities are filled in at connection time through STATVFS call */
2993 additional_flags
|= conn
->fs_capabilities
;
2994 additional_flags
|= lp_parm_int(conn
->params
->service
,
2995 "share", "fake_fscaps",
2998 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2999 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3000 additional_flags
); /* FS ATTRIBUTES */
3002 SIVAL(pdata
,4,255); /* Max filename component length */
3003 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3004 and will think we can't do long filenames */
3005 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3006 PTR_DIFF(end_data
, pdata
+12),
3009 data_len
= 12 + len
;
3012 case SMB_QUERY_FS_LABEL_INFO
:
3013 case SMB_FS_LABEL_INFORMATION
:
3014 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3015 PTR_DIFF(end_data
, pdata
+4), 0);
3020 case SMB_QUERY_FS_VOLUME_INFO
:
3021 case SMB_FS_VOLUME_INFORMATION
:
3024 * Add volume serial number - hash of a combination of
3025 * the called hostname and the service name.
3027 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3028 (str_checksum(get_local_machine_name())<<16));
3030 /* Max label len is 32 characters. */
3031 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3032 PTR_DIFF(end_data
, pdata
+18),
3034 SIVAL(pdata
,12,len
);
3037 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3038 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3041 case SMB_QUERY_FS_SIZE_INFO
:
3042 case SMB_FS_SIZE_INFORMATION
:
3044 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3046 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3047 return map_nt_error_from_unix(errno
);
3049 block_size
= lp_block_size(snum
);
3050 if (bsize
< block_size
) {
3051 uint64_t factor
= block_size
/bsize
;
3056 if (bsize
> block_size
) {
3057 uint64_t factor
= bsize
/block_size
;
3062 bytes_per_sector
= 512;
3063 sectors_per_unit
= bsize
/bytes_per_sector
;
3064 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3065 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3066 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3067 SBIG_UINT(pdata
,0,dsize
);
3068 SBIG_UINT(pdata
,8,dfree
);
3069 SIVAL(pdata
,16,sectors_per_unit
);
3070 SIVAL(pdata
,20,bytes_per_sector
);
3074 case SMB_FS_FULL_SIZE_INFORMATION
:
3076 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3078 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3079 return map_nt_error_from_unix(errno
);
3081 block_size
= lp_block_size(snum
);
3082 if (bsize
< block_size
) {
3083 uint64_t factor
= block_size
/bsize
;
3088 if (bsize
> block_size
) {
3089 uint64_t factor
= bsize
/block_size
;
3094 bytes_per_sector
= 512;
3095 sectors_per_unit
= bsize
/bytes_per_sector
;
3096 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3097 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3098 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3099 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3100 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3101 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3102 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3103 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3107 case SMB_QUERY_FS_DEVICE_INFO
:
3108 case SMB_FS_DEVICE_INFORMATION
:
3110 SIVAL(pdata
,0,0); /* dev type */
3111 SIVAL(pdata
,4,0); /* characteristics */
3114 #ifdef HAVE_SYS_QUOTAS
3115 case SMB_FS_QUOTA_INFORMATION
:
3117 * what we have to send --metze:
3119 * Unknown1: 24 NULL bytes
3120 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3121 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3122 * Quota Flags: 2 byte :
3123 * Unknown3: 6 NULL bytes
3127 * details for Quota Flags:
3129 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3130 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3131 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3132 * 0x0001 Enable Quotas: enable quota for this fs
3136 /* we need to fake up a fsp here,
3137 * because its not send in this call
3140 SMB_NTQUOTA_STRUCT quotas
;
3143 ZERO_STRUCT(quotas
);
3149 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3150 DEBUG(0,("set_user_quota: access_denied "
3151 "service [%s] user [%s]\n",
3152 lp_servicename(SNUM(conn
)),
3153 conn
->server_info
->unix_name
));
3154 return NT_STATUS_ACCESS_DENIED
;
3157 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3158 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3159 return map_nt_error_from_unix(errno
);
3164 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3165 lp_servicename(SNUM(conn
))));
3167 /* Unknown1 24 NULL bytes*/
3168 SBIG_UINT(pdata
,0,(uint64_t)0);
3169 SBIG_UINT(pdata
,8,(uint64_t)0);
3170 SBIG_UINT(pdata
,16,(uint64_t)0);
3172 /* Default Soft Quota 8 bytes */
3173 SBIG_UINT(pdata
,24,quotas
.softlim
);
3175 /* Default Hard Quota 8 bytes */
3176 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3178 /* Quota flag 2 bytes */
3179 SSVAL(pdata
,40,quotas
.qflags
);
3181 /* Unknown3 6 NULL bytes */
3187 #endif /* HAVE_SYS_QUOTAS */
3188 case SMB_FS_OBJECTID_INFORMATION
:
3190 unsigned char objid
[16];
3191 struct smb_extended_info extended_info
;
3192 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3193 samba_extended_info_version (&extended_info
);
3194 SIVAL(pdata
,16,extended_info
.samba_magic
);
3195 SIVAL(pdata
,20,extended_info
.samba_version
);
3196 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3197 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3198 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3204 * Query the version and capabilities of the CIFS UNIX extensions
3208 case SMB_QUERY_CIFS_UNIX_INFO
:
3210 bool large_write
= lp_min_receive_file_size() &&
3211 !srv_is_signing_active(smbd_server_conn
);
3212 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3213 int encrypt_caps
= 0;
3215 if (!lp_unix_extensions()) {
3216 return NT_STATUS_INVALID_LEVEL
;
3219 switch (conn
->encrypt_level
) {
3225 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3228 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3229 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3230 large_write
= false;
3236 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3237 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3239 /* We have POSIX ACLs, pathname, encryption,
3240 * large read/write, and locking capability. */
3242 SBIG_UINT(pdata
,4,((uint64_t)(
3243 CIFS_UNIX_POSIX_ACLS_CAP
|
3244 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3245 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3246 CIFS_UNIX_EXTATTR_CAP
|
3247 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3249 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3251 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3255 case SMB_QUERY_POSIX_FS_INFO
:
3258 vfs_statvfs_struct svfs
;
3260 if (!lp_unix_extensions()) {
3261 return NT_STATUS_INVALID_LEVEL
;
3264 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3268 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3269 SIVAL(pdata
,4,svfs
.BlockSize
);
3270 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3271 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3272 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3273 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3274 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3275 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3276 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3278 } else if (rc
== EOPNOTSUPP
) {
3279 return NT_STATUS_INVALID_LEVEL
;
3280 #endif /* EOPNOTSUPP */
3282 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3283 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3288 case SMB_QUERY_POSIX_WHOAMI
:
3294 if (!lp_unix_extensions()) {
3295 return NT_STATUS_INVALID_LEVEL
;
3298 if (max_data_bytes
< 40) {
3299 return NT_STATUS_BUFFER_TOO_SMALL
;
3302 /* We ARE guest if global_sid_Builtin_Guests is
3303 * in our list of SIDs.
3305 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3306 conn
->server_info
->ptok
)) {
3307 flags
|= SMB_WHOAMI_GUEST
;
3310 /* We are NOT guest if global_sid_Authenticated_Users
3311 * is in our list of SIDs.
3313 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3314 conn
->server_info
->ptok
)) {
3315 flags
&= ~SMB_WHOAMI_GUEST
;
3318 /* NOTE: 8 bytes for UID/GID, irrespective of native
3319 * platform size. This matches
3320 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3322 data_len
= 4 /* flags */
3329 + 4 /* pad/reserved */
3330 + (conn
->server_info
->utok
.ngroups
* 8)
3332 + (conn
->server_info
->ptok
->num_sids
*
3336 SIVAL(pdata
, 0, flags
);
3337 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3339 (uint64_t)conn
->server_info
->utok
.uid
);
3340 SBIG_UINT(pdata
, 16,
3341 (uint64_t)conn
->server_info
->utok
.gid
);
3344 if (data_len
>= max_data_bytes
) {
3345 /* Potential overflow, skip the GIDs and SIDs. */
3347 SIVAL(pdata
, 24, 0); /* num_groups */
3348 SIVAL(pdata
, 28, 0); /* num_sids */
3349 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3350 SIVAL(pdata
, 36, 0); /* reserved */
3356 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3357 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3359 /* We walk the SID list twice, but this call is fairly
3360 * infrequent, and I don't expect that it's performance
3361 * sensitive -- jpeach
3363 for (i
= 0, sid_bytes
= 0;
3364 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3365 sid_bytes
+= ndr_size_dom_sid(
3366 &conn
->server_info
->ptok
->user_sids
[i
],
3371 /* SID list byte count */
3372 SIVAL(pdata
, 32, sid_bytes
);
3374 /* 4 bytes pad/reserved - must be zero */
3375 SIVAL(pdata
, 36, 0);
3379 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3380 SBIG_UINT(pdata
, data_len
,
3381 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3387 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3388 int sid_len
= ndr_size_dom_sid(
3389 &conn
->server_info
->ptok
->user_sids
[i
],
3393 sid_linearize(pdata
+ data_len
, sid_len
,
3394 &conn
->server_info
->ptok
->user_sids
[i
]);
3395 data_len
+= sid_len
;
3401 case SMB_MAC_QUERY_FS_INFO
:
3403 * Thursby MAC extension... ONLY on NTFS filesystems
3404 * once we do streams then we don't need this
3406 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3408 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3413 return NT_STATUS_INVALID_LEVEL
;
3416 *ret_data_len
= data_len
;
3417 return NT_STATUS_OK
;
3420 /****************************************************************************
3421 Reply to a TRANS2_QFSINFO (query filesystem info).
3422 ****************************************************************************/
3424 static void call_trans2qfsinfo(connection_struct
*conn
,
3425 struct smb_request
*req
,
3426 char **pparams
, int total_params
,
3427 char **ppdata
, int total_data
,
3428 unsigned int max_data_bytes
)
3430 char *params
= *pparams
;
3431 uint16_t info_level
;
3435 if (total_params
< 2) {
3436 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3440 info_level
= SVAL(params
,0);
3442 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3443 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3444 DEBUG(0,("call_trans2qfsinfo: encryption required "
3445 "and info level 0x%x sent.\n",
3446 (unsigned int)info_level
));
3447 exit_server_cleanly("encryption required "
3453 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3455 status
= smbd_do_qfsinfo(conn
, req
,
3460 if (!NT_STATUS_IS_OK(status
)) {
3461 reply_nterror(req
, status
);
3465 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3468 DEBUG( 4, ( "%s info_level = %d\n",
3469 smb_fn_name(req
->cmd
), info_level
) );
3474 /****************************************************************************
3475 Reply to a TRANS2_SETFSINFO (set filesystem info).
3476 ****************************************************************************/
3478 static void call_trans2setfsinfo(connection_struct
*conn
,
3479 struct smb_request
*req
,
3480 char **pparams
, int total_params
,
3481 char **ppdata
, int total_data
,
3482 unsigned int max_data_bytes
)
3484 char *pdata
= *ppdata
;
3485 char *params
= *pparams
;
3488 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3491 if (total_params
< 4) {
3492 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3494 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3498 info_level
= SVAL(params
,2);
3501 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3502 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3503 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3504 "info level (0x%x) on IPC$.\n",
3505 (unsigned int)info_level
));
3506 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3511 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3512 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3513 DEBUG(0,("call_trans2setfsinfo: encryption required "
3514 "and info level 0x%x sent.\n",
3515 (unsigned int)info_level
));
3516 exit_server_cleanly("encryption required "
3522 switch(info_level
) {
3523 case SMB_SET_CIFS_UNIX_INFO
:
3525 uint16 client_unix_major
;
3526 uint16 client_unix_minor
;
3527 uint32 client_unix_cap_low
;
3528 uint32 client_unix_cap_high
;
3530 if (!lp_unix_extensions()) {
3532 NT_STATUS_INVALID_LEVEL
);
3536 /* There should be 12 bytes of capabilities set. */
3537 if (total_data
< 8) {
3540 NT_STATUS_INVALID_PARAMETER
);
3543 client_unix_major
= SVAL(pdata
,0);
3544 client_unix_minor
= SVAL(pdata
,2);
3545 client_unix_cap_low
= IVAL(pdata
,4);
3546 client_unix_cap_high
= IVAL(pdata
,8);
3547 /* Just print these values for now. */
3548 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3549 cap_low = 0x%x, cap_high = 0x%x\n",
3550 (unsigned int)client_unix_major
,
3551 (unsigned int)client_unix_minor
,
3552 (unsigned int)client_unix_cap_low
,
3553 (unsigned int)client_unix_cap_high
));
3555 /* Here is where we must switch to posix pathname processing... */
3556 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3557 lp_set_posix_pathnames();
3558 mangle_change_to_posix();
3561 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3562 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3563 /* Client that knows how to do posix locks,
3564 * but not posix open/mkdir operations. Set a
3565 * default type for read/write checks. */
3567 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3573 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3576 size_t param_len
= 0;
3577 size_t data_len
= total_data
;
3579 if (!lp_unix_extensions()) {
3582 NT_STATUS_INVALID_LEVEL
);
3586 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3589 NT_STATUS_NOT_SUPPORTED
);
3593 DEBUG( 4,("call_trans2setfsinfo: "
3594 "request transport encryption.\n"));
3596 status
= srv_request_encryption_setup(conn
,
3597 (unsigned char **)ppdata
,
3599 (unsigned char **)pparams
,
3602 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3603 !NT_STATUS_IS_OK(status
)) {
3604 reply_nterror(req
, status
);
3608 send_trans2_replies(conn
, req
,
3615 if (NT_STATUS_IS_OK(status
)) {
3616 /* Server-side transport
3617 * encryption is now *on*. */
3618 status
= srv_encryption_start(conn
);
3619 if (!NT_STATUS_IS_OK(status
)) {
3620 exit_server_cleanly(
3621 "Failure in setting "
3622 "up encrypted transport");
3628 case SMB_FS_QUOTA_INFORMATION
:
3630 files_struct
*fsp
= NULL
;
3631 SMB_NTQUOTA_STRUCT quotas
;
3633 ZERO_STRUCT(quotas
);
3636 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3637 ||!CAN_WRITE(conn
)) {
3638 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3639 lp_servicename(SNUM(conn
)),
3640 conn
->server_info
->unix_name
));
3641 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3645 /* note: normaly there're 48 bytes,
3646 * but we didn't use the last 6 bytes for now
3649 fsp
= file_fsp(req
, SVAL(params
,0));
3651 if (!check_fsp_ntquota_handle(conn
, req
,
3653 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3655 req
, NT_STATUS_INVALID_HANDLE
);
3659 if (total_data
< 42) {
3660 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3664 NT_STATUS_INVALID_PARAMETER
);
3668 /* unknown_1 24 NULL bytes in pdata*/
3670 /* the soft quotas 8 bytes (uint64_t)*/
3671 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3672 #ifdef LARGE_SMB_OFF_T
3673 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3674 #else /* LARGE_SMB_OFF_T */
3675 if ((IVAL(pdata
,28) != 0)&&
3676 ((quotas
.softlim
!= 0xFFFFFFFF)||
3677 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3678 /* more than 32 bits? */
3681 NT_STATUS_INVALID_PARAMETER
);
3684 #endif /* LARGE_SMB_OFF_T */
3686 /* the hard quotas 8 bytes (uint64_t)*/
3687 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3688 #ifdef LARGE_SMB_OFF_T
3689 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3690 #else /* LARGE_SMB_OFF_T */
3691 if ((IVAL(pdata
,36) != 0)&&
3692 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3693 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3694 /* more than 32 bits? */
3697 NT_STATUS_INVALID_PARAMETER
);
3700 #endif /* LARGE_SMB_OFF_T */
3702 /* quota_flags 2 bytes **/
3703 quotas
.qflags
= SVAL(pdata
,40);
3705 /* unknown_2 6 NULL bytes follow*/
3707 /* now set the quotas */
3708 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3709 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3710 reply_nterror(req
, map_nt_error_from_unix(errno
));
3717 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3719 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3725 * sending this reply works fine,
3726 * but I'm not sure it's the same
3727 * like windows do...
3730 reply_outbuf(req
, 10, 0);
3733 #if defined(HAVE_POSIX_ACLS)
3734 /****************************************************************************
3735 Utility function to count the number of entries in a POSIX acl.
3736 ****************************************************************************/
3738 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3740 unsigned int ace_count
= 0;
3741 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3742 SMB_ACL_ENTRY_T entry
;
3744 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3746 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3747 entry_id
= SMB_ACL_NEXT_ENTRY
;
3754 /****************************************************************************
3755 Utility function to marshall a POSIX acl into wire format.
3756 ****************************************************************************/
3758 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3760 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3761 SMB_ACL_ENTRY_T entry
;
3763 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3764 SMB_ACL_TAG_T tagtype
;
3765 SMB_ACL_PERMSET_T permset
;
3766 unsigned char perms
= 0;
3767 unsigned int own_grp
;
3770 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3771 entry_id
= SMB_ACL_NEXT_ENTRY
;
3774 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3775 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3779 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3780 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3784 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3785 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3786 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3788 SCVAL(pdata
,1,perms
);
3791 case SMB_ACL_USER_OBJ
:
3792 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3793 own_grp
= (unsigned int)pst
->st_ex_uid
;
3794 SIVAL(pdata
,2,own_grp
);
3799 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3801 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3804 own_grp
= (unsigned int)*puid
;
3805 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3806 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3807 SIVAL(pdata
,2,own_grp
);
3811 case SMB_ACL_GROUP_OBJ
:
3812 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3813 own_grp
= (unsigned int)pst
->st_ex_gid
;
3814 SIVAL(pdata
,2,own_grp
);
3819 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3821 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3824 own_grp
= (unsigned int)*pgid
;
3825 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3826 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3827 SIVAL(pdata
,2,own_grp
);
3832 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3833 SIVAL(pdata
,2,0xFFFFFFFF);
3834 SIVAL(pdata
,6,0xFFFFFFFF);
3837 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3838 SIVAL(pdata
,2,0xFFFFFFFF);
3839 SIVAL(pdata
,6,0xFFFFFFFF);
3842 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3845 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3852 /****************************************************************************
3853 Store the FILE_UNIX_BASIC info.
3854 ****************************************************************************/
3856 static char *store_file_unix_basic(connection_struct
*conn
,
3859 const SMB_STRUCT_STAT
*psbuf
)
3861 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3862 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3864 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3867 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3870 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3871 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3872 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3875 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3879 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3883 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3886 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3890 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3894 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ex_ino
); /* inode number */
3897 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3901 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3908 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3909 * the chflags(2) (or equivalent) flags.
3911 * XXX: this really should be behind the VFS interface. To do this, we would
3912 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3913 * Each VFS module could then implement its own mapping as appropriate for the
3914 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3916 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3920 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3924 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3928 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3932 { UF_HIDDEN
, EXT_HIDDEN
},
3935 /* Do not remove. We need to guarantee that this array has at least one
3936 * entry to build on HP-UX.
3942 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3943 uint32
*smb_fflags
, uint32
*smb_fmask
)
3947 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3948 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3949 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3950 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3955 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3956 const uint32 smb_fflags
,
3957 const uint32 smb_fmask
,
3960 uint32 max_fmask
= 0;
3963 *stat_fflags
= psbuf
->st_ex_flags
;
3965 /* For each flags requested in smb_fmask, check the state of the
3966 * corresponding flag in smb_fflags and set or clear the matching
3970 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3971 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3972 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3973 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3974 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3976 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3981 /* If smb_fmask is asking to set any bits that are not supported by
3982 * our flag mappings, we should fail.
3984 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3992 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3993 * of file flags and birth (create) time.
3995 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3998 const SMB_STRUCT_STAT
*psbuf
)
4000 uint32 file_flags
= 0;
4001 uint32 flags_mask
= 0;
4003 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4005 /* Create (birth) time 64 bit */
4006 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4009 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4010 SIVAL(pdata
, 0, file_flags
); /* flags */
4011 SIVAL(pdata
, 4, flags_mask
); /* mask */
4017 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4018 const struct stream_struct
*streams
,
4020 unsigned int max_data_bytes
,
4021 unsigned int *data_size
)
4024 unsigned int ofs
= 0;
4026 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4027 unsigned int next_offset
;
4029 smb_ucs2_t
*namebuf
;
4031 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4032 streams
[i
].name
, &namelen
) ||
4035 return NT_STATUS_INVALID_PARAMETER
;
4039 * name_buf is now null-terminated, we need to marshall as not
4045 SIVAL(data
, ofs
+4, namelen
);
4046 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4047 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4048 memcpy(data
+ofs
+24, namebuf
, namelen
);
4049 TALLOC_FREE(namebuf
);
4051 next_offset
= ofs
+ 24 + namelen
;
4053 if (i
== num_streams
-1) {
4054 SIVAL(data
, ofs
, 0);
4057 unsigned int align
= ndr_align_size(next_offset
, 8);
4059 memset(data
+next_offset
, 0, align
);
4060 next_offset
+= align
;
4062 SIVAL(data
, ofs
, next_offset
- ofs
);
4071 return NT_STATUS_OK
;
4074 /****************************************************************************
4075 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4076 ****************************************************************************/
4078 static void call_trans2qpipeinfo(connection_struct
*conn
,
4079 struct smb_request
*req
,
4080 unsigned int tran_call
,
4081 char **pparams
, int total_params
,
4082 char **ppdata
, int total_data
,
4083 unsigned int max_data_bytes
)
4085 char *params
= *pparams
;
4086 char *pdata
= *ppdata
;
4087 unsigned int data_size
= 0;
4088 unsigned int param_size
= 2;
4093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4097 if (total_params
< 4) {
4098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4102 fsp
= file_fsp(req
, SVAL(params
,0));
4103 if (!fsp_is_np(fsp
)) {
4104 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4108 info_level
= SVAL(params
,2);
4110 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4111 if (*pparams
== NULL
) {
4112 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4117 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4118 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4119 if (*ppdata
== NULL
) {
4120 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4125 switch (info_level
) {
4126 case SMB_FILE_STANDARD_INFORMATION
:
4128 SOFF_T(pdata
,0,4096LL);
4135 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4139 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4145 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4146 TALLOC_CTX
*mem_ctx
,
4147 uint16_t info_level
,
4149 struct smb_filename
*smb_fname
,
4150 bool delete_pending
,
4151 struct timespec write_time_ts
,
4153 struct ea_list
*ea_list
,
4154 int lock_data_count
,
4157 unsigned int max_data_bytes
,
4159 unsigned int *pdata_size
)
4161 char *pdata
= *ppdata
;
4162 char *dstart
, *dend
;
4163 unsigned int data_size
;
4164 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4165 time_t create_time
, mtime
, atime
, c_time
;
4166 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4173 uint64_t file_size
= 0;
4175 uint64_t allocation_size
= 0;
4176 uint64_t file_index
= 0;
4177 uint32_t access_mask
= 0;
4179 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4180 return NT_STATUS_INVALID_LEVEL
;
4183 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4184 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4185 info_level
, max_data_bytes
));
4188 mode
= dos_mode_msdfs(conn
, smb_fname
);
4190 mode
= dos_mode(conn
, smb_fname
);
4193 mode
= FILE_ATTRIBUTE_NORMAL
;
4195 nlink
= psbuf
->st_ex_nlink
;
4197 if (nlink
&& (mode
&aDIR
)) {
4201 if ((nlink
> 0) && delete_pending
) {
4205 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4206 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4207 if (*ppdata
== NULL
) {
4208 return NT_STATUS_NO_MEMORY
;
4212 dend
= dstart
+ data_size
- 1;
4214 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4215 update_stat_ex_mtime(psbuf
, write_time_ts
);
4218 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4219 mtime_ts
= psbuf
->st_ex_mtime
;
4220 atime_ts
= psbuf
->st_ex_atime
;
4221 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4223 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4224 dos_filetime_timespec(&create_time_ts
);
4225 dos_filetime_timespec(&mtime_ts
);
4226 dos_filetime_timespec(&atime_ts
);
4227 dos_filetime_timespec(&ctime_ts
);
4230 create_time
= convert_timespec_to_time_t(create_time_ts
);
4231 mtime
= convert_timespec_to_time_t(mtime_ts
);
4232 atime
= convert_timespec_to_time_t(atime_ts
);
4233 c_time
= convert_timespec_to_time_t(ctime_ts
);
4235 p
= strrchr_m(smb_fname
->base_name
,'/');
4237 base_name
= smb_fname
->base_name
;
4241 /* NT expects the name to be in an exact form of the *full*
4242 filename. See the trans2 torture test */
4243 if (ISDOT(base_name
)) {
4244 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4246 return NT_STATUS_NO_MEMORY
;
4249 dos_fname
= talloc_asprintf(mem_ctx
,
4251 smb_fname
->base_name
);
4253 return NT_STATUS_NO_MEMORY
;
4255 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4256 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4257 smb_fname
->stream_name
);
4259 return NT_STATUS_NO_MEMORY
;
4263 string_replace(dos_fname
, '/', '\\');
4266 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4269 /* Do we have this path open ? */
4271 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4272 fsp1
= file_find_di_first(fileid
);
4273 if (fsp1
&& fsp1
->initial_allocation_size
) {
4274 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4278 if (!(mode
& aDIR
)) {
4279 file_size
= get_file_size_stat(psbuf
);
4283 pos
= fsp
->fh
->position_information
;
4287 access_mask
= fsp
->access_mask
;
4289 /* GENERIC_EXECUTE mapping from Windows */
4290 access_mask
= 0x12019F;
4293 /* This should be an index number - looks like
4296 I think this causes us to fail the IFSKIT
4297 BasicFileInformationTest. -tpot */
4298 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
4299 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
4301 switch (info_level
) {
4302 case SMB_INFO_STANDARD
:
4303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4305 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4306 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4307 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4308 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4309 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4310 SSVAL(pdata
,l1_attrFile
,mode
);
4313 case SMB_INFO_QUERY_EA_SIZE
:
4315 unsigned int ea_size
=
4316 estimate_ea_size(conn
, fsp
,
4317 smb_fname
->base_name
);
4318 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4320 srv_put_dos_date2(pdata
,0,create_time
);
4321 srv_put_dos_date2(pdata
,4,atime
);
4322 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4323 SIVAL(pdata
,12,(uint32
)file_size
);
4324 SIVAL(pdata
,16,(uint32
)allocation_size
);
4325 SSVAL(pdata
,20,mode
);
4326 SIVAL(pdata
,22,ea_size
);
4330 case SMB_INFO_IS_NAME_VALID
:
4331 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4333 /* os/2 needs this ? really ?*/
4334 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4336 /* This is only reached for qpathinfo */
4340 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4342 size_t total_ea_len
= 0;
4343 struct ea_list
*ea_file_list
= NULL
;
4345 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4348 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4349 smb_fname
->base_name
,
4351 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4353 if (!ea_list
|| (total_ea_len
> data_size
)) {
4355 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4359 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4363 case SMB_INFO_QUERY_ALL_EAS
:
4365 /* We have data_size bytes to put EA's into. */
4366 size_t total_ea_len
= 0;
4368 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4370 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4371 smb_fname
->base_name
,
4373 if (!ea_list
|| (total_ea_len
> data_size
)) {
4375 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4379 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4383 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4385 /* This is FileFullEaInformation - 0xF which maps to
4386 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4388 /* We have data_size bytes to put EA's into. */
4389 size_t total_ea_len
= 0;
4390 struct ea_list
*ea_file_list
= NULL
;
4392 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4394 /*TODO: add filtering and index handling */
4397 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4398 smb_fname
->base_name
,
4400 if (!ea_file_list
) {
4401 return NT_STATUS_NO_EAS_ON_FILE
;
4404 status
= fill_ea_chained_buffer(mem_ctx
,
4408 conn
, ea_file_list
);
4409 if (!NT_STATUS_IS_OK(status
)) {
4415 case SMB_FILE_BASIC_INFORMATION
:
4416 case SMB_QUERY_FILE_BASIC_INFO
:
4418 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4420 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4426 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4427 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4428 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4429 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4430 SIVAL(pdata
,32,mode
);
4432 DEBUG(5,("SMB_QFBI - "));
4433 DEBUG(5,("create: %s ", ctime(&create_time
)));
4434 DEBUG(5,("access: %s ", ctime(&atime
)));
4435 DEBUG(5,("write: %s ", ctime(&mtime
)));
4436 DEBUG(5,("change: %s ", ctime(&c_time
)));
4437 DEBUG(5,("mode: %x\n", mode
));
4440 case SMB_FILE_STANDARD_INFORMATION
:
4441 case SMB_QUERY_FILE_STANDARD_INFO
:
4443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4445 SOFF_T(pdata
,0,allocation_size
);
4446 SOFF_T(pdata
,8,file_size
);
4447 SIVAL(pdata
,16,nlink
);
4448 SCVAL(pdata
,20,delete_pending
?1:0);
4449 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4450 SSVAL(pdata
,22,0); /* Padding. */
4453 case SMB_FILE_EA_INFORMATION
:
4454 case SMB_QUERY_FILE_EA_INFO
:
4456 unsigned int ea_size
=
4457 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4460 SIVAL(pdata
,0,ea_size
);
4464 /* Get the 8.3 name - used if NT SMB was negotiated. */
4465 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4466 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4469 char mangled_name
[13];
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4471 if (!name_to_8_3(base_name
,mangled_name
,
4472 True
,conn
->params
)) {
4473 return NT_STATUS_NO_MEMORY
;
4475 len
= srvstr_push(dstart
, flags2
,
4476 pdata
+4, mangled_name
,
4477 PTR_DIFF(dend
, pdata
+4),
4479 data_size
= 4 + len
;
4484 case SMB_QUERY_FILE_NAME_INFO
:
4488 this must be *exactly* right for ACLs on mapped drives to work
4490 len
= srvstr_push(dstart
, flags2
,
4492 PTR_DIFF(dend
, pdata
+4),
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4495 data_size
= 4 + len
;
4500 case SMB_FILE_ALLOCATION_INFORMATION
:
4501 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4504 SOFF_T(pdata
,0,allocation_size
);
4507 case SMB_FILE_END_OF_FILE_INFORMATION
:
4508 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4509 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4511 SOFF_T(pdata
,0,file_size
);
4514 case SMB_QUERY_FILE_ALL_INFO
:
4515 case SMB_FILE_ALL_INFORMATION
:
4518 unsigned int ea_size
=
4519 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4521 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4522 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4523 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4524 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4525 SIVAL(pdata
,32,mode
);
4526 SIVAL(pdata
,36,0); /* padding. */
4528 SOFF_T(pdata
,0,allocation_size
);
4529 SOFF_T(pdata
,8,file_size
);
4530 SIVAL(pdata
,16,nlink
);
4531 SCVAL(pdata
,20,delete_pending
);
4532 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4535 SIVAL(pdata
,0,ea_size
);
4536 pdata
+= 4; /* EA info */
4537 len
= srvstr_push(dstart
, flags2
,
4539 PTR_DIFF(dend
, pdata
+4),
4543 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4547 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4550 unsigned int ea_size
=
4551 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4553 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4554 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4555 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4556 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4557 SIVAL(pdata
, 0x20, mode
);
4558 SIVAL(pdata
, 0x24, 0); /* padding. */
4559 SBVAL(pdata
, 0x28, allocation_size
);
4560 SBVAL(pdata
, 0x30, file_size
);
4561 SIVAL(pdata
, 0x38, nlink
);
4562 SCVAL(pdata
, 0x3C, delete_pending
);
4563 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4564 SSVAL(pdata
, 0x3E, 0); /* padding */
4565 SBVAL(pdata
, 0x40, file_index
);
4566 SIVAL(pdata
, 0x48, ea_size
);
4567 SIVAL(pdata
, 0x4C, access_mask
);
4568 SBVAL(pdata
, 0x50, pos
);
4569 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4570 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4574 len
= srvstr_push(dstart
, flags2
,
4576 PTR_DIFF(dend
, pdata
+4),
4580 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4583 case SMB_FILE_INTERNAL_INFORMATION
:
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4586 SBVAL(pdata
, 0, file_index
);
4590 case SMB_FILE_ACCESS_INFORMATION
:
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4592 SIVAL(pdata
, 0, access_mask
);
4596 case SMB_FILE_NAME_INFORMATION
:
4597 /* Pathname with leading '\'. */
4600 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4602 SIVAL(pdata
,0,byte_len
);
4603 data_size
= 4 + byte_len
;
4607 case SMB_FILE_DISPOSITION_INFORMATION
:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4610 SCVAL(pdata
,0,delete_pending
);
4613 case SMB_FILE_POSITION_INFORMATION
:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4616 SOFF_T(pdata
,0,pos
);
4619 case SMB_FILE_MODE_INFORMATION
:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4621 SIVAL(pdata
,0,mode
);
4625 case SMB_FILE_ALIGNMENT_INFORMATION
:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4627 SIVAL(pdata
,0,0); /* No alignment needed. */
4632 * NT4 server just returns "invalid query" to this - if we try
4633 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4636 /* The first statement above is false - verified using Thursby
4637 * client against NT4 -- gcolley.
4639 case SMB_QUERY_FILE_STREAM_INFO
:
4640 case SMB_FILE_STREAM_INFORMATION
: {
4641 unsigned int num_streams
;
4642 struct stream_struct
*streams
;
4644 DEBUG(10,("smbd_do_qfilepathinfo: "
4645 "SMB_FILE_STREAM_INFORMATION\n"));
4647 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4648 return NT_STATUS_INVALID_PARAMETER
;
4651 status
= SMB_VFS_STREAMINFO(
4652 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4653 &num_streams
, &streams
);
4655 if (!NT_STATUS_IS_OK(status
)) {
4656 DEBUG(10, ("could not get stream info: %s\n",
4657 nt_errstr(status
)));
4661 status
= marshall_stream_info(num_streams
, streams
,
4662 pdata
, max_data_bytes
,
4665 if (!NT_STATUS_IS_OK(status
)) {
4666 DEBUG(10, ("marshall_stream_info failed: %s\n",
4667 nt_errstr(status
)));
4671 TALLOC_FREE(streams
);
4675 case SMB_QUERY_COMPRESSION_INFO
:
4676 case SMB_FILE_COMPRESSION_INFORMATION
:
4677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4678 SOFF_T(pdata
,0,file_size
);
4679 SIVAL(pdata
,8,0); /* ??? */
4680 SIVAL(pdata
,12,0); /* ??? */
4684 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4686 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4687 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4688 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4689 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4690 SOFF_T(pdata
,32,allocation_size
);
4691 SOFF_T(pdata
,40,file_size
);
4692 SIVAL(pdata
,48,mode
);
4693 SIVAL(pdata
,52,0); /* ??? */
4697 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4699 SIVAL(pdata
,0,mode
);
4705 * CIFS UNIX Extensions.
4708 case SMB_QUERY_FILE_UNIX_BASIC
:
4710 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4711 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4715 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4717 for (i
=0; i
<100; i
++)
4718 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4724 case SMB_QUERY_FILE_UNIX_INFO2
:
4726 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4727 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4731 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4733 for (i
=0; i
<100; i
++)
4734 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4740 case SMB_QUERY_FILE_UNIX_LINK
:
4743 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4746 return NT_STATUS_NO_MEMORY
;
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4751 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4752 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4755 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4757 len
= SMB_VFS_READLINK(conn
,
4758 smb_fname
->base_name
,
4761 return map_nt_error_from_unix(errno
);
4764 len
= srvstr_push(dstart
, flags2
,
4766 PTR_DIFF(dend
, pdata
),
4769 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4774 #if defined(HAVE_POSIX_ACLS)
4775 case SMB_QUERY_POSIX_ACL
:
4777 SMB_ACL_T file_acl
= NULL
;
4778 SMB_ACL_T def_acl
= NULL
;
4779 uint16 num_file_acls
= 0;
4780 uint16 num_def_acls
= 0;
4782 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4783 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4786 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4787 smb_fname
->base_name
,
4788 SMB_ACL_TYPE_ACCESS
);
4791 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4792 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4793 "not implemented on "
4794 "filesystem containing %s\n",
4795 smb_fname
->base_name
));
4796 return NT_STATUS_NOT_IMPLEMENTED
;
4799 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4800 if (fsp
&& fsp
->is_directory
) {
4802 SMB_VFS_SYS_ACL_GET_FILE(
4804 fsp
->fsp_name
->base_name
,
4805 SMB_ACL_TYPE_DEFAULT
);
4808 SMB_VFS_SYS_ACL_GET_FILE(
4810 smb_fname
->base_name
,
4811 SMB_ACL_TYPE_DEFAULT
);
4813 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4816 num_file_acls
= count_acl_entries(conn
, file_acl
);
4817 num_def_acls
= count_acl_entries(conn
, def_acl
);
4819 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4820 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4822 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4823 SMB_POSIX_ACL_HEADER_SIZE
) ));
4825 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4828 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4830 return NT_STATUS_BUFFER_TOO_SMALL
;
4833 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4834 SSVAL(pdata
,2,num_file_acls
);
4835 SSVAL(pdata
,4,num_def_acls
);
4836 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4838 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4841 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4843 return NT_STATUS_INTERNAL_ERROR
;
4845 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_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
;
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4861 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4867 case SMB_QUERY_POSIX_LOCK
:
4872 enum brl_type lock_type
;
4874 /* We need an open file with a real fd for this. */
4875 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4876 return NT_STATUS_INVALID_LEVEL
;
4879 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4880 return NT_STATUS_INVALID_PARAMETER
;
4883 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4884 case POSIX_LOCK_TYPE_READ
:
4885 lock_type
= READ_LOCK
;
4887 case POSIX_LOCK_TYPE_WRITE
:
4888 lock_type
= WRITE_LOCK
;
4890 case POSIX_LOCK_TYPE_UNLOCK
:
4892 /* There's no point in asking for an unlock... */
4893 return NT_STATUS_INVALID_PARAMETER
;
4896 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4897 #if defined(HAVE_LONGLONG)
4898 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4899 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4900 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4901 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4902 #else /* HAVE_LONGLONG */
4903 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4904 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4905 #endif /* HAVE_LONGLONG */
4907 status
= query_lock(fsp
,
4914 if (ERROR_WAS_LOCK_DENIED(status
)) {
4915 /* Here we need to report who has it locked... */
4916 data_size
= POSIX_LOCK_DATA_SIZE
;
4918 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4919 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4920 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4921 #if defined(HAVE_LONGLONG)
4922 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4923 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4924 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4925 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4926 #else /* HAVE_LONGLONG */
4927 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4928 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4929 #endif /* HAVE_LONGLONG */
4931 } else if (NT_STATUS_IS_OK(status
)) {
4932 /* For success we just return a copy of what we sent
4933 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4934 data_size
= POSIX_LOCK_DATA_SIZE
;
4935 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4936 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4944 return NT_STATUS_INVALID_LEVEL
;
4947 *pdata_size
= data_size
;
4948 return NT_STATUS_OK
;
4951 /****************************************************************************
4952 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4953 file name or file id).
4954 ****************************************************************************/
4956 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4957 struct smb_request
*req
,
4958 unsigned int tran_call
,
4959 char **pparams
, int total_params
,
4960 char **ppdata
, int total_data
,
4961 unsigned int max_data_bytes
)
4963 char *params
= *pparams
;
4964 char *pdata
= *ppdata
;
4966 unsigned int data_size
= 0;
4967 unsigned int param_size
= 2;
4968 struct smb_filename
*smb_fname
= NULL
;
4969 bool delete_pending
= False
;
4970 struct timespec write_time_ts
;
4971 files_struct
*fsp
= NULL
;
4972 struct file_id fileid
;
4973 struct ea_list
*ea_list
= NULL
;
4974 int lock_data_count
= 0;
4975 char *lock_data
= NULL
;
4976 bool ms_dfs_link
= false;
4977 NTSTATUS status
= NT_STATUS_OK
;
4980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4984 ZERO_STRUCT(write_time_ts
);
4986 if (tran_call
== TRANSACT2_QFILEINFO
) {
4987 if (total_params
< 4) {
4988 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4993 call_trans2qpipeinfo(conn
, req
, tran_call
,
4994 pparams
, total_params
,
5000 fsp
= file_fsp(req
, SVAL(params
,0));
5001 info_level
= SVAL(params
,2);
5003 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5005 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5006 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5010 /* Initial check for valid fsp ptr. */
5011 if (!check_fsp_open(conn
, req
, fsp
)) {
5015 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5017 if (!NT_STATUS_IS_OK(status
)) {
5018 reply_nterror(req
, status
);
5022 if(fsp
->fake_file_handle
) {
5024 * This is actually for the QUOTA_FAKE_FILE --metze
5027 /* We know this name is ok, it's already passed the checks. */
5029 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5031 * This is actually a QFILEINFO on a directory
5032 * handle (returned from an NT SMB). NT5.0 seems
5033 * to do this call. JRA.
5036 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5037 /* Always do lstat for UNIX calls. */
5038 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5039 DEBUG(3,("call_trans2qfilepathinfo: "
5040 "SMB_VFS_LSTAT of %s failed "
5042 smb_fname_str_dbg(smb_fname
),
5045 map_nt_error_from_unix(errno
));
5048 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5049 DEBUG(3,("call_trans2qfilepathinfo: "
5050 "SMB_VFS_STAT of %s failed (%s)\n",
5051 smb_fname_str_dbg(smb_fname
),
5054 map_nt_error_from_unix(errno
));
5058 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5059 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5062 * Original code - this is an open file.
5064 if (!check_fsp(conn
, req
, fsp
)) {
5068 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5069 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5070 fsp
->fnum
, strerror(errno
)));
5072 map_nt_error_from_unix(errno
));
5075 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5076 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5083 if (total_params
< 7) {
5084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5088 info_level
= SVAL(params
,0);
5090 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5092 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5093 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5097 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5099 STR_TERMINATE
, &status
);
5100 if (!NT_STATUS_IS_OK(status
)) {
5101 reply_nterror(req
, status
);
5105 status
= filename_convert(req
,
5107 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5112 if (!NT_STATUS_IS_OK(status
)) {
5113 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5114 reply_botherror(req
,
5115 NT_STATUS_PATH_NOT_COVERED
,
5116 ERRSRV
, ERRbadpath
);
5119 reply_nterror(req
, status
);
5123 /* If this is a stream, check if there is a delete_pending. */
5124 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5125 && is_ntfs_stream_smb_fname(smb_fname
)) {
5126 struct smb_filename
*smb_fname_base
= NULL
;
5128 /* Create an smb_filename with stream_name == NULL. */
5130 create_synthetic_smb_fname(talloc_tos(),
5131 smb_fname
->base_name
,
5134 if (!NT_STATUS_IS_OK(status
)) {
5135 reply_nterror(req
, status
);
5139 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5140 /* Always do lstat for UNIX calls. */
5141 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5142 DEBUG(3,("call_trans2qfilepathinfo: "
5143 "SMB_VFS_LSTAT of %s failed "
5145 smb_fname_str_dbg(smb_fname_base
),
5147 TALLOC_FREE(smb_fname_base
);
5149 map_nt_error_from_unix(errno
));
5153 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5154 DEBUG(3,("call_trans2qfilepathinfo: "
5155 "fileinfo of %s failed "
5157 smb_fname_str_dbg(smb_fname_base
),
5159 TALLOC_FREE(smb_fname_base
);
5161 map_nt_error_from_unix(errno
));
5166 fileid
= vfs_file_id_from_sbuf(conn
,
5167 &smb_fname_base
->st
);
5168 TALLOC_FREE(smb_fname_base
);
5169 get_file_infos(fileid
, &delete_pending
, NULL
);
5170 if (delete_pending
) {
5171 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5176 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5177 /* Always do lstat for UNIX calls. */
5178 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5179 DEBUG(3,("call_trans2qfilepathinfo: "
5180 "SMB_VFS_LSTAT of %s failed (%s)\n",
5181 smb_fname_str_dbg(smb_fname
),
5184 map_nt_error_from_unix(errno
));
5188 } else if (!VALID_STAT(smb_fname
->st
) &&
5189 SMB_VFS_STAT(conn
, smb_fname
) &&
5190 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5191 ms_dfs_link
= check_msdfs_link(conn
,
5192 smb_fname
->base_name
,
5196 DEBUG(3,("call_trans2qfilepathinfo: "
5197 "SMB_VFS_STAT of %s failed (%s)\n",
5198 smb_fname_str_dbg(smb_fname
),
5201 map_nt_error_from_unix(errno
));
5206 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5207 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5208 if (delete_pending
) {
5209 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5214 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5215 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5216 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5218 /* Pull out any data sent here before we realloc. */
5219 switch (info_level
) {
5220 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5222 /* Pull any EA list from the data portion. */
5225 if (total_data
< 4) {
5227 req
, NT_STATUS_INVALID_PARAMETER
);
5230 ea_size
= IVAL(pdata
,0);
5232 if (total_data
> 0 && ea_size
!= total_data
) {
5233 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5234 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5236 req
, NT_STATUS_INVALID_PARAMETER
);
5240 if (!lp_ea_support(SNUM(conn
))) {
5241 reply_doserror(req
, ERRDOS
,
5242 ERReasnotsupported
);
5246 /* Pull out the list of names. */
5247 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5250 req
, NT_STATUS_INVALID_PARAMETER
);
5256 case SMB_QUERY_POSIX_LOCK
:
5258 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5259 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5263 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5265 req
, NT_STATUS_INVALID_PARAMETER
);
5269 /* Copy the lock range data. */
5270 lock_data
= (char *)TALLOC_MEMDUP(
5271 req
, pdata
, total_data
);
5273 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5276 lock_data_count
= total_data
;
5282 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5283 if (*pparams
== NULL
) {
5284 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5291 * draft-leach-cifs-v1-spec-02.txt
5292 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5295 * The requested information is placed in the Data portion of the
5296 * transaction response. For the information levels greater than 0x100,
5297 * the transaction response has 1 parameter word which should be
5298 * ignored by the client.
5300 * However Windows only follows this rule for the IS_NAME_VALID call.
5302 switch (info_level
) {
5303 case SMB_INFO_IS_NAME_VALID
:
5308 if ((info_level
& 0xFF00) == 0xFF00) {
5310 * We use levels that start with 0xFF00
5311 * internally to represent SMB2 specific levels
5313 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5317 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5319 delete_pending
, write_time_ts
,
5320 ms_dfs_link
, ea_list
,
5321 lock_data_count
, lock_data
,
5322 req
->flags2
, max_data_bytes
,
5323 ppdata
, &data_size
);
5324 if (!NT_STATUS_IS_OK(status
)) {
5325 reply_nterror(req
, status
);
5329 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5335 /****************************************************************************
5336 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5338 ****************************************************************************/
5340 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5341 connection_struct
*conn
,
5342 const struct smb_filename
*smb_fname_old
,
5343 const struct smb_filename
*smb_fname_new
)
5345 NTSTATUS status
= NT_STATUS_OK
;
5347 /* source must already exist. */
5348 if (!VALID_STAT(smb_fname_old
->st
)) {
5349 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5352 /* Disallow if newname already exists. */
5353 if (VALID_STAT(smb_fname_new
->st
)) {
5354 return NT_STATUS_OBJECT_NAME_COLLISION
;
5357 /* No links from a directory. */
5358 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5359 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5362 /* Setting a hardlink to/from a stream isn't currently supported. */
5363 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5364 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5365 return NT_STATUS_INVALID_PARAMETER
;
5368 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5369 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5371 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5372 smb_fname_new
->base_name
) != 0) {
5373 status
= map_nt_error_from_unix(errno
);
5374 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5375 nt_errstr(status
), smb_fname_old
->base_name
,
5376 smb_fname_new
->base_name
));
5381 /****************************************************************************
5382 Deal with setting the time from any of the setfilepathinfo functions.
5383 ****************************************************************************/
5385 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5387 const struct smb_filename
*smb_fname
,
5388 struct smb_file_time
*ft
,
5389 bool setting_write_time
)
5391 struct smb_filename
*smb_fname_base
= NULL
;
5393 FILE_NOTIFY_CHANGE_LAST_ACCESS
5394 |FILE_NOTIFY_CHANGE_LAST_WRITE
5395 |FILE_NOTIFY_CHANGE_CREATION
;
5398 if (!VALID_STAT(smb_fname
->st
)) {
5399 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5402 /* get some defaults (no modifications) if any info is zero or -1. */
5403 if (null_timespec(ft
->create_time
)) {
5404 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5407 if (null_timespec(ft
->atime
)) {
5408 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5411 if (null_timespec(ft
->mtime
)) {
5412 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5415 if (!setting_write_time
) {
5416 /* ft->mtime comes from change time, not write time. */
5417 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5420 /* Ensure the resolution is the correct for
5421 * what we can store on this filesystem. */
5423 round_timespec(conn
->ts_res
, &ft
->create_time
);
5424 round_timespec(conn
->ts_res
, &ft
->ctime
);
5425 round_timespec(conn
->ts_res
, &ft
->atime
);
5426 round_timespec(conn
->ts_res
, &ft
->mtime
);
5428 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5429 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5430 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5431 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5432 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5433 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5434 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5435 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5437 if (setting_write_time
) {
5439 * This was a Windows setfileinfo on an open file.
5440 * NT does this a lot. We also need to
5441 * set the time here, as it can be read by
5442 * FindFirst/FindNext and with the patch for bug #2045
5443 * in smbd/fileio.c it ensures that this timestamp is
5444 * kept sticky even after a write. We save the request
5445 * away and will set it on file close and after a write. JRA.
5448 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5449 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5452 if (fsp
->base_fsp
) {
5453 set_sticky_write_time_fsp(fsp
->base_fsp
,
5456 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5459 set_sticky_write_time_path(
5460 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5465 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5467 /* Always call ntimes on the base, even if a stream was passed in. */
5468 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5469 NULL
, &smb_fname
->st
,
5471 if (!NT_STATUS_IS_OK(status
)) {
5475 if(file_ntimes(conn
, smb_fname_base
, ft
)!=0) {
5476 TALLOC_FREE(smb_fname_base
);
5477 return map_nt_error_from_unix(errno
);
5479 TALLOC_FREE(smb_fname_base
);
5481 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5482 smb_fname
->base_name
);
5483 return NT_STATUS_OK
;
5486 /****************************************************************************
5487 Deal with setting the dosmode from any of the setfilepathinfo functions.
5488 ****************************************************************************/
5490 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5491 const struct smb_filename
*smb_fname
,
5494 struct smb_filename
*smb_fname_base
= NULL
;
5497 if (!VALID_STAT(smb_fname
->st
)) {
5498 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5501 /* Always operate on the base_name, even if a stream was passed in. */
5502 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5503 NULL
, &smb_fname
->st
,
5505 if (!NT_STATUS_IS_OK(status
)) {
5510 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5517 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5519 /* check the mode isn't different, before changing it */
5520 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5521 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5522 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5523 (unsigned int)dosmode
));
5525 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5527 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5529 smb_fname_str_dbg(smb_fname_base
),
5531 status
= map_nt_error_from_unix(errno
);
5535 status
= NT_STATUS_OK
;
5537 TALLOC_FREE(smb_fname_base
);
5541 /****************************************************************************
5542 Deal with setting the size from any of the setfilepathinfo functions.
5543 ****************************************************************************/
5545 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5546 struct smb_request
*req
,
5548 const struct smb_filename
*smb_fname
,
5549 const SMB_STRUCT_STAT
*psbuf
,
5552 NTSTATUS status
= NT_STATUS_OK
;
5553 struct smb_filename
*smb_fname_tmp
= NULL
;
5554 files_struct
*new_fsp
= NULL
;
5556 if (!VALID_STAT(*psbuf
)) {
5557 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5560 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5562 if (size
== get_file_size_stat(psbuf
)) {
5563 return NT_STATUS_OK
;
5566 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5567 smb_fname_str_dbg(smb_fname
), (double)size
));
5569 if (fsp
&& fsp
->fh
->fd
!= -1) {
5570 /* Handle based call. */
5571 if (vfs_set_filelen(fsp
, size
) == -1) {
5572 return map_nt_error_from_unix(errno
);
5574 trigger_write_time_update_immediate(fsp
);
5575 return NT_STATUS_OK
;
5578 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5579 if (!NT_STATUS_IS_OK(status
)) {
5583 smb_fname_tmp
->st
= *psbuf
;
5585 status
= SMB_VFS_CREATE_FILE(
5588 0, /* root_dir_fid */
5589 smb_fname_tmp
, /* fname */
5590 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5591 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5593 FILE_OPEN
, /* create_disposition*/
5594 0, /* create_options */
5595 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5596 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5597 0, /* allocation_size */
5600 &new_fsp
, /* result */
5603 TALLOC_FREE(smb_fname_tmp
);
5605 if (!NT_STATUS_IS_OK(status
)) {
5606 /* NB. We check for open_was_deferred in the caller. */
5610 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5611 status
= map_nt_error_from_unix(errno
);
5612 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5616 trigger_write_time_update_immediate(new_fsp
);
5617 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5618 return NT_STATUS_OK
;
5621 /****************************************************************************
5622 Deal with SMB_INFO_SET_EA.
5623 ****************************************************************************/
5625 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5629 const struct smb_filename
*smb_fname
)
5631 struct ea_list
*ea_list
= NULL
;
5632 TALLOC_CTX
*ctx
= NULL
;
5633 NTSTATUS status
= NT_STATUS_OK
;
5635 if (total_data
< 10) {
5637 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5638 length. They seem to have no effect. Bug #3212. JRA */
5640 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5641 /* We're done. We only get EA info in this call. */
5642 return NT_STATUS_OK
;
5645 return NT_STATUS_INVALID_PARAMETER
;
5648 if (IVAL(pdata
,0) > total_data
) {
5649 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5650 IVAL(pdata
,0), (unsigned int)total_data
));
5651 return NT_STATUS_INVALID_PARAMETER
;
5655 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5657 return NT_STATUS_INVALID_PARAMETER
;
5659 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5664 /****************************************************************************
5665 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5666 ****************************************************************************/
5668 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5673 struct ea_list
*ea_list
= NULL
;
5677 return NT_STATUS_INVALID_HANDLE
;
5680 if (!lp_ea_support(SNUM(conn
))) {
5681 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5682 "EA's not supported.\n",
5683 (unsigned int)total_data
));
5684 return NT_STATUS_EAS_NOT_SUPPORTED
;
5687 if (total_data
< 10) {
5688 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5690 (unsigned int)total_data
));
5691 return NT_STATUS_INVALID_PARAMETER
;
5694 ea_list
= read_nttrans_ea_list(talloc_tos(),
5699 return NT_STATUS_INVALID_PARAMETER
;
5701 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5703 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5704 smb_fname_str_dbg(fsp
->fsp_name
),
5705 nt_errstr(status
) ));
5711 /****************************************************************************
5712 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5713 ****************************************************************************/
5715 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5719 const struct smb_filename
*smb_fname
)
5721 NTSTATUS status
= NT_STATUS_OK
;
5722 bool delete_on_close
;
5725 if (total_data
< 1) {
5726 return NT_STATUS_INVALID_PARAMETER
;
5730 return NT_STATUS_INVALID_HANDLE
;
5733 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5734 dosmode
= dos_mode(conn
, smb_fname
);
5736 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5737 "delete_on_close = %u\n",
5738 smb_fname_str_dbg(smb_fname
),
5739 (unsigned int)dosmode
,
5740 (unsigned int)delete_on_close
));
5742 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5744 if (!NT_STATUS_IS_OK(status
)) {
5748 /* The set is across all open files on this dev/inode pair. */
5749 if (!set_delete_on_close(fsp
, delete_on_close
,
5750 &conn
->server_info
->utok
)) {
5751 return NT_STATUS_ACCESS_DENIED
;
5753 return NT_STATUS_OK
;
5756 /****************************************************************************
5757 Deal with SMB_FILE_POSITION_INFORMATION.
5758 ****************************************************************************/
5760 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5765 uint64_t position_information
;
5767 if (total_data
< 8) {
5768 return NT_STATUS_INVALID_PARAMETER
;
5772 /* Ignore on pathname based set. */
5773 return NT_STATUS_OK
;
5776 position_information
= (uint64_t)IVAL(pdata
,0);
5777 #ifdef LARGE_SMB_OFF_T
5778 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5779 #else /* LARGE_SMB_OFF_T */
5780 if (IVAL(pdata
,4) != 0) {
5781 /* more than 32 bits? */
5782 return NT_STATUS_INVALID_PARAMETER
;
5784 #endif /* LARGE_SMB_OFF_T */
5786 DEBUG(10,("smb_file_position_information: Set file position "
5787 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5788 (double)position_information
));
5789 fsp
->fh
->position_information
= position_information
;
5790 return NT_STATUS_OK
;
5793 /****************************************************************************
5794 Deal with SMB_FILE_MODE_INFORMATION.
5795 ****************************************************************************/
5797 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5803 if (total_data
< 4) {
5804 return NT_STATUS_INVALID_PARAMETER
;
5806 mode
= IVAL(pdata
,0);
5807 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5808 return NT_STATUS_INVALID_PARAMETER
;
5810 return NT_STATUS_OK
;
5813 /****************************************************************************
5814 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5815 ****************************************************************************/
5817 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5818 struct smb_request
*req
,
5821 const struct smb_filename
*smb_fname
)
5823 char *link_target
= NULL
;
5824 const char *newname
= smb_fname
->base_name
;
5825 NTSTATUS status
= NT_STATUS_OK
;
5826 TALLOC_CTX
*ctx
= talloc_tos();
5828 /* Set a symbolic link. */
5829 /* Don't allow this if follow links is false. */
5831 if (total_data
== 0) {
5832 return NT_STATUS_INVALID_PARAMETER
;
5835 if (!lp_symlinks(SNUM(conn
))) {
5836 return NT_STATUS_ACCESS_DENIED
;
5839 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5840 total_data
, STR_TERMINATE
);
5843 return NT_STATUS_INVALID_PARAMETER
;
5846 /* !widelinks forces the target path to be within the share. */
5847 /* This means we can interpret the target as a pathname. */
5848 if (!lp_widelinks(SNUM(conn
))) {
5849 char *rel_name
= NULL
;
5850 char *last_dirp
= NULL
;
5852 if (*link_target
== '/') {
5853 /* No absolute paths allowed. */
5854 return NT_STATUS_ACCESS_DENIED
;
5856 rel_name
= talloc_strdup(ctx
,newname
);
5858 return NT_STATUS_NO_MEMORY
;
5860 last_dirp
= strrchr_m(rel_name
, '/');
5862 last_dirp
[1] = '\0';
5864 rel_name
= talloc_strdup(ctx
,"./");
5866 return NT_STATUS_NO_MEMORY
;
5869 rel_name
= talloc_asprintf_append(rel_name
,
5873 return NT_STATUS_NO_MEMORY
;
5876 status
= check_name(conn
, rel_name
);
5877 if (!NT_STATUS_IS_OK(status
)) {
5882 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5883 newname
, link_target
));
5885 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5886 return map_nt_error_from_unix(errno
);
5889 return NT_STATUS_OK
;
5892 /****************************************************************************
5893 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5894 ****************************************************************************/
5896 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5897 struct smb_request
*req
,
5898 const char *pdata
, int total_data
,
5899 const struct smb_filename
*smb_fname_new
)
5901 char *oldname
= NULL
;
5902 struct smb_filename
*smb_fname_old
= NULL
;
5903 TALLOC_CTX
*ctx
= talloc_tos();
5904 NTSTATUS status
= NT_STATUS_OK
;
5906 /* Set a hard link. */
5907 if (total_data
== 0) {
5908 return NT_STATUS_INVALID_PARAMETER
;
5911 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5912 total_data
, STR_TERMINATE
, &status
);
5913 if (!NT_STATUS_IS_OK(status
)) {
5917 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5918 smb_fname_str_dbg(smb_fname_new
), oldname
));
5920 status
= filename_convert(ctx
,
5922 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5927 if (!NT_STATUS_IS_OK(status
)) {
5931 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5934 /****************************************************************************
5935 Deal with SMB_FILE_RENAME_INFORMATION.
5936 ****************************************************************************/
5938 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5939 struct smb_request
*req
,
5943 struct smb_filename
*smb_fname_src
)
5948 char *newname
= NULL
;
5949 struct smb_filename
*smb_fname_dst
= NULL
;
5950 bool dest_has_wcard
= False
;
5951 NTSTATUS status
= NT_STATUS_OK
;
5953 TALLOC_CTX
*ctx
= talloc_tos();
5955 if (total_data
< 13) {
5956 return NT_STATUS_INVALID_PARAMETER
;
5959 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5960 root_fid
= IVAL(pdata
,4);
5961 len
= IVAL(pdata
,8);
5963 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5964 return NT_STATUS_INVALID_PARAMETER
;
5967 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5970 if (!NT_STATUS_IS_OK(status
)) {
5974 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5977 status
= resolve_dfspath_wcard(ctx
, conn
,
5978 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5982 if (!NT_STATUS_IS_OK(status
)) {
5986 /* Check the new name has no '/' characters. */
5987 if (strchr_m(newname
, '/')) {
5988 return NT_STATUS_NOT_SUPPORTED
;
5991 if (fsp
&& fsp
->base_fsp
) {
5992 /* newname must be a stream name. */
5993 if (newname
[0] != ':') {
5994 return NT_STATUS_NOT_SUPPORTED
;
5997 /* Create an smb_fname to call rename_internals_fsp() with. */
5998 status
= create_synthetic_smb_fname(talloc_tos(),
5999 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6001 if (!NT_STATUS_IS_OK(status
)) {
6006 * Set the original last component, since
6007 * rename_internals_fsp() requires it.
6009 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6011 if (smb_fname_dst
->original_lcomp
== NULL
) {
6012 status
= NT_STATUS_NO_MEMORY
;
6018 * Build up an smb_fname_dst based on the filename passed in.
6019 * We basically just strip off the last component, and put on
6020 * the newname instead.
6022 char *base_name
= NULL
;
6024 /* newname must *not* be a stream name. */
6025 if (newname
[0] == ':') {
6026 return NT_STATUS_NOT_SUPPORTED
;
6030 * Strip off the last component (filename) of the path passed
6033 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6035 return NT_STATUS_NO_MEMORY
;
6037 p
= strrchr_m(base_name
, '/');
6041 base_name
= talloc_strdup(ctx
, "./");
6043 return NT_STATUS_NO_MEMORY
;
6046 /* Append the new name. */
6047 base_name
= talloc_asprintf_append(base_name
,
6051 return NT_STATUS_NO_MEMORY
;
6054 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6057 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6060 /* If an error we expect this to be
6061 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6063 if (!NT_STATUS_IS_OK(status
)) {
6064 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6068 /* Create an smb_fname to call rename_internals_fsp() */
6069 status
= create_synthetic_smb_fname(ctx
,
6073 if (!NT_STATUS_IS_OK(status
)) {
6080 DEBUG(10,("smb_file_rename_information: "
6081 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6082 fsp
->fnum
, fsp_str_dbg(fsp
),
6083 smb_fname_str_dbg(smb_fname_dst
)));
6084 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6087 DEBUG(10,("smb_file_rename_information: "
6088 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6089 smb_fname_str_dbg(smb_fname_src
),
6090 smb_fname_str_dbg(smb_fname_dst
)));
6091 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6092 smb_fname_dst
, 0, overwrite
, false,
6094 FILE_WRITE_ATTRIBUTES
);
6097 TALLOC_FREE(smb_fname_dst
);
6101 /****************************************************************************
6102 Deal with SMB_SET_POSIX_ACL.
6103 ****************************************************************************/
6105 #if defined(HAVE_POSIX_ACLS)
6106 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6110 const struct smb_filename
*smb_fname
)
6112 uint16 posix_acl_version
;
6113 uint16 num_file_acls
;
6114 uint16 num_def_acls
;
6115 bool valid_file_acls
= True
;
6116 bool valid_def_acls
= True
;
6118 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6119 return NT_STATUS_INVALID_PARAMETER
;
6121 posix_acl_version
= SVAL(pdata
,0);
6122 num_file_acls
= SVAL(pdata
,2);
6123 num_def_acls
= SVAL(pdata
,4);
6125 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6126 valid_file_acls
= False
;
6130 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6131 valid_def_acls
= False
;
6135 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6136 return NT_STATUS_INVALID_PARAMETER
;
6139 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6140 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6141 return NT_STATUS_INVALID_PARAMETER
;
6144 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6145 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6146 (unsigned int)num_file_acls
,
6147 (unsigned int)num_def_acls
));
6149 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6150 smb_fname
->base_name
, num_file_acls
,
6151 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6152 return map_nt_error_from_unix(errno
);
6155 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6156 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6157 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6158 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6159 return map_nt_error_from_unix(errno
);
6161 return NT_STATUS_OK
;
6165 /****************************************************************************
6166 Deal with SMB_SET_POSIX_LOCK.
6167 ****************************************************************************/
6169 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6170 struct smb_request
*req
,
6178 bool blocking_lock
= False
;
6179 enum brl_type lock_type
;
6181 NTSTATUS status
= NT_STATUS_OK
;
6183 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6184 return NT_STATUS_INVALID_HANDLE
;
6187 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6188 return NT_STATUS_INVALID_PARAMETER
;
6191 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6192 case POSIX_LOCK_TYPE_READ
:
6193 lock_type
= READ_LOCK
;
6195 case POSIX_LOCK_TYPE_WRITE
:
6196 /* Return the right POSIX-mappable error code for files opened read-only. */
6197 if (!fsp
->can_write
) {
6198 return NT_STATUS_INVALID_HANDLE
;
6200 lock_type
= WRITE_LOCK
;
6202 case POSIX_LOCK_TYPE_UNLOCK
:
6203 lock_type
= UNLOCK_LOCK
;
6206 return NT_STATUS_INVALID_PARAMETER
;
6209 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6210 blocking_lock
= False
;
6211 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6212 blocking_lock
= True
;
6214 return NT_STATUS_INVALID_PARAMETER
;
6217 if (!lp_blocking_locks(SNUM(conn
))) {
6218 blocking_lock
= False
;
6221 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6222 #if defined(HAVE_LONGLONG)
6223 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6224 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6225 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6226 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6227 #else /* HAVE_LONGLONG */
6228 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6229 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6230 #endif /* HAVE_LONGLONG */
6232 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6233 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6235 (unsigned int)lock_type
,
6236 (unsigned int)lock_pid
,
6240 if (lock_type
== UNLOCK_LOCK
) {
6241 status
= do_unlock(smbd_messaging_context(),
6248 uint32 block_smbpid
;
6250 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6262 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6264 * A blocking lock was requested. Package up
6265 * this smb into a queued request and push it
6266 * onto the blocking lock queue.
6268 if(push_blocking_lock_request(br_lck
,
6271 -1, /* infinite timeout. */
6279 TALLOC_FREE(br_lck
);
6283 TALLOC_FREE(br_lck
);
6289 /****************************************************************************
6290 Deal with SMB_SET_FILE_BASIC_INFO.
6291 ****************************************************************************/
6293 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6297 const struct smb_filename
*smb_fname
)
6299 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6300 struct smb_file_time ft
;
6302 NTSTATUS status
= NT_STATUS_OK
;
6306 if (total_data
< 36) {
6307 return NT_STATUS_INVALID_PARAMETER
;
6310 /* Set the attributes */
6311 dosmode
= IVAL(pdata
,32);
6312 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6313 if (!NT_STATUS_IS_OK(status
)) {
6318 ft
.create_time
= interpret_long_date(pdata
);
6321 ft
.atime
= interpret_long_date(pdata
+8);
6324 ft
.mtime
= interpret_long_date(pdata
+16);
6327 ft
.ctime
= interpret_long_date(pdata
+24);
6329 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6330 smb_fname_str_dbg(smb_fname
)));
6332 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6336 /****************************************************************************
6337 Deal with SMB_INFO_STANDARD.
6338 ****************************************************************************/
6340 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6344 const struct smb_filename
*smb_fname
)
6346 struct smb_file_time ft
;
6350 if (total_data
< 12) {
6351 return NT_STATUS_INVALID_PARAMETER
;
6355 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6357 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6359 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6361 DEBUG(10,("smb_set_info_standard: file %s\n",
6362 smb_fname_str_dbg(smb_fname
)));
6364 return smb_set_file_time(conn
,
6371 /****************************************************************************
6372 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6373 ****************************************************************************/
6375 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6376 struct smb_request
*req
,
6380 struct smb_filename
*smb_fname
)
6382 uint64_t allocation_size
= 0;
6383 NTSTATUS status
= NT_STATUS_OK
;
6384 files_struct
*new_fsp
= NULL
;
6386 if (!VALID_STAT(smb_fname
->st
)) {
6387 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6390 if (total_data
< 8) {
6391 return NT_STATUS_INVALID_PARAMETER
;
6394 allocation_size
= (uint64_t)IVAL(pdata
,0);
6395 #ifdef LARGE_SMB_OFF_T
6396 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6397 #else /* LARGE_SMB_OFF_T */
6398 if (IVAL(pdata
,4) != 0) {
6399 /* more than 32 bits? */
6400 return NT_STATUS_INVALID_PARAMETER
;
6402 #endif /* LARGE_SMB_OFF_T */
6404 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6405 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6406 (double)allocation_size
));
6408 if (allocation_size
) {
6409 allocation_size
= smb_roundup(conn
, allocation_size
);
6412 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6413 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6414 (double)allocation_size
));
6416 if (fsp
&& fsp
->fh
->fd
!= -1) {
6417 /* Open file handle. */
6418 /* Only change if needed. */
6419 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6420 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6421 return map_nt_error_from_unix(errno
);
6424 /* But always update the time. */
6426 * This is equivalent to a write. Ensure it's seen immediately
6427 * if there are no pending writes.
6429 trigger_write_time_update_immediate(fsp
);
6430 return NT_STATUS_OK
;
6433 /* Pathname or stat or directory file. */
6434 status
= SMB_VFS_CREATE_FILE(
6437 0, /* root_dir_fid */
6438 smb_fname
, /* fname */
6439 FILE_WRITE_DATA
, /* access_mask */
6440 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6442 FILE_OPEN
, /* create_disposition*/
6443 0, /* create_options */
6444 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6445 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6446 0, /* allocation_size */
6449 &new_fsp
, /* result */
6452 if (!NT_STATUS_IS_OK(status
)) {
6453 /* NB. We check for open_was_deferred in the caller. */
6457 /* Only change if needed. */
6458 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6459 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6460 status
= map_nt_error_from_unix(errno
);
6461 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6466 /* Changing the allocation size should set the last mod time. */
6468 * This is equivalent to a write. Ensure it's seen immediately
6469 * if there are no pending writes.
6471 trigger_write_time_update_immediate(new_fsp
);
6473 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6474 return NT_STATUS_OK
;
6477 /****************************************************************************
6478 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6479 ****************************************************************************/
6481 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6482 struct smb_request
*req
,
6486 const struct smb_filename
*smb_fname
)
6490 if (total_data
< 8) {
6491 return NT_STATUS_INVALID_PARAMETER
;
6494 size
= IVAL(pdata
,0);
6495 #ifdef LARGE_SMB_OFF_T
6496 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6497 #else /* LARGE_SMB_OFF_T */
6498 if (IVAL(pdata
,4) != 0) {
6499 /* more than 32 bits? */
6500 return NT_STATUS_INVALID_PARAMETER
;
6502 #endif /* LARGE_SMB_OFF_T */
6503 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6504 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6507 return smb_set_file_size(conn
, req
,
6514 /****************************************************************************
6515 Allow a UNIX info mknod.
6516 ****************************************************************************/
6518 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6521 const struct smb_filename
*smb_fname
)
6523 uint32 file_type
= IVAL(pdata
,56);
6524 #if defined(HAVE_MAKEDEV)
6525 uint32 dev_major
= IVAL(pdata
,60);
6526 uint32 dev_minor
= IVAL(pdata
,68);
6528 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6529 uint32 raw_unixmode
= IVAL(pdata
,84);
6533 if (total_data
< 100) {
6534 return NT_STATUS_INVALID_PARAMETER
;
6537 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6538 PERM_NEW_FILE
, &unixmode
);
6539 if (!NT_STATUS_IS_OK(status
)) {
6543 #if defined(HAVE_MAKEDEV)
6544 dev
= makedev(dev_major
, dev_minor
);
6547 switch (file_type
) {
6548 #if defined(S_IFIFO)
6549 case UNIX_TYPE_FIFO
:
6550 unixmode
|= S_IFIFO
;
6553 #if defined(S_IFSOCK)
6554 case UNIX_TYPE_SOCKET
:
6555 unixmode
|= S_IFSOCK
;
6558 #if defined(S_IFCHR)
6559 case UNIX_TYPE_CHARDEV
:
6560 unixmode
|= S_IFCHR
;
6563 #if defined(S_IFBLK)
6564 case UNIX_TYPE_BLKDEV
:
6565 unixmode
|= S_IFBLK
;
6569 return NT_STATUS_INVALID_PARAMETER
;
6572 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6573 "%.0f mode 0%o for file %s\n", (double)dev
,
6574 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6576 /* Ok - do the mknod. */
6577 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6578 return map_nt_error_from_unix(errno
);
6581 /* If any of the other "set" calls fail we
6582 * don't want to end up with a half-constructed mknod.
6585 if (lp_inherit_perms(SNUM(conn
))) {
6587 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6589 return NT_STATUS_NO_MEMORY
;
6591 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6593 TALLOC_FREE(parent
);
6596 return NT_STATUS_OK
;
6599 /****************************************************************************
6600 Deal with SMB_SET_FILE_UNIX_BASIC.
6601 ****************************************************************************/
6603 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6604 struct smb_request
*req
,
6608 const struct smb_filename
*smb_fname
)
6610 struct smb_file_time ft
;
6611 uint32 raw_unixmode
;
6614 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6615 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6616 NTSTATUS status
= NT_STATUS_OK
;
6617 bool delete_on_fail
= False
;
6618 enum perm_type ptype
;
6619 files_struct
*all_fsps
= NULL
;
6620 bool modify_mtime
= true;
6622 SMB_STRUCT_STAT sbuf
;
6626 if (total_data
< 100) {
6627 return NT_STATUS_INVALID_PARAMETER
;
6630 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6631 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6632 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6633 #ifdef LARGE_SMB_OFF_T
6634 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6635 #else /* LARGE_SMB_OFF_T */
6636 if (IVAL(pdata
,4) != 0) {
6637 /* more than 32 bits? */
6638 return NT_STATUS_INVALID_PARAMETER
;
6640 #endif /* LARGE_SMB_OFF_T */
6643 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6644 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6645 set_owner
= (uid_t
)IVAL(pdata
,40);
6646 set_grp
= (gid_t
)IVAL(pdata
,48);
6647 raw_unixmode
= IVAL(pdata
,84);
6649 if (VALID_STAT(smb_fname
->st
)) {
6650 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6651 ptype
= PERM_EXISTING_DIR
;
6653 ptype
= PERM_EXISTING_FILE
;
6656 ptype
= PERM_NEW_FILE
;
6659 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6661 if (!NT_STATUS_IS_OK(status
)) {
6665 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6666 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6667 smb_fname_str_dbg(smb_fname
), (double)size
,
6668 (unsigned int)set_owner
, (unsigned int)set_grp
,
6669 (int)raw_unixmode
));
6671 sbuf
= smb_fname
->st
;
6673 if (!VALID_STAT(sbuf
)) {
6674 struct smb_filename
*smb_fname_tmp
= NULL
;
6676 * The only valid use of this is to create character and block
6677 * devices, and named pipes. This is deprecated (IMHO) and
6678 * a new info level should be used for mknod. JRA.
6681 status
= smb_unix_mknod(conn
,
6685 if (!NT_STATUS_IS_OK(status
)) {
6689 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6691 if (!NT_STATUS_IS_OK(status
)) {
6695 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6696 status
= map_nt_error_from_unix(errno
);
6697 TALLOC_FREE(smb_fname_tmp
);
6698 SMB_VFS_UNLINK(conn
, smb_fname
);
6702 sbuf
= smb_fname_tmp
->st
;
6703 TALLOC_FREE(smb_fname_tmp
);
6705 /* Ensure we don't try and change anything else. */
6706 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6707 size
= get_file_size_stat(&sbuf
);
6708 ft
.atime
= sbuf
.st_ex_atime
;
6709 ft
.mtime
= sbuf
.st_ex_mtime
;
6711 * We continue here as we might want to change the
6714 delete_on_fail
= True
;
6718 /* Horrible backwards compatibility hack as an old server bug
6719 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6723 size
= get_file_size_stat(&sbuf
);
6728 * Deal with the UNIX specific mode set.
6731 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6732 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6733 "setting mode 0%o for file %s\n",
6734 (unsigned int)unixmode
,
6735 smb_fname_str_dbg(smb_fname
)));
6736 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6737 return map_nt_error_from_unix(errno
);
6742 * Deal with the UNIX specific uid set.
6745 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6746 (sbuf
.st_ex_uid
!= set_owner
)) {
6749 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6750 "changing owner %u for path %s\n",
6751 (unsigned int)set_owner
,
6752 smb_fname_str_dbg(smb_fname
)));
6754 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6755 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6756 set_owner
, (gid_t
)-1);
6758 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6759 set_owner
, (gid_t
)-1);
6763 status
= map_nt_error_from_unix(errno
);
6764 if (delete_on_fail
) {
6765 SMB_VFS_UNLINK(conn
, smb_fname
);
6772 * Deal with the UNIX specific gid set.
6775 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6776 (sbuf
.st_ex_gid
!= set_grp
)) {
6777 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6778 "changing group %u for file %s\n",
6779 (unsigned int)set_owner
,
6780 smb_fname_str_dbg(smb_fname
)));
6781 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6783 status
= map_nt_error_from_unix(errno
);
6784 if (delete_on_fail
) {
6785 SMB_VFS_UNLINK(conn
, smb_fname
);
6791 /* Deal with any size changes. */
6793 status
= smb_set_file_size(conn
, req
,
6798 if (!NT_STATUS_IS_OK(status
)) {
6802 /* Deal with any time changes. */
6803 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6804 /* No change, don't cancel anything. */
6808 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6809 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6810 all_fsps
= file_find_di_next(all_fsps
)) {
6812 * We're setting the time explicitly for UNIX.
6813 * Cancel any pending changes over all handles.
6815 all_fsps
->update_write_time_on_close
= false;
6816 TALLOC_FREE(all_fsps
->update_write_time_event
);
6820 * Override the "setting_write_time"
6821 * parameter here as it almost does what
6822 * we need. Just remember if we modified
6823 * mtime and send the notify ourselves.
6825 if (null_timespec(ft
.mtime
)) {
6826 modify_mtime
= false;
6829 status
= smb_set_file_time(conn
,
6835 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6836 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6841 /****************************************************************************
6842 Deal with SMB_SET_FILE_UNIX_INFO2.
6843 ****************************************************************************/
6845 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6846 struct smb_request
*req
,
6850 const struct smb_filename
*smb_fname
)
6856 if (total_data
< 116) {
6857 return NT_STATUS_INVALID_PARAMETER
;
6860 /* Start by setting all the fields that are common between UNIX_BASIC
6863 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6865 if (!NT_STATUS_IS_OK(status
)) {
6869 smb_fflags
= IVAL(pdata
, 108);
6870 smb_fmask
= IVAL(pdata
, 112);
6872 /* NB: We should only attempt to alter the file flags if the client
6873 * sends a non-zero mask.
6875 if (smb_fmask
!= 0) {
6876 int stat_fflags
= 0;
6878 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6879 smb_fmask
, &stat_fflags
)) {
6880 /* Client asked to alter a flag we don't understand. */
6881 return NT_STATUS_INVALID_PARAMETER
;
6884 if (fsp
&& fsp
->fh
->fd
!= -1) {
6885 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6886 return NT_STATUS_NOT_SUPPORTED
;
6888 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6889 stat_fflags
) != 0) {
6890 return map_nt_error_from_unix(errno
);
6895 /* XXX: need to add support for changing the create_time here. You
6896 * can do this for paths on Darwin with setattrlist(2). The right way
6897 * to hook this up is probably by extending the VFS utimes interface.
6900 return NT_STATUS_OK
;
6903 /****************************************************************************
6904 Create a directory with POSIX semantics.
6905 ****************************************************************************/
6907 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6908 struct smb_request
*req
,
6911 struct smb_filename
*smb_fname
,
6912 int *pdata_return_size
)
6914 NTSTATUS status
= NT_STATUS_OK
;
6915 uint32 raw_unixmode
= 0;
6916 uint32 mod_unixmode
= 0;
6917 mode_t unixmode
= (mode_t
)0;
6918 files_struct
*fsp
= NULL
;
6919 uint16 info_level_return
= 0;
6921 char *pdata
= *ppdata
;
6923 if (total_data
< 18) {
6924 return NT_STATUS_INVALID_PARAMETER
;
6927 raw_unixmode
= IVAL(pdata
,8);
6928 /* Next 4 bytes are not yet defined. */
6930 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6931 PERM_NEW_DIR
, &unixmode
);
6932 if (!NT_STATUS_IS_OK(status
)) {
6936 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6938 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6939 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6941 status
= SMB_VFS_CREATE_FILE(
6944 0, /* root_dir_fid */
6945 smb_fname
, /* fname */
6946 FILE_READ_ATTRIBUTES
, /* access_mask */
6947 FILE_SHARE_NONE
, /* share_access */
6948 FILE_CREATE
, /* create_disposition*/
6949 FILE_DIRECTORY_FILE
, /* create_options */
6950 mod_unixmode
, /* file_attributes */
6951 0, /* oplock_request */
6952 0, /* allocation_size */
6958 if (NT_STATUS_IS_OK(status
)) {
6959 close_file(req
, fsp
, NORMAL_CLOSE
);
6962 info_level_return
= SVAL(pdata
,16);
6964 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6965 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6966 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6967 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6969 *pdata_return_size
= 12;
6972 /* Realloc the data size */
6973 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6974 if (*ppdata
== NULL
) {
6975 *pdata_return_size
= 0;
6976 return NT_STATUS_NO_MEMORY
;
6980 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6981 SSVAL(pdata
,2,0); /* No fnum. */
6982 SIVAL(pdata
,4,info
); /* Was directory created. */
6984 switch (info_level_return
) {
6985 case SMB_QUERY_FILE_UNIX_BASIC
:
6986 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6987 SSVAL(pdata
,10,0); /* Padding. */
6988 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6991 case SMB_QUERY_FILE_UNIX_INFO2
:
6992 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6993 SSVAL(pdata
,10,0); /* Padding. */
6994 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6998 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6999 SSVAL(pdata
,10,0); /* Padding. */
7006 /****************************************************************************
7007 Open/Create a file with POSIX semantics.
7008 ****************************************************************************/
7010 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7011 struct smb_request
*req
,
7014 struct smb_filename
*smb_fname
,
7015 int *pdata_return_size
)
7017 bool extended_oplock_granted
= False
;
7018 char *pdata
= *ppdata
;
7020 uint32 wire_open_mode
= 0;
7021 uint32 raw_unixmode
= 0;
7022 uint32 mod_unixmode
= 0;
7023 uint32 create_disp
= 0;
7024 uint32 access_mask
= 0;
7025 uint32 create_options
= 0;
7026 NTSTATUS status
= NT_STATUS_OK
;
7027 mode_t unixmode
= (mode_t
)0;
7028 files_struct
*fsp
= NULL
;
7029 int oplock_request
= 0;
7031 uint16 info_level_return
= 0;
7033 if (total_data
< 18) {
7034 return NT_STATUS_INVALID_PARAMETER
;
7037 flags
= IVAL(pdata
,0);
7038 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7039 if (oplock_request
) {
7040 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7043 wire_open_mode
= IVAL(pdata
,4);
7045 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7046 return smb_posix_mkdir(conn
, req
,
7053 switch (wire_open_mode
& SMB_ACCMODE
) {
7055 access_mask
= FILE_READ_DATA
;
7058 access_mask
= FILE_WRITE_DATA
;
7061 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7064 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7065 (unsigned int)wire_open_mode
));
7066 return NT_STATUS_INVALID_PARAMETER
;
7069 wire_open_mode
&= ~SMB_ACCMODE
;
7071 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7072 create_disp
= FILE_CREATE
;
7073 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7074 create_disp
= FILE_OVERWRITE_IF
;
7075 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7076 create_disp
= FILE_OPEN_IF
;
7077 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7078 create_disp
= FILE_OPEN
;
7080 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7081 (unsigned int)wire_open_mode
));
7082 return NT_STATUS_INVALID_PARAMETER
;
7085 raw_unixmode
= IVAL(pdata
,8);
7086 /* Next 4 bytes are not yet defined. */
7088 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7089 (VALID_STAT(smb_fname
->st
) ?
7090 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7093 if (!NT_STATUS_IS_OK(status
)) {
7097 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7099 if (wire_open_mode
& SMB_O_SYNC
) {
7100 create_options
|= FILE_WRITE_THROUGH
;
7102 if (wire_open_mode
& SMB_O_APPEND
) {
7103 access_mask
|= FILE_APPEND_DATA
;
7105 if (wire_open_mode
& SMB_O_DIRECT
) {
7106 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7109 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7110 smb_fname_str_dbg(smb_fname
),
7111 (unsigned int)wire_open_mode
,
7112 (unsigned int)unixmode
));
7114 status
= SMB_VFS_CREATE_FILE(
7117 0, /* root_dir_fid */
7118 smb_fname
, /* fname */
7119 access_mask
, /* access_mask */
7120 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7122 create_disp
, /* create_disposition*/
7123 FILE_NON_DIRECTORY_FILE
, /* create_options */
7124 mod_unixmode
, /* file_attributes */
7125 oplock_request
, /* oplock_request */
7126 0, /* allocation_size */
7132 if (!NT_STATUS_IS_OK(status
)) {
7136 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7137 extended_oplock_granted
= True
;
7140 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7141 extended_oplock_granted
= True
;
7144 info_level_return
= SVAL(pdata
,16);
7146 /* Allocate the correct return size. */
7148 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7149 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7150 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7151 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7153 *pdata_return_size
= 12;
7156 /* Realloc the data size */
7157 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7158 if (*ppdata
== NULL
) {
7159 close_file(req
, fsp
, ERROR_CLOSE
);
7160 *pdata_return_size
= 0;
7161 return NT_STATUS_NO_MEMORY
;
7165 if (extended_oplock_granted
) {
7166 if (flags
& REQUEST_BATCH_OPLOCK
) {
7167 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7169 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7171 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7172 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7174 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7177 SSVAL(pdata
,2,fsp
->fnum
);
7178 SIVAL(pdata
,4,info
); /* Was file created etc. */
7180 switch (info_level_return
) {
7181 case SMB_QUERY_FILE_UNIX_BASIC
:
7182 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7183 SSVAL(pdata
,10,0); /* padding. */
7184 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7187 case SMB_QUERY_FILE_UNIX_INFO2
:
7188 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7189 SSVAL(pdata
,10,0); /* padding. */
7190 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7194 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7195 SSVAL(pdata
,10,0); /* padding. */
7198 return NT_STATUS_OK
;
7201 /****************************************************************************
7202 Delete a file with POSIX semantics.
7203 ****************************************************************************/
7205 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7206 struct smb_request
*req
,
7209 struct smb_filename
*smb_fname
)
7211 NTSTATUS status
= NT_STATUS_OK
;
7212 files_struct
*fsp
= NULL
;
7216 int create_options
= 0;
7218 struct share_mode_lock
*lck
= NULL
;
7220 if (total_data
< 2) {
7221 return NT_STATUS_INVALID_PARAMETER
;
7224 flags
= SVAL(pdata
,0);
7226 if (!VALID_STAT(smb_fname
->st
)) {
7227 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7230 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7231 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7232 return NT_STATUS_NOT_A_DIRECTORY
;
7235 DEBUG(10,("smb_posix_unlink: %s %s\n",
7236 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7237 smb_fname_str_dbg(smb_fname
)));
7239 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7240 create_options
|= FILE_DIRECTORY_FILE
;
7243 status
= SMB_VFS_CREATE_FILE(
7246 0, /* root_dir_fid */
7247 smb_fname
, /* fname */
7248 DELETE_ACCESS
, /* access_mask */
7249 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7251 FILE_OPEN
, /* create_disposition*/
7252 create_options
, /* create_options */
7253 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7254 0, /* oplock_request */
7255 0, /* allocation_size */
7261 if (!NT_STATUS_IS_OK(status
)) {
7266 * Don't lie to client. If we can't really delete due to
7267 * non-POSIX opens return SHARING_VIOLATION.
7270 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7273 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7274 "lock for file %s\n", fsp_str_dbg(fsp
)));
7275 close_file(req
, fsp
, NORMAL_CLOSE
);
7276 return NT_STATUS_INVALID_PARAMETER
;
7280 * See if others still have the file open. If this is the case, then
7281 * don't delete. If all opens are POSIX delete we can set the delete
7282 * on close disposition.
7284 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7285 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7286 if (is_valid_share_mode_entry(e
)) {
7287 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7290 /* Fail with sharing violation. */
7291 close_file(req
, fsp
, NORMAL_CLOSE
);
7293 return NT_STATUS_SHARING_VIOLATION
;
7298 * Set the delete on close.
7300 status
= smb_set_file_disposition_info(conn
,
7306 if (!NT_STATUS_IS_OK(status
)) {
7307 close_file(req
, fsp
, NORMAL_CLOSE
);
7312 return close_file(req
, fsp
, NORMAL_CLOSE
);
7315 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7316 struct smb_request
*req
,
7317 TALLOC_CTX
*mem_ctx
,
7318 uint16_t info_level
,
7320 struct smb_filename
*smb_fname
,
7321 char **ppdata
, int total_data
,
7324 char *pdata
= *ppdata
;
7325 NTSTATUS status
= NT_STATUS_OK
;
7326 int data_return_size
= 0;
7330 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7331 return NT_STATUS_INVALID_LEVEL
;
7334 if (!CAN_WRITE(conn
)) {
7335 /* Allow POSIX opens. The open path will deny
7336 * any non-readonly opens. */
7337 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7338 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7342 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7343 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7344 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7346 switch (info_level
) {
7348 case SMB_INFO_STANDARD
:
7350 status
= smb_set_info_standard(conn
,
7358 case SMB_INFO_SET_EA
:
7360 status
= smb_info_set_ea(conn
,
7368 case SMB_SET_FILE_BASIC_INFO
:
7369 case SMB_FILE_BASIC_INFORMATION
:
7371 status
= smb_set_file_basic_info(conn
,
7379 case SMB_FILE_ALLOCATION_INFORMATION
:
7380 case SMB_SET_FILE_ALLOCATION_INFO
:
7382 status
= smb_set_file_allocation_info(conn
, req
,
7390 case SMB_FILE_END_OF_FILE_INFORMATION
:
7391 case SMB_SET_FILE_END_OF_FILE_INFO
:
7393 status
= smb_set_file_end_of_file_info(conn
, req
,
7401 case SMB_FILE_DISPOSITION_INFORMATION
:
7402 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7405 /* JRA - We used to just ignore this on a path ?
7406 * Shouldn't this be invalid level on a pathname
7409 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7410 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7413 status
= smb_set_file_disposition_info(conn
,
7421 case SMB_FILE_POSITION_INFORMATION
:
7423 status
= smb_file_position_information(conn
,
7430 case SMB_FILE_FULL_EA_INFORMATION
:
7432 status
= smb_set_file_full_ea_info(conn
,
7439 /* From tridge Samba4 :
7440 * MODE_INFORMATION in setfileinfo (I have no
7441 * idea what "mode information" on a file is - it takes a value of 0,
7442 * 2, 4 or 6. What could it be?).
7445 case SMB_FILE_MODE_INFORMATION
:
7447 status
= smb_file_mode_information(conn
,
7454 * CIFS UNIX extensions.
7457 case SMB_SET_FILE_UNIX_BASIC
:
7459 status
= smb_set_file_unix_basic(conn
, req
,
7467 case SMB_SET_FILE_UNIX_INFO2
:
7469 status
= smb_set_file_unix_info2(conn
, req
,
7477 case SMB_SET_FILE_UNIX_LINK
:
7480 /* We must have a pathname for this. */
7481 return NT_STATUS_INVALID_LEVEL
;
7483 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7484 total_data
, smb_fname
);
7488 case SMB_SET_FILE_UNIX_HLINK
:
7491 /* We must have a pathname for this. */
7492 return NT_STATUS_INVALID_LEVEL
;
7494 status
= smb_set_file_unix_hlink(conn
, req
,
7500 case SMB_FILE_RENAME_INFORMATION
:
7502 status
= smb_file_rename_information(conn
, req
,
7508 #if defined(HAVE_POSIX_ACLS)
7509 case SMB_SET_POSIX_ACL
:
7511 status
= smb_set_posix_acl(conn
,
7520 case SMB_SET_POSIX_LOCK
:
7523 return NT_STATUS_INVALID_LEVEL
;
7525 status
= smb_set_posix_lock(conn
, req
,
7526 pdata
, total_data
, fsp
);
7530 case SMB_POSIX_PATH_OPEN
:
7533 /* We must have a pathname for this. */
7534 return NT_STATUS_INVALID_LEVEL
;
7537 status
= smb_posix_open(conn
, req
,
7545 case SMB_POSIX_PATH_UNLINK
:
7548 /* We must have a pathname for this. */
7549 return NT_STATUS_INVALID_LEVEL
;
7552 status
= smb_posix_unlink(conn
, req
,
7560 return NT_STATUS_INVALID_LEVEL
;
7563 if (!NT_STATUS_IS_OK(status
)) {
7567 *ret_data_size
= data_return_size
;
7568 return NT_STATUS_OK
;
7571 /****************************************************************************
7572 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7573 ****************************************************************************/
7575 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7576 struct smb_request
*req
,
7577 unsigned int tran_call
,
7578 char **pparams
, int total_params
,
7579 char **ppdata
, int total_data
,
7580 unsigned int max_data_bytes
)
7582 char *params
= *pparams
;
7583 char *pdata
= *ppdata
;
7585 struct smb_filename
*smb_fname
= NULL
;
7586 files_struct
*fsp
= NULL
;
7587 NTSTATUS status
= NT_STATUS_OK
;
7588 int data_return_size
= 0;
7591 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7595 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7596 if (total_params
< 4) {
7597 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7601 fsp
= file_fsp(req
, SVAL(params
,0));
7602 /* Basic check for non-null fsp. */
7603 if (!check_fsp_open(conn
, req
, fsp
)) {
7606 info_level
= SVAL(params
,2);
7608 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7610 if (!NT_STATUS_IS_OK(status
)) {
7611 reply_nterror(req
, status
);
7615 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7617 * This is actually a SETFILEINFO on a directory
7618 * handle (returned from an NT SMB). NT5.0 seems
7619 * to do this call. JRA.
7621 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7622 /* Always do lstat for UNIX calls. */
7623 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7624 DEBUG(3,("call_trans2setfilepathinfo: "
7625 "SMB_VFS_LSTAT of %s failed "
7627 smb_fname_str_dbg(smb_fname
),
7629 reply_nterror(req
, map_nt_error_from_unix(errno
));
7633 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7634 DEBUG(3,("call_trans2setfilepathinfo: "
7635 "fileinfo of %s failed (%s)\n",
7636 smb_fname_str_dbg(smb_fname
),
7638 reply_nterror(req
, map_nt_error_from_unix(errno
));
7642 } else if (fsp
->print_file
) {
7644 * Doing a DELETE_ON_CLOSE should cancel a print job.
7646 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7647 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7649 DEBUG(3,("call_trans2setfilepathinfo: "
7650 "Cancelling print job (%s)\n",
7654 send_trans2_replies(conn
, req
, params
, 2,
7659 reply_doserror(req
, ERRDOS
, ERRbadpath
);
7664 * Original code - this is an open file.
7666 if (!check_fsp(conn
, req
, fsp
)) {
7670 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7671 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7672 "of fnum %d failed (%s)\n", fsp
->fnum
,
7674 reply_nterror(req
, map_nt_error_from_unix(errno
));
7682 if (total_params
< 7) {
7683 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7687 info_level
= SVAL(params
,0);
7688 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7689 total_params
- 6, STR_TERMINATE
,
7691 if (!NT_STATUS_IS_OK(status
)) {
7692 reply_nterror(req
, status
);
7696 status
= filename_convert(req
, conn
,
7697 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7702 if (!NT_STATUS_IS_OK(status
)) {
7703 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7704 reply_botherror(req
,
7705 NT_STATUS_PATH_NOT_COVERED
,
7706 ERRSRV
, ERRbadpath
);
7709 reply_nterror(req
, status
);
7713 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7715 * For CIFS UNIX extensions the target name may not exist.
7718 /* Always do lstat for UNIX calls. */
7719 SMB_VFS_LSTAT(conn
, smb_fname
);
7721 } else if (!VALID_STAT(smb_fname
->st
) &&
7722 SMB_VFS_STAT(conn
, smb_fname
)) {
7723 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7725 smb_fname_str_dbg(smb_fname
),
7727 reply_nterror(req
, map_nt_error_from_unix(errno
));
7732 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7733 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7734 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7736 /* Realloc the parameter size */
7737 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7738 if (*pparams
== NULL
) {
7739 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7746 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7752 if (!NT_STATUS_IS_OK(status
)) {
7753 if (open_was_deferred(req
->mid
)) {
7754 /* We have re-scheduled this call. */
7757 if (blocking_lock_was_deferred(req
->mid
)) {
7758 /* We have re-scheduled this call. */
7761 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7762 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7763 ERRSRV
, ERRbadpath
);
7766 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7767 reply_openerror(req
, status
);
7771 reply_nterror(req
, status
);
7775 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7781 /****************************************************************************
7782 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7783 ****************************************************************************/
7785 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7786 char **pparams
, int total_params
,
7787 char **ppdata
, int total_data
,
7788 unsigned int max_data_bytes
)
7790 struct smb_filename
*smb_dname
= NULL
;
7791 char *params
= *pparams
;
7792 char *pdata
= *ppdata
;
7793 char *directory
= NULL
;
7794 NTSTATUS status
= NT_STATUS_OK
;
7795 struct ea_list
*ea_list
= NULL
;
7796 TALLOC_CTX
*ctx
= talloc_tos();
7798 if (!CAN_WRITE(conn
)) {
7799 reply_doserror(req
, ERRSRV
, ERRaccess
);
7803 if (total_params
< 5) {
7804 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7808 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7809 total_params
- 4, STR_TERMINATE
,
7811 if (!NT_STATUS_IS_OK(status
)) {
7812 reply_nterror(req
, status
);
7816 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7818 status
= filename_convert(ctx
,
7820 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7826 if (!NT_STATUS_IS_OK(status
)) {
7827 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7828 reply_botherror(req
,
7829 NT_STATUS_PATH_NOT_COVERED
,
7830 ERRSRV
, ERRbadpath
);
7833 reply_nterror(req
, status
);
7837 /* Any data in this call is an EA list. */
7838 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7839 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7844 * OS/2 workplace shell seems to send SET_EA requests of "null"
7845 * length (4 bytes containing IVAL 4).
7846 * They seem to have no effect. Bug #3212. JRA.
7849 if (total_data
!= 4) {
7850 if (total_data
< 10) {
7851 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7855 if (IVAL(pdata
,0) > total_data
) {
7856 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7857 IVAL(pdata
,0), (unsigned int)total_data
));
7858 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7862 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7869 /* If total_data == 4 Windows doesn't care what values
7870 * are placed in that field, it just ignores them.
7871 * The System i QNTC IBM SMB client puts bad values here,
7872 * so ignore them. */
7874 status
= create_directory(conn
, req
, smb_dname
);
7876 if (!NT_STATUS_IS_OK(status
)) {
7877 reply_nterror(req
, status
);
7881 /* Try and set any given EA. */
7883 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7884 if (!NT_STATUS_IS_OK(status
)) {
7885 reply_nterror(req
, status
);
7890 /* Realloc the parameter and data sizes */
7891 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7892 if(*pparams
== NULL
) {
7893 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7900 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7903 TALLOC_FREE(smb_dname
);
7907 /****************************************************************************
7908 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7909 We don't actually do this - we just send a null response.
7910 ****************************************************************************/
7912 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7913 struct smb_request
*req
,
7914 char **pparams
, int total_params
,
7915 char **ppdata
, int total_data
,
7916 unsigned int max_data_bytes
)
7918 char *params
= *pparams
;
7921 if (total_params
< 6) {
7922 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7926 info_level
= SVAL(params
,4);
7927 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7929 switch (info_level
) {
7934 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7938 /* Realloc the parameter and data sizes */
7939 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7940 if (*pparams
== NULL
) {
7941 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7946 SSVAL(params
,0,fnf_handle
);
7947 SSVAL(params
,2,0); /* No changes */
7948 SSVAL(params
,4,0); /* No EA errors */
7955 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7960 /****************************************************************************
7961 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7962 changes). Currently this does nothing.
7963 ****************************************************************************/
7965 static void call_trans2findnotifynext(connection_struct
*conn
,
7966 struct smb_request
*req
,
7967 char **pparams
, int total_params
,
7968 char **ppdata
, int total_data
,
7969 unsigned int max_data_bytes
)
7971 char *params
= *pparams
;
7973 DEBUG(3,("call_trans2findnotifynext\n"));
7975 /* Realloc the parameter and data sizes */
7976 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7977 if (*pparams
== NULL
) {
7978 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7983 SSVAL(params
,0,0); /* No changes */
7984 SSVAL(params
,2,0); /* No EA errors */
7986 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7991 /****************************************************************************
7992 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7993 ****************************************************************************/
7995 static void call_trans2getdfsreferral(connection_struct
*conn
,
7996 struct smb_request
*req
,
7997 char **pparams
, int total_params
,
7998 char **ppdata
, int total_data
,
7999 unsigned int max_data_bytes
)
8001 char *params
= *pparams
;
8002 char *pathname
= NULL
;
8004 int max_referral_level
;
8005 NTSTATUS status
= NT_STATUS_OK
;
8006 TALLOC_CTX
*ctx
= talloc_tos();
8008 DEBUG(10,("call_trans2getdfsreferral\n"));
8010 if (total_params
< 3) {
8011 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8015 max_referral_level
= SVAL(params
,0);
8017 if(!lp_host_msdfs()) {
8018 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
8022 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8023 total_params
- 2, STR_TERMINATE
);
8025 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8028 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8029 ppdata
,&status
)) < 0) {
8030 reply_nterror(req
, status
);
8034 SSVAL(req
->inbuf
, smb_flg2
,
8035 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8036 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8041 #define LMCAT_SPL 0x53
8042 #define LMFUNC_GETJOBID 0x60
8044 /****************************************************************************
8045 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8046 ****************************************************************************/
8048 static void call_trans2ioctl(connection_struct
*conn
,
8049 struct smb_request
*req
,
8050 char **pparams
, int total_params
,
8051 char **ppdata
, int total_data
,
8052 unsigned int max_data_bytes
)
8054 char *pdata
= *ppdata
;
8055 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8057 /* check for an invalid fid before proceeding */
8060 reply_doserror(req
, ERRDOS
, ERRbadfid
);
8064 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8065 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8066 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8067 if (*ppdata
== NULL
) {
8068 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8073 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8074 CAN ACCEPT THIS IN UNICODE. JRA. */
8076 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8077 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8078 global_myname(), 15,
8079 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8080 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8081 lp_servicename(SNUM(conn
)), 13,
8082 STR_ASCII
|STR_TERMINATE
); /* Service name */
8083 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8088 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8089 reply_doserror(req
, ERRSRV
, ERRerror
);
8092 /****************************************************************************
8093 Reply to a SMBfindclose (stop trans2 directory search).
8094 ****************************************************************************/
8096 void reply_findclose(struct smb_request
*req
)
8099 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8101 START_PROFILE(SMBfindclose
);
8104 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8105 END_PROFILE(SMBfindclose
);
8109 dptr_num
= SVALS(req
->vwv
+0, 0);
8111 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8113 dptr_close(sconn
, &dptr_num
);
8115 reply_outbuf(req
, 0, 0);
8117 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8119 END_PROFILE(SMBfindclose
);
8123 /****************************************************************************
8124 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8125 ****************************************************************************/
8127 void reply_findnclose(struct smb_request
*req
)
8131 START_PROFILE(SMBfindnclose
);
8134 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8135 END_PROFILE(SMBfindnclose
);
8139 dptr_num
= SVAL(req
->vwv
+0, 0);
8141 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8143 /* We never give out valid handles for a
8144 findnotifyfirst - so any dptr_num is ok here.
8147 reply_outbuf(req
, 0, 0);
8149 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8151 END_PROFILE(SMBfindnclose
);
8155 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8156 struct trans_state
*state
)
8158 if (Protocol
>= PROTOCOL_NT1
) {
8159 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8160 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8163 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8164 if (state
->call
!= TRANSACT2_QFSINFO
&&
8165 state
->call
!= TRANSACT2_SETFSINFO
) {
8166 DEBUG(0,("handle_trans2: encryption required "
8168 (unsigned int)state
->call
));
8169 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8174 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8176 /* Now we must call the relevant TRANS2 function */
8177 switch(state
->call
) {
8178 case TRANSACT2_OPEN
:
8180 START_PROFILE(Trans2_open
);
8181 call_trans2open(conn
, req
,
8182 &state
->param
, state
->total_param
,
8183 &state
->data
, state
->total_data
,
8184 state
->max_data_return
);
8185 END_PROFILE(Trans2_open
);
8189 case TRANSACT2_FINDFIRST
:
8191 START_PROFILE(Trans2_findfirst
);
8192 call_trans2findfirst(conn
, req
,
8193 &state
->param
, state
->total_param
,
8194 &state
->data
, state
->total_data
,
8195 state
->max_data_return
);
8196 END_PROFILE(Trans2_findfirst
);
8200 case TRANSACT2_FINDNEXT
:
8202 START_PROFILE(Trans2_findnext
);
8203 call_trans2findnext(conn
, req
,
8204 &state
->param
, state
->total_param
,
8205 &state
->data
, state
->total_data
,
8206 state
->max_data_return
);
8207 END_PROFILE(Trans2_findnext
);
8211 case TRANSACT2_QFSINFO
:
8213 START_PROFILE(Trans2_qfsinfo
);
8214 call_trans2qfsinfo(conn
, req
,
8215 &state
->param
, state
->total_param
,
8216 &state
->data
, state
->total_data
,
8217 state
->max_data_return
);
8218 END_PROFILE(Trans2_qfsinfo
);
8222 case TRANSACT2_SETFSINFO
:
8224 START_PROFILE(Trans2_setfsinfo
);
8225 call_trans2setfsinfo(conn
, req
,
8226 &state
->param
, state
->total_param
,
8227 &state
->data
, state
->total_data
,
8228 state
->max_data_return
);
8229 END_PROFILE(Trans2_setfsinfo
);
8233 case TRANSACT2_QPATHINFO
:
8234 case TRANSACT2_QFILEINFO
:
8236 START_PROFILE(Trans2_qpathinfo
);
8237 call_trans2qfilepathinfo(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_qpathinfo
);
8245 case TRANSACT2_SETPATHINFO
:
8246 case TRANSACT2_SETFILEINFO
:
8248 START_PROFILE(Trans2_setpathinfo
);
8249 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8250 &state
->param
, state
->total_param
,
8251 &state
->data
, state
->total_data
,
8252 state
->max_data_return
);
8253 END_PROFILE(Trans2_setpathinfo
);
8257 case TRANSACT2_FINDNOTIFYFIRST
:
8259 START_PROFILE(Trans2_findnotifyfirst
);
8260 call_trans2findnotifyfirst(conn
, req
,
8261 &state
->param
, state
->total_param
,
8262 &state
->data
, state
->total_data
,
8263 state
->max_data_return
);
8264 END_PROFILE(Trans2_findnotifyfirst
);
8268 case TRANSACT2_FINDNOTIFYNEXT
:
8270 START_PROFILE(Trans2_findnotifynext
);
8271 call_trans2findnotifynext(conn
, req
,
8272 &state
->param
, state
->total_param
,
8273 &state
->data
, state
->total_data
,
8274 state
->max_data_return
);
8275 END_PROFILE(Trans2_findnotifynext
);
8279 case TRANSACT2_MKDIR
:
8281 START_PROFILE(Trans2_mkdir
);
8282 call_trans2mkdir(conn
, req
,
8283 &state
->param
, state
->total_param
,
8284 &state
->data
, state
->total_data
,
8285 state
->max_data_return
);
8286 END_PROFILE(Trans2_mkdir
);
8290 case TRANSACT2_GET_DFS_REFERRAL
:
8292 START_PROFILE(Trans2_get_dfs_referral
);
8293 call_trans2getdfsreferral(conn
, req
,
8294 &state
->param
, state
->total_param
,
8295 &state
->data
, state
->total_data
,
8296 state
->max_data_return
);
8297 END_PROFILE(Trans2_get_dfs_referral
);
8301 case TRANSACT2_IOCTL
:
8303 START_PROFILE(Trans2_ioctl
);
8304 call_trans2ioctl(conn
, req
,
8305 &state
->param
, state
->total_param
,
8306 &state
->data
, state
->total_data
,
8307 state
->max_data_return
);
8308 END_PROFILE(Trans2_ioctl
);
8313 /* Error in request */
8314 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8315 reply_doserror(req
, ERRSRV
,ERRerror
);
8319 /****************************************************************************
8320 Reply to a SMBtrans2.
8321 ****************************************************************************/
8323 void reply_trans2(struct smb_request
*req
)
8325 connection_struct
*conn
= req
->conn
;
8330 unsigned int tran_call
;
8331 struct trans_state
*state
;
8334 START_PROFILE(SMBtrans2
);
8336 if (req
->wct
< 14) {
8337 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8338 END_PROFILE(SMBtrans2
);
8342 dsoff
= SVAL(req
->vwv
+12, 0);
8343 dscnt
= SVAL(req
->vwv
+11, 0);
8344 psoff
= SVAL(req
->vwv
+10, 0);
8345 pscnt
= SVAL(req
->vwv
+9, 0);
8346 tran_call
= SVAL(req
->vwv
+14, 0);
8348 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8349 if (!NT_STATUS_IS_OK(result
)) {
8350 DEBUG(2, ("Got invalid trans2 request: %s\n",
8351 nt_errstr(result
)));
8352 reply_nterror(req
, result
);
8353 END_PROFILE(SMBtrans2
);
8358 switch (tran_call
) {
8359 /* List the allowed trans2 calls on IPC$ */
8360 case TRANSACT2_OPEN
:
8361 case TRANSACT2_GET_DFS_REFERRAL
:
8362 case TRANSACT2_QFILEINFO
:
8363 case TRANSACT2_QFSINFO
:
8364 case TRANSACT2_SETFSINFO
:
8367 reply_doserror(req
, ERRSRV
, ERRaccess
);
8368 END_PROFILE(SMBtrans2
);
8373 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8374 DEBUG(0, ("talloc failed\n"));
8375 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8376 END_PROFILE(SMBtrans2
);
8380 state
->cmd
= SMBtrans2
;
8382 state
->mid
= req
->mid
;
8383 state
->vuid
= req
->vuid
;
8384 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8385 state
->setup
= NULL
;
8386 state
->total_param
= SVAL(req
->vwv
+0, 0);
8387 state
->param
= NULL
;
8388 state
->total_data
= SVAL(req
->vwv
+1, 0);
8390 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8391 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8392 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8393 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8394 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8396 state
->call
= tran_call
;
8398 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8399 is so as a sanity check */
8400 if (state
->setup_count
!= 1) {
8402 * Need to have rc=0 for ioctl to get job id for OS/2.
8403 * Network printing will fail if function is not successful.
8404 * Similar function in reply.c will be used if protocol
8405 * is LANMAN1.0 instead of LM1.2X002.
8406 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8407 * outbuf doesn't have to be set(only job id is used).
8409 if ( (state
->setup_count
== 4)
8410 && (tran_call
== TRANSACT2_IOCTL
)
8411 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8412 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8413 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8415 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8416 DEBUG(2,("Transaction is %d\n",tran_call
));
8418 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8419 END_PROFILE(SMBtrans2
);
8424 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8427 if (state
->total_data
) {
8429 if (trans_oob(state
->total_data
, 0, dscnt
)
8430 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8434 /* Can't use talloc here, the core routines do realloc on the
8435 * params and data. */
8436 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8437 if (state
->data
== NULL
) {
8438 DEBUG(0,("reply_trans2: data malloc fail for %u "
8439 "bytes !\n", (unsigned int)state
->total_data
));
8441 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8442 END_PROFILE(SMBtrans2
);
8446 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8449 if (state
->total_param
) {
8451 if (trans_oob(state
->total_param
, 0, pscnt
)
8452 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8456 /* Can't use talloc here, the core routines do realloc on the
8457 * params and data. */
8458 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8459 if (state
->param
== NULL
) {
8460 DEBUG(0,("reply_trans: param malloc fail for %u "
8461 "bytes !\n", (unsigned int)state
->total_param
));
8462 SAFE_FREE(state
->data
);
8464 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8465 END_PROFILE(SMBtrans2
);
8469 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8472 state
->received_data
= dscnt
;
8473 state
->received_param
= pscnt
;
8475 if ((state
->received_param
== state
->total_param
) &&
8476 (state
->received_data
== state
->total_data
)) {
8478 handle_trans2(conn
, req
, state
);
8480 SAFE_FREE(state
->data
);
8481 SAFE_FREE(state
->param
);
8483 END_PROFILE(SMBtrans2
);
8487 DLIST_ADD(conn
->pending_trans
, state
);
8489 /* We need to send an interim response then receive the rest
8490 of the parameter/data bytes */
8491 reply_outbuf(req
, 0, 0);
8492 show_msg((char *)req
->outbuf
);
8493 END_PROFILE(SMBtrans2
);
8498 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8499 SAFE_FREE(state
->data
);
8500 SAFE_FREE(state
->param
);
8502 END_PROFILE(SMBtrans2
);
8503 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8507 /****************************************************************************
8508 Reply to a SMBtranss2
8509 ****************************************************************************/
8511 void reply_transs2(struct smb_request
*req
)
8513 connection_struct
*conn
= req
->conn
;
8514 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8515 struct trans_state
*state
;
8517 START_PROFILE(SMBtranss2
);
8519 show_msg((char *)req
->inbuf
);
8522 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8523 END_PROFILE(SMBtranss2
);
8527 for (state
= conn
->pending_trans
; state
!= NULL
;
8528 state
= state
->next
) {
8529 if (state
->mid
== req
->mid
) {
8534 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8536 END_PROFILE(SMBtranss2
);
8540 /* Revise state->total_param and state->total_data in case they have
8541 changed downwards */
8543 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8544 state
->total_param
= SVAL(req
->vwv
+0, 0);
8545 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8546 state
->total_data
= SVAL(req
->vwv
+1, 0);
8548 pcnt
= SVAL(req
->vwv
+2, 0);
8549 poff
= SVAL(req
->vwv
+3, 0);
8550 pdisp
= SVAL(req
->vwv
+4, 0);
8552 dcnt
= SVAL(req
->vwv
+5, 0);
8553 doff
= SVAL(req
->vwv
+6, 0);
8554 ddisp
= SVAL(req
->vwv
+7, 0);
8556 state
->received_param
+= pcnt
;
8557 state
->received_data
+= dcnt
;
8559 if ((state
->received_data
> state
->total_data
) ||
8560 (state
->received_param
> state
->total_param
))
8564 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8565 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8568 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8572 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8573 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8576 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8579 if ((state
->received_param
< state
->total_param
) ||
8580 (state
->received_data
< state
->total_data
)) {
8581 END_PROFILE(SMBtranss2
);
8585 handle_trans2(conn
, req
, state
);
8587 DLIST_REMOVE(conn
->pending_trans
, state
);
8588 SAFE_FREE(state
->data
);
8589 SAFE_FREE(state
->param
);
8592 END_PROFILE(SMBtranss2
);
8597 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8598 DLIST_REMOVE(conn
->pending_trans
, state
);
8599 SAFE_FREE(state
->data
);
8600 SAFE_FREE(state
->param
);
8602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8603 END_PROFILE(SMBtranss2
);