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
,
80 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
81 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
84 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
96 files_struct
*fsp
, const char *fname
,
97 const char *ea_name
, struct ea_struct
*pea
)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size
= 256;
106 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
108 return NT_STATUS_NO_MEMORY
;
111 if (fsp
&& fsp
->fh
->fd
!= -1) {
112 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
114 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
117 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
123 return map_nt_error_from_unix(errno
);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
127 dump_data(10, (uint8
*)val
, sizeret
);
130 if (strnequal(ea_name
, "user.", 5)) {
131 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
133 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
135 if (pea
->name
== NULL
) {
137 return NT_STATUS_NO_MEMORY
;
139 pea
->value
.data
= (unsigned char *)val
;
140 pea
->value
.length
= (size_t)sizeret
;
144 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
145 files_struct
*fsp
, const char *fname
,
146 char ***pnames
, size_t *pnum_names
)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size
= 1024;
150 char *ea_namelist
= NULL
;
155 ssize_t sizeret
= -1;
157 if (!lp_ea_support(SNUM(conn
))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY
;
173 while (ea_namelist_size
<= 65536) {
175 ea_namelist
= TALLOC_REALLOC_ARRAY(
176 names
, ea_namelist
, char, ea_namelist_size
);
177 if (ea_namelist
== NULL
) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY
;
183 if (fsp
&& fsp
->fh
->fd
!= -1) {
184 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
187 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
191 if ((sizeret
== -1) && (errno
== ERANGE
)) {
192 ea_namelist_size
*= 2;
201 return map_nt_error_from_unix(errno
);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret
));
215 * Ensure the result is 0-terminated
218 if (ea_namelist
[sizeret
-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR
;
228 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
232 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY
;
242 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
243 names
[num_names
++] = p
;
247 *pnum_names
= num_names
;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
256 const char *fname
, size_t *pea_total_len
)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list
*ea_list_head
= NULL
;
266 if (!lp_ea_support(SNUM(conn
))) {
270 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
273 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
277 for (i
=0; i
<num_names
; i
++) {
278 struct ea_list
*listp
;
281 if (strnequal(names
[i
], "system.", 7)
282 || samba_private_attr_name(names
[i
]))
285 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
296 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
299 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
303 (unsigned int)listp
->ea
.value
.length
));
305 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
309 /* Add on 4 for total length. */
310 if (*pea_total_len
) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len
));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
326 connection_struct
*conn
, struct ea_list
*ea_list
)
328 unsigned int ret_data_size
= 4;
331 SMB_ASSERT(total_data_size
>= 4);
333 if (!lp_ea_support(SNUM(conn
))) {
338 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
341 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
342 dos_namelen
= strlen(dos_ea_name
);
343 if (dos_namelen
> 255 || dos_namelen
== 0) {
346 if (ea_list
->ea
.value
.length
> 65535) {
349 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
353 /* We know we have room. */
354 SCVAL(p
,0,ea_list
->ea
.flags
);
355 SCVAL(p
,1,dos_namelen
);
356 SSVAL(p
,2,ea_list
->ea
.value
.length
);
357 fstrcpy(p
+4, dos_ea_name
);
358 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
360 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
361 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
364 ret_data_size
= PTR_DIFF(p
, pdata
);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
366 SIVAL(pdata
,0,ret_data_size
);
367 return ret_data_size
;
370 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
372 unsigned int total_data_size
,
373 unsigned int *ret_data_size
,
374 connection_struct
*conn
,
375 struct ea_list
*ea_list
)
377 uint8_t *p
= (uint8_t *)pdata
;
378 uint8_t *last_start
= NULL
;
382 if (!lp_ea_support(SNUM(conn
))) {
383 return NT_STATUS_NO_EAS_ON_FILE
;
386 for (; ea_list
; ea_list
= ea_list
->next
) {
392 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
396 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
397 dos_namelen
= strlen(dos_ea_name
);
398 if (dos_namelen
> 255 || dos_namelen
== 0) {
399 return NT_STATUS_INTERNAL_ERROR
;
401 if (ea_list
->ea
.value
.length
> 65535) {
402 return NT_STATUS_INTERNAL_ERROR
;
405 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
408 size_t pad
= 4 - (this_size
% 4);
412 if (this_size
> total_data_size
) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH
;
416 /* We know we have room. */
417 SIVAL(p
, 0x00, 0); /* next offset */
418 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
419 SCVAL(p
, 0x05, dos_namelen
);
420 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
421 fstrcpy((char *)(p
+0x08), dos_ea_name
);
422 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
424 total_data_size
-= this_size
;
428 *ret_data_size
= PTR_DIFF(p
, pdata
);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
433 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
435 size_t total_ea_len
= 0;
436 TALLOC_CTX
*mem_ctx
= NULL
;
438 if (!lp_ea_support(SNUM(conn
))) {
441 mem_ctx
= talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
453 TALLOC_CTX
*mem_ctx
= talloc_tos();
454 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
456 for (; ea_list
; ea_list
= ea_list
->next
) {
457 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name
[5], ea_list
->ea
.name
));
460 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
471 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
475 if (!lp_ea_support(SNUM(conn
))) {
476 return NT_STATUS_EAS_NOT_SUPPORTED
;
479 /* For now setting EAs on streams isn't supported. */
480 fname
= smb_fname
->base_name
;
482 for (;ea_list
; ea_list
= ea_list
->next
) {
484 fstring unix_ea_name
;
486 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
487 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
489 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
491 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
493 if (samba_private_attr_name(unix_ea_name
)) {
494 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
495 return NT_STATUS_ACCESS_DENIED
;
498 if (ea_list
->ea
.value
.length
== 0) {
499 /* Remove the attribute. */
500 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
501 DEBUG(10,("set_ea: deleting ea name %s on "
502 "file %s by file descriptor.\n",
503 unix_ea_name
, fsp_str_dbg(fsp
)));
504 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
506 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
507 unix_ea_name
, fname
));
508 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
511 /* Removing a non existent attribute always succeeds. */
512 if (ret
== -1 && errno
== ENOATTR
) {
513 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
519 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
520 DEBUG(10,("set_ea: setting ea name %s on file "
521 "%s by file descriptor.\n",
522 unix_ea_name
, fsp_str_dbg(fsp
)));
523 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
524 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
526 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
527 unix_ea_name
, fname
));
528 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
529 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
535 if (errno
== ENOTSUP
) {
536 return NT_STATUS_EAS_NOT_SUPPORTED
;
539 return map_nt_error_from_unix(errno
);
545 /****************************************************************************
546 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
547 ****************************************************************************/
549 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
551 struct ea_list
*ea_list_head
= NULL
;
552 size_t converted_size
, offset
= 0;
554 while (offset
+ 2 < data_size
) {
555 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
556 unsigned int namelen
= CVAL(pdata
,offset
);
558 offset
++; /* Go past the namelen byte. */
560 /* integer wrap paranioa. */
561 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
562 (offset
> data_size
) || (namelen
> data_size
) ||
563 (offset
+ namelen
>= data_size
)) {
566 /* Ensure the name is null terminated. */
567 if (pdata
[offset
+ namelen
] != '\0') {
570 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
572 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
573 "failed: %s", strerror(errno
)));
579 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
580 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
581 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
587 /****************************************************************************
588 Read one EA list entry from the buffer.
589 ****************************************************************************/
591 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
593 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
595 unsigned int namelen
;
596 size_t converted_size
;
606 eal
->ea
.flags
= CVAL(pdata
,0);
607 namelen
= CVAL(pdata
,1);
608 val_len
= SVAL(pdata
,2);
610 if (4 + namelen
+ 1 + val_len
> data_size
) {
614 /* Ensure the name is null terminated. */
615 if (pdata
[namelen
+ 4] != '\0') {
618 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
619 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
626 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
627 if (!eal
->ea
.value
.data
) {
631 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
633 /* Ensure we're null terminated just in case we print the value. */
634 eal
->ea
.value
.data
[val_len
] = '\0';
635 /* But don't count the null. */
636 eal
->ea
.value
.length
--;
639 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
642 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
643 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
648 /****************************************************************************
649 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
650 ****************************************************************************/
652 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
654 struct ea_list
*ea_list_head
= NULL
;
656 size_t bytes_used
= 0;
658 while (offset
< data_size
) {
659 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
665 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
666 offset
+= bytes_used
;
672 /****************************************************************************
673 Count the total EA size needed.
674 ****************************************************************************/
676 static size_t ea_list_size(struct ea_list
*ealist
)
679 struct ea_list
*listp
;
682 for (listp
= ealist
; listp
; listp
= listp
->next
) {
683 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
684 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
686 /* Add on 4 for total length. */
694 /****************************************************************************
695 Return a union of EA's from a file list and a list of names.
696 The TALLOC context for the two lists *MUST* be identical as we steal
697 memory from one list to add to another. JRA.
698 ****************************************************************************/
700 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
702 struct ea_list
*nlistp
, *flistp
;
704 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
705 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
706 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
712 /* Copy the data from this entry. */
713 nlistp
->ea
.flags
= flistp
->ea
.flags
;
714 nlistp
->ea
.value
= flistp
->ea
.value
;
717 nlistp
->ea
.flags
= 0;
718 ZERO_STRUCT(nlistp
->ea
.value
);
722 *total_ea_len
= ea_list_size(name_list
);
726 /****************************************************************************
727 Send the required number of replies back.
728 We assume all fields other than the data fields are
729 set correctly for the type of call.
730 HACK ! Always assumes smb_setup field is zero.
731 ****************************************************************************/
733 void send_trans2_replies(connection_struct
*conn
,
734 struct smb_request
*req
,
741 /* As we are using a protocol > LANMAN1 then the max_send
742 variable must have been set in the sessetupX call.
743 This takes precedence over the max_xmit field in the
744 global struct. These different max_xmit variables should
745 be merged as this is now too confusing */
747 int data_to_send
= datasize
;
748 int params_to_send
= paramsize
;
750 const char *pp
= params
;
751 const char *pd
= pdata
;
752 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
753 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
754 int data_alignment_offset
= 0;
755 bool overflow
= False
;
756 struct smbd_server_connection
*sconn
= smbd_server_conn
;
757 int max_send
= sconn
->smb1
.sessions
.max_send
;
759 /* Modify the data_to_send and datasize and set the error if
760 we're trying to send more than max_data_bytes. We still send
761 the part of the packet(s) that fit. Strange, but needed
764 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
765 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
766 max_data_bytes
, datasize
));
767 datasize
= data_to_send
= max_data_bytes
;
771 /* If there genuinely are no parameters or data to send just send the empty packet */
773 if(params_to_send
== 0 && data_to_send
== 0) {
774 reply_outbuf(req
, 10, 0);
775 show_msg((char *)req
->outbuf
);
776 if (!srv_send_smb(smbd_server_fd(),
779 IS_CONN_ENCRYPTED(conn
),
781 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
783 TALLOC_FREE(req
->outbuf
);
787 /* When sending params and data ensure that both are nicely aligned */
788 /* Only do this alignment when there is also data to send - else
789 can cause NT redirector problems. */
791 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
792 data_alignment_offset
= 4 - (params_to_send
% 4);
794 /* Space is bufsize minus Netbios over TCP header minus SMB header */
795 /* The alignment_offset is to align the param bytes on an even byte
796 boundary. NT 4.0 Beta needs this to work correctly. */
798 useable_space
= max_send
- (smb_size
801 + data_alignment_offset
);
803 if (useable_space
< 0) {
804 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
805 "= %d!!!", useable_space
));
806 exit_server_cleanly("send_trans2_replies: Not enough space");
809 while (params_to_send
|| data_to_send
) {
810 /* Calculate whether we will totally or partially fill this packet */
812 total_sent_thistime
= params_to_send
+ data_to_send
;
814 /* We can never send more than useable_space */
816 * Note that 'useable_space' does not include the alignment offsets,
817 * but we must include the alignment offsets in the calculation of
818 * the length of the data we send over the wire, as the alignment offsets
819 * are sent here. Fix from Marc_Jacobsen@hp.com.
822 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
824 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
825 + data_alignment_offset
);
828 * We might have SMBtrans2s in req which was transferred to
829 * the outbuf, fix that.
831 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
833 /* Set total params and data to be sent */
834 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
835 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
837 /* Calculate how many parameters and data we can fit into
838 * this packet. Parameters get precedence
841 params_sent_thistime
= MIN(params_to_send
,useable_space
);
842 data_sent_thistime
= useable_space
- params_sent_thistime
;
843 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
845 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
847 /* smb_proff is the offset from the start of the SMB header to the
848 parameter bytes, however the first 4 bytes of outbuf are
849 the Netbios over TCP header. Thus use smb_base() to subtract
850 them from the calculation */
852 SSVAL(req
->outbuf
,smb_proff
,
853 ((smb_buf(req
->outbuf
)+alignment_offset
)
854 - smb_base(req
->outbuf
)));
856 if(params_sent_thistime
== 0)
857 SSVAL(req
->outbuf
,smb_prdisp
,0);
859 /* Absolute displacement of param bytes sent in this packet */
860 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
862 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
863 if(data_sent_thistime
== 0) {
864 SSVAL(req
->outbuf
,smb_droff
,0);
865 SSVAL(req
->outbuf
,smb_drdisp
, 0);
867 /* The offset of the data bytes is the offset of the
868 parameter bytes plus the number of parameters being sent this time */
869 SSVAL(req
->outbuf
, smb_droff
,
870 ((smb_buf(req
->outbuf
)+alignment_offset
)
871 - smb_base(req
->outbuf
))
872 + params_sent_thistime
+ data_alignment_offset
);
873 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
876 /* Initialize the padding for alignment */
878 if (alignment_offset
!= 0) {
879 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
882 /* Copy the param bytes into the packet */
884 if(params_sent_thistime
) {
885 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
886 params_sent_thistime
);
889 /* Copy in the data bytes */
890 if(data_sent_thistime
) {
891 if (data_alignment_offset
!= 0) {
892 memset((smb_buf(req
->outbuf
)+alignment_offset
+
893 params_sent_thistime
), 0,
894 data_alignment_offset
);
896 memcpy(smb_buf(req
->outbuf
)+alignment_offset
897 +params_sent_thistime
+data_alignment_offset
,
898 pd
,data_sent_thistime
);
901 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
902 params_sent_thistime
, data_sent_thistime
, useable_space
));
903 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
904 params_to_send
, data_to_send
, paramsize
, datasize
));
907 error_packet_set((char *)req
->outbuf
,
908 ERRDOS
,ERRbufferoverflow
,
909 STATUS_BUFFER_OVERFLOW
,
913 /* Send the packet */
914 show_msg((char *)req
->outbuf
);
915 if (!srv_send_smb(smbd_server_fd(),
918 IS_CONN_ENCRYPTED(conn
),
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req
->outbuf
);
924 pp
+= params_sent_thistime
;
925 pd
+= data_sent_thistime
;
927 params_to_send
-= params_sent_thistime
;
928 data_to_send
-= data_sent_thistime
;
931 if(params_to_send
< 0 || data_to_send
< 0) {
932 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
933 params_to_send
, data_to_send
));
941 /****************************************************************************
942 Reply to a TRANSACT2_OPEN.
943 ****************************************************************************/
945 static void call_trans2open(connection_struct
*conn
,
946 struct smb_request
*req
,
947 char **pparams
, int total_params
,
948 char **ppdata
, int total_data
,
949 unsigned int max_data_bytes
)
951 struct smb_filename
*smb_fname
= NULL
;
952 char *params
= *pparams
;
953 char *pdata
= *ppdata
;
958 bool return_additional_info
;
971 struct ea_list
*ea_list
= NULL
;
976 uint32 create_disposition
;
977 uint32 create_options
= 0;
978 TALLOC_CTX
*ctx
= talloc_tos();
981 * Ensure we have enough parameters to perform the operation.
984 if (total_params
< 29) {
985 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
989 flags
= SVAL(params
, 0);
990 deny_mode
= SVAL(params
, 2);
991 open_attr
= SVAL(params
,6);
992 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
993 if (oplock_request
) {
994 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
998 return_additional_info
= BITSETW(params
,0);
999 open_sattr
= SVAL(params
, 4);
1000 open_time
= make_unix_date3(params
+8);
1002 open_ofun
= SVAL(params
,12);
1003 open_size
= IVAL(params
,14);
1004 pname
= ¶ms
[28];
1007 reply_doserror(req
, ERRSRV
, ERRaccess
);
1011 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1012 total_params
- 28, STR_TERMINATE
,
1014 if (!NT_STATUS_IS_OK(status
)) {
1015 reply_nterror(req
, status
);
1019 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1020 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1021 (unsigned int)open_ofun
, open_size
));
1023 status
= filename_convert(ctx
,
1025 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1030 if (!NT_STATUS_IS_OK(status
)) {
1031 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1032 reply_botherror(req
,
1033 NT_STATUS_PATH_NOT_COVERED
,
1034 ERRSRV
, ERRbadpath
);
1037 reply_nterror(req
, status
);
1041 if (open_ofun
== 0) {
1042 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1046 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1047 &access_mask
, &share_mode
,
1048 &create_disposition
,
1050 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
1054 /* Any data in this call is an EA list. */
1055 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
1056 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1060 if (total_data
!= 4) {
1061 if (total_data
< 10) {
1062 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1066 if (IVAL(pdata
,0) > total_data
) {
1067 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1068 IVAL(pdata
,0), (unsigned int)total_data
));
1069 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1073 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1076 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1079 } else if (IVAL(pdata
,0) != 4) {
1080 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1084 status
= SMB_VFS_CREATE_FILE(
1087 0, /* root_dir_fid */
1088 smb_fname
, /* fname */
1089 access_mask
, /* access_mask */
1090 share_mode
, /* share_access */
1091 create_disposition
, /* create_disposition*/
1092 create_options
, /* create_options */
1093 open_attr
, /* file_attributes */
1094 oplock_request
, /* oplock_request */
1095 open_size
, /* allocation_size */
1097 ea_list
, /* ea_list */
1099 &smb_action
); /* psbuf */
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 if (open_was_deferred(req
->mid
)) {
1103 /* We have re-scheduled this call. */
1106 reply_openerror(req
, status
);
1110 size
= get_file_size_stat(&smb_fname
->st
);
1111 fattr
= dos_mode(conn
, smb_fname
);
1112 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1113 inode
= smb_fname
->st
.st_ex_ino
;
1115 close_file(req
, fsp
, ERROR_CLOSE
);
1116 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1120 /* Realloc the size of parameters and data we will return */
1121 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1122 if(*pparams
== NULL
) {
1123 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1128 SSVAL(params
,0,fsp
->fnum
);
1129 SSVAL(params
,2,fattr
);
1130 srv_put_dos_date2(params
,4, mtime
);
1131 SIVAL(params
,8, (uint32
)size
);
1132 SSVAL(params
,12,deny_mode
);
1133 SSVAL(params
,14,0); /* open_type - file or directory. */
1134 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1136 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1137 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1140 SSVAL(params
,18,smb_action
);
1143 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1145 SIVAL(params
,20,inode
);
1146 SSVAL(params
,24,0); /* Padding. */
1148 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1149 fsp
->fsp_name
->base_name
);
1150 SIVAL(params
, 26, ea_size
);
1152 SIVAL(params
, 26, 0);
1155 /* Send the required number of replies */
1156 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1158 TALLOC_FREE(smb_fname
);
1161 /*********************************************************
1162 Routine to check if a given string matches exactly.
1163 as a special case a mask of "." does NOT match. That
1164 is required for correct wildcard semantics
1165 Case can be significant or not.
1166 **********************************************************/
1168 static bool exact_match(bool has_wild
,
1169 bool case_sensitive
,
1173 if (mask
[0] == '.' && mask
[1] == 0) {
1181 if (case_sensitive
) {
1182 return strcmp(str
,mask
)==0;
1184 return StrCaseCmp(str
,mask
) == 0;
1188 /****************************************************************************
1189 Return the filetype for UNIX extensions.
1190 ****************************************************************************/
1192 static uint32
unix_filetype(mode_t mode
)
1195 return UNIX_TYPE_FILE
;
1196 else if(S_ISDIR(mode
))
1197 return UNIX_TYPE_DIR
;
1199 else if(S_ISLNK(mode
))
1200 return UNIX_TYPE_SYMLINK
;
1203 else if(S_ISCHR(mode
))
1204 return UNIX_TYPE_CHARDEV
;
1207 else if(S_ISBLK(mode
))
1208 return UNIX_TYPE_BLKDEV
;
1211 else if(S_ISFIFO(mode
))
1212 return UNIX_TYPE_FIFO
;
1215 else if(S_ISSOCK(mode
))
1216 return UNIX_TYPE_SOCKET
;
1219 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1220 return UNIX_TYPE_UNKNOWN
;
1223 /****************************************************************************
1224 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1225 ****************************************************************************/
1227 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1229 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1230 const SMB_STRUCT_STAT
*psbuf
,
1232 enum perm_type ptype
,
1237 if (perms
== SMB_MODE_NO_CHANGE
) {
1238 if (!VALID_STAT(*psbuf
)) {
1239 return NT_STATUS_INVALID_PARAMETER
;
1241 *ret_perms
= psbuf
->st_ex_mode
;
1242 return NT_STATUS_OK
;
1246 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1247 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1248 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1249 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1250 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1251 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1252 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1253 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1254 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1256 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1259 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1262 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1267 /* Apply mode mask */
1268 ret
&= lp_create_mask(SNUM(conn
));
1269 /* Add in force bits */
1270 ret
|= lp_force_create_mode(SNUM(conn
));
1273 ret
&= lp_dir_mask(SNUM(conn
));
1274 /* Add in force bits */
1275 ret
|= lp_force_dir_mode(SNUM(conn
));
1277 case PERM_EXISTING_FILE
:
1278 /* Apply mode mask */
1279 ret
&= lp_security_mask(SNUM(conn
));
1280 /* Add in force bits */
1281 ret
|= lp_force_security_mode(SNUM(conn
));
1283 case PERM_EXISTING_DIR
:
1284 /* Apply mode mask */
1285 ret
&= lp_dir_security_mask(SNUM(conn
));
1286 /* Add in force bits */
1287 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1292 return NT_STATUS_OK
;
1295 /****************************************************************************
1296 Needed to show the msdfs symlinks as directories. Modifies psbuf
1297 to be a directory if it's a msdfs link.
1298 ****************************************************************************/
1300 static bool check_msdfs_link(connection_struct
*conn
,
1301 const char *pathname
,
1302 SMB_STRUCT_STAT
*psbuf
)
1304 int saved_errno
= errno
;
1305 if(lp_host_msdfs() &&
1306 lp_msdfs_root(SNUM(conn
)) &&
1307 is_msdfs_link(conn
, pathname
, psbuf
)) {
1309 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1312 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1313 errno
= saved_errno
;
1316 errno
= saved_errno
;
1321 /****************************************************************************
1322 Get a level dependent lanman2 dir entry.
1323 ****************************************************************************/
1325 struct smbd_dirptr_lanman2_state
{
1326 connection_struct
*conn
;
1327 uint32_t info_level
;
1328 bool check_mangled_names
;
1330 bool got_exact_match
;
1333 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1339 struct smbd_dirptr_lanman2_state
*state
=
1340 (struct smbd_dirptr_lanman2_state
*)private_data
;
1342 char mangled_name
[13]; /* mangled 8.3 name. */
1346 /* Mangle fname if it's an illegal name. */
1347 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1348 ok
= name_to_8_3(dname
, mangled_name
,
1349 true, state
->conn
->params
);
1353 fname
= mangled_name
;
1358 got_match
= exact_match(state
->has_wild
,
1359 state
->conn
->case_sensitive
,
1361 state
->got_exact_match
= got_match
;
1363 got_match
= mask_match(fname
, mask
,
1364 state
->conn
->case_sensitive
);
1367 if(!got_match
&& state
->check_mangled_names
&&
1368 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1370 * It turns out that NT matches wildcards against
1371 * both long *and* short names. This may explain some
1372 * of the wildcard wierdness from old DOS clients
1373 * that some people have been seeing.... JRA.
1375 /* Force the mangling into 8.3. */
1376 ok
= name_to_8_3(fname
, mangled_name
,
1377 false, state
->conn
->params
);
1382 got_match
= exact_match(state
->has_wild
,
1383 state
->conn
->case_sensitive
,
1384 mangled_name
, mask
);
1385 state
->got_exact_match
= got_match
;
1387 got_match
= mask_match(mangled_name
, mask
,
1388 state
->conn
->case_sensitive
);
1396 *_fname
= talloc_strdup(ctx
, fname
);
1397 if (*_fname
== NULL
) {
1404 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1406 struct smb_filename
*smb_fname
,
1409 struct smbd_dirptr_lanman2_state
*state
=
1410 (struct smbd_dirptr_lanman2_state
*)private_data
;
1411 bool ms_dfs_link
= false;
1414 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1415 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1416 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1417 "Couldn't lstat [%s] (%s)\n",
1418 smb_fname_str_dbg(smb_fname
),
1422 } else if (!VALID_STAT(smb_fname
->st
) &&
1423 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1424 /* Needed to show the msdfs symlinks as
1427 ms_dfs_link
= check_msdfs_link(state
->conn
,
1428 smb_fname
->base_name
,
1431 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1432 "Couldn't stat [%s] (%s)\n",
1433 smb_fname_str_dbg(smb_fname
),
1440 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1442 mode
= dos_mode(state
->conn
, smb_fname
);
1449 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1450 connection_struct
*conn
,
1452 uint32_t info_level
,
1453 struct ea_list
*name_list
,
1454 bool check_mangled_names
,
1455 bool requires_resume_key
,
1458 const struct smb_filename
*smb_fname
,
1459 uint64_t space_remaining
,
1464 uint64_t *last_entry_off
)
1466 char *p
, *q
, *pdata
= *ppdata
;
1468 uint64_t file_size
= 0;
1469 uint64_t allocation_size
= 0;
1471 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1472 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1473 time_t c_date
= (time_t)0;
1475 char *last_entry_ptr
;
1477 uint32_t nt_extmode
; /* Used for NT connections instead of mode */
1479 *out_of_space
= false;
1481 ZERO_STRUCT(mdate_ts
);
1482 ZERO_STRUCT(adate_ts
);
1483 ZERO_STRUCT(create_date_ts
);
1484 ZERO_STRUCT(cdate_ts
);
1486 if (!(mode
& aDIR
)) {
1487 file_size
= get_file_size_stat(&smb_fname
->st
);
1489 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1491 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1492 adate_ts
= smb_fname
->st
.st_ex_atime
;
1493 create_date_ts
= get_create_timespec(NULL
, smb_fname
);
1494 cdate_ts
= get_change_timespec(NULL
, smb_fname
);
1496 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1497 dos_filetime_timespec(&create_date_ts
);
1498 dos_filetime_timespec(&mdate_ts
);
1499 dos_filetime_timespec(&adate_ts
);
1500 dos_filetime_timespec(&cdate_ts
);
1503 create_date
= convert_timespec_to_time_t(create_date_ts
);
1504 mdate
= convert_timespec_to_time_t(mdate_ts
);
1505 adate
= convert_timespec_to_time_t(adate_ts
);
1506 c_date
= convert_timespec_to_time_t(cdate_ts
);
1511 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1513 switch (info_level
) {
1514 case SMB_FIND_INFO_STANDARD
:
1515 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1516 if(requires_resume_key
) {
1520 srv_put_dos_date2(p
,0,create_date
);
1521 srv_put_dos_date2(p
,4,adate
);
1522 srv_put_dos_date2(p
,8,mdate
);
1523 SIVAL(p
,12,(uint32
)file_size
);
1524 SIVAL(p
,16,(uint32
)allocation_size
);
1528 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1529 p
+= ucs2_align(base_data
, p
, 0);
1531 len
= srvstr_push(base_data
, flags2
, p
,
1532 fname
, PTR_DIFF(end_data
, p
),
1534 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1536 SCVAL(nameptr
, -1, len
- 2);
1538 SCVAL(nameptr
, -1, 0);
1542 SCVAL(nameptr
, -1, len
- 1);
1544 SCVAL(nameptr
, -1, 0);
1550 case SMB_FIND_EA_SIZE
:
1551 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1552 if (requires_resume_key
) {
1556 srv_put_dos_date2(p
,0,create_date
);
1557 srv_put_dos_date2(p
,4,adate
);
1558 srv_put_dos_date2(p
,8,mdate
);
1559 SIVAL(p
,12,(uint32
)file_size
);
1560 SIVAL(p
,16,(uint32
)allocation_size
);
1563 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1564 smb_fname
->base_name
);
1565 SIVAL(p
,22,ea_size
); /* Extended attributes */
1569 len
= srvstr_push(base_data
, flags2
,
1570 p
, fname
, PTR_DIFF(end_data
, p
),
1571 STR_TERMINATE
| STR_NOALIGN
);
1572 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1585 SCVAL(nameptr
,0,len
);
1587 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1590 case SMB_FIND_EA_LIST
:
1592 struct ea_list
*file_list
= NULL
;
1595 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1599 if (requires_resume_key
) {
1603 srv_put_dos_date2(p
,0,create_date
);
1604 srv_put_dos_date2(p
,4,adate
);
1605 srv_put_dos_date2(p
,8,mdate
);
1606 SIVAL(p
,12,(uint32
)file_size
);
1607 SIVAL(p
,16,(uint32
)allocation_size
);
1609 p
+= 22; /* p now points to the EA area. */
1611 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1612 smb_fname
->base_name
,
1614 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1616 /* We need to determine if this entry will fit in the space available. */
1617 /* Max string size is 255 bytes. */
1618 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1619 *out_of_space
= true;
1620 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1621 return False
; /* Not finished - just out of space */
1624 /* Push the ea_data followed by the name. */
1625 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1627 len
= srvstr_push(base_data
, flags2
,
1628 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1629 STR_TERMINATE
| STR_NOALIGN
);
1630 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1643 SCVAL(nameptr
,0,len
);
1645 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1649 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1651 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1653 SIVAL(p
,0,reskey
); p
+= 4;
1654 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1655 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1656 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1657 put_long_date_timespec(p
,cdate_ts
); p
+= 8;
1658 SOFF_T(p
,0,file_size
); p
+= 8;
1659 SOFF_T(p
,0,allocation_size
); p
+= 8;
1660 SIVAL(p
,0,nt_extmode
); p
+= 4;
1661 q
= p
; p
+= 4; /* q is placeholder for name length. */
1663 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1664 smb_fname
->base_name
);
1665 SIVAL(p
,0,ea_size
); /* Extended attributes */
1668 /* Clear the short name buffer. This is
1669 * IMPORTANT as not doing so will trigger
1670 * a Win2k client bug. JRA.
1672 if (!was_8_3
&& check_mangled_names
) {
1673 char mangled_name
[13]; /* mangled 8.3 name. */
1674 if (!name_to_8_3(fname
,mangled_name
,True
,
1676 /* Error - mangle failed ! */
1677 memset(mangled_name
,'\0',12);
1679 mangled_name
[12] = 0;
1680 len
= srvstr_push(base_data
, flags2
,
1681 p
+2, mangled_name
, 24,
1682 STR_UPPER
|STR_UNICODE
);
1684 memset(p
+ 2 + len
,'\0',24 - len
);
1691 len
= srvstr_push(base_data
, flags2
, p
,
1692 fname
, PTR_DIFF(end_data
, p
),
1693 STR_TERMINATE_ASCII
);
1696 SIVAL(p
,0,0); /* Ensure any padding is null. */
1697 len
= PTR_DIFF(p
, pdata
);
1698 len
= (len
+ 3) & ~3;
1703 case SMB_FIND_FILE_DIRECTORY_INFO
:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1706 SIVAL(p
,0,reskey
); p
+= 4;
1707 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1708 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1709 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1710 put_long_date_timespec(p
,cdate_ts
); p
+= 8;
1711 SOFF_T(p
,0,file_size
); p
+= 8;
1712 SOFF_T(p
,0,allocation_size
); p
+= 8;
1713 SIVAL(p
,0,nt_extmode
); p
+= 4;
1714 len
= srvstr_push(base_data
, flags2
,
1715 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1716 STR_TERMINATE_ASCII
);
1719 SIVAL(p
,0,0); /* Ensure any padding is null. */
1720 len
= PTR_DIFF(p
, pdata
);
1721 len
= (len
+ 3) & ~3;
1726 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1727 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1729 SIVAL(p
,0,reskey
); p
+= 4;
1730 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1731 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1732 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1733 put_long_date_timespec(p
,cdate_ts
); p
+= 8;
1734 SOFF_T(p
,0,file_size
); p
+= 8;
1735 SOFF_T(p
,0,allocation_size
); p
+= 8;
1736 SIVAL(p
,0,nt_extmode
); p
+= 4;
1737 q
= p
; p
+= 4; /* q is placeholder for name length. */
1739 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1740 smb_fname
->base_name
);
1741 SIVAL(p
,0,ea_size
); /* Extended attributes */
1744 len
= srvstr_push(base_data
, flags2
, p
,
1745 fname
, PTR_DIFF(end_data
, p
),
1746 STR_TERMINATE_ASCII
);
1750 SIVAL(p
,0,0); /* Ensure any padding is null. */
1751 len
= PTR_DIFF(p
, pdata
);
1752 len
= (len
+ 3) & ~3;
1757 case SMB_FIND_FILE_NAMES_INFO
:
1758 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1760 SIVAL(p
,0,reskey
); p
+= 4;
1762 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1763 acl on a dir (tridge) */
1764 len
= srvstr_push(base_data
, flags2
, p
,
1765 fname
, PTR_DIFF(end_data
, p
),
1766 STR_TERMINATE_ASCII
);
1769 SIVAL(p
,0,0); /* Ensure any padding is null. */
1770 len
= PTR_DIFF(p
, pdata
);
1771 len
= (len
+ 3) & ~3;
1776 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1777 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1779 SIVAL(p
,0,reskey
); p
+= 4;
1780 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1781 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1782 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1783 put_long_date_timespec(p
,cdate_ts
); p
+= 8;
1784 SOFF_T(p
,0,file_size
); p
+= 8;
1785 SOFF_T(p
,0,allocation_size
); p
+= 8;
1786 SIVAL(p
,0,nt_extmode
); p
+= 4;
1787 q
= p
; p
+= 4; /* q is placeholder for name length. */
1789 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1790 smb_fname
->base_name
);
1791 SIVAL(p
,0,ea_size
); /* Extended attributes */
1794 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1795 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1796 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1797 len
= srvstr_push(base_data
, flags2
, p
,
1798 fname
, PTR_DIFF(end_data
, p
),
1799 STR_TERMINATE_ASCII
);
1802 SIVAL(p
,0,0); /* Ensure any padding is null. */
1803 len
= PTR_DIFF(p
, pdata
);
1804 len
= (len
+ 3) & ~3;
1809 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1811 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1813 SIVAL(p
,0,reskey
); p
+= 4;
1814 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1815 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1816 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1817 put_long_date_timespec(p
,cdate_ts
); p
+= 8;
1818 SOFF_T(p
,0,file_size
); p
+= 8;
1819 SOFF_T(p
,0,allocation_size
); p
+= 8;
1820 SIVAL(p
,0,nt_extmode
); p
+= 4;
1821 q
= p
; p
+= 4; /* q is placeholder for name length */
1823 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1824 smb_fname
->base_name
);
1825 SIVAL(p
,0,ea_size
); /* Extended attributes */
1828 /* Clear the short name buffer. This is
1829 * IMPORTANT as not doing so will trigger
1830 * a Win2k client bug. JRA.
1832 if (!was_8_3
&& check_mangled_names
) {
1833 char mangled_name
[13]; /* mangled 8.3 name. */
1834 if (!name_to_8_3(fname
,mangled_name
,True
,
1836 /* Error - mangle failed ! */
1837 memset(mangled_name
,'\0',12);
1839 mangled_name
[12] = 0;
1840 len
= srvstr_push(base_data
, flags2
,
1841 p
+2, mangled_name
, 24,
1842 STR_UPPER
|STR_UNICODE
);
1845 memset(p
+ 2 + len
,'\0',24 - len
);
1852 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1853 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1854 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1855 len
= srvstr_push(base_data
, flags2
, p
,
1856 fname
, PTR_DIFF(end_data
, p
),
1857 STR_TERMINATE_ASCII
);
1860 SIVAL(p
,0,0); /* Ensure any padding is null. */
1861 len
= PTR_DIFF(p
, pdata
);
1862 len
= (len
+ 3) & ~3;
1867 /* CIFS UNIX Extension. */
1869 case SMB_FIND_FILE_UNIX
:
1870 case SMB_FIND_FILE_UNIX_INFO2
:
1872 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1874 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1876 if (info_level
== SMB_FIND_FILE_UNIX
) {
1877 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1878 p
= store_file_unix_basic(conn
, p
,
1879 NULL
, &smb_fname
->st
);
1880 len
= srvstr_push(base_data
, flags2
, p
,
1881 fname
, PTR_DIFF(end_data
, p
),
1884 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1885 p
= store_file_unix_basic_info2(conn
, p
,
1886 NULL
, &smb_fname
->st
);
1889 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1890 PTR_DIFF(end_data
, p
), 0);
1891 SIVAL(nameptr
, 0, len
);
1895 SIVAL(p
,0,0); /* Ensure any padding is null. */
1897 len
= PTR_DIFF(p
, pdata
);
1898 len
= (len
+ 3) & ~3;
1899 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1901 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1909 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1910 *out_of_space
= true;
1911 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1912 return false; /* Not finished - just out of space */
1915 /* Setup the last entry pointer, as an offset from base_data */
1916 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1917 /* Advance the data pointer to the next slot */
1923 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1924 connection_struct
*conn
,
1925 struct dptr_struct
*dirptr
,
1927 const char *path_mask
,
1930 int requires_resume_key
,
1936 int space_remaining
,
1938 bool *got_exact_match
,
1939 int *_last_entry_off
,
1940 struct ea_list
*name_list
)
1943 const char *mask
= NULL
;
1944 long prev_dirpos
= 0;
1947 struct smb_filename
*smb_fname
= NULL
;
1948 struct smbd_dirptr_lanman2_state state
;
1950 uint64_t last_entry_off
= 0;
1954 state
.info_level
= info_level
;
1955 state
.check_mangled_names
= lp_manglednames(conn
->params
);
1956 state
.has_wild
= dptr_has_wild(dirptr
);
1957 state
.got_exact_match
= false;
1959 *out_of_space
= false;
1960 *got_exact_match
= false;
1962 p
= strrchr_m(path_mask
,'/');
1973 ok
= smbd_dirptr_get_entry(ctx
,
1979 smbd_dirptr_lanman2_match_fn
,
1980 smbd_dirptr_lanman2_mode_fn
,
1990 *got_exact_match
= state
.got_exact_match
;
1992 ok
= smbd_marshall_dir_entry(ctx
,
1997 state
.check_mangled_names
,
1998 requires_resume_key
,
2009 TALLOC_FREE(smb_fname
);
2010 if (*out_of_space
) {
2011 dptr_SeekDir(dirptr
, prev_dirpos
);
2018 *_last_entry_off
= last_entry_off
;
2022 /****************************************************************************
2023 Reply to a TRANS2_FINDFIRST.
2024 ****************************************************************************/
2026 static void call_trans2findfirst(connection_struct
*conn
,
2027 struct smb_request
*req
,
2028 char **pparams
, int total_params
,
2029 char **ppdata
, int total_data
,
2030 unsigned int max_data_bytes
)
2032 /* We must be careful here that we don't return more than the
2033 allowed number of data bytes. If this means returning fewer than
2034 maxentries then so be it. We assume that the redirector has
2035 enough room for the fixed number of parameter bytes it has
2037 struct smb_filename
*smb_dname
= NULL
;
2038 char *params
= *pparams
;
2039 char *pdata
= *ppdata
;
2043 uint16 findfirst_flags
;
2044 bool close_after_first
;
2046 bool requires_resume_key
;
2048 char *directory
= NULL
;
2051 int last_entry_off
=0;
2055 bool finished
= False
;
2056 bool dont_descend
= False
;
2057 bool out_of_space
= False
;
2058 int space_remaining
;
2059 bool mask_contains_wcard
= False
;
2060 struct ea_list
*ea_list
= NULL
;
2061 NTSTATUS ntstatus
= NT_STATUS_OK
;
2062 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2063 TALLOC_CTX
*ctx
= talloc_tos();
2064 struct dptr_struct
*dirptr
= NULL
;
2065 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2067 if (total_params
< 13) {
2068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2072 dirtype
= SVAL(params
,0);
2073 maxentries
= SVAL(params
,2);
2074 findfirst_flags
= SVAL(params
,4);
2075 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2076 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2077 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2078 info_level
= SVAL(params
,6);
2080 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2081 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2082 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2083 info_level
, max_data_bytes
));
2086 /* W2K3 seems to treat zero as 1. */
2090 switch (info_level
) {
2091 case SMB_FIND_INFO_STANDARD
:
2092 case SMB_FIND_EA_SIZE
:
2093 case SMB_FIND_EA_LIST
:
2094 case SMB_FIND_FILE_DIRECTORY_INFO
:
2095 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2096 case SMB_FIND_FILE_NAMES_INFO
:
2097 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2098 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2099 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2101 case SMB_FIND_FILE_UNIX
:
2102 case SMB_FIND_FILE_UNIX_INFO2
:
2103 /* Always use filesystem for UNIX mtime query. */
2104 ask_sharemode
= false;
2105 if (!lp_unix_extensions()) {
2106 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2111 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2115 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2116 params
+12, total_params
- 12,
2117 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2118 if (!NT_STATUS_IS_OK(ntstatus
)) {
2119 reply_nterror(req
, ntstatus
);
2123 ntstatus
= filename_convert(ctx
, conn
,
2124 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2127 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2128 &mask_contains_wcard
,
2130 if (!NT_STATUS_IS_OK(ntstatus
)) {
2131 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2132 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2133 ERRSRV
, ERRbadpath
);
2136 reply_nterror(req
, ntstatus
);
2140 mask
= smb_dname
->original_lcomp
;
2142 directory
= smb_dname
->base_name
;
2144 p
= strrchr_m(directory
,'/');
2146 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2147 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2148 mask
= talloc_strdup(ctx
,"*");
2150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2153 mask_contains_wcard
= True
;
2155 directory
= talloc_strdup(talloc_tos(), "./");
2157 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2164 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2166 if (info_level
== SMB_FIND_EA_LIST
) {
2169 if (total_data
< 4) {
2170 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2174 ea_size
= IVAL(pdata
,0);
2175 if (ea_size
!= total_data
) {
2176 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2177 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2178 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2182 if (!lp_ea_support(SNUM(conn
))) {
2183 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2187 /* Pull out the list of names. */
2188 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2195 *ppdata
= (char *)SMB_REALLOC(
2196 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2197 if(*ppdata
== NULL
) {
2198 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2202 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2204 /* Realloc the params space */
2205 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2206 if (*pparams
== NULL
) {
2207 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2212 /* Save the wildcard match and attribs we are using on this directory -
2213 needed as lanman2 assumes these are being saved between calls */
2215 ntstatus
= dptr_create(conn
,
2221 mask_contains_wcard
,
2225 if (!NT_STATUS_IS_OK(ntstatus
)) {
2226 reply_nterror(req
, ntstatus
);
2230 dptr_num
= dptr_dnum(dirptr
);
2231 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2233 /* Initialize per TRANS2_FIND_FIRST operation data */
2234 dptr_init_search_op(dirptr
);
2236 /* We don't need to check for VOL here as this is returned by
2237 a different TRANS2 call. */
2239 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2240 directory
,lp_dontdescend(SNUM(conn
))));
2241 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2242 dont_descend
= True
;
2245 space_remaining
= max_data_bytes
;
2246 out_of_space
= False
;
2248 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2249 bool got_exact_match
= False
;
2251 /* this is a heuristic to avoid seeking the dirptr except when
2252 absolutely necessary. It allows for a filename of about 40 chars */
2253 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2254 out_of_space
= True
;
2257 finished
= !get_lanman2_dir_entry(ctx
,
2261 mask
,dirtype
,info_level
,
2262 requires_resume_key
,dont_descend
,
2265 space_remaining
, &out_of_space
,
2267 &last_entry_off
, ea_list
);
2270 if (finished
&& out_of_space
)
2273 if (!finished
&& !out_of_space
)
2277 * As an optimisation if we know we aren't looking
2278 * for a wildcard name (ie. the name matches the wildcard exactly)
2279 * then we can finish on any (first) match.
2280 * This speeds up large directory searches. JRA.
2286 /* Ensure space_remaining never goes -ve. */
2287 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2288 space_remaining
= 0;
2289 out_of_space
= true;
2291 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2295 /* Check if we can close the dirptr */
2296 if(close_after_first
|| (finished
&& close_if_end
)) {
2297 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2298 dptr_close(sconn
, &dptr_num
);
2302 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2303 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2304 * the protocol level is less than NT1. Tested with smbclient. JRA.
2305 * This should fix the OS/2 client bug #2335.
2308 if(numentries
== 0) {
2309 dptr_close(sconn
, &dptr_num
);
2310 if (Protocol
< PROTOCOL_NT1
) {
2311 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2314 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2315 ERRDOS
, ERRbadfile
);
2320 /* At this point pdata points to numentries directory entries. */
2322 /* Set up the return parameter block */
2323 SSVAL(params
,0,dptr_num
);
2324 SSVAL(params
,2,numentries
);
2325 SSVAL(params
,4,finished
);
2326 SSVAL(params
,6,0); /* Never an EA error */
2327 SSVAL(params
,8,last_entry_off
);
2329 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2332 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2333 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2335 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2339 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2340 smb_fn_name(req
->cmd
),
2341 mask
, directory
, dirtype
, numentries
) );
2344 * Force a name mangle here to ensure that the
2345 * mask as an 8.3 name is top of the mangled cache.
2346 * The reasons for this are subtle. Don't remove
2347 * this code unless you know what you are doing
2348 * (see PR#13758). JRA.
2351 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2352 char mangled_name
[13];
2353 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2356 TALLOC_FREE(smb_dname
);
2360 /****************************************************************************
2361 Reply to a TRANS2_FINDNEXT.
2362 ****************************************************************************/
2364 static void call_trans2findnext(connection_struct
*conn
,
2365 struct smb_request
*req
,
2366 char **pparams
, int total_params
,
2367 char **ppdata
, int total_data
,
2368 unsigned int max_data_bytes
)
2370 /* We must be careful here that we don't return more than the
2371 allowed number of data bytes. If this means returning fewer than
2372 maxentries then so be it. We assume that the redirector has
2373 enough room for the fixed number of parameter bytes it has
2375 char *params
= *pparams
;
2376 char *pdata
= *ppdata
;
2382 uint16 findnext_flags
;
2383 bool close_after_request
;
2385 bool requires_resume_key
;
2387 bool mask_contains_wcard
= False
;
2388 char *resume_name
= NULL
;
2389 const char *mask
= NULL
;
2390 const char *directory
= NULL
;
2394 int i
, last_entry_off
=0;
2395 bool finished
= False
;
2396 bool dont_descend
= False
;
2397 bool out_of_space
= False
;
2398 int space_remaining
;
2399 struct ea_list
*ea_list
= NULL
;
2400 NTSTATUS ntstatus
= NT_STATUS_OK
;
2401 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2402 TALLOC_CTX
*ctx
= talloc_tos();
2403 struct dptr_struct
*dirptr
;
2404 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2406 if (total_params
< 13) {
2407 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2411 dptr_num
= SVAL(params
,0);
2412 maxentries
= SVAL(params
,2);
2413 info_level
= SVAL(params
,4);
2414 resume_key
= IVAL(params
,6);
2415 findnext_flags
= SVAL(params
,10);
2416 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2417 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2418 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2419 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2421 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2423 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2424 &mask_contains_wcard
);
2425 if (!NT_STATUS_IS_OK(ntstatus
)) {
2426 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2427 complain (it thinks we're asking for the directory above the shared
2428 path or an invalid name). Catch this as the resume name is only compared, never used in
2429 a file access. JRA. */
2430 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2431 &resume_name
, params
+12,
2435 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2436 reply_nterror(req
, ntstatus
);
2441 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2442 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2443 resume_key = %d resume name = %s continue=%d level = %d\n",
2444 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2445 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2448 /* W2K3 seems to treat zero as 1. */
2452 switch (info_level
) {
2453 case SMB_FIND_INFO_STANDARD
:
2454 case SMB_FIND_EA_SIZE
:
2455 case SMB_FIND_EA_LIST
:
2456 case SMB_FIND_FILE_DIRECTORY_INFO
:
2457 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2458 case SMB_FIND_FILE_NAMES_INFO
:
2459 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2460 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2461 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2463 case SMB_FIND_FILE_UNIX
:
2464 case SMB_FIND_FILE_UNIX_INFO2
:
2465 /* Always use filesystem for UNIX mtime query. */
2466 ask_sharemode
= false;
2467 if (!lp_unix_extensions()) {
2468 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2473 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2477 if (info_level
== SMB_FIND_EA_LIST
) {
2480 if (total_data
< 4) {
2481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2485 ea_size
= IVAL(pdata
,0);
2486 if (ea_size
!= total_data
) {
2487 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2488 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2493 if (!lp_ea_support(SNUM(conn
))) {
2494 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2498 /* Pull out the list of names. */
2499 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2506 *ppdata
= (char *)SMB_REALLOC(
2507 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2508 if(*ppdata
== NULL
) {
2509 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2514 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2516 /* Realloc the params space */
2517 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2518 if(*pparams
== NULL
) {
2519 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2525 /* Check that the dptr is valid */
2526 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2527 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2531 directory
= dptr_path(sconn
, dptr_num
);
2533 /* Get the wildcard mask from the dptr */
2534 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2535 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2536 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2542 /* Get the attr mask from the dptr */
2543 dirtype
= dptr_attr(sconn
, dptr_num
);
2545 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2546 dptr_num
, mask
, dirtype
,
2548 dptr_TellDir(dirptr
)));
2550 /* Initialize per TRANS2_FIND_NEXT operation data */
2551 dptr_init_search_op(dirptr
);
2553 /* We don't need to check for VOL here as this is returned by
2554 a different TRANS2 call. */
2556 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2557 directory
,lp_dontdescend(SNUM(conn
))));
2558 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2559 dont_descend
= True
;
2562 space_remaining
= max_data_bytes
;
2563 out_of_space
= False
;
2566 * Seek to the correct position. We no longer use the resume key but
2567 * depend on the last file name instead.
2570 if(*resume_name
&& !continue_bit
) {
2573 long current_pos
= 0;
2575 * Remember, name_to_8_3 is called by
2576 * get_lanman2_dir_entry(), so the resume name
2577 * could be mangled. Ensure we check the unmangled name.
2580 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2581 char *new_resume_name
= NULL
;
2582 mangle_lookup_name_from_8_3(ctx
,
2586 if (new_resume_name
) {
2587 resume_name
= new_resume_name
;
2592 * Fix for NT redirector problem triggered by resume key indexes
2593 * changing between directory scans. We now return a resume key of 0
2594 * and instead look for the filename to continue from (also given
2595 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2596 * findfirst/findnext (as is usual) then the directory pointer
2597 * should already be at the correct place.
2600 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2601 } /* end if resume_name && !continue_bit */
2603 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2604 bool got_exact_match
= False
;
2606 /* this is a heuristic to avoid seeking the dirptr except when
2607 absolutely necessary. It allows for a filename of about 40 chars */
2608 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2609 out_of_space
= True
;
2612 finished
= !get_lanman2_dir_entry(ctx
,
2616 mask
,dirtype
,info_level
,
2617 requires_resume_key
,dont_descend
,
2620 space_remaining
, &out_of_space
,
2622 &last_entry_off
, ea_list
);
2625 if (finished
&& out_of_space
)
2628 if (!finished
&& !out_of_space
)
2632 * As an optimisation if we know we aren't looking
2633 * for a wildcard name (ie. the name matches the wildcard exactly)
2634 * then we can finish on any (first) match.
2635 * This speeds up large directory searches. JRA.
2641 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2644 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2645 smb_fn_name(req
->cmd
),
2646 mask
, directory
, dirtype
, numentries
) );
2648 /* Check if we can close the dirptr */
2649 if(close_after_request
|| (finished
&& close_if_end
)) {
2650 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2651 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2654 /* Set up the return parameter block */
2655 SSVAL(params
,0,numentries
);
2656 SSVAL(params
,2,finished
);
2657 SSVAL(params
,4,0); /* Never an EA error */
2658 SSVAL(params
,6,last_entry_off
);
2660 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2666 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2668 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2672 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2674 SMB_ASSERT(extended_info
!= NULL
);
2676 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2677 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2678 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2679 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2680 #ifdef SAMBA_VERSION_REVISION
2681 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2683 extended_info
->samba_subversion
= 0;
2684 #ifdef SAMBA_VERSION_RC_RELEASE
2685 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2687 #ifdef SAMBA_VERSION_PRE_RELEASE
2688 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2691 #ifdef SAMBA_VERSION_VENDOR_PATCH
2692 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2694 extended_info
->samba_gitcommitdate
= 0;
2695 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2696 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2699 memset(extended_info
->samba_version_string
, 0,
2700 sizeof(extended_info
->samba_version_string
));
2702 snprintf (extended_info
->samba_version_string
,
2703 sizeof(extended_info
->samba_version_string
),
2704 "%s", samba_version_string());
2707 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2708 TALLOC_CTX
*mem_ctx
,
2709 uint16_t info_level
,
2711 unsigned int max_data_bytes
,
2715 char *pdata
, *end_data
;
2716 int data_len
= 0, len
;
2717 const char *vname
= volume_label(SNUM(conn
));
2718 int snum
= SNUM(conn
);
2719 char *fstype
= lp_fstype(SNUM(conn
));
2720 uint32 additional_flags
= 0;
2721 struct smb_filename
*smb_fname_dot
= NULL
;
2726 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2727 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2728 "info level (0x%x) on IPC$.\n",
2729 (unsigned int)info_level
));
2730 return NT_STATUS_ACCESS_DENIED
;
2734 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2736 status
= create_synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
,
2738 if (!NT_STATUS_IS_OK(status
)) {
2742 if(SMB_VFS_STAT(conn
, smb_fname_dot
) != 0) {
2743 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2744 TALLOC_FREE(smb_fname_dot
);
2745 return map_nt_error_from_unix(errno
);
2748 st
= smb_fname_dot
->st
;
2749 TALLOC_FREE(smb_fname_dot
);
2751 *ppdata
= (char *)SMB_REALLOC(
2752 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2753 if (*ppdata
== NULL
) {
2754 return NT_STATUS_NO_MEMORY
;
2758 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2759 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2761 switch (info_level
) {
2762 case SMB_INFO_ALLOCATION
:
2764 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2766 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2767 return map_nt_error_from_unix(errno
);
2770 block_size
= lp_block_size(snum
);
2771 if (bsize
< block_size
) {
2772 uint64_t factor
= block_size
/bsize
;
2777 if (bsize
> block_size
) {
2778 uint64_t factor
= bsize
/block_size
;
2783 bytes_per_sector
= 512;
2784 sectors_per_unit
= bsize
/bytes_per_sector
;
2786 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2787 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2788 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2790 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2791 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2792 SIVAL(pdata
,l1_cUnit
,dsize
);
2793 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2794 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2798 case SMB_INFO_VOLUME
:
2799 /* Return volume name */
2801 * Add volume serial number - hash of a combination of
2802 * the called hostname and the service name.
2804 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2806 * Win2k3 and previous mess this up by sending a name length
2807 * one byte short. I believe only older clients (OS/2 Win9x) use
2808 * this call so try fixing this by adding a terminating null to
2809 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2813 pdata
+l2_vol_szVolLabel
, vname
,
2814 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2815 STR_NOALIGN
|STR_TERMINATE
);
2816 SCVAL(pdata
,l2_vol_cch
,len
);
2817 data_len
= l2_vol_szVolLabel
+ len
;
2818 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2819 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2823 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2824 case SMB_FS_ATTRIBUTE_INFORMATION
:
2826 additional_flags
= 0;
2827 #if defined(HAVE_SYS_QUOTAS)
2828 additional_flags
|= FILE_VOLUME_QUOTAS
;
2831 if(lp_nt_acl_support(SNUM(conn
))) {
2832 additional_flags
|= FILE_PERSISTENT_ACLS
;
2835 /* Capabilities are filled in at connection time through STATVFS call */
2836 additional_flags
|= conn
->fs_capabilities
;
2838 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2839 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2840 additional_flags
); /* FS ATTRIBUTES */
2842 SIVAL(pdata
,4,255); /* Max filename component length */
2843 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2844 and will think we can't do long filenames */
2845 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2846 PTR_DIFF(end_data
, pdata
+12),
2849 data_len
= 12 + len
;
2852 case SMB_QUERY_FS_LABEL_INFO
:
2853 case SMB_FS_LABEL_INFORMATION
:
2854 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2855 PTR_DIFF(end_data
, pdata
+4), 0);
2860 case SMB_QUERY_FS_VOLUME_INFO
:
2861 case SMB_FS_VOLUME_INFORMATION
:
2864 * Add volume serial number - hash of a combination of
2865 * the called hostname and the service name.
2867 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2868 (str_checksum(get_local_machine_name())<<16));
2870 /* Max label len is 32 characters. */
2871 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2872 PTR_DIFF(end_data
, pdata
+18),
2874 SIVAL(pdata
,12,len
);
2877 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2878 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2881 case SMB_QUERY_FS_SIZE_INFO
:
2882 case SMB_FS_SIZE_INFORMATION
:
2884 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2886 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2887 return map_nt_error_from_unix(errno
);
2889 block_size
= lp_block_size(snum
);
2890 if (bsize
< block_size
) {
2891 uint64_t factor
= block_size
/bsize
;
2896 if (bsize
> block_size
) {
2897 uint64_t factor
= bsize
/block_size
;
2902 bytes_per_sector
= 512;
2903 sectors_per_unit
= bsize
/bytes_per_sector
;
2904 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2905 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2906 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2907 SBIG_UINT(pdata
,0,dsize
);
2908 SBIG_UINT(pdata
,8,dfree
);
2909 SIVAL(pdata
,16,sectors_per_unit
);
2910 SIVAL(pdata
,20,bytes_per_sector
);
2914 case SMB_FS_FULL_SIZE_INFORMATION
:
2916 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2918 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2919 return map_nt_error_from_unix(errno
);
2921 block_size
= lp_block_size(snum
);
2922 if (bsize
< block_size
) {
2923 uint64_t factor
= block_size
/bsize
;
2928 if (bsize
> block_size
) {
2929 uint64_t factor
= bsize
/block_size
;
2934 bytes_per_sector
= 512;
2935 sectors_per_unit
= bsize
/bytes_per_sector
;
2936 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2937 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2938 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2939 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2940 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2941 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2942 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2943 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2947 case SMB_QUERY_FS_DEVICE_INFO
:
2948 case SMB_FS_DEVICE_INFORMATION
:
2950 SIVAL(pdata
,0,0); /* dev type */
2951 SIVAL(pdata
,4,0); /* characteristics */
2954 #ifdef HAVE_SYS_QUOTAS
2955 case SMB_FS_QUOTA_INFORMATION
:
2957 * what we have to send --metze:
2959 * Unknown1: 24 NULL bytes
2960 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2961 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2962 * Quota Flags: 2 byte :
2963 * Unknown3: 6 NULL bytes
2967 * details for Quota Flags:
2969 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2970 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2971 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2972 * 0x0001 Enable Quotas: enable quota for this fs
2976 /* we need to fake up a fsp here,
2977 * because its not send in this call
2980 SMB_NTQUOTA_STRUCT quotas
;
2983 ZERO_STRUCT(quotas
);
2989 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
2990 DEBUG(0,("set_user_quota: access_denied "
2991 "service [%s] user [%s]\n",
2992 lp_servicename(SNUM(conn
)),
2993 conn
->server_info
->unix_name
));
2994 return NT_STATUS_ACCESS_DENIED
;
2997 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2998 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2999 return map_nt_error_from_unix(errno
);
3004 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3005 lp_servicename(SNUM(conn
))));
3007 /* Unknown1 24 NULL bytes*/
3008 SBIG_UINT(pdata
,0,(uint64_t)0);
3009 SBIG_UINT(pdata
,8,(uint64_t)0);
3010 SBIG_UINT(pdata
,16,(uint64_t)0);
3012 /* Default Soft Quota 8 bytes */
3013 SBIG_UINT(pdata
,24,quotas
.softlim
);
3015 /* Default Hard Quota 8 bytes */
3016 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3018 /* Quota flag 2 bytes */
3019 SSVAL(pdata
,40,quotas
.qflags
);
3021 /* Unknown3 6 NULL bytes */
3027 #endif /* HAVE_SYS_QUOTAS */
3028 case SMB_FS_OBJECTID_INFORMATION
:
3030 unsigned char objid
[16];
3031 struct smb_extended_info extended_info
;
3032 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3033 samba_extended_info_version (&extended_info
);
3034 SIVAL(pdata
,16,extended_info
.samba_magic
);
3035 SIVAL(pdata
,20,extended_info
.samba_version
);
3036 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3037 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3038 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3044 * Query the version and capabilities of the CIFS UNIX extensions
3048 case SMB_QUERY_CIFS_UNIX_INFO
:
3050 bool large_write
= lp_min_receive_file_size() &&
3051 !srv_is_signing_active(smbd_server_conn
);
3052 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3053 int encrypt_caps
= 0;
3055 if (!lp_unix_extensions()) {
3056 return NT_STATUS_INVALID_LEVEL
;
3059 switch (conn
->encrypt_level
) {
3065 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3068 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3069 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3070 large_write
= false;
3076 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3077 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3079 /* We have POSIX ACLs, pathname, encryption,
3080 * large read/write, and locking capability. */
3082 SBIG_UINT(pdata
,4,((uint64_t)(
3083 CIFS_UNIX_POSIX_ACLS_CAP
|
3084 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3085 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3086 CIFS_UNIX_EXTATTR_CAP
|
3087 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3089 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3091 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3095 case SMB_QUERY_POSIX_FS_INFO
:
3098 vfs_statvfs_struct svfs
;
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL
;
3104 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3108 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3109 SIVAL(pdata
,4,svfs
.BlockSize
);
3110 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3111 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3112 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3113 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3114 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3115 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3116 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3118 } else if (rc
== EOPNOTSUPP
) {
3119 return NT_STATUS_INVALID_LEVEL
;
3120 #endif /* EOPNOTSUPP */
3122 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3123 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3128 case SMB_QUERY_POSIX_WHOAMI
:
3134 if (!lp_unix_extensions()) {
3135 return NT_STATUS_INVALID_LEVEL
;
3138 if (max_data_bytes
< 40) {
3139 return NT_STATUS_BUFFER_TOO_SMALL
;
3142 /* We ARE guest if global_sid_Builtin_Guests is
3143 * in our list of SIDs.
3145 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3146 conn
->server_info
->ptok
)) {
3147 flags
|= SMB_WHOAMI_GUEST
;
3150 /* We are NOT guest if global_sid_Authenticated_Users
3151 * is in our list of SIDs.
3153 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3154 conn
->server_info
->ptok
)) {
3155 flags
&= ~SMB_WHOAMI_GUEST
;
3158 /* NOTE: 8 bytes for UID/GID, irrespective of native
3159 * platform size. This matches
3160 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3162 data_len
= 4 /* flags */
3169 + 4 /* pad/reserved */
3170 + (conn
->server_info
->utok
.ngroups
* 8)
3172 + (conn
->server_info
->ptok
->num_sids
*
3176 SIVAL(pdata
, 0, flags
);
3177 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3179 (uint64_t)conn
->server_info
->utok
.uid
);
3180 SBIG_UINT(pdata
, 16,
3181 (uint64_t)conn
->server_info
->utok
.gid
);
3184 if (data_len
>= max_data_bytes
) {
3185 /* Potential overflow, skip the GIDs and SIDs. */
3187 SIVAL(pdata
, 24, 0); /* num_groups */
3188 SIVAL(pdata
, 28, 0); /* num_sids */
3189 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3190 SIVAL(pdata
, 36, 0); /* reserved */
3196 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3197 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3199 /* We walk the SID list twice, but this call is fairly
3200 * infrequent, and I don't expect that it's performance
3201 * sensitive -- jpeach
3203 for (i
= 0, sid_bytes
= 0;
3204 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3205 sid_bytes
+= ndr_size_dom_sid(
3206 &conn
->server_info
->ptok
->user_sids
[i
],
3211 /* SID list byte count */
3212 SIVAL(pdata
, 32, sid_bytes
);
3214 /* 4 bytes pad/reserved - must be zero */
3215 SIVAL(pdata
, 36, 0);
3219 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3220 SBIG_UINT(pdata
, data_len
,
3221 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3227 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3228 int sid_len
= ndr_size_dom_sid(
3229 &conn
->server_info
->ptok
->user_sids
[i
],
3233 sid_linearize(pdata
+ data_len
, sid_len
,
3234 &conn
->server_info
->ptok
->user_sids
[i
]);
3235 data_len
+= sid_len
;
3241 case SMB_MAC_QUERY_FS_INFO
:
3243 * Thursby MAC extension... ONLY on NTFS filesystems
3244 * once we do streams then we don't need this
3246 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3248 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3253 return NT_STATUS_INVALID_LEVEL
;
3256 *ret_data_len
= data_len
;
3257 return NT_STATUS_OK
;
3260 /****************************************************************************
3261 Reply to a TRANS2_QFSINFO (query filesystem info).
3262 ****************************************************************************/
3264 static void call_trans2qfsinfo(connection_struct
*conn
,
3265 struct smb_request
*req
,
3266 char **pparams
, int total_params
,
3267 char **ppdata
, int total_data
,
3268 unsigned int max_data_bytes
)
3270 char *params
= *pparams
;
3271 uint16_t info_level
;
3275 if (total_params
< 2) {
3276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3280 info_level
= SVAL(params
,0);
3282 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3283 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3284 DEBUG(0,("call_trans2qfsinfo: encryption required "
3285 "and info level 0x%x sent.\n",
3286 (unsigned int)info_level
));
3287 exit_server_cleanly("encryption required "
3293 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3295 status
= smbd_do_qfsinfo(conn
, req
,
3300 if (!NT_STATUS_IS_OK(status
)) {
3301 reply_nterror(req
, status
);
3305 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3308 DEBUG( 4, ( "%s info_level = %d\n",
3309 smb_fn_name(req
->cmd
), info_level
) );
3314 /****************************************************************************
3315 Reply to a TRANS2_SETFSINFO (set filesystem info).
3316 ****************************************************************************/
3318 static void call_trans2setfsinfo(connection_struct
*conn
,
3319 struct smb_request
*req
,
3320 char **pparams
, int total_params
,
3321 char **ppdata
, int total_data
,
3322 unsigned int max_data_bytes
)
3324 char *pdata
= *ppdata
;
3325 char *params
= *pparams
;
3328 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3331 if (total_params
< 4) {
3332 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3334 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3338 info_level
= SVAL(params
,2);
3341 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3342 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3343 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3344 "info level (0x%x) on IPC$.\n",
3345 (unsigned int)info_level
));
3346 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3351 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3352 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3353 DEBUG(0,("call_trans2setfsinfo: encryption required "
3354 "and info level 0x%x sent.\n",
3355 (unsigned int)info_level
));
3356 exit_server_cleanly("encryption required "
3362 switch(info_level
) {
3363 case SMB_SET_CIFS_UNIX_INFO
:
3365 uint16 client_unix_major
;
3366 uint16 client_unix_minor
;
3367 uint32 client_unix_cap_low
;
3368 uint32 client_unix_cap_high
;
3370 if (!lp_unix_extensions()) {
3372 NT_STATUS_INVALID_LEVEL
);
3376 /* There should be 12 bytes of capabilities set. */
3377 if (total_data
< 8) {
3380 NT_STATUS_INVALID_PARAMETER
);
3383 client_unix_major
= SVAL(pdata
,0);
3384 client_unix_minor
= SVAL(pdata
,2);
3385 client_unix_cap_low
= IVAL(pdata
,4);
3386 client_unix_cap_high
= IVAL(pdata
,8);
3387 /* Just print these values for now. */
3388 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3389 cap_low = 0x%x, cap_high = 0x%x\n",
3390 (unsigned int)client_unix_major
,
3391 (unsigned int)client_unix_minor
,
3392 (unsigned int)client_unix_cap_low
,
3393 (unsigned int)client_unix_cap_high
));
3395 /* Here is where we must switch to posix pathname processing... */
3396 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3397 lp_set_posix_pathnames();
3398 mangle_change_to_posix();
3401 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3402 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3403 /* Client that knows how to do posix locks,
3404 * but not posix open/mkdir operations. Set a
3405 * default type for read/write checks. */
3407 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3413 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3416 size_t param_len
= 0;
3417 size_t data_len
= total_data
;
3419 if (!lp_unix_extensions()) {
3422 NT_STATUS_INVALID_LEVEL
);
3426 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3429 NT_STATUS_NOT_SUPPORTED
);
3433 DEBUG( 4,("call_trans2setfsinfo: "
3434 "request transport encryption.\n"));
3436 status
= srv_request_encryption_setup(conn
,
3437 (unsigned char **)ppdata
,
3439 (unsigned char **)pparams
,
3442 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3443 !NT_STATUS_IS_OK(status
)) {
3444 reply_nterror(req
, status
);
3448 send_trans2_replies(conn
, req
,
3455 if (NT_STATUS_IS_OK(status
)) {
3456 /* Server-side transport
3457 * encryption is now *on*. */
3458 status
= srv_encryption_start(conn
);
3459 if (!NT_STATUS_IS_OK(status
)) {
3460 exit_server_cleanly(
3461 "Failure in setting "
3462 "up encrypted transport");
3468 case SMB_FS_QUOTA_INFORMATION
:
3470 files_struct
*fsp
= NULL
;
3471 SMB_NTQUOTA_STRUCT quotas
;
3473 ZERO_STRUCT(quotas
);
3476 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3477 ||!CAN_WRITE(conn
)) {
3478 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3479 lp_servicename(SNUM(conn
)),
3480 conn
->server_info
->unix_name
));
3481 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3485 /* note: normaly there're 48 bytes,
3486 * but we didn't use the last 6 bytes for now
3489 fsp
= file_fsp(req
, SVAL(params
,0));
3491 if (!check_fsp_ntquota_handle(conn
, req
,
3493 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3495 req
, NT_STATUS_INVALID_HANDLE
);
3499 if (total_data
< 42) {
3500 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3504 NT_STATUS_INVALID_PARAMETER
);
3508 /* unknown_1 24 NULL bytes in pdata*/
3510 /* the soft quotas 8 bytes (uint64_t)*/
3511 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3512 #ifdef LARGE_SMB_OFF_T
3513 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3514 #else /* LARGE_SMB_OFF_T */
3515 if ((IVAL(pdata
,28) != 0)&&
3516 ((quotas
.softlim
!= 0xFFFFFFFF)||
3517 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3518 /* more than 32 bits? */
3521 NT_STATUS_INVALID_PARAMETER
);
3524 #endif /* LARGE_SMB_OFF_T */
3526 /* the hard quotas 8 bytes (uint64_t)*/
3527 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3528 #ifdef LARGE_SMB_OFF_T
3529 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3530 #else /* LARGE_SMB_OFF_T */
3531 if ((IVAL(pdata
,36) != 0)&&
3532 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3533 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3534 /* more than 32 bits? */
3537 NT_STATUS_INVALID_PARAMETER
);
3540 #endif /* LARGE_SMB_OFF_T */
3542 /* quota_flags 2 bytes **/
3543 quotas
.qflags
= SVAL(pdata
,40);
3545 /* unknown_2 6 NULL bytes follow*/
3547 /* now set the quotas */
3548 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3549 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3550 reply_nterror(req
, map_nt_error_from_unix(errno
));
3557 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3559 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3565 * sending this reply works fine,
3566 * but I'm not sure it's the same
3567 * like windows do...
3570 reply_outbuf(req
, 10, 0);
3573 #if defined(HAVE_POSIX_ACLS)
3574 /****************************************************************************
3575 Utility function to count the number of entries in a POSIX acl.
3576 ****************************************************************************/
3578 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3580 unsigned int ace_count
= 0;
3581 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3582 SMB_ACL_ENTRY_T entry
;
3584 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3586 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3587 entry_id
= SMB_ACL_NEXT_ENTRY
;
3594 /****************************************************************************
3595 Utility function to marshall a POSIX acl into wire format.
3596 ****************************************************************************/
3598 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3600 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3601 SMB_ACL_ENTRY_T entry
;
3603 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3604 SMB_ACL_TAG_T tagtype
;
3605 SMB_ACL_PERMSET_T permset
;
3606 unsigned char perms
= 0;
3607 unsigned int own_grp
;
3610 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3611 entry_id
= SMB_ACL_NEXT_ENTRY
;
3614 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3615 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3619 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3624 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3625 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3626 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3628 SCVAL(pdata
,1,perms
);
3631 case SMB_ACL_USER_OBJ
:
3632 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3633 own_grp
= (unsigned int)pst
->st_ex_uid
;
3634 SIVAL(pdata
,2,own_grp
);
3639 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3641 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3644 own_grp
= (unsigned int)*puid
;
3645 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3646 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3647 SIVAL(pdata
,2,own_grp
);
3651 case SMB_ACL_GROUP_OBJ
:
3652 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3653 own_grp
= (unsigned int)pst
->st_ex_gid
;
3654 SIVAL(pdata
,2,own_grp
);
3659 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3661 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3664 own_grp
= (unsigned int)*pgid
;
3665 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3666 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3667 SIVAL(pdata
,2,own_grp
);
3672 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3673 SIVAL(pdata
,2,0xFFFFFFFF);
3674 SIVAL(pdata
,6,0xFFFFFFFF);
3677 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3678 SIVAL(pdata
,2,0xFFFFFFFF);
3679 SIVAL(pdata
,6,0xFFFFFFFF);
3682 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3685 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3692 /****************************************************************************
3693 Store the FILE_UNIX_BASIC info.
3694 ****************************************************************************/
3696 static char *store_file_unix_basic(connection_struct
*conn
,
3699 const SMB_STRUCT_STAT
*psbuf
)
3701 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3702 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3704 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3707 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3710 put_long_date_timespec(pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3711 put_long_date_timespec(pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3712 put_long_date_timespec(pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3715 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3719 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3723 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3726 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3730 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3734 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ex_ino
); /* inode number */
3737 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3741 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3748 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3749 * the chflags(2) (or equivalent) flags.
3751 * XXX: this really should be behind the VFS interface. To do this, we would
3752 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3753 * Each VFS module could then implement its own mapping as appropriate for the
3754 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3756 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3760 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3764 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3768 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3772 { UF_HIDDEN
, EXT_HIDDEN
},
3775 /* Do not remove. We need to guarantee that this array has at least one
3776 * entry to build on HP-UX.
3782 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3783 uint32
*smb_fflags
, uint32
*smb_fmask
)
3787 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3788 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3789 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3790 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3795 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3796 const uint32 smb_fflags
,
3797 const uint32 smb_fmask
,
3800 uint32 max_fmask
= 0;
3803 *stat_fflags
= psbuf
->st_ex_flags
;
3805 /* For each flags requested in smb_fmask, check the state of the
3806 * corresponding flag in smb_fflags and set or clear the matching
3810 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3811 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3812 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3813 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3814 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3816 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3821 /* If smb_fmask is asking to set any bits that are not supported by
3822 * our flag mappings, we should fail.
3824 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3832 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3833 * of file flags and birth (create) time.
3835 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3838 const SMB_STRUCT_STAT
*psbuf
)
3840 uint32 file_flags
= 0;
3841 uint32 flags_mask
= 0;
3843 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3845 /* Create (birth) time 64 bit */
3846 put_long_date_timespec(pdata
, psbuf
->st_ex_btime
);
3849 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3850 SIVAL(pdata
, 0, file_flags
); /* flags */
3851 SIVAL(pdata
, 4, flags_mask
); /* mask */
3857 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3858 const struct stream_struct
*streams
,
3860 unsigned int max_data_bytes
,
3861 unsigned int *data_size
)
3864 unsigned int ofs
= 0;
3866 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
3867 unsigned int next_offset
;
3869 smb_ucs2_t
*namebuf
;
3871 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3872 streams
[i
].name
, &namelen
) ||
3875 return NT_STATUS_INVALID_PARAMETER
;
3879 * name_buf is now null-terminated, we need to marshall as not
3885 SIVAL(data
, ofs
+4, namelen
);
3886 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3887 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3888 memcpy(data
+ofs
+24, namebuf
, namelen
);
3889 TALLOC_FREE(namebuf
);
3891 next_offset
= ofs
+ 24 + namelen
;
3893 if (i
== num_streams
-1) {
3894 SIVAL(data
, ofs
, 0);
3897 unsigned int align
= ndr_align_size(next_offset
, 8);
3899 memset(data
+next_offset
, 0, align
);
3900 next_offset
+= align
;
3902 SIVAL(data
, ofs
, next_offset
- ofs
);
3911 return NT_STATUS_OK
;
3914 /****************************************************************************
3915 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3916 ****************************************************************************/
3918 static void call_trans2qpipeinfo(connection_struct
*conn
,
3919 struct smb_request
*req
,
3920 unsigned int tran_call
,
3921 char **pparams
, int total_params
,
3922 char **ppdata
, int total_data
,
3923 unsigned int max_data_bytes
)
3925 char *params
= *pparams
;
3926 char *pdata
= *ppdata
;
3927 unsigned int data_size
= 0;
3928 unsigned int param_size
= 2;
3933 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3937 if (total_params
< 4) {
3938 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3942 fsp
= file_fsp(req
, SVAL(params
,0));
3943 if (!fsp_is_np(fsp
)) {
3944 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3948 info_level
= SVAL(params
,2);
3950 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3951 if (*pparams
== NULL
) {
3952 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3957 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3958 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3959 if (*ppdata
== NULL
) {
3960 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3965 switch (info_level
) {
3966 case SMB_FILE_STANDARD_INFORMATION
:
3968 SOFF_T(pdata
,0,4096LL);
3975 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3979 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
3985 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3986 TALLOC_CTX
*mem_ctx
,
3987 uint16_t info_level
,
3989 const struct smb_filename
*smb_fname
,
3990 bool delete_pending
,
3991 struct timespec write_time_ts
,
3993 struct ea_list
*ea_list
,
3994 int lock_data_count
,
3997 unsigned int max_data_bytes
,
3999 unsigned int *pdata_size
)
4001 char *pdata
= *ppdata
;
4002 char *dstart
, *dend
;
4003 unsigned int data_size
;
4004 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4005 time_t create_time
, mtime
, atime
, c_time
;
4006 SMB_STRUCT_STAT sbuf
;
4013 uint64_t file_size
= 0;
4015 uint64_t allocation_size
= 0;
4016 uint64_t file_index
= 0;
4017 uint32_t access_mask
= 0;
4019 sbuf
= smb_fname
->st
;
4021 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4022 return NT_STATUS_INVALID_LEVEL
;
4025 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4026 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4027 info_level
, max_data_bytes
));
4030 mode
= dos_mode_msdfs(conn
, smb_fname
);
4032 mode
= dos_mode(conn
, smb_fname
);
4035 mode
= FILE_ATTRIBUTE_NORMAL
;
4037 nlink
= sbuf
.st_ex_nlink
;
4039 if (nlink
&& (mode
&aDIR
)) {
4043 if ((nlink
> 0) && delete_pending
) {
4047 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4048 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4049 if (*ppdata
== NULL
) {
4050 return NT_STATUS_NO_MEMORY
;
4054 dend
= dstart
+ data_size
- 1;
4056 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4057 update_stat_ex_mtime(&sbuf
, write_time_ts
);
4060 create_time_ts
= get_create_timespec(fsp
, smb_fname
);
4061 mtime_ts
= sbuf
.st_ex_mtime
;
4062 atime_ts
= sbuf
.st_ex_atime
;
4063 ctime_ts
= get_change_timespec(fsp
, smb_fname
);
4065 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4066 dos_filetime_timespec(&create_time_ts
);
4067 dos_filetime_timespec(&mtime_ts
);
4068 dos_filetime_timespec(&atime_ts
);
4069 dos_filetime_timespec(&ctime_ts
);
4072 create_time
= convert_timespec_to_time_t(create_time_ts
);
4073 mtime
= convert_timespec_to_time_t(mtime_ts
);
4074 atime
= convert_timespec_to_time_t(atime_ts
);
4075 c_time
= convert_timespec_to_time_t(ctime_ts
);
4077 p
= strrchr_m(smb_fname
->base_name
,'/');
4079 base_name
= smb_fname
->base_name
;
4083 /* NT expects the name to be in an exact form of the *full*
4084 filename. See the trans2 torture test */
4085 if (ISDOT(base_name
)) {
4086 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4088 return NT_STATUS_NO_MEMORY
;
4091 dos_fname
= talloc_asprintf(mem_ctx
,
4093 smb_fname
->base_name
);
4095 return NT_STATUS_NO_MEMORY
;
4097 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4098 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4099 smb_fname
->stream_name
);
4101 return NT_STATUS_NO_MEMORY
;
4105 string_replace(dos_fname
, '/', '\\');
4108 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, &sbuf
);
4111 /* Do we have this path open ? */
4113 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
4114 fsp1
= file_find_di_first(fileid
);
4115 if (fsp1
&& fsp1
->initial_allocation_size
) {
4116 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, &sbuf
);
4120 if (!(mode
& aDIR
)) {
4121 file_size
= get_file_size_stat(&sbuf
);
4125 pos
= fsp
->fh
->position_information
;
4129 access_mask
= fsp
->access_mask
;
4131 /* GENERIC_EXECUTE mapping from Windows */
4132 access_mask
= 0x12019F;
4135 /* This should be an index number - looks like
4138 I think this causes us to fail the IFSKIT
4139 BasicFileInformationTest. -tpot */
4140 file_index
= ((sbuf
.st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
4141 file_index
|= ((uint64_t)((sbuf
.st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
4143 switch (info_level
) {
4144 case SMB_INFO_STANDARD
:
4145 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4147 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4148 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4149 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4150 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4151 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4152 SSVAL(pdata
,l1_attrFile
,mode
);
4155 case SMB_INFO_QUERY_EA_SIZE
:
4157 unsigned int ea_size
=
4158 estimate_ea_size(conn
, fsp
,
4159 smb_fname
->base_name
);
4160 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4162 srv_put_dos_date2(pdata
,0,create_time
);
4163 srv_put_dos_date2(pdata
,4,atime
);
4164 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4165 SIVAL(pdata
,12,(uint32
)file_size
);
4166 SIVAL(pdata
,16,(uint32
)allocation_size
);
4167 SSVAL(pdata
,20,mode
);
4168 SIVAL(pdata
,22,ea_size
);
4172 case SMB_INFO_IS_NAME_VALID
:
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4175 /* os/2 needs this ? really ?*/
4176 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4178 /* This is only reached for qpathinfo */
4182 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4184 size_t total_ea_len
= 0;
4185 struct ea_list
*ea_file_list
= NULL
;
4187 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4190 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4191 smb_fname
->base_name
,
4193 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4195 if (!ea_list
|| (total_ea_len
> data_size
)) {
4197 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4201 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4205 case SMB_INFO_QUERY_ALL_EAS
:
4207 /* We have data_size bytes to put EA's into. */
4208 size_t total_ea_len
= 0;
4210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4212 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4213 smb_fname
->base_name
,
4215 if (!ea_list
|| (total_ea_len
> data_size
)) {
4217 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4221 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4225 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4227 /* We have data_size bytes to put EA's into. */
4228 size_t total_ea_len
= 0;
4229 struct ea_list
*ea_file_list
= NULL
;
4231 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4233 /*TODO: add filtering and index handling */
4236 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4237 smb_fname
->base_name
,
4239 if (!ea_file_list
) {
4240 return NT_STATUS_NO_EAS_ON_FILE
;
4243 status
= fill_ea_chained_buffer(mem_ctx
,
4247 conn
, ea_file_list
);
4248 if (!NT_STATUS_IS_OK(status
)) {
4254 case SMB_FILE_BASIC_INFORMATION
:
4255 case SMB_QUERY_FILE_BASIC_INFO
:
4257 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4258 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4259 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4261 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4265 put_long_date_timespec(pdata
,create_time_ts
);
4266 put_long_date_timespec(pdata
+8,atime_ts
);
4267 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4268 put_long_date_timespec(pdata
+24,ctime_ts
); /* change time */
4269 SIVAL(pdata
,32,mode
);
4271 DEBUG(5,("SMB_QFBI - "));
4272 DEBUG(5,("create: %s ", ctime(&create_time
)));
4273 DEBUG(5,("access: %s ", ctime(&atime
)));
4274 DEBUG(5,("write: %s ", ctime(&mtime
)));
4275 DEBUG(5,("change: %s ", ctime(&c_time
)));
4276 DEBUG(5,("mode: %x\n", mode
));
4279 case SMB_FILE_STANDARD_INFORMATION
:
4280 case SMB_QUERY_FILE_STANDARD_INFO
:
4282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4284 SOFF_T(pdata
,0,allocation_size
);
4285 SOFF_T(pdata
,8,file_size
);
4286 SIVAL(pdata
,16,nlink
);
4287 SCVAL(pdata
,20,delete_pending
?1:0);
4288 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4289 SSVAL(pdata
,22,0); /* Padding. */
4292 case SMB_FILE_EA_INFORMATION
:
4293 case SMB_QUERY_FILE_EA_INFO
:
4295 unsigned int ea_size
=
4296 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4299 SIVAL(pdata
,0,ea_size
);
4303 /* Get the 8.3 name - used if NT SMB was negotiated. */
4304 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4305 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4308 char mangled_name
[13];
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4310 if (!name_to_8_3(base_name
,mangled_name
,
4311 True
,conn
->params
)) {
4312 return NT_STATUS_NO_MEMORY
;
4314 len
= srvstr_push(dstart
, flags2
,
4315 pdata
+4, mangled_name
,
4316 PTR_DIFF(dend
, pdata
+4),
4318 data_size
= 4 + len
;
4323 case SMB_QUERY_FILE_NAME_INFO
:
4327 this must be *exactly* right for ACLs on mapped drives to work
4329 len
= srvstr_push(dstart
, flags2
,
4331 PTR_DIFF(dend
, pdata
+4),
4333 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4334 data_size
= 4 + len
;
4339 case SMB_FILE_ALLOCATION_INFORMATION
:
4340 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4343 SOFF_T(pdata
,0,allocation_size
);
4346 case SMB_FILE_END_OF_FILE_INFORMATION
:
4347 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4350 SOFF_T(pdata
,0,file_size
);
4353 case SMB_QUERY_FILE_ALL_INFO
:
4354 case SMB_FILE_ALL_INFORMATION
:
4357 unsigned int ea_size
=
4358 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4359 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4360 put_long_date_timespec(pdata
,create_time_ts
);
4361 put_long_date_timespec(pdata
+8,atime_ts
);
4362 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4363 put_long_date_timespec(pdata
+24,ctime_ts
); /* change time */
4364 SIVAL(pdata
,32,mode
);
4365 SIVAL(pdata
,36,0); /* padding. */
4367 SOFF_T(pdata
,0,allocation_size
);
4368 SOFF_T(pdata
,8,file_size
);
4369 SIVAL(pdata
,16,nlink
);
4370 SCVAL(pdata
,20,delete_pending
);
4371 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4374 SIVAL(pdata
,0,ea_size
);
4375 pdata
+= 4; /* EA info */
4376 len
= srvstr_push(dstart
, flags2
,
4378 PTR_DIFF(dend
, pdata
+4),
4382 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4386 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4389 unsigned int ea_size
=
4390 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4391 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4392 put_long_date_timespec(pdata
+0x00,create_time_ts
);
4393 put_long_date_timespec(pdata
+0x08,atime_ts
);
4394 put_long_date_timespec(pdata
+0x10,mtime_ts
); /* write time */
4395 put_long_date_timespec(pdata
+0x18,ctime_ts
); /* change time */
4396 SIVAL(pdata
, 0x20, mode
);
4397 SIVAL(pdata
, 0x24, 0); /* padding. */
4398 SBVAL(pdata
, 0x28, allocation_size
);
4399 SBVAL(pdata
, 0x30, file_size
);
4400 SIVAL(pdata
, 0x38, nlink
);
4401 SCVAL(pdata
, 0x3C, delete_pending
);
4402 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4403 SSVAL(pdata
, 0x3E, 0); /* padding */
4404 SBVAL(pdata
, 0x40, file_index
);
4405 SIVAL(pdata
, 0x48, ea_size
);
4406 SIVAL(pdata
, 0x4C, access_mask
);
4407 SBVAL(pdata
, 0x50, pos
);
4408 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4409 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4413 len
= srvstr_push(dstart
, flags2
,
4415 PTR_DIFF(dend
, pdata
+4),
4419 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4422 case SMB_FILE_INTERNAL_INFORMATION
:
4424 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4425 SBVAL(pdata
, 0, file_index
);
4429 case SMB_FILE_ACCESS_INFORMATION
:
4430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4431 SIVAL(pdata
, 0, access_mask
);
4435 case SMB_FILE_NAME_INFORMATION
:
4436 /* Pathname with leading '\'. */
4439 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4440 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4441 SIVAL(pdata
,0,byte_len
);
4442 data_size
= 4 + byte_len
;
4446 case SMB_FILE_DISPOSITION_INFORMATION
:
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4449 SCVAL(pdata
,0,delete_pending
);
4452 case SMB_FILE_POSITION_INFORMATION
:
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4455 SOFF_T(pdata
,0,pos
);
4458 case SMB_FILE_MODE_INFORMATION
:
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4460 SIVAL(pdata
,0,mode
);
4464 case SMB_FILE_ALIGNMENT_INFORMATION
:
4465 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4466 SIVAL(pdata
,0,0); /* No alignment needed. */
4471 * NT4 server just returns "invalid query" to this - if we try
4472 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4475 /* The first statement above is false - verified using Thursby
4476 * client against NT4 -- gcolley.
4478 case SMB_QUERY_FILE_STREAM_INFO
:
4479 case SMB_FILE_STREAM_INFORMATION
: {
4480 unsigned int num_streams
;
4481 struct stream_struct
*streams
;
4483 DEBUG(10,("smbd_do_qfilepathinfo: "
4484 "SMB_FILE_STREAM_INFORMATION\n"));
4486 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4487 return NT_STATUS_INVALID_PARAMETER
;
4490 status
= SMB_VFS_STREAMINFO(
4491 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4492 &num_streams
, &streams
);
4494 if (!NT_STATUS_IS_OK(status
)) {
4495 DEBUG(10, ("could not get stream info: %s\n",
4496 nt_errstr(status
)));
4500 status
= marshall_stream_info(num_streams
, streams
,
4501 pdata
, max_data_bytes
,
4504 if (!NT_STATUS_IS_OK(status
)) {
4505 DEBUG(10, ("marshall_stream_info failed: %s\n",
4506 nt_errstr(status
)));
4510 TALLOC_FREE(streams
);
4514 case SMB_QUERY_COMPRESSION_INFO
:
4515 case SMB_FILE_COMPRESSION_INFORMATION
:
4516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4517 SOFF_T(pdata
,0,file_size
);
4518 SIVAL(pdata
,8,0); /* ??? */
4519 SIVAL(pdata
,12,0); /* ??? */
4523 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4525 put_long_date_timespec(pdata
,create_time_ts
);
4526 put_long_date_timespec(pdata
+8,atime_ts
);
4527 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4528 put_long_date_timespec(pdata
+24,ctime_ts
); /* change time */
4529 SOFF_T(pdata
,32,allocation_size
);
4530 SOFF_T(pdata
,40,file_size
);
4531 SIVAL(pdata
,48,mode
);
4532 SIVAL(pdata
,52,0); /* ??? */
4536 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4538 SIVAL(pdata
,0,mode
);
4544 * CIFS UNIX Extensions.
4547 case SMB_QUERY_FILE_UNIX_BASIC
:
4549 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4550 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4554 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4556 for (i
=0; i
<100; i
++)
4557 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4563 case SMB_QUERY_FILE_UNIX_INFO2
:
4565 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4566 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4570 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4572 for (i
=0; i
<100; i
++)
4573 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4579 case SMB_QUERY_FILE_UNIX_LINK
:
4582 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4585 return NT_STATUS_NO_MEMORY
;
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4590 if(!S_ISLNK(sbuf
.st_ex_mode
)) {
4591 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4594 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4596 len
= SMB_VFS_READLINK(conn
,
4597 smb_fname
->base_name
,
4600 return map_nt_error_from_unix(errno
);
4603 len
= srvstr_push(dstart
, flags2
,
4605 PTR_DIFF(dend
, pdata
),
4608 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4613 #if defined(HAVE_POSIX_ACLS)
4614 case SMB_QUERY_POSIX_ACL
:
4616 SMB_ACL_T file_acl
= NULL
;
4617 SMB_ACL_T def_acl
= NULL
;
4618 uint16 num_file_acls
= 0;
4619 uint16 num_def_acls
= 0;
4621 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4622 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4625 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4626 smb_fname
->base_name
,
4627 SMB_ACL_TYPE_ACCESS
);
4630 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4631 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4632 "not implemented on "
4633 "filesystem containing %s\n",
4634 smb_fname
->base_name
));
4635 return NT_STATUS_NOT_IMPLEMENTED
;
4638 if (S_ISDIR(sbuf
.st_ex_mode
)) {
4639 if (fsp
&& fsp
->is_directory
) {
4641 SMB_VFS_SYS_ACL_GET_FILE(
4643 fsp
->fsp_name
->base_name
,
4644 SMB_ACL_TYPE_DEFAULT
);
4647 SMB_VFS_SYS_ACL_GET_FILE(
4649 smb_fname
->base_name
,
4650 SMB_ACL_TYPE_DEFAULT
);
4652 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4655 num_file_acls
= count_acl_entries(conn
, file_acl
);
4656 num_def_acls
= count_acl_entries(conn
, def_acl
);
4658 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4659 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4661 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4662 SMB_POSIX_ACL_HEADER_SIZE
) ));
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4667 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4669 return NT_STATUS_BUFFER_TOO_SMALL
;
4672 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4673 SSVAL(pdata
,2,num_file_acls
);
4674 SSVAL(pdata
,4,num_def_acls
);
4675 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4682 return NT_STATUS_INTERNAL_ERROR
;
4684 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4691 return NT_STATUS_INTERNAL_ERROR
;
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4700 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4706 case SMB_QUERY_POSIX_LOCK
:
4711 enum brl_type lock_type
;
4713 /* We need an open file with a real fd for this. */
4714 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4715 return NT_STATUS_INVALID_LEVEL
;
4718 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4719 return NT_STATUS_INVALID_PARAMETER
;
4722 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4723 case POSIX_LOCK_TYPE_READ
:
4724 lock_type
= READ_LOCK
;
4726 case POSIX_LOCK_TYPE_WRITE
:
4727 lock_type
= WRITE_LOCK
;
4729 case POSIX_LOCK_TYPE_UNLOCK
:
4731 /* There's no point in asking for an unlock... */
4732 return NT_STATUS_INVALID_PARAMETER
;
4735 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4736 #if defined(HAVE_LONGLONG)
4737 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4738 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4739 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4740 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4741 #else /* HAVE_LONGLONG */
4742 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4743 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4744 #endif /* HAVE_LONGLONG */
4746 status
= query_lock(fsp
,
4753 if (ERROR_WAS_LOCK_DENIED(status
)) {
4754 /* Here we need to report who has it locked... */
4755 data_size
= POSIX_LOCK_DATA_SIZE
;
4757 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4758 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4759 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4760 #if defined(HAVE_LONGLONG)
4761 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4762 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4763 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4764 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4765 #else /* HAVE_LONGLONG */
4766 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4767 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4768 #endif /* HAVE_LONGLONG */
4770 } else if (NT_STATUS_IS_OK(status
)) {
4771 /* For success we just return a copy of what we sent
4772 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4773 data_size
= POSIX_LOCK_DATA_SIZE
;
4774 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4775 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4783 return NT_STATUS_INVALID_LEVEL
;
4786 *pdata_size
= data_size
;
4787 return NT_STATUS_OK
;
4790 /****************************************************************************
4791 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4792 file name or file id).
4793 ****************************************************************************/
4795 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4796 struct smb_request
*req
,
4797 unsigned int tran_call
,
4798 char **pparams
, int total_params
,
4799 char **ppdata
, int total_data
,
4800 unsigned int max_data_bytes
)
4802 char *params
= *pparams
;
4803 char *pdata
= *ppdata
;
4805 unsigned int data_size
= 0;
4806 unsigned int param_size
= 2;
4807 struct smb_filename
*smb_fname
= NULL
;
4808 bool delete_pending
= False
;
4809 struct timespec write_time_ts
;
4810 files_struct
*fsp
= NULL
;
4811 struct file_id fileid
;
4812 struct ea_list
*ea_list
= NULL
;
4813 int lock_data_count
= 0;
4814 char *lock_data
= NULL
;
4815 bool ms_dfs_link
= false;
4816 NTSTATUS status
= NT_STATUS_OK
;
4819 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4823 ZERO_STRUCT(write_time_ts
);
4825 if (tran_call
== TRANSACT2_QFILEINFO
) {
4826 if (total_params
< 4) {
4827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4832 call_trans2qpipeinfo(conn
, req
, tran_call
,
4833 pparams
, total_params
,
4839 fsp
= file_fsp(req
, SVAL(params
,0));
4840 info_level
= SVAL(params
,2);
4842 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
4844 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4845 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4849 /* Initial check for valid fsp ptr. */
4850 if (!check_fsp_open(conn
, req
, fsp
)) {
4854 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
4856 if (!NT_STATUS_IS_OK(status
)) {
4857 reply_nterror(req
, status
);
4861 if(fsp
->fake_file_handle
) {
4863 * This is actually for the QUOTA_FAKE_FILE --metze
4866 /* We know this name is ok, it's already passed the checks. */
4868 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4870 * This is actually a QFILEINFO on a directory
4871 * handle (returned from an NT SMB). NT5.0 seems
4872 * to do this call. JRA.
4875 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4876 /* Always do lstat for UNIX calls. */
4877 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
4878 DEBUG(3,("call_trans2qfilepathinfo: "
4879 "SMB_VFS_LSTAT of %s failed "
4881 smb_fname_str_dbg(smb_fname
),
4884 map_nt_error_from_unix(errno
));
4887 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
4888 DEBUG(3,("call_trans2qfilepathinfo: "
4889 "SMB_VFS_STAT of %s failed (%s)\n",
4890 smb_fname_str_dbg(smb_fname
),
4893 map_nt_error_from_unix(errno
));
4897 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
4898 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4901 * Original code - this is an open file.
4903 if (!check_fsp(conn
, req
, fsp
)) {
4907 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
4908 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4909 fsp
->fnum
, strerror(errno
)));
4911 map_nt_error_from_unix(errno
));
4914 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
4915 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
4922 if (total_params
< 7) {
4923 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4927 info_level
= SVAL(params
,0);
4929 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
4931 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4932 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4936 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
4938 STR_TERMINATE
, &status
);
4939 if (!NT_STATUS_IS_OK(status
)) {
4940 reply_nterror(req
, status
);
4944 status
= filename_convert(req
,
4946 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4951 if (!NT_STATUS_IS_OK(status
)) {
4952 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4953 reply_botherror(req
,
4954 NT_STATUS_PATH_NOT_COVERED
,
4955 ERRSRV
, ERRbadpath
);
4958 reply_nterror(req
, status
);
4962 /* If this is a stream, check if there is a delete_pending. */
4963 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
4964 && is_ntfs_stream_smb_fname(smb_fname
)) {
4965 struct smb_filename
*smb_fname_base
= NULL
;
4967 /* Create an smb_filename with stream_name == NULL. */
4969 create_synthetic_smb_fname(talloc_tos(),
4970 smb_fname
->base_name
,
4973 if (!NT_STATUS_IS_OK(status
)) {
4974 reply_nterror(req
, status
);
4978 if (INFO_LEVEL_IS_UNIX(info_level
)) {
4979 /* Always do lstat for UNIX calls. */
4980 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
4981 DEBUG(3,("call_trans2qfilepathinfo: "
4982 "SMB_VFS_LSTAT of %s failed "
4984 smb_fname_str_dbg(smb_fname_base
),
4986 TALLOC_FREE(smb_fname_base
);
4988 map_nt_error_from_unix(errno
));
4992 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
4993 DEBUG(3,("call_trans2qfilepathinfo: "
4994 "fileinfo of %s failed "
4996 smb_fname_str_dbg(smb_fname_base
),
4998 TALLOC_FREE(smb_fname_base
);
5000 map_nt_error_from_unix(errno
));
5005 fileid
= vfs_file_id_from_sbuf(conn
,
5006 &smb_fname_base
->st
);
5007 TALLOC_FREE(smb_fname_base
);
5008 get_file_infos(fileid
, &delete_pending
, NULL
);
5009 if (delete_pending
) {
5010 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5015 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5016 /* Always do lstat for UNIX calls. */
5017 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5018 DEBUG(3,("call_trans2qfilepathinfo: "
5019 "SMB_VFS_LSTAT of %s failed (%s)\n",
5020 smb_fname_str_dbg(smb_fname
),
5023 map_nt_error_from_unix(errno
));
5027 } else if (!VALID_STAT(smb_fname
->st
) &&
5028 SMB_VFS_STAT(conn
, smb_fname
) &&
5029 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5030 ms_dfs_link
= check_msdfs_link(conn
,
5031 smb_fname
->base_name
,
5035 DEBUG(3,("call_trans2qfilepathinfo: "
5036 "SMB_VFS_STAT of %s failed (%s)\n",
5037 smb_fname_str_dbg(smb_fname
),
5040 map_nt_error_from_unix(errno
));
5045 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5046 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5047 if (delete_pending
) {
5048 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5053 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5054 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5055 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5057 /* Pull out any data sent here before we realloc. */
5058 switch (info_level
) {
5059 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5061 /* Pull any EA list from the data portion. */
5064 if (total_data
< 4) {
5066 req
, NT_STATUS_INVALID_PARAMETER
);
5069 ea_size
= IVAL(pdata
,0);
5071 if (total_data
> 0 && ea_size
!= total_data
) {
5072 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5073 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5075 req
, NT_STATUS_INVALID_PARAMETER
);
5079 if (!lp_ea_support(SNUM(conn
))) {
5080 reply_doserror(req
, ERRDOS
,
5081 ERReasnotsupported
);
5085 /* Pull out the list of names. */
5086 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5089 req
, NT_STATUS_INVALID_PARAMETER
);
5095 case SMB_QUERY_POSIX_LOCK
:
5097 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5098 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5102 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5104 req
, NT_STATUS_INVALID_PARAMETER
);
5108 /* Copy the lock range data. */
5109 lock_data
= (char *)TALLOC_MEMDUP(
5110 req
, pdata
, total_data
);
5112 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5115 lock_data_count
= total_data
;
5121 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5122 if (*pparams
== NULL
) {
5123 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5130 * draft-leach-cifs-v1-spec-02.txt
5131 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5134 * The requested information is placed in the Data portion of the
5135 * transaction response. For the information levels greater than 0x100,
5136 * the transaction response has 1 parameter word which should be
5137 * ignored by the client.
5139 * However Windows only follows this rule for the IS_NAME_VALID call.
5141 switch (info_level
) {
5142 case SMB_INFO_IS_NAME_VALID
:
5147 if ((info_level
& 0xFF00) == 0xFF00) {
5149 * We use levels that start with 0xFF00
5150 * internally to represent SMB2 specific levels
5152 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5156 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5158 delete_pending
, write_time_ts
,
5159 ms_dfs_link
, ea_list
,
5160 lock_data_count
, lock_data
,
5161 req
->flags2
, max_data_bytes
,
5162 ppdata
, &data_size
);
5163 if (!NT_STATUS_IS_OK(status
)) {
5164 reply_nterror(req
, status
);
5168 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5174 /****************************************************************************
5175 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5177 ****************************************************************************/
5179 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5180 connection_struct
*conn
,
5181 const struct smb_filename
*smb_fname_old
,
5182 const struct smb_filename
*smb_fname_new
)
5184 NTSTATUS status
= NT_STATUS_OK
;
5186 /* source must already exist. */
5187 if (!VALID_STAT(smb_fname_old
->st
)) {
5188 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5191 /* Disallow if newname already exists. */
5192 if (VALID_STAT(smb_fname_new
->st
)) {
5193 return NT_STATUS_OBJECT_NAME_COLLISION
;
5196 /* No links from a directory. */
5197 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5198 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5201 /* Setting a hardlink to/from a stream isn't currently supported. */
5202 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5203 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5204 return NT_STATUS_INVALID_PARAMETER
;
5207 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5208 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5210 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5211 smb_fname_new
->base_name
) != 0) {
5212 status
= map_nt_error_from_unix(errno
);
5213 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5214 nt_errstr(status
), smb_fname_old
->base_name
,
5215 smb_fname_new
->base_name
));
5220 /****************************************************************************
5221 Deal with setting the time from any of the setfilepathinfo functions.
5222 ****************************************************************************/
5224 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5226 const struct smb_filename
*smb_fname
,
5227 struct smb_file_time
*ft
,
5228 bool setting_write_time
)
5230 struct smb_filename
*smb_fname_base
= NULL
;
5232 FILE_NOTIFY_CHANGE_LAST_ACCESS
5233 |FILE_NOTIFY_CHANGE_LAST_WRITE
5234 |FILE_NOTIFY_CHANGE_CREATION
;
5237 if (!VALID_STAT(smb_fname
->st
)) {
5238 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5241 /* get some defaults (no modifications) if any info is zero or -1. */
5242 if (null_timespec(ft
->create_time
)) {
5243 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5246 if (null_timespec(ft
->atime
)) {
5247 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5250 if (null_timespec(ft
->mtime
)) {
5251 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5254 if (!setting_write_time
) {
5255 /* ft->mtime comes from change time, not write time. */
5256 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5259 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5260 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5261 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5262 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5263 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5264 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5265 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5266 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5268 if (setting_write_time
) {
5270 * This was a Windows setfileinfo on an open file.
5271 * NT does this a lot. We also need to
5272 * set the time here, as it can be read by
5273 * FindFirst/FindNext and with the patch for bug #2045
5274 * in smbd/fileio.c it ensures that this timestamp is
5275 * kept sticky even after a write. We save the request
5276 * away and will set it on file close and after a write. JRA.
5279 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5280 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5283 if (fsp
->base_fsp
) {
5284 set_sticky_write_time_fsp(fsp
->base_fsp
,
5287 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5290 set_sticky_write_time_path(
5291 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5296 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5298 /* Always call ntimes on the base, even if a stream was passed in. */
5299 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5300 NULL
, &smb_fname
->st
,
5302 if (!NT_STATUS_IS_OK(status
)) {
5306 if(file_ntimes(conn
, smb_fname_base
, ft
)!=0) {
5307 TALLOC_FREE(smb_fname_base
);
5308 return map_nt_error_from_unix(errno
);
5310 TALLOC_FREE(smb_fname_base
);
5312 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5313 smb_fname
->base_name
);
5314 return NT_STATUS_OK
;
5317 /****************************************************************************
5318 Deal with setting the dosmode from any of the setfilepathinfo functions.
5319 ****************************************************************************/
5321 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5322 const struct smb_filename
*smb_fname
,
5325 struct smb_filename
*smb_fname_base
= NULL
;
5328 if (!VALID_STAT(smb_fname
->st
)) {
5329 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5332 /* Always operate on the base_name, even if a stream was passed in. */
5333 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5334 NULL
, &smb_fname
->st
,
5336 if (!NT_STATUS_IS_OK(status
)) {
5341 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5348 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5350 /* check the mode isn't different, before changing it */
5351 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5352 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5353 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5354 (unsigned int)dosmode
));
5356 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5358 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5360 smb_fname_str_dbg(smb_fname_base
),
5362 status
= map_nt_error_from_unix(errno
);
5366 status
= NT_STATUS_OK
;
5368 TALLOC_FREE(smb_fname_base
);
5372 /****************************************************************************
5373 Deal with setting the size from any of the setfilepathinfo functions.
5374 ****************************************************************************/
5376 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5377 struct smb_request
*req
,
5379 const struct smb_filename
*smb_fname
,
5380 const SMB_STRUCT_STAT
*psbuf
,
5383 NTSTATUS status
= NT_STATUS_OK
;
5384 struct smb_filename
*smb_fname_tmp
= NULL
;
5385 files_struct
*new_fsp
= NULL
;
5387 if (!VALID_STAT(*psbuf
)) {
5388 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5391 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5393 if (size
== get_file_size_stat(psbuf
)) {
5394 return NT_STATUS_OK
;
5397 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5398 smb_fname_str_dbg(smb_fname
), (double)size
));
5400 if (fsp
&& fsp
->fh
->fd
!= -1) {
5401 /* Handle based call. */
5402 if (vfs_set_filelen(fsp
, size
) == -1) {
5403 return map_nt_error_from_unix(errno
);
5405 trigger_write_time_update_immediate(fsp
);
5406 return NT_STATUS_OK
;
5409 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5410 if (!NT_STATUS_IS_OK(status
)) {
5414 smb_fname_tmp
->st
= *psbuf
;
5416 status
= SMB_VFS_CREATE_FILE(
5419 0, /* root_dir_fid */
5420 smb_fname_tmp
, /* fname */
5421 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5422 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5424 FILE_OPEN
, /* create_disposition*/
5425 0, /* create_options */
5426 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5427 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5428 0, /* allocation_size */
5431 &new_fsp
, /* result */
5434 TALLOC_FREE(smb_fname_tmp
);
5436 if (!NT_STATUS_IS_OK(status
)) {
5437 /* NB. We check for open_was_deferred in the caller. */
5441 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5442 status
= map_nt_error_from_unix(errno
);
5443 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5447 trigger_write_time_update_immediate(new_fsp
);
5448 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5449 return NT_STATUS_OK
;
5452 /****************************************************************************
5453 Deal with SMB_INFO_SET_EA.
5454 ****************************************************************************/
5456 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5460 const struct smb_filename
*smb_fname
)
5462 struct ea_list
*ea_list
= NULL
;
5463 TALLOC_CTX
*ctx
= NULL
;
5464 NTSTATUS status
= NT_STATUS_OK
;
5466 if (total_data
< 10) {
5468 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5469 length. They seem to have no effect. Bug #3212. JRA */
5471 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5472 /* We're done. We only get EA info in this call. */
5473 return NT_STATUS_OK
;
5476 return NT_STATUS_INVALID_PARAMETER
;
5479 if (IVAL(pdata
,0) > total_data
) {
5480 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5481 IVAL(pdata
,0), (unsigned int)total_data
));
5482 return NT_STATUS_INVALID_PARAMETER
;
5486 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5488 return NT_STATUS_INVALID_PARAMETER
;
5490 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5495 /****************************************************************************
5496 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5497 ****************************************************************************/
5499 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5503 const struct smb_filename
*smb_fname
)
5505 NTSTATUS status
= NT_STATUS_OK
;
5506 bool delete_on_close
;
5509 if (total_data
< 1) {
5510 return NT_STATUS_INVALID_PARAMETER
;
5514 return NT_STATUS_INVALID_HANDLE
;
5517 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5518 dosmode
= dos_mode(conn
, smb_fname
);
5520 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5521 "delete_on_close = %u\n",
5522 smb_fname_str_dbg(smb_fname
),
5523 (unsigned int)dosmode
,
5524 (unsigned int)delete_on_close
));
5526 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5528 if (!NT_STATUS_IS_OK(status
)) {
5532 /* The set is across all open files on this dev/inode pair. */
5533 if (!set_delete_on_close(fsp
, delete_on_close
,
5534 &conn
->server_info
->utok
)) {
5535 return NT_STATUS_ACCESS_DENIED
;
5537 return NT_STATUS_OK
;
5540 /****************************************************************************
5541 Deal with SMB_FILE_POSITION_INFORMATION.
5542 ****************************************************************************/
5544 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5549 uint64_t position_information
;
5551 if (total_data
< 8) {
5552 return NT_STATUS_INVALID_PARAMETER
;
5556 /* Ignore on pathname based set. */
5557 return NT_STATUS_OK
;
5560 position_information
= (uint64_t)IVAL(pdata
,0);
5561 #ifdef LARGE_SMB_OFF_T
5562 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5563 #else /* LARGE_SMB_OFF_T */
5564 if (IVAL(pdata
,4) != 0) {
5565 /* more than 32 bits? */
5566 return NT_STATUS_INVALID_PARAMETER
;
5568 #endif /* LARGE_SMB_OFF_T */
5570 DEBUG(10,("smb_file_position_information: Set file position "
5571 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5572 (double)position_information
));
5573 fsp
->fh
->position_information
= position_information
;
5574 return NT_STATUS_OK
;
5577 /****************************************************************************
5578 Deal with SMB_FILE_MODE_INFORMATION.
5579 ****************************************************************************/
5581 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5587 if (total_data
< 4) {
5588 return NT_STATUS_INVALID_PARAMETER
;
5590 mode
= IVAL(pdata
,0);
5591 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5592 return NT_STATUS_INVALID_PARAMETER
;
5594 return NT_STATUS_OK
;
5597 /****************************************************************************
5598 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5599 ****************************************************************************/
5601 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5602 struct smb_request
*req
,
5605 const struct smb_filename
*smb_fname
)
5607 char *link_target
= NULL
;
5608 const char *newname
= smb_fname
->base_name
;
5609 NTSTATUS status
= NT_STATUS_OK
;
5610 TALLOC_CTX
*ctx
= talloc_tos();
5612 /* Set a symbolic link. */
5613 /* Don't allow this if follow links is false. */
5615 if (total_data
== 0) {
5616 return NT_STATUS_INVALID_PARAMETER
;
5619 if (!lp_symlinks(SNUM(conn
))) {
5620 return NT_STATUS_ACCESS_DENIED
;
5623 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5624 total_data
, STR_TERMINATE
);
5627 return NT_STATUS_INVALID_PARAMETER
;
5630 /* !widelinks forces the target path to be within the share. */
5631 /* This means we can interpret the target as a pathname. */
5632 if (!lp_widelinks(SNUM(conn
))) {
5633 char *rel_name
= NULL
;
5634 char *last_dirp
= NULL
;
5636 if (*link_target
== '/') {
5637 /* No absolute paths allowed. */
5638 return NT_STATUS_ACCESS_DENIED
;
5640 rel_name
= talloc_strdup(ctx
,newname
);
5642 return NT_STATUS_NO_MEMORY
;
5644 last_dirp
= strrchr_m(rel_name
, '/');
5646 last_dirp
[1] = '\0';
5648 rel_name
= talloc_strdup(ctx
,"./");
5650 return NT_STATUS_NO_MEMORY
;
5653 rel_name
= talloc_asprintf_append(rel_name
,
5657 return NT_STATUS_NO_MEMORY
;
5660 status
= check_name(conn
, rel_name
);
5661 if (!NT_STATUS_IS_OK(status
)) {
5666 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5667 newname
, link_target
));
5669 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5670 return map_nt_error_from_unix(errno
);
5673 return NT_STATUS_OK
;
5676 /****************************************************************************
5677 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5678 ****************************************************************************/
5680 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5681 struct smb_request
*req
,
5682 const char *pdata
, int total_data
,
5683 const struct smb_filename
*smb_fname_new
)
5685 char *oldname
= NULL
;
5686 struct smb_filename
*smb_fname_old
= NULL
;
5687 TALLOC_CTX
*ctx
= talloc_tos();
5688 NTSTATUS status
= NT_STATUS_OK
;
5690 /* Set a hard link. */
5691 if (total_data
== 0) {
5692 return NT_STATUS_INVALID_PARAMETER
;
5695 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5696 total_data
, STR_TERMINATE
, &status
);
5697 if (!NT_STATUS_IS_OK(status
)) {
5701 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5702 smb_fname_str_dbg(smb_fname_new
), oldname
));
5704 status
= filename_convert(ctx
,
5706 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5711 if (!NT_STATUS_IS_OK(status
)) {
5715 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5718 /****************************************************************************
5719 Deal with SMB_FILE_RENAME_INFORMATION.
5720 ****************************************************************************/
5722 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5723 struct smb_request
*req
,
5727 struct smb_filename
*smb_fname_src
)
5732 char *newname
= NULL
;
5733 struct smb_filename
*smb_fname_dst
= NULL
;
5734 bool dest_has_wcard
= False
;
5735 NTSTATUS status
= NT_STATUS_OK
;
5737 TALLOC_CTX
*ctx
= talloc_tos();
5739 if (total_data
< 13) {
5740 return NT_STATUS_INVALID_PARAMETER
;
5743 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5744 root_fid
= IVAL(pdata
,4);
5745 len
= IVAL(pdata
,8);
5747 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5748 return NT_STATUS_INVALID_PARAMETER
;
5751 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5754 if (!NT_STATUS_IS_OK(status
)) {
5758 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5761 status
= resolve_dfspath_wcard(ctx
, conn
,
5762 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5766 if (!NT_STATUS_IS_OK(status
)) {
5770 /* Check the new name has no '/' characters. */
5771 if (strchr_m(newname
, '/')) {
5772 return NT_STATUS_NOT_SUPPORTED
;
5775 if (fsp
&& fsp
->base_fsp
) {
5776 /* newname must be a stream name. */
5777 if (newname
[0] != ':') {
5778 return NT_STATUS_NOT_SUPPORTED
;
5781 /* Create an smb_fname to call rename_internals_fsp() with. */
5782 status
= create_synthetic_smb_fname(talloc_tos(),
5783 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
5785 if (!NT_STATUS_IS_OK(status
)) {
5790 * Set the original last component, since
5791 * rename_internals_fsp() requires it.
5793 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
5795 if (smb_fname_dst
->original_lcomp
== NULL
) {
5796 status
= NT_STATUS_NO_MEMORY
;
5802 * Build up an smb_fname_dst based on the filename passed in.
5803 * We basically just strip off the last component, and put on
5804 * the newname instead.
5806 char *base_name
= NULL
;
5808 /* newname must *not* be a stream name. */
5809 if (newname
[0] == ':') {
5810 return NT_STATUS_NOT_SUPPORTED
;
5814 * Strip off the last component (filename) of the path passed
5817 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
5819 return NT_STATUS_NO_MEMORY
;
5821 p
= strrchr_m(base_name
, '/');
5825 base_name
= talloc_strdup(ctx
, "./");
5827 return NT_STATUS_NO_MEMORY
;
5830 /* Append the new name. */
5831 base_name
= talloc_asprintf_append(base_name
,
5835 return NT_STATUS_NO_MEMORY
;
5838 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
5841 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
5844 /* If an error we expect this to be
5845 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5847 if (!NT_STATUS_IS_OK(status
)) {
5848 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5852 /* Create an smb_fname to call rename_internals_fsp() */
5853 status
= create_synthetic_smb_fname(ctx
,
5857 if (!NT_STATUS_IS_OK(status
)) {
5864 DEBUG(10,("smb_file_rename_information: "
5865 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5866 fsp
->fnum
, fsp_str_dbg(fsp
),
5867 smb_fname_str_dbg(smb_fname_dst
)));
5868 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
5871 DEBUG(10,("smb_file_rename_information: "
5872 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5873 smb_fname_str_dbg(smb_fname_src
),
5874 smb_fname_str_dbg(smb_fname_dst
)));
5875 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
5876 smb_fname_dst
, 0, overwrite
, false,
5878 FILE_WRITE_ATTRIBUTES
);
5881 TALLOC_FREE(smb_fname_dst
);
5885 /****************************************************************************
5886 Deal with SMB_SET_POSIX_ACL.
5887 ****************************************************************************/
5889 #if defined(HAVE_POSIX_ACLS)
5890 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5894 const struct smb_filename
*smb_fname
)
5896 uint16 posix_acl_version
;
5897 uint16 num_file_acls
;
5898 uint16 num_def_acls
;
5899 bool valid_file_acls
= True
;
5900 bool valid_def_acls
= True
;
5902 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5903 return NT_STATUS_INVALID_PARAMETER
;
5905 posix_acl_version
= SVAL(pdata
,0);
5906 num_file_acls
= SVAL(pdata
,2);
5907 num_def_acls
= SVAL(pdata
,4);
5909 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5910 valid_file_acls
= False
;
5914 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5915 valid_def_acls
= False
;
5919 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5920 return NT_STATUS_INVALID_PARAMETER
;
5923 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5924 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5925 return NT_STATUS_INVALID_PARAMETER
;
5928 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5929 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
5930 (unsigned int)num_file_acls
,
5931 (unsigned int)num_def_acls
));
5933 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
5934 smb_fname
->base_name
, num_file_acls
,
5935 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5936 return map_nt_error_from_unix(errno
);
5939 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
5940 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
5941 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5942 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5943 return map_nt_error_from_unix(errno
);
5945 return NT_STATUS_OK
;
5949 /****************************************************************************
5950 Deal with SMB_SET_POSIX_LOCK.
5951 ****************************************************************************/
5953 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5954 struct smb_request
*req
,
5962 bool blocking_lock
= False
;
5963 enum brl_type lock_type
;
5965 NTSTATUS status
= NT_STATUS_OK
;
5967 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5968 return NT_STATUS_INVALID_HANDLE
;
5971 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5972 return NT_STATUS_INVALID_PARAMETER
;
5975 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5976 case POSIX_LOCK_TYPE_READ
:
5977 lock_type
= READ_LOCK
;
5979 case POSIX_LOCK_TYPE_WRITE
:
5980 /* Return the right POSIX-mappable error code for files opened read-only. */
5981 if (!fsp
->can_write
) {
5982 return NT_STATUS_INVALID_HANDLE
;
5984 lock_type
= WRITE_LOCK
;
5986 case POSIX_LOCK_TYPE_UNLOCK
:
5987 lock_type
= UNLOCK_LOCK
;
5990 return NT_STATUS_INVALID_PARAMETER
;
5993 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5994 blocking_lock
= False
;
5995 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5996 blocking_lock
= True
;
5998 return NT_STATUS_INVALID_PARAMETER
;
6001 if (!lp_blocking_locks(SNUM(conn
))) {
6002 blocking_lock
= False
;
6005 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6006 #if defined(HAVE_LONGLONG)
6007 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6008 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6009 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6010 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6011 #else /* HAVE_LONGLONG */
6012 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6013 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6014 #endif /* HAVE_LONGLONG */
6016 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6017 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6019 (unsigned int)lock_type
,
6020 (unsigned int)lock_pid
,
6024 if (lock_type
== UNLOCK_LOCK
) {
6025 status
= do_unlock(smbd_messaging_context(),
6032 uint32 block_smbpid
;
6034 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6046 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6048 * A blocking lock was requested. Package up
6049 * this smb into a queued request and push it
6050 * onto the blocking lock queue.
6052 if(push_blocking_lock_request(br_lck
,
6055 -1, /* infinite timeout. */
6063 TALLOC_FREE(br_lck
);
6067 TALLOC_FREE(br_lck
);
6073 /****************************************************************************
6074 Deal with SMB_SET_FILE_BASIC_INFO.
6075 ****************************************************************************/
6077 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6081 const struct smb_filename
*smb_fname
)
6083 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6084 struct smb_file_time ft
;
6086 NTSTATUS status
= NT_STATUS_OK
;
6090 if (total_data
< 36) {
6091 return NT_STATUS_INVALID_PARAMETER
;
6094 /* Set the attributes */
6095 dosmode
= IVAL(pdata
,32);
6096 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6097 if (!NT_STATUS_IS_OK(status
)) {
6102 ft
.create_time
= interpret_long_date(pdata
);
6105 ft
.atime
= interpret_long_date(pdata
+8);
6108 ft
.mtime
= interpret_long_date(pdata
+16);
6111 ft
.ctime
= interpret_long_date(pdata
+24);
6113 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6114 smb_fname_str_dbg(smb_fname
)));
6116 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6120 /****************************************************************************
6121 Deal with SMB_INFO_STANDARD.
6122 ****************************************************************************/
6124 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6128 const struct smb_filename
*smb_fname
)
6130 struct smb_file_time ft
;
6134 if (total_data
< 12) {
6135 return NT_STATUS_INVALID_PARAMETER
;
6139 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6141 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6143 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6145 DEBUG(10,("smb_set_info_standard: file %s\n",
6146 smb_fname_str_dbg(smb_fname
)));
6148 return smb_set_file_time(conn
,
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6157 ****************************************************************************/
6159 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6160 struct smb_request
*req
,
6164 struct smb_filename
*smb_fname
)
6166 uint64_t allocation_size
= 0;
6167 NTSTATUS status
= NT_STATUS_OK
;
6168 files_struct
*new_fsp
= NULL
;
6170 if (!VALID_STAT(smb_fname
->st
)) {
6171 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6174 if (total_data
< 8) {
6175 return NT_STATUS_INVALID_PARAMETER
;
6178 allocation_size
= (uint64_t)IVAL(pdata
,0);
6179 #ifdef LARGE_SMB_OFF_T
6180 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6181 #else /* LARGE_SMB_OFF_T */
6182 if (IVAL(pdata
,4) != 0) {
6183 /* more than 32 bits? */
6184 return NT_STATUS_INVALID_PARAMETER
;
6186 #endif /* LARGE_SMB_OFF_T */
6188 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6189 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6190 (double)allocation_size
));
6192 if (allocation_size
) {
6193 allocation_size
= smb_roundup(conn
, allocation_size
);
6196 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6197 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6198 (double)allocation_size
));
6200 if (fsp
&& fsp
->fh
->fd
!= -1) {
6201 /* Open file handle. */
6202 /* Only change if needed. */
6203 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6204 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6205 return map_nt_error_from_unix(errno
);
6208 /* But always update the time. */
6210 * This is equivalent to a write. Ensure it's seen immediately
6211 * if there are no pending writes.
6213 trigger_write_time_update_immediate(fsp
);
6214 return NT_STATUS_OK
;
6217 /* Pathname or stat or directory file. */
6218 status
= SMB_VFS_CREATE_FILE(
6221 0, /* root_dir_fid */
6222 smb_fname
, /* fname */
6223 FILE_WRITE_DATA
, /* access_mask */
6224 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6226 FILE_OPEN
, /* create_disposition*/
6227 0, /* create_options */
6228 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6229 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6230 0, /* allocation_size */
6233 &new_fsp
, /* result */
6236 if (!NT_STATUS_IS_OK(status
)) {
6237 /* NB. We check for open_was_deferred in the caller. */
6241 /* Only change if needed. */
6242 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6243 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6244 status
= map_nt_error_from_unix(errno
);
6245 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6250 /* Changing the allocation size should set the last mod time. */
6252 * This is equivalent to a write. Ensure it's seen immediately
6253 * if there are no pending writes.
6255 trigger_write_time_update_immediate(new_fsp
);
6257 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6258 return NT_STATUS_OK
;
6261 /****************************************************************************
6262 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6263 ****************************************************************************/
6265 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6266 struct smb_request
*req
,
6270 const struct smb_filename
*smb_fname
)
6274 if (total_data
< 8) {
6275 return NT_STATUS_INVALID_PARAMETER
;
6278 size
= IVAL(pdata
,0);
6279 #ifdef LARGE_SMB_OFF_T
6280 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6281 #else /* LARGE_SMB_OFF_T */
6282 if (IVAL(pdata
,4) != 0) {
6283 /* more than 32 bits? */
6284 return NT_STATUS_INVALID_PARAMETER
;
6286 #endif /* LARGE_SMB_OFF_T */
6287 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6288 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6291 return smb_set_file_size(conn
, req
,
6298 /****************************************************************************
6299 Allow a UNIX info mknod.
6300 ****************************************************************************/
6302 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6305 const struct smb_filename
*smb_fname
)
6307 uint32 file_type
= IVAL(pdata
,56);
6308 #if defined(HAVE_MAKEDEV)
6309 uint32 dev_major
= IVAL(pdata
,60);
6310 uint32 dev_minor
= IVAL(pdata
,68);
6312 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6313 uint32 raw_unixmode
= IVAL(pdata
,84);
6317 if (total_data
< 100) {
6318 return NT_STATUS_INVALID_PARAMETER
;
6321 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6322 PERM_NEW_FILE
, &unixmode
);
6323 if (!NT_STATUS_IS_OK(status
)) {
6327 #if defined(HAVE_MAKEDEV)
6328 dev
= makedev(dev_major
, dev_minor
);
6331 switch (file_type
) {
6332 #if defined(S_IFIFO)
6333 case UNIX_TYPE_FIFO
:
6334 unixmode
|= S_IFIFO
;
6337 #if defined(S_IFSOCK)
6338 case UNIX_TYPE_SOCKET
:
6339 unixmode
|= S_IFSOCK
;
6342 #if defined(S_IFCHR)
6343 case UNIX_TYPE_CHARDEV
:
6344 unixmode
|= S_IFCHR
;
6347 #if defined(S_IFBLK)
6348 case UNIX_TYPE_BLKDEV
:
6349 unixmode
|= S_IFBLK
;
6353 return NT_STATUS_INVALID_PARAMETER
;
6356 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6357 "%.0f mode 0%o for file %s\n", (double)dev
,
6358 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6360 /* Ok - do the mknod. */
6361 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6362 return map_nt_error_from_unix(errno
);
6365 /* If any of the other "set" calls fail we
6366 * don't want to end up with a half-constructed mknod.
6369 if (lp_inherit_perms(SNUM(conn
))) {
6371 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6373 return NT_STATUS_NO_MEMORY
;
6375 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6377 TALLOC_FREE(parent
);
6380 return NT_STATUS_OK
;
6383 /****************************************************************************
6384 Deal with SMB_SET_FILE_UNIX_BASIC.
6385 ****************************************************************************/
6387 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6388 struct smb_request
*req
,
6392 const struct smb_filename
*smb_fname
)
6394 struct smb_file_time ft
;
6395 uint32 raw_unixmode
;
6398 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6399 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6400 NTSTATUS status
= NT_STATUS_OK
;
6401 bool delete_on_fail
= False
;
6402 enum perm_type ptype
;
6403 files_struct
*all_fsps
= NULL
;
6404 bool modify_mtime
= true;
6406 SMB_STRUCT_STAT sbuf
;
6410 if (total_data
< 100) {
6411 return NT_STATUS_INVALID_PARAMETER
;
6414 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6415 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6416 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6417 #ifdef LARGE_SMB_OFF_T
6418 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6419 #else /* LARGE_SMB_OFF_T */
6420 if (IVAL(pdata
,4) != 0) {
6421 /* more than 32 bits? */
6422 return NT_STATUS_INVALID_PARAMETER
;
6424 #endif /* LARGE_SMB_OFF_T */
6427 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6428 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6429 set_owner
= (uid_t
)IVAL(pdata
,40);
6430 set_grp
= (gid_t
)IVAL(pdata
,48);
6431 raw_unixmode
= IVAL(pdata
,84);
6433 if (VALID_STAT(smb_fname
->st
)) {
6434 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6435 ptype
= PERM_EXISTING_DIR
;
6437 ptype
= PERM_EXISTING_FILE
;
6440 ptype
= PERM_NEW_FILE
;
6443 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6445 if (!NT_STATUS_IS_OK(status
)) {
6449 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6450 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6451 smb_fname_str_dbg(smb_fname
), (double)size
,
6452 (unsigned int)set_owner
, (unsigned int)set_grp
,
6453 (int)raw_unixmode
));
6455 sbuf
= smb_fname
->st
;
6457 if (!VALID_STAT(sbuf
)) {
6458 struct smb_filename
*smb_fname_tmp
= NULL
;
6460 * The only valid use of this is to create character and block
6461 * devices, and named pipes. This is deprecated (IMHO) and
6462 * a new info level should be used for mknod. JRA.
6465 status
= smb_unix_mknod(conn
,
6469 if (!NT_STATUS_IS_OK(status
)) {
6473 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6475 if (!NT_STATUS_IS_OK(status
)) {
6479 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6480 status
= map_nt_error_from_unix(errno
);
6481 TALLOC_FREE(smb_fname_tmp
);
6482 SMB_VFS_UNLINK(conn
, smb_fname
);
6486 sbuf
= smb_fname_tmp
->st
;
6487 TALLOC_FREE(smb_fname_tmp
);
6489 /* Ensure we don't try and change anything else. */
6490 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6491 size
= get_file_size_stat(&sbuf
);
6492 ft
.atime
= sbuf
.st_ex_atime
;
6493 ft
.mtime
= sbuf
.st_ex_mtime
;
6495 * We continue here as we might want to change the
6498 delete_on_fail
= True
;
6502 /* Horrible backwards compatibility hack as an old server bug
6503 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6507 size
= get_file_size_stat(&sbuf
);
6512 * Deal with the UNIX specific mode set.
6515 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6516 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6517 "setting mode 0%o for file %s\n",
6518 (unsigned int)unixmode
,
6519 smb_fname_str_dbg(smb_fname
)));
6520 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6521 return map_nt_error_from_unix(errno
);
6526 * Deal with the UNIX specific uid set.
6529 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6530 (sbuf
.st_ex_uid
!= set_owner
)) {
6533 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6534 "changing owner %u for path %s\n",
6535 (unsigned int)set_owner
,
6536 smb_fname_str_dbg(smb_fname
)));
6538 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6539 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6540 set_owner
, (gid_t
)-1);
6542 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6543 set_owner
, (gid_t
)-1);
6547 status
= map_nt_error_from_unix(errno
);
6548 if (delete_on_fail
) {
6549 SMB_VFS_UNLINK(conn
, smb_fname
);
6556 * Deal with the UNIX specific gid set.
6559 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6560 (sbuf
.st_ex_gid
!= set_grp
)) {
6561 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6562 "changing group %u for file %s\n",
6563 (unsigned int)set_owner
,
6564 smb_fname_str_dbg(smb_fname
)));
6565 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6567 status
= map_nt_error_from_unix(errno
);
6568 if (delete_on_fail
) {
6569 SMB_VFS_UNLINK(conn
, smb_fname
);
6575 /* Deal with any size changes. */
6577 status
= smb_set_file_size(conn
, req
,
6582 if (!NT_STATUS_IS_OK(status
)) {
6586 /* Deal with any time changes. */
6587 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6588 /* No change, don't cancel anything. */
6592 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6593 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6594 all_fsps
= file_find_di_next(all_fsps
)) {
6596 * We're setting the time explicitly for UNIX.
6597 * Cancel any pending changes over all handles.
6599 all_fsps
->update_write_time_on_close
= false;
6600 TALLOC_FREE(all_fsps
->update_write_time_event
);
6604 * Override the "setting_write_time"
6605 * parameter here as it almost does what
6606 * we need. Just remember if we modified
6607 * mtime and send the notify ourselves.
6609 if (null_timespec(ft
.mtime
)) {
6610 modify_mtime
= false;
6613 status
= smb_set_file_time(conn
,
6619 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6620 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6625 /****************************************************************************
6626 Deal with SMB_SET_FILE_UNIX_INFO2.
6627 ****************************************************************************/
6629 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6630 struct smb_request
*req
,
6634 const struct smb_filename
*smb_fname
)
6640 if (total_data
< 116) {
6641 return NT_STATUS_INVALID_PARAMETER
;
6644 /* Start by setting all the fields that are common between UNIX_BASIC
6647 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6649 if (!NT_STATUS_IS_OK(status
)) {
6653 smb_fflags
= IVAL(pdata
, 108);
6654 smb_fmask
= IVAL(pdata
, 112);
6656 /* NB: We should only attempt to alter the file flags if the client
6657 * sends a non-zero mask.
6659 if (smb_fmask
!= 0) {
6660 int stat_fflags
= 0;
6662 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6663 smb_fmask
, &stat_fflags
)) {
6664 /* Client asked to alter a flag we don't understand. */
6665 return NT_STATUS_INVALID_PARAMETER
;
6668 if (fsp
&& fsp
->fh
->fd
!= -1) {
6669 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6670 return NT_STATUS_NOT_SUPPORTED
;
6672 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6673 stat_fflags
) != 0) {
6674 return map_nt_error_from_unix(errno
);
6679 /* XXX: need to add support for changing the create_time here. You
6680 * can do this for paths on Darwin with setattrlist(2). The right way
6681 * to hook this up is probably by extending the VFS utimes interface.
6684 return NT_STATUS_OK
;
6687 /****************************************************************************
6688 Create a directory with POSIX semantics.
6689 ****************************************************************************/
6691 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6692 struct smb_request
*req
,
6695 struct smb_filename
*smb_fname
,
6696 int *pdata_return_size
)
6698 NTSTATUS status
= NT_STATUS_OK
;
6699 uint32 raw_unixmode
= 0;
6700 uint32 mod_unixmode
= 0;
6701 mode_t unixmode
= (mode_t
)0;
6702 files_struct
*fsp
= NULL
;
6703 uint16 info_level_return
= 0;
6705 char *pdata
= *ppdata
;
6707 if (total_data
< 18) {
6708 return NT_STATUS_INVALID_PARAMETER
;
6711 raw_unixmode
= IVAL(pdata
,8);
6712 /* Next 4 bytes are not yet defined. */
6714 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6715 PERM_NEW_DIR
, &unixmode
);
6716 if (!NT_STATUS_IS_OK(status
)) {
6720 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6722 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6723 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6725 status
= SMB_VFS_CREATE_FILE(
6728 0, /* root_dir_fid */
6729 smb_fname
, /* fname */
6730 FILE_READ_ATTRIBUTES
, /* access_mask */
6731 FILE_SHARE_NONE
, /* share_access */
6732 FILE_CREATE
, /* create_disposition*/
6733 FILE_DIRECTORY_FILE
, /* create_options */
6734 mod_unixmode
, /* file_attributes */
6735 0, /* oplock_request */
6736 0, /* allocation_size */
6742 if (NT_STATUS_IS_OK(status
)) {
6743 close_file(req
, fsp
, NORMAL_CLOSE
);
6746 info_level_return
= SVAL(pdata
,16);
6748 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6749 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6750 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6751 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6753 *pdata_return_size
= 12;
6756 /* Realloc the data size */
6757 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6758 if (*ppdata
== NULL
) {
6759 *pdata_return_size
= 0;
6760 return NT_STATUS_NO_MEMORY
;
6764 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6765 SSVAL(pdata
,2,0); /* No fnum. */
6766 SIVAL(pdata
,4,info
); /* Was directory created. */
6768 switch (info_level_return
) {
6769 case SMB_QUERY_FILE_UNIX_BASIC
:
6770 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6771 SSVAL(pdata
,10,0); /* Padding. */
6772 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6775 case SMB_QUERY_FILE_UNIX_INFO2
:
6776 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6777 SSVAL(pdata
,10,0); /* Padding. */
6778 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6782 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6783 SSVAL(pdata
,10,0); /* Padding. */
6790 /****************************************************************************
6791 Open/Create a file with POSIX semantics.
6792 ****************************************************************************/
6794 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6795 struct smb_request
*req
,
6798 struct smb_filename
*smb_fname
,
6799 int *pdata_return_size
)
6801 bool extended_oplock_granted
= False
;
6802 char *pdata
= *ppdata
;
6804 uint32 wire_open_mode
= 0;
6805 uint32 raw_unixmode
= 0;
6806 uint32 mod_unixmode
= 0;
6807 uint32 create_disp
= 0;
6808 uint32 access_mask
= 0;
6809 uint32 create_options
= 0;
6810 NTSTATUS status
= NT_STATUS_OK
;
6811 mode_t unixmode
= (mode_t
)0;
6812 files_struct
*fsp
= NULL
;
6813 int oplock_request
= 0;
6815 uint16 info_level_return
= 0;
6817 if (total_data
< 18) {
6818 return NT_STATUS_INVALID_PARAMETER
;
6821 flags
= IVAL(pdata
,0);
6822 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6823 if (oplock_request
) {
6824 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6827 wire_open_mode
= IVAL(pdata
,4);
6829 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6830 return smb_posix_mkdir(conn
, req
,
6837 switch (wire_open_mode
& SMB_ACCMODE
) {
6839 access_mask
= FILE_READ_DATA
;
6842 access_mask
= FILE_WRITE_DATA
;
6845 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
6848 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6849 (unsigned int)wire_open_mode
));
6850 return NT_STATUS_INVALID_PARAMETER
;
6853 wire_open_mode
&= ~SMB_ACCMODE
;
6855 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6856 create_disp
= FILE_CREATE
;
6857 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6858 create_disp
= FILE_OVERWRITE_IF
;
6859 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6860 create_disp
= FILE_OPEN_IF
;
6861 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
6862 create_disp
= FILE_OPEN
;
6864 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6865 (unsigned int)wire_open_mode
));
6866 return NT_STATUS_INVALID_PARAMETER
;
6869 raw_unixmode
= IVAL(pdata
,8);
6870 /* Next 4 bytes are not yet defined. */
6872 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6873 (VALID_STAT(smb_fname
->st
) ?
6874 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
6877 if (!NT_STATUS_IS_OK(status
)) {
6881 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6883 if (wire_open_mode
& SMB_O_SYNC
) {
6884 create_options
|= FILE_WRITE_THROUGH
;
6886 if (wire_open_mode
& SMB_O_APPEND
) {
6887 access_mask
|= FILE_APPEND_DATA
;
6889 if (wire_open_mode
& SMB_O_DIRECT
) {
6890 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6893 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6894 smb_fname_str_dbg(smb_fname
),
6895 (unsigned int)wire_open_mode
,
6896 (unsigned int)unixmode
));
6898 status
= SMB_VFS_CREATE_FILE(
6901 0, /* root_dir_fid */
6902 smb_fname
, /* fname */
6903 access_mask
, /* access_mask */
6904 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6906 create_disp
, /* create_disposition*/
6907 FILE_NON_DIRECTORY_FILE
, /* create_options */
6908 mod_unixmode
, /* file_attributes */
6909 oplock_request
, /* oplock_request */
6910 0, /* allocation_size */
6916 if (!NT_STATUS_IS_OK(status
)) {
6920 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6921 extended_oplock_granted
= True
;
6924 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6925 extended_oplock_granted
= True
;
6928 info_level_return
= SVAL(pdata
,16);
6930 /* Allocate the correct return size. */
6932 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6933 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6934 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6935 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6937 *pdata_return_size
= 12;
6940 /* Realloc the data size */
6941 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6942 if (*ppdata
== NULL
) {
6943 close_file(req
, fsp
, ERROR_CLOSE
);
6944 *pdata_return_size
= 0;
6945 return NT_STATUS_NO_MEMORY
;
6949 if (extended_oplock_granted
) {
6950 if (flags
& REQUEST_BATCH_OPLOCK
) {
6951 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6953 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6955 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6956 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6958 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6961 SSVAL(pdata
,2,fsp
->fnum
);
6962 SIVAL(pdata
,4,info
); /* Was file created etc. */
6964 switch (info_level_return
) {
6965 case SMB_QUERY_FILE_UNIX_BASIC
:
6966 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6967 SSVAL(pdata
,10,0); /* padding. */
6968 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6971 case SMB_QUERY_FILE_UNIX_INFO2
:
6972 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6973 SSVAL(pdata
,10,0); /* padding. */
6974 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6978 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6979 SSVAL(pdata
,10,0); /* padding. */
6982 return NT_STATUS_OK
;
6985 /****************************************************************************
6986 Delete a file with POSIX semantics.
6987 ****************************************************************************/
6989 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6990 struct smb_request
*req
,
6993 struct smb_filename
*smb_fname
)
6995 NTSTATUS status
= NT_STATUS_OK
;
6996 files_struct
*fsp
= NULL
;
7000 int create_options
= 0;
7002 struct share_mode_lock
*lck
= NULL
;
7004 if (total_data
< 2) {
7005 return NT_STATUS_INVALID_PARAMETER
;
7008 flags
= SVAL(pdata
,0);
7010 if (!VALID_STAT(smb_fname
->st
)) {
7011 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7014 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7015 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7016 return NT_STATUS_NOT_A_DIRECTORY
;
7019 DEBUG(10,("smb_posix_unlink: %s %s\n",
7020 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7021 smb_fname_str_dbg(smb_fname
)));
7023 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7024 create_options
|= FILE_DIRECTORY_FILE
;
7027 status
= SMB_VFS_CREATE_FILE(
7030 0, /* root_dir_fid */
7031 smb_fname
, /* fname */
7032 DELETE_ACCESS
, /* access_mask */
7033 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7035 FILE_OPEN
, /* create_disposition*/
7036 create_options
, /* create_options */
7037 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7038 0, /* oplock_request */
7039 0, /* allocation_size */
7045 if (!NT_STATUS_IS_OK(status
)) {
7050 * Don't lie to client. If we can't really delete due to
7051 * non-POSIX opens return SHARING_VIOLATION.
7054 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7057 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7058 "lock for file %s\n", fsp_str_dbg(fsp
)));
7059 close_file(req
, fsp
, NORMAL_CLOSE
);
7060 return NT_STATUS_INVALID_PARAMETER
;
7064 * See if others still have the file open. If this is the case, then
7065 * don't delete. If all opens are POSIX delete we can set the delete
7066 * on close disposition.
7068 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7069 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7070 if (is_valid_share_mode_entry(e
)) {
7071 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7074 /* Fail with sharing violation. */
7075 close_file(req
, fsp
, NORMAL_CLOSE
);
7077 return NT_STATUS_SHARING_VIOLATION
;
7082 * Set the delete on close.
7084 status
= smb_set_file_disposition_info(conn
,
7090 if (!NT_STATUS_IS_OK(status
)) {
7091 close_file(req
, fsp
, NORMAL_CLOSE
);
7096 return close_file(req
, fsp
, NORMAL_CLOSE
);
7099 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7100 struct smb_request
*req
,
7101 TALLOC_CTX
*mem_ctx
,
7102 uint16_t info_level
,
7104 struct smb_filename
*smb_fname
,
7105 char **ppdata
, int total_data
,
7108 char *pdata
= *ppdata
;
7109 NTSTATUS status
= NT_STATUS_OK
;
7110 int data_return_size
= 0;
7114 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7115 return NT_STATUS_INVALID_LEVEL
;
7118 if (!CAN_WRITE(conn
)) {
7119 /* Allow POSIX opens. The open path will deny
7120 * any non-readonly opens. */
7121 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7122 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7126 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7127 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7128 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7130 switch (info_level
) {
7132 case SMB_INFO_STANDARD
:
7134 status
= smb_set_info_standard(conn
,
7142 case SMB_INFO_SET_EA
:
7144 status
= smb_info_set_ea(conn
,
7152 case SMB_SET_FILE_BASIC_INFO
:
7153 case SMB_FILE_BASIC_INFORMATION
:
7155 status
= smb_set_file_basic_info(conn
,
7163 case SMB_FILE_ALLOCATION_INFORMATION
:
7164 case SMB_SET_FILE_ALLOCATION_INFO
:
7166 status
= smb_set_file_allocation_info(conn
, req
,
7174 case SMB_FILE_END_OF_FILE_INFORMATION
:
7175 case SMB_SET_FILE_END_OF_FILE_INFO
:
7177 status
= smb_set_file_end_of_file_info(conn
, req
,
7185 case SMB_FILE_DISPOSITION_INFORMATION
:
7186 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7189 /* JRA - We used to just ignore this on a path ?
7190 * Shouldn't this be invalid level on a pathname
7193 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7194 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7197 status
= smb_set_file_disposition_info(conn
,
7205 case SMB_FILE_POSITION_INFORMATION
:
7207 status
= smb_file_position_information(conn
,
7214 /* From tridge Samba4 :
7215 * MODE_INFORMATION in setfileinfo (I have no
7216 * idea what "mode information" on a file is - it takes a value of 0,
7217 * 2, 4 or 6. What could it be?).
7220 case SMB_FILE_MODE_INFORMATION
:
7222 status
= smb_file_mode_information(conn
,
7229 * CIFS UNIX extensions.
7232 case SMB_SET_FILE_UNIX_BASIC
:
7234 status
= smb_set_file_unix_basic(conn
, req
,
7242 case SMB_SET_FILE_UNIX_INFO2
:
7244 status
= smb_set_file_unix_info2(conn
, req
,
7252 case SMB_SET_FILE_UNIX_LINK
:
7255 /* We must have a pathname for this. */
7256 return NT_STATUS_INVALID_LEVEL
;
7258 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7259 total_data
, smb_fname
);
7263 case SMB_SET_FILE_UNIX_HLINK
:
7266 /* We must have a pathname for this. */
7267 return NT_STATUS_INVALID_LEVEL
;
7269 status
= smb_set_file_unix_hlink(conn
, req
,
7275 case SMB_FILE_RENAME_INFORMATION
:
7277 status
= smb_file_rename_information(conn
, req
,
7283 #if defined(HAVE_POSIX_ACLS)
7284 case SMB_SET_POSIX_ACL
:
7286 status
= smb_set_posix_acl(conn
,
7295 case SMB_SET_POSIX_LOCK
:
7298 return NT_STATUS_INVALID_LEVEL
;
7300 status
= smb_set_posix_lock(conn
, req
,
7301 pdata
, total_data
, fsp
);
7305 case SMB_POSIX_PATH_OPEN
:
7308 /* We must have a pathname for this. */
7309 return NT_STATUS_INVALID_LEVEL
;
7312 status
= smb_posix_open(conn
, req
,
7320 case SMB_POSIX_PATH_UNLINK
:
7323 /* We must have a pathname for this. */
7324 return NT_STATUS_INVALID_LEVEL
;
7327 status
= smb_posix_unlink(conn
, req
,
7335 return NT_STATUS_INVALID_LEVEL
;
7338 if (!NT_STATUS_IS_OK(status
)) {
7342 *ret_data_size
= data_return_size
;
7343 return NT_STATUS_OK
;
7346 /****************************************************************************
7347 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7348 ****************************************************************************/
7350 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7351 struct smb_request
*req
,
7352 unsigned int tran_call
,
7353 char **pparams
, int total_params
,
7354 char **ppdata
, int total_data
,
7355 unsigned int max_data_bytes
)
7357 char *params
= *pparams
;
7358 char *pdata
= *ppdata
;
7360 struct smb_filename
*smb_fname
= NULL
;
7361 files_struct
*fsp
= NULL
;
7362 NTSTATUS status
= NT_STATUS_OK
;
7363 int data_return_size
= 0;
7366 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7370 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7371 if (total_params
< 4) {
7372 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7376 fsp
= file_fsp(req
, SVAL(params
,0));
7377 /* Basic check for non-null fsp. */
7378 if (!check_fsp_open(conn
, req
, fsp
)) {
7381 info_level
= SVAL(params
,2);
7383 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7385 if (!NT_STATUS_IS_OK(status
)) {
7386 reply_nterror(req
, status
);
7390 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7392 * This is actually a SETFILEINFO on a directory
7393 * handle (returned from an NT SMB). NT5.0 seems
7394 * to do this call. JRA.
7396 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7397 /* Always do lstat for UNIX calls. */
7398 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7399 DEBUG(3,("call_trans2setfilepathinfo: "
7400 "SMB_VFS_LSTAT of %s failed "
7402 smb_fname_str_dbg(smb_fname
),
7404 reply_nterror(req
, map_nt_error_from_unix(errno
));
7408 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7409 DEBUG(3,("call_trans2setfilepathinfo: "
7410 "fileinfo of %s failed (%s)\n",
7411 smb_fname_str_dbg(smb_fname
),
7413 reply_nterror(req
, map_nt_error_from_unix(errno
));
7417 } else if (fsp
->print_file
) {
7419 * Doing a DELETE_ON_CLOSE should cancel a print job.
7421 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7422 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7424 DEBUG(3,("call_trans2setfilepathinfo: "
7425 "Cancelling print job (%s)\n",
7429 send_trans2_replies(conn
, req
, params
, 2,
7434 reply_doserror(req
, ERRDOS
, ERRbadpath
);
7439 * Original code - this is an open file.
7441 if (!check_fsp(conn
, req
, fsp
)) {
7445 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7446 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7447 "of fnum %d failed (%s)\n", fsp
->fnum
,
7449 reply_nterror(req
, map_nt_error_from_unix(errno
));
7457 if (total_params
< 7) {
7458 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7462 info_level
= SVAL(params
,0);
7463 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7464 total_params
- 6, STR_TERMINATE
,
7466 if (!NT_STATUS_IS_OK(status
)) {
7467 reply_nterror(req
, status
);
7471 status
= filename_convert(req
, conn
,
7472 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7477 if (!NT_STATUS_IS_OK(status
)) {
7478 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7479 reply_botherror(req
,
7480 NT_STATUS_PATH_NOT_COVERED
,
7481 ERRSRV
, ERRbadpath
);
7484 reply_nterror(req
, status
);
7488 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7490 * For CIFS UNIX extensions the target name may not exist.
7493 /* Always do lstat for UNIX calls. */
7494 SMB_VFS_LSTAT(conn
, smb_fname
);
7496 } else if (!VALID_STAT(smb_fname
->st
) &&
7497 SMB_VFS_STAT(conn
, smb_fname
)) {
7498 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7500 smb_fname_str_dbg(smb_fname
),
7502 reply_nterror(req
, map_nt_error_from_unix(errno
));
7507 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7508 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7509 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7511 /* Realloc the parameter size */
7512 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7513 if (*pparams
== NULL
) {
7514 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7521 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7527 if (!NT_STATUS_IS_OK(status
)) {
7528 if (open_was_deferred(req
->mid
)) {
7529 /* We have re-scheduled this call. */
7532 if (blocking_lock_was_deferred(req
->mid
)) {
7533 /* We have re-scheduled this call. */
7536 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7537 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7538 ERRSRV
, ERRbadpath
);
7541 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7542 reply_openerror(req
, status
);
7546 reply_nterror(req
, status
);
7550 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7556 /****************************************************************************
7557 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7558 ****************************************************************************/
7560 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7561 char **pparams
, int total_params
,
7562 char **ppdata
, int total_data
,
7563 unsigned int max_data_bytes
)
7565 struct smb_filename
*smb_dname
= NULL
;
7566 char *params
= *pparams
;
7567 char *pdata
= *ppdata
;
7568 char *directory
= NULL
;
7569 NTSTATUS status
= NT_STATUS_OK
;
7570 struct ea_list
*ea_list
= NULL
;
7571 TALLOC_CTX
*ctx
= talloc_tos();
7573 if (!CAN_WRITE(conn
)) {
7574 reply_doserror(req
, ERRSRV
, ERRaccess
);
7578 if (total_params
< 5) {
7579 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7583 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7584 total_params
- 4, STR_TERMINATE
,
7586 if (!NT_STATUS_IS_OK(status
)) {
7587 reply_nterror(req
, status
);
7591 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7593 status
= filename_convert(ctx
,
7595 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7601 if (!NT_STATUS_IS_OK(status
)) {
7602 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7603 reply_botherror(req
,
7604 NT_STATUS_PATH_NOT_COVERED
,
7605 ERRSRV
, ERRbadpath
);
7608 reply_nterror(req
, status
);
7612 /* Any data in this call is an EA list. */
7613 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7614 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7619 * OS/2 workplace shell seems to send SET_EA requests of "null"
7620 * length (4 bytes containing IVAL 4).
7621 * They seem to have no effect. Bug #3212. JRA.
7624 if (total_data
!= 4) {
7625 if (total_data
< 10) {
7626 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7630 if (IVAL(pdata
,0) > total_data
) {
7631 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7632 IVAL(pdata
,0), (unsigned int)total_data
));
7633 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7637 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7640 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7644 /* If total_data == 4 Windows doesn't care what values
7645 * are placed in that field, it just ignores them.
7646 * The System i QNTC IBM SMB client puts bad values here,
7647 * so ignore them. */
7649 status
= create_directory(conn
, req
, smb_dname
);
7651 if (!NT_STATUS_IS_OK(status
)) {
7652 reply_nterror(req
, status
);
7656 /* Try and set any given EA. */
7658 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7659 if (!NT_STATUS_IS_OK(status
)) {
7660 reply_nterror(req
, status
);
7665 /* Realloc the parameter and data sizes */
7666 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7667 if(*pparams
== NULL
) {
7668 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7675 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7678 TALLOC_FREE(smb_dname
);
7682 /****************************************************************************
7683 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7684 We don't actually do this - we just send a null response.
7685 ****************************************************************************/
7687 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7688 struct smb_request
*req
,
7689 char **pparams
, int total_params
,
7690 char **ppdata
, int total_data
,
7691 unsigned int max_data_bytes
)
7693 char *params
= *pparams
;
7696 if (total_params
< 6) {
7697 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7701 info_level
= SVAL(params
,4);
7702 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7704 switch (info_level
) {
7709 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7713 /* Realloc the parameter and data sizes */
7714 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7715 if (*pparams
== NULL
) {
7716 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7721 SSVAL(params
,0,fnf_handle
);
7722 SSVAL(params
,2,0); /* No changes */
7723 SSVAL(params
,4,0); /* No EA errors */
7730 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7735 /****************************************************************************
7736 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7737 changes). Currently this does nothing.
7738 ****************************************************************************/
7740 static void call_trans2findnotifynext(connection_struct
*conn
,
7741 struct smb_request
*req
,
7742 char **pparams
, int total_params
,
7743 char **ppdata
, int total_data
,
7744 unsigned int max_data_bytes
)
7746 char *params
= *pparams
;
7748 DEBUG(3,("call_trans2findnotifynext\n"));
7750 /* Realloc the parameter and data sizes */
7751 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7752 if (*pparams
== NULL
) {
7753 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7758 SSVAL(params
,0,0); /* No changes */
7759 SSVAL(params
,2,0); /* No EA errors */
7761 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7766 /****************************************************************************
7767 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7768 ****************************************************************************/
7770 static void call_trans2getdfsreferral(connection_struct
*conn
,
7771 struct smb_request
*req
,
7772 char **pparams
, int total_params
,
7773 char **ppdata
, int total_data
,
7774 unsigned int max_data_bytes
)
7776 char *params
= *pparams
;
7777 char *pathname
= NULL
;
7779 int max_referral_level
;
7780 NTSTATUS status
= NT_STATUS_OK
;
7781 TALLOC_CTX
*ctx
= talloc_tos();
7783 DEBUG(10,("call_trans2getdfsreferral\n"));
7785 if (total_params
< 3) {
7786 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7790 max_referral_level
= SVAL(params
,0);
7792 if(!lp_host_msdfs()) {
7793 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
7797 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
7798 total_params
- 2, STR_TERMINATE
);
7800 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
7803 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
7804 ppdata
,&status
)) < 0) {
7805 reply_nterror(req
, status
);
7809 SSVAL(req
->inbuf
, smb_flg2
,
7810 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
7811 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
7816 #define LMCAT_SPL 0x53
7817 #define LMFUNC_GETJOBID 0x60
7819 /****************************************************************************
7820 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7821 ****************************************************************************/
7823 static void call_trans2ioctl(connection_struct
*conn
,
7824 struct smb_request
*req
,
7825 char **pparams
, int total_params
,
7826 char **ppdata
, int total_data
,
7827 unsigned int max_data_bytes
)
7829 char *pdata
= *ppdata
;
7830 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
7832 /* check for an invalid fid before proceeding */
7835 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7839 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
7840 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
7841 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
7842 if (*ppdata
== NULL
) {
7843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7848 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7849 CAN ACCEPT THIS IN UNICODE. JRA. */
7851 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
7852 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
7853 global_myname(), 15,
7854 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
7855 srvstr_push(pdata
, req
->flags2
, pdata
+18,
7856 lp_servicename(SNUM(conn
)), 13,
7857 STR_ASCII
|STR_TERMINATE
); /* Service name */
7858 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
7863 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7864 reply_doserror(req
, ERRSRV
, ERRerror
);
7867 /****************************************************************************
7868 Reply to a SMBfindclose (stop trans2 directory search).
7869 ****************************************************************************/
7871 void reply_findclose(struct smb_request
*req
)
7874 struct smbd_server_connection
*sconn
= smbd_server_conn
;
7876 START_PROFILE(SMBfindclose
);
7879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7880 END_PROFILE(SMBfindclose
);
7884 dptr_num
= SVALS(req
->vwv
+0, 0);
7886 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7888 dptr_close(sconn
, &dptr_num
);
7890 reply_outbuf(req
, 0, 0);
7892 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7894 END_PROFILE(SMBfindclose
);
7898 /****************************************************************************
7899 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7900 ****************************************************************************/
7902 void reply_findnclose(struct smb_request
*req
)
7906 START_PROFILE(SMBfindnclose
);
7909 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7910 END_PROFILE(SMBfindnclose
);
7914 dptr_num
= SVAL(req
->vwv
+0, 0);
7916 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7918 /* We never give out valid handles for a
7919 findnotifyfirst - so any dptr_num is ok here.
7922 reply_outbuf(req
, 0, 0);
7924 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7926 END_PROFILE(SMBfindnclose
);
7930 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7931 struct trans_state
*state
)
7933 if (Protocol
>= PROTOCOL_NT1
) {
7934 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7935 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7938 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
7939 if (state
->call
!= TRANSACT2_QFSINFO
&&
7940 state
->call
!= TRANSACT2_SETFSINFO
) {
7941 DEBUG(0,("handle_trans2: encryption required "
7943 (unsigned int)state
->call
));
7944 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7949 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
7951 /* Now we must call the relevant TRANS2 function */
7952 switch(state
->call
) {
7953 case TRANSACT2_OPEN
:
7955 START_PROFILE(Trans2_open
);
7956 call_trans2open(conn
, req
,
7957 &state
->param
, state
->total_param
,
7958 &state
->data
, state
->total_data
,
7959 state
->max_data_return
);
7960 END_PROFILE(Trans2_open
);
7964 case TRANSACT2_FINDFIRST
:
7966 START_PROFILE(Trans2_findfirst
);
7967 call_trans2findfirst(conn
, req
,
7968 &state
->param
, state
->total_param
,
7969 &state
->data
, state
->total_data
,
7970 state
->max_data_return
);
7971 END_PROFILE(Trans2_findfirst
);
7975 case TRANSACT2_FINDNEXT
:
7977 START_PROFILE(Trans2_findnext
);
7978 call_trans2findnext(conn
, req
,
7979 &state
->param
, state
->total_param
,
7980 &state
->data
, state
->total_data
,
7981 state
->max_data_return
);
7982 END_PROFILE(Trans2_findnext
);
7986 case TRANSACT2_QFSINFO
:
7988 START_PROFILE(Trans2_qfsinfo
);
7989 call_trans2qfsinfo(conn
, req
,
7990 &state
->param
, state
->total_param
,
7991 &state
->data
, state
->total_data
,
7992 state
->max_data_return
);
7993 END_PROFILE(Trans2_qfsinfo
);
7997 case TRANSACT2_SETFSINFO
:
7999 START_PROFILE(Trans2_setfsinfo
);
8000 call_trans2setfsinfo(conn
, req
,
8001 &state
->param
, state
->total_param
,
8002 &state
->data
, state
->total_data
,
8003 state
->max_data_return
);
8004 END_PROFILE(Trans2_setfsinfo
);
8008 case TRANSACT2_QPATHINFO
:
8009 case TRANSACT2_QFILEINFO
:
8011 START_PROFILE(Trans2_qpathinfo
);
8012 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8013 &state
->param
, state
->total_param
,
8014 &state
->data
, state
->total_data
,
8015 state
->max_data_return
);
8016 END_PROFILE(Trans2_qpathinfo
);
8020 case TRANSACT2_SETPATHINFO
:
8021 case TRANSACT2_SETFILEINFO
:
8023 START_PROFILE(Trans2_setpathinfo
);
8024 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8025 &state
->param
, state
->total_param
,
8026 &state
->data
, state
->total_data
,
8027 state
->max_data_return
);
8028 END_PROFILE(Trans2_setpathinfo
);
8032 case TRANSACT2_FINDNOTIFYFIRST
:
8034 START_PROFILE(Trans2_findnotifyfirst
);
8035 call_trans2findnotifyfirst(conn
, req
,
8036 &state
->param
, state
->total_param
,
8037 &state
->data
, state
->total_data
,
8038 state
->max_data_return
);
8039 END_PROFILE(Trans2_findnotifyfirst
);
8043 case TRANSACT2_FINDNOTIFYNEXT
:
8045 START_PROFILE(Trans2_findnotifynext
);
8046 call_trans2findnotifynext(conn
, req
,
8047 &state
->param
, state
->total_param
,
8048 &state
->data
, state
->total_data
,
8049 state
->max_data_return
);
8050 END_PROFILE(Trans2_findnotifynext
);
8054 case TRANSACT2_MKDIR
:
8056 START_PROFILE(Trans2_mkdir
);
8057 call_trans2mkdir(conn
, req
,
8058 &state
->param
, state
->total_param
,
8059 &state
->data
, state
->total_data
,
8060 state
->max_data_return
);
8061 END_PROFILE(Trans2_mkdir
);
8065 case TRANSACT2_GET_DFS_REFERRAL
:
8067 START_PROFILE(Trans2_get_dfs_referral
);
8068 call_trans2getdfsreferral(conn
, req
,
8069 &state
->param
, state
->total_param
,
8070 &state
->data
, state
->total_data
,
8071 state
->max_data_return
);
8072 END_PROFILE(Trans2_get_dfs_referral
);
8076 case TRANSACT2_IOCTL
:
8078 START_PROFILE(Trans2_ioctl
);
8079 call_trans2ioctl(conn
, req
,
8080 &state
->param
, state
->total_param
,
8081 &state
->data
, state
->total_data
,
8082 state
->max_data_return
);
8083 END_PROFILE(Trans2_ioctl
);
8088 /* Error in request */
8089 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8090 reply_doserror(req
, ERRSRV
,ERRerror
);
8094 /****************************************************************************
8095 Reply to a SMBtrans2.
8096 ****************************************************************************/
8098 void reply_trans2(struct smb_request
*req
)
8100 connection_struct
*conn
= req
->conn
;
8105 unsigned int tran_call
;
8106 struct trans_state
*state
;
8109 START_PROFILE(SMBtrans2
);
8111 if (req
->wct
< 14) {
8112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8113 END_PROFILE(SMBtrans2
);
8117 dsoff
= SVAL(req
->vwv
+12, 0);
8118 dscnt
= SVAL(req
->vwv
+11, 0);
8119 psoff
= SVAL(req
->vwv
+10, 0);
8120 pscnt
= SVAL(req
->vwv
+9, 0);
8121 tran_call
= SVAL(req
->vwv
+14, 0);
8123 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8124 if (!NT_STATUS_IS_OK(result
)) {
8125 DEBUG(2, ("Got invalid trans2 request: %s\n",
8126 nt_errstr(result
)));
8127 reply_nterror(req
, result
);
8128 END_PROFILE(SMBtrans2
);
8133 switch (tran_call
) {
8134 /* List the allowed trans2 calls on IPC$ */
8135 case TRANSACT2_OPEN
:
8136 case TRANSACT2_GET_DFS_REFERRAL
:
8137 case TRANSACT2_QFILEINFO
:
8138 case TRANSACT2_QFSINFO
:
8139 case TRANSACT2_SETFSINFO
:
8142 reply_doserror(req
, ERRSRV
, ERRaccess
);
8143 END_PROFILE(SMBtrans2
);
8148 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8149 DEBUG(0, ("talloc failed\n"));
8150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8151 END_PROFILE(SMBtrans2
);
8155 state
->cmd
= SMBtrans2
;
8157 state
->mid
= req
->mid
;
8158 state
->vuid
= req
->vuid
;
8159 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8160 state
->setup
= NULL
;
8161 state
->total_param
= SVAL(req
->vwv
+0, 0);
8162 state
->param
= NULL
;
8163 state
->total_data
= SVAL(req
->vwv
+1, 0);
8165 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8166 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8167 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8168 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8169 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8171 state
->call
= tran_call
;
8173 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8174 is so as a sanity check */
8175 if (state
->setup_count
!= 1) {
8177 * Need to have rc=0 for ioctl to get job id for OS/2.
8178 * Network printing will fail if function is not successful.
8179 * Similar function in reply.c will be used if protocol
8180 * is LANMAN1.0 instead of LM1.2X002.
8181 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8182 * outbuf doesn't have to be set(only job id is used).
8184 if ( (state
->setup_count
== 4)
8185 && (tran_call
== TRANSACT2_IOCTL
)
8186 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8187 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8188 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8190 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8191 DEBUG(2,("Transaction is %d\n",tran_call
));
8193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8194 END_PROFILE(SMBtrans2
);
8199 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8202 if (state
->total_data
) {
8204 if (trans_oob(state
->total_data
, 0, dscnt
)
8205 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8209 /* Can't use talloc here, the core routines do realloc on the
8210 * params and data. */
8211 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8212 if (state
->data
== NULL
) {
8213 DEBUG(0,("reply_trans2: data malloc fail for %u "
8214 "bytes !\n", (unsigned int)state
->total_data
));
8216 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8217 END_PROFILE(SMBtrans2
);
8221 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8224 if (state
->total_param
) {
8226 if (trans_oob(state
->total_param
, 0, pscnt
)
8227 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8231 /* Can't use talloc here, the core routines do realloc on the
8232 * params and data. */
8233 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8234 if (state
->param
== NULL
) {
8235 DEBUG(0,("reply_trans: param malloc fail for %u "
8236 "bytes !\n", (unsigned int)state
->total_param
));
8237 SAFE_FREE(state
->data
);
8239 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8240 END_PROFILE(SMBtrans2
);
8244 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8247 state
->received_data
= dscnt
;
8248 state
->received_param
= pscnt
;
8250 if ((state
->received_param
== state
->total_param
) &&
8251 (state
->received_data
== state
->total_data
)) {
8253 handle_trans2(conn
, req
, state
);
8255 SAFE_FREE(state
->data
);
8256 SAFE_FREE(state
->param
);
8258 END_PROFILE(SMBtrans2
);
8262 DLIST_ADD(conn
->pending_trans
, state
);
8264 /* We need to send an interim response then receive the rest
8265 of the parameter/data bytes */
8266 reply_outbuf(req
, 0, 0);
8267 show_msg((char *)req
->outbuf
);
8268 END_PROFILE(SMBtrans2
);
8273 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8274 SAFE_FREE(state
->data
);
8275 SAFE_FREE(state
->param
);
8277 END_PROFILE(SMBtrans2
);
8278 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8282 /****************************************************************************
8283 Reply to a SMBtranss2
8284 ****************************************************************************/
8286 void reply_transs2(struct smb_request
*req
)
8288 connection_struct
*conn
= req
->conn
;
8289 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8290 struct trans_state
*state
;
8292 START_PROFILE(SMBtranss2
);
8294 show_msg((char *)req
->inbuf
);
8297 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8298 END_PROFILE(SMBtranss2
);
8302 for (state
= conn
->pending_trans
; state
!= NULL
;
8303 state
= state
->next
) {
8304 if (state
->mid
== req
->mid
) {
8309 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8310 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8311 END_PROFILE(SMBtranss2
);
8315 /* Revise state->total_param and state->total_data in case they have
8316 changed downwards */
8318 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8319 state
->total_param
= SVAL(req
->vwv
+0, 0);
8320 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8321 state
->total_data
= SVAL(req
->vwv
+1, 0);
8323 pcnt
= SVAL(req
->vwv
+2, 0);
8324 poff
= SVAL(req
->vwv
+3, 0);
8325 pdisp
= SVAL(req
->vwv
+4, 0);
8327 dcnt
= SVAL(req
->vwv
+5, 0);
8328 doff
= SVAL(req
->vwv
+6, 0);
8329 ddisp
= SVAL(req
->vwv
+7, 0);
8331 state
->received_param
+= pcnt
;
8332 state
->received_data
+= dcnt
;
8334 if ((state
->received_data
> state
->total_data
) ||
8335 (state
->received_param
> state
->total_param
))
8339 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8340 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8343 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8347 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8348 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8351 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8354 if ((state
->received_param
< state
->total_param
) ||
8355 (state
->received_data
< state
->total_data
)) {
8356 END_PROFILE(SMBtranss2
);
8360 handle_trans2(conn
, req
, state
);
8362 DLIST_REMOVE(conn
->pending_trans
, state
);
8363 SAFE_FREE(state
->data
);
8364 SAFE_FREE(state
->param
);
8367 END_PROFILE(SMBtranss2
);
8372 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8373 DLIST_REMOVE(conn
->pending_trans
, state
);
8374 SAFE_FREE(state
->data
);
8375 SAFE_FREE(state
->param
);
8377 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8378 END_PROFILE(SMBtranss2
);