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"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "libcli/security/security.h"
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct
*conn
,
39 const SMB_STRUCT_STAT
*psbuf
);
41 static char *store_file_unix_basic_info2(connection_struct
*conn
,
44 const SMB_STRUCT_STAT
*psbuf
);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
53 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type
= get_remote_arch();
57 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
58 val
= SMB_ROUNDUP(val
,rval
);
63 /********************************************************************
64 Create a 64 bit FileIndex. If the file is on the same device as
65 the root of the share, just return the 64-bit inode. If it isn't,
66 mangle as we used to do.
67 ********************************************************************/
69 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
72 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
73 return (uint64_t)psbuf
->st_ex_ino
;
75 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
76 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
80 /****************************************************************************
81 Utility functions for dealing with extended attributes.
82 ****************************************************************************/
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static bool samba_private_attr_name(const char *unix_ea_name
)
90 static const char * const prohibited_ea_names
[] = {
91 SAMBA_POSIX_INHERITANCE_EA_NAME
,
92 SAMBA_XATTR_DOS_ATTRIB
,
100 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
101 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
104 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
105 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
111 /****************************************************************************
112 Get one EA value. Fill in a struct ea_struct.
113 ****************************************************************************/
115 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
116 files_struct
*fsp
, const char *fname
,
117 const char *ea_name
, struct ea_struct
*pea
)
119 /* Get the value of this xattr. Max size is 64k. */
120 size_t attr_size
= 256;
126 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
128 return NT_STATUS_NO_MEMORY
;
131 if (fsp
&& fsp
->fh
->fd
!= -1) {
132 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
134 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
137 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
143 return map_nt_error_from_unix(errno
);
146 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
147 dump_data(10, (uint8
*)val
, sizeret
);
150 if (strnequal(ea_name
, "user.", 5)) {
151 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
153 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
155 if (pea
->name
== NULL
) {
157 return NT_STATUS_NO_MEMORY
;
159 pea
->value
.data
= (unsigned char *)val
;
160 pea
->value
.length
= (size_t)sizeret
;
164 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
165 files_struct
*fsp
, const char *fname
,
166 char ***pnames
, size_t *pnum_names
)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size
= 1024;
170 char *ea_namelist
= NULL
;
175 ssize_t sizeret
= -1;
177 if (!lp_ea_support(SNUM(conn
))) {
186 * TALLOC the result early to get the talloc hierarchy right.
189 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
191 DEBUG(0, ("talloc failed\n"));
192 return NT_STATUS_NO_MEMORY
;
195 while (ea_namelist_size
<= 65536) {
197 ea_namelist
= TALLOC_REALLOC_ARRAY(
198 names
, ea_namelist
, char, ea_namelist_size
);
199 if (ea_namelist
== NULL
) {
200 DEBUG(0, ("talloc failed\n"));
202 return NT_STATUS_NO_MEMORY
;
205 if (fsp
&& fsp
->fh
->fd
!= -1) {
206 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
209 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
213 if ((sizeret
== -1) && (errno
== ERANGE
)) {
214 ea_namelist_size
*= 2;
223 return map_nt_error_from_unix(errno
);
226 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
227 (unsigned int)sizeret
));
239 * Ensure the result is 0-terminated
242 if (ea_namelist
[sizeret
-1] != '\0') {
244 return NT_STATUS_INTERNAL_ERROR
;
252 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
256 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
258 DEBUG(0, ("talloc failed\n"));
260 return NT_STATUS_NO_MEMORY
;
266 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
267 names
[num_names
++] = p
;
275 *pnum_names
= num_names
;
279 /****************************************************************************
280 Return a linked list of the total EA's. Plus the total size
281 ****************************************************************************/
283 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
284 const char *fname
, size_t *pea_total_len
)
286 /* Get a list of all xattrs. Max namesize is 64k. */
289 struct ea_list
*ea_list_head
= NULL
;
294 if (!lp_ea_support(SNUM(conn
))) {
298 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
301 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
305 for (i
=0; i
<num_names
; i
++) {
306 struct ea_list
*listp
;
309 if (strnequal(names
[i
], "system.", 7)
310 || samba_private_attr_name(names
[i
]))
313 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
318 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
324 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
327 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
329 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
330 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
331 (unsigned int)listp
->ea
.value
.length
));
333 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
337 /* Add on 4 for total length. */
338 if (*pea_total_len
) {
342 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
343 (unsigned int)*pea_total_len
));
348 /****************************************************************************
349 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
351 ****************************************************************************/
353 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
354 connection_struct
*conn
, struct ea_list
*ea_list
)
356 unsigned int ret_data_size
= 4;
359 SMB_ASSERT(total_data_size
>= 4);
361 if (!lp_ea_support(SNUM(conn
))) {
366 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
369 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
370 dos_namelen
= strlen(dos_ea_name
);
371 if (dos_namelen
> 255 || dos_namelen
== 0) {
374 if (ea_list
->ea
.value
.length
> 65535) {
377 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
381 /* We know we have room. */
382 SCVAL(p
,0,ea_list
->ea
.flags
);
383 SCVAL(p
,1,dos_namelen
);
384 SSVAL(p
,2,ea_list
->ea
.value
.length
);
385 fstrcpy(p
+4, dos_ea_name
);
386 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
388 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
389 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
392 ret_data_size
= PTR_DIFF(p
, pdata
);
393 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
394 SIVAL(pdata
,0,ret_data_size
);
395 return ret_data_size
;
398 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
400 unsigned int total_data_size
,
401 unsigned int *ret_data_size
,
402 connection_struct
*conn
,
403 struct ea_list
*ea_list
)
405 uint8_t *p
= (uint8_t *)pdata
;
406 uint8_t *last_start
= NULL
;
410 if (!lp_ea_support(SNUM(conn
))) {
411 return NT_STATUS_NO_EAS_ON_FILE
;
414 for (; ea_list
; ea_list
= ea_list
->next
) {
420 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
424 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
425 dos_namelen
= strlen(dos_ea_name
);
426 if (dos_namelen
> 255 || dos_namelen
== 0) {
427 return NT_STATUS_INTERNAL_ERROR
;
429 if (ea_list
->ea
.value
.length
> 65535) {
430 return NT_STATUS_INTERNAL_ERROR
;
433 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
436 size_t pad
= 4 - (this_size
% 4);
440 if (this_size
> total_data_size
) {
441 return NT_STATUS_INFO_LENGTH_MISMATCH
;
444 /* We know we have room. */
445 SIVAL(p
, 0x00, 0); /* next offset */
446 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
447 SCVAL(p
, 0x05, dos_namelen
);
448 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
449 fstrcpy((char *)(p
+0x08), dos_ea_name
);
450 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
452 total_data_size
-= this_size
;
456 *ret_data_size
= PTR_DIFF(p
, pdata
);
457 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
461 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
463 size_t total_ea_len
= 0;
464 TALLOC_CTX
*mem_ctx
= NULL
;
466 if (!lp_ea_support(SNUM(conn
))) {
469 mem_ctx
= talloc_tos();
470 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
474 /****************************************************************************
475 Ensure the EA name is case insensitive by matching any existing EA name.
476 ****************************************************************************/
478 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
481 TALLOC_CTX
*mem_ctx
= talloc_tos();
482 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
484 for (; ea_list
; ea_list
= ea_list
->next
) {
485 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
486 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
487 &unix_ea_name
[5], ea_list
->ea
.name
));
488 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
494 /****************************************************************************
495 Set or delete an extended attribute.
496 ****************************************************************************/
498 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
499 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
503 if (!lp_ea_support(SNUM(conn
))) {
504 return NT_STATUS_EAS_NOT_SUPPORTED
;
507 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
508 return NT_STATUS_ACCESS_DENIED
;
511 /* For now setting EAs on streams isn't supported. */
512 fname
= smb_fname
->base_name
;
514 for (;ea_list
; ea_list
= ea_list
->next
) {
516 fstring unix_ea_name
;
518 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
519 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
521 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
523 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
525 if (samba_private_attr_name(unix_ea_name
)) {
526 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
527 return NT_STATUS_ACCESS_DENIED
;
530 if (ea_list
->ea
.value
.length
== 0) {
531 /* Remove the attribute. */
532 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
533 DEBUG(10,("set_ea: deleting ea name %s on "
534 "file %s by file descriptor.\n",
535 unix_ea_name
, fsp_str_dbg(fsp
)));
536 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
538 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
539 unix_ea_name
, fname
));
540 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
543 /* Removing a non existent attribute always succeeds. */
544 if (ret
== -1 && errno
== ENOATTR
) {
545 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
551 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
552 DEBUG(10,("set_ea: setting ea name %s on file "
553 "%s by file descriptor.\n",
554 unix_ea_name
, fsp_str_dbg(fsp
)));
555 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
556 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
558 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
559 unix_ea_name
, fname
));
560 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
561 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
567 if (errno
== ENOTSUP
) {
568 return NT_STATUS_EAS_NOT_SUPPORTED
;
571 return map_nt_error_from_unix(errno
);
577 /****************************************************************************
578 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
583 struct ea_list
*ea_list_head
= NULL
;
584 size_t converted_size
, offset
= 0;
586 while (offset
+ 2 < data_size
) {
587 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
588 unsigned int namelen
= CVAL(pdata
,offset
);
590 offset
++; /* Go past the namelen byte. */
592 /* integer wrap paranioa. */
593 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
594 (offset
> data_size
) || (namelen
> data_size
) ||
595 (offset
+ namelen
>= data_size
)) {
598 /* Ensure the name is null terminated. */
599 if (pdata
[offset
+ namelen
] != '\0') {
602 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
604 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
605 "failed: %s", strerror(errno
)));
611 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
612 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
613 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
619 /****************************************************************************
620 Read one EA list entry from the buffer.
621 ****************************************************************************/
623 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
625 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
627 unsigned int namelen
;
628 size_t converted_size
;
638 eal
->ea
.flags
= CVAL(pdata
,0);
639 namelen
= CVAL(pdata
,1);
640 val_len
= SVAL(pdata
,2);
642 if (4 + namelen
+ 1 + val_len
> data_size
) {
646 /* Ensure the name is null terminated. */
647 if (pdata
[namelen
+ 4] != '\0') {
650 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
651 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
658 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
659 if (!eal
->ea
.value
.data
) {
663 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
665 /* Ensure we're null terminated just in case we print the value. */
666 eal
->ea
.value
.data
[val_len
] = '\0';
667 /* But don't count the null. */
668 eal
->ea
.value
.length
--;
671 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
674 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
675 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
680 /****************************************************************************
681 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
682 ****************************************************************************/
684 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
686 struct ea_list
*ea_list_head
= NULL
;
688 size_t bytes_used
= 0;
690 while (offset
< data_size
) {
691 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
697 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
698 offset
+= bytes_used
;
704 /****************************************************************************
705 Count the total EA size needed.
706 ****************************************************************************/
708 static size_t ea_list_size(struct ea_list
*ealist
)
711 struct ea_list
*listp
;
714 for (listp
= ealist
; listp
; listp
= listp
->next
) {
715 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
716 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
718 /* Add on 4 for total length. */
726 /****************************************************************************
727 Return a union of EA's from a file list and a list of names.
728 The TALLOC context for the two lists *MUST* be identical as we steal
729 memory from one list to add to another. JRA.
730 ****************************************************************************/
732 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
734 struct ea_list
*nlistp
, *flistp
;
736 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
737 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
738 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
744 /* Copy the data from this entry. */
745 nlistp
->ea
.flags
= flistp
->ea
.flags
;
746 nlistp
->ea
.value
= flistp
->ea
.value
;
749 nlistp
->ea
.flags
= 0;
750 ZERO_STRUCT(nlistp
->ea
.value
);
754 *total_ea_len
= ea_list_size(name_list
);
758 /****************************************************************************
759 Send the required number of replies back.
760 We assume all fields other than the data fields are
761 set correctly for the type of call.
762 HACK ! Always assumes smb_setup field is zero.
763 ****************************************************************************/
765 void send_trans2_replies(connection_struct
*conn
,
766 struct smb_request
*req
,
773 /* As we are using a protocol > LANMAN1 then the max_send
774 variable must have been set in the sessetupX call.
775 This takes precedence over the max_xmit field in the
776 global struct. These different max_xmit variables should
777 be merged as this is now too confusing */
779 int data_to_send
= datasize
;
780 int params_to_send
= paramsize
;
782 const char *pp
= params
;
783 const char *pd
= pdata
;
784 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
785 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
786 int data_alignment_offset
= 0;
787 bool overflow
= False
;
788 struct smbd_server_connection
*sconn
= req
->sconn
;
789 int max_send
= sconn
->smb1
.sessions
.max_send
;
791 /* Modify the data_to_send and datasize and set the error if
792 we're trying to send more than max_data_bytes. We still send
793 the part of the packet(s) that fit. Strange, but needed
796 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
797 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
798 max_data_bytes
, datasize
));
799 datasize
= data_to_send
= max_data_bytes
;
803 /* If there genuinely are no parameters or data to send just send the empty packet */
805 if(params_to_send
== 0 && data_to_send
== 0) {
806 reply_outbuf(req
, 10, 0);
807 show_msg((char *)req
->outbuf
);
808 if (!srv_send_smb(sconn
,
811 IS_CONN_ENCRYPTED(conn
),
813 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
815 TALLOC_FREE(req
->outbuf
);
819 /* When sending params and data ensure that both are nicely aligned */
820 /* Only do this alignment when there is also data to send - else
821 can cause NT redirector problems. */
823 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
824 data_alignment_offset
= 4 - (params_to_send
% 4);
826 /* Space is bufsize minus Netbios over TCP header minus SMB header */
827 /* The alignment_offset is to align the param bytes on an even byte
828 boundary. NT 4.0 Beta needs this to work correctly. */
830 useable_space
= max_send
- (smb_size
833 + data_alignment_offset
);
835 if (useable_space
< 0) {
836 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
837 "= %d!!!", useable_space
));
838 exit_server_cleanly("send_trans2_replies: Not enough space");
841 while (params_to_send
|| data_to_send
) {
842 /* Calculate whether we will totally or partially fill this packet */
844 total_sent_thistime
= params_to_send
+ data_to_send
;
846 /* We can never send more than useable_space */
848 * Note that 'useable_space' does not include the alignment offsets,
849 * but we must include the alignment offsets in the calculation of
850 * the length of the data we send over the wire, as the alignment offsets
851 * are sent here. Fix from Marc_Jacobsen@hp.com.
854 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
856 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
857 + data_alignment_offset
);
860 * We might have SMBtrans2s in req which was transferred to
861 * the outbuf, fix that.
863 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
865 /* Set total params and data to be sent */
866 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
867 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
869 /* Calculate how many parameters and data we can fit into
870 * this packet. Parameters get precedence
873 params_sent_thistime
= MIN(params_to_send
,useable_space
);
874 data_sent_thistime
= useable_space
- params_sent_thistime
;
875 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
877 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
879 /* smb_proff is the offset from the start of the SMB header to the
880 parameter bytes, however the first 4 bytes of outbuf are
881 the Netbios over TCP header. Thus use smb_base() to subtract
882 them from the calculation */
884 SSVAL(req
->outbuf
,smb_proff
,
885 ((smb_buf(req
->outbuf
)+alignment_offset
)
886 - smb_base(req
->outbuf
)));
888 if(params_sent_thistime
== 0)
889 SSVAL(req
->outbuf
,smb_prdisp
,0);
891 /* Absolute displacement of param bytes sent in this packet */
892 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
894 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
895 if(data_sent_thistime
== 0) {
896 SSVAL(req
->outbuf
,smb_droff
,0);
897 SSVAL(req
->outbuf
,smb_drdisp
, 0);
899 /* The offset of the data bytes is the offset of the
900 parameter bytes plus the number of parameters being sent this time */
901 SSVAL(req
->outbuf
, smb_droff
,
902 ((smb_buf(req
->outbuf
)+alignment_offset
)
903 - smb_base(req
->outbuf
))
904 + params_sent_thistime
+ data_alignment_offset
);
905 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
908 /* Initialize the padding for alignment */
910 if (alignment_offset
!= 0) {
911 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
914 /* Copy the param bytes into the packet */
916 if(params_sent_thistime
) {
917 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
918 params_sent_thistime
);
921 /* Copy in the data bytes */
922 if(data_sent_thistime
) {
923 if (data_alignment_offset
!= 0) {
924 memset((smb_buf(req
->outbuf
)+alignment_offset
+
925 params_sent_thistime
), 0,
926 data_alignment_offset
);
928 memcpy(smb_buf(req
->outbuf
)+alignment_offset
929 +params_sent_thistime
+data_alignment_offset
,
930 pd
,data_sent_thistime
);
933 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
934 params_sent_thistime
, data_sent_thistime
, useable_space
));
935 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
936 params_to_send
, data_to_send
, paramsize
, datasize
));
939 error_packet_set((char *)req
->outbuf
,
940 ERRDOS
,ERRbufferoverflow
,
941 STATUS_BUFFER_OVERFLOW
,
945 /* Send the packet */
946 show_msg((char *)req
->outbuf
);
947 if (!srv_send_smb(sconn
,
950 IS_CONN_ENCRYPTED(conn
),
952 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
954 TALLOC_FREE(req
->outbuf
);
956 pp
+= params_sent_thistime
;
957 pd
+= data_sent_thistime
;
959 params_to_send
-= params_sent_thistime
;
960 data_to_send
-= data_sent_thistime
;
963 if(params_to_send
< 0 || data_to_send
< 0) {
964 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
965 params_to_send
, data_to_send
));
973 /****************************************************************************
974 Reply to a TRANSACT2_OPEN.
975 ****************************************************************************/
977 static void call_trans2open(connection_struct
*conn
,
978 struct smb_request
*req
,
979 char **pparams
, int total_params
,
980 char **ppdata
, int total_data
,
981 unsigned int max_data_bytes
)
983 struct smb_filename
*smb_fname
= NULL
;
984 char *params
= *pparams
;
985 char *pdata
= *ppdata
;
990 bool return_additional_info
;
1000 SMB_INO_T inode
= 0;
1003 struct ea_list
*ea_list
= NULL
;
1008 uint32 create_disposition
;
1009 uint32 create_options
= 0;
1010 uint32_t private_flags
= 0;
1011 TALLOC_CTX
*ctx
= talloc_tos();
1014 * Ensure we have enough parameters to perform the operation.
1017 if (total_params
< 29) {
1018 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1022 flags
= SVAL(params
, 0);
1023 deny_mode
= SVAL(params
, 2);
1024 open_attr
= SVAL(params
,6);
1025 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1026 if (oplock_request
) {
1027 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1031 return_additional_info
= BITSETW(params
,0);
1032 open_sattr
= SVAL(params
, 4);
1033 open_time
= make_unix_date3(params
+8);
1035 open_ofun
= SVAL(params
,12);
1036 open_size
= IVAL(params
,14);
1037 pname
= ¶ms
[28];
1040 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1044 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1045 total_params
- 28, STR_TERMINATE
,
1047 if (!NT_STATUS_IS_OK(status
)) {
1048 reply_nterror(req
, status
);
1052 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1053 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1054 (unsigned int)open_ofun
, open_size
));
1056 status
= filename_convert(ctx
,
1058 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1063 if (!NT_STATUS_IS_OK(status
)) {
1064 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1065 reply_botherror(req
,
1066 NT_STATUS_PATH_NOT_COVERED
,
1067 ERRSRV
, ERRbadpath
);
1070 reply_nterror(req
, status
);
1074 if (open_ofun
== 0) {
1075 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1079 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1080 &access_mask
, &share_mode
,
1081 &create_disposition
,
1084 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1088 /* Any data in this call is an EA list. */
1089 if (total_data
&& (total_data
!= 4)) {
1090 if (total_data
< 10) {
1091 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1095 if (IVAL(pdata
,0) > total_data
) {
1096 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1097 IVAL(pdata
,0), (unsigned int)total_data
));
1098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1102 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1109 if (!lp_ea_support(SNUM(conn
))) {
1110 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1115 status
= SMB_VFS_CREATE_FILE(
1118 0, /* root_dir_fid */
1119 smb_fname
, /* fname */
1120 access_mask
, /* access_mask */
1121 share_mode
, /* share_access */
1122 create_disposition
, /* create_disposition*/
1123 create_options
, /* create_options */
1124 open_attr
, /* file_attributes */
1125 oplock_request
, /* oplock_request */
1126 open_size
, /* allocation_size */
1129 ea_list
, /* ea_list */
1131 &smb_action
); /* psbuf */
1133 if (!NT_STATUS_IS_OK(status
)) {
1134 if (open_was_deferred(req
->mid
)) {
1135 /* We have re-scheduled this call. */
1138 reply_openerror(req
, status
);
1142 size
= get_file_size_stat(&smb_fname
->st
);
1143 fattr
= dos_mode(conn
, smb_fname
);
1144 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1145 inode
= smb_fname
->st
.st_ex_ino
;
1147 close_file(req
, fsp
, ERROR_CLOSE
);
1148 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1152 /* Realloc the size of parameters and data we will return */
1153 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1154 if(*pparams
== NULL
) {
1155 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1160 SSVAL(params
,0,fsp
->fnum
);
1161 SSVAL(params
,2,fattr
);
1162 srv_put_dos_date2(params
,4, mtime
);
1163 SIVAL(params
,8, (uint32
)size
);
1164 SSVAL(params
,12,deny_mode
);
1165 SSVAL(params
,14,0); /* open_type - file or directory. */
1166 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1168 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1169 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1172 SSVAL(params
,18,smb_action
);
1175 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1177 SIVAL(params
,20,inode
);
1178 SSVAL(params
,24,0); /* Padding. */
1180 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1181 fsp
->fsp_name
->base_name
);
1182 SIVAL(params
, 26, ea_size
);
1184 SIVAL(params
, 26, 0);
1187 /* Send the required number of replies */
1188 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1190 TALLOC_FREE(smb_fname
);
1193 /*********************************************************
1194 Routine to check if a given string matches exactly.
1195 as a special case a mask of "." does NOT match. That
1196 is required for correct wildcard semantics
1197 Case can be significant or not.
1198 **********************************************************/
1200 static bool exact_match(bool has_wild
,
1201 bool case_sensitive
,
1205 if (mask
[0] == '.' && mask
[1] == 0) {
1213 if (case_sensitive
) {
1214 return strcmp(str
,mask
)==0;
1216 return StrCaseCmp(str
,mask
) == 0;
1220 /****************************************************************************
1221 Return the filetype for UNIX extensions.
1222 ****************************************************************************/
1224 static uint32
unix_filetype(mode_t mode
)
1227 return UNIX_TYPE_FILE
;
1228 else if(S_ISDIR(mode
))
1229 return UNIX_TYPE_DIR
;
1231 else if(S_ISLNK(mode
))
1232 return UNIX_TYPE_SYMLINK
;
1235 else if(S_ISCHR(mode
))
1236 return UNIX_TYPE_CHARDEV
;
1239 else if(S_ISBLK(mode
))
1240 return UNIX_TYPE_BLKDEV
;
1243 else if(S_ISFIFO(mode
))
1244 return UNIX_TYPE_FIFO
;
1247 else if(S_ISSOCK(mode
))
1248 return UNIX_TYPE_SOCKET
;
1251 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1252 return UNIX_TYPE_UNKNOWN
;
1255 /****************************************************************************
1256 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1257 ****************************************************************************/
1259 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1261 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1262 const SMB_STRUCT_STAT
*psbuf
,
1264 enum perm_type ptype
,
1269 if (perms
== SMB_MODE_NO_CHANGE
) {
1270 if (!VALID_STAT(*psbuf
)) {
1271 return NT_STATUS_INVALID_PARAMETER
;
1273 *ret_perms
= psbuf
->st_ex_mode
;
1274 return NT_STATUS_OK
;
1278 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1279 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1280 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1281 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1282 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1283 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1284 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1285 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1286 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1288 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1291 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1294 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1299 /* Apply mode mask */
1300 ret
&= lp_create_mask(SNUM(conn
));
1301 /* Add in force bits */
1302 ret
|= lp_force_create_mode(SNUM(conn
));
1305 ret
&= lp_dir_mask(SNUM(conn
));
1306 /* Add in force bits */
1307 ret
|= lp_force_dir_mode(SNUM(conn
));
1309 case PERM_EXISTING_FILE
:
1310 /* Apply mode mask */
1311 ret
&= lp_security_mask(SNUM(conn
));
1312 /* Add in force bits */
1313 ret
|= lp_force_security_mode(SNUM(conn
));
1315 case PERM_EXISTING_DIR
:
1316 /* Apply mode mask */
1317 ret
&= lp_dir_security_mask(SNUM(conn
));
1318 /* Add in force bits */
1319 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1324 return NT_STATUS_OK
;
1327 /****************************************************************************
1328 Needed to show the msdfs symlinks as directories. Modifies psbuf
1329 to be a directory if it's a msdfs link.
1330 ****************************************************************************/
1332 static bool check_msdfs_link(connection_struct
*conn
,
1333 const char *pathname
,
1334 SMB_STRUCT_STAT
*psbuf
)
1336 int saved_errno
= errno
;
1337 if(lp_host_msdfs() &&
1338 lp_msdfs_root(SNUM(conn
)) &&
1339 is_msdfs_link(conn
, pathname
, psbuf
)) {
1341 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1344 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1345 errno
= saved_errno
;
1348 errno
= saved_errno
;
1353 /****************************************************************************
1354 Get a level dependent lanman2 dir entry.
1355 ****************************************************************************/
1357 struct smbd_dirptr_lanman2_state
{
1358 connection_struct
*conn
;
1359 uint32_t info_level
;
1360 bool check_mangled_names
;
1362 bool got_exact_match
;
1365 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1371 struct smbd_dirptr_lanman2_state
*state
=
1372 (struct smbd_dirptr_lanman2_state
*)private_data
;
1374 char mangled_name
[13]; /* mangled 8.3 name. */
1378 /* Mangle fname if it's an illegal name. */
1379 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1380 ok
= name_to_8_3(dname
, mangled_name
,
1381 true, state
->conn
->params
);
1385 fname
= mangled_name
;
1390 got_match
= exact_match(state
->has_wild
,
1391 state
->conn
->case_sensitive
,
1393 state
->got_exact_match
= got_match
;
1395 got_match
= mask_match(fname
, mask
,
1396 state
->conn
->case_sensitive
);
1399 if(!got_match
&& state
->check_mangled_names
&&
1400 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1402 * It turns out that NT matches wildcards against
1403 * both long *and* short names. This may explain some
1404 * of the wildcard wierdness from old DOS clients
1405 * that some people have been seeing.... JRA.
1407 /* Force the mangling into 8.3. */
1408 ok
= name_to_8_3(fname
, mangled_name
,
1409 false, state
->conn
->params
);
1414 got_match
= exact_match(state
->has_wild
,
1415 state
->conn
->case_sensitive
,
1416 mangled_name
, mask
);
1417 state
->got_exact_match
= got_match
;
1419 got_match
= mask_match(mangled_name
, mask
,
1420 state
->conn
->case_sensitive
);
1428 *_fname
= talloc_strdup(ctx
, fname
);
1429 if (*_fname
== NULL
) {
1436 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1438 struct smb_filename
*smb_fname
,
1441 struct smbd_dirptr_lanman2_state
*state
=
1442 (struct smbd_dirptr_lanman2_state
*)private_data
;
1443 bool ms_dfs_link
= false;
1446 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1447 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1448 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1449 "Couldn't lstat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname
),
1454 } else if (!VALID_STAT(smb_fname
->st
) &&
1455 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1456 /* Needed to show the msdfs symlinks as
1459 ms_dfs_link
= check_msdfs_link(state
->conn
,
1460 smb_fname
->base_name
,
1463 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1464 "Couldn't stat [%s] (%s)\n",
1465 smb_fname_str_dbg(smb_fname
),
1472 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1474 mode
= dos_mode(state
->conn
, smb_fname
);
1481 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1482 connection_struct
*conn
,
1484 uint32_t info_level
,
1485 struct ea_list
*name_list
,
1486 bool check_mangled_names
,
1487 bool requires_resume_key
,
1490 const struct smb_filename
*smb_fname
,
1491 int space_remaining
,
1498 uint64_t *last_entry_off
)
1500 char *p
, *q
, *pdata
= *ppdata
;
1502 uint64_t file_size
= 0;
1503 uint64_t allocation_size
= 0;
1504 uint64_t file_index
= 0;
1506 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1507 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1508 time_t c_date
= (time_t)0;
1510 char *last_entry_ptr
;
1515 *out_of_space
= false;
1517 ZERO_STRUCT(mdate_ts
);
1518 ZERO_STRUCT(adate_ts
);
1519 ZERO_STRUCT(create_date_ts
);
1520 ZERO_STRUCT(cdate_ts
);
1522 if (!(mode
& aDIR
)) {
1523 file_size
= get_file_size_stat(&smb_fname
->st
);
1525 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1527 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1529 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1530 adate_ts
= smb_fname
->st
.st_ex_atime
;
1531 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1532 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1534 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1535 dos_filetime_timespec(&create_date_ts
);
1536 dos_filetime_timespec(&mdate_ts
);
1537 dos_filetime_timespec(&adate_ts
);
1538 dos_filetime_timespec(&cdate_ts
);
1541 create_date
= convert_timespec_to_time_t(create_date_ts
);
1542 mdate
= convert_timespec_to_time_t(mdate_ts
);
1543 adate
= convert_timespec_to_time_t(adate_ts
);
1544 c_date
= convert_timespec_to_time_t(cdate_ts
);
1546 /* align the record */
1547 SMB_ASSERT(align
>= 1);
1549 off
= (int)PTR_DIFF(pdata
, base_data
);
1550 pad
= (off
+ (align
-1)) & ~(align
-1);
1553 if (pad
&& pad
> space_remaining
) {
1554 *out_of_space
= true;
1555 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1556 "for padding (wanted %u, had %d)\n",
1559 return false; /* Not finished - just out of space */
1563 /* initialize padding to 0 */
1565 memset(pdata
, 0, pad
);
1567 space_remaining
-= pad
;
1569 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1579 switch (info_level
) {
1580 case SMB_FIND_INFO_STANDARD
:
1581 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1582 if(requires_resume_key
) {
1586 srv_put_dos_date2(p
,0,create_date
);
1587 srv_put_dos_date2(p
,4,adate
);
1588 srv_put_dos_date2(p
,8,mdate
);
1589 SIVAL(p
,12,(uint32
)file_size
);
1590 SIVAL(p
,16,(uint32
)allocation_size
);
1594 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1595 p
+= ucs2_align(base_data
, p
, 0);
1597 len
= srvstr_push(base_data
, flags2
, p
,
1598 fname
, PTR_DIFF(end_data
, p
),
1600 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1602 SCVAL(nameptr
, -1, len
- 2);
1604 SCVAL(nameptr
, -1, 0);
1608 SCVAL(nameptr
, -1, len
- 1);
1610 SCVAL(nameptr
, -1, 0);
1616 case SMB_FIND_EA_SIZE
:
1617 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1618 if (requires_resume_key
) {
1622 srv_put_dos_date2(p
,0,create_date
);
1623 srv_put_dos_date2(p
,4,adate
);
1624 srv_put_dos_date2(p
,8,mdate
);
1625 SIVAL(p
,12,(uint32
)file_size
);
1626 SIVAL(p
,16,(uint32
)allocation_size
);
1629 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1630 smb_fname
->base_name
);
1631 SIVAL(p
,22,ea_size
); /* Extended attributes */
1635 len
= srvstr_push(base_data
, flags2
,
1636 p
, fname
, PTR_DIFF(end_data
, p
),
1637 STR_TERMINATE
| STR_NOALIGN
);
1638 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1651 SCVAL(nameptr
,0,len
);
1653 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1656 case SMB_FIND_EA_LIST
:
1658 struct ea_list
*file_list
= NULL
;
1661 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1665 if (requires_resume_key
) {
1669 srv_put_dos_date2(p
,0,create_date
);
1670 srv_put_dos_date2(p
,4,adate
);
1671 srv_put_dos_date2(p
,8,mdate
);
1672 SIVAL(p
,12,(uint32
)file_size
);
1673 SIVAL(p
,16,(uint32
)allocation_size
);
1675 p
+= 22; /* p now points to the EA area. */
1677 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1678 smb_fname
->base_name
,
1680 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1682 /* We need to determine if this entry will fit in the space available. */
1683 /* Max string size is 255 bytes. */
1684 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1685 *out_of_space
= true;
1686 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1687 "(wanted %u, had %d)\n",
1688 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1690 return False
; /* Not finished - just out of space */
1693 /* Push the ea_data followed by the name. */
1694 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1696 len
= srvstr_push(base_data
, flags2
,
1697 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1698 STR_TERMINATE
| STR_NOALIGN
);
1699 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1712 SCVAL(nameptr
,0,len
);
1714 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1718 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1720 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1722 SIVAL(p
,0,reskey
); p
+= 4;
1723 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1724 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1725 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1726 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1727 SOFF_T(p
,0,file_size
); p
+= 8;
1728 SOFF_T(p
,0,allocation_size
); p
+= 8;
1729 SIVAL(p
,0,mode
); p
+= 4;
1730 q
= p
; p
+= 4; /* q is placeholder for name length. */
1732 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1733 smb_fname
->base_name
);
1734 SIVAL(p
,0,ea_size
); /* Extended attributes */
1737 /* Clear the short name buffer. This is
1738 * IMPORTANT as not doing so will trigger
1739 * a Win2k client bug. JRA.
1741 if (!was_8_3
&& check_mangled_names
) {
1742 char mangled_name
[13]; /* mangled 8.3 name. */
1743 if (!name_to_8_3(fname
,mangled_name
,True
,
1745 /* Error - mangle failed ! */
1746 memset(mangled_name
,'\0',12);
1748 mangled_name
[12] = 0;
1749 len
= srvstr_push(base_data
, flags2
,
1750 p
+2, mangled_name
, 24,
1751 STR_UPPER
|STR_UNICODE
);
1753 memset(p
+ 2 + len
,'\0',24 - len
);
1760 len
= srvstr_push(base_data
, flags2
, p
,
1761 fname
, PTR_DIFF(end_data
, p
),
1762 STR_TERMINATE_ASCII
);
1766 len
= PTR_DIFF(p
, pdata
);
1767 pad
= (len
+ (align
-1)) & ~(align
-1);
1769 * offset to the next entry, the caller
1770 * will overwrite it for the last entry
1771 * that's why we always include the padding
1775 * set padding to zero
1778 memset(p
, 0, pad
- len
);
1785 case SMB_FIND_FILE_DIRECTORY_INFO
:
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1788 SIVAL(p
,0,reskey
); p
+= 4;
1789 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1790 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1791 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1792 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1793 SOFF_T(p
,0,file_size
); p
+= 8;
1794 SOFF_T(p
,0,allocation_size
); p
+= 8;
1795 SIVAL(p
,0,mode
); p
+= 4;
1796 len
= srvstr_push(base_data
, flags2
,
1797 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
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_FULL_DIRECTORY_INFO
:
1822 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1824 SIVAL(p
,0,reskey
); p
+= 4;
1825 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1826 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1827 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1828 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1829 SOFF_T(p
,0,file_size
); p
+= 8;
1830 SOFF_T(p
,0,allocation_size
); p
+= 8;
1831 SIVAL(p
,0,mode
); p
+= 4;
1832 q
= p
; p
+= 4; /* q is placeholder for name length. */
1834 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1835 smb_fname
->base_name
);
1836 SIVAL(p
,0,ea_size
); /* Extended attributes */
1839 len
= srvstr_push(base_data
, flags2
, p
,
1840 fname
, PTR_DIFF(end_data
, p
),
1841 STR_TERMINATE_ASCII
);
1845 len
= PTR_DIFF(p
, pdata
);
1846 pad
= (len
+ (align
-1)) & ~(align
-1);
1848 * offset to the next entry, the caller
1849 * will overwrite it for the last entry
1850 * that's why we always include the padding
1854 * set padding to zero
1857 memset(p
, 0, pad
- len
);
1864 case SMB_FIND_FILE_NAMES_INFO
:
1865 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1867 SIVAL(p
,0,reskey
); p
+= 4;
1869 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1870 acl on a dir (tridge) */
1871 len
= srvstr_push(base_data
, flags2
, p
,
1872 fname
, PTR_DIFF(end_data
, p
),
1873 STR_TERMINATE_ASCII
);
1877 len
= PTR_DIFF(p
, pdata
);
1878 pad
= (len
+ (align
-1)) & ~(align
-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1886 * set padding to zero
1889 memset(p
, 0, pad
- len
);
1896 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1899 SIVAL(p
,0,reskey
); p
+= 4;
1900 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1901 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1902 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1903 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1904 SOFF_T(p
,0,file_size
); p
+= 8;
1905 SOFF_T(p
,0,allocation_size
); p
+= 8;
1906 SIVAL(p
,0,mode
); p
+= 4;
1907 q
= p
; p
+= 4; /* q is placeholder for name length. */
1909 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1910 smb_fname
->base_name
);
1911 SIVAL(p
,0,ea_size
); /* Extended attributes */
1914 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1915 SBVAL(p
,0,file_index
); p
+= 8;
1916 len
= srvstr_push(base_data
, flags2
, p
,
1917 fname
, PTR_DIFF(end_data
, p
),
1918 STR_TERMINATE_ASCII
);
1922 len
= PTR_DIFF(p
, pdata
);
1923 pad
= (len
+ (align
-1)) & ~(align
-1);
1925 * offset to the next entry, the caller
1926 * will overwrite it for the last entry
1927 * that's why we always include the padding
1931 * set padding to zero
1934 memset(p
, 0, pad
- len
);
1941 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1943 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1945 SIVAL(p
,0,reskey
); p
+= 4;
1946 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1947 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1948 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1949 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1950 SOFF_T(p
,0,file_size
); p
+= 8;
1951 SOFF_T(p
,0,allocation_size
); p
+= 8;
1952 SIVAL(p
,0,mode
); p
+= 4;
1953 q
= p
; p
+= 4; /* q is placeholder for name length */
1955 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1956 smb_fname
->base_name
);
1957 SIVAL(p
,0,ea_size
); /* Extended attributes */
1960 /* Clear the short name buffer. This is
1961 * IMPORTANT as not doing so will trigger
1962 * a Win2k client bug. JRA.
1964 if (!was_8_3
&& check_mangled_names
) {
1965 char mangled_name
[13]; /* mangled 8.3 name. */
1966 if (!name_to_8_3(fname
,mangled_name
,True
,
1968 /* Error - mangle failed ! */
1969 memset(mangled_name
,'\0',12);
1971 mangled_name
[12] = 0;
1972 len
= srvstr_push(base_data
, flags2
,
1973 p
+2, mangled_name
, 24,
1974 STR_UPPER
|STR_UNICODE
);
1977 memset(p
+ 2 + len
,'\0',24 - len
);
1984 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1985 SBVAL(p
,0,file_index
); p
+= 8;
1986 len
= srvstr_push(base_data
, flags2
, p
,
1987 fname
, PTR_DIFF(end_data
, p
),
1988 STR_TERMINATE_ASCII
);
1992 len
= PTR_DIFF(p
, pdata
);
1993 pad
= (len
+ (align
-1)) & ~(align
-1);
1995 * offset to the next entry, the caller
1996 * will overwrite it for the last entry
1997 * that's why we always include the padding
2001 * set padding to zero
2004 memset(p
, 0, pad
- len
);
2011 /* CIFS UNIX Extension. */
2013 case SMB_FIND_FILE_UNIX
:
2014 case SMB_FIND_FILE_UNIX_INFO2
:
2016 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2018 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2020 if (info_level
== SMB_FIND_FILE_UNIX
) {
2021 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2022 p
= store_file_unix_basic(conn
, p
,
2023 NULL
, &smb_fname
->st
);
2024 len
= srvstr_push(base_data
, flags2
, p
,
2025 fname
, PTR_DIFF(end_data
, p
),
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2029 p
= store_file_unix_basic_info2(conn
, p
,
2030 NULL
, &smb_fname
->st
);
2033 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2034 PTR_DIFF(end_data
, p
), 0);
2035 SIVAL(nameptr
, 0, len
);
2040 len
= PTR_DIFF(p
, pdata
);
2041 pad
= (len
+ (align
-1)) & ~(align
-1);
2043 * offset to the next entry, the caller
2044 * will overwrite it for the last entry
2045 * that's why we always include the padding
2049 * set padding to zero
2052 memset(p
, 0, pad
- len
);
2057 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2065 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2066 *out_of_space
= true;
2067 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2068 "(wanted %u, had %d)\n",
2069 (unsigned int)PTR_DIFF(p
,pdata
),
2071 return false; /* Not finished - just out of space */
2074 /* Setup the last entry pointer, as an offset from base_data */
2075 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2076 /* Advance the data pointer to the next slot */
2082 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2083 connection_struct
*conn
,
2084 struct dptr_struct
*dirptr
,
2086 const char *path_mask
,
2089 int requires_resume_key
,
2097 int space_remaining
,
2099 bool *got_exact_match
,
2100 int *_last_entry_off
,
2101 struct ea_list
*name_list
)
2104 const char *mask
= NULL
;
2105 long prev_dirpos
= 0;
2108 struct smb_filename
*smb_fname
= NULL
;
2109 struct smbd_dirptr_lanman2_state state
;
2111 uint64_t last_entry_off
= 0;
2115 state
.info_level
= info_level
;
2116 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2117 state
.has_wild
= dptr_has_wild(dirptr
);
2118 state
.got_exact_match
= false;
2120 *out_of_space
= false;
2121 *got_exact_match
= false;
2123 p
= strrchr_m(path_mask
,'/');
2134 ok
= smbd_dirptr_get_entry(ctx
,
2140 smbd_dirptr_lanman2_match_fn
,
2141 smbd_dirptr_lanman2_mode_fn
,
2151 *got_exact_match
= state
.got_exact_match
;
2153 ok
= smbd_marshall_dir_entry(ctx
,
2158 state
.check_mangled_names
,
2159 requires_resume_key
,
2172 TALLOC_FREE(smb_fname
);
2173 if (*out_of_space
) {
2174 dptr_SeekDir(dirptr
, prev_dirpos
);
2181 *_last_entry_off
= last_entry_off
;
2185 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2186 connection_struct
*conn
,
2187 struct dptr_struct
*dirptr
,
2189 const char *path_mask
,
2192 bool requires_resume_key
,
2198 int space_remaining
,
2200 bool *got_exact_match
,
2201 int *last_entry_off
,
2202 struct ea_list
*name_list
)
2205 const bool do_pad
= true;
2207 if (info_level
>= 1 && info_level
<= 3) {
2208 /* No alignment on earlier info levels. */
2212 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2213 path_mask
, dirtype
, info_level
,
2214 requires_resume_key
, dont_descend
, ask_sharemode
,
2216 ppdata
, base_data
, end_data
,
2218 out_of_space
, got_exact_match
,
2219 last_entry_off
, name_list
);
2222 /****************************************************************************
2223 Reply to a TRANS2_FINDFIRST.
2224 ****************************************************************************/
2226 static void call_trans2findfirst(connection_struct
*conn
,
2227 struct smb_request
*req
,
2228 char **pparams
, int total_params
,
2229 char **ppdata
, int total_data
,
2230 unsigned int max_data_bytes
)
2232 /* We must be careful here that we don't return more than the
2233 allowed number of data bytes. If this means returning fewer than
2234 maxentries then so be it. We assume that the redirector has
2235 enough room for the fixed number of parameter bytes it has
2237 struct smb_filename
*smb_dname
= NULL
;
2238 char *params
= *pparams
;
2239 char *pdata
= *ppdata
;
2243 uint16 findfirst_flags
;
2244 bool close_after_first
;
2246 bool requires_resume_key
;
2248 char *directory
= NULL
;
2251 int last_entry_off
=0;
2255 bool finished
= False
;
2256 bool dont_descend
= False
;
2257 bool out_of_space
= False
;
2258 int space_remaining
;
2259 bool mask_contains_wcard
= False
;
2260 struct ea_list
*ea_list
= NULL
;
2261 NTSTATUS ntstatus
= NT_STATUS_OK
;
2262 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2263 TALLOC_CTX
*ctx
= talloc_tos();
2264 struct dptr_struct
*dirptr
= NULL
;
2265 struct smbd_server_connection
*sconn
= req
->sconn
;
2267 if (total_params
< 13) {
2268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2272 dirtype
= SVAL(params
,0);
2273 maxentries
= SVAL(params
,2);
2274 findfirst_flags
= SVAL(params
,4);
2275 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2276 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2277 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2278 info_level
= SVAL(params
,6);
2280 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2281 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2282 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2283 info_level
, max_data_bytes
));
2286 /* W2K3 seems to treat zero as 1. */
2290 switch (info_level
) {
2291 case SMB_FIND_INFO_STANDARD
:
2292 case SMB_FIND_EA_SIZE
:
2293 case SMB_FIND_EA_LIST
:
2294 case SMB_FIND_FILE_DIRECTORY_INFO
:
2295 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2296 case SMB_FIND_FILE_NAMES_INFO
:
2297 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2298 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2301 case SMB_FIND_FILE_UNIX
:
2302 case SMB_FIND_FILE_UNIX_INFO2
:
2303 /* Always use filesystem for UNIX mtime query. */
2304 ask_sharemode
= false;
2305 if (!lp_unix_extensions()) {
2306 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2311 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2315 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2316 params
+12, total_params
- 12,
2317 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2318 if (!NT_STATUS_IS_OK(ntstatus
)) {
2319 reply_nterror(req
, ntstatus
);
2323 ntstatus
= filename_convert(ctx
, conn
,
2324 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2327 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2328 &mask_contains_wcard
,
2330 if (!NT_STATUS_IS_OK(ntstatus
)) {
2331 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2332 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2333 ERRSRV
, ERRbadpath
);
2336 reply_nterror(req
, ntstatus
);
2340 mask
= smb_dname
->original_lcomp
;
2342 directory
= smb_dname
->base_name
;
2344 p
= strrchr_m(directory
,'/');
2346 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2347 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2348 mask
= talloc_strdup(ctx
,"*");
2350 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2353 mask_contains_wcard
= True
;
2355 directory
= talloc_strdup(talloc_tos(), "./");
2357 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2364 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2366 if (info_level
== SMB_FIND_EA_LIST
) {
2369 if (total_data
< 4) {
2370 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2374 ea_size
= IVAL(pdata
,0);
2375 if (ea_size
!= total_data
) {
2376 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2377 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2378 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2382 if (!lp_ea_support(SNUM(conn
))) {
2383 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2387 /* Pull out the list of names. */
2388 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2390 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2395 *ppdata
= (char *)SMB_REALLOC(
2396 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2397 if(*ppdata
== NULL
) {
2398 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2402 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2404 /* Realloc the params space */
2405 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2406 if (*pparams
== NULL
) {
2407 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2412 /* Save the wildcard match and attribs we are using on this directory -
2413 needed as lanman2 assumes these are being saved between calls */
2415 ntstatus
= dptr_create(conn
,
2421 mask_contains_wcard
,
2425 if (!NT_STATUS_IS_OK(ntstatus
)) {
2426 reply_nterror(req
, ntstatus
);
2430 dptr_num
= dptr_dnum(dirptr
);
2431 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2433 /* Initialize per TRANS2_FIND_FIRST operation data */
2434 dptr_init_search_op(dirptr
);
2436 /* We don't need to check for VOL here as this is returned by
2437 a different TRANS2 call. */
2439 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2440 directory
,lp_dontdescend(SNUM(conn
))));
2441 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2442 dont_descend
= True
;
2445 space_remaining
= max_data_bytes
;
2446 out_of_space
= False
;
2448 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2449 bool got_exact_match
= False
;
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2454 out_of_space
= True
;
2457 finished
= !get_lanman2_dir_entry(ctx
,
2461 mask
,dirtype
,info_level
,
2462 requires_resume_key
,dont_descend
,
2465 space_remaining
, &out_of_space
,
2467 &last_entry_off
, ea_list
);
2470 if (finished
&& out_of_space
)
2473 if (!finished
&& !out_of_space
)
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2486 /* Ensure space_remaining never goes -ve. */
2487 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2488 space_remaining
= 0;
2489 out_of_space
= true;
2491 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2495 /* Check if we can close the dirptr */
2496 if(close_after_first
|| (finished
&& close_if_end
)) {
2497 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2498 dptr_close(sconn
, &dptr_num
);
2502 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2503 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2504 * the protocol level is less than NT1. Tested with smbclient. JRA.
2505 * This should fix the OS/2 client bug #2335.
2508 if(numentries
== 0) {
2509 dptr_close(sconn
, &dptr_num
);
2510 if (get_Protocol() < PROTOCOL_NT1
) {
2511 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2514 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2515 ERRDOS
, ERRbadfile
);
2520 /* At this point pdata points to numentries directory entries. */
2522 /* Set up the return parameter block */
2523 SSVAL(params
,0,dptr_num
);
2524 SSVAL(params
,2,numentries
);
2525 SSVAL(params
,4,finished
);
2526 SSVAL(params
,6,0); /* Never an EA error */
2527 SSVAL(params
,8,last_entry_off
);
2529 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2532 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2533 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2535 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2539 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2540 smb_fn_name(req
->cmd
),
2541 mask
, directory
, dirtype
, numentries
) );
2544 * Force a name mangle here to ensure that the
2545 * mask as an 8.3 name is top of the mangled cache.
2546 * The reasons for this are subtle. Don't remove
2547 * this code unless you know what you are doing
2548 * (see PR#13758). JRA.
2551 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2552 char mangled_name
[13];
2553 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2556 TALLOC_FREE(smb_dname
);
2560 /****************************************************************************
2561 Reply to a TRANS2_FINDNEXT.
2562 ****************************************************************************/
2564 static void call_trans2findnext(connection_struct
*conn
,
2565 struct smb_request
*req
,
2566 char **pparams
, int total_params
,
2567 char **ppdata
, int total_data
,
2568 unsigned int max_data_bytes
)
2570 /* We must be careful here that we don't return more than the
2571 allowed number of data bytes. If this means returning fewer than
2572 maxentries then so be it. We assume that the redirector has
2573 enough room for the fixed number of parameter bytes it has
2575 char *params
= *pparams
;
2576 char *pdata
= *ppdata
;
2582 uint16 findnext_flags
;
2583 bool close_after_request
;
2585 bool requires_resume_key
;
2587 bool mask_contains_wcard
= False
;
2588 char *resume_name
= NULL
;
2589 const char *mask
= NULL
;
2590 const char *directory
= NULL
;
2594 int i
, last_entry_off
=0;
2595 bool finished
= False
;
2596 bool dont_descend
= False
;
2597 bool out_of_space
= False
;
2598 int space_remaining
;
2599 struct ea_list
*ea_list
= NULL
;
2600 NTSTATUS ntstatus
= NT_STATUS_OK
;
2601 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2602 TALLOC_CTX
*ctx
= talloc_tos();
2603 struct dptr_struct
*dirptr
;
2604 struct smbd_server_connection
*sconn
= req
->sconn
;
2606 if (total_params
< 13) {
2607 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2611 dptr_num
= SVAL(params
,0);
2612 maxentries
= SVAL(params
,2);
2613 info_level
= SVAL(params
,4);
2614 resume_key
= IVAL(params
,6);
2615 findnext_flags
= SVAL(params
,10);
2616 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2617 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2618 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2619 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2621 if (!continue_bit
) {
2622 /* We only need resume_name if continue_bit is zero. */
2623 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2625 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2626 &mask_contains_wcard
);
2627 if (!NT_STATUS_IS_OK(ntstatus
)) {
2628 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2629 complain (it thinks we're asking for the directory above the shared
2630 path or an invalid name). Catch this as the resume name is only compared, never used in
2631 a file access. JRA. */
2632 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2633 &resume_name
, params
+12,
2637 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2638 reply_nterror(req
, ntstatus
);
2644 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2645 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2646 resume_key = %d resume name = %s continue=%d level = %d\n",
2647 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2648 requires_resume_key
, resume_key
,
2649 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2652 /* W2K3 seems to treat zero as 1. */
2656 switch (info_level
) {
2657 case SMB_FIND_INFO_STANDARD
:
2658 case SMB_FIND_EA_SIZE
:
2659 case SMB_FIND_EA_LIST
:
2660 case SMB_FIND_FILE_DIRECTORY_INFO
:
2661 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2662 case SMB_FIND_FILE_NAMES_INFO
:
2663 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2664 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2665 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2667 case SMB_FIND_FILE_UNIX
:
2668 case SMB_FIND_FILE_UNIX_INFO2
:
2669 /* Always use filesystem for UNIX mtime query. */
2670 ask_sharemode
= false;
2671 if (!lp_unix_extensions()) {
2672 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2677 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2681 if (info_level
== SMB_FIND_EA_LIST
) {
2684 if (total_data
< 4) {
2685 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2689 ea_size
= IVAL(pdata
,0);
2690 if (ea_size
!= total_data
) {
2691 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2692 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2693 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2697 if (!lp_ea_support(SNUM(conn
))) {
2698 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2702 /* Pull out the list of names. */
2703 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2710 *ppdata
= (char *)SMB_REALLOC(
2711 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2712 if(*ppdata
== NULL
) {
2713 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2718 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2720 /* Realloc the params space */
2721 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2722 if(*pparams
== NULL
) {
2723 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2729 /* Check that the dptr is valid */
2730 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2731 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2735 directory
= dptr_path(sconn
, dptr_num
);
2737 /* Get the wildcard mask from the dptr */
2738 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2739 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2740 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2746 /* Get the attr mask from the dptr */
2747 dirtype
= dptr_attr(sconn
, dptr_num
);
2749 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2750 dptr_num
, mask
, dirtype
,
2752 dptr_TellDir(dirptr
)));
2754 /* Initialize per TRANS2_FIND_NEXT operation data */
2755 dptr_init_search_op(dirptr
);
2757 /* We don't need to check for VOL here as this is returned by
2758 a different TRANS2 call. */
2760 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2761 directory
,lp_dontdescend(SNUM(conn
))));
2762 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2763 dont_descend
= True
;
2766 space_remaining
= max_data_bytes
;
2767 out_of_space
= False
;
2770 * Seek to the correct position. We no longer use the resume key but
2771 * depend on the last file name instead.
2774 if(!continue_bit
&& resume_name
&& *resume_name
) {
2777 long current_pos
= 0;
2779 * Remember, name_to_8_3 is called by
2780 * get_lanman2_dir_entry(), so the resume name
2781 * could be mangled. Ensure we check the unmangled name.
2784 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2785 char *new_resume_name
= NULL
;
2786 mangle_lookup_name_from_8_3(ctx
,
2790 if (new_resume_name
) {
2791 resume_name
= new_resume_name
;
2796 * Fix for NT redirector problem triggered by resume key indexes
2797 * changing between directory scans. We now return a resume key of 0
2798 * and instead look for the filename to continue from (also given
2799 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2800 * findfirst/findnext (as is usual) then the directory pointer
2801 * should already be at the correct place.
2804 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2805 } /* end if resume_name && !continue_bit */
2807 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2808 bool got_exact_match
= False
;
2810 /* this is a heuristic to avoid seeking the dirptr except when
2811 absolutely necessary. It allows for a filename of about 40 chars */
2812 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2813 out_of_space
= True
;
2816 finished
= !get_lanman2_dir_entry(ctx
,
2820 mask
,dirtype
,info_level
,
2821 requires_resume_key
,dont_descend
,
2824 space_remaining
, &out_of_space
,
2826 &last_entry_off
, ea_list
);
2829 if (finished
&& out_of_space
)
2832 if (!finished
&& !out_of_space
)
2836 * As an optimisation if we know we aren't looking
2837 * for a wildcard name (ie. the name matches the wildcard exactly)
2838 * then we can finish on any (first) match.
2839 * This speeds up large directory searches. JRA.
2845 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2848 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2849 smb_fn_name(req
->cmd
),
2850 mask
, directory
, dirtype
, numentries
) );
2852 /* Check if we can close the dirptr */
2853 if(close_after_request
|| (finished
&& close_if_end
)) {
2854 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2855 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2858 /* Set up the return parameter block */
2859 SSVAL(params
,0,numentries
);
2860 SSVAL(params
,2,finished
);
2861 SSVAL(params
,4,0); /* Never an EA error */
2862 SSVAL(params
,6,last_entry_off
);
2864 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2870 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2872 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2876 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2878 SMB_ASSERT(extended_info
!= NULL
);
2880 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2881 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2882 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2883 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2884 #ifdef SAMBA_VERSION_REVISION
2885 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2887 extended_info
->samba_subversion
= 0;
2888 #ifdef SAMBA_VERSION_RC_RELEASE
2889 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2891 #ifdef SAMBA_VERSION_PRE_RELEASE
2892 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2895 #ifdef SAMBA_VERSION_VENDOR_PATCH
2896 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2898 extended_info
->samba_gitcommitdate
= 0;
2899 #ifdef SAMBA_VERSION_COMMIT_TIME
2900 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2903 memset(extended_info
->samba_version_string
, 0,
2904 sizeof(extended_info
->samba_version_string
));
2906 snprintf (extended_info
->samba_version_string
,
2907 sizeof(extended_info
->samba_version_string
),
2908 "%s", samba_version_string());
2911 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2912 TALLOC_CTX
*mem_ctx
,
2913 uint16_t info_level
,
2915 unsigned int max_data_bytes
,
2919 char *pdata
, *end_data
;
2920 int data_len
= 0, len
;
2921 const char *vname
= volume_label(SNUM(conn
));
2922 int snum
= SNUM(conn
);
2923 char *fstype
= lp_fstype(SNUM(conn
));
2924 uint32 additional_flags
= 0;
2925 struct smb_filename smb_fname_dot
;
2929 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2930 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2931 "info level (0x%x) on IPC$.\n",
2932 (unsigned int)info_level
));
2933 return NT_STATUS_ACCESS_DENIED
;
2937 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2939 ZERO_STRUCT(smb_fname_dot
);
2940 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2942 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2943 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2944 return map_nt_error_from_unix(errno
);
2947 st
= smb_fname_dot
.st
;
2949 *ppdata
= (char *)SMB_REALLOC(
2950 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2951 if (*ppdata
== NULL
) {
2952 return NT_STATUS_NO_MEMORY
;
2956 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2957 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2959 switch (info_level
) {
2960 case SMB_INFO_ALLOCATION
:
2962 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2964 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2965 return map_nt_error_from_unix(errno
);
2968 block_size
= lp_block_size(snum
);
2969 if (bsize
< block_size
) {
2970 uint64_t factor
= block_size
/bsize
;
2975 if (bsize
> block_size
) {
2976 uint64_t factor
= bsize
/block_size
;
2981 bytes_per_sector
= 512;
2982 sectors_per_unit
= bsize
/bytes_per_sector
;
2984 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2985 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2986 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2988 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2989 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2990 SIVAL(pdata
,l1_cUnit
,dsize
);
2991 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2992 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2996 case SMB_INFO_VOLUME
:
2997 /* Return volume name */
2999 * Add volume serial number - hash of a combination of
3000 * the called hostname and the service name.
3002 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3004 * Win2k3 and previous mess this up by sending a name length
3005 * one byte short. I believe only older clients (OS/2 Win9x) use
3006 * this call so try fixing this by adding a terminating null to
3007 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3011 pdata
+l2_vol_szVolLabel
, vname
,
3012 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3013 STR_NOALIGN
|STR_TERMINATE
);
3014 SCVAL(pdata
,l2_vol_cch
,len
);
3015 data_len
= l2_vol_szVolLabel
+ len
;
3016 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3017 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3021 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3022 case SMB_FS_ATTRIBUTE_INFORMATION
:
3024 additional_flags
= 0;
3025 #if defined(HAVE_SYS_QUOTAS)
3026 additional_flags
|= FILE_VOLUME_QUOTAS
;
3029 if(lp_nt_acl_support(SNUM(conn
))) {
3030 additional_flags
|= FILE_PERSISTENT_ACLS
;
3033 /* Capabilities are filled in at connection time through STATVFS call */
3034 additional_flags
|= conn
->fs_capabilities
;
3035 additional_flags
|= lp_parm_int(conn
->params
->service
,
3036 "share", "fake_fscaps",
3039 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3040 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3041 additional_flags
); /* FS ATTRIBUTES */
3043 SIVAL(pdata
,4,255); /* Max filename component length */
3044 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3045 and will think we can't do long filenames */
3046 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3047 PTR_DIFF(end_data
, pdata
+12),
3050 data_len
= 12 + len
;
3053 case SMB_QUERY_FS_LABEL_INFO
:
3054 case SMB_FS_LABEL_INFORMATION
:
3055 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3056 PTR_DIFF(end_data
, pdata
+4), 0);
3061 case SMB_QUERY_FS_VOLUME_INFO
:
3062 case SMB_FS_VOLUME_INFORMATION
:
3065 * Add volume serial number - hash of a combination of
3066 * the called hostname and the service name.
3068 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3069 (str_checksum(get_local_machine_name())<<16));
3071 /* Max label len is 32 characters. */
3072 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3073 PTR_DIFF(end_data
, pdata
+18),
3075 SIVAL(pdata
,12,len
);
3078 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3079 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3082 case SMB_QUERY_FS_SIZE_INFO
:
3083 case SMB_FS_SIZE_INFORMATION
:
3085 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3087 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3088 return map_nt_error_from_unix(errno
);
3090 block_size
= lp_block_size(snum
);
3091 if (bsize
< block_size
) {
3092 uint64_t factor
= block_size
/bsize
;
3097 if (bsize
> block_size
) {
3098 uint64_t factor
= bsize
/block_size
;
3103 bytes_per_sector
= 512;
3104 sectors_per_unit
= bsize
/bytes_per_sector
;
3105 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3106 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3107 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3108 SBIG_UINT(pdata
,0,dsize
);
3109 SBIG_UINT(pdata
,8,dfree
);
3110 SIVAL(pdata
,16,sectors_per_unit
);
3111 SIVAL(pdata
,20,bytes_per_sector
);
3115 case SMB_FS_FULL_SIZE_INFORMATION
:
3117 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3119 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3120 return map_nt_error_from_unix(errno
);
3122 block_size
= lp_block_size(snum
);
3123 if (bsize
< block_size
) {
3124 uint64_t factor
= block_size
/bsize
;
3129 if (bsize
> block_size
) {
3130 uint64_t factor
= bsize
/block_size
;
3135 bytes_per_sector
= 512;
3136 sectors_per_unit
= bsize
/bytes_per_sector
;
3137 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3138 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3139 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3140 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3141 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3142 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3143 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3144 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3148 case SMB_QUERY_FS_DEVICE_INFO
:
3149 case SMB_FS_DEVICE_INFORMATION
:
3151 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3153 if (!CAN_WRITE(conn
)) {
3154 characteristics
|= FILE_READ_ONLY_DEVICE
;
3157 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3158 SIVAL(pdata
,4,characteristics
);
3162 #ifdef HAVE_SYS_QUOTAS
3163 case SMB_FS_QUOTA_INFORMATION
:
3165 * what we have to send --metze:
3167 * Unknown1: 24 NULL bytes
3168 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3169 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3170 * Quota Flags: 2 byte :
3171 * Unknown3: 6 NULL bytes
3175 * details for Quota Flags:
3177 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3178 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3179 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3180 * 0x0001 Enable Quotas: enable quota for this fs
3184 /* we need to fake up a fsp here,
3185 * because its not send in this call
3188 SMB_NTQUOTA_STRUCT quotas
;
3191 ZERO_STRUCT(quotas
);
3197 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3198 DEBUG(0,("set_user_quota: access_denied "
3199 "service [%s] user [%s]\n",
3200 lp_servicename(SNUM(conn
)),
3201 conn
->server_info
->unix_name
));
3202 return NT_STATUS_ACCESS_DENIED
;
3205 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3206 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3207 return map_nt_error_from_unix(errno
);
3212 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3213 lp_servicename(SNUM(conn
))));
3215 /* Unknown1 24 NULL bytes*/
3216 SBIG_UINT(pdata
,0,(uint64_t)0);
3217 SBIG_UINT(pdata
,8,(uint64_t)0);
3218 SBIG_UINT(pdata
,16,(uint64_t)0);
3220 /* Default Soft Quota 8 bytes */
3221 SBIG_UINT(pdata
,24,quotas
.softlim
);
3223 /* Default Hard Quota 8 bytes */
3224 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3226 /* Quota flag 2 bytes */
3227 SSVAL(pdata
,40,quotas
.qflags
);
3229 /* Unknown3 6 NULL bytes */
3235 #endif /* HAVE_SYS_QUOTAS */
3236 case SMB_FS_OBJECTID_INFORMATION
:
3238 unsigned char objid
[16];
3239 struct smb_extended_info extended_info
;
3240 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3241 samba_extended_info_version (&extended_info
);
3242 SIVAL(pdata
,16,extended_info
.samba_magic
);
3243 SIVAL(pdata
,20,extended_info
.samba_version
);
3244 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3245 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3246 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3252 * Query the version and capabilities of the CIFS UNIX extensions
3256 case SMB_QUERY_CIFS_UNIX_INFO
:
3258 bool large_write
= lp_min_receive_file_size() &&
3259 !srv_is_signing_active(conn
->sconn
);
3260 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3261 int encrypt_caps
= 0;
3263 if (!lp_unix_extensions()) {
3264 return NT_STATUS_INVALID_LEVEL
;
3267 switch (conn
->encrypt_level
) {
3273 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3276 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3277 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3278 large_write
= false;
3284 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3285 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3287 /* We have POSIX ACLs, pathname, encryption,
3288 * large read/write, and locking capability. */
3290 SBIG_UINT(pdata
,4,((uint64_t)(
3291 CIFS_UNIX_POSIX_ACLS_CAP
|
3292 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3293 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3294 CIFS_UNIX_EXTATTR_CAP
|
3295 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3297 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3299 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3303 case SMB_QUERY_POSIX_FS_INFO
:
3306 vfs_statvfs_struct svfs
;
3308 if (!lp_unix_extensions()) {
3309 return NT_STATUS_INVALID_LEVEL
;
3312 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3316 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3317 SIVAL(pdata
,4,svfs
.BlockSize
);
3318 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3319 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3320 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3321 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3322 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3323 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3324 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3326 } else if (rc
== EOPNOTSUPP
) {
3327 return NT_STATUS_INVALID_LEVEL
;
3328 #endif /* EOPNOTSUPP */
3330 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3331 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3336 case SMB_QUERY_POSIX_WHOAMI
:
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL
;
3346 if (max_data_bytes
< 40) {
3347 return NT_STATUS_BUFFER_TOO_SMALL
;
3350 /* We ARE guest if global_sid_Builtin_Guests is
3351 * in our list of SIDs.
3353 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3354 conn
->server_info
->ptok
)) {
3355 flags
|= SMB_WHOAMI_GUEST
;
3358 /* We are NOT guest if global_sid_Authenticated_Users
3359 * is in our list of SIDs.
3361 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3362 conn
->server_info
->ptok
)) {
3363 flags
&= ~SMB_WHOAMI_GUEST
;
3366 /* NOTE: 8 bytes for UID/GID, irrespective of native
3367 * platform size. This matches
3368 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3370 data_len
= 4 /* flags */
3377 + 4 /* pad/reserved */
3378 + (conn
->server_info
->utok
.ngroups
* 8)
3380 + (conn
->server_info
->ptok
->num_sids
*
3384 SIVAL(pdata
, 0, flags
);
3385 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3387 (uint64_t)conn
->server_info
->utok
.uid
);
3388 SBIG_UINT(pdata
, 16,
3389 (uint64_t)conn
->server_info
->utok
.gid
);
3392 if (data_len
>= max_data_bytes
) {
3393 /* Potential overflow, skip the GIDs and SIDs. */
3395 SIVAL(pdata
, 24, 0); /* num_groups */
3396 SIVAL(pdata
, 28, 0); /* num_sids */
3397 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3398 SIVAL(pdata
, 36, 0); /* reserved */
3404 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3405 SIVAL(pdata
, 28, conn
->server_info
->ptok
->num_sids
);
3407 /* We walk the SID list twice, but this call is fairly
3408 * infrequent, and I don't expect that it's performance
3409 * sensitive -- jpeach
3411 for (i
= 0, sid_bytes
= 0;
3412 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3413 sid_bytes
+= ndr_size_dom_sid(
3414 &conn
->server_info
->ptok
->sids
[i
],
3418 /* SID list byte count */
3419 SIVAL(pdata
, 32, sid_bytes
);
3421 /* 4 bytes pad/reserved - must be zero */
3422 SIVAL(pdata
, 36, 0);
3426 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3427 SBIG_UINT(pdata
, data_len
,
3428 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3434 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3435 int sid_len
= ndr_size_dom_sid(
3436 &conn
->server_info
->ptok
->sids
[i
],
3439 sid_linearize(pdata
+ data_len
, sid_len
,
3440 &conn
->server_info
->ptok
->sids
[i
]);
3441 data_len
+= sid_len
;
3447 case SMB_MAC_QUERY_FS_INFO
:
3449 * Thursby MAC extension... ONLY on NTFS filesystems
3450 * once we do streams then we don't need this
3452 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3454 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3459 return NT_STATUS_INVALID_LEVEL
;
3462 *ret_data_len
= data_len
;
3463 return NT_STATUS_OK
;
3466 /****************************************************************************
3467 Reply to a TRANS2_QFSINFO (query filesystem info).
3468 ****************************************************************************/
3470 static void call_trans2qfsinfo(connection_struct
*conn
,
3471 struct smb_request
*req
,
3472 char **pparams
, int total_params
,
3473 char **ppdata
, int total_data
,
3474 unsigned int max_data_bytes
)
3476 char *params
= *pparams
;
3477 uint16_t info_level
;
3481 if (total_params
< 2) {
3482 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3486 info_level
= SVAL(params
,0);
3488 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3489 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3490 DEBUG(0,("call_trans2qfsinfo: encryption required "
3491 "and info level 0x%x sent.\n",
3492 (unsigned int)info_level
));
3493 exit_server_cleanly("encryption required "
3499 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3501 status
= smbd_do_qfsinfo(conn
, req
,
3506 if (!NT_STATUS_IS_OK(status
)) {
3507 reply_nterror(req
, status
);
3511 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3514 DEBUG( 4, ( "%s info_level = %d\n",
3515 smb_fn_name(req
->cmd
), info_level
) );
3520 /****************************************************************************
3521 Reply to a TRANS2_SETFSINFO (set filesystem info).
3522 ****************************************************************************/
3524 static void call_trans2setfsinfo(connection_struct
*conn
,
3525 struct smb_request
*req
,
3526 char **pparams
, int total_params
,
3527 char **ppdata
, int total_data
,
3528 unsigned int max_data_bytes
)
3530 char *pdata
= *ppdata
;
3531 char *params
= *pparams
;
3534 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3537 if (total_params
< 4) {
3538 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3544 info_level
= SVAL(params
,2);
3547 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3548 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3549 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3550 "info level (0x%x) on IPC$.\n",
3551 (unsigned int)info_level
));
3552 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3557 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3558 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3559 DEBUG(0,("call_trans2setfsinfo: encryption required "
3560 "and info level 0x%x sent.\n",
3561 (unsigned int)info_level
));
3562 exit_server_cleanly("encryption required "
3568 switch(info_level
) {
3569 case SMB_SET_CIFS_UNIX_INFO
:
3571 uint16 client_unix_major
;
3572 uint16 client_unix_minor
;
3573 uint32 client_unix_cap_low
;
3574 uint32 client_unix_cap_high
;
3576 if (!lp_unix_extensions()) {
3578 NT_STATUS_INVALID_LEVEL
);
3582 /* There should be 12 bytes of capabilities set. */
3583 if (total_data
< 8) {
3586 NT_STATUS_INVALID_PARAMETER
);
3589 client_unix_major
= SVAL(pdata
,0);
3590 client_unix_minor
= SVAL(pdata
,2);
3591 client_unix_cap_low
= IVAL(pdata
,4);
3592 client_unix_cap_high
= IVAL(pdata
,8);
3593 /* Just print these values for now. */
3594 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3595 cap_low = 0x%x, cap_high = 0x%x\n",
3596 (unsigned int)client_unix_major
,
3597 (unsigned int)client_unix_minor
,
3598 (unsigned int)client_unix_cap_low
,
3599 (unsigned int)client_unix_cap_high
));
3601 /* Here is where we must switch to posix pathname processing... */
3602 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3603 lp_set_posix_pathnames();
3604 mangle_change_to_posix();
3607 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3608 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3609 /* Client that knows how to do posix locks,
3610 * but not posix open/mkdir operations. Set a
3611 * default type for read/write checks. */
3613 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3619 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3622 size_t param_len
= 0;
3623 size_t data_len
= total_data
;
3625 if (!lp_unix_extensions()) {
3628 NT_STATUS_INVALID_LEVEL
);
3632 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3635 NT_STATUS_NOT_SUPPORTED
);
3639 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3640 DEBUG( 2,("call_trans2setfsinfo: "
3641 "request transport encryption disabled"
3642 "with 'fork echo handler = yes'\n"));
3645 NT_STATUS_NOT_SUPPORTED
);
3649 DEBUG( 4,("call_trans2setfsinfo: "
3650 "request transport encryption.\n"));
3652 status
= srv_request_encryption_setup(conn
,
3653 (unsigned char **)ppdata
,
3655 (unsigned char **)pparams
,
3658 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3659 !NT_STATUS_IS_OK(status
)) {
3660 reply_nterror(req
, status
);
3664 send_trans2_replies(conn
, req
,
3671 if (NT_STATUS_IS_OK(status
)) {
3672 /* Server-side transport
3673 * encryption is now *on*. */
3674 status
= srv_encryption_start(conn
);
3675 if (!NT_STATUS_IS_OK(status
)) {
3676 exit_server_cleanly(
3677 "Failure in setting "
3678 "up encrypted transport");
3684 case SMB_FS_QUOTA_INFORMATION
:
3686 files_struct
*fsp
= NULL
;
3687 SMB_NTQUOTA_STRUCT quotas
;
3689 ZERO_STRUCT(quotas
);
3692 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3693 ||!CAN_WRITE(conn
)) {
3694 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3695 lp_servicename(SNUM(conn
)),
3696 conn
->server_info
->unix_name
));
3697 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3701 /* note: normaly there're 48 bytes,
3702 * but we didn't use the last 6 bytes for now
3705 fsp
= file_fsp(req
, SVAL(params
,0));
3707 if (!check_fsp_ntquota_handle(conn
, req
,
3709 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3711 req
, NT_STATUS_INVALID_HANDLE
);
3715 if (total_data
< 42) {
3716 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3720 NT_STATUS_INVALID_PARAMETER
);
3724 /* unknown_1 24 NULL bytes in pdata*/
3726 /* the soft quotas 8 bytes (uint64_t)*/
3727 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3728 #ifdef LARGE_SMB_OFF_T
3729 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3730 #else /* LARGE_SMB_OFF_T */
3731 if ((IVAL(pdata
,28) != 0)&&
3732 ((quotas
.softlim
!= 0xFFFFFFFF)||
3733 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3734 /* more than 32 bits? */
3737 NT_STATUS_INVALID_PARAMETER
);
3740 #endif /* LARGE_SMB_OFF_T */
3742 /* the hard quotas 8 bytes (uint64_t)*/
3743 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3744 #ifdef LARGE_SMB_OFF_T
3745 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3746 #else /* LARGE_SMB_OFF_T */
3747 if ((IVAL(pdata
,36) != 0)&&
3748 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3749 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3750 /* more than 32 bits? */
3753 NT_STATUS_INVALID_PARAMETER
);
3756 #endif /* LARGE_SMB_OFF_T */
3758 /* quota_flags 2 bytes **/
3759 quotas
.qflags
= SVAL(pdata
,40);
3761 /* unknown_2 6 NULL bytes follow*/
3763 /* now set the quotas */
3764 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3765 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3766 reply_nterror(req
, map_nt_error_from_unix(errno
));
3773 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3775 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3781 * sending this reply works fine,
3782 * but I'm not sure it's the same
3783 * like windows do...
3786 reply_outbuf(req
, 10, 0);
3789 #if defined(HAVE_POSIX_ACLS)
3790 /****************************************************************************
3791 Utility function to count the number of entries in a POSIX acl.
3792 ****************************************************************************/
3794 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3796 unsigned int ace_count
= 0;
3797 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3798 SMB_ACL_ENTRY_T entry
;
3800 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3802 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3803 entry_id
= SMB_ACL_NEXT_ENTRY
;
3810 /****************************************************************************
3811 Utility function to marshall a POSIX acl into wire format.
3812 ****************************************************************************/
3814 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3816 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3817 SMB_ACL_ENTRY_T entry
;
3819 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3820 SMB_ACL_TAG_T tagtype
;
3821 SMB_ACL_PERMSET_T permset
;
3822 unsigned char perms
= 0;
3823 unsigned int own_grp
;
3826 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3827 entry_id
= SMB_ACL_NEXT_ENTRY
;
3830 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3835 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3836 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3840 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3841 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3842 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3844 SCVAL(pdata
,1,perms
);
3847 case SMB_ACL_USER_OBJ
:
3848 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3849 own_grp
= (unsigned int)pst
->st_ex_uid
;
3850 SIVAL(pdata
,2,own_grp
);
3855 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3857 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3860 own_grp
= (unsigned int)*puid
;
3861 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3862 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3863 SIVAL(pdata
,2,own_grp
);
3867 case SMB_ACL_GROUP_OBJ
:
3868 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3869 own_grp
= (unsigned int)pst
->st_ex_gid
;
3870 SIVAL(pdata
,2,own_grp
);
3875 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3877 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3880 own_grp
= (unsigned int)*pgid
;
3881 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3882 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3883 SIVAL(pdata
,2,own_grp
);
3888 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3889 SIVAL(pdata
,2,0xFFFFFFFF);
3890 SIVAL(pdata
,6,0xFFFFFFFF);
3893 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3894 SIVAL(pdata
,2,0xFFFFFFFF);
3895 SIVAL(pdata
,6,0xFFFFFFFF);
3898 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3901 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3908 /****************************************************************************
3909 Store the FILE_UNIX_BASIC info.
3910 ****************************************************************************/
3912 static char *store_file_unix_basic(connection_struct
*conn
,
3915 const SMB_STRUCT_STAT
*psbuf
)
3917 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3919 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3920 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3922 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3925 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3928 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3929 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3930 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3933 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3937 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3941 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3944 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3948 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3952 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3955 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3959 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3966 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3967 * the chflags(2) (or equivalent) flags.
3969 * XXX: this really should be behind the VFS interface. To do this, we would
3970 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3971 * Each VFS module could then implement its own mapping as appropriate for the
3972 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3974 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3978 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3982 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3986 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3990 { UF_HIDDEN
, EXT_HIDDEN
},
3993 /* Do not remove. We need to guarantee that this array has at least one
3994 * entry to build on HP-UX.
4000 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4001 uint32
*smb_fflags
, uint32
*smb_fmask
)
4005 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4006 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4007 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4008 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4013 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4014 const uint32 smb_fflags
,
4015 const uint32 smb_fmask
,
4018 uint32 max_fmask
= 0;
4021 *stat_fflags
= psbuf
->st_ex_flags
;
4023 /* For each flags requested in smb_fmask, check the state of the
4024 * corresponding flag in smb_fflags and set or clear the matching
4028 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4029 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4030 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4031 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4032 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4034 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4039 /* If smb_fmask is asking to set any bits that are not supported by
4040 * our flag mappings, we should fail.
4042 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4050 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4051 * of file flags and birth (create) time.
4053 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4056 const SMB_STRUCT_STAT
*psbuf
)
4058 uint32 file_flags
= 0;
4059 uint32 flags_mask
= 0;
4061 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4063 /* Create (birth) time 64 bit */
4064 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4067 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4068 SIVAL(pdata
, 0, file_flags
); /* flags */
4069 SIVAL(pdata
, 4, flags_mask
); /* mask */
4075 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4076 const struct stream_struct
*streams
,
4078 unsigned int max_data_bytes
,
4079 unsigned int *data_size
)
4082 unsigned int ofs
= 0;
4084 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4085 unsigned int next_offset
;
4087 smb_ucs2_t
*namebuf
;
4089 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4090 streams
[i
].name
, &namelen
) ||
4093 return NT_STATUS_INVALID_PARAMETER
;
4097 * name_buf is now null-terminated, we need to marshall as not
4103 SIVAL(data
, ofs
+4, namelen
);
4104 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4105 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4106 memcpy(data
+ofs
+24, namebuf
, namelen
);
4107 TALLOC_FREE(namebuf
);
4109 next_offset
= ofs
+ 24 + namelen
;
4111 if (i
== num_streams
-1) {
4112 SIVAL(data
, ofs
, 0);
4115 unsigned int align
= ndr_align_size(next_offset
, 8);
4117 memset(data
+next_offset
, 0, align
);
4118 next_offset
+= align
;
4120 SIVAL(data
, ofs
, next_offset
- ofs
);
4129 return NT_STATUS_OK
;
4132 /****************************************************************************
4133 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4134 ****************************************************************************/
4136 static void call_trans2qpipeinfo(connection_struct
*conn
,
4137 struct smb_request
*req
,
4138 unsigned int tran_call
,
4139 char **pparams
, int total_params
,
4140 char **ppdata
, int total_data
,
4141 unsigned int max_data_bytes
)
4143 char *params
= *pparams
;
4144 char *pdata
= *ppdata
;
4145 unsigned int data_size
= 0;
4146 unsigned int param_size
= 2;
4151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4155 if (total_params
< 4) {
4156 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4160 fsp
= file_fsp(req
, SVAL(params
,0));
4161 if (!fsp_is_np(fsp
)) {
4162 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4166 info_level
= SVAL(params
,2);
4168 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4169 if (*pparams
== NULL
) {
4170 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4175 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4176 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4177 if (*ppdata
== NULL
) {
4178 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4183 switch (info_level
) {
4184 case SMB_FILE_STANDARD_INFORMATION
:
4186 SOFF_T(pdata
,0,4096LL);
4193 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4197 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4203 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4204 TALLOC_CTX
*mem_ctx
,
4205 uint16_t info_level
,
4207 struct smb_filename
*smb_fname
,
4208 bool delete_pending
,
4209 struct timespec write_time_ts
,
4210 struct ea_list
*ea_list
,
4211 int lock_data_count
,
4214 unsigned int max_data_bytes
,
4216 unsigned int *pdata_size
)
4218 char *pdata
= *ppdata
;
4219 char *dstart
, *dend
;
4220 unsigned int data_size
;
4221 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4222 time_t create_time
, mtime
, atime
, c_time
;
4223 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4230 uint64_t file_size
= 0;
4232 uint64_t allocation_size
= 0;
4233 uint64_t file_index
= 0;
4234 uint32_t access_mask
= 0;
4236 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4237 return NT_STATUS_INVALID_LEVEL
;
4240 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4241 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4242 info_level
, max_data_bytes
));
4244 mode
= dos_mode(conn
, smb_fname
);
4245 nlink
= psbuf
->st_ex_nlink
;
4247 if (nlink
&& (mode
&aDIR
)) {
4251 if ((nlink
> 0) && delete_pending
) {
4255 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4256 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4257 if (*ppdata
== NULL
) {
4258 return NT_STATUS_NO_MEMORY
;
4262 dend
= dstart
+ data_size
- 1;
4264 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4265 update_stat_ex_mtime(psbuf
, write_time_ts
);
4268 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4269 mtime_ts
= psbuf
->st_ex_mtime
;
4270 atime_ts
= psbuf
->st_ex_atime
;
4271 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4273 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4274 dos_filetime_timespec(&create_time_ts
);
4275 dos_filetime_timespec(&mtime_ts
);
4276 dos_filetime_timespec(&atime_ts
);
4277 dos_filetime_timespec(&ctime_ts
);
4280 create_time
= convert_timespec_to_time_t(create_time_ts
);
4281 mtime
= convert_timespec_to_time_t(mtime_ts
);
4282 atime
= convert_timespec_to_time_t(atime_ts
);
4283 c_time
= convert_timespec_to_time_t(ctime_ts
);
4285 p
= strrchr_m(smb_fname
->base_name
,'/');
4287 base_name
= smb_fname
->base_name
;
4291 /* NT expects the name to be in an exact form of the *full*
4292 filename. See the trans2 torture test */
4293 if (ISDOT(base_name
)) {
4294 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4296 return NT_STATUS_NO_MEMORY
;
4299 dos_fname
= talloc_asprintf(mem_ctx
,
4301 smb_fname
->base_name
);
4303 return NT_STATUS_NO_MEMORY
;
4305 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4306 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4307 smb_fname
->stream_name
);
4309 return NT_STATUS_NO_MEMORY
;
4313 string_replace(dos_fname
, '/', '\\');
4316 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4319 /* Do we have this path open ? */
4321 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4322 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4323 if (fsp1
&& fsp1
->initial_allocation_size
) {
4324 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4328 if (!(mode
& aDIR
)) {
4329 file_size
= get_file_size_stat(psbuf
);
4333 pos
= fsp
->fh
->position_information
;
4337 access_mask
= fsp
->access_mask
;
4339 /* GENERIC_EXECUTE mapping from Windows */
4340 access_mask
= 0x12019F;
4343 /* This should be an index number - looks like
4346 I think this causes us to fail the IFSKIT
4347 BasicFileInformationTest. -tpot */
4348 file_index
= get_FileIndex(conn
, psbuf
);
4350 switch (info_level
) {
4351 case SMB_INFO_STANDARD
:
4352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4354 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4355 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4356 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4357 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4358 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4359 SSVAL(pdata
,l1_attrFile
,mode
);
4362 case SMB_INFO_QUERY_EA_SIZE
:
4364 unsigned int ea_size
=
4365 estimate_ea_size(conn
, fsp
,
4366 smb_fname
->base_name
);
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4369 srv_put_dos_date2(pdata
,0,create_time
);
4370 srv_put_dos_date2(pdata
,4,atime
);
4371 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4372 SIVAL(pdata
,12,(uint32
)file_size
);
4373 SIVAL(pdata
,16,(uint32
)allocation_size
);
4374 SSVAL(pdata
,20,mode
);
4375 SIVAL(pdata
,22,ea_size
);
4379 case SMB_INFO_IS_NAME_VALID
:
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4382 /* os/2 needs this ? really ?*/
4383 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4385 /* This is only reached for qpathinfo */
4389 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4391 size_t total_ea_len
= 0;
4392 struct ea_list
*ea_file_list
= NULL
;
4394 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4397 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4398 smb_fname
->base_name
,
4400 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4402 if (!ea_list
|| (total_ea_len
> data_size
)) {
4404 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4408 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4412 case SMB_INFO_QUERY_ALL_EAS
:
4414 /* We have data_size bytes to put EA's into. */
4415 size_t total_ea_len
= 0;
4417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4419 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4420 smb_fname
->base_name
,
4422 if (!ea_list
|| (total_ea_len
> data_size
)) {
4424 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4428 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4432 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4434 /* This is FileFullEaInformation - 0xF which maps to
4435 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4437 /* We have data_size bytes to put EA's into. */
4438 size_t total_ea_len
= 0;
4439 struct ea_list
*ea_file_list
= NULL
;
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4443 /*TODO: add filtering and index handling */
4446 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4447 smb_fname
->base_name
,
4449 if (!ea_file_list
) {
4450 return NT_STATUS_NO_EAS_ON_FILE
;
4453 status
= fill_ea_chained_buffer(mem_ctx
,
4457 conn
, ea_file_list
);
4458 if (!NT_STATUS_IS_OK(status
)) {
4464 case SMB_FILE_BASIC_INFORMATION
:
4465 case SMB_QUERY_FILE_BASIC_INFO
:
4467 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4469 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4475 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4476 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4477 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4478 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4479 SIVAL(pdata
,32,mode
);
4481 DEBUG(5,("SMB_QFBI - "));
4482 DEBUG(5,("create: %s ", ctime(&create_time
)));
4483 DEBUG(5,("access: %s ", ctime(&atime
)));
4484 DEBUG(5,("write: %s ", ctime(&mtime
)));
4485 DEBUG(5,("change: %s ", ctime(&c_time
)));
4486 DEBUG(5,("mode: %x\n", mode
));
4489 case SMB_FILE_STANDARD_INFORMATION
:
4490 case SMB_QUERY_FILE_STANDARD_INFO
:
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4494 SOFF_T(pdata
,0,allocation_size
);
4495 SOFF_T(pdata
,8,file_size
);
4496 SIVAL(pdata
,16,nlink
);
4497 SCVAL(pdata
,20,delete_pending
?1:0);
4498 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4499 SSVAL(pdata
,22,0); /* Padding. */
4502 case SMB_FILE_EA_INFORMATION
:
4503 case SMB_QUERY_FILE_EA_INFO
:
4505 unsigned int ea_size
=
4506 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4509 SIVAL(pdata
,0,ea_size
);
4513 /* Get the 8.3 name - used if NT SMB was negotiated. */
4514 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4515 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4518 char mangled_name
[13];
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4520 if (!name_to_8_3(base_name
,mangled_name
,
4521 True
,conn
->params
)) {
4522 return NT_STATUS_NO_MEMORY
;
4524 len
= srvstr_push(dstart
, flags2
,
4525 pdata
+4, mangled_name
,
4526 PTR_DIFF(dend
, pdata
+4),
4528 data_size
= 4 + len
;
4533 case SMB_QUERY_FILE_NAME_INFO
:
4537 this must be *exactly* right for ACLs on mapped drives to work
4539 len
= srvstr_push(dstart
, flags2
,
4541 PTR_DIFF(dend
, pdata
+4),
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4544 data_size
= 4 + len
;
4549 case SMB_FILE_ALLOCATION_INFORMATION
:
4550 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4553 SOFF_T(pdata
,0,allocation_size
);
4556 case SMB_FILE_END_OF_FILE_INFORMATION
:
4557 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4560 SOFF_T(pdata
,0,file_size
);
4563 case SMB_QUERY_FILE_ALL_INFO
:
4564 case SMB_FILE_ALL_INFORMATION
:
4567 unsigned int ea_size
=
4568 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4570 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4571 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4572 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4573 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4574 SIVAL(pdata
,32,mode
);
4575 SIVAL(pdata
,36,0); /* padding. */
4577 SOFF_T(pdata
,0,allocation_size
);
4578 SOFF_T(pdata
,8,file_size
);
4579 SIVAL(pdata
,16,nlink
);
4580 SCVAL(pdata
,20,delete_pending
);
4581 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4584 SIVAL(pdata
,0,ea_size
);
4585 pdata
+= 4; /* EA info */
4586 len
= srvstr_push(dstart
, flags2
,
4588 PTR_DIFF(dend
, pdata
+4),
4592 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4596 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4599 unsigned int ea_size
=
4600 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4602 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4603 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4604 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4605 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4606 SIVAL(pdata
, 0x20, mode
);
4607 SIVAL(pdata
, 0x24, 0); /* padding. */
4608 SBVAL(pdata
, 0x28, allocation_size
);
4609 SBVAL(pdata
, 0x30, file_size
);
4610 SIVAL(pdata
, 0x38, nlink
);
4611 SCVAL(pdata
, 0x3C, delete_pending
);
4612 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4613 SSVAL(pdata
, 0x3E, 0); /* padding */
4614 SBVAL(pdata
, 0x40, file_index
);
4615 SIVAL(pdata
, 0x48, ea_size
);
4616 SIVAL(pdata
, 0x4C, access_mask
);
4617 SBVAL(pdata
, 0x50, pos
);
4618 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4619 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4623 len
= srvstr_push(dstart
, flags2
,
4625 PTR_DIFF(dend
, pdata
+4),
4629 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4632 case SMB_FILE_INTERNAL_INFORMATION
:
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4635 SBVAL(pdata
, 0, file_index
);
4639 case SMB_FILE_ACCESS_INFORMATION
:
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4641 SIVAL(pdata
, 0, access_mask
);
4645 case SMB_FILE_NAME_INFORMATION
:
4646 /* Pathname with leading '\'. */
4649 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4651 SIVAL(pdata
,0,byte_len
);
4652 data_size
= 4 + byte_len
;
4656 case SMB_FILE_DISPOSITION_INFORMATION
:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4659 SCVAL(pdata
,0,delete_pending
);
4662 case SMB_FILE_POSITION_INFORMATION
:
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4665 SOFF_T(pdata
,0,pos
);
4668 case SMB_FILE_MODE_INFORMATION
:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4670 SIVAL(pdata
,0,mode
);
4674 case SMB_FILE_ALIGNMENT_INFORMATION
:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4676 SIVAL(pdata
,0,0); /* No alignment needed. */
4681 * NT4 server just returns "invalid query" to this - if we try
4682 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4685 /* The first statement above is false - verified using Thursby
4686 * client against NT4 -- gcolley.
4688 case SMB_QUERY_FILE_STREAM_INFO
:
4689 case SMB_FILE_STREAM_INFORMATION
: {
4690 unsigned int num_streams
;
4691 struct stream_struct
*streams
;
4693 DEBUG(10,("smbd_do_qfilepathinfo: "
4694 "SMB_FILE_STREAM_INFORMATION\n"));
4696 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4697 return NT_STATUS_INVALID_PARAMETER
;
4700 status
= SMB_VFS_STREAMINFO(
4701 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4702 &num_streams
, &streams
);
4704 if (!NT_STATUS_IS_OK(status
)) {
4705 DEBUG(10, ("could not get stream info: %s\n",
4706 nt_errstr(status
)));
4710 status
= marshall_stream_info(num_streams
, streams
,
4711 pdata
, max_data_bytes
,
4714 if (!NT_STATUS_IS_OK(status
)) {
4715 DEBUG(10, ("marshall_stream_info failed: %s\n",
4716 nt_errstr(status
)));
4720 TALLOC_FREE(streams
);
4724 case SMB_QUERY_COMPRESSION_INFO
:
4725 case SMB_FILE_COMPRESSION_INFORMATION
:
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4727 SOFF_T(pdata
,0,file_size
);
4728 SIVAL(pdata
,8,0); /* ??? */
4729 SIVAL(pdata
,12,0); /* ??? */
4733 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4735 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4736 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4737 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4738 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4739 SOFF_T(pdata
,32,allocation_size
);
4740 SOFF_T(pdata
,40,file_size
);
4741 SIVAL(pdata
,48,mode
);
4742 SIVAL(pdata
,52,0); /* ??? */
4746 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4748 SIVAL(pdata
,0,mode
);
4754 * CIFS UNIX Extensions.
4757 case SMB_QUERY_FILE_UNIX_BASIC
:
4759 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4760 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4762 DEBUG(4,("smbd_do_qfilepathinfo: "
4763 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4764 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4768 case SMB_QUERY_FILE_UNIX_INFO2
:
4770 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4771 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4775 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4777 for (i
=0; i
<100; i
++)
4778 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4784 case SMB_QUERY_FILE_UNIX_LINK
:
4787 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4790 return NT_STATUS_NO_MEMORY
;
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4795 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4796 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4799 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4801 len
= SMB_VFS_READLINK(conn
,
4802 smb_fname
->base_name
,
4805 return map_nt_error_from_unix(errno
);
4808 len
= srvstr_push(dstart
, flags2
,
4810 PTR_DIFF(dend
, pdata
),
4813 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4818 #if defined(HAVE_POSIX_ACLS)
4819 case SMB_QUERY_POSIX_ACL
:
4821 SMB_ACL_T file_acl
= NULL
;
4822 SMB_ACL_T def_acl
= NULL
;
4823 uint16 num_file_acls
= 0;
4824 uint16 num_def_acls
= 0;
4826 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4827 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4830 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4831 smb_fname
->base_name
,
4832 SMB_ACL_TYPE_ACCESS
);
4835 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4836 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4837 "not implemented on "
4838 "filesystem containing %s\n",
4839 smb_fname
->base_name
));
4840 return NT_STATUS_NOT_IMPLEMENTED
;
4843 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4844 if (fsp
&& fsp
->is_directory
) {
4846 SMB_VFS_SYS_ACL_GET_FILE(
4848 fsp
->fsp_name
->base_name
,
4849 SMB_ACL_TYPE_DEFAULT
);
4852 SMB_VFS_SYS_ACL_GET_FILE(
4854 smb_fname
->base_name
,
4855 SMB_ACL_TYPE_DEFAULT
);
4857 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4860 num_file_acls
= count_acl_entries(conn
, file_acl
);
4861 num_def_acls
= count_acl_entries(conn
, def_acl
);
4863 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4864 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4866 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4867 SMB_POSIX_ACL_HEADER_SIZE
) ));
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4872 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4874 return NT_STATUS_BUFFER_TOO_SMALL
;
4877 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4878 SSVAL(pdata
,2,num_file_acls
);
4879 SSVAL(pdata
,4,num_def_acls
);
4880 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4887 return NT_STATUS_INTERNAL_ERROR
;
4889 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4896 return NT_STATUS_INTERNAL_ERROR
;
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4905 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4911 case SMB_QUERY_POSIX_LOCK
:
4916 enum brl_type lock_type
;
4918 /* We need an open file with a real fd for this. */
4919 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4920 return NT_STATUS_INVALID_LEVEL
;
4923 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4924 return NT_STATUS_INVALID_PARAMETER
;
4927 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4928 case POSIX_LOCK_TYPE_READ
:
4929 lock_type
= READ_LOCK
;
4931 case POSIX_LOCK_TYPE_WRITE
:
4932 lock_type
= WRITE_LOCK
;
4934 case POSIX_LOCK_TYPE_UNLOCK
:
4936 /* There's no point in asking for an unlock... */
4937 return NT_STATUS_INVALID_PARAMETER
;
4940 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4941 #if defined(HAVE_LONGLONG)
4942 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4943 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4944 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4945 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4946 #else /* HAVE_LONGLONG */
4947 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4948 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4949 #endif /* HAVE_LONGLONG */
4951 status
= query_lock(fsp
,
4958 if (ERROR_WAS_LOCK_DENIED(status
)) {
4959 /* Here we need to report who has it locked... */
4960 data_size
= POSIX_LOCK_DATA_SIZE
;
4962 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4963 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4964 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4965 #if defined(HAVE_LONGLONG)
4966 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4967 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4968 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4969 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4970 #else /* HAVE_LONGLONG */
4971 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4972 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4973 #endif /* HAVE_LONGLONG */
4975 } else if (NT_STATUS_IS_OK(status
)) {
4976 /* For success we just return a copy of what we sent
4977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4978 data_size
= POSIX_LOCK_DATA_SIZE
;
4979 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4980 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4988 return NT_STATUS_INVALID_LEVEL
;
4991 *pdata_size
= data_size
;
4992 return NT_STATUS_OK
;
4995 /****************************************************************************
4996 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4997 file name or file id).
4998 ****************************************************************************/
5000 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5001 struct smb_request
*req
,
5002 unsigned int tran_call
,
5003 char **pparams
, int total_params
,
5004 char **ppdata
, int total_data
,
5005 unsigned int max_data_bytes
)
5007 char *params
= *pparams
;
5008 char *pdata
= *ppdata
;
5010 unsigned int data_size
= 0;
5011 unsigned int param_size
= 2;
5012 struct smb_filename
*smb_fname
= NULL
;
5013 bool delete_pending
= False
;
5014 struct timespec write_time_ts
;
5015 files_struct
*fsp
= NULL
;
5016 struct file_id fileid
;
5017 struct ea_list
*ea_list
= NULL
;
5018 int lock_data_count
= 0;
5019 char *lock_data
= NULL
;
5020 NTSTATUS status
= NT_STATUS_OK
;
5023 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5027 ZERO_STRUCT(write_time_ts
);
5029 if (tran_call
== TRANSACT2_QFILEINFO
) {
5030 if (total_params
< 4) {
5031 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5036 call_trans2qpipeinfo(conn
, req
, tran_call
,
5037 pparams
, total_params
,
5043 fsp
= file_fsp(req
, SVAL(params
,0));
5044 info_level
= SVAL(params
,2);
5046 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5048 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5049 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5053 /* Initial check for valid fsp ptr. */
5054 if (!check_fsp_open(conn
, req
, fsp
)) {
5058 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5060 if (!NT_STATUS_IS_OK(status
)) {
5061 reply_nterror(req
, status
);
5065 if(fsp
->fake_file_handle
) {
5067 * This is actually for the QUOTA_FAKE_FILE --metze
5070 /* We know this name is ok, it's already passed the checks. */
5072 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5074 * This is actually a QFILEINFO on a directory
5075 * handle (returned from an NT SMB). NT5.0 seems
5076 * to do this call. JRA.
5079 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5080 /* Always do lstat for UNIX calls. */
5081 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5082 DEBUG(3,("call_trans2qfilepathinfo: "
5083 "SMB_VFS_LSTAT of %s failed "
5085 smb_fname_str_dbg(smb_fname
),
5088 map_nt_error_from_unix(errno
));
5091 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5092 DEBUG(3,("call_trans2qfilepathinfo: "
5093 "SMB_VFS_STAT of %s failed (%s)\n",
5094 smb_fname_str_dbg(smb_fname
),
5097 map_nt_error_from_unix(errno
));
5101 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5102 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5105 * Original code - this is an open file.
5107 if (!check_fsp(conn
, req
, fsp
)) {
5111 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5112 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5113 fsp
->fnum
, strerror(errno
)));
5115 map_nt_error_from_unix(errno
));
5118 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5119 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5126 if (total_params
< 7) {
5127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5131 info_level
= SVAL(params
,0);
5133 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5135 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5136 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5140 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5142 STR_TERMINATE
, &status
);
5143 if (!NT_STATUS_IS_OK(status
)) {
5144 reply_nterror(req
, status
);
5148 status
= filename_convert(req
,
5150 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5155 if (!NT_STATUS_IS_OK(status
)) {
5156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5157 reply_botherror(req
,
5158 NT_STATUS_PATH_NOT_COVERED
,
5159 ERRSRV
, ERRbadpath
);
5162 reply_nterror(req
, status
);
5166 /* If this is a stream, check if there is a delete_pending. */
5167 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5168 && is_ntfs_stream_smb_fname(smb_fname
)) {
5169 struct smb_filename
*smb_fname_base
= NULL
;
5171 /* Create an smb_filename with stream_name == NULL. */
5173 create_synthetic_smb_fname(talloc_tos(),
5174 smb_fname
->base_name
,
5177 if (!NT_STATUS_IS_OK(status
)) {
5178 reply_nterror(req
, status
);
5182 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed "
5188 smb_fname_str_dbg(smb_fname_base
),
5190 TALLOC_FREE(smb_fname_base
);
5192 map_nt_error_from_unix(errno
));
5196 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "fileinfo of %s failed "
5200 smb_fname_str_dbg(smb_fname_base
),
5202 TALLOC_FREE(smb_fname_base
);
5204 map_nt_error_from_unix(errno
));
5209 fileid
= vfs_file_id_from_sbuf(conn
,
5210 &smb_fname_base
->st
);
5211 TALLOC_FREE(smb_fname_base
);
5212 get_file_infos(fileid
, &delete_pending
, NULL
);
5213 if (delete_pending
) {
5214 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5219 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname
),
5227 map_nt_error_from_unix(errno
));
5232 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname
),
5238 map_nt_error_from_unix(errno
));
5243 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5244 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5245 if (delete_pending
) {
5246 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5251 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5252 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5253 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5255 /* Pull out any data sent here before we realloc. */
5256 switch (info_level
) {
5257 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5259 /* Pull any EA list from the data portion. */
5262 if (total_data
< 4) {
5264 req
, NT_STATUS_INVALID_PARAMETER
);
5267 ea_size
= IVAL(pdata
,0);
5269 if (total_data
> 0 && ea_size
!= total_data
) {
5270 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5271 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5273 req
, NT_STATUS_INVALID_PARAMETER
);
5277 if (!lp_ea_support(SNUM(conn
))) {
5278 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5282 /* Pull out the list of names. */
5283 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5286 req
, NT_STATUS_INVALID_PARAMETER
);
5292 case SMB_QUERY_POSIX_LOCK
:
5294 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5295 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5299 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5301 req
, NT_STATUS_INVALID_PARAMETER
);
5305 /* Copy the lock range data. */
5306 lock_data
= (char *)TALLOC_MEMDUP(
5307 req
, pdata
, total_data
);
5309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5312 lock_data_count
= total_data
;
5318 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5319 if (*pparams
== NULL
) {
5320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5327 * draft-leach-cifs-v1-spec-02.txt
5328 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5331 * The requested information is placed in the Data portion of the
5332 * transaction response. For the information levels greater than 0x100,
5333 * the transaction response has 1 parameter word which should be
5334 * ignored by the client.
5336 * However Windows only follows this rule for the IS_NAME_VALID call.
5338 switch (info_level
) {
5339 case SMB_INFO_IS_NAME_VALID
:
5344 if ((info_level
& 0xFF00) == 0xFF00) {
5346 * We use levels that start with 0xFF00
5347 * internally to represent SMB2 specific levels
5349 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5353 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5355 delete_pending
, write_time_ts
,
5357 lock_data_count
, lock_data
,
5358 req
->flags2
, max_data_bytes
,
5359 ppdata
, &data_size
);
5360 if (!NT_STATUS_IS_OK(status
)) {
5361 reply_nterror(req
, status
);
5365 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5371 /****************************************************************************
5372 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5374 ****************************************************************************/
5376 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5377 connection_struct
*conn
,
5378 struct smb_request
*req
,
5379 bool overwrite_if_exists
,
5380 const struct smb_filename
*smb_fname_old
,
5381 struct smb_filename
*smb_fname_new
)
5383 NTSTATUS status
= NT_STATUS_OK
;
5385 /* source must already exist. */
5386 if (!VALID_STAT(smb_fname_old
->st
)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5390 if (VALID_STAT(smb_fname_new
->st
)) {
5391 if (overwrite_if_exists
) {
5392 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5393 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5395 status
= unlink_internals(conn
,
5397 FILE_ATTRIBUTE_NORMAL
,
5400 if (!NT_STATUS_IS_OK(status
)) {
5404 /* Disallow if newname already exists. */
5405 return NT_STATUS_OBJECT_NAME_COLLISION
;
5409 /* No links from a directory. */
5410 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5411 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5414 /* Setting a hardlink to/from a stream isn't currently supported. */
5415 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5416 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5417 return NT_STATUS_INVALID_PARAMETER
;
5420 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5421 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5423 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5424 smb_fname_new
->base_name
) != 0) {
5425 status
= map_nt_error_from_unix(errno
);
5426 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5427 nt_errstr(status
), smb_fname_old
->base_name
,
5428 smb_fname_new
->base_name
));
5433 /****************************************************************************
5434 Deal with setting the time from any of the setfilepathinfo functions.
5435 ****************************************************************************/
5437 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5439 const struct smb_filename
*smb_fname
,
5440 struct smb_file_time
*ft
,
5441 bool setting_write_time
)
5443 struct smb_filename smb_fname_base
;
5445 FILE_NOTIFY_CHANGE_LAST_ACCESS
5446 |FILE_NOTIFY_CHANGE_LAST_WRITE
5447 |FILE_NOTIFY_CHANGE_CREATION
;
5449 if (!VALID_STAT(smb_fname
->st
)) {
5450 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5453 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5454 return NT_STATUS_ACCESS_DENIED
;
5457 /* get some defaults (no modifications) if any info is zero or -1. */
5458 if (null_timespec(ft
->create_time
)) {
5459 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5462 if (null_timespec(ft
->atime
)) {
5463 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5466 if (null_timespec(ft
->mtime
)) {
5467 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5470 if (!setting_write_time
) {
5471 /* ft->mtime comes from change time, not write time. */
5472 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5475 /* Ensure the resolution is the correct for
5476 * what we can store on this filesystem. */
5478 round_timespec(conn
->ts_res
, &ft
->create_time
);
5479 round_timespec(conn
->ts_res
, &ft
->ctime
);
5480 round_timespec(conn
->ts_res
, &ft
->atime
);
5481 round_timespec(conn
->ts_res
, &ft
->mtime
);
5483 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5485 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5487 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5488 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5489 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5490 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5492 if (setting_write_time
) {
5494 * This was a Windows setfileinfo on an open file.
5495 * NT does this a lot. We also need to
5496 * set the time here, as it can be read by
5497 * FindFirst/FindNext and with the patch for bug #2045
5498 * in smbd/fileio.c it ensures that this timestamp is
5499 * kept sticky even after a write. We save the request
5500 * away and will set it on file close and after a write. JRA.
5503 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5504 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5507 if (fsp
->base_fsp
) {
5508 set_sticky_write_time_fsp(fsp
->base_fsp
,
5511 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5514 set_sticky_write_time_path(
5515 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5520 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5522 /* Always call ntimes on the base, even if a stream was passed in. */
5523 smb_fname_base
= *smb_fname
;
5524 smb_fname_base
.stream_name
= NULL
;
5526 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5527 return map_nt_error_from_unix(errno
);
5530 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5531 smb_fname
->base_name
);
5532 return NT_STATUS_OK
;
5535 /****************************************************************************
5536 Deal with setting the dosmode from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5540 const struct smb_filename
*smb_fname
,
5543 struct smb_filename
*smb_fname_base
= NULL
;
5546 if (!VALID_STAT(smb_fname
->st
)) {
5547 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5550 /* Always operate on the base_name, even if a stream was passed in. */
5551 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5552 NULL
, &smb_fname
->st
,
5554 if (!NT_STATUS_IS_OK(status
)) {
5559 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5566 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5568 /* check the mode isn't different, before changing it */
5569 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5570 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5571 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5572 (unsigned int)dosmode
));
5574 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5576 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5578 smb_fname_str_dbg(smb_fname_base
),
5580 status
= map_nt_error_from_unix(errno
);
5584 status
= NT_STATUS_OK
;
5586 TALLOC_FREE(smb_fname_base
);
5590 /****************************************************************************
5591 Deal with setting the size from any of the setfilepathinfo functions.
5592 ****************************************************************************/
5594 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5595 struct smb_request
*req
,
5597 const struct smb_filename
*smb_fname
,
5598 const SMB_STRUCT_STAT
*psbuf
,
5600 bool fail_after_createfile
)
5602 NTSTATUS status
= NT_STATUS_OK
;
5603 struct smb_filename
*smb_fname_tmp
= NULL
;
5604 files_struct
*new_fsp
= NULL
;
5606 if (!VALID_STAT(*psbuf
)) {
5607 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5610 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5611 return NT_STATUS_ACCESS_DENIED
;
5614 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5616 if (size
== get_file_size_stat(psbuf
)) {
5617 return NT_STATUS_OK
;
5620 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5621 smb_fname_str_dbg(smb_fname
), (double)size
));
5623 if (fsp
&& fsp
->fh
->fd
!= -1) {
5624 /* Handle based call. */
5625 if (vfs_set_filelen(fsp
, size
) == -1) {
5626 return map_nt_error_from_unix(errno
);
5628 trigger_write_time_update_immediate(fsp
);
5629 return NT_STATUS_OK
;
5632 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5633 if (!NT_STATUS_IS_OK(status
)) {
5637 smb_fname_tmp
->st
= *psbuf
;
5639 status
= SMB_VFS_CREATE_FILE(
5642 0, /* root_dir_fid */
5643 smb_fname_tmp
, /* fname */
5644 FILE_WRITE_DATA
, /* access_mask */
5645 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5647 FILE_OPEN
, /* create_disposition*/
5648 0, /* create_options */
5649 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5650 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5651 0, /* allocation_size */
5652 0, /* private_flags */
5655 &new_fsp
, /* result */
5658 TALLOC_FREE(smb_fname_tmp
);
5660 if (!NT_STATUS_IS_OK(status
)) {
5661 /* NB. We check for open_was_deferred in the caller. */
5665 /* See RAW-SFILEINFO-END-OF-FILE */
5666 if (fail_after_createfile
) {
5667 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5668 return NT_STATUS_INVALID_LEVEL
;
5671 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5672 status
= map_nt_error_from_unix(errno
);
5673 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5677 trigger_write_time_update_immediate(new_fsp
);
5678 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5679 return NT_STATUS_OK
;
5682 /****************************************************************************
5683 Deal with SMB_INFO_SET_EA.
5684 ****************************************************************************/
5686 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5690 const struct smb_filename
*smb_fname
)
5692 struct ea_list
*ea_list
= NULL
;
5693 TALLOC_CTX
*ctx
= NULL
;
5694 NTSTATUS status
= NT_STATUS_OK
;
5696 if (total_data
< 10) {
5698 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5699 length. They seem to have no effect. Bug #3212. JRA */
5701 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5702 /* We're done. We only get EA info in this call. */
5703 return NT_STATUS_OK
;
5706 return NT_STATUS_INVALID_PARAMETER
;
5709 if (IVAL(pdata
,0) > total_data
) {
5710 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5711 IVAL(pdata
,0), (unsigned int)total_data
));
5712 return NT_STATUS_INVALID_PARAMETER
;
5716 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5718 return NT_STATUS_INVALID_PARAMETER
;
5721 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5722 return NT_STATUS_ACCESS_DENIED
;
5725 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5730 /****************************************************************************
5731 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5732 ****************************************************************************/
5734 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5739 struct ea_list
*ea_list
= NULL
;
5743 return NT_STATUS_INVALID_HANDLE
;
5746 if (!lp_ea_support(SNUM(conn
))) {
5747 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5748 "EA's not supported.\n",
5749 (unsigned int)total_data
));
5750 return NT_STATUS_EAS_NOT_SUPPORTED
;
5753 if (total_data
< 10) {
5754 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5756 (unsigned int)total_data
));
5757 return NT_STATUS_INVALID_PARAMETER
;
5760 ea_list
= read_nttrans_ea_list(talloc_tos(),
5765 return NT_STATUS_INVALID_PARAMETER
;
5768 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5769 return NT_STATUS_ACCESS_DENIED
;
5772 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5774 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5775 smb_fname_str_dbg(fsp
->fsp_name
),
5776 nt_errstr(status
) ));
5782 /****************************************************************************
5783 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5784 ****************************************************************************/
5786 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5790 struct smb_filename
*smb_fname
)
5792 NTSTATUS status
= NT_STATUS_OK
;
5793 bool delete_on_close
;
5796 if (total_data
< 1) {
5797 return NT_STATUS_INVALID_PARAMETER
;
5801 return NT_STATUS_INVALID_HANDLE
;
5804 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5805 dosmode
= dos_mode(conn
, smb_fname
);
5807 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5808 "delete_on_close = %u\n",
5809 smb_fname_str_dbg(smb_fname
),
5810 (unsigned int)dosmode
,
5811 (unsigned int)delete_on_close
));
5813 if (delete_on_close
) {
5814 status
= can_set_delete_on_close(fsp
, dosmode
);
5815 if (!NT_STATUS_IS_OK(status
)) {
5820 /* The set is across all open files on this dev/inode pair. */
5821 if (!set_delete_on_close(fsp
, delete_on_close
,
5822 &conn
->server_info
->utok
)) {
5823 return NT_STATUS_ACCESS_DENIED
;
5825 return NT_STATUS_OK
;
5828 /****************************************************************************
5829 Deal with SMB_FILE_POSITION_INFORMATION.
5830 ****************************************************************************/
5832 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5837 uint64_t position_information
;
5839 if (total_data
< 8) {
5840 return NT_STATUS_INVALID_PARAMETER
;
5844 /* Ignore on pathname based set. */
5845 return NT_STATUS_OK
;
5848 position_information
= (uint64_t)IVAL(pdata
,0);
5849 #ifdef LARGE_SMB_OFF_T
5850 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5851 #else /* LARGE_SMB_OFF_T */
5852 if (IVAL(pdata
,4) != 0) {
5853 /* more than 32 bits? */
5854 return NT_STATUS_INVALID_PARAMETER
;
5856 #endif /* LARGE_SMB_OFF_T */
5858 DEBUG(10,("smb_file_position_information: Set file position "
5859 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5860 (double)position_information
));
5861 fsp
->fh
->position_information
= position_information
;
5862 return NT_STATUS_OK
;
5865 /****************************************************************************
5866 Deal with SMB_FILE_MODE_INFORMATION.
5867 ****************************************************************************/
5869 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5875 if (total_data
< 4) {
5876 return NT_STATUS_INVALID_PARAMETER
;
5878 mode
= IVAL(pdata
,0);
5879 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5880 return NT_STATUS_INVALID_PARAMETER
;
5882 return NT_STATUS_OK
;
5885 /****************************************************************************
5886 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5887 ****************************************************************************/
5889 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5890 struct smb_request
*req
,
5893 const struct smb_filename
*smb_fname
)
5895 char *link_target
= NULL
;
5896 const char *newname
= smb_fname
->base_name
;
5897 TALLOC_CTX
*ctx
= talloc_tos();
5899 /* Set a symbolic link. */
5900 /* Don't allow this if follow links is false. */
5902 if (total_data
== 0) {
5903 return NT_STATUS_INVALID_PARAMETER
;
5906 if (!lp_symlinks(SNUM(conn
))) {
5907 return NT_STATUS_ACCESS_DENIED
;
5910 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5911 total_data
, STR_TERMINATE
);
5914 return NT_STATUS_INVALID_PARAMETER
;
5917 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5918 newname
, link_target
));
5920 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5921 return map_nt_error_from_unix(errno
);
5924 return NT_STATUS_OK
;
5927 /****************************************************************************
5928 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5929 ****************************************************************************/
5931 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5932 struct smb_request
*req
,
5933 const char *pdata
, int total_data
,
5934 struct smb_filename
*smb_fname_new
)
5936 char *oldname
= NULL
;
5937 struct smb_filename
*smb_fname_old
= NULL
;
5938 TALLOC_CTX
*ctx
= talloc_tos();
5939 NTSTATUS status
= NT_STATUS_OK
;
5941 /* Set a hard link. */
5942 if (total_data
== 0) {
5943 return NT_STATUS_INVALID_PARAMETER
;
5946 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5947 total_data
, STR_TERMINATE
, &status
);
5948 if (!NT_STATUS_IS_OK(status
)) {
5952 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5953 smb_fname_str_dbg(smb_fname_new
), oldname
));
5955 status
= filename_convert(ctx
,
5957 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5962 if (!NT_STATUS_IS_OK(status
)) {
5966 return hardlink_internals(ctx
, conn
, req
, false,
5967 smb_fname_old
, smb_fname_new
);
5970 /****************************************************************************
5971 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5972 ****************************************************************************/
5974 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5975 struct smb_request
*req
,
5979 struct smb_filename
*smb_fname_src
)
5983 char *newname
= NULL
;
5984 struct smb_filename
*smb_fname_dst
= NULL
;
5985 NTSTATUS status
= NT_STATUS_OK
;
5986 TALLOC_CTX
*ctx
= talloc_tos();
5989 return NT_STATUS_INVALID_HANDLE
;
5992 if (total_data
< 20) {
5993 return NT_STATUS_INVALID_PARAMETER
;
5996 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5997 len
= IVAL(pdata
,16);
5999 if (len
> (total_data
- 20) || (len
== 0)) {
6000 return NT_STATUS_INVALID_PARAMETER
;
6003 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6004 &pdata
[20], len
, STR_TERMINATE
,
6006 if (!NT_STATUS_IS_OK(status
)) {
6010 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6013 status
= filename_convert(ctx
,
6015 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6020 if (!NT_STATUS_IS_OK(status
)) {
6024 if (fsp
->base_fsp
) {
6025 /* newname must be a stream name. */
6026 if (newname
[0] != ':') {
6027 return NT_STATUS_NOT_SUPPORTED
;
6030 /* Create an smb_fname to call rename_internals_fsp() with. */
6031 status
= create_synthetic_smb_fname(talloc_tos(),
6032 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6034 if (!NT_STATUS_IS_OK(status
)) {
6039 * Set the original last component, since
6040 * rename_internals_fsp() requires it.
6042 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6044 if (smb_fname_dst
->original_lcomp
== NULL
) {
6045 status
= NT_STATUS_NO_MEMORY
;
6051 DEBUG(10,("smb2_file_rename_information: "
6052 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6053 fsp
->fnum
, fsp_str_dbg(fsp
),
6054 smb_fname_str_dbg(smb_fname_dst
)));
6055 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6059 TALLOC_FREE(smb_fname_dst
);
6063 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6064 struct smb_request
*req
,
6068 struct smb_filename
*smb_fname_src
)
6072 char *newname
= NULL
;
6073 struct smb_filename
*smb_fname_dst
= NULL
;
6074 NTSTATUS status
= NT_STATUS_OK
;
6075 TALLOC_CTX
*ctx
= talloc_tos();
6078 return NT_STATUS_INVALID_HANDLE
;
6081 if (total_data
< 20) {
6082 return NT_STATUS_INVALID_PARAMETER
;
6085 overwrite
= (CVAL(pdata
,0) ? true : false);
6086 len
= IVAL(pdata
,16);
6088 if (len
> (total_data
- 20) || (len
== 0)) {
6089 return NT_STATUS_INVALID_PARAMETER
;
6092 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6093 &pdata
[20], len
, STR_TERMINATE
,
6095 if (!NT_STATUS_IS_OK(status
)) {
6099 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6102 status
= filename_convert(ctx
,
6104 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6109 if (!NT_STATUS_IS_OK(status
)) {
6113 if (fsp
->base_fsp
) {
6114 /* No stream names. */
6115 return NT_STATUS_NOT_SUPPORTED
;
6118 DEBUG(10,("smb_file_link_information: "
6119 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6120 fsp
->fnum
, fsp_str_dbg(fsp
),
6121 smb_fname_str_dbg(smb_fname_dst
)));
6122 status
= hardlink_internals(ctx
,
6129 TALLOC_FREE(smb_fname_dst
);
6133 /****************************************************************************
6134 Deal with SMB_FILE_RENAME_INFORMATION.
6135 ****************************************************************************/
6137 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6138 struct smb_request
*req
,
6142 struct smb_filename
*smb_fname_src
)
6147 char *newname
= NULL
;
6148 struct smb_filename
*smb_fname_dst
= NULL
;
6149 bool dest_has_wcard
= False
;
6150 NTSTATUS status
= NT_STATUS_OK
;
6152 TALLOC_CTX
*ctx
= talloc_tos();
6154 if (total_data
< 13) {
6155 return NT_STATUS_INVALID_PARAMETER
;
6158 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6159 root_fid
= IVAL(pdata
,4);
6160 len
= IVAL(pdata
,8);
6162 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6163 return NT_STATUS_INVALID_PARAMETER
;
6166 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6169 if (!NT_STATUS_IS_OK(status
)) {
6173 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6176 status
= resolve_dfspath_wcard(ctx
, conn
,
6177 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6182 if (!NT_STATUS_IS_OK(status
)) {
6186 /* Check the new name has no '/' characters. */
6187 if (strchr_m(newname
, '/')) {
6188 return NT_STATUS_NOT_SUPPORTED
;
6191 if (fsp
&& fsp
->base_fsp
) {
6192 /* newname must be a stream name. */
6193 if (newname
[0] != ':') {
6194 return NT_STATUS_NOT_SUPPORTED
;
6197 /* Create an smb_fname to call rename_internals_fsp() with. */
6198 status
= create_synthetic_smb_fname(talloc_tos(),
6199 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6201 if (!NT_STATUS_IS_OK(status
)) {
6206 * Set the original last component, since
6207 * rename_internals_fsp() requires it.
6209 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6211 if (smb_fname_dst
->original_lcomp
== NULL
) {
6212 status
= NT_STATUS_NO_MEMORY
;
6218 * Build up an smb_fname_dst based on the filename passed in.
6219 * We basically just strip off the last component, and put on
6220 * the newname instead.
6222 char *base_name
= NULL
;
6224 /* newname must *not* be a stream name. */
6225 if (newname
[0] == ':') {
6226 return NT_STATUS_NOT_SUPPORTED
;
6230 * Strip off the last component (filename) of the path passed
6233 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6235 return NT_STATUS_NO_MEMORY
;
6237 p
= strrchr_m(base_name
, '/');
6241 base_name
= talloc_strdup(ctx
, "./");
6243 return NT_STATUS_NO_MEMORY
;
6246 /* Append the new name. */
6247 base_name
= talloc_asprintf_append(base_name
,
6251 return NT_STATUS_NO_MEMORY
;
6254 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6257 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6260 /* If an error we expect this to be
6261 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6263 if (!NT_STATUS_IS_OK(status
)) {
6264 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6268 /* Create an smb_fname to call rename_internals_fsp() */
6269 status
= create_synthetic_smb_fname(ctx
,
6273 if (!NT_STATUS_IS_OK(status
)) {
6280 DEBUG(10,("smb_file_rename_information: "
6281 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6282 fsp
->fnum
, fsp_str_dbg(fsp
),
6283 smb_fname_str_dbg(smb_fname_dst
)));
6284 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6287 DEBUG(10,("smb_file_rename_information: "
6288 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6289 smb_fname_str_dbg(smb_fname_src
),
6290 smb_fname_str_dbg(smb_fname_dst
)));
6291 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6292 smb_fname_dst
, 0, overwrite
, false,
6294 FILE_WRITE_ATTRIBUTES
);
6297 TALLOC_FREE(smb_fname_dst
);
6301 /****************************************************************************
6302 Deal with SMB_SET_POSIX_ACL.
6303 ****************************************************************************/
6305 #if defined(HAVE_POSIX_ACLS)
6306 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6310 const struct smb_filename
*smb_fname
)
6312 uint16 posix_acl_version
;
6313 uint16 num_file_acls
;
6314 uint16 num_def_acls
;
6315 bool valid_file_acls
= True
;
6316 bool valid_def_acls
= True
;
6318 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6319 return NT_STATUS_INVALID_PARAMETER
;
6321 posix_acl_version
= SVAL(pdata
,0);
6322 num_file_acls
= SVAL(pdata
,2);
6323 num_def_acls
= SVAL(pdata
,4);
6325 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6326 valid_file_acls
= False
;
6330 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6331 valid_def_acls
= False
;
6335 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6336 return NT_STATUS_INVALID_PARAMETER
;
6339 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6340 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6341 return NT_STATUS_INVALID_PARAMETER
;
6344 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6345 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6346 (unsigned int)num_file_acls
,
6347 (unsigned int)num_def_acls
));
6349 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6350 smb_fname
->base_name
, num_file_acls
,
6351 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6352 return map_nt_error_from_unix(errno
);
6355 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6356 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6357 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6358 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6359 return map_nt_error_from_unix(errno
);
6361 return NT_STATUS_OK
;
6365 /****************************************************************************
6366 Deal with SMB_SET_POSIX_LOCK.
6367 ****************************************************************************/
6369 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6370 struct smb_request
*req
,
6378 bool blocking_lock
= False
;
6379 enum brl_type lock_type
;
6381 NTSTATUS status
= NT_STATUS_OK
;
6383 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6384 return NT_STATUS_INVALID_HANDLE
;
6387 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6388 return NT_STATUS_INVALID_PARAMETER
;
6391 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6392 case POSIX_LOCK_TYPE_READ
:
6393 lock_type
= READ_LOCK
;
6395 case POSIX_LOCK_TYPE_WRITE
:
6396 /* Return the right POSIX-mappable error code for files opened read-only. */
6397 if (!fsp
->can_write
) {
6398 return NT_STATUS_INVALID_HANDLE
;
6400 lock_type
= WRITE_LOCK
;
6402 case POSIX_LOCK_TYPE_UNLOCK
:
6403 lock_type
= UNLOCK_LOCK
;
6406 return NT_STATUS_INVALID_PARAMETER
;
6409 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6410 blocking_lock
= False
;
6411 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6412 blocking_lock
= True
;
6414 return NT_STATUS_INVALID_PARAMETER
;
6417 if (!lp_blocking_locks(SNUM(conn
))) {
6418 blocking_lock
= False
;
6421 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6422 #if defined(HAVE_LONGLONG)
6423 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6424 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6425 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6426 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6427 #else /* HAVE_LONGLONG */
6428 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6429 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6430 #endif /* HAVE_LONGLONG */
6432 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6433 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6435 (unsigned int)lock_type
,
6436 (unsigned long long)smblctx
,
6440 if (lock_type
== UNLOCK_LOCK
) {
6441 status
= do_unlock(req
->sconn
->msg_ctx
,
6448 uint64_t block_smblctx
;
6450 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6462 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6464 * A blocking lock was requested. Package up
6465 * this smb into a queued request and push it
6466 * onto the blocking lock queue.
6468 if(push_blocking_lock_request(br_lck
,
6471 -1, /* infinite timeout. */
6479 TALLOC_FREE(br_lck
);
6483 TALLOC_FREE(br_lck
);
6489 /****************************************************************************
6490 Deal with SMB_SET_FILE_BASIC_INFO.
6491 ****************************************************************************/
6493 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6497 const struct smb_filename
*smb_fname
)
6499 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6500 struct smb_file_time ft
;
6502 NTSTATUS status
= NT_STATUS_OK
;
6506 if (total_data
< 36) {
6507 return NT_STATUS_INVALID_PARAMETER
;
6510 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6511 return NT_STATUS_ACCESS_DENIED
;
6514 /* Set the attributes */
6515 dosmode
= IVAL(pdata
,32);
6516 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6517 if (!NT_STATUS_IS_OK(status
)) {
6522 ft
.create_time
= interpret_long_date(pdata
);
6525 ft
.atime
= interpret_long_date(pdata
+8);
6528 ft
.mtime
= interpret_long_date(pdata
+16);
6531 ft
.ctime
= interpret_long_date(pdata
+24);
6533 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6534 smb_fname_str_dbg(smb_fname
)));
6536 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6540 /****************************************************************************
6541 Deal with SMB_INFO_STANDARD.
6542 ****************************************************************************/
6544 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6548 const struct smb_filename
*smb_fname
)
6550 struct smb_file_time ft
;
6554 if (total_data
< 12) {
6555 return NT_STATUS_INVALID_PARAMETER
;
6558 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6559 return NT_STATUS_ACCESS_DENIED
;
6563 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6565 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6567 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6569 DEBUG(10,("smb_set_info_standard: file %s\n",
6570 smb_fname_str_dbg(smb_fname
)));
6572 return smb_set_file_time(conn
,
6579 /****************************************************************************
6580 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6581 ****************************************************************************/
6583 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6584 struct smb_request
*req
,
6588 struct smb_filename
*smb_fname
)
6590 uint64_t allocation_size
= 0;
6591 NTSTATUS status
= NT_STATUS_OK
;
6592 files_struct
*new_fsp
= NULL
;
6594 if (!VALID_STAT(smb_fname
->st
)) {
6595 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6598 if (total_data
< 8) {
6599 return NT_STATUS_INVALID_PARAMETER
;
6602 allocation_size
= (uint64_t)IVAL(pdata
,0);
6603 #ifdef LARGE_SMB_OFF_T
6604 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6605 #else /* LARGE_SMB_OFF_T */
6606 if (IVAL(pdata
,4) != 0) {
6607 /* more than 32 bits? */
6608 return NT_STATUS_INVALID_PARAMETER
;
6610 #endif /* LARGE_SMB_OFF_T */
6612 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6613 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6614 (double)allocation_size
));
6616 if (allocation_size
) {
6617 allocation_size
= smb_roundup(conn
, allocation_size
);
6620 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6621 return NT_STATUS_ACCESS_DENIED
;
6624 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6625 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6626 (double)allocation_size
));
6628 if (fsp
&& fsp
->fh
->fd
!= -1) {
6629 /* Open file handle. */
6630 /* Only change if needed. */
6631 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6632 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6633 return map_nt_error_from_unix(errno
);
6636 /* But always update the time. */
6638 * This is equivalent to a write. Ensure it's seen immediately
6639 * if there are no pending writes.
6641 trigger_write_time_update_immediate(fsp
);
6642 return NT_STATUS_OK
;
6645 /* Pathname or stat or directory file. */
6646 status
= SMB_VFS_CREATE_FILE(
6649 0, /* root_dir_fid */
6650 smb_fname
, /* fname */
6651 FILE_WRITE_DATA
, /* access_mask */
6652 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6654 FILE_OPEN
, /* create_disposition*/
6655 0, /* create_options */
6656 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6657 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6658 0, /* allocation_size */
6659 0, /* private_flags */
6662 &new_fsp
, /* result */
6665 if (!NT_STATUS_IS_OK(status
)) {
6666 /* NB. We check for open_was_deferred in the caller. */
6670 /* Only change if needed. */
6671 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6672 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6673 status
= map_nt_error_from_unix(errno
);
6674 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6679 /* Changing the allocation size should set the last mod time. */
6681 * This is equivalent to a write. Ensure it's seen immediately
6682 * if there are no pending writes.
6684 trigger_write_time_update_immediate(new_fsp
);
6686 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6687 return NT_STATUS_OK
;
6690 /****************************************************************************
6691 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6692 ****************************************************************************/
6694 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6695 struct smb_request
*req
,
6699 const struct smb_filename
*smb_fname
,
6700 bool fail_after_createfile
)
6704 if (total_data
< 8) {
6705 return NT_STATUS_INVALID_PARAMETER
;
6708 size
= IVAL(pdata
,0);
6709 #ifdef LARGE_SMB_OFF_T
6710 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6711 #else /* LARGE_SMB_OFF_T */
6712 if (IVAL(pdata
,4) != 0) {
6713 /* more than 32 bits? */
6714 return NT_STATUS_INVALID_PARAMETER
;
6716 #endif /* LARGE_SMB_OFF_T */
6717 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6718 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6721 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6722 return NT_STATUS_ACCESS_DENIED
;
6725 return smb_set_file_size(conn
, req
,
6730 fail_after_createfile
);
6733 /****************************************************************************
6734 Allow a UNIX info mknod.
6735 ****************************************************************************/
6737 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6740 const struct smb_filename
*smb_fname
)
6742 uint32 file_type
= IVAL(pdata
,56);
6743 #if defined(HAVE_MAKEDEV)
6744 uint32 dev_major
= IVAL(pdata
,60);
6745 uint32 dev_minor
= IVAL(pdata
,68);
6747 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6748 uint32 raw_unixmode
= IVAL(pdata
,84);
6752 if (total_data
< 100) {
6753 return NT_STATUS_INVALID_PARAMETER
;
6756 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6757 PERM_NEW_FILE
, &unixmode
);
6758 if (!NT_STATUS_IS_OK(status
)) {
6762 #if defined(HAVE_MAKEDEV)
6763 dev
= makedev(dev_major
, dev_minor
);
6766 switch (file_type
) {
6767 #if defined(S_IFIFO)
6768 case UNIX_TYPE_FIFO
:
6769 unixmode
|= S_IFIFO
;
6772 #if defined(S_IFSOCK)
6773 case UNIX_TYPE_SOCKET
:
6774 unixmode
|= S_IFSOCK
;
6777 #if defined(S_IFCHR)
6778 case UNIX_TYPE_CHARDEV
:
6779 unixmode
|= S_IFCHR
;
6782 #if defined(S_IFBLK)
6783 case UNIX_TYPE_BLKDEV
:
6784 unixmode
|= S_IFBLK
;
6788 return NT_STATUS_INVALID_PARAMETER
;
6791 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6792 "%.0f mode 0%o for file %s\n", (double)dev
,
6793 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6795 /* Ok - do the mknod. */
6796 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6797 return map_nt_error_from_unix(errno
);
6800 /* If any of the other "set" calls fail we
6801 * don't want to end up with a half-constructed mknod.
6804 if (lp_inherit_perms(SNUM(conn
))) {
6806 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6808 return NT_STATUS_NO_MEMORY
;
6810 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6812 TALLOC_FREE(parent
);
6815 return NT_STATUS_OK
;
6818 /****************************************************************************
6819 Deal with SMB_SET_FILE_UNIX_BASIC.
6820 ****************************************************************************/
6822 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6823 struct smb_request
*req
,
6827 const struct smb_filename
*smb_fname
)
6829 struct smb_file_time ft
;
6830 uint32 raw_unixmode
;
6833 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6834 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6835 NTSTATUS status
= NT_STATUS_OK
;
6836 bool delete_on_fail
= False
;
6837 enum perm_type ptype
;
6838 files_struct
*all_fsps
= NULL
;
6839 bool modify_mtime
= true;
6841 struct smb_filename
*smb_fname_tmp
= NULL
;
6842 SMB_STRUCT_STAT sbuf
;
6846 if (total_data
< 100) {
6847 return NT_STATUS_INVALID_PARAMETER
;
6850 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6851 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6852 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6853 #ifdef LARGE_SMB_OFF_T
6854 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6855 #else /* LARGE_SMB_OFF_T */
6856 if (IVAL(pdata
,4) != 0) {
6857 /* more than 32 bits? */
6858 return NT_STATUS_INVALID_PARAMETER
;
6860 #endif /* LARGE_SMB_OFF_T */
6863 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6864 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6865 set_owner
= (uid_t
)IVAL(pdata
,40);
6866 set_grp
= (gid_t
)IVAL(pdata
,48);
6867 raw_unixmode
= IVAL(pdata
,84);
6869 if (VALID_STAT(smb_fname
->st
)) {
6870 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6871 ptype
= PERM_EXISTING_DIR
;
6873 ptype
= PERM_EXISTING_FILE
;
6876 ptype
= PERM_NEW_FILE
;
6879 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6881 if (!NT_STATUS_IS_OK(status
)) {
6885 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6886 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6887 smb_fname_str_dbg(smb_fname
), (double)size
,
6888 (unsigned int)set_owner
, (unsigned int)set_grp
,
6889 (int)raw_unixmode
));
6891 sbuf
= smb_fname
->st
;
6893 if (!VALID_STAT(sbuf
)) {
6895 * The only valid use of this is to create character and block
6896 * devices, and named pipes. This is deprecated (IMHO) and
6897 * a new info level should be used for mknod. JRA.
6900 status
= smb_unix_mknod(conn
,
6904 if (!NT_STATUS_IS_OK(status
)) {
6908 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6910 if (!NT_STATUS_IS_OK(status
)) {
6914 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6915 status
= map_nt_error_from_unix(errno
);
6916 TALLOC_FREE(smb_fname_tmp
);
6917 SMB_VFS_UNLINK(conn
, smb_fname
);
6921 sbuf
= smb_fname_tmp
->st
;
6922 smb_fname
= smb_fname_tmp
;
6924 /* Ensure we don't try and change anything else. */
6925 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6926 size
= get_file_size_stat(&sbuf
);
6927 ft
.atime
= sbuf
.st_ex_atime
;
6928 ft
.mtime
= sbuf
.st_ex_mtime
;
6930 * We continue here as we might want to change the
6933 delete_on_fail
= True
;
6937 /* Horrible backwards compatibility hack as an old server bug
6938 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6942 size
= get_file_size_stat(&sbuf
);
6947 * Deal with the UNIX specific mode set.
6950 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6951 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6952 "setting mode 0%o for file %s\n",
6953 (unsigned int)unixmode
,
6954 smb_fname_str_dbg(smb_fname
)));
6955 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6956 return map_nt_error_from_unix(errno
);
6961 * Deal with the UNIX specific uid set.
6964 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6965 (sbuf
.st_ex_uid
!= set_owner
)) {
6968 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6969 "changing owner %u for path %s\n",
6970 (unsigned int)set_owner
,
6971 smb_fname_str_dbg(smb_fname
)));
6973 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6974 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6975 set_owner
, (gid_t
)-1);
6977 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6978 set_owner
, (gid_t
)-1);
6982 status
= map_nt_error_from_unix(errno
);
6983 if (delete_on_fail
) {
6984 SMB_VFS_UNLINK(conn
, smb_fname
);
6991 * Deal with the UNIX specific gid set.
6994 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6995 (sbuf
.st_ex_gid
!= set_grp
)) {
6996 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6997 "changing group %u for file %s\n",
6998 (unsigned int)set_owner
,
6999 smb_fname_str_dbg(smb_fname
)));
7000 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7002 status
= map_nt_error_from_unix(errno
);
7003 if (delete_on_fail
) {
7004 SMB_VFS_UNLINK(conn
, smb_fname
);
7010 /* Deal with any size changes. */
7012 status
= smb_set_file_size(conn
, req
,
7018 if (!NT_STATUS_IS_OK(status
)) {
7022 /* Deal with any time changes. */
7023 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7024 /* No change, don't cancel anything. */
7028 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7029 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7030 all_fsps
= file_find_di_next(all_fsps
)) {
7032 * We're setting the time explicitly for UNIX.
7033 * Cancel any pending changes over all handles.
7035 all_fsps
->update_write_time_on_close
= false;
7036 TALLOC_FREE(all_fsps
->update_write_time_event
);
7040 * Override the "setting_write_time"
7041 * parameter here as it almost does what
7042 * we need. Just remember if we modified
7043 * mtime and send the notify ourselves.
7045 if (null_timespec(ft
.mtime
)) {
7046 modify_mtime
= false;
7049 status
= smb_set_file_time(conn
,
7055 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7056 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7061 /****************************************************************************
7062 Deal with SMB_SET_FILE_UNIX_INFO2.
7063 ****************************************************************************/
7065 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7066 struct smb_request
*req
,
7070 const struct smb_filename
*smb_fname
)
7076 if (total_data
< 116) {
7077 return NT_STATUS_INVALID_PARAMETER
;
7080 /* Start by setting all the fields that are common between UNIX_BASIC
7083 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7085 if (!NT_STATUS_IS_OK(status
)) {
7089 smb_fflags
= IVAL(pdata
, 108);
7090 smb_fmask
= IVAL(pdata
, 112);
7092 /* NB: We should only attempt to alter the file flags if the client
7093 * sends a non-zero mask.
7095 if (smb_fmask
!= 0) {
7096 int stat_fflags
= 0;
7098 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7099 smb_fmask
, &stat_fflags
)) {
7100 /* Client asked to alter a flag we don't understand. */
7101 return NT_STATUS_INVALID_PARAMETER
;
7104 if (fsp
&& fsp
->fh
->fd
!= -1) {
7105 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7106 return NT_STATUS_NOT_SUPPORTED
;
7108 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7109 stat_fflags
) != 0) {
7110 return map_nt_error_from_unix(errno
);
7115 /* XXX: need to add support for changing the create_time here. You
7116 * can do this for paths on Darwin with setattrlist(2). The right way
7117 * to hook this up is probably by extending the VFS utimes interface.
7120 return NT_STATUS_OK
;
7123 /****************************************************************************
7124 Create a directory with POSIX semantics.
7125 ****************************************************************************/
7127 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7128 struct smb_request
*req
,
7131 struct smb_filename
*smb_fname
,
7132 int *pdata_return_size
)
7134 NTSTATUS status
= NT_STATUS_OK
;
7135 uint32 raw_unixmode
= 0;
7136 uint32 mod_unixmode
= 0;
7137 mode_t unixmode
= (mode_t
)0;
7138 files_struct
*fsp
= NULL
;
7139 uint16 info_level_return
= 0;
7141 char *pdata
= *ppdata
;
7143 if (total_data
< 18) {
7144 return NT_STATUS_INVALID_PARAMETER
;
7147 raw_unixmode
= IVAL(pdata
,8);
7148 /* Next 4 bytes are not yet defined. */
7150 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7151 PERM_NEW_DIR
, &unixmode
);
7152 if (!NT_STATUS_IS_OK(status
)) {
7156 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7158 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7159 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7161 status
= SMB_VFS_CREATE_FILE(
7164 0, /* root_dir_fid */
7165 smb_fname
, /* fname */
7166 FILE_READ_ATTRIBUTES
, /* access_mask */
7167 FILE_SHARE_NONE
, /* share_access */
7168 FILE_CREATE
, /* create_disposition*/
7169 FILE_DIRECTORY_FILE
, /* create_options */
7170 mod_unixmode
, /* file_attributes */
7171 0, /* oplock_request */
7172 0, /* allocation_size */
7173 0, /* private_flags */
7179 if (NT_STATUS_IS_OK(status
)) {
7180 close_file(req
, fsp
, NORMAL_CLOSE
);
7183 info_level_return
= SVAL(pdata
,16);
7185 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7186 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7187 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7188 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7190 *pdata_return_size
= 12;
7193 /* Realloc the data size */
7194 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7195 if (*ppdata
== NULL
) {
7196 *pdata_return_size
= 0;
7197 return NT_STATUS_NO_MEMORY
;
7201 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7202 SSVAL(pdata
,2,0); /* No fnum. */
7203 SIVAL(pdata
,4,info
); /* Was directory created. */
7205 switch (info_level_return
) {
7206 case SMB_QUERY_FILE_UNIX_BASIC
:
7207 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7208 SSVAL(pdata
,10,0); /* Padding. */
7209 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7212 case SMB_QUERY_FILE_UNIX_INFO2
:
7213 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7214 SSVAL(pdata
,10,0); /* Padding. */
7215 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7219 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7220 SSVAL(pdata
,10,0); /* Padding. */
7227 /****************************************************************************
7228 Open/Create a file with POSIX semantics.
7229 ****************************************************************************/
7231 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7232 struct smb_request
*req
,
7235 struct smb_filename
*smb_fname
,
7236 int *pdata_return_size
)
7238 bool extended_oplock_granted
= False
;
7239 char *pdata
= *ppdata
;
7241 uint32 wire_open_mode
= 0;
7242 uint32 raw_unixmode
= 0;
7243 uint32 mod_unixmode
= 0;
7244 uint32 create_disp
= 0;
7245 uint32 access_mask
= 0;
7246 uint32 create_options
= 0;
7247 NTSTATUS status
= NT_STATUS_OK
;
7248 mode_t unixmode
= (mode_t
)0;
7249 files_struct
*fsp
= NULL
;
7250 int oplock_request
= 0;
7252 uint16 info_level_return
= 0;
7254 if (total_data
< 18) {
7255 return NT_STATUS_INVALID_PARAMETER
;
7258 flags
= IVAL(pdata
,0);
7259 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7260 if (oplock_request
) {
7261 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7264 wire_open_mode
= IVAL(pdata
,4);
7266 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7267 return smb_posix_mkdir(conn
, req
,
7274 switch (wire_open_mode
& SMB_ACCMODE
) {
7276 access_mask
= FILE_READ_DATA
;
7279 access_mask
= FILE_WRITE_DATA
;
7282 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7285 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7286 (unsigned int)wire_open_mode
));
7287 return NT_STATUS_INVALID_PARAMETER
;
7290 wire_open_mode
&= ~SMB_ACCMODE
;
7292 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7293 create_disp
= FILE_CREATE
;
7294 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7295 create_disp
= FILE_OVERWRITE_IF
;
7296 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7297 create_disp
= FILE_OPEN_IF
;
7298 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7299 create_disp
= FILE_OPEN
;
7301 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7302 (unsigned int)wire_open_mode
));
7303 return NT_STATUS_INVALID_PARAMETER
;
7306 raw_unixmode
= IVAL(pdata
,8);
7307 /* Next 4 bytes are not yet defined. */
7309 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7310 (VALID_STAT(smb_fname
->st
) ?
7311 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7314 if (!NT_STATUS_IS_OK(status
)) {
7318 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7320 if (wire_open_mode
& SMB_O_SYNC
) {
7321 create_options
|= FILE_WRITE_THROUGH
;
7323 if (wire_open_mode
& SMB_O_APPEND
) {
7324 access_mask
|= FILE_APPEND_DATA
;
7326 if (wire_open_mode
& SMB_O_DIRECT
) {
7327 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7330 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7331 smb_fname_str_dbg(smb_fname
),
7332 (unsigned int)wire_open_mode
,
7333 (unsigned int)unixmode
));
7335 status
= SMB_VFS_CREATE_FILE(
7338 0, /* root_dir_fid */
7339 smb_fname
, /* fname */
7340 access_mask
, /* access_mask */
7341 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7343 create_disp
, /* create_disposition*/
7344 FILE_NON_DIRECTORY_FILE
, /* create_options */
7345 mod_unixmode
, /* file_attributes */
7346 oplock_request
, /* oplock_request */
7347 0, /* allocation_size */
7348 0, /* private_flags */
7354 if (!NT_STATUS_IS_OK(status
)) {
7358 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7359 extended_oplock_granted
= True
;
7362 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7363 extended_oplock_granted
= True
;
7366 info_level_return
= SVAL(pdata
,16);
7368 /* Allocate the correct return size. */
7370 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7371 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7372 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7373 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7375 *pdata_return_size
= 12;
7378 /* Realloc the data size */
7379 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7380 if (*ppdata
== NULL
) {
7381 close_file(req
, fsp
, ERROR_CLOSE
);
7382 *pdata_return_size
= 0;
7383 return NT_STATUS_NO_MEMORY
;
7387 if (extended_oplock_granted
) {
7388 if (flags
& REQUEST_BATCH_OPLOCK
) {
7389 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7391 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7393 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7394 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7396 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7399 SSVAL(pdata
,2,fsp
->fnum
);
7400 SIVAL(pdata
,4,info
); /* Was file created etc. */
7402 switch (info_level_return
) {
7403 case SMB_QUERY_FILE_UNIX_BASIC
:
7404 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7405 SSVAL(pdata
,10,0); /* padding. */
7406 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7409 case SMB_QUERY_FILE_UNIX_INFO2
:
7410 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7411 SSVAL(pdata
,10,0); /* padding. */
7412 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7416 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7417 SSVAL(pdata
,10,0); /* padding. */
7420 return NT_STATUS_OK
;
7423 /****************************************************************************
7424 Delete a file with POSIX semantics.
7425 ****************************************************************************/
7427 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7428 struct smb_request
*req
,
7431 struct smb_filename
*smb_fname
)
7433 NTSTATUS status
= NT_STATUS_OK
;
7434 files_struct
*fsp
= NULL
;
7438 int create_options
= 0;
7440 struct share_mode_lock
*lck
= NULL
;
7442 if (total_data
< 2) {
7443 return NT_STATUS_INVALID_PARAMETER
;
7446 flags
= SVAL(pdata
,0);
7448 if (!VALID_STAT(smb_fname
->st
)) {
7449 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7452 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7453 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7454 return NT_STATUS_NOT_A_DIRECTORY
;
7457 DEBUG(10,("smb_posix_unlink: %s %s\n",
7458 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7459 smb_fname_str_dbg(smb_fname
)));
7461 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7462 create_options
|= FILE_DIRECTORY_FILE
;
7465 status
= SMB_VFS_CREATE_FILE(
7468 0, /* root_dir_fid */
7469 smb_fname
, /* fname */
7470 DELETE_ACCESS
, /* access_mask */
7471 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7473 FILE_OPEN
, /* create_disposition*/
7474 create_options
, /* create_options */
7475 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7476 0, /* oplock_request */
7477 0, /* allocation_size */
7478 0, /* private_flags */
7484 if (!NT_STATUS_IS_OK(status
)) {
7489 * Don't lie to client. If we can't really delete due to
7490 * non-POSIX opens return SHARING_VIOLATION.
7493 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7496 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7497 "lock for file %s\n", fsp_str_dbg(fsp
)));
7498 close_file(req
, fsp
, NORMAL_CLOSE
);
7499 return NT_STATUS_INVALID_PARAMETER
;
7503 * See if others still have the file open. If this is the case, then
7504 * don't delete. If all opens are POSIX delete we can set the delete
7505 * on close disposition.
7507 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7508 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7509 if (is_valid_share_mode_entry(e
)) {
7510 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7513 /* Fail with sharing violation. */
7514 close_file(req
, fsp
, NORMAL_CLOSE
);
7516 return NT_STATUS_SHARING_VIOLATION
;
7521 * Set the delete on close.
7523 status
= smb_set_file_disposition_info(conn
,
7529 if (!NT_STATUS_IS_OK(status
)) {
7530 close_file(req
, fsp
, NORMAL_CLOSE
);
7535 return close_file(req
, fsp
, NORMAL_CLOSE
);
7538 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7539 struct smb_request
*req
,
7540 TALLOC_CTX
*mem_ctx
,
7541 uint16_t info_level
,
7543 struct smb_filename
*smb_fname
,
7544 char **ppdata
, int total_data
,
7547 char *pdata
= *ppdata
;
7548 NTSTATUS status
= NT_STATUS_OK
;
7549 int data_return_size
= 0;
7553 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7554 return NT_STATUS_INVALID_LEVEL
;
7557 if (!CAN_WRITE(conn
)) {
7558 /* Allow POSIX opens. The open path will deny
7559 * any non-readonly opens. */
7560 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7561 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7565 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7566 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7567 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7569 switch (info_level
) {
7571 case SMB_INFO_STANDARD
:
7573 status
= smb_set_info_standard(conn
,
7581 case SMB_INFO_SET_EA
:
7583 status
= smb_info_set_ea(conn
,
7591 case SMB_SET_FILE_BASIC_INFO
:
7592 case SMB_FILE_BASIC_INFORMATION
:
7594 status
= smb_set_file_basic_info(conn
,
7602 case SMB_FILE_ALLOCATION_INFORMATION
:
7603 case SMB_SET_FILE_ALLOCATION_INFO
:
7605 status
= smb_set_file_allocation_info(conn
, req
,
7613 case SMB_FILE_END_OF_FILE_INFORMATION
:
7614 case SMB_SET_FILE_END_OF_FILE_INFO
:
7617 * XP/Win7 both fail after the createfile with
7618 * SMB_SET_FILE_END_OF_FILE_INFO but not
7619 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7620 * The level is known here, so pass it down
7624 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7626 status
= smb_set_file_end_of_file_info(conn
, req
,
7635 case SMB_FILE_DISPOSITION_INFORMATION
:
7636 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7639 /* JRA - We used to just ignore this on a path ?
7640 * Shouldn't this be invalid level on a pathname
7643 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7644 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7647 status
= smb_set_file_disposition_info(conn
,
7655 case SMB_FILE_POSITION_INFORMATION
:
7657 status
= smb_file_position_information(conn
,
7664 case SMB_FILE_FULL_EA_INFORMATION
:
7666 status
= smb_set_file_full_ea_info(conn
,
7673 /* From tridge Samba4 :
7674 * MODE_INFORMATION in setfileinfo (I have no
7675 * idea what "mode information" on a file is - it takes a value of 0,
7676 * 2, 4 or 6. What could it be?).
7679 case SMB_FILE_MODE_INFORMATION
:
7681 status
= smb_file_mode_information(conn
,
7688 * CIFS UNIX extensions.
7691 case SMB_SET_FILE_UNIX_BASIC
:
7693 status
= smb_set_file_unix_basic(conn
, req
,
7701 case SMB_SET_FILE_UNIX_INFO2
:
7703 status
= smb_set_file_unix_info2(conn
, req
,
7711 case SMB_SET_FILE_UNIX_LINK
:
7714 /* We must have a pathname for this. */
7715 return NT_STATUS_INVALID_LEVEL
;
7717 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7718 total_data
, smb_fname
);
7722 case SMB_SET_FILE_UNIX_HLINK
:
7725 /* We must have a pathname for this. */
7726 return NT_STATUS_INVALID_LEVEL
;
7728 status
= smb_set_file_unix_hlink(conn
, req
,
7734 case SMB_FILE_RENAME_INFORMATION
:
7736 status
= smb_file_rename_information(conn
, req
,
7742 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7744 /* SMB2 rename information. */
7745 status
= smb2_file_rename_information(conn
, req
,
7751 case SMB_FILE_LINK_INFORMATION
:
7753 status
= smb_file_link_information(conn
, req
,
7759 #if defined(HAVE_POSIX_ACLS)
7760 case SMB_SET_POSIX_ACL
:
7762 status
= smb_set_posix_acl(conn
,
7771 case SMB_SET_POSIX_LOCK
:
7774 return NT_STATUS_INVALID_LEVEL
;
7776 status
= smb_set_posix_lock(conn
, req
,
7777 pdata
, total_data
, fsp
);
7781 case SMB_POSIX_PATH_OPEN
:
7784 /* We must have a pathname for this. */
7785 return NT_STATUS_INVALID_LEVEL
;
7788 status
= smb_posix_open(conn
, req
,
7796 case SMB_POSIX_PATH_UNLINK
:
7799 /* We must have a pathname for this. */
7800 return NT_STATUS_INVALID_LEVEL
;
7803 status
= smb_posix_unlink(conn
, req
,
7811 return NT_STATUS_INVALID_LEVEL
;
7814 if (!NT_STATUS_IS_OK(status
)) {
7818 *ret_data_size
= data_return_size
;
7819 return NT_STATUS_OK
;
7822 /****************************************************************************
7823 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7824 ****************************************************************************/
7826 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7827 struct smb_request
*req
,
7828 unsigned int tran_call
,
7829 char **pparams
, int total_params
,
7830 char **ppdata
, int total_data
,
7831 unsigned int max_data_bytes
)
7833 char *params
= *pparams
;
7834 char *pdata
= *ppdata
;
7836 struct smb_filename
*smb_fname
= NULL
;
7837 files_struct
*fsp
= NULL
;
7838 NTSTATUS status
= NT_STATUS_OK
;
7839 int data_return_size
= 0;
7842 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7846 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7847 if (total_params
< 4) {
7848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7852 fsp
= file_fsp(req
, SVAL(params
,0));
7853 /* Basic check for non-null fsp. */
7854 if (!check_fsp_open(conn
, req
, fsp
)) {
7857 info_level
= SVAL(params
,2);
7859 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7861 if (!NT_STATUS_IS_OK(status
)) {
7862 reply_nterror(req
, status
);
7866 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7868 * This is actually a SETFILEINFO on a directory
7869 * handle (returned from an NT SMB). NT5.0 seems
7870 * to do this call. JRA.
7872 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7873 /* Always do lstat for UNIX calls. */
7874 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7875 DEBUG(3,("call_trans2setfilepathinfo: "
7876 "SMB_VFS_LSTAT of %s failed "
7878 smb_fname_str_dbg(smb_fname
),
7880 reply_nterror(req
, map_nt_error_from_unix(errno
));
7884 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7885 DEBUG(3,("call_trans2setfilepathinfo: "
7886 "fileinfo of %s failed (%s)\n",
7887 smb_fname_str_dbg(smb_fname
),
7889 reply_nterror(req
, map_nt_error_from_unix(errno
));
7893 } else if (fsp
->print_file
) {
7895 * Doing a DELETE_ON_CLOSE should cancel a print job.
7897 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7898 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7900 DEBUG(3,("call_trans2setfilepathinfo: "
7901 "Cancelling print job (%s)\n",
7905 send_trans2_replies(conn
, req
, params
, 2,
7911 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7916 * Original code - this is an open file.
7918 if (!check_fsp(conn
, req
, fsp
)) {
7922 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7923 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7924 "of fnum %d failed (%s)\n", fsp
->fnum
,
7926 reply_nterror(req
, map_nt_error_from_unix(errno
));
7934 if (total_params
< 7) {
7935 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7939 info_level
= SVAL(params
,0);
7940 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7941 total_params
- 6, STR_TERMINATE
,
7943 if (!NT_STATUS_IS_OK(status
)) {
7944 reply_nterror(req
, status
);
7948 status
= filename_convert(req
, conn
,
7949 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7954 if (!NT_STATUS_IS_OK(status
)) {
7955 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7956 reply_botherror(req
,
7957 NT_STATUS_PATH_NOT_COVERED
,
7958 ERRSRV
, ERRbadpath
);
7961 reply_nterror(req
, status
);
7965 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7967 * For CIFS UNIX extensions the target name may not exist.
7970 /* Always do lstat for UNIX calls. */
7971 SMB_VFS_LSTAT(conn
, smb_fname
);
7973 } else if (!VALID_STAT(smb_fname
->st
) &&
7974 SMB_VFS_STAT(conn
, smb_fname
)) {
7975 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7977 smb_fname_str_dbg(smb_fname
),
7979 reply_nterror(req
, map_nt_error_from_unix(errno
));
7984 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7985 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7986 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7988 /* Realloc the parameter size */
7989 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7990 if (*pparams
== NULL
) {
7991 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7998 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8004 if (!NT_STATUS_IS_OK(status
)) {
8005 if (open_was_deferred(req
->mid
)) {
8006 /* We have re-scheduled this call. */
8009 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8010 /* We have re-scheduled this call. */
8013 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8014 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8015 ERRSRV
, ERRbadpath
);
8018 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8019 reply_openerror(req
, status
);
8023 reply_nterror(req
, status
);
8027 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8033 /****************************************************************************
8034 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8035 ****************************************************************************/
8037 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8038 char **pparams
, int total_params
,
8039 char **ppdata
, int total_data
,
8040 unsigned int max_data_bytes
)
8042 struct smb_filename
*smb_dname
= NULL
;
8043 char *params
= *pparams
;
8044 char *pdata
= *ppdata
;
8045 char *directory
= NULL
;
8046 NTSTATUS status
= NT_STATUS_OK
;
8047 struct ea_list
*ea_list
= NULL
;
8048 TALLOC_CTX
*ctx
= talloc_tos();
8050 if (!CAN_WRITE(conn
)) {
8051 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8055 if (total_params
< 5) {
8056 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8060 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8061 total_params
- 4, STR_TERMINATE
,
8063 if (!NT_STATUS_IS_OK(status
)) {
8064 reply_nterror(req
, status
);
8068 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8070 status
= filename_convert(ctx
,
8072 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8078 if (!NT_STATUS_IS_OK(status
)) {
8079 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8080 reply_botherror(req
,
8081 NT_STATUS_PATH_NOT_COVERED
,
8082 ERRSRV
, ERRbadpath
);
8085 reply_nterror(req
, status
);
8090 * OS/2 workplace shell seems to send SET_EA requests of "null"
8091 * length (4 bytes containing IVAL 4).
8092 * They seem to have no effect. Bug #3212. JRA.
8095 if (total_data
&& (total_data
!= 4)) {
8096 /* Any data in this call is an EA list. */
8097 if (total_data
< 10) {
8098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8102 if (IVAL(pdata
,0) > total_data
) {
8103 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8104 IVAL(pdata
,0), (unsigned int)total_data
));
8105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8109 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8116 if (!lp_ea_support(SNUM(conn
))) {
8117 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8121 /* If total_data == 4 Windows doesn't care what values
8122 * are placed in that field, it just ignores them.
8123 * The System i QNTC IBM SMB client puts bad values here,
8124 * so ignore them. */
8126 status
= create_directory(conn
, req
, smb_dname
);
8128 if (!NT_STATUS_IS_OK(status
)) {
8129 reply_nterror(req
, status
);
8133 /* Try and set any given EA. */
8135 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8136 if (!NT_STATUS_IS_OK(status
)) {
8137 reply_nterror(req
, status
);
8142 /* Realloc the parameter and data sizes */
8143 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8144 if(*pparams
== NULL
) {
8145 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8152 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8155 TALLOC_FREE(smb_dname
);
8159 /****************************************************************************
8160 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8161 We don't actually do this - we just send a null response.
8162 ****************************************************************************/
8164 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8165 struct smb_request
*req
,
8166 char **pparams
, int total_params
,
8167 char **ppdata
, int total_data
,
8168 unsigned int max_data_bytes
)
8170 char *params
= *pparams
;
8173 if (total_params
< 6) {
8174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8178 info_level
= SVAL(params
,4);
8179 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8181 switch (info_level
) {
8186 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8190 /* Realloc the parameter and data sizes */
8191 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8192 if (*pparams
== NULL
) {
8193 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8198 SSVAL(params
,0,fnf_handle
);
8199 SSVAL(params
,2,0); /* No changes */
8200 SSVAL(params
,4,0); /* No EA errors */
8207 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8212 /****************************************************************************
8213 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8214 changes). Currently this does nothing.
8215 ****************************************************************************/
8217 static void call_trans2findnotifynext(connection_struct
*conn
,
8218 struct smb_request
*req
,
8219 char **pparams
, int total_params
,
8220 char **ppdata
, int total_data
,
8221 unsigned int max_data_bytes
)
8223 char *params
= *pparams
;
8225 DEBUG(3,("call_trans2findnotifynext\n"));
8227 /* Realloc the parameter and data sizes */
8228 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8229 if (*pparams
== NULL
) {
8230 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8235 SSVAL(params
,0,0); /* No changes */
8236 SSVAL(params
,2,0); /* No EA errors */
8238 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8243 /****************************************************************************
8244 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8245 ****************************************************************************/
8247 static void call_trans2getdfsreferral(connection_struct
*conn
,
8248 struct smb_request
*req
,
8249 char **pparams
, int total_params
,
8250 char **ppdata
, int total_data
,
8251 unsigned int max_data_bytes
)
8253 char *params
= *pparams
;
8254 char *pathname
= NULL
;
8256 int max_referral_level
;
8257 NTSTATUS status
= NT_STATUS_OK
;
8258 TALLOC_CTX
*ctx
= talloc_tos();
8260 DEBUG(10,("call_trans2getdfsreferral\n"));
8262 if (total_params
< 3) {
8263 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8267 max_referral_level
= SVAL(params
,0);
8269 if(!lp_host_msdfs()) {
8270 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8274 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8275 total_params
- 2, STR_TERMINATE
);
8277 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8280 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8281 ppdata
,&status
)) < 0) {
8282 reply_nterror(req
, status
);
8286 SSVAL(req
->inbuf
, smb_flg2
,
8287 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8288 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8293 #define LMCAT_SPL 0x53
8294 #define LMFUNC_GETJOBID 0x60
8296 /****************************************************************************
8297 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8298 ****************************************************************************/
8300 static void call_trans2ioctl(connection_struct
*conn
,
8301 struct smb_request
*req
,
8302 char **pparams
, int total_params
,
8303 char **ppdata
, int total_data
,
8304 unsigned int max_data_bytes
)
8306 char *pdata
= *ppdata
;
8307 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8309 /* check for an invalid fid before proceeding */
8312 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8316 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8317 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8318 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8319 if (*ppdata
== NULL
) {
8320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8325 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8326 CAN ACCEPT THIS IN UNICODE. JRA. */
8329 if (fsp
->print_file
) {
8330 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8334 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8335 global_myname(), 15,
8336 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8337 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8338 lp_servicename(SNUM(conn
)), 13,
8339 STR_ASCII
|STR_TERMINATE
); /* Service name */
8340 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8345 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8346 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8349 /****************************************************************************
8350 Reply to a SMBfindclose (stop trans2 directory search).
8351 ****************************************************************************/
8353 void reply_findclose(struct smb_request
*req
)
8356 struct smbd_server_connection
*sconn
= req
->sconn
;
8358 START_PROFILE(SMBfindclose
);
8361 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8362 END_PROFILE(SMBfindclose
);
8366 dptr_num
= SVALS(req
->vwv
+0, 0);
8368 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8370 dptr_close(sconn
, &dptr_num
);
8372 reply_outbuf(req
, 0, 0);
8374 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8376 END_PROFILE(SMBfindclose
);
8380 /****************************************************************************
8381 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8382 ****************************************************************************/
8384 void reply_findnclose(struct smb_request
*req
)
8388 START_PROFILE(SMBfindnclose
);
8391 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8392 END_PROFILE(SMBfindnclose
);
8396 dptr_num
= SVAL(req
->vwv
+0, 0);
8398 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8400 /* We never give out valid handles for a
8401 findnotifyfirst - so any dptr_num is ok here.
8404 reply_outbuf(req
, 0, 0);
8406 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8408 END_PROFILE(SMBfindnclose
);
8412 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8413 struct trans_state
*state
)
8415 if (get_Protocol() >= PROTOCOL_NT1
) {
8416 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8417 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8420 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8421 if (state
->call
!= TRANSACT2_QFSINFO
&&
8422 state
->call
!= TRANSACT2_SETFSINFO
) {
8423 DEBUG(0,("handle_trans2: encryption required "
8425 (unsigned int)state
->call
));
8426 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8431 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8433 /* Now we must call the relevant TRANS2 function */
8434 switch(state
->call
) {
8435 case TRANSACT2_OPEN
:
8437 START_PROFILE(Trans2_open
);
8438 call_trans2open(conn
, req
,
8439 &state
->param
, state
->total_param
,
8440 &state
->data
, state
->total_data
,
8441 state
->max_data_return
);
8442 END_PROFILE(Trans2_open
);
8446 case TRANSACT2_FINDFIRST
:
8448 START_PROFILE(Trans2_findfirst
);
8449 call_trans2findfirst(conn
, req
,
8450 &state
->param
, state
->total_param
,
8451 &state
->data
, state
->total_data
,
8452 state
->max_data_return
);
8453 END_PROFILE(Trans2_findfirst
);
8457 case TRANSACT2_FINDNEXT
:
8459 START_PROFILE(Trans2_findnext
);
8460 call_trans2findnext(conn
, req
,
8461 &state
->param
, state
->total_param
,
8462 &state
->data
, state
->total_data
,
8463 state
->max_data_return
);
8464 END_PROFILE(Trans2_findnext
);
8468 case TRANSACT2_QFSINFO
:
8470 START_PROFILE(Trans2_qfsinfo
);
8471 call_trans2qfsinfo(conn
, req
,
8472 &state
->param
, state
->total_param
,
8473 &state
->data
, state
->total_data
,
8474 state
->max_data_return
);
8475 END_PROFILE(Trans2_qfsinfo
);
8479 case TRANSACT2_SETFSINFO
:
8481 START_PROFILE(Trans2_setfsinfo
);
8482 call_trans2setfsinfo(conn
, req
,
8483 &state
->param
, state
->total_param
,
8484 &state
->data
, state
->total_data
,
8485 state
->max_data_return
);
8486 END_PROFILE(Trans2_setfsinfo
);
8490 case TRANSACT2_QPATHINFO
:
8491 case TRANSACT2_QFILEINFO
:
8493 START_PROFILE(Trans2_qpathinfo
);
8494 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8495 &state
->param
, state
->total_param
,
8496 &state
->data
, state
->total_data
,
8497 state
->max_data_return
);
8498 END_PROFILE(Trans2_qpathinfo
);
8502 case TRANSACT2_SETPATHINFO
:
8503 case TRANSACT2_SETFILEINFO
:
8505 START_PROFILE(Trans2_setpathinfo
);
8506 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8507 &state
->param
, state
->total_param
,
8508 &state
->data
, state
->total_data
,
8509 state
->max_data_return
);
8510 END_PROFILE(Trans2_setpathinfo
);
8514 case TRANSACT2_FINDNOTIFYFIRST
:
8516 START_PROFILE(Trans2_findnotifyfirst
);
8517 call_trans2findnotifyfirst(conn
, req
,
8518 &state
->param
, state
->total_param
,
8519 &state
->data
, state
->total_data
,
8520 state
->max_data_return
);
8521 END_PROFILE(Trans2_findnotifyfirst
);
8525 case TRANSACT2_FINDNOTIFYNEXT
:
8527 START_PROFILE(Trans2_findnotifynext
);
8528 call_trans2findnotifynext(conn
, req
,
8529 &state
->param
, state
->total_param
,
8530 &state
->data
, state
->total_data
,
8531 state
->max_data_return
);
8532 END_PROFILE(Trans2_findnotifynext
);
8536 case TRANSACT2_MKDIR
:
8538 START_PROFILE(Trans2_mkdir
);
8539 call_trans2mkdir(conn
, req
,
8540 &state
->param
, state
->total_param
,
8541 &state
->data
, state
->total_data
,
8542 state
->max_data_return
);
8543 END_PROFILE(Trans2_mkdir
);
8547 case TRANSACT2_GET_DFS_REFERRAL
:
8549 START_PROFILE(Trans2_get_dfs_referral
);
8550 call_trans2getdfsreferral(conn
, req
,
8551 &state
->param
, state
->total_param
,
8552 &state
->data
, state
->total_data
,
8553 state
->max_data_return
);
8554 END_PROFILE(Trans2_get_dfs_referral
);
8558 case TRANSACT2_IOCTL
:
8560 START_PROFILE(Trans2_ioctl
);
8561 call_trans2ioctl(conn
, req
,
8562 &state
->param
, state
->total_param
,
8563 &state
->data
, state
->total_data
,
8564 state
->max_data_return
);
8565 END_PROFILE(Trans2_ioctl
);
8570 /* Error in request */
8571 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8572 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8576 /****************************************************************************
8577 Reply to a SMBtrans2.
8578 ****************************************************************************/
8580 void reply_trans2(struct smb_request
*req
)
8582 connection_struct
*conn
= req
->conn
;
8587 unsigned int tran_call
;
8588 struct trans_state
*state
;
8591 START_PROFILE(SMBtrans2
);
8593 if (req
->wct
< 14) {
8594 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8595 END_PROFILE(SMBtrans2
);
8599 dsoff
= SVAL(req
->vwv
+12, 0);
8600 dscnt
= SVAL(req
->vwv
+11, 0);
8601 psoff
= SVAL(req
->vwv
+10, 0);
8602 pscnt
= SVAL(req
->vwv
+9, 0);
8603 tran_call
= SVAL(req
->vwv
+14, 0);
8605 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8606 if (!NT_STATUS_IS_OK(result
)) {
8607 DEBUG(2, ("Got invalid trans2 request: %s\n",
8608 nt_errstr(result
)));
8609 reply_nterror(req
, result
);
8610 END_PROFILE(SMBtrans2
);
8615 switch (tran_call
) {
8616 /* List the allowed trans2 calls on IPC$ */
8617 case TRANSACT2_OPEN
:
8618 case TRANSACT2_GET_DFS_REFERRAL
:
8619 case TRANSACT2_QFILEINFO
:
8620 case TRANSACT2_QFSINFO
:
8621 case TRANSACT2_SETFSINFO
:
8624 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8625 END_PROFILE(SMBtrans2
);
8630 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8631 DEBUG(0, ("talloc failed\n"));
8632 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8633 END_PROFILE(SMBtrans2
);
8637 state
->cmd
= SMBtrans2
;
8639 state
->mid
= req
->mid
;
8640 state
->vuid
= req
->vuid
;
8641 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8642 state
->setup
= NULL
;
8643 state
->total_param
= SVAL(req
->vwv
+0, 0);
8644 state
->param
= NULL
;
8645 state
->total_data
= SVAL(req
->vwv
+1, 0);
8647 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8648 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8649 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8650 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8651 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8653 state
->call
= tran_call
;
8655 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8656 is so as a sanity check */
8657 if (state
->setup_count
!= 1) {
8659 * Need to have rc=0 for ioctl to get job id for OS/2.
8660 * Network printing will fail if function is not successful.
8661 * Similar function in reply.c will be used if protocol
8662 * is LANMAN1.0 instead of LM1.2X002.
8663 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8664 * outbuf doesn't have to be set(only job id is used).
8666 if ( (state
->setup_count
== 4)
8667 && (tran_call
== TRANSACT2_IOCTL
)
8668 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8669 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8670 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8672 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8673 DEBUG(2,("Transaction is %d\n",tran_call
));
8675 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8676 END_PROFILE(SMBtrans2
);
8681 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8684 if (state
->total_data
) {
8686 if (trans_oob(state
->total_data
, 0, dscnt
)
8687 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8691 /* Can't use talloc here, the core routines do realloc on the
8692 * params and data. */
8693 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8694 if (state
->data
== NULL
) {
8695 DEBUG(0,("reply_trans2: data malloc fail for %u "
8696 "bytes !\n", (unsigned int)state
->total_data
));
8698 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8699 END_PROFILE(SMBtrans2
);
8703 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8706 if (state
->total_param
) {
8708 if (trans_oob(state
->total_param
, 0, pscnt
)
8709 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8713 /* Can't use talloc here, the core routines do realloc on the
8714 * params and data. */
8715 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8716 if (state
->param
== NULL
) {
8717 DEBUG(0,("reply_trans: param malloc fail for %u "
8718 "bytes !\n", (unsigned int)state
->total_param
));
8719 SAFE_FREE(state
->data
);
8721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8722 END_PROFILE(SMBtrans2
);
8726 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8729 state
->received_data
= dscnt
;
8730 state
->received_param
= pscnt
;
8732 if ((state
->received_param
== state
->total_param
) &&
8733 (state
->received_data
== state
->total_data
)) {
8735 handle_trans2(conn
, req
, state
);
8737 SAFE_FREE(state
->data
);
8738 SAFE_FREE(state
->param
);
8740 END_PROFILE(SMBtrans2
);
8744 DLIST_ADD(conn
->pending_trans
, state
);
8746 /* We need to send an interim response then receive the rest
8747 of the parameter/data bytes */
8748 reply_outbuf(req
, 0, 0);
8749 show_msg((char *)req
->outbuf
);
8750 END_PROFILE(SMBtrans2
);
8755 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8756 SAFE_FREE(state
->data
);
8757 SAFE_FREE(state
->param
);
8759 END_PROFILE(SMBtrans2
);
8760 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8764 /****************************************************************************
8765 Reply to a SMBtranss2
8766 ****************************************************************************/
8768 void reply_transs2(struct smb_request
*req
)
8770 connection_struct
*conn
= req
->conn
;
8771 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8772 struct trans_state
*state
;
8774 START_PROFILE(SMBtranss2
);
8776 show_msg((char *)req
->inbuf
);
8779 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8780 END_PROFILE(SMBtranss2
);
8784 for (state
= conn
->pending_trans
; state
!= NULL
;
8785 state
= state
->next
) {
8786 if (state
->mid
== req
->mid
) {
8791 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8792 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8793 END_PROFILE(SMBtranss2
);
8797 /* Revise state->total_param and state->total_data in case they have
8798 changed downwards */
8800 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8801 state
->total_param
= SVAL(req
->vwv
+0, 0);
8802 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8803 state
->total_data
= SVAL(req
->vwv
+1, 0);
8805 pcnt
= SVAL(req
->vwv
+2, 0);
8806 poff
= SVAL(req
->vwv
+3, 0);
8807 pdisp
= SVAL(req
->vwv
+4, 0);
8809 dcnt
= SVAL(req
->vwv
+5, 0);
8810 doff
= SVAL(req
->vwv
+6, 0);
8811 ddisp
= SVAL(req
->vwv
+7, 0);
8813 state
->received_param
+= pcnt
;
8814 state
->received_data
+= dcnt
;
8816 if ((state
->received_data
> state
->total_data
) ||
8817 (state
->received_param
> state
->total_param
))
8821 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8822 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8825 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8829 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8830 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8833 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8836 if ((state
->received_param
< state
->total_param
) ||
8837 (state
->received_data
< state
->total_data
)) {
8838 END_PROFILE(SMBtranss2
);
8842 handle_trans2(conn
, req
, state
);
8844 DLIST_REMOVE(conn
->pending_trans
, state
);
8845 SAFE_FREE(state
->data
);
8846 SAFE_FREE(state
->param
);
8849 END_PROFILE(SMBtranss2
);
8854 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8855 DLIST_REMOVE(conn
->pending_trans
, state
);
8856 SAFE_FREE(state
->data
);
8857 SAFE_FREE(state
->param
);
8859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8860 END_PROFILE(SMBtranss2
);