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 */
1529 memset(pdata
, 0, pad
);
1531 space_remaining
-= pad
;
1540 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1542 switch (info_level
) {
1543 case SMB_FIND_INFO_STANDARD
:
1544 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1545 if(requires_resume_key
) {
1549 srv_put_dos_date2(p
,0,create_date
);
1550 srv_put_dos_date2(p
,4,adate
);
1551 srv_put_dos_date2(p
,8,mdate
);
1552 SIVAL(p
,12,(uint32
)file_size
);
1553 SIVAL(p
,16,(uint32
)allocation_size
);
1557 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1558 p
+= ucs2_align(base_data
, p
, 0);
1560 len
= srvstr_push(base_data
, flags2
, p
,
1561 fname
, PTR_DIFF(end_data
, p
),
1563 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1565 SCVAL(nameptr
, -1, len
- 2);
1567 SCVAL(nameptr
, -1, 0);
1571 SCVAL(nameptr
, -1, len
- 1);
1573 SCVAL(nameptr
, -1, 0);
1579 case SMB_FIND_EA_SIZE
:
1580 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1581 if (requires_resume_key
) {
1585 srv_put_dos_date2(p
,0,create_date
);
1586 srv_put_dos_date2(p
,4,adate
);
1587 srv_put_dos_date2(p
,8,mdate
);
1588 SIVAL(p
,12,(uint32
)file_size
);
1589 SIVAL(p
,16,(uint32
)allocation_size
);
1592 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1593 smb_fname
->base_name
);
1594 SIVAL(p
,22,ea_size
); /* Extended attributes */
1598 len
= srvstr_push(base_data
, flags2
,
1599 p
, fname
, PTR_DIFF(end_data
, p
),
1600 STR_TERMINATE
| STR_NOALIGN
);
1601 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1614 SCVAL(nameptr
,0,len
);
1616 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1619 case SMB_FIND_EA_LIST
:
1621 struct ea_list
*file_list
= NULL
;
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1628 if (requires_resume_key
) {
1632 srv_put_dos_date2(p
,0,create_date
);
1633 srv_put_dos_date2(p
,4,adate
);
1634 srv_put_dos_date2(p
,8,mdate
);
1635 SIVAL(p
,12,(uint32
)file_size
);
1636 SIVAL(p
,16,(uint32
)allocation_size
);
1638 p
+= 22; /* p now points to the EA area. */
1640 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1641 smb_fname
->base_name
,
1643 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1645 /* We need to determine if this entry will fit in the space available. */
1646 /* Max string size is 255 bytes. */
1647 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1648 *out_of_space
= true;
1649 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1650 return False
; /* Not finished - just out of space */
1653 /* Push the ea_data followed by the name. */
1654 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1656 len
= srvstr_push(base_data
, flags2
,
1657 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1658 STR_TERMINATE
| STR_NOALIGN
);
1659 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1672 SCVAL(nameptr
,0,len
);
1674 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1678 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1679 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1680 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1682 SIVAL(p
,0,reskey
); p
+= 4;
1683 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1684 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1685 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1686 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1687 SOFF_T(p
,0,file_size
); p
+= 8;
1688 SOFF_T(p
,0,allocation_size
); p
+= 8;
1689 SIVAL(p
,0,nt_extmode
); p
+= 4;
1690 q
= p
; p
+= 4; /* q is placeholder for name length. */
1692 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1693 smb_fname
->base_name
);
1694 SIVAL(p
,0,ea_size
); /* Extended attributes */
1697 /* Clear the short name buffer. This is
1698 * IMPORTANT as not doing so will trigger
1699 * a Win2k client bug. JRA.
1701 if (!was_8_3
&& check_mangled_names
) {
1702 char mangled_name
[13]; /* mangled 8.3 name. */
1703 if (!name_to_8_3(fname
,mangled_name
,True
,
1705 /* Error - mangle failed ! */
1706 memset(mangled_name
,'\0',12);
1708 mangled_name
[12] = 0;
1709 len
= srvstr_push(base_data
, flags2
,
1710 p
+2, mangled_name
, 24,
1711 STR_UPPER
|STR_UNICODE
);
1713 memset(p
+ 2 + len
,'\0',24 - len
);
1720 len
= srvstr_push(base_data
, flags2
, p
,
1721 fname
, PTR_DIFF(end_data
, p
),
1722 STR_TERMINATE_ASCII
);
1726 len
= PTR_DIFF(p
, pdata
);
1727 pad
= (len
+ (align
-1)) & ~(align
-1);
1729 * offset to the next entry, the caller
1730 * will overwrite it for the last entry
1731 * that's why we always include the padding
1735 * set padding to zero
1738 memset(p
, 0, pad
- len
);
1745 case SMB_FIND_FILE_DIRECTORY_INFO
:
1746 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1748 SIVAL(p
,0,reskey
); p
+= 4;
1749 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1750 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1751 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1752 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1753 SOFF_T(p
,0,file_size
); p
+= 8;
1754 SOFF_T(p
,0,allocation_size
); p
+= 8;
1755 SIVAL(p
,0,nt_extmode
); p
+= 4;
1756 len
= srvstr_push(base_data
, flags2
,
1757 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1758 STR_TERMINATE_ASCII
);
1762 len
= PTR_DIFF(p
, pdata
);
1763 pad
= (len
+ (align
-1)) & ~(align
-1);
1765 * offset to the next entry, the caller
1766 * will overwrite it for the last entry
1767 * that's why we always include the padding
1771 * set padding to zero
1774 memset(p
, 0, pad
- len
);
1781 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1782 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1784 SIVAL(p
,0,reskey
); p
+= 4;
1785 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1787 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1788 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1789 SOFF_T(p
,0,file_size
); p
+= 8;
1790 SOFF_T(p
,0,allocation_size
); p
+= 8;
1791 SIVAL(p
,0,nt_extmode
); p
+= 4;
1792 q
= p
; p
+= 4; /* q is placeholder for name length. */
1794 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1795 smb_fname
->base_name
);
1796 SIVAL(p
,0,ea_size
); /* Extended attributes */
1799 len
= srvstr_push(base_data
, flags2
, p
,
1800 fname
, PTR_DIFF(end_data
, p
),
1801 STR_TERMINATE_ASCII
);
1805 len
= PTR_DIFF(p
, pdata
);
1806 pad
= (len
+ (align
-1)) & ~(align
-1);
1808 * offset to the next entry, the caller
1809 * will overwrite it for the last entry
1810 * that's why we always include the padding
1814 * set padding to zero
1817 memset(p
, 0, pad
- len
);
1824 case SMB_FIND_FILE_NAMES_INFO
:
1825 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1827 SIVAL(p
,0,reskey
); p
+= 4;
1829 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1830 acl on a dir (tridge) */
1831 len
= srvstr_push(base_data
, flags2
, p
,
1832 fname
, PTR_DIFF(end_data
, p
),
1833 STR_TERMINATE_ASCII
);
1837 len
= PTR_DIFF(p
, pdata
);
1838 pad
= (len
+ (align
-1)) & ~(align
-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1846 * set padding to zero
1849 memset(p
, 0, pad
- len
);
1856 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1859 SIVAL(p
,0,reskey
); p
+= 4;
1860 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1862 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1863 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1864 SOFF_T(p
,0,file_size
); p
+= 8;
1865 SOFF_T(p
,0,allocation_size
); p
+= 8;
1866 SIVAL(p
,0,nt_extmode
); p
+= 4;
1867 q
= p
; p
+= 4; /* q is placeholder for name length. */
1869 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1870 smb_fname
->base_name
);
1871 SIVAL(p
,0,ea_size
); /* Extended attributes */
1874 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1875 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1876 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1877 len
= srvstr_push(base_data
, flags2
, p
,
1878 fname
, PTR_DIFF(end_data
, p
),
1879 STR_TERMINATE_ASCII
);
1883 len
= PTR_DIFF(p
, pdata
);
1884 pad
= (len
+ (align
-1)) & ~(align
-1);
1886 * offset to the next entry, the caller
1887 * will overwrite it for the last entry
1888 * that's why we always include the padding
1892 * set padding to zero
1895 memset(p
, 0, pad
- len
);
1902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1903 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1904 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1906 SIVAL(p
,0,reskey
); p
+= 4;
1907 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1908 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1909 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1910 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1911 SOFF_T(p
,0,file_size
); p
+= 8;
1912 SOFF_T(p
,0,allocation_size
); p
+= 8;
1913 SIVAL(p
,0,nt_extmode
); p
+= 4;
1914 q
= p
; p
+= 4; /* q is placeholder for name length */
1916 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1917 smb_fname
->base_name
);
1918 SIVAL(p
,0,ea_size
); /* Extended attributes */
1921 /* Clear the short name buffer. This is
1922 * IMPORTANT as not doing so will trigger
1923 * a Win2k client bug. JRA.
1925 if (!was_8_3
&& check_mangled_names
) {
1926 char mangled_name
[13]; /* mangled 8.3 name. */
1927 if (!name_to_8_3(fname
,mangled_name
,True
,
1929 /* Error - mangle failed ! */
1930 memset(mangled_name
,'\0',12);
1932 mangled_name
[12] = 0;
1933 len
= srvstr_push(base_data
, flags2
,
1934 p
+2, mangled_name
, 24,
1935 STR_UPPER
|STR_UNICODE
);
1938 memset(p
+ 2 + len
,'\0',24 - len
);
1945 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1946 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1947 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1948 len
= srvstr_push(base_data
, flags2
, p
,
1949 fname
, PTR_DIFF(end_data
, p
),
1950 STR_TERMINATE_ASCII
);
1954 len
= PTR_DIFF(p
, pdata
);
1955 pad
= (len
+ (align
-1)) & ~(align
-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1963 * set padding to zero
1966 memset(p
, 0, pad
- len
);
1973 /* CIFS UNIX Extension. */
1975 case SMB_FIND_FILE_UNIX
:
1976 case SMB_FIND_FILE_UNIX_INFO2
:
1978 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1980 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1982 if (info_level
== SMB_FIND_FILE_UNIX
) {
1983 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1984 p
= store_file_unix_basic(conn
, p
,
1985 NULL
, &smb_fname
->st
);
1986 len
= srvstr_push(base_data
, flags2
, p
,
1987 fname
, PTR_DIFF(end_data
, p
),
1990 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1991 p
= store_file_unix_basic_info2(conn
, p
,
1992 NULL
, &smb_fname
->st
);
1995 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1996 PTR_DIFF(end_data
, p
), 0);
1997 SIVAL(nameptr
, 0, len
);
2002 len
= PTR_DIFF(p
, pdata
);
2003 pad
= (len
+ (align
-1)) & ~(align
-1);
2005 * offset to the next entry, the caller
2006 * will overwrite it for the last entry
2007 * that's why we always include the padding
2011 * set padding to zero
2014 memset(p
, 0, pad
- len
);
2019 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2028 *out_of_space
= true;
2029 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2030 return false; /* Not finished - just out of space */
2033 /* Setup the last entry pointer, as an offset from base_data */
2034 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2035 /* Advance the data pointer to the next slot */
2041 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2042 connection_struct
*conn
,
2043 struct dptr_struct
*dirptr
,
2045 const char *path_mask
,
2048 int requires_resume_key
,
2056 int space_remaining
,
2058 bool *got_exact_match
,
2059 int *_last_entry_off
,
2060 struct ea_list
*name_list
)
2063 const char *mask
= NULL
;
2064 long prev_dirpos
= 0;
2067 struct smb_filename
*smb_fname
= NULL
;
2068 struct smbd_dirptr_lanman2_state state
;
2070 uint64_t last_entry_off
= 0;
2074 state
.info_level
= info_level
;
2075 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2076 state
.has_wild
= dptr_has_wild(dirptr
);
2077 state
.got_exact_match
= false;
2079 *out_of_space
= false;
2080 *got_exact_match
= false;
2082 p
= strrchr_m(path_mask
,'/');
2093 ok
= smbd_dirptr_get_entry(ctx
,
2099 smbd_dirptr_lanman2_match_fn
,
2100 smbd_dirptr_lanman2_mode_fn
,
2110 *got_exact_match
= state
.got_exact_match
;
2112 ok
= smbd_marshall_dir_entry(ctx
,
2117 state
.check_mangled_names
,
2118 requires_resume_key
,
2131 TALLOC_FREE(smb_fname
);
2132 if (*out_of_space
) {
2133 dptr_SeekDir(dirptr
, prev_dirpos
);
2140 *_last_entry_off
= last_entry_off
;
2144 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2145 connection_struct
*conn
,
2146 struct dptr_struct
*dirptr
,
2148 const char *path_mask
,
2151 bool requires_resume_key
,
2157 int space_remaining
,
2159 bool *got_exact_match
,
2160 int *last_entry_off
,
2161 struct ea_list
*name_list
)
2164 const bool do_pad
= true;
2166 if (info_level
>= 1 && info_level
<= 3) {
2167 /* No alignment on earlier info levels. */
2171 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2172 path_mask
, dirtype
, info_level
,
2173 requires_resume_key
, dont_descend
, ask_sharemode
,
2175 ppdata
, base_data
, end_data
,
2177 out_of_space
, got_exact_match
,
2178 last_entry_off
, name_list
);
2181 /****************************************************************************
2182 Reply to a TRANS2_FINDFIRST.
2183 ****************************************************************************/
2185 static void call_trans2findfirst(connection_struct
*conn
,
2186 struct smb_request
*req
,
2187 char **pparams
, int total_params
,
2188 char **ppdata
, int total_data
,
2189 unsigned int max_data_bytes
)
2191 /* We must be careful here that we don't return more than the
2192 allowed number of data bytes. If this means returning fewer than
2193 maxentries then so be it. We assume that the redirector has
2194 enough room for the fixed number of parameter bytes it has
2196 struct smb_filename
*smb_dname
= NULL
;
2197 char *params
= *pparams
;
2198 char *pdata
= *ppdata
;
2202 uint16 findfirst_flags
;
2203 bool close_after_first
;
2205 bool requires_resume_key
;
2207 char *directory
= NULL
;
2210 int last_entry_off
=0;
2214 bool finished
= False
;
2215 bool dont_descend
= False
;
2216 bool out_of_space
= False
;
2217 int space_remaining
;
2218 bool mask_contains_wcard
= False
;
2219 struct ea_list
*ea_list
= NULL
;
2220 NTSTATUS ntstatus
= NT_STATUS_OK
;
2221 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2222 TALLOC_CTX
*ctx
= talloc_tos();
2223 struct dptr_struct
*dirptr
= NULL
;
2224 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2226 if (total_params
< 13) {
2227 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2231 dirtype
= SVAL(params
,0);
2232 maxentries
= SVAL(params
,2);
2233 findfirst_flags
= SVAL(params
,4);
2234 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2235 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2236 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2237 info_level
= SVAL(params
,6);
2239 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2240 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2241 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2242 info_level
, max_data_bytes
));
2245 /* W2K3 seems to treat zero as 1. */
2249 switch (info_level
) {
2250 case SMB_FIND_INFO_STANDARD
:
2251 case SMB_FIND_EA_SIZE
:
2252 case SMB_FIND_EA_LIST
:
2253 case SMB_FIND_FILE_DIRECTORY_INFO
:
2254 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2255 case SMB_FIND_FILE_NAMES_INFO
:
2256 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2257 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2258 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2260 case SMB_FIND_FILE_UNIX
:
2261 case SMB_FIND_FILE_UNIX_INFO2
:
2262 /* Always use filesystem for UNIX mtime query. */
2263 ask_sharemode
= false;
2264 if (!lp_unix_extensions()) {
2265 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2270 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2274 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2275 params
+12, total_params
- 12,
2276 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2277 if (!NT_STATUS_IS_OK(ntstatus
)) {
2278 reply_nterror(req
, ntstatus
);
2282 ntstatus
= filename_convert(ctx
, conn
,
2283 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2286 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2287 &mask_contains_wcard
,
2289 if (!NT_STATUS_IS_OK(ntstatus
)) {
2290 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2291 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2292 ERRSRV
, ERRbadpath
);
2295 reply_nterror(req
, ntstatus
);
2299 mask
= smb_dname
->original_lcomp
;
2301 directory
= smb_dname
->base_name
;
2303 p
= strrchr_m(directory
,'/');
2305 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2306 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2307 mask
= talloc_strdup(ctx
,"*");
2309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2312 mask_contains_wcard
= True
;
2314 directory
= talloc_strdup(talloc_tos(), "./");
2316 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2323 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2325 if (info_level
== SMB_FIND_EA_LIST
) {
2328 if (total_data
< 4) {
2329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2333 ea_size
= IVAL(pdata
,0);
2334 if (ea_size
!= total_data
) {
2335 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2336 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2337 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2341 if (!lp_ea_support(SNUM(conn
))) {
2342 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2346 /* Pull out the list of names. */
2347 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2349 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2354 *ppdata
= (char *)SMB_REALLOC(
2355 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2356 if(*ppdata
== NULL
) {
2357 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2361 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2363 /* Realloc the params space */
2364 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2365 if (*pparams
== NULL
) {
2366 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2371 /* Save the wildcard match and attribs we are using on this directory -
2372 needed as lanman2 assumes these are being saved between calls */
2374 ntstatus
= dptr_create(conn
,
2380 mask_contains_wcard
,
2384 if (!NT_STATUS_IS_OK(ntstatus
)) {
2385 reply_nterror(req
, ntstatus
);
2389 dptr_num
= dptr_dnum(dirptr
);
2390 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2392 /* Initialize per TRANS2_FIND_FIRST operation data */
2393 dptr_init_search_op(dirptr
);
2395 /* We don't need to check for VOL here as this is returned by
2396 a different TRANS2 call. */
2398 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2399 directory
,lp_dontdescend(SNUM(conn
))));
2400 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2401 dont_descend
= True
;
2404 space_remaining
= max_data_bytes
;
2405 out_of_space
= False
;
2407 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2408 bool got_exact_match
= False
;
2410 /* this is a heuristic to avoid seeking the dirptr except when
2411 absolutely necessary. It allows for a filename of about 40 chars */
2412 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2413 out_of_space
= True
;
2416 finished
= !get_lanman2_dir_entry(ctx
,
2420 mask
,dirtype
,info_level
,
2421 requires_resume_key
,dont_descend
,
2424 space_remaining
, &out_of_space
,
2426 &last_entry_off
, ea_list
);
2429 if (finished
&& out_of_space
)
2432 if (!finished
&& !out_of_space
)
2436 * As an optimisation if we know we aren't looking
2437 * for a wildcard name (ie. the name matches the wildcard exactly)
2438 * then we can finish on any (first) match.
2439 * This speeds up large directory searches. JRA.
2445 /* Ensure space_remaining never goes -ve. */
2446 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2447 space_remaining
= 0;
2448 out_of_space
= true;
2450 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2454 /* Check if we can close the dirptr */
2455 if(close_after_first
|| (finished
&& close_if_end
)) {
2456 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2457 dptr_close(sconn
, &dptr_num
);
2461 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2462 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2463 * the protocol level is less than NT1. Tested with smbclient. JRA.
2464 * This should fix the OS/2 client bug #2335.
2467 if(numentries
== 0) {
2468 dptr_close(sconn
, &dptr_num
);
2469 if (Protocol
< PROTOCOL_NT1
) {
2470 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2473 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2474 ERRDOS
, ERRbadfile
);
2479 /* At this point pdata points to numentries directory entries. */
2481 /* Set up the return parameter block */
2482 SSVAL(params
,0,dptr_num
);
2483 SSVAL(params
,2,numentries
);
2484 SSVAL(params
,4,finished
);
2485 SSVAL(params
,6,0); /* Never an EA error */
2486 SSVAL(params
,8,last_entry_off
);
2488 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2491 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2492 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2494 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2498 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2499 smb_fn_name(req
->cmd
),
2500 mask
, directory
, dirtype
, numentries
) );
2503 * Force a name mangle here to ensure that the
2504 * mask as an 8.3 name is top of the mangled cache.
2505 * The reasons for this are subtle. Don't remove
2506 * this code unless you know what you are doing
2507 * (see PR#13758). JRA.
2510 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2511 char mangled_name
[13];
2512 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2515 TALLOC_FREE(smb_dname
);
2519 /****************************************************************************
2520 Reply to a TRANS2_FINDNEXT.
2521 ****************************************************************************/
2523 static void call_trans2findnext(connection_struct
*conn
,
2524 struct smb_request
*req
,
2525 char **pparams
, int total_params
,
2526 char **ppdata
, int total_data
,
2527 unsigned int max_data_bytes
)
2529 /* We must be careful here that we don't return more than the
2530 allowed number of data bytes. If this means returning fewer than
2531 maxentries then so be it. We assume that the redirector has
2532 enough room for the fixed number of parameter bytes it has
2534 char *params
= *pparams
;
2535 char *pdata
= *ppdata
;
2541 uint16 findnext_flags
;
2542 bool close_after_request
;
2544 bool requires_resume_key
;
2546 bool mask_contains_wcard
= False
;
2547 char *resume_name
= NULL
;
2548 const char *mask
= NULL
;
2549 const char *directory
= NULL
;
2553 int i
, last_entry_off
=0;
2554 bool finished
= False
;
2555 bool dont_descend
= False
;
2556 bool out_of_space
= False
;
2557 int space_remaining
;
2558 struct ea_list
*ea_list
= NULL
;
2559 NTSTATUS ntstatus
= NT_STATUS_OK
;
2560 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2561 TALLOC_CTX
*ctx
= talloc_tos();
2562 struct dptr_struct
*dirptr
;
2563 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2565 if (total_params
< 13) {
2566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2570 dptr_num
= SVAL(params
,0);
2571 maxentries
= SVAL(params
,2);
2572 info_level
= SVAL(params
,4);
2573 resume_key
= IVAL(params
,6);
2574 findnext_flags
= SVAL(params
,10);
2575 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2576 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2577 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2578 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2580 if (!continue_bit
) {
2581 /* We only need resume_name if continue_bit is zero. */
2582 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2584 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2585 &mask_contains_wcard
);
2586 if (!NT_STATUS_IS_OK(ntstatus
)) {
2587 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2588 complain (it thinks we're asking for the directory above the shared
2589 path or an invalid name). Catch this as the resume name is only compared, never used in
2590 a file access. JRA. */
2591 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2592 &resume_name
, params
+12,
2596 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2597 reply_nterror(req
, ntstatus
);
2603 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2604 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2605 resume_key = %d resume name = %s continue=%d level = %d\n",
2606 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2607 requires_resume_key
, resume_key
,
2608 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2611 /* W2K3 seems to treat zero as 1. */
2615 switch (info_level
) {
2616 case SMB_FIND_INFO_STANDARD
:
2617 case SMB_FIND_EA_SIZE
:
2618 case SMB_FIND_EA_LIST
:
2619 case SMB_FIND_FILE_DIRECTORY_INFO
:
2620 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2621 case SMB_FIND_FILE_NAMES_INFO
:
2622 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2623 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2624 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2626 case SMB_FIND_FILE_UNIX
:
2627 case SMB_FIND_FILE_UNIX_INFO2
:
2628 /* Always use filesystem for UNIX mtime query. */
2629 ask_sharemode
= false;
2630 if (!lp_unix_extensions()) {
2631 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2636 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2640 if (info_level
== SMB_FIND_EA_LIST
) {
2643 if (total_data
< 4) {
2644 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2648 ea_size
= IVAL(pdata
,0);
2649 if (ea_size
!= total_data
) {
2650 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2651 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2652 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2656 if (!lp_ea_support(SNUM(conn
))) {
2657 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2661 /* Pull out the list of names. */
2662 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2664 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2669 *ppdata
= (char *)SMB_REALLOC(
2670 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2671 if(*ppdata
== NULL
) {
2672 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2677 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2679 /* Realloc the params space */
2680 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2681 if(*pparams
== NULL
) {
2682 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2688 /* Check that the dptr is valid */
2689 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2690 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2694 directory
= dptr_path(sconn
, dptr_num
);
2696 /* Get the wildcard mask from the dptr */
2697 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2698 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2699 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2705 /* Get the attr mask from the dptr */
2706 dirtype
= dptr_attr(sconn
, dptr_num
);
2708 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2709 dptr_num
, mask
, dirtype
,
2711 dptr_TellDir(dirptr
)));
2713 /* Initialize per TRANS2_FIND_NEXT operation data */
2714 dptr_init_search_op(dirptr
);
2716 /* We don't need to check for VOL here as this is returned by
2717 a different TRANS2 call. */
2719 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2720 directory
,lp_dontdescend(SNUM(conn
))));
2721 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2722 dont_descend
= True
;
2725 space_remaining
= max_data_bytes
;
2726 out_of_space
= False
;
2729 * Seek to the correct position. We no longer use the resume key but
2730 * depend on the last file name instead.
2733 if(!continue_bit
&& resume_name
&& *resume_name
) {
2736 long current_pos
= 0;
2738 * Remember, name_to_8_3 is called by
2739 * get_lanman2_dir_entry(), so the resume name
2740 * could be mangled. Ensure we check the unmangled name.
2743 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2744 char *new_resume_name
= NULL
;
2745 mangle_lookup_name_from_8_3(ctx
,
2749 if (new_resume_name
) {
2750 resume_name
= new_resume_name
;
2755 * Fix for NT redirector problem triggered by resume key indexes
2756 * changing between directory scans. We now return a resume key of 0
2757 * and instead look for the filename to continue from (also given
2758 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2759 * findfirst/findnext (as is usual) then the directory pointer
2760 * should already be at the correct place.
2763 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2764 } /* end if resume_name && !continue_bit */
2766 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2767 bool got_exact_match
= False
;
2769 /* this is a heuristic to avoid seeking the dirptr except when
2770 absolutely necessary. It allows for a filename of about 40 chars */
2771 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2772 out_of_space
= True
;
2775 finished
= !get_lanman2_dir_entry(ctx
,
2779 mask
,dirtype
,info_level
,
2780 requires_resume_key
,dont_descend
,
2783 space_remaining
, &out_of_space
,
2785 &last_entry_off
, ea_list
);
2788 if (finished
&& out_of_space
)
2791 if (!finished
&& !out_of_space
)
2795 * As an optimisation if we know we aren't looking
2796 * for a wildcard name (ie. the name matches the wildcard exactly)
2797 * then we can finish on any (first) match.
2798 * This speeds up large directory searches. JRA.
2804 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2807 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2808 smb_fn_name(req
->cmd
),
2809 mask
, directory
, dirtype
, numentries
) );
2811 /* Check if we can close the dirptr */
2812 if(close_after_request
|| (finished
&& close_if_end
)) {
2813 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2814 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2817 /* Set up the return parameter block */
2818 SSVAL(params
,0,numentries
);
2819 SSVAL(params
,2,finished
);
2820 SSVAL(params
,4,0); /* Never an EA error */
2821 SSVAL(params
,6,last_entry_off
);
2823 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2829 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2831 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2835 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2837 SMB_ASSERT(extended_info
!= NULL
);
2839 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2840 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2841 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2842 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2843 #ifdef SAMBA_VERSION_REVISION
2844 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2846 extended_info
->samba_subversion
= 0;
2847 #ifdef SAMBA_VERSION_RC_RELEASE
2848 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2850 #ifdef SAMBA_VERSION_PRE_RELEASE
2851 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2854 #ifdef SAMBA_VERSION_VENDOR_PATCH
2855 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2857 extended_info
->samba_gitcommitdate
= 0;
2858 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2859 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2862 memset(extended_info
->samba_version_string
, 0,
2863 sizeof(extended_info
->samba_version_string
));
2865 snprintf (extended_info
->samba_version_string
,
2866 sizeof(extended_info
->samba_version_string
),
2867 "%s", samba_version_string());
2870 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2871 TALLOC_CTX
*mem_ctx
,
2872 uint16_t info_level
,
2874 unsigned int max_data_bytes
,
2878 char *pdata
, *end_data
;
2879 int data_len
= 0, len
;
2880 const char *vname
= volume_label(SNUM(conn
));
2881 int snum
= SNUM(conn
);
2882 char *fstype
= lp_fstype(SNUM(conn
));
2883 uint32 additional_flags
= 0;
2884 struct smb_filename
*smb_fname_dot
= NULL
;
2889 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2890 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2891 "info level (0x%x) on IPC$.\n",
2892 (unsigned int)info_level
));
2893 return NT_STATUS_ACCESS_DENIED
;
2897 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2899 status
= create_synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
,
2901 if (!NT_STATUS_IS_OK(status
)) {
2905 if(SMB_VFS_STAT(conn
, smb_fname_dot
) != 0) {
2906 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2907 TALLOC_FREE(smb_fname_dot
);
2908 return map_nt_error_from_unix(errno
);
2911 st
= smb_fname_dot
->st
;
2912 TALLOC_FREE(smb_fname_dot
);
2914 *ppdata
= (char *)SMB_REALLOC(
2915 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2916 if (*ppdata
== NULL
) {
2917 return NT_STATUS_NO_MEMORY
;
2921 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2922 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2924 switch (info_level
) {
2925 case SMB_INFO_ALLOCATION
:
2927 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2929 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2930 return map_nt_error_from_unix(errno
);
2933 block_size
= lp_block_size(snum
);
2934 if (bsize
< block_size
) {
2935 uint64_t factor
= block_size
/bsize
;
2940 if (bsize
> block_size
) {
2941 uint64_t factor
= bsize
/block_size
;
2946 bytes_per_sector
= 512;
2947 sectors_per_unit
= bsize
/bytes_per_sector
;
2949 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2950 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2951 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2953 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2954 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2955 SIVAL(pdata
,l1_cUnit
,dsize
);
2956 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2957 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2961 case SMB_INFO_VOLUME
:
2962 /* Return volume name */
2964 * Add volume serial number - hash of a combination of
2965 * the called hostname and the service name.
2967 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2969 * Win2k3 and previous mess this up by sending a name length
2970 * one byte short. I believe only older clients (OS/2 Win9x) use
2971 * this call so try fixing this by adding a terminating null to
2972 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2976 pdata
+l2_vol_szVolLabel
, vname
,
2977 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2978 STR_NOALIGN
|STR_TERMINATE
);
2979 SCVAL(pdata
,l2_vol_cch
,len
);
2980 data_len
= l2_vol_szVolLabel
+ len
;
2981 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2982 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2986 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2987 case SMB_FS_ATTRIBUTE_INFORMATION
:
2989 additional_flags
= 0;
2990 #if defined(HAVE_SYS_QUOTAS)
2991 additional_flags
|= FILE_VOLUME_QUOTAS
;
2994 if(lp_nt_acl_support(SNUM(conn
))) {
2995 additional_flags
|= FILE_PERSISTENT_ACLS
;
2998 /* Capabilities are filled in at connection time through STATVFS call */
2999 additional_flags
|= conn
->fs_capabilities
;
3000 additional_flags
|= lp_parm_int(conn
->params
->service
,
3001 "share", "fake_fscaps",
3004 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3005 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3006 additional_flags
); /* FS ATTRIBUTES */
3008 SIVAL(pdata
,4,255); /* Max filename component length */
3009 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3010 and will think we can't do long filenames */
3011 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3012 PTR_DIFF(end_data
, pdata
+12),
3015 data_len
= 12 + len
;
3018 case SMB_QUERY_FS_LABEL_INFO
:
3019 case SMB_FS_LABEL_INFORMATION
:
3020 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3021 PTR_DIFF(end_data
, pdata
+4), 0);
3026 case SMB_QUERY_FS_VOLUME_INFO
:
3027 case SMB_FS_VOLUME_INFORMATION
:
3030 * Add volume serial number - hash of a combination of
3031 * the called hostname and the service name.
3033 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3034 (str_checksum(get_local_machine_name())<<16));
3036 /* Max label len is 32 characters. */
3037 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3038 PTR_DIFF(end_data
, pdata
+18),
3040 SIVAL(pdata
,12,len
);
3043 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3044 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3047 case SMB_QUERY_FS_SIZE_INFO
:
3048 case SMB_FS_SIZE_INFORMATION
:
3050 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3052 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3053 return map_nt_error_from_unix(errno
);
3055 block_size
= lp_block_size(snum
);
3056 if (bsize
< block_size
) {
3057 uint64_t factor
= block_size
/bsize
;
3062 if (bsize
> block_size
) {
3063 uint64_t factor
= bsize
/block_size
;
3068 bytes_per_sector
= 512;
3069 sectors_per_unit
= bsize
/bytes_per_sector
;
3070 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3071 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3072 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3073 SBIG_UINT(pdata
,0,dsize
);
3074 SBIG_UINT(pdata
,8,dfree
);
3075 SIVAL(pdata
,16,sectors_per_unit
);
3076 SIVAL(pdata
,20,bytes_per_sector
);
3080 case SMB_FS_FULL_SIZE_INFORMATION
:
3082 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3084 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno
);
3087 block_size
= lp_block_size(snum
);
3088 if (bsize
< block_size
) {
3089 uint64_t factor
= block_size
/bsize
;
3094 if (bsize
> block_size
) {
3095 uint64_t factor
= bsize
/block_size
;
3100 bytes_per_sector
= 512;
3101 sectors_per_unit
= bsize
/bytes_per_sector
;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3104 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3105 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3106 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3107 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3108 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3109 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3113 case SMB_QUERY_FS_DEVICE_INFO
:
3114 case SMB_FS_DEVICE_INFORMATION
:
3116 SIVAL(pdata
,0,0); /* dev type */
3117 SIVAL(pdata
,4,0); /* characteristics */
3120 #ifdef HAVE_SYS_QUOTAS
3121 case SMB_FS_QUOTA_INFORMATION
:
3123 * what we have to send --metze:
3125 * Unknown1: 24 NULL bytes
3126 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3127 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3128 * Quota Flags: 2 byte :
3129 * Unknown3: 6 NULL bytes
3133 * details for Quota Flags:
3135 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3136 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3137 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3138 * 0x0001 Enable Quotas: enable quota for this fs
3142 /* we need to fake up a fsp here,
3143 * because its not send in this call
3146 SMB_NTQUOTA_STRUCT quotas
;
3149 ZERO_STRUCT(quotas
);
3155 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3156 DEBUG(0,("set_user_quota: access_denied "
3157 "service [%s] user [%s]\n",
3158 lp_servicename(SNUM(conn
)),
3159 conn
->server_info
->unix_name
));
3160 return NT_STATUS_ACCESS_DENIED
;
3163 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3164 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3165 return map_nt_error_from_unix(errno
);
3170 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3171 lp_servicename(SNUM(conn
))));
3173 /* Unknown1 24 NULL bytes*/
3174 SBIG_UINT(pdata
,0,(uint64_t)0);
3175 SBIG_UINT(pdata
,8,(uint64_t)0);
3176 SBIG_UINT(pdata
,16,(uint64_t)0);
3178 /* Default Soft Quota 8 bytes */
3179 SBIG_UINT(pdata
,24,quotas
.softlim
);
3181 /* Default Hard Quota 8 bytes */
3182 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3184 /* Quota flag 2 bytes */
3185 SSVAL(pdata
,40,quotas
.qflags
);
3187 /* Unknown3 6 NULL bytes */
3193 #endif /* HAVE_SYS_QUOTAS */
3194 case SMB_FS_OBJECTID_INFORMATION
:
3196 unsigned char objid
[16];
3197 struct smb_extended_info extended_info
;
3198 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3199 samba_extended_info_version (&extended_info
);
3200 SIVAL(pdata
,16,extended_info
.samba_magic
);
3201 SIVAL(pdata
,20,extended_info
.samba_version
);
3202 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3203 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3204 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3210 * Query the version and capabilities of the CIFS UNIX extensions
3214 case SMB_QUERY_CIFS_UNIX_INFO
:
3216 bool large_write
= lp_min_receive_file_size() &&
3217 !srv_is_signing_active(smbd_server_conn
);
3218 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3219 int encrypt_caps
= 0;
3221 if (!lp_unix_extensions()) {
3222 return NT_STATUS_INVALID_LEVEL
;
3225 switch (conn
->encrypt_level
) {
3231 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3234 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3235 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3236 large_write
= false;
3242 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3243 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3245 /* We have POSIX ACLs, pathname, encryption,
3246 * large read/write, and locking capability. */
3248 SBIG_UINT(pdata
,4,((uint64_t)(
3249 CIFS_UNIX_POSIX_ACLS_CAP
|
3250 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3251 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3252 CIFS_UNIX_EXTATTR_CAP
|
3253 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3255 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3257 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3261 case SMB_QUERY_POSIX_FS_INFO
:
3264 vfs_statvfs_struct svfs
;
3266 if (!lp_unix_extensions()) {
3267 return NT_STATUS_INVALID_LEVEL
;
3270 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3274 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3275 SIVAL(pdata
,4,svfs
.BlockSize
);
3276 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3277 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3278 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3279 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3280 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3281 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3282 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3284 } else if (rc
== EOPNOTSUPP
) {
3285 return NT_STATUS_INVALID_LEVEL
;
3286 #endif /* EOPNOTSUPP */
3288 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3289 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3294 case SMB_QUERY_POSIX_WHOAMI
:
3300 if (!lp_unix_extensions()) {
3301 return NT_STATUS_INVALID_LEVEL
;
3304 if (max_data_bytes
< 40) {
3305 return NT_STATUS_BUFFER_TOO_SMALL
;
3308 /* We ARE guest if global_sid_Builtin_Guests is
3309 * in our list of SIDs.
3311 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3312 conn
->server_info
->ptok
)) {
3313 flags
|= SMB_WHOAMI_GUEST
;
3316 /* We are NOT guest if global_sid_Authenticated_Users
3317 * is in our list of SIDs.
3319 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3320 conn
->server_info
->ptok
)) {
3321 flags
&= ~SMB_WHOAMI_GUEST
;
3324 /* NOTE: 8 bytes for UID/GID, irrespective of native
3325 * platform size. This matches
3326 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3328 data_len
= 4 /* flags */
3335 + 4 /* pad/reserved */
3336 + (conn
->server_info
->utok
.ngroups
* 8)
3338 + (conn
->server_info
->ptok
->num_sids
*
3342 SIVAL(pdata
, 0, flags
);
3343 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3345 (uint64_t)conn
->server_info
->utok
.uid
);
3346 SBIG_UINT(pdata
, 16,
3347 (uint64_t)conn
->server_info
->utok
.gid
);
3350 if (data_len
>= max_data_bytes
) {
3351 /* Potential overflow, skip the GIDs and SIDs. */
3353 SIVAL(pdata
, 24, 0); /* num_groups */
3354 SIVAL(pdata
, 28, 0); /* num_sids */
3355 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3356 SIVAL(pdata
, 36, 0); /* reserved */
3362 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3363 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3365 /* We walk the SID list twice, but this call is fairly
3366 * infrequent, and I don't expect that it's performance
3367 * sensitive -- jpeach
3369 for (i
= 0, sid_bytes
= 0;
3370 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3371 sid_bytes
+= ndr_size_dom_sid(
3372 &conn
->server_info
->ptok
->user_sids
[i
],
3377 /* SID list byte count */
3378 SIVAL(pdata
, 32, sid_bytes
);
3380 /* 4 bytes pad/reserved - must be zero */
3381 SIVAL(pdata
, 36, 0);
3385 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3386 SBIG_UINT(pdata
, data_len
,
3387 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3393 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3394 int sid_len
= ndr_size_dom_sid(
3395 &conn
->server_info
->ptok
->user_sids
[i
],
3399 sid_linearize(pdata
+ data_len
, sid_len
,
3400 &conn
->server_info
->ptok
->user_sids
[i
]);
3401 data_len
+= sid_len
;
3407 case SMB_MAC_QUERY_FS_INFO
:
3409 * Thursby MAC extension... ONLY on NTFS filesystems
3410 * once we do streams then we don't need this
3412 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3414 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3419 return NT_STATUS_INVALID_LEVEL
;
3422 *ret_data_len
= data_len
;
3423 return NT_STATUS_OK
;
3426 /****************************************************************************
3427 Reply to a TRANS2_QFSINFO (query filesystem info).
3428 ****************************************************************************/
3430 static void call_trans2qfsinfo(connection_struct
*conn
,
3431 struct smb_request
*req
,
3432 char **pparams
, int total_params
,
3433 char **ppdata
, int total_data
,
3434 unsigned int max_data_bytes
)
3436 char *params
= *pparams
;
3437 uint16_t info_level
;
3441 if (total_params
< 2) {
3442 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3446 info_level
= SVAL(params
,0);
3448 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3449 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3450 DEBUG(0,("call_trans2qfsinfo: encryption required "
3451 "and info level 0x%x sent.\n",
3452 (unsigned int)info_level
));
3453 exit_server_cleanly("encryption required "
3459 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3461 status
= smbd_do_qfsinfo(conn
, req
,
3466 if (!NT_STATUS_IS_OK(status
)) {
3467 reply_nterror(req
, status
);
3471 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3474 DEBUG( 4, ( "%s info_level = %d\n",
3475 smb_fn_name(req
->cmd
), info_level
) );
3480 /****************************************************************************
3481 Reply to a TRANS2_SETFSINFO (set filesystem info).
3482 ****************************************************************************/
3484 static void call_trans2setfsinfo(connection_struct
*conn
,
3485 struct smb_request
*req
,
3486 char **pparams
, int total_params
,
3487 char **ppdata
, int total_data
,
3488 unsigned int max_data_bytes
)
3490 char *pdata
= *ppdata
;
3491 char *params
= *pparams
;
3494 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3497 if (total_params
< 4) {
3498 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3500 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3504 info_level
= SVAL(params
,2);
3507 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3508 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3509 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3510 "info level (0x%x) on IPC$.\n",
3511 (unsigned int)info_level
));
3512 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3517 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3518 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3519 DEBUG(0,("call_trans2setfsinfo: encryption required "
3520 "and info level 0x%x sent.\n",
3521 (unsigned int)info_level
));
3522 exit_server_cleanly("encryption required "
3528 switch(info_level
) {
3529 case SMB_SET_CIFS_UNIX_INFO
:
3531 uint16 client_unix_major
;
3532 uint16 client_unix_minor
;
3533 uint32 client_unix_cap_low
;
3534 uint32 client_unix_cap_high
;
3536 if (!lp_unix_extensions()) {
3538 NT_STATUS_INVALID_LEVEL
);
3542 /* There should be 12 bytes of capabilities set. */
3543 if (total_data
< 8) {
3546 NT_STATUS_INVALID_PARAMETER
);
3549 client_unix_major
= SVAL(pdata
,0);
3550 client_unix_minor
= SVAL(pdata
,2);
3551 client_unix_cap_low
= IVAL(pdata
,4);
3552 client_unix_cap_high
= IVAL(pdata
,8);
3553 /* Just print these values for now. */
3554 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3555 cap_low = 0x%x, cap_high = 0x%x\n",
3556 (unsigned int)client_unix_major
,
3557 (unsigned int)client_unix_minor
,
3558 (unsigned int)client_unix_cap_low
,
3559 (unsigned int)client_unix_cap_high
));
3561 /* Here is where we must switch to posix pathname processing... */
3562 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3563 lp_set_posix_pathnames();
3564 mangle_change_to_posix();
3567 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3568 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3569 /* Client that knows how to do posix locks,
3570 * but not posix open/mkdir operations. Set a
3571 * default type for read/write checks. */
3573 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3579 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3582 size_t param_len
= 0;
3583 size_t data_len
= total_data
;
3585 if (!lp_unix_extensions()) {
3588 NT_STATUS_INVALID_LEVEL
);
3592 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3595 NT_STATUS_NOT_SUPPORTED
);
3599 DEBUG( 4,("call_trans2setfsinfo: "
3600 "request transport encryption.\n"));
3602 status
= srv_request_encryption_setup(conn
,
3603 (unsigned char **)ppdata
,
3605 (unsigned char **)pparams
,
3608 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3609 !NT_STATUS_IS_OK(status
)) {
3610 reply_nterror(req
, status
);
3614 send_trans2_replies(conn
, req
,
3621 if (NT_STATUS_IS_OK(status
)) {
3622 /* Server-side transport
3623 * encryption is now *on*. */
3624 status
= srv_encryption_start(conn
);
3625 if (!NT_STATUS_IS_OK(status
)) {
3626 exit_server_cleanly(
3627 "Failure in setting "
3628 "up encrypted transport");
3634 case SMB_FS_QUOTA_INFORMATION
:
3636 files_struct
*fsp
= NULL
;
3637 SMB_NTQUOTA_STRUCT quotas
;
3639 ZERO_STRUCT(quotas
);
3642 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3643 ||!CAN_WRITE(conn
)) {
3644 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3645 lp_servicename(SNUM(conn
)),
3646 conn
->server_info
->unix_name
));
3647 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3651 /* note: normaly there're 48 bytes,
3652 * but we didn't use the last 6 bytes for now
3655 fsp
= file_fsp(req
, SVAL(params
,0));
3657 if (!check_fsp_ntquota_handle(conn
, req
,
3659 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3661 req
, NT_STATUS_INVALID_HANDLE
);
3665 if (total_data
< 42) {
3666 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3670 NT_STATUS_INVALID_PARAMETER
);
3674 /* unknown_1 24 NULL bytes in pdata*/
3676 /* the soft quotas 8 bytes (uint64_t)*/
3677 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3678 #ifdef LARGE_SMB_OFF_T
3679 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3680 #else /* LARGE_SMB_OFF_T */
3681 if ((IVAL(pdata
,28) != 0)&&
3682 ((quotas
.softlim
!= 0xFFFFFFFF)||
3683 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3684 /* more than 32 bits? */
3687 NT_STATUS_INVALID_PARAMETER
);
3690 #endif /* LARGE_SMB_OFF_T */
3692 /* the hard quotas 8 bytes (uint64_t)*/
3693 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3694 #ifdef LARGE_SMB_OFF_T
3695 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3696 #else /* LARGE_SMB_OFF_T */
3697 if ((IVAL(pdata
,36) != 0)&&
3698 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3699 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3700 /* more than 32 bits? */
3703 NT_STATUS_INVALID_PARAMETER
);
3706 #endif /* LARGE_SMB_OFF_T */
3708 /* quota_flags 2 bytes **/
3709 quotas
.qflags
= SVAL(pdata
,40);
3711 /* unknown_2 6 NULL bytes follow*/
3713 /* now set the quotas */
3714 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3715 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3716 reply_nterror(req
, map_nt_error_from_unix(errno
));
3723 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3725 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3731 * sending this reply works fine,
3732 * but I'm not sure it's the same
3733 * like windows do...
3736 reply_outbuf(req
, 10, 0);
3739 #if defined(HAVE_POSIX_ACLS)
3740 /****************************************************************************
3741 Utility function to count the number of entries in a POSIX acl.
3742 ****************************************************************************/
3744 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3746 unsigned int ace_count
= 0;
3747 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3748 SMB_ACL_ENTRY_T entry
;
3750 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3752 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3753 entry_id
= SMB_ACL_NEXT_ENTRY
;
3760 /****************************************************************************
3761 Utility function to marshall a POSIX acl into wire format.
3762 ****************************************************************************/
3764 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3766 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3767 SMB_ACL_ENTRY_T entry
;
3769 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3770 SMB_ACL_TAG_T tagtype
;
3771 SMB_ACL_PERMSET_T permset
;
3772 unsigned char perms
= 0;
3773 unsigned int own_grp
;
3776 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3777 entry_id
= SMB_ACL_NEXT_ENTRY
;
3780 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3781 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3785 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3786 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3790 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3791 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3792 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3794 SCVAL(pdata
,1,perms
);
3797 case SMB_ACL_USER_OBJ
:
3798 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3799 own_grp
= (unsigned int)pst
->st_ex_uid
;
3800 SIVAL(pdata
,2,own_grp
);
3805 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3807 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3810 own_grp
= (unsigned int)*puid
;
3811 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3812 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3813 SIVAL(pdata
,2,own_grp
);
3817 case SMB_ACL_GROUP_OBJ
:
3818 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3819 own_grp
= (unsigned int)pst
->st_ex_gid
;
3820 SIVAL(pdata
,2,own_grp
);
3825 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3827 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3830 own_grp
= (unsigned int)*pgid
;
3831 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3832 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3833 SIVAL(pdata
,2,own_grp
);
3838 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3839 SIVAL(pdata
,2,0xFFFFFFFF);
3840 SIVAL(pdata
,6,0xFFFFFFFF);
3843 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3844 SIVAL(pdata
,2,0xFFFFFFFF);
3845 SIVAL(pdata
,6,0xFFFFFFFF);
3848 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3851 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3858 /****************************************************************************
3859 Store the FILE_UNIX_BASIC info.
3860 ****************************************************************************/
3862 static char *store_file_unix_basic(connection_struct
*conn
,
3865 const SMB_STRUCT_STAT
*psbuf
)
3867 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3868 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3870 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3873 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3876 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3877 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3878 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3881 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3885 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3889 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3892 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3896 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3900 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ex_ino
); /* inode number */
3903 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3907 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3914 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3915 * the chflags(2) (or equivalent) flags.
3917 * XXX: this really should be behind the VFS interface. To do this, we would
3918 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3919 * Each VFS module could then implement its own mapping as appropriate for the
3920 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3922 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3926 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3930 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3934 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3938 { UF_HIDDEN
, EXT_HIDDEN
},
3941 /* Do not remove. We need to guarantee that this array has at least one
3942 * entry to build on HP-UX.
3948 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3949 uint32
*smb_fflags
, uint32
*smb_fmask
)
3953 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3954 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3955 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3956 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3961 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3962 const uint32 smb_fflags
,
3963 const uint32 smb_fmask
,
3966 uint32 max_fmask
= 0;
3969 *stat_fflags
= psbuf
->st_ex_flags
;
3971 /* For each flags requested in smb_fmask, check the state of the
3972 * corresponding flag in smb_fflags and set or clear the matching
3976 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3977 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3978 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3979 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3980 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3982 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3987 /* If smb_fmask is asking to set any bits that are not supported by
3988 * our flag mappings, we should fail.
3990 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3998 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3999 * of file flags and birth (create) time.
4001 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4004 const SMB_STRUCT_STAT
*psbuf
)
4006 uint32 file_flags
= 0;
4007 uint32 flags_mask
= 0;
4009 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4011 /* Create (birth) time 64 bit */
4012 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4015 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4016 SIVAL(pdata
, 0, file_flags
); /* flags */
4017 SIVAL(pdata
, 4, flags_mask
); /* mask */
4023 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4024 const struct stream_struct
*streams
,
4026 unsigned int max_data_bytes
,
4027 unsigned int *data_size
)
4030 unsigned int ofs
= 0;
4032 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4033 unsigned int next_offset
;
4035 smb_ucs2_t
*namebuf
;
4037 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4038 streams
[i
].name
, &namelen
) ||
4041 return NT_STATUS_INVALID_PARAMETER
;
4045 * name_buf is now null-terminated, we need to marshall as not
4051 SIVAL(data
, ofs
+4, namelen
);
4052 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4053 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4054 memcpy(data
+ofs
+24, namebuf
, namelen
);
4055 TALLOC_FREE(namebuf
);
4057 next_offset
= ofs
+ 24 + namelen
;
4059 if (i
== num_streams
-1) {
4060 SIVAL(data
, ofs
, 0);
4063 unsigned int align
= ndr_align_size(next_offset
, 8);
4065 memset(data
+next_offset
, 0, align
);
4066 next_offset
+= align
;
4068 SIVAL(data
, ofs
, next_offset
- ofs
);
4077 return NT_STATUS_OK
;
4080 /****************************************************************************
4081 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4082 ****************************************************************************/
4084 static void call_trans2qpipeinfo(connection_struct
*conn
,
4085 struct smb_request
*req
,
4086 unsigned int tran_call
,
4087 char **pparams
, int total_params
,
4088 char **ppdata
, int total_data
,
4089 unsigned int max_data_bytes
)
4091 char *params
= *pparams
;
4092 char *pdata
= *ppdata
;
4093 unsigned int data_size
= 0;
4094 unsigned int param_size
= 2;
4099 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4103 if (total_params
< 4) {
4104 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4108 fsp
= file_fsp(req
, SVAL(params
,0));
4109 if (!fsp_is_np(fsp
)) {
4110 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4114 info_level
= SVAL(params
,2);
4116 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4117 if (*pparams
== NULL
) {
4118 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4123 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4124 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4125 if (*ppdata
== NULL
) {
4126 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4131 switch (info_level
) {
4132 case SMB_FILE_STANDARD_INFORMATION
:
4134 SOFF_T(pdata
,0,4096LL);
4141 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4145 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4151 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4152 TALLOC_CTX
*mem_ctx
,
4153 uint16_t info_level
,
4155 struct smb_filename
*smb_fname
,
4156 bool delete_pending
,
4157 struct timespec write_time_ts
,
4159 struct ea_list
*ea_list
,
4160 int lock_data_count
,
4163 unsigned int max_data_bytes
,
4165 unsigned int *pdata_size
)
4167 char *pdata
= *ppdata
;
4168 char *dstart
, *dend
;
4169 unsigned int data_size
;
4170 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4171 time_t create_time
, mtime
, atime
, c_time
;
4172 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4179 uint64_t file_size
= 0;
4181 uint64_t allocation_size
= 0;
4182 uint64_t file_index
= 0;
4183 uint32_t access_mask
= 0;
4185 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4186 return NT_STATUS_INVALID_LEVEL
;
4189 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4190 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4191 info_level
, max_data_bytes
));
4194 mode
= dos_mode_msdfs(conn
, smb_fname
);
4196 mode
= dos_mode(conn
, smb_fname
);
4199 mode
= FILE_ATTRIBUTE_NORMAL
;
4201 nlink
= psbuf
->st_ex_nlink
;
4203 if (nlink
&& (mode
&aDIR
)) {
4207 if ((nlink
> 0) && delete_pending
) {
4211 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4212 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4213 if (*ppdata
== NULL
) {
4214 return NT_STATUS_NO_MEMORY
;
4218 dend
= dstart
+ data_size
- 1;
4220 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4221 update_stat_ex_mtime(psbuf
, write_time_ts
);
4224 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4225 mtime_ts
= psbuf
->st_ex_mtime
;
4226 atime_ts
= psbuf
->st_ex_atime
;
4227 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4229 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4230 dos_filetime_timespec(&create_time_ts
);
4231 dos_filetime_timespec(&mtime_ts
);
4232 dos_filetime_timespec(&atime_ts
);
4233 dos_filetime_timespec(&ctime_ts
);
4236 create_time
= convert_timespec_to_time_t(create_time_ts
);
4237 mtime
= convert_timespec_to_time_t(mtime_ts
);
4238 atime
= convert_timespec_to_time_t(atime_ts
);
4239 c_time
= convert_timespec_to_time_t(ctime_ts
);
4241 p
= strrchr_m(smb_fname
->base_name
,'/');
4243 base_name
= smb_fname
->base_name
;
4247 /* NT expects the name to be in an exact form of the *full*
4248 filename. See the trans2 torture test */
4249 if (ISDOT(base_name
)) {
4250 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4252 return NT_STATUS_NO_MEMORY
;
4255 dos_fname
= talloc_asprintf(mem_ctx
,
4257 smb_fname
->base_name
);
4259 return NT_STATUS_NO_MEMORY
;
4261 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4262 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4263 smb_fname
->stream_name
);
4265 return NT_STATUS_NO_MEMORY
;
4269 string_replace(dos_fname
, '/', '\\');
4272 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4275 /* Do we have this path open ? */
4277 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4278 fsp1
= file_find_di_first(fileid
);
4279 if (fsp1
&& fsp1
->initial_allocation_size
) {
4280 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4284 if (!(mode
& aDIR
)) {
4285 file_size
= get_file_size_stat(psbuf
);
4289 pos
= fsp
->fh
->position_information
;
4293 access_mask
= fsp
->access_mask
;
4295 /* GENERIC_EXECUTE mapping from Windows */
4296 access_mask
= 0x12019F;
4299 /* This should be an index number - looks like
4302 I think this causes us to fail the IFSKIT
4303 BasicFileInformationTest. -tpot */
4304 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
4305 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
4307 switch (info_level
) {
4308 case SMB_INFO_STANDARD
:
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4311 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4312 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4313 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4314 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4315 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4316 SSVAL(pdata
,l1_attrFile
,mode
);
4319 case SMB_INFO_QUERY_EA_SIZE
:
4321 unsigned int ea_size
=
4322 estimate_ea_size(conn
, fsp
,
4323 smb_fname
->base_name
);
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4326 srv_put_dos_date2(pdata
,0,create_time
);
4327 srv_put_dos_date2(pdata
,4,atime
);
4328 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4329 SIVAL(pdata
,12,(uint32
)file_size
);
4330 SIVAL(pdata
,16,(uint32
)allocation_size
);
4331 SSVAL(pdata
,20,mode
);
4332 SIVAL(pdata
,22,ea_size
);
4336 case SMB_INFO_IS_NAME_VALID
:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4339 /* os/2 needs this ? really ?*/
4340 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4342 /* This is only reached for qpathinfo */
4346 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4348 size_t total_ea_len
= 0;
4349 struct ea_list
*ea_file_list
= NULL
;
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4354 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4355 smb_fname
->base_name
,
4357 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4359 if (!ea_list
|| (total_ea_len
> data_size
)) {
4361 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4365 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4369 case SMB_INFO_QUERY_ALL_EAS
:
4371 /* We have data_size bytes to put EA's into. */
4372 size_t total_ea_len
= 0;
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4376 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4377 smb_fname
->base_name
,
4379 if (!ea_list
|| (total_ea_len
> data_size
)) {
4381 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4385 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4389 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4391 /* This is FileFullEaInformation - 0xF which maps to
4392 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4394 /* We have data_size bytes to put EA's into. */
4395 size_t total_ea_len
= 0;
4396 struct ea_list
*ea_file_list
= NULL
;
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4400 /*TODO: add filtering and index handling */
4403 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4404 smb_fname
->base_name
,
4406 if (!ea_file_list
) {
4407 return NT_STATUS_NO_EAS_ON_FILE
;
4410 status
= fill_ea_chained_buffer(mem_ctx
,
4414 conn
, ea_file_list
);
4415 if (!NT_STATUS_IS_OK(status
)) {
4421 case SMB_FILE_BASIC_INFORMATION
:
4422 case SMB_QUERY_FILE_BASIC_INFO
:
4424 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4426 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4432 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4433 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4434 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4435 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4436 SIVAL(pdata
,32,mode
);
4438 DEBUG(5,("SMB_QFBI - "));
4439 DEBUG(5,("create: %s ", ctime(&create_time
)));
4440 DEBUG(5,("access: %s ", ctime(&atime
)));
4441 DEBUG(5,("write: %s ", ctime(&mtime
)));
4442 DEBUG(5,("change: %s ", ctime(&c_time
)));
4443 DEBUG(5,("mode: %x\n", mode
));
4446 case SMB_FILE_STANDARD_INFORMATION
:
4447 case SMB_QUERY_FILE_STANDARD_INFO
:
4449 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4451 SOFF_T(pdata
,0,allocation_size
);
4452 SOFF_T(pdata
,8,file_size
);
4453 SIVAL(pdata
,16,nlink
);
4454 SCVAL(pdata
,20,delete_pending
?1:0);
4455 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4456 SSVAL(pdata
,22,0); /* Padding. */
4459 case SMB_FILE_EA_INFORMATION
:
4460 case SMB_QUERY_FILE_EA_INFO
:
4462 unsigned int ea_size
=
4463 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4466 SIVAL(pdata
,0,ea_size
);
4470 /* Get the 8.3 name - used if NT SMB was negotiated. */
4471 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4472 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4475 char mangled_name
[13];
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4477 if (!name_to_8_3(base_name
,mangled_name
,
4478 True
,conn
->params
)) {
4479 return NT_STATUS_NO_MEMORY
;
4481 len
= srvstr_push(dstart
, flags2
,
4482 pdata
+4, mangled_name
,
4483 PTR_DIFF(dend
, pdata
+4),
4485 data_size
= 4 + len
;
4490 case SMB_QUERY_FILE_NAME_INFO
:
4494 this must be *exactly* right for ACLs on mapped drives to work
4496 len
= srvstr_push(dstart
, flags2
,
4498 PTR_DIFF(dend
, pdata
+4),
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4501 data_size
= 4 + len
;
4506 case SMB_FILE_ALLOCATION_INFORMATION
:
4507 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4510 SOFF_T(pdata
,0,allocation_size
);
4513 case SMB_FILE_END_OF_FILE_INFORMATION
:
4514 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4517 SOFF_T(pdata
,0,file_size
);
4520 case SMB_QUERY_FILE_ALL_INFO
:
4521 case SMB_FILE_ALL_INFORMATION
:
4524 unsigned int ea_size
=
4525 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4527 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4528 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4529 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4530 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4531 SIVAL(pdata
,32,mode
);
4532 SIVAL(pdata
,36,0); /* padding. */
4534 SOFF_T(pdata
,0,allocation_size
);
4535 SOFF_T(pdata
,8,file_size
);
4536 SIVAL(pdata
,16,nlink
);
4537 SCVAL(pdata
,20,delete_pending
);
4538 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4541 SIVAL(pdata
,0,ea_size
);
4542 pdata
+= 4; /* EA info */
4543 len
= srvstr_push(dstart
, flags2
,
4545 PTR_DIFF(dend
, pdata
+4),
4549 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4553 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4556 unsigned int ea_size
=
4557 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4559 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4560 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4561 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4562 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4563 SIVAL(pdata
, 0x20, mode
);
4564 SIVAL(pdata
, 0x24, 0); /* padding. */
4565 SBVAL(pdata
, 0x28, allocation_size
);
4566 SBVAL(pdata
, 0x30, file_size
);
4567 SIVAL(pdata
, 0x38, nlink
);
4568 SCVAL(pdata
, 0x3C, delete_pending
);
4569 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4570 SSVAL(pdata
, 0x3E, 0); /* padding */
4571 SBVAL(pdata
, 0x40, file_index
);
4572 SIVAL(pdata
, 0x48, ea_size
);
4573 SIVAL(pdata
, 0x4C, access_mask
);
4574 SBVAL(pdata
, 0x50, pos
);
4575 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4576 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4580 len
= srvstr_push(dstart
, flags2
,
4582 PTR_DIFF(dend
, pdata
+4),
4586 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4589 case SMB_FILE_INTERNAL_INFORMATION
:
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4592 SBVAL(pdata
, 0, file_index
);
4596 case SMB_FILE_ACCESS_INFORMATION
:
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4598 SIVAL(pdata
, 0, access_mask
);
4602 case SMB_FILE_NAME_INFORMATION
:
4603 /* Pathname with leading '\'. */
4606 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4608 SIVAL(pdata
,0,byte_len
);
4609 data_size
= 4 + byte_len
;
4613 case SMB_FILE_DISPOSITION_INFORMATION
:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4616 SCVAL(pdata
,0,delete_pending
);
4619 case SMB_FILE_POSITION_INFORMATION
:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4622 SOFF_T(pdata
,0,pos
);
4625 case SMB_FILE_MODE_INFORMATION
:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4627 SIVAL(pdata
,0,mode
);
4631 case SMB_FILE_ALIGNMENT_INFORMATION
:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4633 SIVAL(pdata
,0,0); /* No alignment needed. */
4638 * NT4 server just returns "invalid query" to this - if we try
4639 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4642 /* The first statement above is false - verified using Thursby
4643 * client against NT4 -- gcolley.
4645 case SMB_QUERY_FILE_STREAM_INFO
:
4646 case SMB_FILE_STREAM_INFORMATION
: {
4647 unsigned int num_streams
;
4648 struct stream_struct
*streams
;
4650 DEBUG(10,("smbd_do_qfilepathinfo: "
4651 "SMB_FILE_STREAM_INFORMATION\n"));
4653 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4654 return NT_STATUS_INVALID_PARAMETER
;
4657 status
= SMB_VFS_STREAMINFO(
4658 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4659 &num_streams
, &streams
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4662 DEBUG(10, ("could not get stream info: %s\n",
4663 nt_errstr(status
)));
4667 status
= marshall_stream_info(num_streams
, streams
,
4668 pdata
, max_data_bytes
,
4671 if (!NT_STATUS_IS_OK(status
)) {
4672 DEBUG(10, ("marshall_stream_info failed: %s\n",
4673 nt_errstr(status
)));
4677 TALLOC_FREE(streams
);
4681 case SMB_QUERY_COMPRESSION_INFO
:
4682 case SMB_FILE_COMPRESSION_INFORMATION
:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4684 SOFF_T(pdata
,0,file_size
);
4685 SIVAL(pdata
,8,0); /* ??? */
4686 SIVAL(pdata
,12,0); /* ??? */
4690 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4692 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4693 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4694 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4695 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4696 SOFF_T(pdata
,32,allocation_size
);
4697 SOFF_T(pdata
,40,file_size
);
4698 SIVAL(pdata
,48,mode
);
4699 SIVAL(pdata
,52,0); /* ??? */
4703 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4705 SIVAL(pdata
,0,mode
);
4711 * CIFS UNIX Extensions.
4714 case SMB_QUERY_FILE_UNIX_BASIC
:
4716 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4717 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4721 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4723 for (i
=0; i
<100; i
++)
4724 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4730 case SMB_QUERY_FILE_UNIX_INFO2
:
4732 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4733 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4737 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4739 for (i
=0; i
<100; i
++)
4740 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4746 case SMB_QUERY_FILE_UNIX_LINK
:
4749 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4752 return NT_STATUS_NO_MEMORY
;
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4757 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4758 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4761 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4763 len
= SMB_VFS_READLINK(conn
,
4764 smb_fname
->base_name
,
4767 return map_nt_error_from_unix(errno
);
4770 len
= srvstr_push(dstart
, flags2
,
4772 PTR_DIFF(dend
, pdata
),
4775 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4780 #if defined(HAVE_POSIX_ACLS)
4781 case SMB_QUERY_POSIX_ACL
:
4783 SMB_ACL_T file_acl
= NULL
;
4784 SMB_ACL_T def_acl
= NULL
;
4785 uint16 num_file_acls
= 0;
4786 uint16 num_def_acls
= 0;
4788 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4789 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4792 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4793 smb_fname
->base_name
,
4794 SMB_ACL_TYPE_ACCESS
);
4797 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4798 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4799 "not implemented on "
4800 "filesystem containing %s\n",
4801 smb_fname
->base_name
));
4802 return NT_STATUS_NOT_IMPLEMENTED
;
4805 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4806 if (fsp
&& fsp
->is_directory
) {
4808 SMB_VFS_SYS_ACL_GET_FILE(
4810 fsp
->fsp_name
->base_name
,
4811 SMB_ACL_TYPE_DEFAULT
);
4814 SMB_VFS_SYS_ACL_GET_FILE(
4816 smb_fname
->base_name
,
4817 SMB_ACL_TYPE_DEFAULT
);
4819 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4822 num_file_acls
= count_acl_entries(conn
, file_acl
);
4823 num_def_acls
= count_acl_entries(conn
, def_acl
);
4825 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4826 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4828 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4829 SMB_POSIX_ACL_HEADER_SIZE
) ));
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4836 return NT_STATUS_BUFFER_TOO_SMALL
;
4839 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4840 SSVAL(pdata
,2,num_file_acls
);
4841 SSVAL(pdata
,4,num_def_acls
);
4842 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4849 return NT_STATUS_INTERNAL_ERROR
;
4851 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4858 return NT_STATUS_INTERNAL_ERROR
;
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4867 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4873 case SMB_QUERY_POSIX_LOCK
:
4878 enum brl_type lock_type
;
4880 /* We need an open file with a real fd for this. */
4881 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4882 return NT_STATUS_INVALID_LEVEL
;
4885 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4886 return NT_STATUS_INVALID_PARAMETER
;
4889 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4890 case POSIX_LOCK_TYPE_READ
:
4891 lock_type
= READ_LOCK
;
4893 case POSIX_LOCK_TYPE_WRITE
:
4894 lock_type
= WRITE_LOCK
;
4896 case POSIX_LOCK_TYPE_UNLOCK
:
4898 /* There's no point in asking for an unlock... */
4899 return NT_STATUS_INVALID_PARAMETER
;
4902 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4903 #if defined(HAVE_LONGLONG)
4904 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4905 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4906 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4907 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4908 #else /* HAVE_LONGLONG */
4909 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4910 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4911 #endif /* HAVE_LONGLONG */
4913 status
= query_lock(fsp
,
4920 if (ERROR_WAS_LOCK_DENIED(status
)) {
4921 /* Here we need to report who has it locked... */
4922 data_size
= POSIX_LOCK_DATA_SIZE
;
4924 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4925 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4926 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4927 #if defined(HAVE_LONGLONG)
4928 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4929 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4930 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4931 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4932 #else /* HAVE_LONGLONG */
4933 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4934 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4935 #endif /* HAVE_LONGLONG */
4937 } else if (NT_STATUS_IS_OK(status
)) {
4938 /* For success we just return a copy of what we sent
4939 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4940 data_size
= POSIX_LOCK_DATA_SIZE
;
4941 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4942 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4950 return NT_STATUS_INVALID_LEVEL
;
4953 *pdata_size
= data_size
;
4954 return NT_STATUS_OK
;
4957 /****************************************************************************
4958 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4959 file name or file id).
4960 ****************************************************************************/
4962 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4963 struct smb_request
*req
,
4964 unsigned int tran_call
,
4965 char **pparams
, int total_params
,
4966 char **ppdata
, int total_data
,
4967 unsigned int max_data_bytes
)
4969 char *params
= *pparams
;
4970 char *pdata
= *ppdata
;
4972 unsigned int data_size
= 0;
4973 unsigned int param_size
= 2;
4974 struct smb_filename
*smb_fname
= NULL
;
4975 bool delete_pending
= False
;
4976 struct timespec write_time_ts
;
4977 files_struct
*fsp
= NULL
;
4978 struct file_id fileid
;
4979 struct ea_list
*ea_list
= NULL
;
4980 int lock_data_count
= 0;
4981 char *lock_data
= NULL
;
4982 bool ms_dfs_link
= false;
4983 NTSTATUS status
= NT_STATUS_OK
;
4986 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4990 ZERO_STRUCT(write_time_ts
);
4992 if (tran_call
== TRANSACT2_QFILEINFO
) {
4993 if (total_params
< 4) {
4994 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4999 call_trans2qpipeinfo(conn
, req
, tran_call
,
5000 pparams
, total_params
,
5006 fsp
= file_fsp(req
, SVAL(params
,0));
5007 info_level
= SVAL(params
,2);
5009 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5011 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5012 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5016 /* Initial check for valid fsp ptr. */
5017 if (!check_fsp_open(conn
, req
, fsp
)) {
5021 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5023 if (!NT_STATUS_IS_OK(status
)) {
5024 reply_nterror(req
, status
);
5028 if(fsp
->fake_file_handle
) {
5030 * This is actually for the QUOTA_FAKE_FILE --metze
5033 /* We know this name is ok, it's already passed the checks. */
5035 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5037 * This is actually a QFILEINFO on a directory
5038 * handle (returned from an NT SMB). NT5.0 seems
5039 * to do this call. JRA.
5042 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5043 /* Always do lstat for UNIX calls. */
5044 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5045 DEBUG(3,("call_trans2qfilepathinfo: "
5046 "SMB_VFS_LSTAT of %s failed "
5048 smb_fname_str_dbg(smb_fname
),
5051 map_nt_error_from_unix(errno
));
5054 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5055 DEBUG(3,("call_trans2qfilepathinfo: "
5056 "SMB_VFS_STAT of %s failed (%s)\n",
5057 smb_fname_str_dbg(smb_fname
),
5060 map_nt_error_from_unix(errno
));
5064 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5065 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5068 * Original code - this is an open file.
5070 if (!check_fsp(conn
, req
, fsp
)) {
5074 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5075 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5076 fsp
->fnum
, strerror(errno
)));
5078 map_nt_error_from_unix(errno
));
5081 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5082 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5089 if (total_params
< 7) {
5090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5094 info_level
= SVAL(params
,0);
5096 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5098 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5099 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5103 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5105 STR_TERMINATE
, &status
);
5106 if (!NT_STATUS_IS_OK(status
)) {
5107 reply_nterror(req
, status
);
5111 status
= filename_convert(req
,
5113 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5118 if (!NT_STATUS_IS_OK(status
)) {
5119 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5120 reply_botherror(req
,
5121 NT_STATUS_PATH_NOT_COVERED
,
5122 ERRSRV
, ERRbadpath
);
5125 reply_nterror(req
, status
);
5129 /* If this is a stream, check if there is a delete_pending. */
5130 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5131 && is_ntfs_stream_smb_fname(smb_fname
)) {
5132 struct smb_filename
*smb_fname_base
= NULL
;
5134 /* Create an smb_filename with stream_name == NULL. */
5136 create_synthetic_smb_fname(talloc_tos(),
5137 smb_fname
->base_name
,
5140 if (!NT_STATUS_IS_OK(status
)) {
5141 reply_nterror(req
, status
);
5145 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5146 /* Always do lstat for UNIX calls. */
5147 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5148 DEBUG(3,("call_trans2qfilepathinfo: "
5149 "SMB_VFS_LSTAT of %s failed "
5151 smb_fname_str_dbg(smb_fname_base
),
5153 TALLOC_FREE(smb_fname_base
);
5155 map_nt_error_from_unix(errno
));
5159 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5160 DEBUG(3,("call_trans2qfilepathinfo: "
5161 "fileinfo of %s failed "
5163 smb_fname_str_dbg(smb_fname_base
),
5165 TALLOC_FREE(smb_fname_base
);
5167 map_nt_error_from_unix(errno
));
5172 fileid
= vfs_file_id_from_sbuf(conn
,
5173 &smb_fname_base
->st
);
5174 TALLOC_FREE(smb_fname_base
);
5175 get_file_infos(fileid
, &delete_pending
, NULL
);
5176 if (delete_pending
) {
5177 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5182 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed (%s)\n",
5187 smb_fname_str_dbg(smb_fname
),
5190 map_nt_error_from_unix(errno
));
5194 } else if (!VALID_STAT(smb_fname
->st
) &&
5195 SMB_VFS_STAT(conn
, smb_fname
) &&
5196 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5197 ms_dfs_link
= check_msdfs_link(conn
,
5198 smb_fname
->base_name
,
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "SMB_VFS_STAT of %s failed (%s)\n",
5204 smb_fname_str_dbg(smb_fname
),
5207 map_nt_error_from_unix(errno
));
5212 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5213 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5214 if (delete_pending
) {
5215 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5220 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5221 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5222 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5224 /* Pull out any data sent here before we realloc. */
5225 switch (info_level
) {
5226 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5228 /* Pull any EA list from the data portion. */
5231 if (total_data
< 4) {
5233 req
, NT_STATUS_INVALID_PARAMETER
);
5236 ea_size
= IVAL(pdata
,0);
5238 if (total_data
> 0 && ea_size
!= total_data
) {
5239 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5240 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5242 req
, NT_STATUS_INVALID_PARAMETER
);
5246 if (!lp_ea_support(SNUM(conn
))) {
5247 reply_doserror(req
, ERRDOS
,
5248 ERReasnotsupported
);
5252 /* Pull out the list of names. */
5253 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5256 req
, NT_STATUS_INVALID_PARAMETER
);
5262 case SMB_QUERY_POSIX_LOCK
:
5264 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5265 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5269 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5271 req
, NT_STATUS_INVALID_PARAMETER
);
5275 /* Copy the lock range data. */
5276 lock_data
= (char *)TALLOC_MEMDUP(
5277 req
, pdata
, total_data
);
5279 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5282 lock_data_count
= total_data
;
5288 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5289 if (*pparams
== NULL
) {
5290 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5297 * draft-leach-cifs-v1-spec-02.txt
5298 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5301 * The requested information is placed in the Data portion of the
5302 * transaction response. For the information levels greater than 0x100,
5303 * the transaction response has 1 parameter word which should be
5304 * ignored by the client.
5306 * However Windows only follows this rule for the IS_NAME_VALID call.
5308 switch (info_level
) {
5309 case SMB_INFO_IS_NAME_VALID
:
5314 if ((info_level
& 0xFF00) == 0xFF00) {
5316 * We use levels that start with 0xFF00
5317 * internally to represent SMB2 specific levels
5319 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5323 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5325 delete_pending
, write_time_ts
,
5326 ms_dfs_link
, ea_list
,
5327 lock_data_count
, lock_data
,
5328 req
->flags2
, max_data_bytes
,
5329 ppdata
, &data_size
);
5330 if (!NT_STATUS_IS_OK(status
)) {
5331 reply_nterror(req
, status
);
5335 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5341 /****************************************************************************
5342 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5344 ****************************************************************************/
5346 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5347 connection_struct
*conn
,
5348 const struct smb_filename
*smb_fname_old
,
5349 const struct smb_filename
*smb_fname_new
)
5351 NTSTATUS status
= NT_STATUS_OK
;
5353 /* source must already exist. */
5354 if (!VALID_STAT(smb_fname_old
->st
)) {
5355 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5358 /* Disallow if newname already exists. */
5359 if (VALID_STAT(smb_fname_new
->st
)) {
5360 return NT_STATUS_OBJECT_NAME_COLLISION
;
5363 /* No links from a directory. */
5364 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5365 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5368 /* Setting a hardlink to/from a stream isn't currently supported. */
5369 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5370 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5371 return NT_STATUS_INVALID_PARAMETER
;
5374 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5375 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5377 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5378 smb_fname_new
->base_name
) != 0) {
5379 status
= map_nt_error_from_unix(errno
);
5380 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5381 nt_errstr(status
), smb_fname_old
->base_name
,
5382 smb_fname_new
->base_name
));
5387 /****************************************************************************
5388 Deal with setting the time from any of the setfilepathinfo functions.
5389 ****************************************************************************/
5391 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5393 const struct smb_filename
*smb_fname
,
5394 struct smb_file_time
*ft
,
5395 bool setting_write_time
)
5397 struct smb_filename
*smb_fname_base
= NULL
;
5399 FILE_NOTIFY_CHANGE_LAST_ACCESS
5400 |FILE_NOTIFY_CHANGE_LAST_WRITE
5401 |FILE_NOTIFY_CHANGE_CREATION
;
5404 if (!VALID_STAT(smb_fname
->st
)) {
5405 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5408 /* get some defaults (no modifications) if any info is zero or -1. */
5409 if (null_timespec(ft
->create_time
)) {
5410 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5413 if (null_timespec(ft
->atime
)) {
5414 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5417 if (null_timespec(ft
->mtime
)) {
5418 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5421 if (!setting_write_time
) {
5422 /* ft->mtime comes from change time, not write time. */
5423 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5426 /* Ensure the resolution is the correct for
5427 * what we can store on this filesystem. */
5429 round_timespec(conn
->ts_res
, &ft
->create_time
);
5430 round_timespec(conn
->ts_res
, &ft
->ctime
);
5431 round_timespec(conn
->ts_res
, &ft
->atime
);
5432 round_timespec(conn
->ts_res
, &ft
->mtime
);
5434 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5435 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5436 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5437 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5438 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5440 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5443 if (setting_write_time
) {
5445 * This was a Windows setfileinfo on an open file.
5446 * NT does this a lot. We also need to
5447 * set the time here, as it can be read by
5448 * FindFirst/FindNext and with the patch for bug #2045
5449 * in smbd/fileio.c it ensures that this timestamp is
5450 * kept sticky even after a write. We save the request
5451 * away and will set it on file close and after a write. JRA.
5454 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5455 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5458 if (fsp
->base_fsp
) {
5459 set_sticky_write_time_fsp(fsp
->base_fsp
,
5462 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5465 set_sticky_write_time_path(
5466 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5471 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5473 /* Always call ntimes on the base, even if a stream was passed in. */
5474 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5475 NULL
, &smb_fname
->st
,
5477 if (!NT_STATUS_IS_OK(status
)) {
5481 if(file_ntimes(conn
, smb_fname_base
, ft
)!=0) {
5482 TALLOC_FREE(smb_fname_base
);
5483 return map_nt_error_from_unix(errno
);
5485 TALLOC_FREE(smb_fname_base
);
5487 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5488 smb_fname
->base_name
);
5489 return NT_STATUS_OK
;
5492 /****************************************************************************
5493 Deal with setting the dosmode from any of the setfilepathinfo functions.
5494 ****************************************************************************/
5496 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5497 const struct smb_filename
*smb_fname
,
5500 struct smb_filename
*smb_fname_base
= NULL
;
5503 if (!VALID_STAT(smb_fname
->st
)) {
5504 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5507 /* Always operate on the base_name, even if a stream was passed in. */
5508 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5509 NULL
, &smb_fname
->st
,
5511 if (!NT_STATUS_IS_OK(status
)) {
5516 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5523 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5525 /* check the mode isn't different, before changing it */
5526 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5527 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5528 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5529 (unsigned int)dosmode
));
5531 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5533 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5535 smb_fname_str_dbg(smb_fname_base
),
5537 status
= map_nt_error_from_unix(errno
);
5541 status
= NT_STATUS_OK
;
5543 TALLOC_FREE(smb_fname_base
);
5547 /****************************************************************************
5548 Deal with setting the size from any of the setfilepathinfo functions.
5549 ****************************************************************************/
5551 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5552 struct smb_request
*req
,
5554 const struct smb_filename
*smb_fname
,
5555 const SMB_STRUCT_STAT
*psbuf
,
5558 NTSTATUS status
= NT_STATUS_OK
;
5559 struct smb_filename
*smb_fname_tmp
= NULL
;
5560 files_struct
*new_fsp
= NULL
;
5562 if (!VALID_STAT(*psbuf
)) {
5563 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5566 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5568 if (size
== get_file_size_stat(psbuf
)) {
5569 return NT_STATUS_OK
;
5572 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5573 smb_fname_str_dbg(smb_fname
), (double)size
));
5575 if (fsp
&& fsp
->fh
->fd
!= -1) {
5576 /* Handle based call. */
5577 if (vfs_set_filelen(fsp
, size
) == -1) {
5578 return map_nt_error_from_unix(errno
);
5580 trigger_write_time_update_immediate(fsp
);
5581 return NT_STATUS_OK
;
5584 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5585 if (!NT_STATUS_IS_OK(status
)) {
5589 smb_fname_tmp
->st
= *psbuf
;
5591 status
= SMB_VFS_CREATE_FILE(
5594 0, /* root_dir_fid */
5595 smb_fname_tmp
, /* fname */
5596 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5597 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5599 FILE_OPEN
, /* create_disposition*/
5600 0, /* create_options */
5601 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5602 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5603 0, /* allocation_size */
5606 &new_fsp
, /* result */
5609 TALLOC_FREE(smb_fname_tmp
);
5611 if (!NT_STATUS_IS_OK(status
)) {
5612 /* NB. We check for open_was_deferred in the caller. */
5616 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5617 status
= map_nt_error_from_unix(errno
);
5618 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5622 trigger_write_time_update_immediate(new_fsp
);
5623 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5624 return NT_STATUS_OK
;
5627 /****************************************************************************
5628 Deal with SMB_INFO_SET_EA.
5629 ****************************************************************************/
5631 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5635 const struct smb_filename
*smb_fname
)
5637 struct ea_list
*ea_list
= NULL
;
5638 TALLOC_CTX
*ctx
= NULL
;
5639 NTSTATUS status
= NT_STATUS_OK
;
5641 if (total_data
< 10) {
5643 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5644 length. They seem to have no effect. Bug #3212. JRA */
5646 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5647 /* We're done. We only get EA info in this call. */
5648 return NT_STATUS_OK
;
5651 return NT_STATUS_INVALID_PARAMETER
;
5654 if (IVAL(pdata
,0) > total_data
) {
5655 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5656 IVAL(pdata
,0), (unsigned int)total_data
));
5657 return NT_STATUS_INVALID_PARAMETER
;
5661 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5663 return NT_STATUS_INVALID_PARAMETER
;
5665 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5670 /****************************************************************************
5671 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5672 ****************************************************************************/
5674 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5679 struct ea_list
*ea_list
= NULL
;
5683 return NT_STATUS_INVALID_HANDLE
;
5686 if (!lp_ea_support(SNUM(conn
))) {
5687 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5688 "EA's not supported.\n",
5689 (unsigned int)total_data
));
5690 return NT_STATUS_EAS_NOT_SUPPORTED
;
5693 if (total_data
< 10) {
5694 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5696 (unsigned int)total_data
));
5697 return NT_STATUS_INVALID_PARAMETER
;
5700 ea_list
= read_nttrans_ea_list(talloc_tos(),
5705 return NT_STATUS_INVALID_PARAMETER
;
5707 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5709 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5710 smb_fname_str_dbg(fsp
->fsp_name
),
5711 nt_errstr(status
) ));
5717 /****************************************************************************
5718 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5719 ****************************************************************************/
5721 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5725 const struct smb_filename
*smb_fname
)
5727 NTSTATUS status
= NT_STATUS_OK
;
5728 bool delete_on_close
;
5731 if (total_data
< 1) {
5732 return NT_STATUS_INVALID_PARAMETER
;
5736 return NT_STATUS_INVALID_HANDLE
;
5739 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5740 dosmode
= dos_mode(conn
, smb_fname
);
5742 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5743 "delete_on_close = %u\n",
5744 smb_fname_str_dbg(smb_fname
),
5745 (unsigned int)dosmode
,
5746 (unsigned int)delete_on_close
));
5748 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5750 if (!NT_STATUS_IS_OK(status
)) {
5754 /* The set is across all open files on this dev/inode pair. */
5755 if (!set_delete_on_close(fsp
, delete_on_close
,
5756 &conn
->server_info
->utok
)) {
5757 return NT_STATUS_ACCESS_DENIED
;
5759 return NT_STATUS_OK
;
5762 /****************************************************************************
5763 Deal with SMB_FILE_POSITION_INFORMATION.
5764 ****************************************************************************/
5766 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5771 uint64_t position_information
;
5773 if (total_data
< 8) {
5774 return NT_STATUS_INVALID_PARAMETER
;
5778 /* Ignore on pathname based set. */
5779 return NT_STATUS_OK
;
5782 position_information
= (uint64_t)IVAL(pdata
,0);
5783 #ifdef LARGE_SMB_OFF_T
5784 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5785 #else /* LARGE_SMB_OFF_T */
5786 if (IVAL(pdata
,4) != 0) {
5787 /* more than 32 bits? */
5788 return NT_STATUS_INVALID_PARAMETER
;
5790 #endif /* LARGE_SMB_OFF_T */
5792 DEBUG(10,("smb_file_position_information: Set file position "
5793 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5794 (double)position_information
));
5795 fsp
->fh
->position_information
= position_information
;
5796 return NT_STATUS_OK
;
5799 /****************************************************************************
5800 Deal with SMB_FILE_MODE_INFORMATION.
5801 ****************************************************************************/
5803 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5809 if (total_data
< 4) {
5810 return NT_STATUS_INVALID_PARAMETER
;
5812 mode
= IVAL(pdata
,0);
5813 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5814 return NT_STATUS_INVALID_PARAMETER
;
5816 return NT_STATUS_OK
;
5819 /****************************************************************************
5820 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5821 ****************************************************************************/
5823 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5824 struct smb_request
*req
,
5827 const struct smb_filename
*smb_fname
)
5829 char *link_target
= NULL
;
5830 const char *newname
= smb_fname
->base_name
;
5831 NTSTATUS status
= NT_STATUS_OK
;
5832 TALLOC_CTX
*ctx
= talloc_tos();
5834 /* Set a symbolic link. */
5835 /* Don't allow this if follow links is false. */
5837 if (total_data
== 0) {
5838 return NT_STATUS_INVALID_PARAMETER
;
5841 if (!lp_symlinks(SNUM(conn
))) {
5842 return NT_STATUS_ACCESS_DENIED
;
5845 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5846 total_data
, STR_TERMINATE
);
5849 return NT_STATUS_INVALID_PARAMETER
;
5852 /* !widelinks forces the target path to be within the share. */
5853 /* This means we can interpret the target as a pathname. */
5854 if (!lp_widelinks(SNUM(conn
))) {
5855 char *rel_name
= NULL
;
5856 char *last_dirp
= NULL
;
5858 if (*link_target
== '/') {
5859 /* No absolute paths allowed. */
5860 return NT_STATUS_ACCESS_DENIED
;
5862 rel_name
= talloc_strdup(ctx
,newname
);
5864 return NT_STATUS_NO_MEMORY
;
5866 last_dirp
= strrchr_m(rel_name
, '/');
5868 last_dirp
[1] = '\0';
5870 rel_name
= talloc_strdup(ctx
,"./");
5872 return NT_STATUS_NO_MEMORY
;
5875 rel_name
= talloc_asprintf_append(rel_name
,
5879 return NT_STATUS_NO_MEMORY
;
5882 status
= check_name(conn
, rel_name
);
5883 if (!NT_STATUS_IS_OK(status
)) {
5888 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5889 newname
, link_target
));
5891 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5892 return map_nt_error_from_unix(errno
);
5895 return NT_STATUS_OK
;
5898 /****************************************************************************
5899 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5900 ****************************************************************************/
5902 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5903 struct smb_request
*req
,
5904 const char *pdata
, int total_data
,
5905 const struct smb_filename
*smb_fname_new
)
5907 char *oldname
= NULL
;
5908 struct smb_filename
*smb_fname_old
= NULL
;
5909 TALLOC_CTX
*ctx
= talloc_tos();
5910 NTSTATUS status
= NT_STATUS_OK
;
5912 /* Set a hard link. */
5913 if (total_data
== 0) {
5914 return NT_STATUS_INVALID_PARAMETER
;
5917 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5918 total_data
, STR_TERMINATE
, &status
);
5919 if (!NT_STATUS_IS_OK(status
)) {
5923 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5924 smb_fname_str_dbg(smb_fname_new
), oldname
));
5926 status
= filename_convert(ctx
,
5928 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5933 if (!NT_STATUS_IS_OK(status
)) {
5937 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5940 /****************************************************************************
5941 Deal with SMB_FILE_RENAME_INFORMATION.
5942 ****************************************************************************/
5944 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5945 struct smb_request
*req
,
5949 struct smb_filename
*smb_fname_src
)
5954 char *newname
= NULL
;
5955 struct smb_filename
*smb_fname_dst
= NULL
;
5956 bool dest_has_wcard
= False
;
5957 NTSTATUS status
= NT_STATUS_OK
;
5959 TALLOC_CTX
*ctx
= talloc_tos();
5961 if (total_data
< 13) {
5962 return NT_STATUS_INVALID_PARAMETER
;
5965 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5966 root_fid
= IVAL(pdata
,4);
5967 len
= IVAL(pdata
,8);
5969 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5970 return NT_STATUS_INVALID_PARAMETER
;
5973 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5976 if (!NT_STATUS_IS_OK(status
)) {
5980 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5983 status
= resolve_dfspath_wcard(ctx
, conn
,
5984 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5988 if (!NT_STATUS_IS_OK(status
)) {
5992 /* Check the new name has no '/' characters. */
5993 if (strchr_m(newname
, '/')) {
5994 return NT_STATUS_NOT_SUPPORTED
;
5997 if (fsp
&& fsp
->base_fsp
) {
5998 /* newname must be a stream name. */
5999 if (newname
[0] != ':') {
6000 return NT_STATUS_NOT_SUPPORTED
;
6003 /* Create an smb_fname to call rename_internals_fsp() with. */
6004 status
= create_synthetic_smb_fname(talloc_tos(),
6005 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6007 if (!NT_STATUS_IS_OK(status
)) {
6012 * Set the original last component, since
6013 * rename_internals_fsp() requires it.
6015 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6017 if (smb_fname_dst
->original_lcomp
== NULL
) {
6018 status
= NT_STATUS_NO_MEMORY
;
6024 * Build up an smb_fname_dst based on the filename passed in.
6025 * We basically just strip off the last component, and put on
6026 * the newname instead.
6028 char *base_name
= NULL
;
6030 /* newname must *not* be a stream name. */
6031 if (newname
[0] == ':') {
6032 return NT_STATUS_NOT_SUPPORTED
;
6036 * Strip off the last component (filename) of the path passed
6039 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6041 return NT_STATUS_NO_MEMORY
;
6043 p
= strrchr_m(base_name
, '/');
6047 base_name
= talloc_strdup(ctx
, "./");
6049 return NT_STATUS_NO_MEMORY
;
6052 /* Append the new name. */
6053 base_name
= talloc_asprintf_append(base_name
,
6057 return NT_STATUS_NO_MEMORY
;
6060 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6063 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6066 /* If an error we expect this to be
6067 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6069 if (!NT_STATUS_IS_OK(status
)) {
6070 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6074 /* Create an smb_fname to call rename_internals_fsp() */
6075 status
= create_synthetic_smb_fname(ctx
,
6079 if (!NT_STATUS_IS_OK(status
)) {
6086 DEBUG(10,("smb_file_rename_information: "
6087 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6088 fsp
->fnum
, fsp_str_dbg(fsp
),
6089 smb_fname_str_dbg(smb_fname_dst
)));
6090 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6093 DEBUG(10,("smb_file_rename_information: "
6094 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6095 smb_fname_str_dbg(smb_fname_src
),
6096 smb_fname_str_dbg(smb_fname_dst
)));
6097 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6098 smb_fname_dst
, 0, overwrite
, false,
6100 FILE_WRITE_ATTRIBUTES
);
6103 TALLOC_FREE(smb_fname_dst
);
6107 /****************************************************************************
6108 Deal with SMB_SET_POSIX_ACL.
6109 ****************************************************************************/
6111 #if defined(HAVE_POSIX_ACLS)
6112 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6116 const struct smb_filename
*smb_fname
)
6118 uint16 posix_acl_version
;
6119 uint16 num_file_acls
;
6120 uint16 num_def_acls
;
6121 bool valid_file_acls
= True
;
6122 bool valid_def_acls
= True
;
6124 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6125 return NT_STATUS_INVALID_PARAMETER
;
6127 posix_acl_version
= SVAL(pdata
,0);
6128 num_file_acls
= SVAL(pdata
,2);
6129 num_def_acls
= SVAL(pdata
,4);
6131 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6132 valid_file_acls
= False
;
6136 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6137 valid_def_acls
= False
;
6141 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6142 return NT_STATUS_INVALID_PARAMETER
;
6145 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6146 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6147 return NT_STATUS_INVALID_PARAMETER
;
6150 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6151 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6152 (unsigned int)num_file_acls
,
6153 (unsigned int)num_def_acls
));
6155 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6156 smb_fname
->base_name
, num_file_acls
,
6157 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6158 return map_nt_error_from_unix(errno
);
6161 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6162 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6163 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6164 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6165 return map_nt_error_from_unix(errno
);
6167 return NT_STATUS_OK
;
6171 /****************************************************************************
6172 Deal with SMB_SET_POSIX_LOCK.
6173 ****************************************************************************/
6175 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6176 struct smb_request
*req
,
6184 bool blocking_lock
= False
;
6185 enum brl_type lock_type
;
6187 NTSTATUS status
= NT_STATUS_OK
;
6189 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6190 return NT_STATUS_INVALID_HANDLE
;
6193 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6194 return NT_STATUS_INVALID_PARAMETER
;
6197 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6198 case POSIX_LOCK_TYPE_READ
:
6199 lock_type
= READ_LOCK
;
6201 case POSIX_LOCK_TYPE_WRITE
:
6202 /* Return the right POSIX-mappable error code for files opened read-only. */
6203 if (!fsp
->can_write
) {
6204 return NT_STATUS_INVALID_HANDLE
;
6206 lock_type
= WRITE_LOCK
;
6208 case POSIX_LOCK_TYPE_UNLOCK
:
6209 lock_type
= UNLOCK_LOCK
;
6212 return NT_STATUS_INVALID_PARAMETER
;
6215 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6216 blocking_lock
= False
;
6217 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6218 blocking_lock
= True
;
6220 return NT_STATUS_INVALID_PARAMETER
;
6223 if (!lp_blocking_locks(SNUM(conn
))) {
6224 blocking_lock
= False
;
6227 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6228 #if defined(HAVE_LONGLONG)
6229 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6230 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6231 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6232 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6233 #else /* HAVE_LONGLONG */
6234 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6235 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6236 #endif /* HAVE_LONGLONG */
6238 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6239 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6241 (unsigned int)lock_type
,
6242 (unsigned int)lock_pid
,
6246 if (lock_type
== UNLOCK_LOCK
) {
6247 status
= do_unlock(smbd_messaging_context(),
6254 uint32 block_smbpid
;
6256 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6268 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6270 * A blocking lock was requested. Package up
6271 * this smb into a queued request and push it
6272 * onto the blocking lock queue.
6274 if(push_blocking_lock_request(br_lck
,
6277 -1, /* infinite timeout. */
6285 TALLOC_FREE(br_lck
);
6289 TALLOC_FREE(br_lck
);
6295 /****************************************************************************
6296 Deal with SMB_SET_FILE_BASIC_INFO.
6297 ****************************************************************************/
6299 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6303 const struct smb_filename
*smb_fname
)
6305 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6306 struct smb_file_time ft
;
6308 NTSTATUS status
= NT_STATUS_OK
;
6312 if (total_data
< 36) {
6313 return NT_STATUS_INVALID_PARAMETER
;
6316 /* Set the attributes */
6317 dosmode
= IVAL(pdata
,32);
6318 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6319 if (!NT_STATUS_IS_OK(status
)) {
6324 ft
.create_time
= interpret_long_date(pdata
);
6327 ft
.atime
= interpret_long_date(pdata
+8);
6330 ft
.mtime
= interpret_long_date(pdata
+16);
6333 ft
.ctime
= interpret_long_date(pdata
+24);
6335 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6336 smb_fname_str_dbg(smb_fname
)));
6338 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6342 /****************************************************************************
6343 Deal with SMB_INFO_STANDARD.
6344 ****************************************************************************/
6346 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6350 const struct smb_filename
*smb_fname
)
6352 struct smb_file_time ft
;
6356 if (total_data
< 12) {
6357 return NT_STATUS_INVALID_PARAMETER
;
6361 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6363 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6365 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6367 DEBUG(10,("smb_set_info_standard: file %s\n",
6368 smb_fname_str_dbg(smb_fname
)));
6370 return smb_set_file_time(conn
,
6377 /****************************************************************************
6378 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6379 ****************************************************************************/
6381 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6382 struct smb_request
*req
,
6386 struct smb_filename
*smb_fname
)
6388 uint64_t allocation_size
= 0;
6389 NTSTATUS status
= NT_STATUS_OK
;
6390 files_struct
*new_fsp
= NULL
;
6392 if (!VALID_STAT(smb_fname
->st
)) {
6393 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6396 if (total_data
< 8) {
6397 return NT_STATUS_INVALID_PARAMETER
;
6400 allocation_size
= (uint64_t)IVAL(pdata
,0);
6401 #ifdef LARGE_SMB_OFF_T
6402 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6403 #else /* LARGE_SMB_OFF_T */
6404 if (IVAL(pdata
,4) != 0) {
6405 /* more than 32 bits? */
6406 return NT_STATUS_INVALID_PARAMETER
;
6408 #endif /* LARGE_SMB_OFF_T */
6410 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6411 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6412 (double)allocation_size
));
6414 if (allocation_size
) {
6415 allocation_size
= smb_roundup(conn
, allocation_size
);
6418 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6419 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6420 (double)allocation_size
));
6422 if (fsp
&& fsp
->fh
->fd
!= -1) {
6423 /* Open file handle. */
6424 /* Only change if needed. */
6425 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6426 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6427 return map_nt_error_from_unix(errno
);
6430 /* But always update the time. */
6432 * This is equivalent to a write. Ensure it's seen immediately
6433 * if there are no pending writes.
6435 trigger_write_time_update_immediate(fsp
);
6436 return NT_STATUS_OK
;
6439 /* Pathname or stat or directory file. */
6440 status
= SMB_VFS_CREATE_FILE(
6443 0, /* root_dir_fid */
6444 smb_fname
, /* fname */
6445 FILE_WRITE_DATA
, /* access_mask */
6446 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6448 FILE_OPEN
, /* create_disposition*/
6449 0, /* create_options */
6450 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6451 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6452 0, /* allocation_size */
6455 &new_fsp
, /* result */
6458 if (!NT_STATUS_IS_OK(status
)) {
6459 /* NB. We check for open_was_deferred in the caller. */
6463 /* Only change if needed. */
6464 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6465 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6466 status
= map_nt_error_from_unix(errno
);
6467 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6472 /* Changing the allocation size should set the last mod time. */
6474 * This is equivalent to a write. Ensure it's seen immediately
6475 * if there are no pending writes.
6477 trigger_write_time_update_immediate(new_fsp
);
6479 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6480 return NT_STATUS_OK
;
6483 /****************************************************************************
6484 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6485 ****************************************************************************/
6487 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6488 struct smb_request
*req
,
6492 const struct smb_filename
*smb_fname
)
6496 if (total_data
< 8) {
6497 return NT_STATUS_INVALID_PARAMETER
;
6500 size
= IVAL(pdata
,0);
6501 #ifdef LARGE_SMB_OFF_T
6502 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6503 #else /* LARGE_SMB_OFF_T */
6504 if (IVAL(pdata
,4) != 0) {
6505 /* more than 32 bits? */
6506 return NT_STATUS_INVALID_PARAMETER
;
6508 #endif /* LARGE_SMB_OFF_T */
6509 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6510 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6513 return smb_set_file_size(conn
, req
,
6520 /****************************************************************************
6521 Allow a UNIX info mknod.
6522 ****************************************************************************/
6524 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6527 const struct smb_filename
*smb_fname
)
6529 uint32 file_type
= IVAL(pdata
,56);
6530 #if defined(HAVE_MAKEDEV)
6531 uint32 dev_major
= IVAL(pdata
,60);
6532 uint32 dev_minor
= IVAL(pdata
,68);
6534 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6535 uint32 raw_unixmode
= IVAL(pdata
,84);
6539 if (total_data
< 100) {
6540 return NT_STATUS_INVALID_PARAMETER
;
6543 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6544 PERM_NEW_FILE
, &unixmode
);
6545 if (!NT_STATUS_IS_OK(status
)) {
6549 #if defined(HAVE_MAKEDEV)
6550 dev
= makedev(dev_major
, dev_minor
);
6553 switch (file_type
) {
6554 #if defined(S_IFIFO)
6555 case UNIX_TYPE_FIFO
:
6556 unixmode
|= S_IFIFO
;
6559 #if defined(S_IFSOCK)
6560 case UNIX_TYPE_SOCKET
:
6561 unixmode
|= S_IFSOCK
;
6564 #if defined(S_IFCHR)
6565 case UNIX_TYPE_CHARDEV
:
6566 unixmode
|= S_IFCHR
;
6569 #if defined(S_IFBLK)
6570 case UNIX_TYPE_BLKDEV
:
6571 unixmode
|= S_IFBLK
;
6575 return NT_STATUS_INVALID_PARAMETER
;
6578 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6579 "%.0f mode 0%o for file %s\n", (double)dev
,
6580 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6582 /* Ok - do the mknod. */
6583 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6584 return map_nt_error_from_unix(errno
);
6587 /* If any of the other "set" calls fail we
6588 * don't want to end up with a half-constructed mknod.
6591 if (lp_inherit_perms(SNUM(conn
))) {
6593 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6595 return NT_STATUS_NO_MEMORY
;
6597 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6599 TALLOC_FREE(parent
);
6602 return NT_STATUS_OK
;
6605 /****************************************************************************
6606 Deal with SMB_SET_FILE_UNIX_BASIC.
6607 ****************************************************************************/
6609 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6610 struct smb_request
*req
,
6614 const struct smb_filename
*smb_fname
)
6616 struct smb_file_time ft
;
6617 uint32 raw_unixmode
;
6620 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6621 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6622 NTSTATUS status
= NT_STATUS_OK
;
6623 bool delete_on_fail
= False
;
6624 enum perm_type ptype
;
6625 files_struct
*all_fsps
= NULL
;
6626 bool modify_mtime
= true;
6628 SMB_STRUCT_STAT sbuf
;
6632 if (total_data
< 100) {
6633 return NT_STATUS_INVALID_PARAMETER
;
6636 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6637 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6638 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6639 #ifdef LARGE_SMB_OFF_T
6640 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6641 #else /* LARGE_SMB_OFF_T */
6642 if (IVAL(pdata
,4) != 0) {
6643 /* more than 32 bits? */
6644 return NT_STATUS_INVALID_PARAMETER
;
6646 #endif /* LARGE_SMB_OFF_T */
6649 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6650 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6651 set_owner
= (uid_t
)IVAL(pdata
,40);
6652 set_grp
= (gid_t
)IVAL(pdata
,48);
6653 raw_unixmode
= IVAL(pdata
,84);
6655 if (VALID_STAT(smb_fname
->st
)) {
6656 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6657 ptype
= PERM_EXISTING_DIR
;
6659 ptype
= PERM_EXISTING_FILE
;
6662 ptype
= PERM_NEW_FILE
;
6665 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6667 if (!NT_STATUS_IS_OK(status
)) {
6671 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6672 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6673 smb_fname_str_dbg(smb_fname
), (double)size
,
6674 (unsigned int)set_owner
, (unsigned int)set_grp
,
6675 (int)raw_unixmode
));
6677 sbuf
= smb_fname
->st
;
6679 if (!VALID_STAT(sbuf
)) {
6680 struct smb_filename
*smb_fname_tmp
= NULL
;
6682 * The only valid use of this is to create character and block
6683 * devices, and named pipes. This is deprecated (IMHO) and
6684 * a new info level should be used for mknod. JRA.
6687 status
= smb_unix_mknod(conn
,
6691 if (!NT_STATUS_IS_OK(status
)) {
6695 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6697 if (!NT_STATUS_IS_OK(status
)) {
6701 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6702 status
= map_nt_error_from_unix(errno
);
6703 TALLOC_FREE(smb_fname_tmp
);
6704 SMB_VFS_UNLINK(conn
, smb_fname
);
6708 sbuf
= smb_fname_tmp
->st
;
6709 TALLOC_FREE(smb_fname_tmp
);
6711 /* Ensure we don't try and change anything else. */
6712 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6713 size
= get_file_size_stat(&sbuf
);
6714 ft
.atime
= sbuf
.st_ex_atime
;
6715 ft
.mtime
= sbuf
.st_ex_mtime
;
6717 * We continue here as we might want to change the
6720 delete_on_fail
= True
;
6724 /* Horrible backwards compatibility hack as an old server bug
6725 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6729 size
= get_file_size_stat(&sbuf
);
6734 * Deal with the UNIX specific mode set.
6737 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6738 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6739 "setting mode 0%o for file %s\n",
6740 (unsigned int)unixmode
,
6741 smb_fname_str_dbg(smb_fname
)));
6742 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6743 return map_nt_error_from_unix(errno
);
6748 * Deal with the UNIX specific uid set.
6751 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6752 (sbuf
.st_ex_uid
!= set_owner
)) {
6755 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6756 "changing owner %u for path %s\n",
6757 (unsigned int)set_owner
,
6758 smb_fname_str_dbg(smb_fname
)));
6760 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6761 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6762 set_owner
, (gid_t
)-1);
6764 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6765 set_owner
, (gid_t
)-1);
6769 status
= map_nt_error_from_unix(errno
);
6770 if (delete_on_fail
) {
6771 SMB_VFS_UNLINK(conn
, smb_fname
);
6778 * Deal with the UNIX specific gid set.
6781 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6782 (sbuf
.st_ex_gid
!= set_grp
)) {
6783 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6784 "changing group %u for file %s\n",
6785 (unsigned int)set_owner
,
6786 smb_fname_str_dbg(smb_fname
)));
6787 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6789 status
= map_nt_error_from_unix(errno
);
6790 if (delete_on_fail
) {
6791 SMB_VFS_UNLINK(conn
, smb_fname
);
6797 /* Deal with any size changes. */
6799 status
= smb_set_file_size(conn
, req
,
6804 if (!NT_STATUS_IS_OK(status
)) {
6808 /* Deal with any time changes. */
6809 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6810 /* No change, don't cancel anything. */
6814 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6815 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6816 all_fsps
= file_find_di_next(all_fsps
)) {
6818 * We're setting the time explicitly for UNIX.
6819 * Cancel any pending changes over all handles.
6821 all_fsps
->update_write_time_on_close
= false;
6822 TALLOC_FREE(all_fsps
->update_write_time_event
);
6826 * Override the "setting_write_time"
6827 * parameter here as it almost does what
6828 * we need. Just remember if we modified
6829 * mtime and send the notify ourselves.
6831 if (null_timespec(ft
.mtime
)) {
6832 modify_mtime
= false;
6835 status
= smb_set_file_time(conn
,
6841 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6842 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6847 /****************************************************************************
6848 Deal with SMB_SET_FILE_UNIX_INFO2.
6849 ****************************************************************************/
6851 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6852 struct smb_request
*req
,
6856 const struct smb_filename
*smb_fname
)
6862 if (total_data
< 116) {
6863 return NT_STATUS_INVALID_PARAMETER
;
6866 /* Start by setting all the fields that are common between UNIX_BASIC
6869 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6871 if (!NT_STATUS_IS_OK(status
)) {
6875 smb_fflags
= IVAL(pdata
, 108);
6876 smb_fmask
= IVAL(pdata
, 112);
6878 /* NB: We should only attempt to alter the file flags if the client
6879 * sends a non-zero mask.
6881 if (smb_fmask
!= 0) {
6882 int stat_fflags
= 0;
6884 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6885 smb_fmask
, &stat_fflags
)) {
6886 /* Client asked to alter a flag we don't understand. */
6887 return NT_STATUS_INVALID_PARAMETER
;
6890 if (fsp
&& fsp
->fh
->fd
!= -1) {
6891 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6892 return NT_STATUS_NOT_SUPPORTED
;
6894 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6895 stat_fflags
) != 0) {
6896 return map_nt_error_from_unix(errno
);
6901 /* XXX: need to add support for changing the create_time here. You
6902 * can do this for paths on Darwin with setattrlist(2). The right way
6903 * to hook this up is probably by extending the VFS utimes interface.
6906 return NT_STATUS_OK
;
6909 /****************************************************************************
6910 Create a directory with POSIX semantics.
6911 ****************************************************************************/
6913 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6914 struct smb_request
*req
,
6917 struct smb_filename
*smb_fname
,
6918 int *pdata_return_size
)
6920 NTSTATUS status
= NT_STATUS_OK
;
6921 uint32 raw_unixmode
= 0;
6922 uint32 mod_unixmode
= 0;
6923 mode_t unixmode
= (mode_t
)0;
6924 files_struct
*fsp
= NULL
;
6925 uint16 info_level_return
= 0;
6927 char *pdata
= *ppdata
;
6929 if (total_data
< 18) {
6930 return NT_STATUS_INVALID_PARAMETER
;
6933 raw_unixmode
= IVAL(pdata
,8);
6934 /* Next 4 bytes are not yet defined. */
6936 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6937 PERM_NEW_DIR
, &unixmode
);
6938 if (!NT_STATUS_IS_OK(status
)) {
6942 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6944 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6945 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6947 status
= SMB_VFS_CREATE_FILE(
6950 0, /* root_dir_fid */
6951 smb_fname
, /* fname */
6952 FILE_READ_ATTRIBUTES
, /* access_mask */
6953 FILE_SHARE_NONE
, /* share_access */
6954 FILE_CREATE
, /* create_disposition*/
6955 FILE_DIRECTORY_FILE
, /* create_options */
6956 mod_unixmode
, /* file_attributes */
6957 0, /* oplock_request */
6958 0, /* allocation_size */
6964 if (NT_STATUS_IS_OK(status
)) {
6965 close_file(req
, fsp
, NORMAL_CLOSE
);
6968 info_level_return
= SVAL(pdata
,16);
6970 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6971 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6972 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6973 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6975 *pdata_return_size
= 12;
6978 /* Realloc the data size */
6979 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6980 if (*ppdata
== NULL
) {
6981 *pdata_return_size
= 0;
6982 return NT_STATUS_NO_MEMORY
;
6986 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6987 SSVAL(pdata
,2,0); /* No fnum. */
6988 SIVAL(pdata
,4,info
); /* Was directory created. */
6990 switch (info_level_return
) {
6991 case SMB_QUERY_FILE_UNIX_BASIC
:
6992 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6993 SSVAL(pdata
,10,0); /* Padding. */
6994 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6997 case SMB_QUERY_FILE_UNIX_INFO2
:
6998 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6999 SSVAL(pdata
,10,0); /* Padding. */
7000 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7004 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7005 SSVAL(pdata
,10,0); /* Padding. */
7012 /****************************************************************************
7013 Open/Create a file with POSIX semantics.
7014 ****************************************************************************/
7016 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7017 struct smb_request
*req
,
7020 struct smb_filename
*smb_fname
,
7021 int *pdata_return_size
)
7023 bool extended_oplock_granted
= False
;
7024 char *pdata
= *ppdata
;
7026 uint32 wire_open_mode
= 0;
7027 uint32 raw_unixmode
= 0;
7028 uint32 mod_unixmode
= 0;
7029 uint32 create_disp
= 0;
7030 uint32 access_mask
= 0;
7031 uint32 create_options
= 0;
7032 NTSTATUS status
= NT_STATUS_OK
;
7033 mode_t unixmode
= (mode_t
)0;
7034 files_struct
*fsp
= NULL
;
7035 int oplock_request
= 0;
7037 uint16 info_level_return
= 0;
7039 if (total_data
< 18) {
7040 return NT_STATUS_INVALID_PARAMETER
;
7043 flags
= IVAL(pdata
,0);
7044 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7045 if (oplock_request
) {
7046 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7049 wire_open_mode
= IVAL(pdata
,4);
7051 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7052 return smb_posix_mkdir(conn
, req
,
7059 switch (wire_open_mode
& SMB_ACCMODE
) {
7061 access_mask
= FILE_READ_DATA
;
7064 access_mask
= FILE_WRITE_DATA
;
7067 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7070 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7071 (unsigned int)wire_open_mode
));
7072 return NT_STATUS_INVALID_PARAMETER
;
7075 wire_open_mode
&= ~SMB_ACCMODE
;
7077 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7078 create_disp
= FILE_CREATE
;
7079 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7080 create_disp
= FILE_OVERWRITE_IF
;
7081 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7082 create_disp
= FILE_OPEN_IF
;
7083 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7084 create_disp
= FILE_OPEN
;
7086 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7087 (unsigned int)wire_open_mode
));
7088 return NT_STATUS_INVALID_PARAMETER
;
7091 raw_unixmode
= IVAL(pdata
,8);
7092 /* Next 4 bytes are not yet defined. */
7094 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7095 (VALID_STAT(smb_fname
->st
) ?
7096 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7099 if (!NT_STATUS_IS_OK(status
)) {
7103 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7105 if (wire_open_mode
& SMB_O_SYNC
) {
7106 create_options
|= FILE_WRITE_THROUGH
;
7108 if (wire_open_mode
& SMB_O_APPEND
) {
7109 access_mask
|= FILE_APPEND_DATA
;
7111 if (wire_open_mode
& SMB_O_DIRECT
) {
7112 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7115 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7116 smb_fname_str_dbg(smb_fname
),
7117 (unsigned int)wire_open_mode
,
7118 (unsigned int)unixmode
));
7120 status
= SMB_VFS_CREATE_FILE(
7123 0, /* root_dir_fid */
7124 smb_fname
, /* fname */
7125 access_mask
, /* access_mask */
7126 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7128 create_disp
, /* create_disposition*/
7129 FILE_NON_DIRECTORY_FILE
, /* create_options */
7130 mod_unixmode
, /* file_attributes */
7131 oplock_request
, /* oplock_request */
7132 0, /* allocation_size */
7138 if (!NT_STATUS_IS_OK(status
)) {
7142 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7143 extended_oplock_granted
= True
;
7146 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7147 extended_oplock_granted
= True
;
7150 info_level_return
= SVAL(pdata
,16);
7152 /* Allocate the correct return size. */
7154 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7155 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7156 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7157 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7159 *pdata_return_size
= 12;
7162 /* Realloc the data size */
7163 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7164 if (*ppdata
== NULL
) {
7165 close_file(req
, fsp
, ERROR_CLOSE
);
7166 *pdata_return_size
= 0;
7167 return NT_STATUS_NO_MEMORY
;
7171 if (extended_oplock_granted
) {
7172 if (flags
& REQUEST_BATCH_OPLOCK
) {
7173 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7175 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7177 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7178 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7180 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7183 SSVAL(pdata
,2,fsp
->fnum
);
7184 SIVAL(pdata
,4,info
); /* Was file created etc. */
7186 switch (info_level_return
) {
7187 case SMB_QUERY_FILE_UNIX_BASIC
:
7188 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7189 SSVAL(pdata
,10,0); /* padding. */
7190 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7193 case SMB_QUERY_FILE_UNIX_INFO2
:
7194 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7195 SSVAL(pdata
,10,0); /* padding. */
7196 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7200 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7201 SSVAL(pdata
,10,0); /* padding. */
7204 return NT_STATUS_OK
;
7207 /****************************************************************************
7208 Delete a file with POSIX semantics.
7209 ****************************************************************************/
7211 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7212 struct smb_request
*req
,
7215 struct smb_filename
*smb_fname
)
7217 NTSTATUS status
= NT_STATUS_OK
;
7218 files_struct
*fsp
= NULL
;
7222 int create_options
= 0;
7224 struct share_mode_lock
*lck
= NULL
;
7226 if (total_data
< 2) {
7227 return NT_STATUS_INVALID_PARAMETER
;
7230 flags
= SVAL(pdata
,0);
7232 if (!VALID_STAT(smb_fname
->st
)) {
7233 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7236 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7237 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7238 return NT_STATUS_NOT_A_DIRECTORY
;
7241 DEBUG(10,("smb_posix_unlink: %s %s\n",
7242 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7243 smb_fname_str_dbg(smb_fname
)));
7245 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7246 create_options
|= FILE_DIRECTORY_FILE
;
7249 status
= SMB_VFS_CREATE_FILE(
7252 0, /* root_dir_fid */
7253 smb_fname
, /* fname */
7254 DELETE_ACCESS
, /* access_mask */
7255 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7257 FILE_OPEN
, /* create_disposition*/
7258 create_options
, /* create_options */
7259 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7260 0, /* oplock_request */
7261 0, /* allocation_size */
7267 if (!NT_STATUS_IS_OK(status
)) {
7272 * Don't lie to client. If we can't really delete due to
7273 * non-POSIX opens return SHARING_VIOLATION.
7276 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7279 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7280 "lock for file %s\n", fsp_str_dbg(fsp
)));
7281 close_file(req
, fsp
, NORMAL_CLOSE
);
7282 return NT_STATUS_INVALID_PARAMETER
;
7286 * See if others still have the file open. If this is the case, then
7287 * don't delete. If all opens are POSIX delete we can set the delete
7288 * on close disposition.
7290 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7291 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7292 if (is_valid_share_mode_entry(e
)) {
7293 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7296 /* Fail with sharing violation. */
7297 close_file(req
, fsp
, NORMAL_CLOSE
);
7299 return NT_STATUS_SHARING_VIOLATION
;
7304 * Set the delete on close.
7306 status
= smb_set_file_disposition_info(conn
,
7312 if (!NT_STATUS_IS_OK(status
)) {
7313 close_file(req
, fsp
, NORMAL_CLOSE
);
7318 return close_file(req
, fsp
, NORMAL_CLOSE
);
7321 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7322 struct smb_request
*req
,
7323 TALLOC_CTX
*mem_ctx
,
7324 uint16_t info_level
,
7326 struct smb_filename
*smb_fname
,
7327 char **ppdata
, int total_data
,
7330 char *pdata
= *ppdata
;
7331 NTSTATUS status
= NT_STATUS_OK
;
7332 int data_return_size
= 0;
7336 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7337 return NT_STATUS_INVALID_LEVEL
;
7340 if (!CAN_WRITE(conn
)) {
7341 /* Allow POSIX opens. The open path will deny
7342 * any non-readonly opens. */
7343 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7344 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7348 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7349 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7350 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7352 switch (info_level
) {
7354 case SMB_INFO_STANDARD
:
7356 status
= smb_set_info_standard(conn
,
7364 case SMB_INFO_SET_EA
:
7366 status
= smb_info_set_ea(conn
,
7374 case SMB_SET_FILE_BASIC_INFO
:
7375 case SMB_FILE_BASIC_INFORMATION
:
7377 status
= smb_set_file_basic_info(conn
,
7385 case SMB_FILE_ALLOCATION_INFORMATION
:
7386 case SMB_SET_FILE_ALLOCATION_INFO
:
7388 status
= smb_set_file_allocation_info(conn
, req
,
7396 case SMB_FILE_END_OF_FILE_INFORMATION
:
7397 case SMB_SET_FILE_END_OF_FILE_INFO
:
7399 status
= smb_set_file_end_of_file_info(conn
, req
,
7407 case SMB_FILE_DISPOSITION_INFORMATION
:
7408 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7411 /* JRA - We used to just ignore this on a path ?
7412 * Shouldn't this be invalid level on a pathname
7415 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7416 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7419 status
= smb_set_file_disposition_info(conn
,
7427 case SMB_FILE_POSITION_INFORMATION
:
7429 status
= smb_file_position_information(conn
,
7436 case SMB_FILE_FULL_EA_INFORMATION
:
7438 status
= smb_set_file_full_ea_info(conn
,
7445 /* From tridge Samba4 :
7446 * MODE_INFORMATION in setfileinfo (I have no
7447 * idea what "mode information" on a file is - it takes a value of 0,
7448 * 2, 4 or 6. What could it be?).
7451 case SMB_FILE_MODE_INFORMATION
:
7453 status
= smb_file_mode_information(conn
,
7460 * CIFS UNIX extensions.
7463 case SMB_SET_FILE_UNIX_BASIC
:
7465 status
= smb_set_file_unix_basic(conn
, req
,
7473 case SMB_SET_FILE_UNIX_INFO2
:
7475 status
= smb_set_file_unix_info2(conn
, req
,
7483 case SMB_SET_FILE_UNIX_LINK
:
7486 /* We must have a pathname for this. */
7487 return NT_STATUS_INVALID_LEVEL
;
7489 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7490 total_data
, smb_fname
);
7494 case SMB_SET_FILE_UNIX_HLINK
:
7497 /* We must have a pathname for this. */
7498 return NT_STATUS_INVALID_LEVEL
;
7500 status
= smb_set_file_unix_hlink(conn
, req
,
7506 case SMB_FILE_RENAME_INFORMATION
:
7508 status
= smb_file_rename_information(conn
, req
,
7514 #if defined(HAVE_POSIX_ACLS)
7515 case SMB_SET_POSIX_ACL
:
7517 status
= smb_set_posix_acl(conn
,
7526 case SMB_SET_POSIX_LOCK
:
7529 return NT_STATUS_INVALID_LEVEL
;
7531 status
= smb_set_posix_lock(conn
, req
,
7532 pdata
, total_data
, fsp
);
7536 case SMB_POSIX_PATH_OPEN
:
7539 /* We must have a pathname for this. */
7540 return NT_STATUS_INVALID_LEVEL
;
7543 status
= smb_posix_open(conn
, req
,
7551 case SMB_POSIX_PATH_UNLINK
:
7554 /* We must have a pathname for this. */
7555 return NT_STATUS_INVALID_LEVEL
;
7558 status
= smb_posix_unlink(conn
, req
,
7566 return NT_STATUS_INVALID_LEVEL
;
7569 if (!NT_STATUS_IS_OK(status
)) {
7573 *ret_data_size
= data_return_size
;
7574 return NT_STATUS_OK
;
7577 /****************************************************************************
7578 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7579 ****************************************************************************/
7581 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7582 struct smb_request
*req
,
7583 unsigned int tran_call
,
7584 char **pparams
, int total_params
,
7585 char **ppdata
, int total_data
,
7586 unsigned int max_data_bytes
)
7588 char *params
= *pparams
;
7589 char *pdata
= *ppdata
;
7591 struct smb_filename
*smb_fname
= NULL
;
7592 files_struct
*fsp
= NULL
;
7593 NTSTATUS status
= NT_STATUS_OK
;
7594 int data_return_size
= 0;
7597 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7601 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7602 if (total_params
< 4) {
7603 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7607 fsp
= file_fsp(req
, SVAL(params
,0));
7608 /* Basic check for non-null fsp. */
7609 if (!check_fsp_open(conn
, req
, fsp
)) {
7612 info_level
= SVAL(params
,2);
7614 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7616 if (!NT_STATUS_IS_OK(status
)) {
7617 reply_nterror(req
, status
);
7621 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7623 * This is actually a SETFILEINFO on a directory
7624 * handle (returned from an NT SMB). NT5.0 seems
7625 * to do this call. JRA.
7627 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7628 /* Always do lstat for UNIX calls. */
7629 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7630 DEBUG(3,("call_trans2setfilepathinfo: "
7631 "SMB_VFS_LSTAT of %s failed "
7633 smb_fname_str_dbg(smb_fname
),
7635 reply_nterror(req
, map_nt_error_from_unix(errno
));
7639 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7640 DEBUG(3,("call_trans2setfilepathinfo: "
7641 "fileinfo of %s failed (%s)\n",
7642 smb_fname_str_dbg(smb_fname
),
7644 reply_nterror(req
, map_nt_error_from_unix(errno
));
7648 } else if (fsp
->print_file
) {
7650 * Doing a DELETE_ON_CLOSE should cancel a print job.
7652 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7653 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7655 DEBUG(3,("call_trans2setfilepathinfo: "
7656 "Cancelling print job (%s)\n",
7660 send_trans2_replies(conn
, req
, params
, 2,
7665 reply_doserror(req
, ERRDOS
, ERRbadpath
);
7670 * Original code - this is an open file.
7672 if (!check_fsp(conn
, req
, fsp
)) {
7676 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7677 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7678 "of fnum %d failed (%s)\n", fsp
->fnum
,
7680 reply_nterror(req
, map_nt_error_from_unix(errno
));
7688 if (total_params
< 7) {
7689 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7693 info_level
= SVAL(params
,0);
7694 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7695 total_params
- 6, STR_TERMINATE
,
7697 if (!NT_STATUS_IS_OK(status
)) {
7698 reply_nterror(req
, status
);
7702 status
= filename_convert(req
, conn
,
7703 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7708 if (!NT_STATUS_IS_OK(status
)) {
7709 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7710 reply_botherror(req
,
7711 NT_STATUS_PATH_NOT_COVERED
,
7712 ERRSRV
, ERRbadpath
);
7715 reply_nterror(req
, status
);
7719 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7721 * For CIFS UNIX extensions the target name may not exist.
7724 /* Always do lstat for UNIX calls. */
7725 SMB_VFS_LSTAT(conn
, smb_fname
);
7727 } else if (!VALID_STAT(smb_fname
->st
) &&
7728 SMB_VFS_STAT(conn
, smb_fname
)) {
7729 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7731 smb_fname_str_dbg(smb_fname
),
7733 reply_nterror(req
, map_nt_error_from_unix(errno
));
7738 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7739 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7740 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7742 /* Realloc the parameter size */
7743 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7744 if (*pparams
== NULL
) {
7745 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7752 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7758 if (!NT_STATUS_IS_OK(status
)) {
7759 if (open_was_deferred(req
->mid
)) {
7760 /* We have re-scheduled this call. */
7763 if (blocking_lock_was_deferred(req
->mid
)) {
7764 /* We have re-scheduled this call. */
7767 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7768 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7769 ERRSRV
, ERRbadpath
);
7772 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7773 reply_openerror(req
, status
);
7777 reply_nterror(req
, status
);
7781 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7787 /****************************************************************************
7788 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7789 ****************************************************************************/
7791 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7792 char **pparams
, int total_params
,
7793 char **ppdata
, int total_data
,
7794 unsigned int max_data_bytes
)
7796 struct smb_filename
*smb_dname
= NULL
;
7797 char *params
= *pparams
;
7798 char *pdata
= *ppdata
;
7799 char *directory
= NULL
;
7800 NTSTATUS status
= NT_STATUS_OK
;
7801 struct ea_list
*ea_list
= NULL
;
7802 TALLOC_CTX
*ctx
= talloc_tos();
7804 if (!CAN_WRITE(conn
)) {
7805 reply_doserror(req
, ERRSRV
, ERRaccess
);
7809 if (total_params
< 5) {
7810 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7814 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7815 total_params
- 4, STR_TERMINATE
,
7817 if (!NT_STATUS_IS_OK(status
)) {
7818 reply_nterror(req
, status
);
7822 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7824 status
= filename_convert(ctx
,
7826 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7832 if (!NT_STATUS_IS_OK(status
)) {
7833 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7834 reply_botherror(req
,
7835 NT_STATUS_PATH_NOT_COVERED
,
7836 ERRSRV
, ERRbadpath
);
7839 reply_nterror(req
, status
);
7843 /* Any data in this call is an EA list. */
7844 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7845 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7850 * OS/2 workplace shell seems to send SET_EA requests of "null"
7851 * length (4 bytes containing IVAL 4).
7852 * They seem to have no effect. Bug #3212. JRA.
7855 if (total_data
!= 4) {
7856 if (total_data
< 10) {
7857 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7861 if (IVAL(pdata
,0) > total_data
) {
7862 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7863 IVAL(pdata
,0), (unsigned int)total_data
));
7864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7868 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7871 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7875 /* If total_data == 4 Windows doesn't care what values
7876 * are placed in that field, it just ignores them.
7877 * The System i QNTC IBM SMB client puts bad values here,
7878 * so ignore them. */
7880 status
= create_directory(conn
, req
, smb_dname
);
7882 if (!NT_STATUS_IS_OK(status
)) {
7883 reply_nterror(req
, status
);
7887 /* Try and set any given EA. */
7889 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7890 if (!NT_STATUS_IS_OK(status
)) {
7891 reply_nterror(req
, status
);
7896 /* Realloc the parameter and data sizes */
7897 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7898 if(*pparams
== NULL
) {
7899 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7906 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7909 TALLOC_FREE(smb_dname
);
7913 /****************************************************************************
7914 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7915 We don't actually do this - we just send a null response.
7916 ****************************************************************************/
7918 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7919 struct smb_request
*req
,
7920 char **pparams
, int total_params
,
7921 char **ppdata
, int total_data
,
7922 unsigned int max_data_bytes
)
7924 char *params
= *pparams
;
7927 if (total_params
< 6) {
7928 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7932 info_level
= SVAL(params
,4);
7933 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7935 switch (info_level
) {
7940 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7944 /* Realloc the parameter and data sizes */
7945 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7946 if (*pparams
== NULL
) {
7947 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7952 SSVAL(params
,0,fnf_handle
);
7953 SSVAL(params
,2,0); /* No changes */
7954 SSVAL(params
,4,0); /* No EA errors */
7961 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7966 /****************************************************************************
7967 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7968 changes). Currently this does nothing.
7969 ****************************************************************************/
7971 static void call_trans2findnotifynext(connection_struct
*conn
,
7972 struct smb_request
*req
,
7973 char **pparams
, int total_params
,
7974 char **ppdata
, int total_data
,
7975 unsigned int max_data_bytes
)
7977 char *params
= *pparams
;
7979 DEBUG(3,("call_trans2findnotifynext\n"));
7981 /* Realloc the parameter and data sizes */
7982 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7983 if (*pparams
== NULL
) {
7984 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7989 SSVAL(params
,0,0); /* No changes */
7990 SSVAL(params
,2,0); /* No EA errors */
7992 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7997 /****************************************************************************
7998 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7999 ****************************************************************************/
8001 static void call_trans2getdfsreferral(connection_struct
*conn
,
8002 struct smb_request
*req
,
8003 char **pparams
, int total_params
,
8004 char **ppdata
, int total_data
,
8005 unsigned int max_data_bytes
)
8007 char *params
= *pparams
;
8008 char *pathname
= NULL
;
8010 int max_referral_level
;
8011 NTSTATUS status
= NT_STATUS_OK
;
8012 TALLOC_CTX
*ctx
= talloc_tos();
8014 DEBUG(10,("call_trans2getdfsreferral\n"));
8016 if (total_params
< 3) {
8017 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8021 max_referral_level
= SVAL(params
,0);
8023 if(!lp_host_msdfs()) {
8024 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
8028 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8029 total_params
- 2, STR_TERMINATE
);
8031 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8034 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8035 ppdata
,&status
)) < 0) {
8036 reply_nterror(req
, status
);
8040 SSVAL(req
->inbuf
, smb_flg2
,
8041 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8042 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8047 #define LMCAT_SPL 0x53
8048 #define LMFUNC_GETJOBID 0x60
8050 /****************************************************************************
8051 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8052 ****************************************************************************/
8054 static void call_trans2ioctl(connection_struct
*conn
,
8055 struct smb_request
*req
,
8056 char **pparams
, int total_params
,
8057 char **ppdata
, int total_data
,
8058 unsigned int max_data_bytes
)
8060 char *pdata
= *ppdata
;
8061 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8063 /* check for an invalid fid before proceeding */
8066 reply_doserror(req
, ERRDOS
, ERRbadfid
);
8070 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8071 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8072 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8073 if (*ppdata
== NULL
) {
8074 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8079 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8080 CAN ACCEPT THIS IN UNICODE. JRA. */
8082 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8083 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8084 global_myname(), 15,
8085 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8086 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8087 lp_servicename(SNUM(conn
)), 13,
8088 STR_ASCII
|STR_TERMINATE
); /* Service name */
8089 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8094 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8095 reply_doserror(req
, ERRSRV
, ERRerror
);
8098 /****************************************************************************
8099 Reply to a SMBfindclose (stop trans2 directory search).
8100 ****************************************************************************/
8102 void reply_findclose(struct smb_request
*req
)
8105 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8107 START_PROFILE(SMBfindclose
);
8110 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8111 END_PROFILE(SMBfindclose
);
8115 dptr_num
= SVALS(req
->vwv
+0, 0);
8117 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8119 dptr_close(sconn
, &dptr_num
);
8121 reply_outbuf(req
, 0, 0);
8123 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8125 END_PROFILE(SMBfindclose
);
8129 /****************************************************************************
8130 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8131 ****************************************************************************/
8133 void reply_findnclose(struct smb_request
*req
)
8137 START_PROFILE(SMBfindnclose
);
8140 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8141 END_PROFILE(SMBfindnclose
);
8145 dptr_num
= SVAL(req
->vwv
+0, 0);
8147 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8149 /* We never give out valid handles for a
8150 findnotifyfirst - so any dptr_num is ok here.
8153 reply_outbuf(req
, 0, 0);
8155 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8157 END_PROFILE(SMBfindnclose
);
8161 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8162 struct trans_state
*state
)
8164 if (Protocol
>= PROTOCOL_NT1
) {
8165 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8166 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8169 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8170 if (state
->call
!= TRANSACT2_QFSINFO
&&
8171 state
->call
!= TRANSACT2_SETFSINFO
) {
8172 DEBUG(0,("handle_trans2: encryption required "
8174 (unsigned int)state
->call
));
8175 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8180 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8182 /* Now we must call the relevant TRANS2 function */
8183 switch(state
->call
) {
8184 case TRANSACT2_OPEN
:
8186 START_PROFILE(Trans2_open
);
8187 call_trans2open(conn
, req
,
8188 &state
->param
, state
->total_param
,
8189 &state
->data
, state
->total_data
,
8190 state
->max_data_return
);
8191 END_PROFILE(Trans2_open
);
8195 case TRANSACT2_FINDFIRST
:
8197 START_PROFILE(Trans2_findfirst
);
8198 call_trans2findfirst(conn
, req
,
8199 &state
->param
, state
->total_param
,
8200 &state
->data
, state
->total_data
,
8201 state
->max_data_return
);
8202 END_PROFILE(Trans2_findfirst
);
8206 case TRANSACT2_FINDNEXT
:
8208 START_PROFILE(Trans2_findnext
);
8209 call_trans2findnext(conn
, req
,
8210 &state
->param
, state
->total_param
,
8211 &state
->data
, state
->total_data
,
8212 state
->max_data_return
);
8213 END_PROFILE(Trans2_findnext
);
8217 case TRANSACT2_QFSINFO
:
8219 START_PROFILE(Trans2_qfsinfo
);
8220 call_trans2qfsinfo(conn
, req
,
8221 &state
->param
, state
->total_param
,
8222 &state
->data
, state
->total_data
,
8223 state
->max_data_return
);
8224 END_PROFILE(Trans2_qfsinfo
);
8228 case TRANSACT2_SETFSINFO
:
8230 START_PROFILE(Trans2_setfsinfo
);
8231 call_trans2setfsinfo(conn
, req
,
8232 &state
->param
, state
->total_param
,
8233 &state
->data
, state
->total_data
,
8234 state
->max_data_return
);
8235 END_PROFILE(Trans2_setfsinfo
);
8239 case TRANSACT2_QPATHINFO
:
8240 case TRANSACT2_QFILEINFO
:
8242 START_PROFILE(Trans2_qpathinfo
);
8243 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8244 &state
->param
, state
->total_param
,
8245 &state
->data
, state
->total_data
,
8246 state
->max_data_return
);
8247 END_PROFILE(Trans2_qpathinfo
);
8251 case TRANSACT2_SETPATHINFO
:
8252 case TRANSACT2_SETFILEINFO
:
8254 START_PROFILE(Trans2_setpathinfo
);
8255 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8256 &state
->param
, state
->total_param
,
8257 &state
->data
, state
->total_data
,
8258 state
->max_data_return
);
8259 END_PROFILE(Trans2_setpathinfo
);
8263 case TRANSACT2_FINDNOTIFYFIRST
:
8265 START_PROFILE(Trans2_findnotifyfirst
);
8266 call_trans2findnotifyfirst(conn
, req
,
8267 &state
->param
, state
->total_param
,
8268 &state
->data
, state
->total_data
,
8269 state
->max_data_return
);
8270 END_PROFILE(Trans2_findnotifyfirst
);
8274 case TRANSACT2_FINDNOTIFYNEXT
:
8276 START_PROFILE(Trans2_findnotifynext
);
8277 call_trans2findnotifynext(conn
, req
,
8278 &state
->param
, state
->total_param
,
8279 &state
->data
, state
->total_data
,
8280 state
->max_data_return
);
8281 END_PROFILE(Trans2_findnotifynext
);
8285 case TRANSACT2_MKDIR
:
8287 START_PROFILE(Trans2_mkdir
);
8288 call_trans2mkdir(conn
, req
,
8289 &state
->param
, state
->total_param
,
8290 &state
->data
, state
->total_data
,
8291 state
->max_data_return
);
8292 END_PROFILE(Trans2_mkdir
);
8296 case TRANSACT2_GET_DFS_REFERRAL
:
8298 START_PROFILE(Trans2_get_dfs_referral
);
8299 call_trans2getdfsreferral(conn
, req
,
8300 &state
->param
, state
->total_param
,
8301 &state
->data
, state
->total_data
,
8302 state
->max_data_return
);
8303 END_PROFILE(Trans2_get_dfs_referral
);
8307 case TRANSACT2_IOCTL
:
8309 START_PROFILE(Trans2_ioctl
);
8310 call_trans2ioctl(conn
, req
,
8311 &state
->param
, state
->total_param
,
8312 &state
->data
, state
->total_data
,
8313 state
->max_data_return
);
8314 END_PROFILE(Trans2_ioctl
);
8319 /* Error in request */
8320 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8321 reply_doserror(req
, ERRSRV
,ERRerror
);
8325 /****************************************************************************
8326 Reply to a SMBtrans2.
8327 ****************************************************************************/
8329 void reply_trans2(struct smb_request
*req
)
8331 connection_struct
*conn
= req
->conn
;
8336 unsigned int tran_call
;
8337 struct trans_state
*state
;
8340 START_PROFILE(SMBtrans2
);
8342 if (req
->wct
< 14) {
8343 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8344 END_PROFILE(SMBtrans2
);
8348 dsoff
= SVAL(req
->vwv
+12, 0);
8349 dscnt
= SVAL(req
->vwv
+11, 0);
8350 psoff
= SVAL(req
->vwv
+10, 0);
8351 pscnt
= SVAL(req
->vwv
+9, 0);
8352 tran_call
= SVAL(req
->vwv
+14, 0);
8354 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8355 if (!NT_STATUS_IS_OK(result
)) {
8356 DEBUG(2, ("Got invalid trans2 request: %s\n",
8357 nt_errstr(result
)));
8358 reply_nterror(req
, result
);
8359 END_PROFILE(SMBtrans2
);
8364 switch (tran_call
) {
8365 /* List the allowed trans2 calls on IPC$ */
8366 case TRANSACT2_OPEN
:
8367 case TRANSACT2_GET_DFS_REFERRAL
:
8368 case TRANSACT2_QFILEINFO
:
8369 case TRANSACT2_QFSINFO
:
8370 case TRANSACT2_SETFSINFO
:
8373 reply_doserror(req
, ERRSRV
, ERRaccess
);
8374 END_PROFILE(SMBtrans2
);
8379 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8380 DEBUG(0, ("talloc failed\n"));
8381 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8382 END_PROFILE(SMBtrans2
);
8386 state
->cmd
= SMBtrans2
;
8388 state
->mid
= req
->mid
;
8389 state
->vuid
= req
->vuid
;
8390 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8391 state
->setup
= NULL
;
8392 state
->total_param
= SVAL(req
->vwv
+0, 0);
8393 state
->param
= NULL
;
8394 state
->total_data
= SVAL(req
->vwv
+1, 0);
8396 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8397 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8398 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8399 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8400 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8402 state
->call
= tran_call
;
8404 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8405 is so as a sanity check */
8406 if (state
->setup_count
!= 1) {
8408 * Need to have rc=0 for ioctl to get job id for OS/2.
8409 * Network printing will fail if function is not successful.
8410 * Similar function in reply.c will be used if protocol
8411 * is LANMAN1.0 instead of LM1.2X002.
8412 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8413 * outbuf doesn't have to be set(only job id is used).
8415 if ( (state
->setup_count
== 4)
8416 && (tran_call
== TRANSACT2_IOCTL
)
8417 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8418 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8419 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8421 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8422 DEBUG(2,("Transaction is %d\n",tran_call
));
8424 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8425 END_PROFILE(SMBtrans2
);
8430 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8433 if (state
->total_data
) {
8435 if (trans_oob(state
->total_data
, 0, dscnt
)
8436 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8440 /* Can't use talloc here, the core routines do realloc on the
8441 * params and data. */
8442 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8443 if (state
->data
== NULL
) {
8444 DEBUG(0,("reply_trans2: data malloc fail for %u "
8445 "bytes !\n", (unsigned int)state
->total_data
));
8447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8448 END_PROFILE(SMBtrans2
);
8452 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8455 if (state
->total_param
) {
8457 if (trans_oob(state
->total_param
, 0, pscnt
)
8458 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8462 /* Can't use talloc here, the core routines do realloc on the
8463 * params and data. */
8464 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8465 if (state
->param
== NULL
) {
8466 DEBUG(0,("reply_trans: param malloc fail for %u "
8467 "bytes !\n", (unsigned int)state
->total_param
));
8468 SAFE_FREE(state
->data
);
8470 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8471 END_PROFILE(SMBtrans2
);
8475 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8478 state
->received_data
= dscnt
;
8479 state
->received_param
= pscnt
;
8481 if ((state
->received_param
== state
->total_param
) &&
8482 (state
->received_data
== state
->total_data
)) {
8484 handle_trans2(conn
, req
, state
);
8486 SAFE_FREE(state
->data
);
8487 SAFE_FREE(state
->param
);
8489 END_PROFILE(SMBtrans2
);
8493 DLIST_ADD(conn
->pending_trans
, state
);
8495 /* We need to send an interim response then receive the rest
8496 of the parameter/data bytes */
8497 reply_outbuf(req
, 0, 0);
8498 show_msg((char *)req
->outbuf
);
8499 END_PROFILE(SMBtrans2
);
8504 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8505 SAFE_FREE(state
->data
);
8506 SAFE_FREE(state
->param
);
8508 END_PROFILE(SMBtrans2
);
8509 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8513 /****************************************************************************
8514 Reply to a SMBtranss2
8515 ****************************************************************************/
8517 void reply_transs2(struct smb_request
*req
)
8519 connection_struct
*conn
= req
->conn
;
8520 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8521 struct trans_state
*state
;
8523 START_PROFILE(SMBtranss2
);
8525 show_msg((char *)req
->inbuf
);
8528 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8529 END_PROFILE(SMBtranss2
);
8533 for (state
= conn
->pending_trans
; state
!= NULL
;
8534 state
= state
->next
) {
8535 if (state
->mid
== req
->mid
) {
8540 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8541 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8542 END_PROFILE(SMBtranss2
);
8546 /* Revise state->total_param and state->total_data in case they have
8547 changed downwards */
8549 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8550 state
->total_param
= SVAL(req
->vwv
+0, 0);
8551 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8552 state
->total_data
= SVAL(req
->vwv
+1, 0);
8554 pcnt
= SVAL(req
->vwv
+2, 0);
8555 poff
= SVAL(req
->vwv
+3, 0);
8556 pdisp
= SVAL(req
->vwv
+4, 0);
8558 dcnt
= SVAL(req
->vwv
+5, 0);
8559 doff
= SVAL(req
->vwv
+6, 0);
8560 ddisp
= SVAL(req
->vwv
+7, 0);
8562 state
->received_param
+= pcnt
;
8563 state
->received_data
+= dcnt
;
8565 if ((state
->received_data
> state
->total_data
) ||
8566 (state
->received_param
> state
->total_param
))
8570 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8571 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8574 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8578 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8579 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8582 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8585 if ((state
->received_param
< state
->total_param
) ||
8586 (state
->received_data
< state
->total_data
)) {
8587 END_PROFILE(SMBtranss2
);
8591 handle_trans2(conn
, req
, state
);
8593 DLIST_REMOVE(conn
->pending_trans
, state
);
8594 SAFE_FREE(state
->data
);
8595 SAFE_FREE(state
->param
);
8598 END_PROFILE(SMBtranss2
);
8603 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8604 DLIST_REMOVE(conn
->pending_trans
, state
);
8605 SAFE_FREE(state
->data
);
8606 SAFE_FREE(state
->param
);
8608 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8609 END_PROFILE(SMBtranss2
);