2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol
;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
52 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name
)
72 static const char * const prohibited_ea_names
[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME
,
74 SAMBA_XATTR_DOS_ATTRIB
,
75 SAMBA_XATTR_DOSTIMESTAMPS
,
81 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
82 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
85 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
97 files_struct
*fsp
, const char *fname
,
98 const char *ea_name
, struct ea_struct
*pea
)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size
= 256;
107 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
109 return NT_STATUS_NO_MEMORY
;
112 if (fsp
&& fsp
->fh
->fd
!= -1) {
113 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
115 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
118 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
124 return map_nt_error_from_unix(errno
);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
128 dump_data(10, (uint8
*)val
, sizeret
);
131 if (strnequal(ea_name
, "user.", 5)) {
132 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
134 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
136 if (pea
->name
== NULL
) {
138 return NT_STATUS_NO_MEMORY
;
140 pea
->value
.data
= (unsigned char *)val
;
141 pea
->value
.length
= (size_t)sizeret
;
145 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
146 files_struct
*fsp
, const char *fname
,
147 char ***pnames
, size_t *pnum_names
)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size
= 1024;
151 char *ea_namelist
= NULL
;
156 ssize_t sizeret
= -1;
158 if (!lp_ea_support(SNUM(conn
))) {
167 * TALLOC the result early to get the talloc hierarchy right.
170 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
172 DEBUG(0, ("talloc failed\n"));
173 return NT_STATUS_NO_MEMORY
;
176 while (ea_namelist_size
<= 65536) {
178 ea_namelist
= TALLOC_REALLOC_ARRAY(
179 names
, ea_namelist
, char, ea_namelist_size
);
180 if (ea_namelist
== NULL
) {
181 DEBUG(0, ("talloc failed\n"));
183 return NT_STATUS_NO_MEMORY
;
186 if (fsp
&& fsp
->fh
->fd
!= -1) {
187 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
190 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
194 if ((sizeret
== -1) && (errno
== ERANGE
)) {
195 ea_namelist_size
*= 2;
204 return map_nt_error_from_unix(errno
);
207 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
208 (unsigned int)sizeret
));
220 * Ensure the result is 0-terminated
223 if (ea_namelist
[sizeret
-1] != '\0') {
225 return NT_STATUS_INTERNAL_ERROR
;
233 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
237 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
239 DEBUG(0, ("talloc failed\n"));
241 return NT_STATUS_NO_MEMORY
;
247 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
248 names
[num_names
++] = p
;
256 *pnum_names
= num_names
;
260 /****************************************************************************
261 Return a linked list of the total EA's. Plus the total size
262 ****************************************************************************/
264 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
265 const char *fname
, size_t *pea_total_len
)
267 /* Get a list of all xattrs. Max namesize is 64k. */
270 struct ea_list
*ea_list_head
= NULL
;
275 if (!lp_ea_support(SNUM(conn
))) {
279 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
282 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
286 for (i
=0; i
<num_names
; i
++) {
287 struct ea_list
*listp
;
290 if (strnequal(names
[i
], "system.", 7)
291 || samba_private_attr_name(names
[i
]))
294 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
299 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
305 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
308 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
310 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
311 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
312 (unsigned int)listp
->ea
.value
.length
));
314 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
318 /* Add on 4 for total length. */
319 if (*pea_total_len
) {
323 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
324 (unsigned int)*pea_total_len
));
329 /****************************************************************************
330 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
332 ****************************************************************************/
334 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
335 connection_struct
*conn
, struct ea_list
*ea_list
)
337 unsigned int ret_data_size
= 4;
340 SMB_ASSERT(total_data_size
>= 4);
342 if (!lp_ea_support(SNUM(conn
))) {
347 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
350 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
351 dos_namelen
= strlen(dos_ea_name
);
352 if (dos_namelen
> 255 || dos_namelen
== 0) {
355 if (ea_list
->ea
.value
.length
> 65535) {
358 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
362 /* We know we have room. */
363 SCVAL(p
,0,ea_list
->ea
.flags
);
364 SCVAL(p
,1,dos_namelen
);
365 SSVAL(p
,2,ea_list
->ea
.value
.length
);
366 fstrcpy(p
+4, dos_ea_name
);
367 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
369 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
370 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
373 ret_data_size
= PTR_DIFF(p
, pdata
);
374 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
375 SIVAL(pdata
,0,ret_data_size
);
376 return ret_data_size
;
379 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
381 unsigned int total_data_size
,
382 unsigned int *ret_data_size
,
383 connection_struct
*conn
,
384 struct ea_list
*ea_list
)
386 uint8_t *p
= (uint8_t *)pdata
;
387 uint8_t *last_start
= NULL
;
391 if (!lp_ea_support(SNUM(conn
))) {
392 return NT_STATUS_NO_EAS_ON_FILE
;
395 for (; ea_list
; ea_list
= ea_list
->next
) {
401 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
405 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
406 dos_namelen
= strlen(dos_ea_name
);
407 if (dos_namelen
> 255 || dos_namelen
== 0) {
408 return NT_STATUS_INTERNAL_ERROR
;
410 if (ea_list
->ea
.value
.length
> 65535) {
411 return NT_STATUS_INTERNAL_ERROR
;
414 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
417 size_t pad
= 4 - (this_size
% 4);
421 if (this_size
> total_data_size
) {
422 return NT_STATUS_INFO_LENGTH_MISMATCH
;
425 /* We know we have room. */
426 SIVAL(p
, 0x00, 0); /* next offset */
427 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
428 SCVAL(p
, 0x05, dos_namelen
);
429 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
430 fstrcpy((char *)(p
+0x08), dos_ea_name
);
431 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
433 total_data_size
-= this_size
;
437 *ret_data_size
= PTR_DIFF(p
, pdata
);
438 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
442 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
444 size_t total_ea_len
= 0;
445 TALLOC_CTX
*mem_ctx
= NULL
;
447 if (!lp_ea_support(SNUM(conn
))) {
450 mem_ctx
= talloc_tos();
451 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
455 /****************************************************************************
456 Ensure the EA name is case insensitive by matching any existing EA name.
457 ****************************************************************************/
459 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
462 TALLOC_CTX
*mem_ctx
= talloc_tos();
463 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
465 for (; ea_list
; ea_list
= ea_list
->next
) {
466 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
467 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
468 &unix_ea_name
[5], ea_list
->ea
.name
));
469 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
475 /****************************************************************************
476 Set or delete an extended attribute.
477 ****************************************************************************/
479 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
480 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
484 if (!lp_ea_support(SNUM(conn
))) {
485 return NT_STATUS_EAS_NOT_SUPPORTED
;
488 /* For now setting EAs on streams isn't supported. */
489 fname
= smb_fname
->base_name
;
491 for (;ea_list
; ea_list
= ea_list
->next
) {
493 fstring unix_ea_name
;
495 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
496 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
498 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
500 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
502 if (samba_private_attr_name(unix_ea_name
)) {
503 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
504 return NT_STATUS_ACCESS_DENIED
;
507 if (ea_list
->ea
.value
.length
== 0) {
508 /* Remove the attribute. */
509 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
510 DEBUG(10,("set_ea: deleting ea name %s on "
511 "file %s by file descriptor.\n",
512 unix_ea_name
, fsp_str_dbg(fsp
)));
513 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
515 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
516 unix_ea_name
, fname
));
517 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
520 /* Removing a non existent attribute always succeeds. */
521 if (ret
== -1 && errno
== ENOATTR
) {
522 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
528 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
529 DEBUG(10,("set_ea: setting ea name %s on file "
530 "%s by file descriptor.\n",
531 unix_ea_name
, fsp_str_dbg(fsp
)));
532 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
533 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
535 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
536 unix_ea_name
, fname
));
537 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
538 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
544 if (errno
== ENOTSUP
) {
545 return NT_STATUS_EAS_NOT_SUPPORTED
;
548 return map_nt_error_from_unix(errno
);
554 /****************************************************************************
555 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
556 ****************************************************************************/
558 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
560 struct ea_list
*ea_list_head
= NULL
;
561 size_t converted_size
, offset
= 0;
563 while (offset
+ 2 < data_size
) {
564 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
565 unsigned int namelen
= CVAL(pdata
,offset
);
567 offset
++; /* Go past the namelen byte. */
569 /* integer wrap paranioa. */
570 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
571 (offset
> data_size
) || (namelen
> data_size
) ||
572 (offset
+ namelen
>= data_size
)) {
575 /* Ensure the name is null terminated. */
576 if (pdata
[offset
+ namelen
] != '\0') {
579 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
581 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
582 "failed: %s", strerror(errno
)));
588 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
589 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
590 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
596 /****************************************************************************
597 Read one EA list entry from the buffer.
598 ****************************************************************************/
600 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
602 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
604 unsigned int namelen
;
605 size_t converted_size
;
615 eal
->ea
.flags
= CVAL(pdata
,0);
616 namelen
= CVAL(pdata
,1);
617 val_len
= SVAL(pdata
,2);
619 if (4 + namelen
+ 1 + val_len
> data_size
) {
623 /* Ensure the name is null terminated. */
624 if (pdata
[namelen
+ 4] != '\0') {
627 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
628 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
635 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
636 if (!eal
->ea
.value
.data
) {
640 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
642 /* Ensure we're null terminated just in case we print the value. */
643 eal
->ea
.value
.data
[val_len
] = '\0';
644 /* But don't count the null. */
645 eal
->ea
.value
.length
--;
648 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
651 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
652 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
657 /****************************************************************************
658 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
659 ****************************************************************************/
661 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
663 struct ea_list
*ea_list_head
= NULL
;
665 size_t bytes_used
= 0;
667 while (offset
< data_size
) {
668 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
674 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
675 offset
+= bytes_used
;
681 /****************************************************************************
682 Count the total EA size needed.
683 ****************************************************************************/
685 static size_t ea_list_size(struct ea_list
*ealist
)
688 struct ea_list
*listp
;
691 for (listp
= ealist
; listp
; listp
= listp
->next
) {
692 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
693 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
695 /* Add on 4 for total length. */
703 /****************************************************************************
704 Return a union of EA's from a file list and a list of names.
705 The TALLOC context for the two lists *MUST* be identical as we steal
706 memory from one list to add to another. JRA.
707 ****************************************************************************/
709 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
711 struct ea_list
*nlistp
, *flistp
;
713 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
714 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
715 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
721 /* Copy the data from this entry. */
722 nlistp
->ea
.flags
= flistp
->ea
.flags
;
723 nlistp
->ea
.value
= flistp
->ea
.value
;
726 nlistp
->ea
.flags
= 0;
727 ZERO_STRUCT(nlistp
->ea
.value
);
731 *total_ea_len
= ea_list_size(name_list
);
735 /****************************************************************************
736 Send the required number of replies back.
737 We assume all fields other than the data fields are
738 set correctly for the type of call.
739 HACK ! Always assumes smb_setup field is zero.
740 ****************************************************************************/
742 void send_trans2_replies(connection_struct
*conn
,
743 struct smb_request
*req
,
750 /* As we are using a protocol > LANMAN1 then the max_send
751 variable must have been set in the sessetupX call.
752 This takes precedence over the max_xmit field in the
753 global struct. These different max_xmit variables should
754 be merged as this is now too confusing */
756 int data_to_send
= datasize
;
757 int params_to_send
= paramsize
;
759 const char *pp
= params
;
760 const char *pd
= pdata
;
761 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
762 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
763 int data_alignment_offset
= 0;
764 bool overflow
= False
;
765 struct smbd_server_connection
*sconn
= smbd_server_conn
;
766 int max_send
= sconn
->smb1
.sessions
.max_send
;
768 /* Modify the data_to_send and datasize and set the error if
769 we're trying to send more than max_data_bytes. We still send
770 the part of the packet(s) that fit. Strange, but needed
773 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
774 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
775 max_data_bytes
, datasize
));
776 datasize
= data_to_send
= max_data_bytes
;
780 /* If there genuinely are no parameters or data to send just send the empty packet */
782 if(params_to_send
== 0 && data_to_send
== 0) {
783 reply_outbuf(req
, 10, 0);
784 show_msg((char *)req
->outbuf
);
785 if (!srv_send_smb(smbd_server_fd(),
788 IS_CONN_ENCRYPTED(conn
),
790 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
792 TALLOC_FREE(req
->outbuf
);
796 /* When sending params and data ensure that both are nicely aligned */
797 /* Only do this alignment when there is also data to send - else
798 can cause NT redirector problems. */
800 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
801 data_alignment_offset
= 4 - (params_to_send
% 4);
803 /* Space is bufsize minus Netbios over TCP header minus SMB header */
804 /* The alignment_offset is to align the param bytes on an even byte
805 boundary. NT 4.0 Beta needs this to work correctly. */
807 useable_space
= max_send
- (smb_size
810 + data_alignment_offset
);
812 if (useable_space
< 0) {
813 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
814 "= %d!!!", useable_space
));
815 exit_server_cleanly("send_trans2_replies: Not enough space");
818 while (params_to_send
|| data_to_send
) {
819 /* Calculate whether we will totally or partially fill this packet */
821 total_sent_thistime
= params_to_send
+ data_to_send
;
823 /* We can never send more than useable_space */
825 * Note that 'useable_space' does not include the alignment offsets,
826 * but we must include the alignment offsets in the calculation of
827 * the length of the data we send over the wire, as the alignment offsets
828 * are sent here. Fix from Marc_Jacobsen@hp.com.
831 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
833 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
834 + data_alignment_offset
);
837 * We might have SMBtrans2s in req which was transferred to
838 * the outbuf, fix that.
840 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
842 /* Set total params and data to be sent */
843 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
844 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
846 /* Calculate how many parameters and data we can fit into
847 * this packet. Parameters get precedence
850 params_sent_thistime
= MIN(params_to_send
,useable_space
);
851 data_sent_thistime
= useable_space
- params_sent_thistime
;
852 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
854 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
856 /* smb_proff is the offset from the start of the SMB header to the
857 parameter bytes, however the first 4 bytes of outbuf are
858 the Netbios over TCP header. Thus use smb_base() to subtract
859 them from the calculation */
861 SSVAL(req
->outbuf
,smb_proff
,
862 ((smb_buf(req
->outbuf
)+alignment_offset
)
863 - smb_base(req
->outbuf
)));
865 if(params_sent_thistime
== 0)
866 SSVAL(req
->outbuf
,smb_prdisp
,0);
868 /* Absolute displacement of param bytes sent in this packet */
869 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
871 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
872 if(data_sent_thistime
== 0) {
873 SSVAL(req
->outbuf
,smb_droff
,0);
874 SSVAL(req
->outbuf
,smb_drdisp
, 0);
876 /* The offset of the data bytes is the offset of the
877 parameter bytes plus the number of parameters being sent this time */
878 SSVAL(req
->outbuf
, smb_droff
,
879 ((smb_buf(req
->outbuf
)+alignment_offset
)
880 - smb_base(req
->outbuf
))
881 + params_sent_thistime
+ data_alignment_offset
);
882 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
885 /* Initialize the padding for alignment */
887 if (alignment_offset
!= 0) {
888 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
891 /* Copy the param bytes into the packet */
893 if(params_sent_thistime
) {
894 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
895 params_sent_thistime
);
898 /* Copy in the data bytes */
899 if(data_sent_thistime
) {
900 if (data_alignment_offset
!= 0) {
901 memset((smb_buf(req
->outbuf
)+alignment_offset
+
902 params_sent_thistime
), 0,
903 data_alignment_offset
);
905 memcpy(smb_buf(req
->outbuf
)+alignment_offset
906 +params_sent_thistime
+data_alignment_offset
,
907 pd
,data_sent_thistime
);
910 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
911 params_sent_thistime
, data_sent_thistime
, useable_space
));
912 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
913 params_to_send
, data_to_send
, paramsize
, datasize
));
916 error_packet_set((char *)req
->outbuf
,
917 ERRDOS
,ERRbufferoverflow
,
918 STATUS_BUFFER_OVERFLOW
,
922 /* Send the packet */
923 show_msg((char *)req
->outbuf
);
924 if (!srv_send_smb(smbd_server_fd(),
927 IS_CONN_ENCRYPTED(conn
),
929 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
931 TALLOC_FREE(req
->outbuf
);
933 pp
+= params_sent_thistime
;
934 pd
+= data_sent_thistime
;
936 params_to_send
-= params_sent_thistime
;
937 data_to_send
-= data_sent_thistime
;
940 if(params_to_send
< 0 || data_to_send
< 0) {
941 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
942 params_to_send
, data_to_send
));
950 /****************************************************************************
951 Reply to a TRANSACT2_OPEN.
952 ****************************************************************************/
954 static void call_trans2open(connection_struct
*conn
,
955 struct smb_request
*req
,
956 char **pparams
, int total_params
,
957 char **ppdata
, int total_data
,
958 unsigned int max_data_bytes
)
960 struct smb_filename
*smb_fname
= NULL
;
961 char *params
= *pparams
;
962 char *pdata
= *ppdata
;
967 bool return_additional_info
;
980 struct ea_list
*ea_list
= NULL
;
985 uint32 create_disposition
;
986 uint32 create_options
= 0;
987 TALLOC_CTX
*ctx
= talloc_tos();
990 * Ensure we have enough parameters to perform the operation.
993 if (total_params
< 29) {
994 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
998 flags
= SVAL(params
, 0);
999 deny_mode
= SVAL(params
, 2);
1000 open_attr
= SVAL(params
,6);
1001 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1002 if (oplock_request
) {
1003 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1007 return_additional_info
= BITSETW(params
,0);
1008 open_sattr
= SVAL(params
, 4);
1009 open_time
= make_unix_date3(params
+8);
1011 open_ofun
= SVAL(params
,12);
1012 open_size
= IVAL(params
,14);
1013 pname
= ¶ms
[28];
1016 reply_doserror(req
, ERRSRV
, ERRaccess
);
1020 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1021 total_params
- 28, STR_TERMINATE
,
1023 if (!NT_STATUS_IS_OK(status
)) {
1024 reply_nterror(req
, status
);
1028 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1029 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1030 (unsigned int)open_ofun
, open_size
));
1032 status
= filename_convert(ctx
,
1034 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1041 reply_botherror(req
,
1042 NT_STATUS_PATH_NOT_COVERED
,
1043 ERRSRV
, ERRbadpath
);
1046 reply_nterror(req
, status
);
1050 if (open_ofun
== 0) {
1051 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1055 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1056 &access_mask
, &share_mode
,
1057 &create_disposition
,
1059 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
1063 /* Any data in this call is an EA list. */
1064 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
1065 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1069 if (total_data
!= 4) {
1070 if (total_data
< 10) {
1071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1075 if (IVAL(pdata
,0) > total_data
) {
1076 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1077 IVAL(pdata
,0), (unsigned int)total_data
));
1078 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1082 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1085 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1088 } else if (IVAL(pdata
,0) != 4) {
1089 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1093 status
= SMB_VFS_CREATE_FILE(
1096 0, /* root_dir_fid */
1097 smb_fname
, /* fname */
1098 access_mask
, /* access_mask */
1099 share_mode
, /* share_access */
1100 create_disposition
, /* create_disposition*/
1101 create_options
, /* create_options */
1102 open_attr
, /* file_attributes */
1103 oplock_request
, /* oplock_request */
1104 open_size
, /* allocation_size */
1106 ea_list
, /* ea_list */
1108 &smb_action
); /* psbuf */
1110 if (!NT_STATUS_IS_OK(status
)) {
1111 if (open_was_deferred(req
->mid
)) {
1112 /* We have re-scheduled this call. */
1115 reply_openerror(req
, status
);
1119 size
= get_file_size_stat(&smb_fname
->st
);
1120 fattr
= dos_mode(conn
, smb_fname
);
1121 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1122 inode
= smb_fname
->st
.st_ex_ino
;
1124 close_file(req
, fsp
, ERROR_CLOSE
);
1125 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1129 /* Realloc the size of parameters and data we will return */
1130 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1131 if(*pparams
== NULL
) {
1132 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1137 SSVAL(params
,0,fsp
->fnum
);
1138 SSVAL(params
,2,fattr
);
1139 srv_put_dos_date2(params
,4, mtime
);
1140 SIVAL(params
,8, (uint32
)size
);
1141 SSVAL(params
,12,deny_mode
);
1142 SSVAL(params
,14,0); /* open_type - file or directory. */
1143 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1145 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1146 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1149 SSVAL(params
,18,smb_action
);
1152 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1154 SIVAL(params
,20,inode
);
1155 SSVAL(params
,24,0); /* Padding. */
1157 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1158 fsp
->fsp_name
->base_name
);
1159 SIVAL(params
, 26, ea_size
);
1161 SIVAL(params
, 26, 0);
1164 /* Send the required number of replies */
1165 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1167 TALLOC_FREE(smb_fname
);
1170 /*********************************************************
1171 Routine to check if a given string matches exactly.
1172 as a special case a mask of "." does NOT match. That
1173 is required for correct wildcard semantics
1174 Case can be significant or not.
1175 **********************************************************/
1177 static bool exact_match(bool has_wild
,
1178 bool case_sensitive
,
1182 if (mask
[0] == '.' && mask
[1] == 0) {
1190 if (case_sensitive
) {
1191 return strcmp(str
,mask
)==0;
1193 return StrCaseCmp(str
,mask
) == 0;
1197 /****************************************************************************
1198 Return the filetype for UNIX extensions.
1199 ****************************************************************************/
1201 static uint32
unix_filetype(mode_t mode
)
1204 return UNIX_TYPE_FILE
;
1205 else if(S_ISDIR(mode
))
1206 return UNIX_TYPE_DIR
;
1208 else if(S_ISLNK(mode
))
1209 return UNIX_TYPE_SYMLINK
;
1212 else if(S_ISCHR(mode
))
1213 return UNIX_TYPE_CHARDEV
;
1216 else if(S_ISBLK(mode
))
1217 return UNIX_TYPE_BLKDEV
;
1220 else if(S_ISFIFO(mode
))
1221 return UNIX_TYPE_FIFO
;
1224 else if(S_ISSOCK(mode
))
1225 return UNIX_TYPE_SOCKET
;
1228 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1229 return UNIX_TYPE_UNKNOWN
;
1232 /****************************************************************************
1233 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1234 ****************************************************************************/
1236 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1238 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1239 const SMB_STRUCT_STAT
*psbuf
,
1241 enum perm_type ptype
,
1246 if (perms
== SMB_MODE_NO_CHANGE
) {
1247 if (!VALID_STAT(*psbuf
)) {
1248 return NT_STATUS_INVALID_PARAMETER
;
1250 *ret_perms
= psbuf
->st_ex_mode
;
1251 return NT_STATUS_OK
;
1255 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1256 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1257 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1258 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1259 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1260 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1261 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1262 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1263 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1265 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1268 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1271 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1276 /* Apply mode mask */
1277 ret
&= lp_create_mask(SNUM(conn
));
1278 /* Add in force bits */
1279 ret
|= lp_force_create_mode(SNUM(conn
));
1282 ret
&= lp_dir_mask(SNUM(conn
));
1283 /* Add in force bits */
1284 ret
|= lp_force_dir_mode(SNUM(conn
));
1286 case PERM_EXISTING_FILE
:
1287 /* Apply mode mask */
1288 ret
&= lp_security_mask(SNUM(conn
));
1289 /* Add in force bits */
1290 ret
|= lp_force_security_mode(SNUM(conn
));
1292 case PERM_EXISTING_DIR
:
1293 /* Apply mode mask */
1294 ret
&= lp_dir_security_mask(SNUM(conn
));
1295 /* Add in force bits */
1296 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1301 return NT_STATUS_OK
;
1304 /****************************************************************************
1305 Needed to show the msdfs symlinks as directories. Modifies psbuf
1306 to be a directory if it's a msdfs link.
1307 ****************************************************************************/
1309 static bool check_msdfs_link(connection_struct
*conn
,
1310 const char *pathname
,
1311 SMB_STRUCT_STAT
*psbuf
)
1313 int saved_errno
= errno
;
1314 if(lp_host_msdfs() &&
1315 lp_msdfs_root(SNUM(conn
)) &&
1316 is_msdfs_link(conn
, pathname
, psbuf
)) {
1318 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1321 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1322 errno
= saved_errno
;
1325 errno
= saved_errno
;
1330 /****************************************************************************
1331 Get a level dependent lanman2 dir entry.
1332 ****************************************************************************/
1334 struct smbd_dirptr_lanman2_state
{
1335 connection_struct
*conn
;
1336 uint32_t info_level
;
1337 bool check_mangled_names
;
1339 bool got_exact_match
;
1342 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1348 struct smbd_dirptr_lanman2_state
*state
=
1349 (struct smbd_dirptr_lanman2_state
*)private_data
;
1351 char mangled_name
[13]; /* mangled 8.3 name. */
1355 /* Mangle fname if it's an illegal name. */
1356 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1357 ok
= name_to_8_3(dname
, mangled_name
,
1358 true, state
->conn
->params
);
1362 fname
= mangled_name
;
1367 got_match
= exact_match(state
->has_wild
,
1368 state
->conn
->case_sensitive
,
1370 state
->got_exact_match
= got_match
;
1372 got_match
= mask_match(fname
, mask
,
1373 state
->conn
->case_sensitive
);
1376 if(!got_match
&& state
->check_mangled_names
&&
1377 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1379 * It turns out that NT matches wildcards against
1380 * both long *and* short names. This may explain some
1381 * of the wildcard wierdness from old DOS clients
1382 * that some people have been seeing.... JRA.
1384 /* Force the mangling into 8.3. */
1385 ok
= name_to_8_3(fname
, mangled_name
,
1386 false, state
->conn
->params
);
1391 got_match
= exact_match(state
->has_wild
,
1392 state
->conn
->case_sensitive
,
1393 mangled_name
, mask
);
1394 state
->got_exact_match
= got_match
;
1396 got_match
= mask_match(mangled_name
, mask
,
1397 state
->conn
->case_sensitive
);
1405 *_fname
= talloc_strdup(ctx
, fname
);
1406 if (*_fname
== NULL
) {
1413 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1415 struct smb_filename
*smb_fname
,
1418 struct smbd_dirptr_lanman2_state
*state
=
1419 (struct smbd_dirptr_lanman2_state
*)private_data
;
1420 bool ms_dfs_link
= false;
1423 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1424 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1425 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1426 "Couldn't lstat [%s] (%s)\n",
1427 smb_fname_str_dbg(smb_fname
),
1431 } else if (!VALID_STAT(smb_fname
->st
) &&
1432 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1433 /* Needed to show the msdfs symlinks as
1436 ms_dfs_link
= check_msdfs_link(state
->conn
,
1437 smb_fname
->base_name
,
1440 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1441 "Couldn't stat [%s] (%s)\n",
1442 smb_fname_str_dbg(smb_fname
),
1449 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1451 mode
= dos_mode(state
->conn
, smb_fname
);
1458 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1459 connection_struct
*conn
,
1461 uint32_t info_level
,
1462 struct ea_list
*name_list
,
1463 bool check_mangled_names
,
1464 bool requires_resume_key
,
1467 const struct smb_filename
*smb_fname
,
1468 uint64_t space_remaining
,
1475 uint64_t *last_entry_off
)
1477 char *p
, *q
, *pdata
= *ppdata
;
1479 uint64_t file_size
= 0;
1480 uint64_t allocation_size
= 0;
1482 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1483 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1484 time_t c_date
= (time_t)0;
1486 char *last_entry_ptr
;
1488 uint32_t nt_extmode
; /* Used for NT connections instead of mode */
1492 *out_of_space
= false;
1494 ZERO_STRUCT(mdate_ts
);
1495 ZERO_STRUCT(adate_ts
);
1496 ZERO_STRUCT(create_date_ts
);
1497 ZERO_STRUCT(cdate_ts
);
1499 if (!(mode
& aDIR
)) {
1500 file_size
= get_file_size_stat(&smb_fname
->st
);
1502 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1504 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1505 adate_ts
= smb_fname
->st
.st_ex_atime
;
1506 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1507 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1509 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1510 dos_filetime_timespec(&create_date_ts
);
1511 dos_filetime_timespec(&mdate_ts
);
1512 dos_filetime_timespec(&adate_ts
);
1513 dos_filetime_timespec(&cdate_ts
);
1516 create_date
= convert_timespec_to_time_t(create_date_ts
);
1517 mdate
= convert_timespec_to_time_t(mdate_ts
);
1518 adate
= convert_timespec_to_time_t(adate_ts
);
1519 c_date
= convert_timespec_to_time_t(cdate_ts
);
1521 /* align the record */
1522 off
= PTR_DIFF(pdata
, base_data
);
1523 pad
= (off
+ (align
-1)) & ~(align
-1);
1526 /* initialize padding to 0 */
1527 memset(pdata
, 0, pad
);
1528 space_remaining
-= pad
;
1537 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1539 switch (info_level
) {
1540 case SMB_FIND_INFO_STANDARD
:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1542 if(requires_resume_key
) {
1546 srv_put_dos_date2(p
,0,create_date
);
1547 srv_put_dos_date2(p
,4,adate
);
1548 srv_put_dos_date2(p
,8,mdate
);
1549 SIVAL(p
,12,(uint32
)file_size
);
1550 SIVAL(p
,16,(uint32
)allocation_size
);
1554 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1555 p
+= ucs2_align(base_data
, p
, 0);
1557 len
= srvstr_push(base_data
, flags2
, p
,
1558 fname
, PTR_DIFF(end_data
, p
),
1560 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1562 SCVAL(nameptr
, -1, len
- 2);
1564 SCVAL(nameptr
, -1, 0);
1568 SCVAL(nameptr
, -1, len
- 1);
1570 SCVAL(nameptr
, -1, 0);
1576 case SMB_FIND_EA_SIZE
:
1577 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1578 if (requires_resume_key
) {
1582 srv_put_dos_date2(p
,0,create_date
);
1583 srv_put_dos_date2(p
,4,adate
);
1584 srv_put_dos_date2(p
,8,mdate
);
1585 SIVAL(p
,12,(uint32
)file_size
);
1586 SIVAL(p
,16,(uint32
)allocation_size
);
1589 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1590 smb_fname
->base_name
);
1591 SIVAL(p
,22,ea_size
); /* Extended attributes */
1595 len
= srvstr_push(base_data
, flags2
,
1596 p
, fname
, PTR_DIFF(end_data
, p
),
1597 STR_TERMINATE
| STR_NOALIGN
);
1598 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1611 SCVAL(nameptr
,0,len
);
1613 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1616 case SMB_FIND_EA_LIST
:
1618 struct ea_list
*file_list
= NULL
;
1621 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1625 if (requires_resume_key
) {
1629 srv_put_dos_date2(p
,0,create_date
);
1630 srv_put_dos_date2(p
,4,adate
);
1631 srv_put_dos_date2(p
,8,mdate
);
1632 SIVAL(p
,12,(uint32
)file_size
);
1633 SIVAL(p
,16,(uint32
)allocation_size
);
1635 p
+= 22; /* p now points to the EA area. */
1637 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1638 smb_fname
->base_name
,
1640 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1642 /* We need to determine if this entry will fit in the space available. */
1643 /* Max string size is 255 bytes. */
1644 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1645 *out_of_space
= true;
1646 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1647 return False
; /* Not finished - just out of space */
1650 /* Push the ea_data followed by the name. */
1651 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1653 len
= srvstr_push(base_data
, flags2
,
1654 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1655 STR_TERMINATE
| STR_NOALIGN
);
1656 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1669 SCVAL(nameptr
,0,len
);
1671 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1676 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1677 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1679 SIVAL(p
,0,reskey
); p
+= 4;
1680 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1681 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1682 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1683 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1684 SOFF_T(p
,0,file_size
); p
+= 8;
1685 SOFF_T(p
,0,allocation_size
); p
+= 8;
1686 SIVAL(p
,0,nt_extmode
); p
+= 4;
1687 q
= p
; p
+= 4; /* q is placeholder for name length. */
1689 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1690 smb_fname
->base_name
);
1691 SIVAL(p
,0,ea_size
); /* Extended attributes */
1694 /* Clear the short name buffer. This is
1695 * IMPORTANT as not doing so will trigger
1696 * a Win2k client bug. JRA.
1698 if (!was_8_3
&& check_mangled_names
) {
1699 char mangled_name
[13]; /* mangled 8.3 name. */
1700 if (!name_to_8_3(fname
,mangled_name
,True
,
1702 /* Error - mangle failed ! */
1703 memset(mangled_name
,'\0',12);
1705 mangled_name
[12] = 0;
1706 len
= srvstr_push(base_data
, flags2
,
1707 p
+2, mangled_name
, 24,
1708 STR_UPPER
|STR_UNICODE
);
1710 memset(p
+ 2 + len
,'\0',24 - len
);
1717 len
= srvstr_push(base_data
, flags2
, p
,
1718 fname
, PTR_DIFF(end_data
, p
),
1719 STR_TERMINATE_ASCII
);
1723 len
= PTR_DIFF(p
, pdata
);
1724 pad
= (len
+ (align
-1)) & ~(align
-1);
1726 * offset to the next entry, the caller
1727 * will overwrite it for the last entry
1728 * that's why we always include the padding
1732 * set padding to zero
1735 memset(p
, 0, pad
- len
);
1742 case SMB_FIND_FILE_DIRECTORY_INFO
:
1743 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1745 SIVAL(p
,0,reskey
); p
+= 4;
1746 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1747 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1748 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1749 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1750 SOFF_T(p
,0,file_size
); p
+= 8;
1751 SOFF_T(p
,0,allocation_size
); p
+= 8;
1752 SIVAL(p
,0,nt_extmode
); p
+= 4;
1753 len
= srvstr_push(base_data
, flags2
,
1754 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1755 STR_TERMINATE_ASCII
);
1759 len
= PTR_DIFF(p
, pdata
);
1760 pad
= (len
+ (align
-1)) & ~(align
-1);
1762 * offset to the next entry, the caller
1763 * will overwrite it for the last entry
1764 * that's why we always include the padding
1768 * set padding to zero
1771 memset(p
, 0, pad
- len
);
1778 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1779 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1781 SIVAL(p
,0,reskey
); p
+= 4;
1782 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1783 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1784 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1786 SOFF_T(p
,0,file_size
); p
+= 8;
1787 SOFF_T(p
,0,allocation_size
); p
+= 8;
1788 SIVAL(p
,0,nt_extmode
); p
+= 4;
1789 q
= p
; p
+= 4; /* q is placeholder for name length. */
1791 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1792 smb_fname
->base_name
);
1793 SIVAL(p
,0,ea_size
); /* Extended attributes */
1796 len
= srvstr_push(base_data
, flags2
, p
,
1797 fname
, PTR_DIFF(end_data
, p
),
1798 STR_TERMINATE_ASCII
);
1802 len
= PTR_DIFF(p
, pdata
);
1803 pad
= (len
+ (align
-1)) & ~(align
-1);
1805 * offset to the next entry, the caller
1806 * will overwrite it for the last entry
1807 * that's why we always include the padding
1811 * set padding to zero
1814 memset(p
, 0, pad
- len
);
1821 case SMB_FIND_FILE_NAMES_INFO
:
1822 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1824 SIVAL(p
,0,reskey
); p
+= 4;
1826 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1827 acl on a dir (tridge) */
1828 len
= srvstr_push(base_data
, flags2
, p
,
1829 fname
, PTR_DIFF(end_data
, p
),
1830 STR_TERMINATE_ASCII
);
1834 len
= PTR_DIFF(p
, pdata
);
1835 pad
= (len
+ (align
-1)) & ~(align
-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1843 * set padding to zero
1846 memset(p
, 0, pad
- len
);
1853 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1854 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1856 SIVAL(p
,0,reskey
); p
+= 4;
1857 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1858 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1859 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1861 SOFF_T(p
,0,file_size
); p
+= 8;
1862 SOFF_T(p
,0,allocation_size
); p
+= 8;
1863 SIVAL(p
,0,nt_extmode
); p
+= 4;
1864 q
= p
; p
+= 4; /* q is placeholder for name length. */
1866 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1867 smb_fname
->base_name
);
1868 SIVAL(p
,0,ea_size
); /* Extended attributes */
1871 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1872 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1873 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1874 len
= srvstr_push(base_data
, flags2
, p
,
1875 fname
, PTR_DIFF(end_data
, p
),
1876 STR_TERMINATE_ASCII
);
1880 len
= PTR_DIFF(p
, pdata
);
1881 pad
= (len
+ (align
-1)) & ~(align
-1);
1883 * offset to the next entry, the caller
1884 * will overwrite it for the last entry
1885 * that's why we always include the padding
1889 * set padding to zero
1892 memset(p
, 0, pad
- len
);
1899 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1900 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1901 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1903 SIVAL(p
,0,reskey
); p
+= 4;
1904 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1905 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1906 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1907 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1908 SOFF_T(p
,0,file_size
); p
+= 8;
1909 SOFF_T(p
,0,allocation_size
); p
+= 8;
1910 SIVAL(p
,0,nt_extmode
); p
+= 4;
1911 q
= p
; p
+= 4; /* q is placeholder for name length */
1913 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1914 smb_fname
->base_name
);
1915 SIVAL(p
,0,ea_size
); /* Extended attributes */
1918 /* Clear the short name buffer. This is
1919 * IMPORTANT as not doing so will trigger
1920 * a Win2k client bug. JRA.
1922 if (!was_8_3
&& check_mangled_names
) {
1923 char mangled_name
[13]; /* mangled 8.3 name. */
1924 if (!name_to_8_3(fname
,mangled_name
,True
,
1926 /* Error - mangle failed ! */
1927 memset(mangled_name
,'\0',12);
1929 mangled_name
[12] = 0;
1930 len
= srvstr_push(base_data
, flags2
,
1931 p
+2, mangled_name
, 24,
1932 STR_UPPER
|STR_UNICODE
);
1935 memset(p
+ 2 + len
,'\0',24 - len
);
1942 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1943 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1944 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1945 len
= srvstr_push(base_data
, flags2
, p
,
1946 fname
, PTR_DIFF(end_data
, p
),
1947 STR_TERMINATE_ASCII
);
1951 len
= PTR_DIFF(p
, pdata
);
1952 pad
= (len
+ (align
-1)) & ~(align
-1);
1954 * offset to the next entry, the caller
1955 * will overwrite it for the last entry
1956 * that's why we always include the padding
1960 * set padding to zero
1963 memset(p
, 0, pad
- len
);
1970 /* CIFS UNIX Extension. */
1972 case SMB_FIND_FILE_UNIX
:
1973 case SMB_FIND_FILE_UNIX_INFO2
:
1975 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1977 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1979 if (info_level
== SMB_FIND_FILE_UNIX
) {
1980 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1981 p
= store_file_unix_basic(conn
, p
,
1982 NULL
, &smb_fname
->st
);
1983 len
= srvstr_push(base_data
, flags2
, p
,
1984 fname
, PTR_DIFF(end_data
, p
),
1987 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1988 p
= store_file_unix_basic_info2(conn
, p
,
1989 NULL
, &smb_fname
->st
);
1992 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1993 PTR_DIFF(end_data
, p
), 0);
1994 SIVAL(nameptr
, 0, len
);
1999 len
= PTR_DIFF(p
, pdata
);
2000 pad
= (len
+ (align
-1)) & ~(align
-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p
, 0, pad
- len
);
2016 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2024 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2025 *out_of_space
= true;
2026 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2027 return false; /* Not finished - just out of space */
2030 /* Setup the last entry pointer, as an offset from base_data */
2031 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2032 /* Advance the data pointer to the next slot */
2038 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2039 connection_struct
*conn
,
2040 struct dptr_struct
*dirptr
,
2042 const char *path_mask
,
2045 int requires_resume_key
,
2053 int space_remaining
,
2055 bool *got_exact_match
,
2056 int *_last_entry_off
,
2057 struct ea_list
*name_list
)
2060 const char *mask
= NULL
;
2061 long prev_dirpos
= 0;
2064 struct smb_filename
*smb_fname
= NULL
;
2065 struct smbd_dirptr_lanman2_state state
;
2067 uint64_t last_entry_off
= 0;
2071 state
.info_level
= info_level
;
2072 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2073 state
.has_wild
= dptr_has_wild(dirptr
);
2074 state
.got_exact_match
= false;
2076 *out_of_space
= false;
2077 *got_exact_match
= false;
2079 p
= strrchr_m(path_mask
,'/');
2090 ok
= smbd_dirptr_get_entry(ctx
,
2096 smbd_dirptr_lanman2_match_fn
,
2097 smbd_dirptr_lanman2_mode_fn
,
2107 *got_exact_match
= state
.got_exact_match
;
2109 ok
= smbd_marshall_dir_entry(ctx
,
2114 state
.check_mangled_names
,
2115 requires_resume_key
,
2128 TALLOC_FREE(smb_fname
);
2129 if (*out_of_space
) {
2130 dptr_SeekDir(dirptr
, prev_dirpos
);
2137 *_last_entry_off
= last_entry_off
;
2141 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2142 connection_struct
*conn
,
2143 struct dptr_struct
*dirptr
,
2145 const char *path_mask
,
2148 int requires_resume_key
,
2154 int space_remaining
,
2156 bool *got_exact_match
,
2157 int *last_entry_off
,
2158 struct ea_list
*name_list
)
2160 bool resume_key
= false;
2161 const uint8_t align
= 4;
2162 const bool do_pad
= true;
2164 if (requires_resume_key
) {
2168 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2169 path_mask
, dirtype
, info_level
,
2170 resume_key
, dont_descend
, ask_sharemode
,
2172 ppdata
, base_data
, end_data
,
2174 out_of_space
, got_exact_match
,
2175 last_entry_off
, name_list
);
2178 /****************************************************************************
2179 Reply to a TRANS2_FINDFIRST.
2180 ****************************************************************************/
2182 static void call_trans2findfirst(connection_struct
*conn
,
2183 struct smb_request
*req
,
2184 char **pparams
, int total_params
,
2185 char **ppdata
, int total_data
,
2186 unsigned int max_data_bytes
)
2188 /* We must be careful here that we don't return more than the
2189 allowed number of data bytes. If this means returning fewer than
2190 maxentries then so be it. We assume that the redirector has
2191 enough room for the fixed number of parameter bytes it has
2193 struct smb_filename
*smb_dname
= NULL
;
2194 char *params
= *pparams
;
2195 char *pdata
= *ppdata
;
2199 uint16 findfirst_flags
;
2200 bool close_after_first
;
2202 bool requires_resume_key
;
2204 char *directory
= NULL
;
2207 int last_entry_off
=0;
2211 bool finished
= False
;
2212 bool dont_descend
= False
;
2213 bool out_of_space
= False
;
2214 int space_remaining
;
2215 bool mask_contains_wcard
= False
;
2216 struct ea_list
*ea_list
= NULL
;
2217 NTSTATUS ntstatus
= NT_STATUS_OK
;
2218 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2219 TALLOC_CTX
*ctx
= talloc_tos();
2220 struct dptr_struct
*dirptr
= NULL
;
2221 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2223 if (total_params
< 13) {
2224 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2228 dirtype
= SVAL(params
,0);
2229 maxentries
= SVAL(params
,2);
2230 findfirst_flags
= SVAL(params
,4);
2231 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2232 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2233 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2234 info_level
= SVAL(params
,6);
2236 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2237 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2238 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2239 info_level
, max_data_bytes
));
2242 /* W2K3 seems to treat zero as 1. */
2246 switch (info_level
) {
2247 case SMB_FIND_INFO_STANDARD
:
2248 case SMB_FIND_EA_SIZE
:
2249 case SMB_FIND_EA_LIST
:
2250 case SMB_FIND_FILE_DIRECTORY_INFO
:
2251 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2252 case SMB_FIND_FILE_NAMES_INFO
:
2253 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2254 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2255 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2257 case SMB_FIND_FILE_UNIX
:
2258 case SMB_FIND_FILE_UNIX_INFO2
:
2259 /* Always use filesystem for UNIX mtime query. */
2260 ask_sharemode
= false;
2261 if (!lp_unix_extensions()) {
2262 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2267 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2271 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2272 params
+12, total_params
- 12,
2273 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2274 if (!NT_STATUS_IS_OK(ntstatus
)) {
2275 reply_nterror(req
, ntstatus
);
2279 ntstatus
= filename_convert(ctx
, conn
,
2280 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2283 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2284 &mask_contains_wcard
,
2286 if (!NT_STATUS_IS_OK(ntstatus
)) {
2287 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2288 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2289 ERRSRV
, ERRbadpath
);
2292 reply_nterror(req
, ntstatus
);
2296 mask
= smb_dname
->original_lcomp
;
2298 directory
= smb_dname
->base_name
;
2300 p
= strrchr_m(directory
,'/');
2302 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2303 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2304 mask
= talloc_strdup(ctx
,"*");
2306 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2309 mask_contains_wcard
= True
;
2311 directory
= talloc_strdup(talloc_tos(), "./");
2313 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2320 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2322 if (info_level
== SMB_FIND_EA_LIST
) {
2325 if (total_data
< 4) {
2326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2330 ea_size
= IVAL(pdata
,0);
2331 if (ea_size
!= total_data
) {
2332 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2334 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2338 if (!lp_ea_support(SNUM(conn
))) {
2339 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2343 /* Pull out the list of names. */
2344 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2351 *ppdata
= (char *)SMB_REALLOC(
2352 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2353 if(*ppdata
== NULL
) {
2354 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2358 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2360 /* Realloc the params space */
2361 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2362 if (*pparams
== NULL
) {
2363 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2368 /* Save the wildcard match and attribs we are using on this directory -
2369 needed as lanman2 assumes these are being saved between calls */
2371 ntstatus
= dptr_create(conn
,
2377 mask_contains_wcard
,
2381 if (!NT_STATUS_IS_OK(ntstatus
)) {
2382 reply_nterror(req
, ntstatus
);
2386 dptr_num
= dptr_dnum(dirptr
);
2387 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2389 /* Initialize per TRANS2_FIND_FIRST operation data */
2390 dptr_init_search_op(dirptr
);
2392 /* We don't need to check for VOL here as this is returned by
2393 a different TRANS2 call. */
2395 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2396 directory
,lp_dontdescend(SNUM(conn
))));
2397 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2398 dont_descend
= True
;
2401 space_remaining
= max_data_bytes
;
2402 out_of_space
= False
;
2404 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2405 bool got_exact_match
= False
;
2407 /* this is a heuristic to avoid seeking the dirptr except when
2408 absolutely necessary. It allows for a filename of about 40 chars */
2409 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2410 out_of_space
= True
;
2413 finished
= !get_lanman2_dir_entry(ctx
,
2417 mask
,dirtype
,info_level
,
2418 requires_resume_key
,dont_descend
,
2421 space_remaining
, &out_of_space
,
2423 &last_entry_off
, ea_list
);
2426 if (finished
&& out_of_space
)
2429 if (!finished
&& !out_of_space
)
2433 * As an optimisation if we know we aren't looking
2434 * for a wildcard name (ie. the name matches the wildcard exactly)
2435 * then we can finish on any (first) match.
2436 * This speeds up large directory searches. JRA.
2442 /* Ensure space_remaining never goes -ve. */
2443 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2444 space_remaining
= 0;
2445 out_of_space
= true;
2447 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2451 /* Check if we can close the dirptr */
2452 if(close_after_first
|| (finished
&& close_if_end
)) {
2453 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2454 dptr_close(sconn
, &dptr_num
);
2458 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2459 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2460 * the protocol level is less than NT1. Tested with smbclient. JRA.
2461 * This should fix the OS/2 client bug #2335.
2464 if(numentries
== 0) {
2465 dptr_close(sconn
, &dptr_num
);
2466 if (Protocol
< PROTOCOL_NT1
) {
2467 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2470 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2471 ERRDOS
, ERRbadfile
);
2476 /* At this point pdata points to numentries directory entries. */
2478 /* Set up the return parameter block */
2479 SSVAL(params
,0,dptr_num
);
2480 SSVAL(params
,2,numentries
);
2481 SSVAL(params
,4,finished
);
2482 SSVAL(params
,6,0); /* Never an EA error */
2483 SSVAL(params
,8,last_entry_off
);
2485 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2488 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2489 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2491 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2495 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2496 smb_fn_name(req
->cmd
),
2497 mask
, directory
, dirtype
, numentries
) );
2500 * Force a name mangle here to ensure that the
2501 * mask as an 8.3 name is top of the mangled cache.
2502 * The reasons for this are subtle. Don't remove
2503 * this code unless you know what you are doing
2504 * (see PR#13758). JRA.
2507 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2508 char mangled_name
[13];
2509 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2512 TALLOC_FREE(smb_dname
);
2516 /****************************************************************************
2517 Reply to a TRANS2_FINDNEXT.
2518 ****************************************************************************/
2520 static void call_trans2findnext(connection_struct
*conn
,
2521 struct smb_request
*req
,
2522 char **pparams
, int total_params
,
2523 char **ppdata
, int total_data
,
2524 unsigned int max_data_bytes
)
2526 /* We must be careful here that we don't return more than the
2527 allowed number of data bytes. If this means returning fewer than
2528 maxentries then so be it. We assume that the redirector has
2529 enough room for the fixed number of parameter bytes it has
2531 char *params
= *pparams
;
2532 char *pdata
= *ppdata
;
2538 uint16 findnext_flags
;
2539 bool close_after_request
;
2541 bool requires_resume_key
;
2543 bool mask_contains_wcard
= False
;
2544 char *resume_name
= NULL
;
2545 const char *mask
= NULL
;
2546 const char *directory
= NULL
;
2550 int i
, last_entry_off
=0;
2551 bool finished
= False
;
2552 bool dont_descend
= False
;
2553 bool out_of_space
= False
;
2554 int space_remaining
;
2555 struct ea_list
*ea_list
= NULL
;
2556 NTSTATUS ntstatus
= NT_STATUS_OK
;
2557 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2558 TALLOC_CTX
*ctx
= talloc_tos();
2559 struct dptr_struct
*dirptr
;
2560 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2562 if (total_params
< 13) {
2563 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2567 dptr_num
= SVAL(params
,0);
2568 maxentries
= SVAL(params
,2);
2569 info_level
= SVAL(params
,4);
2570 resume_key
= IVAL(params
,6);
2571 findnext_flags
= SVAL(params
,10);
2572 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2573 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2574 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2575 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2577 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2579 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2580 &mask_contains_wcard
);
2581 if (!NT_STATUS_IS_OK(ntstatus
)) {
2582 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2583 complain (it thinks we're asking for the directory above the shared
2584 path or an invalid name). Catch this as the resume name is only compared, never used in
2585 a file access. JRA. */
2586 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2587 &resume_name
, params
+12,
2591 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2592 reply_nterror(req
, ntstatus
);
2597 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2598 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2599 resume_key = %d resume name = %s continue=%d level = %d\n",
2600 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2601 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2604 /* W2K3 seems to treat zero as 1. */
2608 switch (info_level
) {
2609 case SMB_FIND_INFO_STANDARD
:
2610 case SMB_FIND_EA_SIZE
:
2611 case SMB_FIND_EA_LIST
:
2612 case SMB_FIND_FILE_DIRECTORY_INFO
:
2613 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2614 case SMB_FIND_FILE_NAMES_INFO
:
2615 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2616 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2617 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2619 case SMB_FIND_FILE_UNIX
:
2620 case SMB_FIND_FILE_UNIX_INFO2
:
2621 /* Always use filesystem for UNIX mtime query. */
2622 ask_sharemode
= false;
2623 if (!lp_unix_extensions()) {
2624 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2629 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2633 if (info_level
== SMB_FIND_EA_LIST
) {
2636 if (total_data
< 4) {
2637 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2641 ea_size
= IVAL(pdata
,0);
2642 if (ea_size
!= total_data
) {
2643 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2644 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2645 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2649 if (!lp_ea_support(SNUM(conn
))) {
2650 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2654 /* Pull out the list of names. */
2655 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2662 *ppdata
= (char *)SMB_REALLOC(
2663 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2664 if(*ppdata
== NULL
) {
2665 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2670 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2672 /* Realloc the params space */
2673 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2674 if(*pparams
== NULL
) {
2675 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2681 /* Check that the dptr is valid */
2682 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2683 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2687 directory
= dptr_path(sconn
, dptr_num
);
2689 /* Get the wildcard mask from the dptr */
2690 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2691 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2692 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2698 /* Get the attr mask from the dptr */
2699 dirtype
= dptr_attr(sconn
, dptr_num
);
2701 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2702 dptr_num
, mask
, dirtype
,
2704 dptr_TellDir(dirptr
)));
2706 /* Initialize per TRANS2_FIND_NEXT operation data */
2707 dptr_init_search_op(dirptr
);
2709 /* We don't need to check for VOL here as this is returned by
2710 a different TRANS2 call. */
2712 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2713 directory
,lp_dontdescend(SNUM(conn
))));
2714 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2715 dont_descend
= True
;
2718 space_remaining
= max_data_bytes
;
2719 out_of_space
= False
;
2722 * Seek to the correct position. We no longer use the resume key but
2723 * depend on the last file name instead.
2726 if(*resume_name
&& !continue_bit
) {
2729 long current_pos
= 0;
2731 * Remember, name_to_8_3 is called by
2732 * get_lanman2_dir_entry(), so the resume name
2733 * could be mangled. Ensure we check the unmangled name.
2736 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2737 char *new_resume_name
= NULL
;
2738 mangle_lookup_name_from_8_3(ctx
,
2742 if (new_resume_name
) {
2743 resume_name
= new_resume_name
;
2748 * Fix for NT redirector problem triggered by resume key indexes
2749 * changing between directory scans. We now return a resume key of 0
2750 * and instead look for the filename to continue from (also given
2751 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2752 * findfirst/findnext (as is usual) then the directory pointer
2753 * should already be at the correct place.
2756 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2757 } /* end if resume_name && !continue_bit */
2759 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2760 bool got_exact_match
= False
;
2762 /* this is a heuristic to avoid seeking the dirptr except when
2763 absolutely necessary. It allows for a filename of about 40 chars */
2764 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2765 out_of_space
= True
;
2768 finished
= !get_lanman2_dir_entry(ctx
,
2772 mask
,dirtype
,info_level
,
2773 requires_resume_key
,dont_descend
,
2776 space_remaining
, &out_of_space
,
2778 &last_entry_off
, ea_list
);
2781 if (finished
&& out_of_space
)
2784 if (!finished
&& !out_of_space
)
2788 * As an optimisation if we know we aren't looking
2789 * for a wildcard name (ie. the name matches the wildcard exactly)
2790 * then we can finish on any (first) match.
2791 * This speeds up large directory searches. JRA.
2797 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2800 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2801 smb_fn_name(req
->cmd
),
2802 mask
, directory
, dirtype
, numentries
) );
2804 /* Check if we can close the dirptr */
2805 if(close_after_request
|| (finished
&& close_if_end
)) {
2806 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2807 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2810 /* Set up the return parameter block */
2811 SSVAL(params
,0,numentries
);
2812 SSVAL(params
,2,finished
);
2813 SSVAL(params
,4,0); /* Never an EA error */
2814 SSVAL(params
,6,last_entry_off
);
2816 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2822 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2824 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2828 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2830 SMB_ASSERT(extended_info
!= NULL
);
2832 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2833 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2834 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2835 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2836 #ifdef SAMBA_VERSION_REVISION
2837 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2839 extended_info
->samba_subversion
= 0;
2840 #ifdef SAMBA_VERSION_RC_RELEASE
2841 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2843 #ifdef SAMBA_VERSION_PRE_RELEASE
2844 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2847 #ifdef SAMBA_VERSION_VENDOR_PATCH
2848 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2850 extended_info
->samba_gitcommitdate
= 0;
2851 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2852 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2855 memset(extended_info
->samba_version_string
, 0,
2856 sizeof(extended_info
->samba_version_string
));
2858 snprintf (extended_info
->samba_version_string
,
2859 sizeof(extended_info
->samba_version_string
),
2860 "%s", samba_version_string());
2863 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2864 TALLOC_CTX
*mem_ctx
,
2865 uint16_t info_level
,
2867 unsigned int max_data_bytes
,
2871 char *pdata
, *end_data
;
2872 int data_len
= 0, len
;
2873 const char *vname
= volume_label(SNUM(conn
));
2874 int snum
= SNUM(conn
);
2875 char *fstype
= lp_fstype(SNUM(conn
));
2876 uint32 additional_flags
= 0;
2877 struct smb_filename
*smb_fname_dot
= NULL
;
2882 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2883 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2884 "info level (0x%x) on IPC$.\n",
2885 (unsigned int)info_level
));
2886 return NT_STATUS_ACCESS_DENIED
;
2890 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2892 status
= create_synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
,
2894 if (!NT_STATUS_IS_OK(status
)) {
2898 if(SMB_VFS_STAT(conn
, smb_fname_dot
) != 0) {
2899 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2900 TALLOC_FREE(smb_fname_dot
);
2901 return map_nt_error_from_unix(errno
);
2904 st
= smb_fname_dot
->st
;
2905 TALLOC_FREE(smb_fname_dot
);
2907 *ppdata
= (char *)SMB_REALLOC(
2908 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2909 if (*ppdata
== NULL
) {
2910 return NT_STATUS_NO_MEMORY
;
2914 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2915 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2917 switch (info_level
) {
2918 case SMB_INFO_ALLOCATION
:
2920 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2922 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2923 return map_nt_error_from_unix(errno
);
2926 block_size
= lp_block_size(snum
);
2927 if (bsize
< block_size
) {
2928 uint64_t factor
= block_size
/bsize
;
2933 if (bsize
> block_size
) {
2934 uint64_t factor
= bsize
/block_size
;
2939 bytes_per_sector
= 512;
2940 sectors_per_unit
= bsize
/bytes_per_sector
;
2942 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2943 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2944 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2946 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2947 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2948 SIVAL(pdata
,l1_cUnit
,dsize
);
2949 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2950 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2954 case SMB_INFO_VOLUME
:
2955 /* Return volume name */
2957 * Add volume serial number - hash of a combination of
2958 * the called hostname and the service name.
2960 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2962 * Win2k3 and previous mess this up by sending a name length
2963 * one byte short. I believe only older clients (OS/2 Win9x) use
2964 * this call so try fixing this by adding a terminating null to
2965 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2969 pdata
+l2_vol_szVolLabel
, vname
,
2970 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2971 STR_NOALIGN
|STR_TERMINATE
);
2972 SCVAL(pdata
,l2_vol_cch
,len
);
2973 data_len
= l2_vol_szVolLabel
+ len
;
2974 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2975 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2979 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2980 case SMB_FS_ATTRIBUTE_INFORMATION
:
2982 additional_flags
= 0;
2983 #if defined(HAVE_SYS_QUOTAS)
2984 additional_flags
|= FILE_VOLUME_QUOTAS
;
2987 if(lp_nt_acl_support(SNUM(conn
))) {
2988 additional_flags
|= FILE_PERSISTENT_ACLS
;
2991 /* Capabilities are filled in at connection time through STATVFS call */
2992 additional_flags
|= conn
->fs_capabilities
;
2993 additional_flags
|= lp_parm_int(conn
->params
->service
,
2994 "share", "fake_fscaps",
2997 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2998 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2999 additional_flags
); /* FS ATTRIBUTES */
3001 SIVAL(pdata
,4,255); /* Max filename component length */
3002 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3003 and will think we can't do long filenames */
3004 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3005 PTR_DIFF(end_data
, pdata
+12),
3008 data_len
= 12 + len
;
3011 case SMB_QUERY_FS_LABEL_INFO
:
3012 case SMB_FS_LABEL_INFORMATION
:
3013 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3014 PTR_DIFF(end_data
, pdata
+4), 0);
3019 case SMB_QUERY_FS_VOLUME_INFO
:
3020 case SMB_FS_VOLUME_INFORMATION
:
3023 * Add volume serial number - hash of a combination of
3024 * the called hostname and the service name.
3026 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3027 (str_checksum(get_local_machine_name())<<16));
3029 /* Max label len is 32 characters. */
3030 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3031 PTR_DIFF(end_data
, pdata
+18),
3033 SIVAL(pdata
,12,len
);
3036 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3037 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3040 case SMB_QUERY_FS_SIZE_INFO
:
3041 case SMB_FS_SIZE_INFORMATION
:
3043 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3045 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3046 return map_nt_error_from_unix(errno
);
3048 block_size
= lp_block_size(snum
);
3049 if (bsize
< block_size
) {
3050 uint64_t factor
= block_size
/bsize
;
3055 if (bsize
> block_size
) {
3056 uint64_t factor
= bsize
/block_size
;
3061 bytes_per_sector
= 512;
3062 sectors_per_unit
= bsize
/bytes_per_sector
;
3063 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3064 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3065 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3066 SBIG_UINT(pdata
,0,dsize
);
3067 SBIG_UINT(pdata
,8,dfree
);
3068 SIVAL(pdata
,16,sectors_per_unit
);
3069 SIVAL(pdata
,20,bytes_per_sector
);
3073 case SMB_FS_FULL_SIZE_INFORMATION
:
3075 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3077 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3078 return map_nt_error_from_unix(errno
);
3080 block_size
= lp_block_size(snum
);
3081 if (bsize
< block_size
) {
3082 uint64_t factor
= block_size
/bsize
;
3087 if (bsize
> block_size
) {
3088 uint64_t factor
= bsize
/block_size
;
3093 bytes_per_sector
= 512;
3094 sectors_per_unit
= bsize
/bytes_per_sector
;
3095 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3096 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3097 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3098 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3099 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3100 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3101 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3102 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3106 case SMB_QUERY_FS_DEVICE_INFO
:
3107 case SMB_FS_DEVICE_INFORMATION
:
3109 SIVAL(pdata
,0,0); /* dev type */
3110 SIVAL(pdata
,4,0); /* characteristics */
3113 #ifdef HAVE_SYS_QUOTAS
3114 case SMB_FS_QUOTA_INFORMATION
:
3116 * what we have to send --metze:
3118 * Unknown1: 24 NULL bytes
3119 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3120 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3121 * Quota Flags: 2 byte :
3122 * Unknown3: 6 NULL bytes
3126 * details for Quota Flags:
3128 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3129 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3130 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3131 * 0x0001 Enable Quotas: enable quota for this fs
3135 /* we need to fake up a fsp here,
3136 * because its not send in this call
3139 SMB_NTQUOTA_STRUCT quotas
;
3142 ZERO_STRUCT(quotas
);
3148 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3149 DEBUG(0,("set_user_quota: access_denied "
3150 "service [%s] user [%s]\n",
3151 lp_servicename(SNUM(conn
)),
3152 conn
->server_info
->unix_name
));
3153 return NT_STATUS_ACCESS_DENIED
;
3156 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3157 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3158 return map_nt_error_from_unix(errno
);
3163 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3164 lp_servicename(SNUM(conn
))));
3166 /* Unknown1 24 NULL bytes*/
3167 SBIG_UINT(pdata
,0,(uint64_t)0);
3168 SBIG_UINT(pdata
,8,(uint64_t)0);
3169 SBIG_UINT(pdata
,16,(uint64_t)0);
3171 /* Default Soft Quota 8 bytes */
3172 SBIG_UINT(pdata
,24,quotas
.softlim
);
3174 /* Default Hard Quota 8 bytes */
3175 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3177 /* Quota flag 2 bytes */
3178 SSVAL(pdata
,40,quotas
.qflags
);
3180 /* Unknown3 6 NULL bytes */
3186 #endif /* HAVE_SYS_QUOTAS */
3187 case SMB_FS_OBJECTID_INFORMATION
:
3189 unsigned char objid
[16];
3190 struct smb_extended_info extended_info
;
3191 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3192 samba_extended_info_version (&extended_info
);
3193 SIVAL(pdata
,16,extended_info
.samba_magic
);
3194 SIVAL(pdata
,20,extended_info
.samba_version
);
3195 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3196 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3197 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3203 * Query the version and capabilities of the CIFS UNIX extensions
3207 case SMB_QUERY_CIFS_UNIX_INFO
:
3209 bool large_write
= lp_min_receive_file_size() &&
3210 !srv_is_signing_active(smbd_server_conn
);
3211 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3212 int encrypt_caps
= 0;
3214 if (!lp_unix_extensions()) {
3215 return NT_STATUS_INVALID_LEVEL
;
3218 switch (conn
->encrypt_level
) {
3224 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3227 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3228 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3229 large_write
= false;
3235 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3236 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3238 /* We have POSIX ACLs, pathname, encryption,
3239 * large read/write, and locking capability. */
3241 SBIG_UINT(pdata
,4,((uint64_t)(
3242 CIFS_UNIX_POSIX_ACLS_CAP
|
3243 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3244 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3245 CIFS_UNIX_EXTATTR_CAP
|
3246 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3248 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3250 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3254 case SMB_QUERY_POSIX_FS_INFO
:
3257 vfs_statvfs_struct svfs
;
3259 if (!lp_unix_extensions()) {
3260 return NT_STATUS_INVALID_LEVEL
;
3263 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3267 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3268 SIVAL(pdata
,4,svfs
.BlockSize
);
3269 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3270 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3271 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3272 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3273 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3274 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3275 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3277 } else if (rc
== EOPNOTSUPP
) {
3278 return NT_STATUS_INVALID_LEVEL
;
3279 #endif /* EOPNOTSUPP */
3281 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3282 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3287 case SMB_QUERY_POSIX_WHOAMI
:
3293 if (!lp_unix_extensions()) {
3294 return NT_STATUS_INVALID_LEVEL
;
3297 if (max_data_bytes
< 40) {
3298 return NT_STATUS_BUFFER_TOO_SMALL
;
3301 /* We ARE guest if global_sid_Builtin_Guests is
3302 * in our list of SIDs.
3304 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3305 conn
->server_info
->ptok
)) {
3306 flags
|= SMB_WHOAMI_GUEST
;
3309 /* We are NOT guest if global_sid_Authenticated_Users
3310 * is in our list of SIDs.
3312 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3313 conn
->server_info
->ptok
)) {
3314 flags
&= ~SMB_WHOAMI_GUEST
;
3317 /* NOTE: 8 bytes for UID/GID, irrespective of native
3318 * platform size. This matches
3319 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3321 data_len
= 4 /* flags */
3328 + 4 /* pad/reserved */
3329 + (conn
->server_info
->utok
.ngroups
* 8)
3331 + (conn
->server_info
->ptok
->num_sids
*
3335 SIVAL(pdata
, 0, flags
);
3336 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3338 (uint64_t)conn
->server_info
->utok
.uid
);
3339 SBIG_UINT(pdata
, 16,
3340 (uint64_t)conn
->server_info
->utok
.gid
);
3343 if (data_len
>= max_data_bytes
) {
3344 /* Potential overflow, skip the GIDs and SIDs. */
3346 SIVAL(pdata
, 24, 0); /* num_groups */
3347 SIVAL(pdata
, 28, 0); /* num_sids */
3348 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3349 SIVAL(pdata
, 36, 0); /* reserved */
3355 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3356 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3358 /* We walk the SID list twice, but this call is fairly
3359 * infrequent, and I don't expect that it's performance
3360 * sensitive -- jpeach
3362 for (i
= 0, sid_bytes
= 0;
3363 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3364 sid_bytes
+= ndr_size_dom_sid(
3365 &conn
->server_info
->ptok
->user_sids
[i
],
3370 /* SID list byte count */
3371 SIVAL(pdata
, 32, sid_bytes
);
3373 /* 4 bytes pad/reserved - must be zero */
3374 SIVAL(pdata
, 36, 0);
3378 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3379 SBIG_UINT(pdata
, data_len
,
3380 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3386 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3387 int sid_len
= ndr_size_dom_sid(
3388 &conn
->server_info
->ptok
->user_sids
[i
],
3392 sid_linearize(pdata
+ data_len
, sid_len
,
3393 &conn
->server_info
->ptok
->user_sids
[i
]);
3394 data_len
+= sid_len
;
3400 case SMB_MAC_QUERY_FS_INFO
:
3402 * Thursby MAC extension... ONLY on NTFS filesystems
3403 * once we do streams then we don't need this
3405 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3407 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3412 return NT_STATUS_INVALID_LEVEL
;
3415 *ret_data_len
= data_len
;
3416 return NT_STATUS_OK
;
3419 /****************************************************************************
3420 Reply to a TRANS2_QFSINFO (query filesystem info).
3421 ****************************************************************************/
3423 static void call_trans2qfsinfo(connection_struct
*conn
,
3424 struct smb_request
*req
,
3425 char **pparams
, int total_params
,
3426 char **ppdata
, int total_data
,
3427 unsigned int max_data_bytes
)
3429 char *params
= *pparams
;
3430 uint16_t info_level
;
3434 if (total_params
< 2) {
3435 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3439 info_level
= SVAL(params
,0);
3441 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3442 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3443 DEBUG(0,("call_trans2qfsinfo: encryption required "
3444 "and info level 0x%x sent.\n",
3445 (unsigned int)info_level
));
3446 exit_server_cleanly("encryption required "
3452 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3454 status
= smbd_do_qfsinfo(conn
, req
,
3459 if (!NT_STATUS_IS_OK(status
)) {
3460 reply_nterror(req
, status
);
3464 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3467 DEBUG( 4, ( "%s info_level = %d\n",
3468 smb_fn_name(req
->cmd
), info_level
) );
3473 /****************************************************************************
3474 Reply to a TRANS2_SETFSINFO (set filesystem info).
3475 ****************************************************************************/
3477 static void call_trans2setfsinfo(connection_struct
*conn
,
3478 struct smb_request
*req
,
3479 char **pparams
, int total_params
,
3480 char **ppdata
, int total_data
,
3481 unsigned int max_data_bytes
)
3483 char *pdata
= *ppdata
;
3484 char *params
= *pparams
;
3487 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3490 if (total_params
< 4) {
3491 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3497 info_level
= SVAL(params
,2);
3500 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3501 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3502 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3503 "info level (0x%x) on IPC$.\n",
3504 (unsigned int)info_level
));
3505 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3510 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3511 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3512 DEBUG(0,("call_trans2setfsinfo: encryption required "
3513 "and info level 0x%x sent.\n",
3514 (unsigned int)info_level
));
3515 exit_server_cleanly("encryption required "
3521 switch(info_level
) {
3522 case SMB_SET_CIFS_UNIX_INFO
:
3524 uint16 client_unix_major
;
3525 uint16 client_unix_minor
;
3526 uint32 client_unix_cap_low
;
3527 uint32 client_unix_cap_high
;
3529 if (!lp_unix_extensions()) {
3531 NT_STATUS_INVALID_LEVEL
);
3535 /* There should be 12 bytes of capabilities set. */
3536 if (total_data
< 8) {
3539 NT_STATUS_INVALID_PARAMETER
);
3542 client_unix_major
= SVAL(pdata
,0);
3543 client_unix_minor
= SVAL(pdata
,2);
3544 client_unix_cap_low
= IVAL(pdata
,4);
3545 client_unix_cap_high
= IVAL(pdata
,8);
3546 /* Just print these values for now. */
3547 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3548 cap_low = 0x%x, cap_high = 0x%x\n",
3549 (unsigned int)client_unix_major
,
3550 (unsigned int)client_unix_minor
,
3551 (unsigned int)client_unix_cap_low
,
3552 (unsigned int)client_unix_cap_high
));
3554 /* Here is where we must switch to posix pathname processing... */
3555 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3556 lp_set_posix_pathnames();
3557 mangle_change_to_posix();
3560 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3561 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3562 /* Client that knows how to do posix locks,
3563 * but not posix open/mkdir operations. Set a
3564 * default type for read/write checks. */
3566 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3572 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3575 size_t param_len
= 0;
3576 size_t data_len
= total_data
;
3578 if (!lp_unix_extensions()) {
3581 NT_STATUS_INVALID_LEVEL
);
3585 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3588 NT_STATUS_NOT_SUPPORTED
);
3592 DEBUG( 4,("call_trans2setfsinfo: "
3593 "request transport encryption.\n"));
3595 status
= srv_request_encryption_setup(conn
,
3596 (unsigned char **)ppdata
,
3598 (unsigned char **)pparams
,
3601 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3602 !NT_STATUS_IS_OK(status
)) {
3603 reply_nterror(req
, status
);
3607 send_trans2_replies(conn
, req
,
3614 if (NT_STATUS_IS_OK(status
)) {
3615 /* Server-side transport
3616 * encryption is now *on*. */
3617 status
= srv_encryption_start(conn
);
3618 if (!NT_STATUS_IS_OK(status
)) {
3619 exit_server_cleanly(
3620 "Failure in setting "
3621 "up encrypted transport");
3627 case SMB_FS_QUOTA_INFORMATION
:
3629 files_struct
*fsp
= NULL
;
3630 SMB_NTQUOTA_STRUCT quotas
;
3632 ZERO_STRUCT(quotas
);
3635 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3636 ||!CAN_WRITE(conn
)) {
3637 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3638 lp_servicename(SNUM(conn
)),
3639 conn
->server_info
->unix_name
));
3640 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3644 /* note: normaly there're 48 bytes,
3645 * but we didn't use the last 6 bytes for now
3648 fsp
= file_fsp(req
, SVAL(params
,0));
3650 if (!check_fsp_ntquota_handle(conn
, req
,
3652 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3654 req
, NT_STATUS_INVALID_HANDLE
);
3658 if (total_data
< 42) {
3659 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3663 NT_STATUS_INVALID_PARAMETER
);
3667 /* unknown_1 24 NULL bytes in pdata*/
3669 /* the soft quotas 8 bytes (uint64_t)*/
3670 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3671 #ifdef LARGE_SMB_OFF_T
3672 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3673 #else /* LARGE_SMB_OFF_T */
3674 if ((IVAL(pdata
,28) != 0)&&
3675 ((quotas
.softlim
!= 0xFFFFFFFF)||
3676 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3677 /* more than 32 bits? */
3680 NT_STATUS_INVALID_PARAMETER
);
3683 #endif /* LARGE_SMB_OFF_T */
3685 /* the hard quotas 8 bytes (uint64_t)*/
3686 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3687 #ifdef LARGE_SMB_OFF_T
3688 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3689 #else /* LARGE_SMB_OFF_T */
3690 if ((IVAL(pdata
,36) != 0)&&
3691 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3692 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3693 /* more than 32 bits? */
3696 NT_STATUS_INVALID_PARAMETER
);
3699 #endif /* LARGE_SMB_OFF_T */
3701 /* quota_flags 2 bytes **/
3702 quotas
.qflags
= SVAL(pdata
,40);
3704 /* unknown_2 6 NULL bytes follow*/
3706 /* now set the quotas */
3707 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3708 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3709 reply_nterror(req
, map_nt_error_from_unix(errno
));
3716 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3718 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3724 * sending this reply works fine,
3725 * but I'm not sure it's the same
3726 * like windows do...
3729 reply_outbuf(req
, 10, 0);
3732 #if defined(HAVE_POSIX_ACLS)
3733 /****************************************************************************
3734 Utility function to count the number of entries in a POSIX acl.
3735 ****************************************************************************/
3737 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3739 unsigned int ace_count
= 0;
3740 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3741 SMB_ACL_ENTRY_T entry
;
3743 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3745 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3746 entry_id
= SMB_ACL_NEXT_ENTRY
;
3753 /****************************************************************************
3754 Utility function to marshall a POSIX acl into wire format.
3755 ****************************************************************************/
3757 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3759 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3760 SMB_ACL_ENTRY_T entry
;
3762 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3763 SMB_ACL_TAG_T tagtype
;
3764 SMB_ACL_PERMSET_T permset
;
3765 unsigned char perms
= 0;
3766 unsigned int own_grp
;
3769 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3770 entry_id
= SMB_ACL_NEXT_ENTRY
;
3773 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3774 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3778 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3779 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3783 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3784 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3785 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3787 SCVAL(pdata
,1,perms
);
3790 case SMB_ACL_USER_OBJ
:
3791 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3792 own_grp
= (unsigned int)pst
->st_ex_uid
;
3793 SIVAL(pdata
,2,own_grp
);
3798 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3800 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3803 own_grp
= (unsigned int)*puid
;
3804 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3805 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3806 SIVAL(pdata
,2,own_grp
);
3810 case SMB_ACL_GROUP_OBJ
:
3811 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3812 own_grp
= (unsigned int)pst
->st_ex_gid
;
3813 SIVAL(pdata
,2,own_grp
);
3818 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3820 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3823 own_grp
= (unsigned int)*pgid
;
3824 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3825 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3826 SIVAL(pdata
,2,own_grp
);
3831 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3832 SIVAL(pdata
,2,0xFFFFFFFF);
3833 SIVAL(pdata
,6,0xFFFFFFFF);
3836 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3837 SIVAL(pdata
,2,0xFFFFFFFF);
3838 SIVAL(pdata
,6,0xFFFFFFFF);
3841 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3844 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3851 /****************************************************************************
3852 Store the FILE_UNIX_BASIC info.
3853 ****************************************************************************/
3855 static char *store_file_unix_basic(connection_struct
*conn
,
3858 const SMB_STRUCT_STAT
*psbuf
)
3860 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3861 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3863 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3866 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3869 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3870 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3871 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3874 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3878 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3882 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3885 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3889 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3893 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ex_ino
); /* inode number */
3896 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3900 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3907 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3908 * the chflags(2) (or equivalent) flags.
3910 * XXX: this really should be behind the VFS interface. To do this, we would
3911 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3912 * Each VFS module could then implement its own mapping as appropriate for the
3913 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3915 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3919 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3923 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3927 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3931 { UF_HIDDEN
, EXT_HIDDEN
},
3934 /* Do not remove. We need to guarantee that this array has at least one
3935 * entry to build on HP-UX.
3941 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3942 uint32
*smb_fflags
, uint32
*smb_fmask
)
3946 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3947 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3948 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3949 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3954 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3955 const uint32 smb_fflags
,
3956 const uint32 smb_fmask
,
3959 uint32 max_fmask
= 0;
3962 *stat_fflags
= psbuf
->st_ex_flags
;
3964 /* For each flags requested in smb_fmask, check the state of the
3965 * corresponding flag in smb_fflags and set or clear the matching
3969 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3970 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3971 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3972 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3973 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3975 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3980 /* If smb_fmask is asking to set any bits that are not supported by
3981 * our flag mappings, we should fail.
3983 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3991 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3992 * of file flags and birth (create) time.
3994 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3997 const SMB_STRUCT_STAT
*psbuf
)
3999 uint32 file_flags
= 0;
4000 uint32 flags_mask
= 0;
4002 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4004 /* Create (birth) time 64 bit */
4005 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4008 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4009 SIVAL(pdata
, 0, file_flags
); /* flags */
4010 SIVAL(pdata
, 4, flags_mask
); /* mask */
4016 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4017 const struct stream_struct
*streams
,
4019 unsigned int max_data_bytes
,
4020 unsigned int *data_size
)
4023 unsigned int ofs
= 0;
4025 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4026 unsigned int next_offset
;
4028 smb_ucs2_t
*namebuf
;
4030 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4031 streams
[i
].name
, &namelen
) ||
4034 return NT_STATUS_INVALID_PARAMETER
;
4038 * name_buf is now null-terminated, we need to marshall as not
4044 SIVAL(data
, ofs
+4, namelen
);
4045 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4046 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4047 memcpy(data
+ofs
+24, namebuf
, namelen
);
4048 TALLOC_FREE(namebuf
);
4050 next_offset
= ofs
+ 24 + namelen
;
4052 if (i
== num_streams
-1) {
4053 SIVAL(data
, ofs
, 0);
4056 unsigned int align
= ndr_align_size(next_offset
, 8);
4058 memset(data
+next_offset
, 0, align
);
4059 next_offset
+= align
;
4061 SIVAL(data
, ofs
, next_offset
- ofs
);
4070 return NT_STATUS_OK
;
4073 /****************************************************************************
4074 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4075 ****************************************************************************/
4077 static void call_trans2qpipeinfo(connection_struct
*conn
,
4078 struct smb_request
*req
,
4079 unsigned int tran_call
,
4080 char **pparams
, int total_params
,
4081 char **ppdata
, int total_data
,
4082 unsigned int max_data_bytes
)
4084 char *params
= *pparams
;
4085 char *pdata
= *ppdata
;
4086 unsigned int data_size
= 0;
4087 unsigned int param_size
= 2;
4092 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4096 if (total_params
< 4) {
4097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4101 fsp
= file_fsp(req
, SVAL(params
,0));
4102 if (!fsp_is_np(fsp
)) {
4103 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4107 info_level
= SVAL(params
,2);
4109 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4110 if (*pparams
== NULL
) {
4111 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4116 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4117 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4118 if (*ppdata
== NULL
) {
4119 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4124 switch (info_level
) {
4125 case SMB_FILE_STANDARD_INFORMATION
:
4127 SOFF_T(pdata
,0,4096LL);
4134 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4138 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4144 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4145 TALLOC_CTX
*mem_ctx
,
4146 uint16_t info_level
,
4148 struct smb_filename
*smb_fname
,
4149 bool delete_pending
,
4150 struct timespec write_time_ts
,
4152 struct ea_list
*ea_list
,
4153 int lock_data_count
,
4156 unsigned int max_data_bytes
,
4158 unsigned int *pdata_size
)
4160 char *pdata
= *ppdata
;
4161 char *dstart
, *dend
;
4162 unsigned int data_size
;
4163 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4164 time_t create_time
, mtime
, atime
, c_time
;
4165 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4172 uint64_t file_size
= 0;
4174 uint64_t allocation_size
= 0;
4175 uint64_t file_index
= 0;
4176 uint32_t access_mask
= 0;
4178 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4179 return NT_STATUS_INVALID_LEVEL
;
4182 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4183 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4184 info_level
, max_data_bytes
));
4187 mode
= dos_mode_msdfs(conn
, smb_fname
);
4189 mode
= dos_mode(conn
, smb_fname
);
4192 mode
= FILE_ATTRIBUTE_NORMAL
;
4194 nlink
= psbuf
->st_ex_nlink
;
4196 if (nlink
&& (mode
&aDIR
)) {
4200 if ((nlink
> 0) && delete_pending
) {
4204 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4205 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4206 if (*ppdata
== NULL
) {
4207 return NT_STATUS_NO_MEMORY
;
4211 dend
= dstart
+ data_size
- 1;
4213 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4214 update_stat_ex_mtime(psbuf
, write_time_ts
);
4217 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4218 mtime_ts
= psbuf
->st_ex_mtime
;
4219 atime_ts
= psbuf
->st_ex_atime
;
4220 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4222 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4223 dos_filetime_timespec(&create_time_ts
);
4224 dos_filetime_timespec(&mtime_ts
);
4225 dos_filetime_timespec(&atime_ts
);
4226 dos_filetime_timespec(&ctime_ts
);
4229 create_time
= convert_timespec_to_time_t(create_time_ts
);
4230 mtime
= convert_timespec_to_time_t(mtime_ts
);
4231 atime
= convert_timespec_to_time_t(atime_ts
);
4232 c_time
= convert_timespec_to_time_t(ctime_ts
);
4234 p
= strrchr_m(smb_fname
->base_name
,'/');
4236 base_name
= smb_fname
->base_name
;
4240 /* NT expects the name to be in an exact form of the *full*
4241 filename. See the trans2 torture test */
4242 if (ISDOT(base_name
)) {
4243 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4245 return NT_STATUS_NO_MEMORY
;
4248 dos_fname
= talloc_asprintf(mem_ctx
,
4250 smb_fname
->base_name
);
4252 return NT_STATUS_NO_MEMORY
;
4254 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4255 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4256 smb_fname
->stream_name
);
4258 return NT_STATUS_NO_MEMORY
;
4262 string_replace(dos_fname
, '/', '\\');
4265 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4268 /* Do we have this path open ? */
4270 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4271 fsp1
= file_find_di_first(fileid
);
4272 if (fsp1
&& fsp1
->initial_allocation_size
) {
4273 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4277 if (!(mode
& aDIR
)) {
4278 file_size
= get_file_size_stat(psbuf
);
4282 pos
= fsp
->fh
->position_information
;
4286 access_mask
= fsp
->access_mask
;
4288 /* GENERIC_EXECUTE mapping from Windows */
4289 access_mask
= 0x12019F;
4292 /* This should be an index number - looks like
4295 I think this causes us to fail the IFSKIT
4296 BasicFileInformationTest. -tpot */
4297 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
4298 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
4300 switch (info_level
) {
4301 case SMB_INFO_STANDARD
:
4302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4304 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4305 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4306 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4307 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4308 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4309 SSVAL(pdata
,l1_attrFile
,mode
);
4312 case SMB_INFO_QUERY_EA_SIZE
:
4314 unsigned int ea_size
=
4315 estimate_ea_size(conn
, fsp
,
4316 smb_fname
->base_name
);
4317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4319 srv_put_dos_date2(pdata
,0,create_time
);
4320 srv_put_dos_date2(pdata
,4,atime
);
4321 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4322 SIVAL(pdata
,12,(uint32
)file_size
);
4323 SIVAL(pdata
,16,(uint32
)allocation_size
);
4324 SSVAL(pdata
,20,mode
);
4325 SIVAL(pdata
,22,ea_size
);
4329 case SMB_INFO_IS_NAME_VALID
:
4330 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4332 /* os/2 needs this ? really ?*/
4333 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4335 /* This is only reached for qpathinfo */
4339 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4341 size_t total_ea_len
= 0;
4342 struct ea_list
*ea_file_list
= NULL
;
4344 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4347 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4348 smb_fname
->base_name
,
4350 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4352 if (!ea_list
|| (total_ea_len
> data_size
)) {
4354 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4358 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4362 case SMB_INFO_QUERY_ALL_EAS
:
4364 /* We have data_size bytes to put EA's into. */
4365 size_t total_ea_len
= 0;
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4369 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4370 smb_fname
->base_name
,
4372 if (!ea_list
|| (total_ea_len
> data_size
)) {
4374 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4378 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4382 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4384 /* This is FileFullEaInformation - 0xF which maps to
4385 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4387 /* We have data_size bytes to put EA's into. */
4388 size_t total_ea_len
= 0;
4389 struct ea_list
*ea_file_list
= NULL
;
4391 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4393 /*TODO: add filtering and index handling */
4396 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4397 smb_fname
->base_name
,
4399 if (!ea_file_list
) {
4400 return NT_STATUS_NO_EAS_ON_FILE
;
4403 status
= fill_ea_chained_buffer(mem_ctx
,
4407 conn
, ea_file_list
);
4408 if (!NT_STATUS_IS_OK(status
)) {
4414 case SMB_FILE_BASIC_INFORMATION
:
4415 case SMB_QUERY_FILE_BASIC_INFO
:
4417 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4419 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4425 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4426 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4427 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4428 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4429 SIVAL(pdata
,32,mode
);
4431 DEBUG(5,("SMB_QFBI - "));
4432 DEBUG(5,("create: %s ", ctime(&create_time
)));
4433 DEBUG(5,("access: %s ", ctime(&atime
)));
4434 DEBUG(5,("write: %s ", ctime(&mtime
)));
4435 DEBUG(5,("change: %s ", ctime(&c_time
)));
4436 DEBUG(5,("mode: %x\n", mode
));
4439 case SMB_FILE_STANDARD_INFORMATION
:
4440 case SMB_QUERY_FILE_STANDARD_INFO
:
4442 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4444 SOFF_T(pdata
,0,allocation_size
);
4445 SOFF_T(pdata
,8,file_size
);
4446 SIVAL(pdata
,16,nlink
);
4447 SCVAL(pdata
,20,delete_pending
?1:0);
4448 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4449 SSVAL(pdata
,22,0); /* Padding. */
4452 case SMB_FILE_EA_INFORMATION
:
4453 case SMB_QUERY_FILE_EA_INFO
:
4455 unsigned int ea_size
=
4456 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4457 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4459 SIVAL(pdata
,0,ea_size
);
4463 /* Get the 8.3 name - used if NT SMB was negotiated. */
4464 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4465 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4468 char mangled_name
[13];
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4470 if (!name_to_8_3(base_name
,mangled_name
,
4471 True
,conn
->params
)) {
4472 return NT_STATUS_NO_MEMORY
;
4474 len
= srvstr_push(dstart
, flags2
,
4475 pdata
+4, mangled_name
,
4476 PTR_DIFF(dend
, pdata
+4),
4478 data_size
= 4 + len
;
4483 case SMB_QUERY_FILE_NAME_INFO
:
4487 this must be *exactly* right for ACLs on mapped drives to work
4489 len
= srvstr_push(dstart
, flags2
,
4491 PTR_DIFF(dend
, pdata
+4),
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4494 data_size
= 4 + len
;
4499 case SMB_FILE_ALLOCATION_INFORMATION
:
4500 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4503 SOFF_T(pdata
,0,allocation_size
);
4506 case SMB_FILE_END_OF_FILE_INFORMATION
:
4507 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4510 SOFF_T(pdata
,0,file_size
);
4513 case SMB_QUERY_FILE_ALL_INFO
:
4514 case SMB_FILE_ALL_INFORMATION
:
4517 unsigned int ea_size
=
4518 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4520 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4521 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4522 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4523 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4524 SIVAL(pdata
,32,mode
);
4525 SIVAL(pdata
,36,0); /* padding. */
4527 SOFF_T(pdata
,0,allocation_size
);
4528 SOFF_T(pdata
,8,file_size
);
4529 SIVAL(pdata
,16,nlink
);
4530 SCVAL(pdata
,20,delete_pending
);
4531 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4534 SIVAL(pdata
,0,ea_size
);
4535 pdata
+= 4; /* EA info */
4536 len
= srvstr_push(dstart
, flags2
,
4538 PTR_DIFF(dend
, pdata
+4),
4542 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4546 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4549 unsigned int ea_size
=
4550 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4552 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4553 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4554 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4555 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4556 SIVAL(pdata
, 0x20, mode
);
4557 SIVAL(pdata
, 0x24, 0); /* padding. */
4558 SBVAL(pdata
, 0x28, allocation_size
);
4559 SBVAL(pdata
, 0x30, file_size
);
4560 SIVAL(pdata
, 0x38, nlink
);
4561 SCVAL(pdata
, 0x3C, delete_pending
);
4562 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4563 SSVAL(pdata
, 0x3E, 0); /* padding */
4564 SBVAL(pdata
, 0x40, file_index
);
4565 SIVAL(pdata
, 0x48, ea_size
);
4566 SIVAL(pdata
, 0x4C, access_mask
);
4567 SBVAL(pdata
, 0x50, pos
);
4568 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4569 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4573 len
= srvstr_push(dstart
, flags2
,
4575 PTR_DIFF(dend
, pdata
+4),
4579 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4582 case SMB_FILE_INTERNAL_INFORMATION
:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4585 SBVAL(pdata
, 0, file_index
);
4589 case SMB_FILE_ACCESS_INFORMATION
:
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4591 SIVAL(pdata
, 0, access_mask
);
4595 case SMB_FILE_NAME_INFORMATION
:
4596 /* Pathname with leading '\'. */
4599 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4601 SIVAL(pdata
,0,byte_len
);
4602 data_size
= 4 + byte_len
;
4606 case SMB_FILE_DISPOSITION_INFORMATION
:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4609 SCVAL(pdata
,0,delete_pending
);
4612 case SMB_FILE_POSITION_INFORMATION
:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4615 SOFF_T(pdata
,0,pos
);
4618 case SMB_FILE_MODE_INFORMATION
:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4620 SIVAL(pdata
,0,mode
);
4624 case SMB_FILE_ALIGNMENT_INFORMATION
:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4626 SIVAL(pdata
,0,0); /* No alignment needed. */
4631 * NT4 server just returns "invalid query" to this - if we try
4632 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4635 /* The first statement above is false - verified using Thursby
4636 * client against NT4 -- gcolley.
4638 case SMB_QUERY_FILE_STREAM_INFO
:
4639 case SMB_FILE_STREAM_INFORMATION
: {
4640 unsigned int num_streams
;
4641 struct stream_struct
*streams
;
4643 DEBUG(10,("smbd_do_qfilepathinfo: "
4644 "SMB_FILE_STREAM_INFORMATION\n"));
4646 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4647 return NT_STATUS_INVALID_PARAMETER
;
4650 status
= SMB_VFS_STREAMINFO(
4651 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4652 &num_streams
, &streams
);
4654 if (!NT_STATUS_IS_OK(status
)) {
4655 DEBUG(10, ("could not get stream info: %s\n",
4656 nt_errstr(status
)));
4660 status
= marshall_stream_info(num_streams
, streams
,
4661 pdata
, max_data_bytes
,
4664 if (!NT_STATUS_IS_OK(status
)) {
4665 DEBUG(10, ("marshall_stream_info failed: %s\n",
4666 nt_errstr(status
)));
4670 TALLOC_FREE(streams
);
4674 case SMB_QUERY_COMPRESSION_INFO
:
4675 case SMB_FILE_COMPRESSION_INFORMATION
:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4677 SOFF_T(pdata
,0,file_size
);
4678 SIVAL(pdata
,8,0); /* ??? */
4679 SIVAL(pdata
,12,0); /* ??? */
4683 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4685 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4686 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4687 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4688 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4689 SOFF_T(pdata
,32,allocation_size
);
4690 SOFF_T(pdata
,40,file_size
);
4691 SIVAL(pdata
,48,mode
);
4692 SIVAL(pdata
,52,0); /* ??? */
4696 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4698 SIVAL(pdata
,0,mode
);
4704 * CIFS UNIX Extensions.
4707 case SMB_QUERY_FILE_UNIX_BASIC
:
4709 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4710 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4714 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4716 for (i
=0; i
<100; i
++)
4717 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4723 case SMB_QUERY_FILE_UNIX_INFO2
:
4725 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4726 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4730 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4732 for (i
=0; i
<100; i
++)
4733 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4739 case SMB_QUERY_FILE_UNIX_LINK
:
4742 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4745 return NT_STATUS_NO_MEMORY
;
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4750 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4751 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4754 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4756 len
= SMB_VFS_READLINK(conn
,
4757 smb_fname
->base_name
,
4760 return map_nt_error_from_unix(errno
);
4763 len
= srvstr_push(dstart
, flags2
,
4765 PTR_DIFF(dend
, pdata
),
4768 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4773 #if defined(HAVE_POSIX_ACLS)
4774 case SMB_QUERY_POSIX_ACL
:
4776 SMB_ACL_T file_acl
= NULL
;
4777 SMB_ACL_T def_acl
= NULL
;
4778 uint16 num_file_acls
= 0;
4779 uint16 num_def_acls
= 0;
4781 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4782 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4785 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4786 smb_fname
->base_name
,
4787 SMB_ACL_TYPE_ACCESS
);
4790 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4791 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4792 "not implemented on "
4793 "filesystem containing %s\n",
4794 smb_fname
->base_name
));
4795 return NT_STATUS_NOT_IMPLEMENTED
;
4798 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4799 if (fsp
&& fsp
->is_directory
) {
4801 SMB_VFS_SYS_ACL_GET_FILE(
4803 fsp
->fsp_name
->base_name
,
4804 SMB_ACL_TYPE_DEFAULT
);
4807 SMB_VFS_SYS_ACL_GET_FILE(
4809 smb_fname
->base_name
,
4810 SMB_ACL_TYPE_DEFAULT
);
4812 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4815 num_file_acls
= count_acl_entries(conn
, file_acl
);
4816 num_def_acls
= count_acl_entries(conn
, def_acl
);
4818 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4819 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4821 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4822 SMB_POSIX_ACL_HEADER_SIZE
) ));
4824 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4827 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4829 return NT_STATUS_BUFFER_TOO_SMALL
;
4832 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4833 SSVAL(pdata
,2,num_file_acls
);
4834 SSVAL(pdata
,4,num_def_acls
);
4835 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4837 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4840 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4842 return NT_STATUS_INTERNAL_ERROR
;
4844 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4846 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4851 return NT_STATUS_INTERNAL_ERROR
;
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4860 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4866 case SMB_QUERY_POSIX_LOCK
:
4871 enum brl_type lock_type
;
4873 /* We need an open file with a real fd for this. */
4874 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4875 return NT_STATUS_INVALID_LEVEL
;
4878 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4879 return NT_STATUS_INVALID_PARAMETER
;
4882 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4883 case POSIX_LOCK_TYPE_READ
:
4884 lock_type
= READ_LOCK
;
4886 case POSIX_LOCK_TYPE_WRITE
:
4887 lock_type
= WRITE_LOCK
;
4889 case POSIX_LOCK_TYPE_UNLOCK
:
4891 /* There's no point in asking for an unlock... */
4892 return NT_STATUS_INVALID_PARAMETER
;
4895 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4896 #if defined(HAVE_LONGLONG)
4897 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4898 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4899 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4900 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4901 #else /* HAVE_LONGLONG */
4902 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4903 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4904 #endif /* HAVE_LONGLONG */
4906 status
= query_lock(fsp
,
4913 if (ERROR_WAS_LOCK_DENIED(status
)) {
4914 /* Here we need to report who has it locked... */
4915 data_size
= POSIX_LOCK_DATA_SIZE
;
4917 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4918 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4919 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4920 #if defined(HAVE_LONGLONG)
4921 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4922 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4923 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4924 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4925 #else /* HAVE_LONGLONG */
4926 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4927 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4928 #endif /* HAVE_LONGLONG */
4930 } else if (NT_STATUS_IS_OK(status
)) {
4931 /* For success we just return a copy of what we sent
4932 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4933 data_size
= POSIX_LOCK_DATA_SIZE
;
4934 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4935 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4943 return NT_STATUS_INVALID_LEVEL
;
4946 *pdata_size
= data_size
;
4947 return NT_STATUS_OK
;
4950 /****************************************************************************
4951 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4952 file name or file id).
4953 ****************************************************************************/
4955 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4956 struct smb_request
*req
,
4957 unsigned int tran_call
,
4958 char **pparams
, int total_params
,
4959 char **ppdata
, int total_data
,
4960 unsigned int max_data_bytes
)
4962 char *params
= *pparams
;
4963 char *pdata
= *ppdata
;
4965 unsigned int data_size
= 0;
4966 unsigned int param_size
= 2;
4967 struct smb_filename
*smb_fname
= NULL
;
4968 bool delete_pending
= False
;
4969 struct timespec write_time_ts
;
4970 files_struct
*fsp
= NULL
;
4971 struct file_id fileid
;
4972 struct ea_list
*ea_list
= NULL
;
4973 int lock_data_count
= 0;
4974 char *lock_data
= NULL
;
4975 bool ms_dfs_link
= false;
4976 NTSTATUS status
= NT_STATUS_OK
;
4979 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4983 ZERO_STRUCT(write_time_ts
);
4985 if (tran_call
== TRANSACT2_QFILEINFO
) {
4986 if (total_params
< 4) {
4987 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4992 call_trans2qpipeinfo(conn
, req
, tran_call
,
4993 pparams
, total_params
,
4999 fsp
= file_fsp(req
, SVAL(params
,0));
5000 info_level
= SVAL(params
,2);
5002 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5004 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5005 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5009 /* Initial check for valid fsp ptr. */
5010 if (!check_fsp_open(conn
, req
, fsp
)) {
5014 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5016 if (!NT_STATUS_IS_OK(status
)) {
5017 reply_nterror(req
, status
);
5021 if(fsp
->fake_file_handle
) {
5023 * This is actually for the QUOTA_FAKE_FILE --metze
5026 /* We know this name is ok, it's already passed the checks. */
5028 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5030 * This is actually a QFILEINFO on a directory
5031 * handle (returned from an NT SMB). NT5.0 seems
5032 * to do this call. JRA.
5035 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5036 /* Always do lstat for UNIX calls. */
5037 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5038 DEBUG(3,("call_trans2qfilepathinfo: "
5039 "SMB_VFS_LSTAT of %s failed "
5041 smb_fname_str_dbg(smb_fname
),
5044 map_nt_error_from_unix(errno
));
5047 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5048 DEBUG(3,("call_trans2qfilepathinfo: "
5049 "SMB_VFS_STAT of %s failed (%s)\n",
5050 smb_fname_str_dbg(smb_fname
),
5053 map_nt_error_from_unix(errno
));
5057 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5058 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5061 * Original code - this is an open file.
5063 if (!check_fsp(conn
, req
, fsp
)) {
5067 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5068 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5069 fsp
->fnum
, strerror(errno
)));
5071 map_nt_error_from_unix(errno
));
5074 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5075 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5082 if (total_params
< 7) {
5083 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5087 info_level
= SVAL(params
,0);
5089 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5091 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5092 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5096 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5098 STR_TERMINATE
, &status
);
5099 if (!NT_STATUS_IS_OK(status
)) {
5100 reply_nterror(req
, status
);
5104 status
= filename_convert(req
,
5106 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5111 if (!NT_STATUS_IS_OK(status
)) {
5112 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5113 reply_botherror(req
,
5114 NT_STATUS_PATH_NOT_COVERED
,
5115 ERRSRV
, ERRbadpath
);
5118 reply_nterror(req
, status
);
5122 /* If this is a stream, check if there is a delete_pending. */
5123 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5124 && is_ntfs_stream_smb_fname(smb_fname
)) {
5125 struct smb_filename
*smb_fname_base
= NULL
;
5127 /* Create an smb_filename with stream_name == NULL. */
5129 create_synthetic_smb_fname(talloc_tos(),
5130 smb_fname
->base_name
,
5133 if (!NT_STATUS_IS_OK(status
)) {
5134 reply_nterror(req
, status
);
5138 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5139 /* Always do lstat for UNIX calls. */
5140 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5141 DEBUG(3,("call_trans2qfilepathinfo: "
5142 "SMB_VFS_LSTAT of %s failed "
5144 smb_fname_str_dbg(smb_fname_base
),
5146 TALLOC_FREE(smb_fname_base
);
5148 map_nt_error_from_unix(errno
));
5152 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5153 DEBUG(3,("call_trans2qfilepathinfo: "
5154 "fileinfo of %s failed "
5156 smb_fname_str_dbg(smb_fname_base
),
5158 TALLOC_FREE(smb_fname_base
);
5160 map_nt_error_from_unix(errno
));
5165 fileid
= vfs_file_id_from_sbuf(conn
,
5166 &smb_fname_base
->st
);
5167 TALLOC_FREE(smb_fname_base
);
5168 get_file_infos(fileid
, &delete_pending
, NULL
);
5169 if (delete_pending
) {
5170 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5175 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5176 /* Always do lstat for UNIX calls. */
5177 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "SMB_VFS_LSTAT of %s failed (%s)\n",
5180 smb_fname_str_dbg(smb_fname
),
5183 map_nt_error_from_unix(errno
));
5187 } else if (!VALID_STAT(smb_fname
->st
) &&
5188 SMB_VFS_STAT(conn
, smb_fname
) &&
5189 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5190 ms_dfs_link
= check_msdfs_link(conn
,
5191 smb_fname
->base_name
,
5195 DEBUG(3,("call_trans2qfilepathinfo: "
5196 "SMB_VFS_STAT of %s failed (%s)\n",
5197 smb_fname_str_dbg(smb_fname
),
5200 map_nt_error_from_unix(errno
));
5205 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5206 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5207 if (delete_pending
) {
5208 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5213 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5214 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5215 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5217 /* Pull out any data sent here before we realloc. */
5218 switch (info_level
) {
5219 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5221 /* Pull any EA list from the data portion. */
5224 if (total_data
< 4) {
5226 req
, NT_STATUS_INVALID_PARAMETER
);
5229 ea_size
= IVAL(pdata
,0);
5231 if (total_data
> 0 && ea_size
!= total_data
) {
5232 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5233 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5235 req
, NT_STATUS_INVALID_PARAMETER
);
5239 if (!lp_ea_support(SNUM(conn
))) {
5240 reply_doserror(req
, ERRDOS
,
5241 ERReasnotsupported
);
5245 /* Pull out the list of names. */
5246 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5249 req
, NT_STATUS_INVALID_PARAMETER
);
5255 case SMB_QUERY_POSIX_LOCK
:
5257 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5258 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5262 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5264 req
, NT_STATUS_INVALID_PARAMETER
);
5268 /* Copy the lock range data. */
5269 lock_data
= (char *)TALLOC_MEMDUP(
5270 req
, pdata
, total_data
);
5272 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5275 lock_data_count
= total_data
;
5281 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5282 if (*pparams
== NULL
) {
5283 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5290 * draft-leach-cifs-v1-spec-02.txt
5291 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5294 * The requested information is placed in the Data portion of the
5295 * transaction response. For the information levels greater than 0x100,
5296 * the transaction response has 1 parameter word which should be
5297 * ignored by the client.
5299 * However Windows only follows this rule for the IS_NAME_VALID call.
5301 switch (info_level
) {
5302 case SMB_INFO_IS_NAME_VALID
:
5307 if ((info_level
& 0xFF00) == 0xFF00) {
5309 * We use levels that start with 0xFF00
5310 * internally to represent SMB2 specific levels
5312 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5316 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5318 delete_pending
, write_time_ts
,
5319 ms_dfs_link
, ea_list
,
5320 lock_data_count
, lock_data
,
5321 req
->flags2
, max_data_bytes
,
5322 ppdata
, &data_size
);
5323 if (!NT_STATUS_IS_OK(status
)) {
5324 reply_nterror(req
, status
);
5328 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5334 /****************************************************************************
5335 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5337 ****************************************************************************/
5339 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5340 connection_struct
*conn
,
5341 const struct smb_filename
*smb_fname_old
,
5342 const struct smb_filename
*smb_fname_new
)
5344 NTSTATUS status
= NT_STATUS_OK
;
5346 /* source must already exist. */
5347 if (!VALID_STAT(smb_fname_old
->st
)) {
5348 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5351 /* Disallow if newname already exists. */
5352 if (VALID_STAT(smb_fname_new
->st
)) {
5353 return NT_STATUS_OBJECT_NAME_COLLISION
;
5356 /* No links from a directory. */
5357 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5358 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5361 /* Setting a hardlink to/from a stream isn't currently supported. */
5362 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5363 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5364 return NT_STATUS_INVALID_PARAMETER
;
5367 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5368 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5370 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5371 smb_fname_new
->base_name
) != 0) {
5372 status
= map_nt_error_from_unix(errno
);
5373 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5374 nt_errstr(status
), smb_fname_old
->base_name
,
5375 smb_fname_new
->base_name
));
5380 /****************************************************************************
5381 Deal with setting the time from any of the setfilepathinfo functions.
5382 ****************************************************************************/
5384 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5386 const struct smb_filename
*smb_fname
,
5387 struct smb_file_time
*ft
,
5388 bool setting_write_time
)
5390 struct smb_filename
*smb_fname_base
= NULL
;
5392 FILE_NOTIFY_CHANGE_LAST_ACCESS
5393 |FILE_NOTIFY_CHANGE_LAST_WRITE
5394 |FILE_NOTIFY_CHANGE_CREATION
;
5397 if (!VALID_STAT(smb_fname
->st
)) {
5398 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5401 /* get some defaults (no modifications) if any info is zero or -1. */
5402 if (null_timespec(ft
->create_time
)) {
5403 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5406 if (null_timespec(ft
->atime
)) {
5407 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5410 if (null_timespec(ft
->mtime
)) {
5411 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5414 if (!setting_write_time
) {
5415 /* ft->mtime comes from change time, not write time. */
5416 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5419 /* Ensure the resolution is the correct for
5420 * what we can store on this filesystem. */
5422 round_timespec(conn
->ts_res
, &ft
->create_time
);
5423 round_timespec(conn
->ts_res
, &ft
->ctime
);
5424 round_timespec(conn
->ts_res
, &ft
->atime
);
5425 round_timespec(conn
->ts_res
, &ft
->mtime
);
5427 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5428 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5429 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5430 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5431 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5432 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5433 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5434 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5436 if (setting_write_time
) {
5438 * This was a Windows setfileinfo on an open file.
5439 * NT does this a lot. We also need to
5440 * set the time here, as it can be read by
5441 * FindFirst/FindNext and with the patch for bug #2045
5442 * in smbd/fileio.c it ensures that this timestamp is
5443 * kept sticky even after a write. We save the request
5444 * away and will set it on file close and after a write. JRA.
5447 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5448 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5451 if (fsp
->base_fsp
) {
5452 set_sticky_write_time_fsp(fsp
->base_fsp
,
5455 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5458 set_sticky_write_time_path(
5459 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5464 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5466 /* Always call ntimes on the base, even if a stream was passed in. */
5467 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5468 NULL
, &smb_fname
->st
,
5470 if (!NT_STATUS_IS_OK(status
)) {
5474 if(file_ntimes(conn
, smb_fname_base
, ft
)!=0) {
5475 TALLOC_FREE(smb_fname_base
);
5476 return map_nt_error_from_unix(errno
);
5478 TALLOC_FREE(smb_fname_base
);
5480 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5481 smb_fname
->base_name
);
5482 return NT_STATUS_OK
;
5485 /****************************************************************************
5486 Deal with setting the dosmode from any of the setfilepathinfo functions.
5487 ****************************************************************************/
5489 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5490 const struct smb_filename
*smb_fname
,
5493 struct smb_filename
*smb_fname_base
= NULL
;
5496 if (!VALID_STAT(smb_fname
->st
)) {
5497 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5500 /* Always operate on the base_name, even if a stream was passed in. */
5501 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5502 NULL
, &smb_fname
->st
,
5504 if (!NT_STATUS_IS_OK(status
)) {
5509 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5516 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5518 /* check the mode isn't different, before changing it */
5519 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5520 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5521 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5522 (unsigned int)dosmode
));
5524 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5526 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5528 smb_fname_str_dbg(smb_fname_base
),
5530 status
= map_nt_error_from_unix(errno
);
5534 status
= NT_STATUS_OK
;
5536 TALLOC_FREE(smb_fname_base
);
5540 /****************************************************************************
5541 Deal with setting the size from any of the setfilepathinfo functions.
5542 ****************************************************************************/
5544 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5545 struct smb_request
*req
,
5547 const struct smb_filename
*smb_fname
,
5548 const SMB_STRUCT_STAT
*psbuf
,
5551 NTSTATUS status
= NT_STATUS_OK
;
5552 struct smb_filename
*smb_fname_tmp
= NULL
;
5553 files_struct
*new_fsp
= NULL
;
5555 if (!VALID_STAT(*psbuf
)) {
5556 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5559 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5561 if (size
== get_file_size_stat(psbuf
)) {
5562 return NT_STATUS_OK
;
5565 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5566 smb_fname_str_dbg(smb_fname
), (double)size
));
5568 if (fsp
&& fsp
->fh
->fd
!= -1) {
5569 /* Handle based call. */
5570 if (vfs_set_filelen(fsp
, size
) == -1) {
5571 return map_nt_error_from_unix(errno
);
5573 trigger_write_time_update_immediate(fsp
);
5574 return NT_STATUS_OK
;
5577 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5578 if (!NT_STATUS_IS_OK(status
)) {
5582 smb_fname_tmp
->st
= *psbuf
;
5584 status
= SMB_VFS_CREATE_FILE(
5587 0, /* root_dir_fid */
5588 smb_fname_tmp
, /* fname */
5589 FILE_WRITE_ATTRIBUTES
, /* access_mask */
5590 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5592 FILE_OPEN
, /* create_disposition*/
5593 0, /* create_options */
5594 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5595 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5596 0, /* allocation_size */
5599 &new_fsp
, /* result */
5602 TALLOC_FREE(smb_fname_tmp
);
5604 if (!NT_STATUS_IS_OK(status
)) {
5605 /* NB. We check for open_was_deferred in the caller. */
5609 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5610 status
= map_nt_error_from_unix(errno
);
5611 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5615 trigger_write_time_update_immediate(new_fsp
);
5616 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5617 return NT_STATUS_OK
;
5620 /****************************************************************************
5621 Deal with SMB_INFO_SET_EA.
5622 ****************************************************************************/
5624 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5628 const struct smb_filename
*smb_fname
)
5630 struct ea_list
*ea_list
= NULL
;
5631 TALLOC_CTX
*ctx
= NULL
;
5632 NTSTATUS status
= NT_STATUS_OK
;
5634 if (total_data
< 10) {
5636 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5637 length. They seem to have no effect. Bug #3212. JRA */
5639 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5640 /* We're done. We only get EA info in this call. */
5641 return NT_STATUS_OK
;
5644 return NT_STATUS_INVALID_PARAMETER
;
5647 if (IVAL(pdata
,0) > total_data
) {
5648 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5649 IVAL(pdata
,0), (unsigned int)total_data
));
5650 return NT_STATUS_INVALID_PARAMETER
;
5654 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5656 return NT_STATUS_INVALID_PARAMETER
;
5658 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5663 /****************************************************************************
5664 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5665 ****************************************************************************/
5667 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5672 struct ea_list
*ea_list
= NULL
;
5676 return NT_STATUS_INVALID_HANDLE
;
5679 if (!lp_ea_support(SNUM(conn
))) {
5680 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5681 "EA's not supported.\n",
5682 (unsigned int)total_data
));
5683 return NT_STATUS_EAS_NOT_SUPPORTED
;
5686 if (total_data
< 10) {
5687 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5689 (unsigned int)total_data
));
5690 return NT_STATUS_INVALID_PARAMETER
;
5693 ea_list
= read_nttrans_ea_list(talloc_tos(),
5698 return NT_STATUS_INVALID_PARAMETER
;
5700 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5702 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5703 smb_fname_str_dbg(fsp
->fsp_name
),
5704 nt_errstr(status
) ));
5710 /****************************************************************************
5711 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5712 ****************************************************************************/
5714 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5718 const struct smb_filename
*smb_fname
)
5720 NTSTATUS status
= NT_STATUS_OK
;
5721 bool delete_on_close
;
5724 if (total_data
< 1) {
5725 return NT_STATUS_INVALID_PARAMETER
;
5729 return NT_STATUS_INVALID_HANDLE
;
5732 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5733 dosmode
= dos_mode(conn
, smb_fname
);
5735 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5736 "delete_on_close = %u\n",
5737 smb_fname_str_dbg(smb_fname
),
5738 (unsigned int)dosmode
,
5739 (unsigned int)delete_on_close
));
5741 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
5743 if (!NT_STATUS_IS_OK(status
)) {
5747 /* The set is across all open files on this dev/inode pair. */
5748 if (!set_delete_on_close(fsp
, delete_on_close
,
5749 &conn
->server_info
->utok
)) {
5750 return NT_STATUS_ACCESS_DENIED
;
5752 return NT_STATUS_OK
;
5755 /****************************************************************************
5756 Deal with SMB_FILE_POSITION_INFORMATION.
5757 ****************************************************************************/
5759 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5764 uint64_t position_information
;
5766 if (total_data
< 8) {
5767 return NT_STATUS_INVALID_PARAMETER
;
5771 /* Ignore on pathname based set. */
5772 return NT_STATUS_OK
;
5775 position_information
= (uint64_t)IVAL(pdata
,0);
5776 #ifdef LARGE_SMB_OFF_T
5777 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5778 #else /* LARGE_SMB_OFF_T */
5779 if (IVAL(pdata
,4) != 0) {
5780 /* more than 32 bits? */
5781 return NT_STATUS_INVALID_PARAMETER
;
5783 #endif /* LARGE_SMB_OFF_T */
5785 DEBUG(10,("smb_file_position_information: Set file position "
5786 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5787 (double)position_information
));
5788 fsp
->fh
->position_information
= position_information
;
5789 return NT_STATUS_OK
;
5792 /****************************************************************************
5793 Deal with SMB_FILE_MODE_INFORMATION.
5794 ****************************************************************************/
5796 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5802 if (total_data
< 4) {
5803 return NT_STATUS_INVALID_PARAMETER
;
5805 mode
= IVAL(pdata
,0);
5806 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5807 return NT_STATUS_INVALID_PARAMETER
;
5809 return NT_STATUS_OK
;
5812 /****************************************************************************
5813 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5814 ****************************************************************************/
5816 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5817 struct smb_request
*req
,
5820 const struct smb_filename
*smb_fname
)
5822 char *link_target
= NULL
;
5823 const char *newname
= smb_fname
->base_name
;
5824 NTSTATUS status
= NT_STATUS_OK
;
5825 TALLOC_CTX
*ctx
= talloc_tos();
5827 /* Set a symbolic link. */
5828 /* Don't allow this if follow links is false. */
5830 if (total_data
== 0) {
5831 return NT_STATUS_INVALID_PARAMETER
;
5834 if (!lp_symlinks(SNUM(conn
))) {
5835 return NT_STATUS_ACCESS_DENIED
;
5838 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5839 total_data
, STR_TERMINATE
);
5842 return NT_STATUS_INVALID_PARAMETER
;
5845 /* !widelinks forces the target path to be within the share. */
5846 /* This means we can interpret the target as a pathname. */
5847 if (!lp_widelinks(SNUM(conn
))) {
5848 char *rel_name
= NULL
;
5849 char *last_dirp
= NULL
;
5851 if (*link_target
== '/') {
5852 /* No absolute paths allowed. */
5853 return NT_STATUS_ACCESS_DENIED
;
5855 rel_name
= talloc_strdup(ctx
,newname
);
5857 return NT_STATUS_NO_MEMORY
;
5859 last_dirp
= strrchr_m(rel_name
, '/');
5861 last_dirp
[1] = '\0';
5863 rel_name
= talloc_strdup(ctx
,"./");
5865 return NT_STATUS_NO_MEMORY
;
5868 rel_name
= talloc_asprintf_append(rel_name
,
5872 return NT_STATUS_NO_MEMORY
;
5875 status
= check_name(conn
, rel_name
);
5876 if (!NT_STATUS_IS_OK(status
)) {
5881 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5882 newname
, link_target
));
5884 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5885 return map_nt_error_from_unix(errno
);
5888 return NT_STATUS_OK
;
5891 /****************************************************************************
5892 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5893 ****************************************************************************/
5895 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5896 struct smb_request
*req
,
5897 const char *pdata
, int total_data
,
5898 const struct smb_filename
*smb_fname_new
)
5900 char *oldname
= NULL
;
5901 struct smb_filename
*smb_fname_old
= NULL
;
5902 TALLOC_CTX
*ctx
= talloc_tos();
5903 NTSTATUS status
= NT_STATUS_OK
;
5905 /* Set a hard link. */
5906 if (total_data
== 0) {
5907 return NT_STATUS_INVALID_PARAMETER
;
5910 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5911 total_data
, STR_TERMINATE
, &status
);
5912 if (!NT_STATUS_IS_OK(status
)) {
5916 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5917 smb_fname_str_dbg(smb_fname_new
), oldname
));
5919 status
= filename_convert(ctx
,
5921 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5926 if (!NT_STATUS_IS_OK(status
)) {
5930 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5933 /****************************************************************************
5934 Deal with SMB_FILE_RENAME_INFORMATION.
5935 ****************************************************************************/
5937 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5938 struct smb_request
*req
,
5942 struct smb_filename
*smb_fname_src
)
5947 char *newname
= NULL
;
5948 struct smb_filename
*smb_fname_dst
= NULL
;
5949 bool dest_has_wcard
= False
;
5950 NTSTATUS status
= NT_STATUS_OK
;
5952 TALLOC_CTX
*ctx
= talloc_tos();
5954 if (total_data
< 13) {
5955 return NT_STATUS_INVALID_PARAMETER
;
5958 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5959 root_fid
= IVAL(pdata
,4);
5960 len
= IVAL(pdata
,8);
5962 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5963 return NT_STATUS_INVALID_PARAMETER
;
5966 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5969 if (!NT_STATUS_IS_OK(status
)) {
5973 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5976 status
= resolve_dfspath_wcard(ctx
, conn
,
5977 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5981 if (!NT_STATUS_IS_OK(status
)) {
5985 /* Check the new name has no '/' characters. */
5986 if (strchr_m(newname
, '/')) {
5987 return NT_STATUS_NOT_SUPPORTED
;
5990 if (fsp
&& fsp
->base_fsp
) {
5991 /* newname must be a stream name. */
5992 if (newname
[0] != ':') {
5993 return NT_STATUS_NOT_SUPPORTED
;
5996 /* Create an smb_fname to call rename_internals_fsp() with. */
5997 status
= create_synthetic_smb_fname(talloc_tos(),
5998 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6000 if (!NT_STATUS_IS_OK(status
)) {
6005 * Set the original last component, since
6006 * rename_internals_fsp() requires it.
6008 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6010 if (smb_fname_dst
->original_lcomp
== NULL
) {
6011 status
= NT_STATUS_NO_MEMORY
;
6017 * Build up an smb_fname_dst based on the filename passed in.
6018 * We basically just strip off the last component, and put on
6019 * the newname instead.
6021 char *base_name
= NULL
;
6023 /* newname must *not* be a stream name. */
6024 if (newname
[0] == ':') {
6025 return NT_STATUS_NOT_SUPPORTED
;
6029 * Strip off the last component (filename) of the path passed
6032 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6034 return NT_STATUS_NO_MEMORY
;
6036 p
= strrchr_m(base_name
, '/');
6040 base_name
= talloc_strdup(ctx
, "./");
6042 return NT_STATUS_NO_MEMORY
;
6045 /* Append the new name. */
6046 base_name
= talloc_asprintf_append(base_name
,
6050 return NT_STATUS_NO_MEMORY
;
6053 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6056 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6059 /* If an error we expect this to be
6060 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6062 if (!NT_STATUS_IS_OK(status
)) {
6063 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6067 /* Create an smb_fname to call rename_internals_fsp() */
6068 status
= create_synthetic_smb_fname(ctx
,
6072 if (!NT_STATUS_IS_OK(status
)) {
6079 DEBUG(10,("smb_file_rename_information: "
6080 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6081 fsp
->fnum
, fsp_str_dbg(fsp
),
6082 smb_fname_str_dbg(smb_fname_dst
)));
6083 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6086 DEBUG(10,("smb_file_rename_information: "
6087 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6088 smb_fname_str_dbg(smb_fname_src
),
6089 smb_fname_str_dbg(smb_fname_dst
)));
6090 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6091 smb_fname_dst
, 0, overwrite
, false,
6093 FILE_WRITE_ATTRIBUTES
);
6096 TALLOC_FREE(smb_fname_dst
);
6100 /****************************************************************************
6101 Deal with SMB_SET_POSIX_ACL.
6102 ****************************************************************************/
6104 #if defined(HAVE_POSIX_ACLS)
6105 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6109 const struct smb_filename
*smb_fname
)
6111 uint16 posix_acl_version
;
6112 uint16 num_file_acls
;
6113 uint16 num_def_acls
;
6114 bool valid_file_acls
= True
;
6115 bool valid_def_acls
= True
;
6117 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6118 return NT_STATUS_INVALID_PARAMETER
;
6120 posix_acl_version
= SVAL(pdata
,0);
6121 num_file_acls
= SVAL(pdata
,2);
6122 num_def_acls
= SVAL(pdata
,4);
6124 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6125 valid_file_acls
= False
;
6129 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6130 valid_def_acls
= False
;
6134 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6135 return NT_STATUS_INVALID_PARAMETER
;
6138 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6139 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6140 return NT_STATUS_INVALID_PARAMETER
;
6143 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6144 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6145 (unsigned int)num_file_acls
,
6146 (unsigned int)num_def_acls
));
6148 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6149 smb_fname
->base_name
, num_file_acls
,
6150 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6151 return map_nt_error_from_unix(errno
);
6154 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6155 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6156 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6157 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6158 return map_nt_error_from_unix(errno
);
6160 return NT_STATUS_OK
;
6164 /****************************************************************************
6165 Deal with SMB_SET_POSIX_LOCK.
6166 ****************************************************************************/
6168 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6169 struct smb_request
*req
,
6177 bool blocking_lock
= False
;
6178 enum brl_type lock_type
;
6180 NTSTATUS status
= NT_STATUS_OK
;
6182 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6183 return NT_STATUS_INVALID_HANDLE
;
6186 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6187 return NT_STATUS_INVALID_PARAMETER
;
6190 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6191 case POSIX_LOCK_TYPE_READ
:
6192 lock_type
= READ_LOCK
;
6194 case POSIX_LOCK_TYPE_WRITE
:
6195 /* Return the right POSIX-mappable error code for files opened read-only. */
6196 if (!fsp
->can_write
) {
6197 return NT_STATUS_INVALID_HANDLE
;
6199 lock_type
= WRITE_LOCK
;
6201 case POSIX_LOCK_TYPE_UNLOCK
:
6202 lock_type
= UNLOCK_LOCK
;
6205 return NT_STATUS_INVALID_PARAMETER
;
6208 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6209 blocking_lock
= False
;
6210 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6211 blocking_lock
= True
;
6213 return NT_STATUS_INVALID_PARAMETER
;
6216 if (!lp_blocking_locks(SNUM(conn
))) {
6217 blocking_lock
= False
;
6220 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6221 #if defined(HAVE_LONGLONG)
6222 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6223 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6224 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6225 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6226 #else /* HAVE_LONGLONG */
6227 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6228 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6229 #endif /* HAVE_LONGLONG */
6231 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6232 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6234 (unsigned int)lock_type
,
6235 (unsigned int)lock_pid
,
6239 if (lock_type
== UNLOCK_LOCK
) {
6240 status
= do_unlock(smbd_messaging_context(),
6247 uint32 block_smbpid
;
6249 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6261 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6263 * A blocking lock was requested. Package up
6264 * this smb into a queued request and push it
6265 * onto the blocking lock queue.
6267 if(push_blocking_lock_request(br_lck
,
6270 -1, /* infinite timeout. */
6278 TALLOC_FREE(br_lck
);
6282 TALLOC_FREE(br_lck
);
6288 /****************************************************************************
6289 Deal with SMB_SET_FILE_BASIC_INFO.
6290 ****************************************************************************/
6292 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6296 const struct smb_filename
*smb_fname
)
6298 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6299 struct smb_file_time ft
;
6301 NTSTATUS status
= NT_STATUS_OK
;
6305 if (total_data
< 36) {
6306 return NT_STATUS_INVALID_PARAMETER
;
6309 /* Set the attributes */
6310 dosmode
= IVAL(pdata
,32);
6311 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6312 if (!NT_STATUS_IS_OK(status
)) {
6317 ft
.create_time
= interpret_long_date(pdata
);
6320 ft
.atime
= interpret_long_date(pdata
+8);
6323 ft
.mtime
= interpret_long_date(pdata
+16);
6326 ft
.ctime
= interpret_long_date(pdata
+24);
6328 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6329 smb_fname_str_dbg(smb_fname
)));
6331 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6335 /****************************************************************************
6336 Deal with SMB_INFO_STANDARD.
6337 ****************************************************************************/
6339 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6343 const struct smb_filename
*smb_fname
)
6345 struct smb_file_time ft
;
6349 if (total_data
< 12) {
6350 return NT_STATUS_INVALID_PARAMETER
;
6354 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6356 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6358 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6360 DEBUG(10,("smb_set_info_standard: file %s\n",
6361 smb_fname_str_dbg(smb_fname
)));
6363 return smb_set_file_time(conn
,
6370 /****************************************************************************
6371 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6372 ****************************************************************************/
6374 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6375 struct smb_request
*req
,
6379 struct smb_filename
*smb_fname
)
6381 uint64_t allocation_size
= 0;
6382 NTSTATUS status
= NT_STATUS_OK
;
6383 files_struct
*new_fsp
= NULL
;
6385 if (!VALID_STAT(smb_fname
->st
)) {
6386 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6389 if (total_data
< 8) {
6390 return NT_STATUS_INVALID_PARAMETER
;
6393 allocation_size
= (uint64_t)IVAL(pdata
,0);
6394 #ifdef LARGE_SMB_OFF_T
6395 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6396 #else /* LARGE_SMB_OFF_T */
6397 if (IVAL(pdata
,4) != 0) {
6398 /* more than 32 bits? */
6399 return NT_STATUS_INVALID_PARAMETER
;
6401 #endif /* LARGE_SMB_OFF_T */
6403 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6404 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6405 (double)allocation_size
));
6407 if (allocation_size
) {
6408 allocation_size
= smb_roundup(conn
, allocation_size
);
6411 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6412 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6413 (double)allocation_size
));
6415 if (fsp
&& fsp
->fh
->fd
!= -1) {
6416 /* Open file handle. */
6417 /* Only change if needed. */
6418 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6419 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6420 return map_nt_error_from_unix(errno
);
6423 /* But always update the time. */
6425 * This is equivalent to a write. Ensure it's seen immediately
6426 * if there are no pending writes.
6428 trigger_write_time_update_immediate(fsp
);
6429 return NT_STATUS_OK
;
6432 /* Pathname or stat or directory file. */
6433 status
= SMB_VFS_CREATE_FILE(
6436 0, /* root_dir_fid */
6437 smb_fname
, /* fname */
6438 FILE_WRITE_DATA
, /* access_mask */
6439 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6441 FILE_OPEN
, /* create_disposition*/
6442 0, /* create_options */
6443 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6444 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6445 0, /* allocation_size */
6448 &new_fsp
, /* result */
6451 if (!NT_STATUS_IS_OK(status
)) {
6452 /* NB. We check for open_was_deferred in the caller. */
6456 /* Only change if needed. */
6457 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6458 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6459 status
= map_nt_error_from_unix(errno
);
6460 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6465 /* Changing the allocation size should set the last mod time. */
6467 * This is equivalent to a write. Ensure it's seen immediately
6468 * if there are no pending writes.
6470 trigger_write_time_update_immediate(new_fsp
);
6472 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6473 return NT_STATUS_OK
;
6476 /****************************************************************************
6477 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6478 ****************************************************************************/
6480 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6481 struct smb_request
*req
,
6485 const struct smb_filename
*smb_fname
)
6489 if (total_data
< 8) {
6490 return NT_STATUS_INVALID_PARAMETER
;
6493 size
= IVAL(pdata
,0);
6494 #ifdef LARGE_SMB_OFF_T
6495 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6496 #else /* LARGE_SMB_OFF_T */
6497 if (IVAL(pdata
,4) != 0) {
6498 /* more than 32 bits? */
6499 return NT_STATUS_INVALID_PARAMETER
;
6501 #endif /* LARGE_SMB_OFF_T */
6502 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6503 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6506 return smb_set_file_size(conn
, req
,
6513 /****************************************************************************
6514 Allow a UNIX info mknod.
6515 ****************************************************************************/
6517 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6520 const struct smb_filename
*smb_fname
)
6522 uint32 file_type
= IVAL(pdata
,56);
6523 #if defined(HAVE_MAKEDEV)
6524 uint32 dev_major
= IVAL(pdata
,60);
6525 uint32 dev_minor
= IVAL(pdata
,68);
6527 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6528 uint32 raw_unixmode
= IVAL(pdata
,84);
6532 if (total_data
< 100) {
6533 return NT_STATUS_INVALID_PARAMETER
;
6536 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6537 PERM_NEW_FILE
, &unixmode
);
6538 if (!NT_STATUS_IS_OK(status
)) {
6542 #if defined(HAVE_MAKEDEV)
6543 dev
= makedev(dev_major
, dev_minor
);
6546 switch (file_type
) {
6547 #if defined(S_IFIFO)
6548 case UNIX_TYPE_FIFO
:
6549 unixmode
|= S_IFIFO
;
6552 #if defined(S_IFSOCK)
6553 case UNIX_TYPE_SOCKET
:
6554 unixmode
|= S_IFSOCK
;
6557 #if defined(S_IFCHR)
6558 case UNIX_TYPE_CHARDEV
:
6559 unixmode
|= S_IFCHR
;
6562 #if defined(S_IFBLK)
6563 case UNIX_TYPE_BLKDEV
:
6564 unixmode
|= S_IFBLK
;
6568 return NT_STATUS_INVALID_PARAMETER
;
6571 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6572 "%.0f mode 0%o for file %s\n", (double)dev
,
6573 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6575 /* Ok - do the mknod. */
6576 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6577 return map_nt_error_from_unix(errno
);
6580 /* If any of the other "set" calls fail we
6581 * don't want to end up with a half-constructed mknod.
6584 if (lp_inherit_perms(SNUM(conn
))) {
6586 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6588 return NT_STATUS_NO_MEMORY
;
6590 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6592 TALLOC_FREE(parent
);
6595 return NT_STATUS_OK
;
6598 /****************************************************************************
6599 Deal with SMB_SET_FILE_UNIX_BASIC.
6600 ****************************************************************************/
6602 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6603 struct smb_request
*req
,
6607 const struct smb_filename
*smb_fname
)
6609 struct smb_file_time ft
;
6610 uint32 raw_unixmode
;
6613 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6614 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6615 NTSTATUS status
= NT_STATUS_OK
;
6616 bool delete_on_fail
= False
;
6617 enum perm_type ptype
;
6618 files_struct
*all_fsps
= NULL
;
6619 bool modify_mtime
= true;
6621 SMB_STRUCT_STAT sbuf
;
6625 if (total_data
< 100) {
6626 return NT_STATUS_INVALID_PARAMETER
;
6629 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6630 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6631 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6632 #ifdef LARGE_SMB_OFF_T
6633 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6634 #else /* LARGE_SMB_OFF_T */
6635 if (IVAL(pdata
,4) != 0) {
6636 /* more than 32 bits? */
6637 return NT_STATUS_INVALID_PARAMETER
;
6639 #endif /* LARGE_SMB_OFF_T */
6642 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6643 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6644 set_owner
= (uid_t
)IVAL(pdata
,40);
6645 set_grp
= (gid_t
)IVAL(pdata
,48);
6646 raw_unixmode
= IVAL(pdata
,84);
6648 if (VALID_STAT(smb_fname
->st
)) {
6649 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6650 ptype
= PERM_EXISTING_DIR
;
6652 ptype
= PERM_EXISTING_FILE
;
6655 ptype
= PERM_NEW_FILE
;
6658 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6660 if (!NT_STATUS_IS_OK(status
)) {
6664 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6665 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6666 smb_fname_str_dbg(smb_fname
), (double)size
,
6667 (unsigned int)set_owner
, (unsigned int)set_grp
,
6668 (int)raw_unixmode
));
6670 sbuf
= smb_fname
->st
;
6672 if (!VALID_STAT(sbuf
)) {
6673 struct smb_filename
*smb_fname_tmp
= NULL
;
6675 * The only valid use of this is to create character and block
6676 * devices, and named pipes. This is deprecated (IMHO) and
6677 * a new info level should be used for mknod. JRA.
6680 status
= smb_unix_mknod(conn
,
6684 if (!NT_STATUS_IS_OK(status
)) {
6688 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6690 if (!NT_STATUS_IS_OK(status
)) {
6694 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6695 status
= map_nt_error_from_unix(errno
);
6696 TALLOC_FREE(smb_fname_tmp
);
6697 SMB_VFS_UNLINK(conn
, smb_fname
);
6701 sbuf
= smb_fname_tmp
->st
;
6702 TALLOC_FREE(smb_fname_tmp
);
6704 /* Ensure we don't try and change anything else. */
6705 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6706 size
= get_file_size_stat(&sbuf
);
6707 ft
.atime
= sbuf
.st_ex_atime
;
6708 ft
.mtime
= sbuf
.st_ex_mtime
;
6710 * We continue here as we might want to change the
6713 delete_on_fail
= True
;
6717 /* Horrible backwards compatibility hack as an old server bug
6718 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6722 size
= get_file_size_stat(&sbuf
);
6727 * Deal with the UNIX specific mode set.
6730 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6731 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6732 "setting mode 0%o for file %s\n",
6733 (unsigned int)unixmode
,
6734 smb_fname_str_dbg(smb_fname
)));
6735 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6736 return map_nt_error_from_unix(errno
);
6741 * Deal with the UNIX specific uid set.
6744 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6745 (sbuf
.st_ex_uid
!= set_owner
)) {
6748 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6749 "changing owner %u for path %s\n",
6750 (unsigned int)set_owner
,
6751 smb_fname_str_dbg(smb_fname
)));
6753 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6754 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6755 set_owner
, (gid_t
)-1);
6757 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6758 set_owner
, (gid_t
)-1);
6762 status
= map_nt_error_from_unix(errno
);
6763 if (delete_on_fail
) {
6764 SMB_VFS_UNLINK(conn
, smb_fname
);
6771 * Deal with the UNIX specific gid set.
6774 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6775 (sbuf
.st_ex_gid
!= set_grp
)) {
6776 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6777 "changing group %u for file %s\n",
6778 (unsigned int)set_owner
,
6779 smb_fname_str_dbg(smb_fname
)));
6780 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6782 status
= map_nt_error_from_unix(errno
);
6783 if (delete_on_fail
) {
6784 SMB_VFS_UNLINK(conn
, smb_fname
);
6790 /* Deal with any size changes. */
6792 status
= smb_set_file_size(conn
, req
,
6797 if (!NT_STATUS_IS_OK(status
)) {
6801 /* Deal with any time changes. */
6802 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6803 /* No change, don't cancel anything. */
6807 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6808 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6809 all_fsps
= file_find_di_next(all_fsps
)) {
6811 * We're setting the time explicitly for UNIX.
6812 * Cancel any pending changes over all handles.
6814 all_fsps
->update_write_time_on_close
= false;
6815 TALLOC_FREE(all_fsps
->update_write_time_event
);
6819 * Override the "setting_write_time"
6820 * parameter here as it almost does what
6821 * we need. Just remember if we modified
6822 * mtime and send the notify ourselves.
6824 if (null_timespec(ft
.mtime
)) {
6825 modify_mtime
= false;
6828 status
= smb_set_file_time(conn
,
6834 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6835 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6840 /****************************************************************************
6841 Deal with SMB_SET_FILE_UNIX_INFO2.
6842 ****************************************************************************/
6844 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6845 struct smb_request
*req
,
6849 const struct smb_filename
*smb_fname
)
6855 if (total_data
< 116) {
6856 return NT_STATUS_INVALID_PARAMETER
;
6859 /* Start by setting all the fields that are common between UNIX_BASIC
6862 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6864 if (!NT_STATUS_IS_OK(status
)) {
6868 smb_fflags
= IVAL(pdata
, 108);
6869 smb_fmask
= IVAL(pdata
, 112);
6871 /* NB: We should only attempt to alter the file flags if the client
6872 * sends a non-zero mask.
6874 if (smb_fmask
!= 0) {
6875 int stat_fflags
= 0;
6877 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6878 smb_fmask
, &stat_fflags
)) {
6879 /* Client asked to alter a flag we don't understand. */
6880 return NT_STATUS_INVALID_PARAMETER
;
6883 if (fsp
&& fsp
->fh
->fd
!= -1) {
6884 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6885 return NT_STATUS_NOT_SUPPORTED
;
6887 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6888 stat_fflags
) != 0) {
6889 return map_nt_error_from_unix(errno
);
6894 /* XXX: need to add support for changing the create_time here. You
6895 * can do this for paths on Darwin with setattrlist(2). The right way
6896 * to hook this up is probably by extending the VFS utimes interface.
6899 return NT_STATUS_OK
;
6902 /****************************************************************************
6903 Create a directory with POSIX semantics.
6904 ****************************************************************************/
6906 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6907 struct smb_request
*req
,
6910 struct smb_filename
*smb_fname
,
6911 int *pdata_return_size
)
6913 NTSTATUS status
= NT_STATUS_OK
;
6914 uint32 raw_unixmode
= 0;
6915 uint32 mod_unixmode
= 0;
6916 mode_t unixmode
= (mode_t
)0;
6917 files_struct
*fsp
= NULL
;
6918 uint16 info_level_return
= 0;
6920 char *pdata
= *ppdata
;
6922 if (total_data
< 18) {
6923 return NT_STATUS_INVALID_PARAMETER
;
6926 raw_unixmode
= IVAL(pdata
,8);
6927 /* Next 4 bytes are not yet defined. */
6929 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6930 PERM_NEW_DIR
, &unixmode
);
6931 if (!NT_STATUS_IS_OK(status
)) {
6935 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6937 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6938 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6940 status
= SMB_VFS_CREATE_FILE(
6943 0, /* root_dir_fid */
6944 smb_fname
, /* fname */
6945 FILE_READ_ATTRIBUTES
, /* access_mask */
6946 FILE_SHARE_NONE
, /* share_access */
6947 FILE_CREATE
, /* create_disposition*/
6948 FILE_DIRECTORY_FILE
, /* create_options */
6949 mod_unixmode
, /* file_attributes */
6950 0, /* oplock_request */
6951 0, /* allocation_size */
6957 if (NT_STATUS_IS_OK(status
)) {
6958 close_file(req
, fsp
, NORMAL_CLOSE
);
6961 info_level_return
= SVAL(pdata
,16);
6963 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6964 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6965 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6966 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6968 *pdata_return_size
= 12;
6971 /* Realloc the data size */
6972 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6973 if (*ppdata
== NULL
) {
6974 *pdata_return_size
= 0;
6975 return NT_STATUS_NO_MEMORY
;
6979 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6980 SSVAL(pdata
,2,0); /* No fnum. */
6981 SIVAL(pdata
,4,info
); /* Was directory created. */
6983 switch (info_level_return
) {
6984 case SMB_QUERY_FILE_UNIX_BASIC
:
6985 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6986 SSVAL(pdata
,10,0); /* Padding. */
6987 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6990 case SMB_QUERY_FILE_UNIX_INFO2
:
6991 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6992 SSVAL(pdata
,10,0); /* Padding. */
6993 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6997 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6998 SSVAL(pdata
,10,0); /* Padding. */
7005 /****************************************************************************
7006 Open/Create a file with POSIX semantics.
7007 ****************************************************************************/
7009 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7010 struct smb_request
*req
,
7013 struct smb_filename
*smb_fname
,
7014 int *pdata_return_size
)
7016 bool extended_oplock_granted
= False
;
7017 char *pdata
= *ppdata
;
7019 uint32 wire_open_mode
= 0;
7020 uint32 raw_unixmode
= 0;
7021 uint32 mod_unixmode
= 0;
7022 uint32 create_disp
= 0;
7023 uint32 access_mask
= 0;
7024 uint32 create_options
= 0;
7025 NTSTATUS status
= NT_STATUS_OK
;
7026 mode_t unixmode
= (mode_t
)0;
7027 files_struct
*fsp
= NULL
;
7028 int oplock_request
= 0;
7030 uint16 info_level_return
= 0;
7032 if (total_data
< 18) {
7033 return NT_STATUS_INVALID_PARAMETER
;
7036 flags
= IVAL(pdata
,0);
7037 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7038 if (oplock_request
) {
7039 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7042 wire_open_mode
= IVAL(pdata
,4);
7044 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7045 return smb_posix_mkdir(conn
, req
,
7052 switch (wire_open_mode
& SMB_ACCMODE
) {
7054 access_mask
= FILE_READ_DATA
;
7057 access_mask
= FILE_WRITE_DATA
;
7060 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7063 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7064 (unsigned int)wire_open_mode
));
7065 return NT_STATUS_INVALID_PARAMETER
;
7068 wire_open_mode
&= ~SMB_ACCMODE
;
7070 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7071 create_disp
= FILE_CREATE
;
7072 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7073 create_disp
= FILE_OVERWRITE_IF
;
7074 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7075 create_disp
= FILE_OPEN_IF
;
7076 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7077 create_disp
= FILE_OPEN
;
7079 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7080 (unsigned int)wire_open_mode
));
7081 return NT_STATUS_INVALID_PARAMETER
;
7084 raw_unixmode
= IVAL(pdata
,8);
7085 /* Next 4 bytes are not yet defined. */
7087 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7088 (VALID_STAT(smb_fname
->st
) ?
7089 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7092 if (!NT_STATUS_IS_OK(status
)) {
7096 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7098 if (wire_open_mode
& SMB_O_SYNC
) {
7099 create_options
|= FILE_WRITE_THROUGH
;
7101 if (wire_open_mode
& SMB_O_APPEND
) {
7102 access_mask
|= FILE_APPEND_DATA
;
7104 if (wire_open_mode
& SMB_O_DIRECT
) {
7105 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7108 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7109 smb_fname_str_dbg(smb_fname
),
7110 (unsigned int)wire_open_mode
,
7111 (unsigned int)unixmode
));
7113 status
= SMB_VFS_CREATE_FILE(
7116 0, /* root_dir_fid */
7117 smb_fname
, /* fname */
7118 access_mask
, /* access_mask */
7119 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7121 create_disp
, /* create_disposition*/
7122 FILE_NON_DIRECTORY_FILE
, /* create_options */
7123 mod_unixmode
, /* file_attributes */
7124 oplock_request
, /* oplock_request */
7125 0, /* allocation_size */
7131 if (!NT_STATUS_IS_OK(status
)) {
7135 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7136 extended_oplock_granted
= True
;
7139 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7140 extended_oplock_granted
= True
;
7143 info_level_return
= SVAL(pdata
,16);
7145 /* Allocate the correct return size. */
7147 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7148 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7149 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7150 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7152 *pdata_return_size
= 12;
7155 /* Realloc the data size */
7156 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7157 if (*ppdata
== NULL
) {
7158 close_file(req
, fsp
, ERROR_CLOSE
);
7159 *pdata_return_size
= 0;
7160 return NT_STATUS_NO_MEMORY
;
7164 if (extended_oplock_granted
) {
7165 if (flags
& REQUEST_BATCH_OPLOCK
) {
7166 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7168 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7170 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7171 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7173 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7176 SSVAL(pdata
,2,fsp
->fnum
);
7177 SIVAL(pdata
,4,info
); /* Was file created etc. */
7179 switch (info_level_return
) {
7180 case SMB_QUERY_FILE_UNIX_BASIC
:
7181 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7182 SSVAL(pdata
,10,0); /* padding. */
7183 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7186 case SMB_QUERY_FILE_UNIX_INFO2
:
7187 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7188 SSVAL(pdata
,10,0); /* padding. */
7189 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7193 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7194 SSVAL(pdata
,10,0); /* padding. */
7197 return NT_STATUS_OK
;
7200 /****************************************************************************
7201 Delete a file with POSIX semantics.
7202 ****************************************************************************/
7204 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7205 struct smb_request
*req
,
7208 struct smb_filename
*smb_fname
)
7210 NTSTATUS status
= NT_STATUS_OK
;
7211 files_struct
*fsp
= NULL
;
7215 int create_options
= 0;
7217 struct share_mode_lock
*lck
= NULL
;
7219 if (total_data
< 2) {
7220 return NT_STATUS_INVALID_PARAMETER
;
7223 flags
= SVAL(pdata
,0);
7225 if (!VALID_STAT(smb_fname
->st
)) {
7226 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7229 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7230 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7231 return NT_STATUS_NOT_A_DIRECTORY
;
7234 DEBUG(10,("smb_posix_unlink: %s %s\n",
7235 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7236 smb_fname_str_dbg(smb_fname
)));
7238 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7239 create_options
|= FILE_DIRECTORY_FILE
;
7242 status
= SMB_VFS_CREATE_FILE(
7245 0, /* root_dir_fid */
7246 smb_fname
, /* fname */
7247 DELETE_ACCESS
, /* access_mask */
7248 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7250 FILE_OPEN
, /* create_disposition*/
7251 create_options
, /* create_options */
7252 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7253 0, /* oplock_request */
7254 0, /* allocation_size */
7260 if (!NT_STATUS_IS_OK(status
)) {
7265 * Don't lie to client. If we can't really delete due to
7266 * non-POSIX opens return SHARING_VIOLATION.
7269 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7272 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7273 "lock for file %s\n", fsp_str_dbg(fsp
)));
7274 close_file(req
, fsp
, NORMAL_CLOSE
);
7275 return NT_STATUS_INVALID_PARAMETER
;
7279 * See if others still have the file open. If this is the case, then
7280 * don't delete. If all opens are POSIX delete we can set the delete
7281 * on close disposition.
7283 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7284 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7285 if (is_valid_share_mode_entry(e
)) {
7286 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7289 /* Fail with sharing violation. */
7290 close_file(req
, fsp
, NORMAL_CLOSE
);
7292 return NT_STATUS_SHARING_VIOLATION
;
7297 * Set the delete on close.
7299 status
= smb_set_file_disposition_info(conn
,
7305 if (!NT_STATUS_IS_OK(status
)) {
7306 close_file(req
, fsp
, NORMAL_CLOSE
);
7311 return close_file(req
, fsp
, NORMAL_CLOSE
);
7314 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7315 struct smb_request
*req
,
7316 TALLOC_CTX
*mem_ctx
,
7317 uint16_t info_level
,
7319 struct smb_filename
*smb_fname
,
7320 char **ppdata
, int total_data
,
7323 char *pdata
= *ppdata
;
7324 NTSTATUS status
= NT_STATUS_OK
;
7325 int data_return_size
= 0;
7329 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7330 return NT_STATUS_INVALID_LEVEL
;
7333 if (!CAN_WRITE(conn
)) {
7334 /* Allow POSIX opens. The open path will deny
7335 * any non-readonly opens. */
7336 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7337 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7341 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7342 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7343 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7345 switch (info_level
) {
7347 case SMB_INFO_STANDARD
:
7349 status
= smb_set_info_standard(conn
,
7357 case SMB_INFO_SET_EA
:
7359 status
= smb_info_set_ea(conn
,
7367 case SMB_SET_FILE_BASIC_INFO
:
7368 case SMB_FILE_BASIC_INFORMATION
:
7370 status
= smb_set_file_basic_info(conn
,
7378 case SMB_FILE_ALLOCATION_INFORMATION
:
7379 case SMB_SET_FILE_ALLOCATION_INFO
:
7381 status
= smb_set_file_allocation_info(conn
, req
,
7389 case SMB_FILE_END_OF_FILE_INFORMATION
:
7390 case SMB_SET_FILE_END_OF_FILE_INFO
:
7392 status
= smb_set_file_end_of_file_info(conn
, req
,
7400 case SMB_FILE_DISPOSITION_INFORMATION
:
7401 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7404 /* JRA - We used to just ignore this on a path ?
7405 * Shouldn't this be invalid level on a pathname
7408 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7409 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7412 status
= smb_set_file_disposition_info(conn
,
7420 case SMB_FILE_POSITION_INFORMATION
:
7422 status
= smb_file_position_information(conn
,
7429 case SMB_FILE_FULL_EA_INFORMATION
:
7431 status
= smb_set_file_full_ea_info(conn
,
7438 /* From tridge Samba4 :
7439 * MODE_INFORMATION in setfileinfo (I have no
7440 * idea what "mode information" on a file is - it takes a value of 0,
7441 * 2, 4 or 6. What could it be?).
7444 case SMB_FILE_MODE_INFORMATION
:
7446 status
= smb_file_mode_information(conn
,
7453 * CIFS UNIX extensions.
7456 case SMB_SET_FILE_UNIX_BASIC
:
7458 status
= smb_set_file_unix_basic(conn
, req
,
7466 case SMB_SET_FILE_UNIX_INFO2
:
7468 status
= smb_set_file_unix_info2(conn
, req
,
7476 case SMB_SET_FILE_UNIX_LINK
:
7479 /* We must have a pathname for this. */
7480 return NT_STATUS_INVALID_LEVEL
;
7482 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7483 total_data
, smb_fname
);
7487 case SMB_SET_FILE_UNIX_HLINK
:
7490 /* We must have a pathname for this. */
7491 return NT_STATUS_INVALID_LEVEL
;
7493 status
= smb_set_file_unix_hlink(conn
, req
,
7499 case SMB_FILE_RENAME_INFORMATION
:
7501 status
= smb_file_rename_information(conn
, req
,
7507 #if defined(HAVE_POSIX_ACLS)
7508 case SMB_SET_POSIX_ACL
:
7510 status
= smb_set_posix_acl(conn
,
7519 case SMB_SET_POSIX_LOCK
:
7522 return NT_STATUS_INVALID_LEVEL
;
7524 status
= smb_set_posix_lock(conn
, req
,
7525 pdata
, total_data
, fsp
);
7529 case SMB_POSIX_PATH_OPEN
:
7532 /* We must have a pathname for this. */
7533 return NT_STATUS_INVALID_LEVEL
;
7536 status
= smb_posix_open(conn
, req
,
7544 case SMB_POSIX_PATH_UNLINK
:
7547 /* We must have a pathname for this. */
7548 return NT_STATUS_INVALID_LEVEL
;
7551 status
= smb_posix_unlink(conn
, req
,
7559 return NT_STATUS_INVALID_LEVEL
;
7562 if (!NT_STATUS_IS_OK(status
)) {
7566 *ret_data_size
= data_return_size
;
7567 return NT_STATUS_OK
;
7570 /****************************************************************************
7571 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7572 ****************************************************************************/
7574 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7575 struct smb_request
*req
,
7576 unsigned int tran_call
,
7577 char **pparams
, int total_params
,
7578 char **ppdata
, int total_data
,
7579 unsigned int max_data_bytes
)
7581 char *params
= *pparams
;
7582 char *pdata
= *ppdata
;
7584 struct smb_filename
*smb_fname
= NULL
;
7585 files_struct
*fsp
= NULL
;
7586 NTSTATUS status
= NT_STATUS_OK
;
7587 int data_return_size
= 0;
7590 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7594 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7595 if (total_params
< 4) {
7596 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7600 fsp
= file_fsp(req
, SVAL(params
,0));
7601 /* Basic check for non-null fsp. */
7602 if (!check_fsp_open(conn
, req
, fsp
)) {
7605 info_level
= SVAL(params
,2);
7607 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7609 if (!NT_STATUS_IS_OK(status
)) {
7610 reply_nterror(req
, status
);
7614 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7616 * This is actually a SETFILEINFO on a directory
7617 * handle (returned from an NT SMB). NT5.0 seems
7618 * to do this call. JRA.
7620 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7621 /* Always do lstat for UNIX calls. */
7622 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7623 DEBUG(3,("call_trans2setfilepathinfo: "
7624 "SMB_VFS_LSTAT of %s failed "
7626 smb_fname_str_dbg(smb_fname
),
7628 reply_nterror(req
, map_nt_error_from_unix(errno
));
7632 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7633 DEBUG(3,("call_trans2setfilepathinfo: "
7634 "fileinfo of %s failed (%s)\n",
7635 smb_fname_str_dbg(smb_fname
),
7637 reply_nterror(req
, map_nt_error_from_unix(errno
));
7641 } else if (fsp
->print_file
) {
7643 * Doing a DELETE_ON_CLOSE should cancel a print job.
7645 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7646 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7648 DEBUG(3,("call_trans2setfilepathinfo: "
7649 "Cancelling print job (%s)\n",
7653 send_trans2_replies(conn
, req
, params
, 2,
7658 reply_doserror(req
, ERRDOS
, ERRbadpath
);
7663 * Original code - this is an open file.
7665 if (!check_fsp(conn
, req
, fsp
)) {
7669 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7670 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7671 "of fnum %d failed (%s)\n", fsp
->fnum
,
7673 reply_nterror(req
, map_nt_error_from_unix(errno
));
7681 if (total_params
< 7) {
7682 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7686 info_level
= SVAL(params
,0);
7687 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7688 total_params
- 6, STR_TERMINATE
,
7690 if (!NT_STATUS_IS_OK(status
)) {
7691 reply_nterror(req
, status
);
7695 status
= filename_convert(req
, conn
,
7696 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7701 if (!NT_STATUS_IS_OK(status
)) {
7702 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7703 reply_botherror(req
,
7704 NT_STATUS_PATH_NOT_COVERED
,
7705 ERRSRV
, ERRbadpath
);
7708 reply_nterror(req
, status
);
7712 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7714 * For CIFS UNIX extensions the target name may not exist.
7717 /* Always do lstat for UNIX calls. */
7718 SMB_VFS_LSTAT(conn
, smb_fname
);
7720 } else if (!VALID_STAT(smb_fname
->st
) &&
7721 SMB_VFS_STAT(conn
, smb_fname
)) {
7722 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7724 smb_fname_str_dbg(smb_fname
),
7726 reply_nterror(req
, map_nt_error_from_unix(errno
));
7731 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7732 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7733 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7735 /* Realloc the parameter size */
7736 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7737 if (*pparams
== NULL
) {
7738 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7745 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7751 if (!NT_STATUS_IS_OK(status
)) {
7752 if (open_was_deferred(req
->mid
)) {
7753 /* We have re-scheduled this call. */
7756 if (blocking_lock_was_deferred(req
->mid
)) {
7757 /* We have re-scheduled this call. */
7760 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7761 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7762 ERRSRV
, ERRbadpath
);
7765 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7766 reply_openerror(req
, status
);
7770 reply_nterror(req
, status
);
7774 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7780 /****************************************************************************
7781 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7782 ****************************************************************************/
7784 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7785 char **pparams
, int total_params
,
7786 char **ppdata
, int total_data
,
7787 unsigned int max_data_bytes
)
7789 struct smb_filename
*smb_dname
= NULL
;
7790 char *params
= *pparams
;
7791 char *pdata
= *ppdata
;
7792 char *directory
= NULL
;
7793 NTSTATUS status
= NT_STATUS_OK
;
7794 struct ea_list
*ea_list
= NULL
;
7795 TALLOC_CTX
*ctx
= talloc_tos();
7797 if (!CAN_WRITE(conn
)) {
7798 reply_doserror(req
, ERRSRV
, ERRaccess
);
7802 if (total_params
< 5) {
7803 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7807 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7808 total_params
- 4, STR_TERMINATE
,
7810 if (!NT_STATUS_IS_OK(status
)) {
7811 reply_nterror(req
, status
);
7815 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7817 status
= filename_convert(ctx
,
7819 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7825 if (!NT_STATUS_IS_OK(status
)) {
7826 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7827 reply_botherror(req
,
7828 NT_STATUS_PATH_NOT_COVERED
,
7829 ERRSRV
, ERRbadpath
);
7832 reply_nterror(req
, status
);
7836 /* Any data in this call is an EA list. */
7837 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7838 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7843 * OS/2 workplace shell seems to send SET_EA requests of "null"
7844 * length (4 bytes containing IVAL 4).
7845 * They seem to have no effect. Bug #3212. JRA.
7848 if (total_data
!= 4) {
7849 if (total_data
< 10) {
7850 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7854 if (IVAL(pdata
,0) > total_data
) {
7855 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7856 IVAL(pdata
,0), (unsigned int)total_data
));
7857 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7861 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7868 /* If total_data == 4 Windows doesn't care what values
7869 * are placed in that field, it just ignores them.
7870 * The System i QNTC IBM SMB client puts bad values here,
7871 * so ignore them. */
7873 status
= create_directory(conn
, req
, smb_dname
);
7875 if (!NT_STATUS_IS_OK(status
)) {
7876 reply_nterror(req
, status
);
7880 /* Try and set any given EA. */
7882 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7883 if (!NT_STATUS_IS_OK(status
)) {
7884 reply_nterror(req
, status
);
7889 /* Realloc the parameter and data sizes */
7890 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7891 if(*pparams
== NULL
) {
7892 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7899 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7902 TALLOC_FREE(smb_dname
);
7906 /****************************************************************************
7907 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7908 We don't actually do this - we just send a null response.
7909 ****************************************************************************/
7911 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7912 struct smb_request
*req
,
7913 char **pparams
, int total_params
,
7914 char **ppdata
, int total_data
,
7915 unsigned int max_data_bytes
)
7917 char *params
= *pparams
;
7920 if (total_params
< 6) {
7921 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7925 info_level
= SVAL(params
,4);
7926 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7928 switch (info_level
) {
7933 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7937 /* Realloc the parameter and data sizes */
7938 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7939 if (*pparams
== NULL
) {
7940 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7945 SSVAL(params
,0,fnf_handle
);
7946 SSVAL(params
,2,0); /* No changes */
7947 SSVAL(params
,4,0); /* No EA errors */
7954 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7959 /****************************************************************************
7960 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7961 changes). Currently this does nothing.
7962 ****************************************************************************/
7964 static void call_trans2findnotifynext(connection_struct
*conn
,
7965 struct smb_request
*req
,
7966 char **pparams
, int total_params
,
7967 char **ppdata
, int total_data
,
7968 unsigned int max_data_bytes
)
7970 char *params
= *pparams
;
7972 DEBUG(3,("call_trans2findnotifynext\n"));
7974 /* Realloc the parameter and data sizes */
7975 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7976 if (*pparams
== NULL
) {
7977 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7982 SSVAL(params
,0,0); /* No changes */
7983 SSVAL(params
,2,0); /* No EA errors */
7985 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7990 /****************************************************************************
7991 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7992 ****************************************************************************/
7994 static void call_trans2getdfsreferral(connection_struct
*conn
,
7995 struct smb_request
*req
,
7996 char **pparams
, int total_params
,
7997 char **ppdata
, int total_data
,
7998 unsigned int max_data_bytes
)
8000 char *params
= *pparams
;
8001 char *pathname
= NULL
;
8003 int max_referral_level
;
8004 NTSTATUS status
= NT_STATUS_OK
;
8005 TALLOC_CTX
*ctx
= talloc_tos();
8007 DEBUG(10,("call_trans2getdfsreferral\n"));
8009 if (total_params
< 3) {
8010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8014 max_referral_level
= SVAL(params
,0);
8016 if(!lp_host_msdfs()) {
8017 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
8021 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8022 total_params
- 2, STR_TERMINATE
);
8024 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8027 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8028 ppdata
,&status
)) < 0) {
8029 reply_nterror(req
, status
);
8033 SSVAL(req
->inbuf
, smb_flg2
,
8034 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8035 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8040 #define LMCAT_SPL 0x53
8041 #define LMFUNC_GETJOBID 0x60
8043 /****************************************************************************
8044 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8045 ****************************************************************************/
8047 static void call_trans2ioctl(connection_struct
*conn
,
8048 struct smb_request
*req
,
8049 char **pparams
, int total_params
,
8050 char **ppdata
, int total_data
,
8051 unsigned int max_data_bytes
)
8053 char *pdata
= *ppdata
;
8054 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8056 /* check for an invalid fid before proceeding */
8059 reply_doserror(req
, ERRDOS
, ERRbadfid
);
8063 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8064 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8065 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8066 if (*ppdata
== NULL
) {
8067 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8072 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8073 CAN ACCEPT THIS IN UNICODE. JRA. */
8075 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8076 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8077 global_myname(), 15,
8078 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8079 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8080 lp_servicename(SNUM(conn
)), 13,
8081 STR_ASCII
|STR_TERMINATE
); /* Service name */
8082 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8087 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8088 reply_doserror(req
, ERRSRV
, ERRerror
);
8091 /****************************************************************************
8092 Reply to a SMBfindclose (stop trans2 directory search).
8093 ****************************************************************************/
8095 void reply_findclose(struct smb_request
*req
)
8098 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8100 START_PROFILE(SMBfindclose
);
8103 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8104 END_PROFILE(SMBfindclose
);
8108 dptr_num
= SVALS(req
->vwv
+0, 0);
8110 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8112 dptr_close(sconn
, &dptr_num
);
8114 reply_outbuf(req
, 0, 0);
8116 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8118 END_PROFILE(SMBfindclose
);
8122 /****************************************************************************
8123 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8124 ****************************************************************************/
8126 void reply_findnclose(struct smb_request
*req
)
8130 START_PROFILE(SMBfindnclose
);
8133 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8134 END_PROFILE(SMBfindnclose
);
8138 dptr_num
= SVAL(req
->vwv
+0, 0);
8140 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8142 /* We never give out valid handles for a
8143 findnotifyfirst - so any dptr_num is ok here.
8146 reply_outbuf(req
, 0, 0);
8148 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8150 END_PROFILE(SMBfindnclose
);
8154 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8155 struct trans_state
*state
)
8157 if (Protocol
>= PROTOCOL_NT1
) {
8158 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8159 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8162 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8163 if (state
->call
!= TRANSACT2_QFSINFO
&&
8164 state
->call
!= TRANSACT2_SETFSINFO
) {
8165 DEBUG(0,("handle_trans2: encryption required "
8167 (unsigned int)state
->call
));
8168 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8173 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8175 /* Now we must call the relevant TRANS2 function */
8176 switch(state
->call
) {
8177 case TRANSACT2_OPEN
:
8179 START_PROFILE(Trans2_open
);
8180 call_trans2open(conn
, req
,
8181 &state
->param
, state
->total_param
,
8182 &state
->data
, state
->total_data
,
8183 state
->max_data_return
);
8184 END_PROFILE(Trans2_open
);
8188 case TRANSACT2_FINDFIRST
:
8190 START_PROFILE(Trans2_findfirst
);
8191 call_trans2findfirst(conn
, req
,
8192 &state
->param
, state
->total_param
,
8193 &state
->data
, state
->total_data
,
8194 state
->max_data_return
);
8195 END_PROFILE(Trans2_findfirst
);
8199 case TRANSACT2_FINDNEXT
:
8201 START_PROFILE(Trans2_findnext
);
8202 call_trans2findnext(conn
, req
,
8203 &state
->param
, state
->total_param
,
8204 &state
->data
, state
->total_data
,
8205 state
->max_data_return
);
8206 END_PROFILE(Trans2_findnext
);
8210 case TRANSACT2_QFSINFO
:
8212 START_PROFILE(Trans2_qfsinfo
);
8213 call_trans2qfsinfo(conn
, req
,
8214 &state
->param
, state
->total_param
,
8215 &state
->data
, state
->total_data
,
8216 state
->max_data_return
);
8217 END_PROFILE(Trans2_qfsinfo
);
8221 case TRANSACT2_SETFSINFO
:
8223 START_PROFILE(Trans2_setfsinfo
);
8224 call_trans2setfsinfo(conn
, req
,
8225 &state
->param
, state
->total_param
,
8226 &state
->data
, state
->total_data
,
8227 state
->max_data_return
);
8228 END_PROFILE(Trans2_setfsinfo
);
8232 case TRANSACT2_QPATHINFO
:
8233 case TRANSACT2_QFILEINFO
:
8235 START_PROFILE(Trans2_qpathinfo
);
8236 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8237 &state
->param
, state
->total_param
,
8238 &state
->data
, state
->total_data
,
8239 state
->max_data_return
);
8240 END_PROFILE(Trans2_qpathinfo
);
8244 case TRANSACT2_SETPATHINFO
:
8245 case TRANSACT2_SETFILEINFO
:
8247 START_PROFILE(Trans2_setpathinfo
);
8248 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8249 &state
->param
, state
->total_param
,
8250 &state
->data
, state
->total_data
,
8251 state
->max_data_return
);
8252 END_PROFILE(Trans2_setpathinfo
);
8256 case TRANSACT2_FINDNOTIFYFIRST
:
8258 START_PROFILE(Trans2_findnotifyfirst
);
8259 call_trans2findnotifyfirst(conn
, req
,
8260 &state
->param
, state
->total_param
,
8261 &state
->data
, state
->total_data
,
8262 state
->max_data_return
);
8263 END_PROFILE(Trans2_findnotifyfirst
);
8267 case TRANSACT2_FINDNOTIFYNEXT
:
8269 START_PROFILE(Trans2_findnotifynext
);
8270 call_trans2findnotifynext(conn
, req
,
8271 &state
->param
, state
->total_param
,
8272 &state
->data
, state
->total_data
,
8273 state
->max_data_return
);
8274 END_PROFILE(Trans2_findnotifynext
);
8278 case TRANSACT2_MKDIR
:
8280 START_PROFILE(Trans2_mkdir
);
8281 call_trans2mkdir(conn
, req
,
8282 &state
->param
, state
->total_param
,
8283 &state
->data
, state
->total_data
,
8284 state
->max_data_return
);
8285 END_PROFILE(Trans2_mkdir
);
8289 case TRANSACT2_GET_DFS_REFERRAL
:
8291 START_PROFILE(Trans2_get_dfs_referral
);
8292 call_trans2getdfsreferral(conn
, req
,
8293 &state
->param
, state
->total_param
,
8294 &state
->data
, state
->total_data
,
8295 state
->max_data_return
);
8296 END_PROFILE(Trans2_get_dfs_referral
);
8300 case TRANSACT2_IOCTL
:
8302 START_PROFILE(Trans2_ioctl
);
8303 call_trans2ioctl(conn
, req
,
8304 &state
->param
, state
->total_param
,
8305 &state
->data
, state
->total_data
,
8306 state
->max_data_return
);
8307 END_PROFILE(Trans2_ioctl
);
8312 /* Error in request */
8313 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8314 reply_doserror(req
, ERRSRV
,ERRerror
);
8318 /****************************************************************************
8319 Reply to a SMBtrans2.
8320 ****************************************************************************/
8322 void reply_trans2(struct smb_request
*req
)
8324 connection_struct
*conn
= req
->conn
;
8329 unsigned int tran_call
;
8330 struct trans_state
*state
;
8333 START_PROFILE(SMBtrans2
);
8335 if (req
->wct
< 14) {
8336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8337 END_PROFILE(SMBtrans2
);
8341 dsoff
= SVAL(req
->vwv
+12, 0);
8342 dscnt
= SVAL(req
->vwv
+11, 0);
8343 psoff
= SVAL(req
->vwv
+10, 0);
8344 pscnt
= SVAL(req
->vwv
+9, 0);
8345 tran_call
= SVAL(req
->vwv
+14, 0);
8347 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8348 if (!NT_STATUS_IS_OK(result
)) {
8349 DEBUG(2, ("Got invalid trans2 request: %s\n",
8350 nt_errstr(result
)));
8351 reply_nterror(req
, result
);
8352 END_PROFILE(SMBtrans2
);
8357 switch (tran_call
) {
8358 /* List the allowed trans2 calls on IPC$ */
8359 case TRANSACT2_OPEN
:
8360 case TRANSACT2_GET_DFS_REFERRAL
:
8361 case TRANSACT2_QFILEINFO
:
8362 case TRANSACT2_QFSINFO
:
8363 case TRANSACT2_SETFSINFO
:
8366 reply_doserror(req
, ERRSRV
, ERRaccess
);
8367 END_PROFILE(SMBtrans2
);
8372 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8373 DEBUG(0, ("talloc failed\n"));
8374 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8375 END_PROFILE(SMBtrans2
);
8379 state
->cmd
= SMBtrans2
;
8381 state
->mid
= req
->mid
;
8382 state
->vuid
= req
->vuid
;
8383 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8384 state
->setup
= NULL
;
8385 state
->total_param
= SVAL(req
->vwv
+0, 0);
8386 state
->param
= NULL
;
8387 state
->total_data
= SVAL(req
->vwv
+1, 0);
8389 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8390 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8391 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8392 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8393 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8395 state
->call
= tran_call
;
8397 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8398 is so as a sanity check */
8399 if (state
->setup_count
!= 1) {
8401 * Need to have rc=0 for ioctl to get job id for OS/2.
8402 * Network printing will fail if function is not successful.
8403 * Similar function in reply.c will be used if protocol
8404 * is LANMAN1.0 instead of LM1.2X002.
8405 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8406 * outbuf doesn't have to be set(only job id is used).
8408 if ( (state
->setup_count
== 4)
8409 && (tran_call
== TRANSACT2_IOCTL
)
8410 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8411 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8412 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8414 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8415 DEBUG(2,("Transaction is %d\n",tran_call
));
8417 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8418 END_PROFILE(SMBtrans2
);
8423 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8426 if (state
->total_data
) {
8428 if (trans_oob(state
->total_data
, 0, dscnt
)
8429 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8433 /* Can't use talloc here, the core routines do realloc on the
8434 * params and data. */
8435 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8436 if (state
->data
== NULL
) {
8437 DEBUG(0,("reply_trans2: data malloc fail for %u "
8438 "bytes !\n", (unsigned int)state
->total_data
));
8440 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8441 END_PROFILE(SMBtrans2
);
8445 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8448 if (state
->total_param
) {
8450 if (trans_oob(state
->total_param
, 0, pscnt
)
8451 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8455 /* Can't use talloc here, the core routines do realloc on the
8456 * params and data. */
8457 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8458 if (state
->param
== NULL
) {
8459 DEBUG(0,("reply_trans: param malloc fail for %u "
8460 "bytes !\n", (unsigned int)state
->total_param
));
8461 SAFE_FREE(state
->data
);
8463 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8464 END_PROFILE(SMBtrans2
);
8468 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8471 state
->received_data
= dscnt
;
8472 state
->received_param
= pscnt
;
8474 if ((state
->received_param
== state
->total_param
) &&
8475 (state
->received_data
== state
->total_data
)) {
8477 handle_trans2(conn
, req
, state
);
8479 SAFE_FREE(state
->data
);
8480 SAFE_FREE(state
->param
);
8482 END_PROFILE(SMBtrans2
);
8486 DLIST_ADD(conn
->pending_trans
, state
);
8488 /* We need to send an interim response then receive the rest
8489 of the parameter/data bytes */
8490 reply_outbuf(req
, 0, 0);
8491 show_msg((char *)req
->outbuf
);
8492 END_PROFILE(SMBtrans2
);
8497 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8498 SAFE_FREE(state
->data
);
8499 SAFE_FREE(state
->param
);
8501 END_PROFILE(SMBtrans2
);
8502 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8506 /****************************************************************************
8507 Reply to a SMBtranss2
8508 ****************************************************************************/
8510 void reply_transs2(struct smb_request
*req
)
8512 connection_struct
*conn
= req
->conn
;
8513 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8514 struct trans_state
*state
;
8516 START_PROFILE(SMBtranss2
);
8518 show_msg((char *)req
->inbuf
);
8521 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8522 END_PROFILE(SMBtranss2
);
8526 for (state
= conn
->pending_trans
; state
!= NULL
;
8527 state
= state
->next
) {
8528 if (state
->mid
== req
->mid
) {
8533 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8535 END_PROFILE(SMBtranss2
);
8539 /* Revise state->total_param and state->total_data in case they have
8540 changed downwards */
8542 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8543 state
->total_param
= SVAL(req
->vwv
+0, 0);
8544 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8545 state
->total_data
= SVAL(req
->vwv
+1, 0);
8547 pcnt
= SVAL(req
->vwv
+2, 0);
8548 poff
= SVAL(req
->vwv
+3, 0);
8549 pdisp
= SVAL(req
->vwv
+4, 0);
8551 dcnt
= SVAL(req
->vwv
+5, 0);
8552 doff
= SVAL(req
->vwv
+6, 0);
8553 ddisp
= SVAL(req
->vwv
+7, 0);
8555 state
->received_param
+= pcnt
;
8556 state
->received_data
+= dcnt
;
8558 if ((state
->received_data
> state
->total_data
) ||
8559 (state
->received_param
> state
->total_param
))
8563 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8564 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8567 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8571 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8572 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8575 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8578 if ((state
->received_param
< state
->total_param
) ||
8579 (state
->received_data
< state
->total_data
)) {
8580 END_PROFILE(SMBtranss2
);
8584 handle_trans2(conn
, req
, state
);
8586 DLIST_REMOVE(conn
->pending_trans
, state
);
8587 SAFE_FREE(state
->data
);
8588 SAFE_FREE(state
->param
);
8591 END_PROFILE(SMBtranss2
);
8596 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8597 DLIST_REMOVE(conn
->pending_trans
, state
);
8598 SAFE_FREE(state
->data
);
8599 SAFE_FREE(state
->param
);
8601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8602 END_PROFILE(SMBtranss2
);