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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
39 #include "libsmb/libsmb.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct
*conn
,
46 const SMB_STRUCT_STAT
*psbuf
);
48 static char *store_file_unix_basic_info2(connection_struct
*conn
,
51 const SMB_STRUCT_STAT
*psbuf
);
53 /********************************************************************
54 Roundup a value to the nearest allocation roundup size boundary.
55 Only do this for Windows clients.
56 ********************************************************************/
58 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
60 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
62 /* Only roundup for Windows clients. */
63 enum remote_arch_types ra_type
= get_remote_arch();
64 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
65 val
= SMB_ROUNDUP(val
,rval
);
70 /********************************************************************
71 Create a 64 bit FileIndex. If the file is on the same device as
72 the root of the share, just return the 64-bit inode. If it isn't,
73 mangle as we used to do.
74 ********************************************************************/
76 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
79 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
80 return (uint64_t)psbuf
->st_ex_ino
;
82 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
83 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name
)
97 static const char * const prohibited_ea_names
[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME
,
99 SAMBA_XATTR_DOS_ATTRIB
,
107 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
108 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
111 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
112 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
118 /****************************************************************************
119 Get one EA value. Fill in a struct ea_struct.
120 ****************************************************************************/
122 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
123 files_struct
*fsp
, const char *fname
,
124 const char *ea_name
, struct ea_struct
*pea
)
126 /* Get the value of this xattr. Max size is 64k. */
127 size_t attr_size
= 256;
133 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
135 return NT_STATUS_NO_MEMORY
;
138 if (fsp
&& fsp
->fh
->fd
!= -1) {
139 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
141 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
144 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
150 return map_nt_error_from_unix(errno
);
153 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
154 dump_data(10, (uint8
*)val
, sizeret
);
157 if (strnequal(ea_name
, "user.", 5)) {
158 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
160 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
162 if (pea
->name
== NULL
) {
164 return NT_STATUS_NO_MEMORY
;
166 pea
->value
.data
= (unsigned char *)val
;
167 pea
->value
.length
= (size_t)sizeret
;
171 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
172 files_struct
*fsp
, const char *fname
,
173 char ***pnames
, size_t *pnum_names
)
175 /* Get a list of all xattrs. Max namesize is 64k. */
176 size_t ea_namelist_size
= 1024;
177 char *ea_namelist
= NULL
;
182 ssize_t sizeret
= -1;
184 if (!lp_ea_support(SNUM(conn
))) {
193 * TALLOC the result early to get the talloc hierarchy right.
196 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
198 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY
;
202 while (ea_namelist_size
<= 65536) {
204 ea_namelist
= TALLOC_REALLOC_ARRAY(
205 names
, ea_namelist
, char, ea_namelist_size
);
206 if (ea_namelist
== NULL
) {
207 DEBUG(0, ("talloc failed\n"));
209 return NT_STATUS_NO_MEMORY
;
212 if (fsp
&& fsp
->fh
->fd
!= -1) {
213 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
216 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
220 if ((sizeret
== -1) && (errno
== ERANGE
)) {
221 ea_namelist_size
*= 2;
230 return map_nt_error_from_unix(errno
);
233 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
234 (unsigned int)sizeret
));
246 * Ensure the result is 0-terminated
249 if (ea_namelist
[sizeret
-1] != '\0') {
251 return NT_STATUS_INTERNAL_ERROR
;
259 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
263 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
265 DEBUG(0, ("talloc failed\n"));
267 return NT_STATUS_NO_MEMORY
;
273 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
274 names
[num_names
++] = p
;
282 *pnum_names
= num_names
;
286 /****************************************************************************
287 Return a linked list of the total EA's. Plus the total size
288 ****************************************************************************/
290 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
291 const char *fname
, size_t *pea_total_len
)
293 /* Get a list of all xattrs. Max namesize is 64k. */
296 struct ea_list
*ea_list_head
= NULL
;
301 if (!lp_ea_support(SNUM(conn
))) {
305 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
308 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
312 for (i
=0; i
<num_names
; i
++) {
313 struct ea_list
*listp
;
316 if (strnequal(names
[i
], "system.", 7)
317 || samba_private_attr_name(names
[i
]))
320 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
325 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
331 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
334 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
336 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
337 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
338 (unsigned int)listp
->ea
.value
.length
));
340 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
344 /* Add on 4 for total length. */
345 if (*pea_total_len
) {
349 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
350 (unsigned int)*pea_total_len
));
355 /****************************************************************************
356 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
358 ****************************************************************************/
360 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
361 connection_struct
*conn
, struct ea_list
*ea_list
)
363 unsigned int ret_data_size
= 4;
366 SMB_ASSERT(total_data_size
>= 4);
368 if (!lp_ea_support(SNUM(conn
))) {
373 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
376 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
377 dos_namelen
= strlen(dos_ea_name
);
378 if (dos_namelen
> 255 || dos_namelen
== 0) {
381 if (ea_list
->ea
.value
.length
> 65535) {
384 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
388 /* We know we have room. */
389 SCVAL(p
,0,ea_list
->ea
.flags
);
390 SCVAL(p
,1,dos_namelen
);
391 SSVAL(p
,2,ea_list
->ea
.value
.length
);
392 fstrcpy(p
+4, dos_ea_name
);
393 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
395 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
396 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
399 ret_data_size
= PTR_DIFF(p
, pdata
);
400 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
401 SIVAL(pdata
,0,ret_data_size
);
402 return ret_data_size
;
405 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
407 unsigned int total_data_size
,
408 unsigned int *ret_data_size
,
409 connection_struct
*conn
,
410 struct ea_list
*ea_list
)
412 uint8_t *p
= (uint8_t *)pdata
;
413 uint8_t *last_start
= NULL
;
417 if (!lp_ea_support(SNUM(conn
))) {
418 return NT_STATUS_NO_EAS_ON_FILE
;
421 for (; ea_list
; ea_list
= ea_list
->next
) {
427 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
431 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
432 dos_namelen
= strlen(dos_ea_name
);
433 if (dos_namelen
> 255 || dos_namelen
== 0) {
434 return NT_STATUS_INTERNAL_ERROR
;
436 if (ea_list
->ea
.value
.length
> 65535) {
437 return NT_STATUS_INTERNAL_ERROR
;
440 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
443 size_t pad
= 4 - (this_size
% 4);
447 if (this_size
> total_data_size
) {
448 return NT_STATUS_INFO_LENGTH_MISMATCH
;
451 /* We know we have room. */
452 SIVAL(p
, 0x00, 0); /* next offset */
453 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
454 SCVAL(p
, 0x05, dos_namelen
);
455 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
456 fstrcpy((char *)(p
+0x08), dos_ea_name
);
457 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
459 total_data_size
-= this_size
;
463 *ret_data_size
= PTR_DIFF(p
, pdata
);
464 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
468 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
470 size_t total_ea_len
= 0;
471 TALLOC_CTX
*mem_ctx
= NULL
;
473 if (!lp_ea_support(SNUM(conn
))) {
476 mem_ctx
= talloc_tos();
477 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
481 /****************************************************************************
482 Ensure the EA name is case insensitive by matching any existing EA name.
483 ****************************************************************************/
485 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
488 TALLOC_CTX
*mem_ctx
= talloc_tos();
489 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
491 for (; ea_list
; ea_list
= ea_list
->next
) {
492 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
493 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
494 &unix_ea_name
[5], ea_list
->ea
.name
));
495 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
501 /****************************************************************************
502 Set or delete an extended attribute.
503 ****************************************************************************/
505 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
506 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
510 if (!lp_ea_support(SNUM(conn
))) {
511 return NT_STATUS_EAS_NOT_SUPPORTED
;
514 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
515 return NT_STATUS_ACCESS_DENIED
;
518 /* For now setting EAs on streams isn't supported. */
519 fname
= smb_fname
->base_name
;
521 for (;ea_list
; ea_list
= ea_list
->next
) {
523 fstring unix_ea_name
;
525 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
526 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
528 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
530 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
532 if (samba_private_attr_name(unix_ea_name
)) {
533 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
534 return NT_STATUS_ACCESS_DENIED
;
537 if (ea_list
->ea
.value
.length
== 0) {
538 /* Remove the attribute. */
539 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
540 DEBUG(10,("set_ea: deleting ea name %s on "
541 "file %s by file descriptor.\n",
542 unix_ea_name
, fsp_str_dbg(fsp
)));
543 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
545 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
546 unix_ea_name
, fname
));
547 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
550 /* Removing a non existent attribute always succeeds. */
551 if (ret
== -1 && errno
== ENOATTR
) {
552 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
558 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
559 DEBUG(10,("set_ea: setting ea name %s on file "
560 "%s by file descriptor.\n",
561 unix_ea_name
, fsp_str_dbg(fsp
)));
562 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
563 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
565 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
566 unix_ea_name
, fname
));
567 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
568 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
574 if (errno
== ENOTSUP
) {
575 return NT_STATUS_EAS_NOT_SUPPORTED
;
578 return map_nt_error_from_unix(errno
);
584 /****************************************************************************
585 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
586 ****************************************************************************/
588 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
590 struct ea_list
*ea_list_head
= NULL
;
591 size_t converted_size
, offset
= 0;
593 while (offset
+ 2 < data_size
) {
594 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
595 unsigned int namelen
= CVAL(pdata
,offset
);
597 offset
++; /* Go past the namelen byte. */
599 /* integer wrap paranioa. */
600 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
601 (offset
> data_size
) || (namelen
> data_size
) ||
602 (offset
+ namelen
>= data_size
)) {
605 /* Ensure the name is null terminated. */
606 if (pdata
[offset
+ namelen
] != '\0') {
609 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
611 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
612 "failed: %s", strerror(errno
)));
618 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
619 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
620 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
626 /****************************************************************************
627 Read one EA list entry from the buffer.
628 ****************************************************************************/
630 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
632 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
634 unsigned int namelen
;
635 size_t converted_size
;
645 eal
->ea
.flags
= CVAL(pdata
,0);
646 namelen
= CVAL(pdata
,1);
647 val_len
= SVAL(pdata
,2);
649 if (4 + namelen
+ 1 + val_len
> data_size
) {
653 /* Ensure the name is null terminated. */
654 if (pdata
[namelen
+ 4] != '\0') {
657 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
658 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
665 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
666 if (!eal
->ea
.value
.data
) {
670 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
672 /* Ensure we're null terminated just in case we print the value. */
673 eal
->ea
.value
.data
[val_len
] = '\0';
674 /* But don't count the null. */
675 eal
->ea
.value
.length
--;
678 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
681 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
682 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
687 /****************************************************************************
688 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
689 ****************************************************************************/
691 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
693 struct ea_list
*ea_list_head
= NULL
;
695 size_t bytes_used
= 0;
697 while (offset
< data_size
) {
698 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
704 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
705 offset
+= bytes_used
;
711 /****************************************************************************
712 Count the total EA size needed.
713 ****************************************************************************/
715 static size_t ea_list_size(struct ea_list
*ealist
)
718 struct ea_list
*listp
;
721 for (listp
= ealist
; listp
; listp
= listp
->next
) {
722 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
723 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
725 /* Add on 4 for total length. */
733 /****************************************************************************
734 Return a union of EA's from a file list and a list of names.
735 The TALLOC context for the two lists *MUST* be identical as we steal
736 memory from one list to add to another. JRA.
737 ****************************************************************************/
739 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
741 struct ea_list
*nlistp
, *flistp
;
743 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
744 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
745 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
751 /* Copy the data from this entry. */
752 nlistp
->ea
.flags
= flistp
->ea
.flags
;
753 nlistp
->ea
.value
= flistp
->ea
.value
;
756 nlistp
->ea
.flags
= 0;
757 ZERO_STRUCT(nlistp
->ea
.value
);
761 *total_ea_len
= ea_list_size(name_list
);
765 /****************************************************************************
766 Send the required number of replies back.
767 We assume all fields other than the data fields are
768 set correctly for the type of call.
769 HACK ! Always assumes smb_setup field is zero.
770 ****************************************************************************/
772 void send_trans2_replies(connection_struct
*conn
,
773 struct smb_request
*req
,
780 /* As we are using a protocol > LANMAN1 then the max_send
781 variable must have been set in the sessetupX call.
782 This takes precedence over the max_xmit field in the
783 global struct. These different max_xmit variables should
784 be merged as this is now too confusing */
786 int data_to_send
= datasize
;
787 int params_to_send
= paramsize
;
789 const char *pp
= params
;
790 const char *pd
= pdata
;
791 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
792 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
793 int data_alignment_offset
= 0;
794 bool overflow
= False
;
795 struct smbd_server_connection
*sconn
= req
->sconn
;
796 int max_send
= sconn
->smb1
.sessions
.max_send
;
798 /* Modify the data_to_send and datasize and set the error if
799 we're trying to send more than max_data_bytes. We still send
800 the part of the packet(s) that fit. Strange, but needed
803 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
804 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
805 max_data_bytes
, datasize
));
806 datasize
= data_to_send
= max_data_bytes
;
810 /* If there genuinely are no parameters or data to send just send the empty packet */
812 if(params_to_send
== 0 && data_to_send
== 0) {
813 reply_outbuf(req
, 10, 0);
814 show_msg((char *)req
->outbuf
);
815 if (!srv_send_smb(sconn
,
818 IS_CONN_ENCRYPTED(conn
),
820 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
822 TALLOC_FREE(req
->outbuf
);
826 /* When sending params and data ensure that both are nicely aligned */
827 /* Only do this alignment when there is also data to send - else
828 can cause NT redirector problems. */
830 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
831 data_alignment_offset
= 4 - (params_to_send
% 4);
833 /* Space is bufsize minus Netbios over TCP header minus SMB header */
834 /* The alignment_offset is to align the param bytes on an even byte
835 boundary. NT 4.0 Beta needs this to work correctly. */
837 useable_space
= max_send
- (smb_size
840 + data_alignment_offset
);
842 if (useable_space
< 0) {
843 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
844 "= %d!!!", useable_space
));
845 exit_server_cleanly("send_trans2_replies: Not enough space");
848 while (params_to_send
|| data_to_send
) {
849 /* Calculate whether we will totally or partially fill this packet */
851 total_sent_thistime
= params_to_send
+ data_to_send
;
853 /* We can never send more than useable_space */
855 * Note that 'useable_space' does not include the alignment offsets,
856 * but we must include the alignment offsets in the calculation of
857 * the length of the data we send over the wire, as the alignment offsets
858 * are sent here. Fix from Marc_Jacobsen@hp.com.
861 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
863 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
864 + data_alignment_offset
);
866 /* Set total params and data to be sent */
867 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
868 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
870 /* Calculate how many parameters and data we can fit into
871 * this packet. Parameters get precedence
874 params_sent_thistime
= MIN(params_to_send
,useable_space
);
875 data_sent_thistime
= useable_space
- params_sent_thistime
;
876 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
878 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
880 /* smb_proff is the offset from the start of the SMB header to the
881 parameter bytes, however the first 4 bytes of outbuf are
882 the Netbios over TCP header. Thus use smb_base() to subtract
883 them from the calculation */
885 SSVAL(req
->outbuf
,smb_proff
,
886 ((smb_buf(req
->outbuf
)+alignment_offset
)
887 - smb_base(req
->outbuf
)));
889 if(params_sent_thistime
== 0)
890 SSVAL(req
->outbuf
,smb_prdisp
,0);
892 /* Absolute displacement of param bytes sent in this packet */
893 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
895 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
896 if(data_sent_thistime
== 0) {
897 SSVAL(req
->outbuf
,smb_droff
,0);
898 SSVAL(req
->outbuf
,smb_drdisp
, 0);
900 /* The offset of the data bytes is the offset of the
901 parameter bytes plus the number of parameters being sent this time */
902 SSVAL(req
->outbuf
, smb_droff
,
903 ((smb_buf(req
->outbuf
)+alignment_offset
)
904 - smb_base(req
->outbuf
))
905 + params_sent_thistime
+ data_alignment_offset
);
906 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
909 /* Initialize the padding for alignment */
911 if (alignment_offset
!= 0) {
912 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
915 /* Copy the param bytes into the packet */
917 if(params_sent_thistime
) {
918 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
919 params_sent_thistime
);
922 /* Copy in the data bytes */
923 if(data_sent_thistime
) {
924 if (data_alignment_offset
!= 0) {
925 memset((smb_buf(req
->outbuf
)+alignment_offset
+
926 params_sent_thistime
), 0,
927 data_alignment_offset
);
929 memcpy(smb_buf(req
->outbuf
)+alignment_offset
930 +params_sent_thistime
+data_alignment_offset
,
931 pd
,data_sent_thistime
);
934 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
935 params_sent_thistime
, data_sent_thistime
, useable_space
));
936 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
937 params_to_send
, data_to_send
, paramsize
, datasize
));
940 error_packet_set((char *)req
->outbuf
,
941 ERRDOS
,ERRbufferoverflow
,
942 STATUS_BUFFER_OVERFLOW
,
946 /* Send the packet */
947 show_msg((char *)req
->outbuf
);
948 if (!srv_send_smb(sconn
,
951 IS_CONN_ENCRYPTED(conn
),
953 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
955 TALLOC_FREE(req
->outbuf
);
957 pp
+= params_sent_thistime
;
958 pd
+= data_sent_thistime
;
960 params_to_send
-= params_sent_thistime
;
961 data_to_send
-= data_sent_thistime
;
964 if(params_to_send
< 0 || data_to_send
< 0) {
965 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
966 params_to_send
, data_to_send
));
974 /****************************************************************************
975 Reply to a TRANSACT2_OPEN.
976 ****************************************************************************/
978 static void call_trans2open(connection_struct
*conn
,
979 struct smb_request
*req
,
980 char **pparams
, int total_params
,
981 char **ppdata
, int total_data
,
982 unsigned int max_data_bytes
)
984 struct smb_filename
*smb_fname
= NULL
;
985 char *params
= *pparams
;
986 char *pdata
= *ppdata
;
991 bool return_additional_info
;
1000 int fattr
=0,mtime
=0;
1001 SMB_INO_T inode
= 0;
1004 struct ea_list
*ea_list
= NULL
;
1009 uint32 create_disposition
;
1010 uint32 create_options
= 0;
1011 uint32_t private_flags
= 0;
1012 TALLOC_CTX
*ctx
= talloc_tos();
1015 * Ensure we have enough parameters to perform the operation.
1018 if (total_params
< 29) {
1019 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1023 flags
= SVAL(params
, 0);
1024 deny_mode
= SVAL(params
, 2);
1025 open_attr
= SVAL(params
,6);
1026 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1027 if (oplock_request
) {
1028 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1032 return_additional_info
= BITSETW(params
,0);
1033 open_sattr
= SVAL(params
, 4);
1034 open_time
= make_unix_date3(params
+8);
1036 open_ofun
= SVAL(params
,12);
1037 open_size
= IVAL(params
,14);
1038 pname
= ¶ms
[28];
1041 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1045 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1046 total_params
- 28, STR_TERMINATE
,
1048 if (!NT_STATUS_IS_OK(status
)) {
1049 reply_nterror(req
, status
);
1053 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1054 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1055 (unsigned int)open_ofun
, open_size
));
1057 status
= filename_convert(ctx
,
1059 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1064 if (!NT_STATUS_IS_OK(status
)) {
1065 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1066 reply_botherror(req
,
1067 NT_STATUS_PATH_NOT_COVERED
,
1068 ERRSRV
, ERRbadpath
);
1071 reply_nterror(req
, status
);
1075 if (open_ofun
== 0) {
1076 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1080 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1082 &access_mask
, &share_mode
,
1083 &create_disposition
,
1086 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1090 /* Any data in this call is an EA list. */
1091 if (total_data
&& (total_data
!= 4)) {
1092 if (total_data
< 10) {
1093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1097 if (IVAL(pdata
,0) > total_data
) {
1098 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1099 IVAL(pdata
,0), (unsigned int)total_data
));
1100 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1104 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1107 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1111 if (!lp_ea_support(SNUM(conn
))) {
1112 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1117 status
= SMB_VFS_CREATE_FILE(
1120 0, /* root_dir_fid */
1121 smb_fname
, /* fname */
1122 access_mask
, /* access_mask */
1123 share_mode
, /* share_access */
1124 create_disposition
, /* create_disposition*/
1125 create_options
, /* create_options */
1126 open_attr
, /* file_attributes */
1127 oplock_request
, /* oplock_request */
1128 open_size
, /* allocation_size */
1131 ea_list
, /* ea_list */
1133 &smb_action
); /* psbuf */
1135 if (!NT_STATUS_IS_OK(status
)) {
1136 if (open_was_deferred(req
->mid
)) {
1137 /* We have re-scheduled this call. */
1140 reply_openerror(req
, status
);
1144 size
= get_file_size_stat(&smb_fname
->st
);
1145 fattr
= dos_mode(conn
, smb_fname
);
1146 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1147 inode
= smb_fname
->st
.st_ex_ino
;
1148 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1149 close_file(req
, fsp
, ERROR_CLOSE
);
1150 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1154 /* Realloc the size of parameters and data we will return */
1155 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1156 if(*pparams
== NULL
) {
1157 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1162 SSVAL(params
,0,fsp
->fnum
);
1163 SSVAL(params
,2,fattr
);
1164 srv_put_dos_date2(params
,4, mtime
);
1165 SIVAL(params
,8, (uint32
)size
);
1166 SSVAL(params
,12,deny_mode
);
1167 SSVAL(params
,14,0); /* open_type - file or directory. */
1168 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1170 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1171 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1174 SSVAL(params
,18,smb_action
);
1177 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1179 SIVAL(params
,20,inode
);
1180 SSVAL(params
,24,0); /* Padding. */
1182 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1183 fsp
->fsp_name
->base_name
);
1184 SIVAL(params
, 26, ea_size
);
1186 SIVAL(params
, 26, 0);
1189 /* Send the required number of replies */
1190 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1192 TALLOC_FREE(smb_fname
);
1195 /*********************************************************
1196 Routine to check if a given string matches exactly.
1197 as a special case a mask of "." does NOT match. That
1198 is required for correct wildcard semantics
1199 Case can be significant or not.
1200 **********************************************************/
1202 static bool exact_match(bool has_wild
,
1203 bool case_sensitive
,
1207 if (mask
[0] == '.' && mask
[1] == 0) {
1215 if (case_sensitive
) {
1216 return strcmp(str
,mask
)==0;
1218 return StrCaseCmp(str
,mask
) == 0;
1222 /****************************************************************************
1223 Return the filetype for UNIX extensions.
1224 ****************************************************************************/
1226 static uint32
unix_filetype(mode_t mode
)
1229 return UNIX_TYPE_FILE
;
1230 else if(S_ISDIR(mode
))
1231 return UNIX_TYPE_DIR
;
1233 else if(S_ISLNK(mode
))
1234 return UNIX_TYPE_SYMLINK
;
1237 else if(S_ISCHR(mode
))
1238 return UNIX_TYPE_CHARDEV
;
1241 else if(S_ISBLK(mode
))
1242 return UNIX_TYPE_BLKDEV
;
1245 else if(S_ISFIFO(mode
))
1246 return UNIX_TYPE_FIFO
;
1249 else if(S_ISSOCK(mode
))
1250 return UNIX_TYPE_SOCKET
;
1253 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1254 return UNIX_TYPE_UNKNOWN
;
1257 /****************************************************************************
1258 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1259 ****************************************************************************/
1261 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1263 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1264 const SMB_STRUCT_STAT
*psbuf
,
1266 enum perm_type ptype
,
1271 if (perms
== SMB_MODE_NO_CHANGE
) {
1272 if (!VALID_STAT(*psbuf
)) {
1273 return NT_STATUS_INVALID_PARAMETER
;
1275 *ret_perms
= psbuf
->st_ex_mode
;
1276 return NT_STATUS_OK
;
1280 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1281 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1282 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1283 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1284 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1285 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1286 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1287 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1288 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1290 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1293 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1296 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1301 /* Apply mode mask */
1302 ret
&= lp_create_mask(SNUM(conn
));
1303 /* Add in force bits */
1304 ret
|= lp_force_create_mode(SNUM(conn
));
1307 ret
&= lp_dir_mask(SNUM(conn
));
1308 /* Add in force bits */
1309 ret
|= lp_force_dir_mode(SNUM(conn
));
1311 case PERM_EXISTING_FILE
:
1312 /* Apply mode mask */
1313 ret
&= lp_security_mask(SNUM(conn
));
1314 /* Add in force bits */
1315 ret
|= lp_force_security_mode(SNUM(conn
));
1317 case PERM_EXISTING_DIR
:
1318 /* Apply mode mask */
1319 ret
&= lp_dir_security_mask(SNUM(conn
));
1320 /* Add in force bits */
1321 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1326 return NT_STATUS_OK
;
1329 /****************************************************************************
1330 Needed to show the msdfs symlinks as directories. Modifies psbuf
1331 to be a directory if it's a msdfs link.
1332 ****************************************************************************/
1334 static bool check_msdfs_link(connection_struct
*conn
,
1335 const char *pathname
,
1336 SMB_STRUCT_STAT
*psbuf
)
1338 int saved_errno
= errno
;
1339 if(lp_host_msdfs() &&
1340 lp_msdfs_root(SNUM(conn
)) &&
1341 is_msdfs_link(conn
, pathname
, psbuf
)) {
1343 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1346 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1347 errno
= saved_errno
;
1350 errno
= saved_errno
;
1355 /****************************************************************************
1356 Get a level dependent lanman2 dir entry.
1357 ****************************************************************************/
1359 struct smbd_dirptr_lanman2_state
{
1360 connection_struct
*conn
;
1361 uint32_t info_level
;
1362 bool check_mangled_names
;
1364 bool got_exact_match
;
1367 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1373 struct smbd_dirptr_lanman2_state
*state
=
1374 (struct smbd_dirptr_lanman2_state
*)private_data
;
1376 char mangled_name
[13]; /* mangled 8.3 name. */
1380 /* Mangle fname if it's an illegal name. */
1381 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1382 ok
= name_to_8_3(dname
, mangled_name
,
1383 true, state
->conn
->params
);
1387 fname
= mangled_name
;
1392 got_match
= exact_match(state
->has_wild
,
1393 state
->conn
->case_sensitive
,
1395 state
->got_exact_match
= got_match
;
1397 got_match
= mask_match(fname
, mask
,
1398 state
->conn
->case_sensitive
);
1401 if(!got_match
&& state
->check_mangled_names
&&
1402 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1404 * It turns out that NT matches wildcards against
1405 * both long *and* short names. This may explain some
1406 * of the wildcard wierdness from old DOS clients
1407 * that some people have been seeing.... JRA.
1409 /* Force the mangling into 8.3. */
1410 ok
= name_to_8_3(fname
, mangled_name
,
1411 false, state
->conn
->params
);
1416 got_match
= exact_match(state
->has_wild
,
1417 state
->conn
->case_sensitive
,
1418 mangled_name
, mask
);
1419 state
->got_exact_match
= got_match
;
1421 got_match
= mask_match(mangled_name
, mask
,
1422 state
->conn
->case_sensitive
);
1430 *_fname
= talloc_strdup(ctx
, fname
);
1431 if (*_fname
== NULL
) {
1438 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1440 struct smb_filename
*smb_fname
,
1443 struct smbd_dirptr_lanman2_state
*state
=
1444 (struct smbd_dirptr_lanman2_state
*)private_data
;
1445 bool ms_dfs_link
= false;
1448 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1449 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1450 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1451 "Couldn't lstat [%s] (%s)\n",
1452 smb_fname_str_dbg(smb_fname
),
1456 } else if (!VALID_STAT(smb_fname
->st
) &&
1457 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1458 /* Needed to show the msdfs symlinks as
1461 ms_dfs_link
= check_msdfs_link(state
->conn
,
1462 smb_fname
->base_name
,
1465 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1466 "Couldn't stat [%s] (%s)\n",
1467 smb_fname_str_dbg(smb_fname
),
1474 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1476 mode
= dos_mode(state
->conn
, smb_fname
);
1483 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1484 connection_struct
*conn
,
1486 uint32_t info_level
,
1487 struct ea_list
*name_list
,
1488 bool check_mangled_names
,
1489 bool requires_resume_key
,
1492 const struct smb_filename
*smb_fname
,
1493 int space_remaining
,
1500 uint64_t *last_entry_off
)
1502 char *p
, *q
, *pdata
= *ppdata
;
1504 uint64_t file_size
= 0;
1505 uint64_t allocation_size
= 0;
1506 uint64_t file_index
= 0;
1508 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1509 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1510 time_t c_date
= (time_t)0;
1512 char *last_entry_ptr
;
1517 *out_of_space
= false;
1519 ZERO_STRUCT(mdate_ts
);
1520 ZERO_STRUCT(adate_ts
);
1521 ZERO_STRUCT(create_date_ts
);
1522 ZERO_STRUCT(cdate_ts
);
1524 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1525 file_size
= get_file_size_stat(&smb_fname
->st
);
1527 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1529 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1531 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1532 adate_ts
= smb_fname
->st
.st_ex_atime
;
1533 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1534 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1536 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1537 dos_filetime_timespec(&create_date_ts
);
1538 dos_filetime_timespec(&mdate_ts
);
1539 dos_filetime_timespec(&adate_ts
);
1540 dos_filetime_timespec(&cdate_ts
);
1543 create_date
= convert_timespec_to_time_t(create_date_ts
);
1544 mdate
= convert_timespec_to_time_t(mdate_ts
);
1545 adate
= convert_timespec_to_time_t(adate_ts
);
1546 c_date
= convert_timespec_to_time_t(cdate_ts
);
1548 /* align the record */
1549 SMB_ASSERT(align
>= 1);
1551 off
= (int)PTR_DIFF(pdata
, base_data
);
1552 pad
= (off
+ (align
-1)) & ~(align
-1);
1555 if (pad
&& pad
> space_remaining
) {
1556 *out_of_space
= true;
1557 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1558 "for padding (wanted %u, had %d)\n",
1561 return false; /* Not finished - just out of space */
1565 /* initialize padding to 0 */
1567 memset(pdata
, 0, pad
);
1569 space_remaining
-= pad
;
1571 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1581 switch (info_level
) {
1582 case SMB_FIND_INFO_STANDARD
:
1583 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1584 if(requires_resume_key
) {
1588 srv_put_dos_date2(p
,0,create_date
);
1589 srv_put_dos_date2(p
,4,adate
);
1590 srv_put_dos_date2(p
,8,mdate
);
1591 SIVAL(p
,12,(uint32
)file_size
);
1592 SIVAL(p
,16,(uint32
)allocation_size
);
1596 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1597 p
+= ucs2_align(base_data
, p
, 0);
1599 len
= srvstr_push(base_data
, flags2
, p
,
1600 fname
, PTR_DIFF(end_data
, p
),
1602 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1604 SCVAL(nameptr
, -1, len
- 2);
1606 SCVAL(nameptr
, -1, 0);
1610 SCVAL(nameptr
, -1, len
- 1);
1612 SCVAL(nameptr
, -1, 0);
1618 case SMB_FIND_EA_SIZE
:
1619 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1620 if (requires_resume_key
) {
1624 srv_put_dos_date2(p
,0,create_date
);
1625 srv_put_dos_date2(p
,4,adate
);
1626 srv_put_dos_date2(p
,8,mdate
);
1627 SIVAL(p
,12,(uint32
)file_size
);
1628 SIVAL(p
,16,(uint32
)allocation_size
);
1631 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1632 smb_fname
->base_name
);
1633 SIVAL(p
,22,ea_size
); /* Extended attributes */
1637 len
= srvstr_push(base_data
, flags2
,
1638 p
, fname
, PTR_DIFF(end_data
, p
),
1639 STR_TERMINATE
| STR_NOALIGN
);
1640 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1653 SCVAL(nameptr
,0,len
);
1655 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1658 case SMB_FIND_EA_LIST
:
1660 struct ea_list
*file_list
= NULL
;
1663 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1667 if (requires_resume_key
) {
1671 srv_put_dos_date2(p
,0,create_date
);
1672 srv_put_dos_date2(p
,4,adate
);
1673 srv_put_dos_date2(p
,8,mdate
);
1674 SIVAL(p
,12,(uint32
)file_size
);
1675 SIVAL(p
,16,(uint32
)allocation_size
);
1677 p
+= 22; /* p now points to the EA area. */
1679 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1680 smb_fname
->base_name
,
1682 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1684 /* We need to determine if this entry will fit in the space available. */
1685 /* Max string size is 255 bytes. */
1686 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1687 *out_of_space
= true;
1688 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1689 "(wanted %u, had %d)\n",
1690 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1692 return False
; /* Not finished - just out of space */
1695 /* Push the ea_data followed by the name. */
1696 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1698 len
= srvstr_push(base_data
, flags2
,
1699 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1700 STR_TERMINATE
| STR_NOALIGN
);
1701 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1714 SCVAL(nameptr
,0,len
);
1716 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1720 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1721 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1722 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1724 SIVAL(p
,0,reskey
); p
+= 4;
1725 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1726 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1727 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1728 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1729 SOFF_T(p
,0,file_size
); p
+= 8;
1730 SOFF_T(p
,0,allocation_size
); p
+= 8;
1731 SIVAL(p
,0,mode
); p
+= 4;
1732 q
= p
; p
+= 4; /* q is placeholder for name length. */
1734 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1735 smb_fname
->base_name
);
1736 SIVAL(p
,0,ea_size
); /* Extended attributes */
1739 /* Clear the short name buffer. This is
1740 * IMPORTANT as not doing so will trigger
1741 * a Win2k client bug. JRA.
1743 if (!was_8_3
&& check_mangled_names
) {
1744 char mangled_name
[13]; /* mangled 8.3 name. */
1745 if (!name_to_8_3(fname
,mangled_name
,True
,
1747 /* Error - mangle failed ! */
1748 memset(mangled_name
,'\0',12);
1750 mangled_name
[12] = 0;
1751 len
= srvstr_push(base_data
, flags2
,
1752 p
+2, mangled_name
, 24,
1753 STR_UPPER
|STR_UNICODE
);
1755 memset(p
+ 2 + len
,'\0',24 - len
);
1762 len
= srvstr_push(base_data
, flags2
, p
,
1763 fname
, PTR_DIFF(end_data
, p
),
1764 STR_TERMINATE_ASCII
);
1768 len
= PTR_DIFF(p
, pdata
);
1769 pad
= (len
+ (align
-1)) & ~(align
-1);
1771 * offset to the next entry, the caller
1772 * will overwrite it for the last entry
1773 * that's why we always include the padding
1777 * set padding to zero
1780 memset(p
, 0, pad
- len
);
1787 case SMB_FIND_FILE_DIRECTORY_INFO
:
1788 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1790 SIVAL(p
,0,reskey
); p
+= 4;
1791 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1792 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1793 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1794 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1795 SOFF_T(p
,0,file_size
); p
+= 8;
1796 SOFF_T(p
,0,allocation_size
); p
+= 8;
1797 SIVAL(p
,0,mode
); p
+= 4;
1798 len
= srvstr_push(base_data
, flags2
,
1799 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1800 STR_TERMINATE_ASCII
);
1804 len
= PTR_DIFF(p
, pdata
);
1805 pad
= (len
+ (align
-1)) & ~(align
-1);
1807 * offset to the next entry, the caller
1808 * will overwrite it for the last entry
1809 * that's why we always include the padding
1813 * set padding to zero
1816 memset(p
, 0, pad
- len
);
1823 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1824 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1826 SIVAL(p
,0,reskey
); p
+= 4;
1827 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1828 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1829 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1830 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1831 SOFF_T(p
,0,file_size
); p
+= 8;
1832 SOFF_T(p
,0,allocation_size
); p
+= 8;
1833 SIVAL(p
,0,mode
); p
+= 4;
1834 q
= p
; p
+= 4; /* q is placeholder for name length. */
1836 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1837 smb_fname
->base_name
);
1838 SIVAL(p
,0,ea_size
); /* Extended attributes */
1841 len
= srvstr_push(base_data
, flags2
, p
,
1842 fname
, PTR_DIFF(end_data
, p
),
1843 STR_TERMINATE_ASCII
);
1847 len
= PTR_DIFF(p
, pdata
);
1848 pad
= (len
+ (align
-1)) & ~(align
-1);
1850 * offset to the next entry, the caller
1851 * will overwrite it for the last entry
1852 * that's why we always include the padding
1856 * set padding to zero
1859 memset(p
, 0, pad
- len
);
1866 case SMB_FIND_FILE_NAMES_INFO
:
1867 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1869 SIVAL(p
,0,reskey
); p
+= 4;
1871 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1872 acl on a dir (tridge) */
1873 len
= srvstr_push(base_data
, flags2
, p
,
1874 fname
, PTR_DIFF(end_data
, p
),
1875 STR_TERMINATE_ASCII
);
1879 len
= PTR_DIFF(p
, pdata
);
1880 pad
= (len
+ (align
-1)) & ~(align
-1);
1882 * offset to the next entry, the caller
1883 * will overwrite it for the last entry
1884 * that's why we always include the padding
1888 * set padding to zero
1891 memset(p
, 0, pad
- len
);
1898 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1899 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1901 SIVAL(p
,0,reskey
); p
+= 4;
1902 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1903 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1904 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1905 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1906 SOFF_T(p
,0,file_size
); p
+= 8;
1907 SOFF_T(p
,0,allocation_size
); p
+= 8;
1908 SIVAL(p
,0,mode
); p
+= 4;
1909 q
= p
; p
+= 4; /* q is placeholder for name length. */
1911 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1912 smb_fname
->base_name
);
1913 SIVAL(p
,0,ea_size
); /* Extended attributes */
1916 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1917 SBVAL(p
,0,file_index
); p
+= 8;
1918 len
= srvstr_push(base_data
, flags2
, p
,
1919 fname
, PTR_DIFF(end_data
, p
),
1920 STR_TERMINATE_ASCII
);
1924 len
= PTR_DIFF(p
, pdata
);
1925 pad
= (len
+ (align
-1)) & ~(align
-1);
1927 * offset to the next entry, the caller
1928 * will overwrite it for the last entry
1929 * that's why we always include the padding
1933 * set padding to zero
1936 memset(p
, 0, pad
- len
);
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1944 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1945 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1947 SIVAL(p
,0,reskey
); p
+= 4;
1948 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1949 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1950 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1951 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1952 SOFF_T(p
,0,file_size
); p
+= 8;
1953 SOFF_T(p
,0,allocation_size
); p
+= 8;
1954 SIVAL(p
,0,mode
); p
+= 4;
1955 q
= p
; p
+= 4; /* q is placeholder for name length */
1957 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1958 smb_fname
->base_name
);
1959 SIVAL(p
,0,ea_size
); /* Extended attributes */
1962 /* Clear the short name buffer. This is
1963 * IMPORTANT as not doing so will trigger
1964 * a Win2k client bug. JRA.
1966 if (!was_8_3
&& check_mangled_names
) {
1967 char mangled_name
[13]; /* mangled 8.3 name. */
1968 if (!name_to_8_3(fname
,mangled_name
,True
,
1970 /* Error - mangle failed ! */
1971 memset(mangled_name
,'\0',12);
1973 mangled_name
[12] = 0;
1974 len
= srvstr_push(base_data
, flags2
,
1975 p
+2, mangled_name
, 24,
1976 STR_UPPER
|STR_UNICODE
);
1979 memset(p
+ 2 + len
,'\0',24 - len
);
1986 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1987 SBVAL(p
,0,file_index
); p
+= 8;
1988 len
= srvstr_push(base_data
, flags2
, p
,
1989 fname
, PTR_DIFF(end_data
, p
),
1990 STR_TERMINATE_ASCII
);
1994 len
= PTR_DIFF(p
, pdata
);
1995 pad
= (len
+ (align
-1)) & ~(align
-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2003 * set padding to zero
2006 memset(p
, 0, pad
- len
);
2013 /* CIFS UNIX Extension. */
2015 case SMB_FIND_FILE_UNIX
:
2016 case SMB_FIND_FILE_UNIX_INFO2
:
2018 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2020 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2022 if (info_level
== SMB_FIND_FILE_UNIX
) {
2023 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2024 p
= store_file_unix_basic(conn
, p
,
2025 NULL
, &smb_fname
->st
);
2026 len
= srvstr_push(base_data
, flags2
, p
,
2027 fname
, PTR_DIFF(end_data
, p
),
2030 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2031 p
= store_file_unix_basic_info2(conn
, p
,
2032 NULL
, &smb_fname
->st
);
2035 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2036 PTR_DIFF(end_data
, p
), 0);
2037 SIVAL(nameptr
, 0, len
);
2042 len
= PTR_DIFF(p
, pdata
);
2043 pad
= (len
+ (align
-1)) & ~(align
-1);
2045 * offset to the next entry, the caller
2046 * will overwrite it for the last entry
2047 * that's why we always include the padding
2051 * set padding to zero
2054 memset(p
, 0, pad
- len
);
2059 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2067 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2068 *out_of_space
= true;
2069 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2070 "(wanted %u, had %d)\n",
2071 (unsigned int)PTR_DIFF(p
,pdata
),
2073 return false; /* Not finished - just out of space */
2076 /* Setup the last entry pointer, as an offset from base_data */
2077 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2078 /* Advance the data pointer to the next slot */
2084 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2085 connection_struct
*conn
,
2086 struct dptr_struct
*dirptr
,
2088 const char *path_mask
,
2091 int requires_resume_key
,
2099 int space_remaining
,
2101 bool *got_exact_match
,
2102 int *_last_entry_off
,
2103 struct ea_list
*name_list
)
2106 const char *mask
= NULL
;
2107 long prev_dirpos
= 0;
2110 struct smb_filename
*smb_fname
= NULL
;
2111 struct smbd_dirptr_lanman2_state state
;
2113 uint64_t last_entry_off
= 0;
2117 state
.info_level
= info_level
;
2118 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2119 state
.has_wild
= dptr_has_wild(dirptr
);
2120 state
.got_exact_match
= false;
2122 *out_of_space
= false;
2123 *got_exact_match
= false;
2125 p
= strrchr_m(path_mask
,'/');
2136 ok
= smbd_dirptr_get_entry(ctx
,
2142 smbd_dirptr_lanman2_match_fn
,
2143 smbd_dirptr_lanman2_mode_fn
,
2153 *got_exact_match
= state
.got_exact_match
;
2155 ok
= smbd_marshall_dir_entry(ctx
,
2160 state
.check_mangled_names
,
2161 requires_resume_key
,
2174 TALLOC_FREE(smb_fname
);
2175 if (*out_of_space
) {
2176 dptr_SeekDir(dirptr
, prev_dirpos
);
2183 *_last_entry_off
= last_entry_off
;
2187 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2188 connection_struct
*conn
,
2189 struct dptr_struct
*dirptr
,
2191 const char *path_mask
,
2194 bool requires_resume_key
,
2200 int space_remaining
,
2202 bool *got_exact_match
,
2203 int *last_entry_off
,
2204 struct ea_list
*name_list
)
2207 const bool do_pad
= true;
2209 if (info_level
>= 1 && info_level
<= 3) {
2210 /* No alignment on earlier info levels. */
2214 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2215 path_mask
, dirtype
, info_level
,
2216 requires_resume_key
, dont_descend
, ask_sharemode
,
2218 ppdata
, base_data
, end_data
,
2220 out_of_space
, got_exact_match
,
2221 last_entry_off
, name_list
);
2224 /****************************************************************************
2225 Reply to a TRANS2_FINDFIRST.
2226 ****************************************************************************/
2228 static void call_trans2findfirst(connection_struct
*conn
,
2229 struct smb_request
*req
,
2230 char **pparams
, int total_params
,
2231 char **ppdata
, int total_data
,
2232 unsigned int max_data_bytes
)
2234 /* We must be careful here that we don't return more than the
2235 allowed number of data bytes. If this means returning fewer than
2236 maxentries then so be it. We assume that the redirector has
2237 enough room for the fixed number of parameter bytes it has
2239 struct smb_filename
*smb_dname
= NULL
;
2240 char *params
= *pparams
;
2241 char *pdata
= *ppdata
;
2245 uint16 findfirst_flags
;
2246 bool close_after_first
;
2248 bool requires_resume_key
;
2250 char *directory
= NULL
;
2253 int last_entry_off
=0;
2257 bool finished
= False
;
2258 bool dont_descend
= False
;
2259 bool out_of_space
= False
;
2260 int space_remaining
;
2261 bool mask_contains_wcard
= False
;
2262 struct ea_list
*ea_list
= NULL
;
2263 NTSTATUS ntstatus
= NT_STATUS_OK
;
2264 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2265 TALLOC_CTX
*ctx
= talloc_tos();
2266 struct dptr_struct
*dirptr
= NULL
;
2267 struct smbd_server_connection
*sconn
= req
->sconn
;
2268 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2270 if (total_params
< 13) {
2271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2275 dirtype
= SVAL(params
,0);
2276 maxentries
= SVAL(params
,2);
2277 findfirst_flags
= SVAL(params
,4);
2278 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2279 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2280 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2281 info_level
= SVAL(params
,6);
2283 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2284 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2285 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2286 info_level
, max_data_bytes
));
2289 /* W2K3 seems to treat zero as 1. */
2293 switch (info_level
) {
2294 case SMB_FIND_INFO_STANDARD
:
2295 case SMB_FIND_EA_SIZE
:
2296 case SMB_FIND_EA_LIST
:
2297 case SMB_FIND_FILE_DIRECTORY_INFO
:
2298 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2299 case SMB_FIND_FILE_NAMES_INFO
:
2300 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2301 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2302 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2304 case SMB_FIND_FILE_UNIX
:
2305 case SMB_FIND_FILE_UNIX_INFO2
:
2306 /* Always use filesystem for UNIX mtime query. */
2307 ask_sharemode
= false;
2308 if (!lp_unix_extensions()) {
2309 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2312 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2315 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2319 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2320 params
+12, total_params
- 12,
2321 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2322 if (!NT_STATUS_IS_OK(ntstatus
)) {
2323 reply_nterror(req
, ntstatus
);
2327 ntstatus
= filename_convert(ctx
, conn
,
2328 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2331 &mask_contains_wcard
,
2333 if (!NT_STATUS_IS_OK(ntstatus
)) {
2334 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2335 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2336 ERRSRV
, ERRbadpath
);
2339 reply_nterror(req
, ntstatus
);
2343 mask
= smb_dname
->original_lcomp
;
2345 directory
= smb_dname
->base_name
;
2347 p
= strrchr_m(directory
,'/');
2349 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2350 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2351 mask
= talloc_strdup(ctx
,"*");
2353 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2356 mask_contains_wcard
= True
;
2362 if (p
== NULL
|| p
== directory
) {
2363 /* Ensure we don't have a directory name of "". */
2364 directory
= talloc_strdup(talloc_tos(), ".");
2366 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2371 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2373 if (info_level
== SMB_FIND_EA_LIST
) {
2376 if (total_data
< 4) {
2377 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2381 ea_size
= IVAL(pdata
,0);
2382 if (ea_size
!= total_data
) {
2383 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2384 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2389 if (!lp_ea_support(SNUM(conn
))) {
2390 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2394 /* Pull out the list of names. */
2395 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2397 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2402 *ppdata
= (char *)SMB_REALLOC(
2403 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2404 if(*ppdata
== NULL
) {
2405 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2409 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2411 /* Realloc the params space */
2412 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2413 if (*pparams
== NULL
) {
2414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2419 /* Save the wildcard match and attribs we are using on this directory -
2420 needed as lanman2 assumes these are being saved between calls */
2422 ntstatus
= dptr_create(conn
,
2429 mask_contains_wcard
,
2433 if (!NT_STATUS_IS_OK(ntstatus
)) {
2434 reply_nterror(req
, ntstatus
);
2438 dptr_num
= dptr_dnum(dirptr
);
2439 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2441 /* Initialize per TRANS2_FIND_FIRST operation data */
2442 dptr_init_search_op(dirptr
);
2444 /* We don't need to check for VOL here as this is returned by
2445 a different TRANS2 call. */
2447 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2448 directory
,lp_dontdescend(SNUM(conn
))));
2449 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2450 dont_descend
= True
;
2453 space_remaining
= max_data_bytes
;
2454 out_of_space
= False
;
2456 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2457 bool got_exact_match
= False
;
2459 /* this is a heuristic to avoid seeking the dirptr except when
2460 absolutely necessary. It allows for a filename of about 40 chars */
2461 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2462 out_of_space
= True
;
2465 finished
= !get_lanman2_dir_entry(ctx
,
2469 mask
,dirtype
,info_level
,
2470 requires_resume_key
,dont_descend
,
2473 space_remaining
, &out_of_space
,
2475 &last_entry_off
, ea_list
);
2478 if (finished
&& out_of_space
)
2481 if (!finished
&& !out_of_space
)
2485 * As an optimisation if we know we aren't looking
2486 * for a wildcard name (ie. the name matches the wildcard exactly)
2487 * then we can finish on any (first) match.
2488 * This speeds up large directory searches. JRA.
2494 /* Ensure space_remaining never goes -ve. */
2495 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2496 space_remaining
= 0;
2497 out_of_space
= true;
2499 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2503 /* Check if we can close the dirptr */
2504 if(close_after_first
|| (finished
&& close_if_end
)) {
2505 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2506 dptr_close(sconn
, &dptr_num
);
2510 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2511 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2512 * the protocol level is less than NT1. Tested with smbclient. JRA.
2513 * This should fix the OS/2 client bug #2335.
2516 if(numentries
== 0) {
2517 dptr_close(sconn
, &dptr_num
);
2518 if (get_Protocol() < PROTOCOL_NT1
) {
2519 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2522 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2523 ERRDOS
, ERRbadfile
);
2528 /* At this point pdata points to numentries directory entries. */
2530 /* Set up the return parameter block */
2531 SSVAL(params
,0,dptr_num
);
2532 SSVAL(params
,2,numentries
);
2533 SSVAL(params
,4,finished
);
2534 SSVAL(params
,6,0); /* Never an EA error */
2535 SSVAL(params
,8,last_entry_off
);
2537 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2540 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2541 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2543 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2547 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2548 smb_fn_name(req
->cmd
),
2549 mask
, directory
, dirtype
, numentries
) );
2552 * Force a name mangle here to ensure that the
2553 * mask as an 8.3 name is top of the mangled cache.
2554 * The reasons for this are subtle. Don't remove
2555 * this code unless you know what you are doing
2556 * (see PR#13758). JRA.
2559 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2560 char mangled_name
[13];
2561 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2564 TALLOC_FREE(smb_dname
);
2568 /****************************************************************************
2569 Reply to a TRANS2_FINDNEXT.
2570 ****************************************************************************/
2572 static void call_trans2findnext(connection_struct
*conn
,
2573 struct smb_request
*req
,
2574 char **pparams
, int total_params
,
2575 char **ppdata
, int total_data
,
2576 unsigned int max_data_bytes
)
2578 /* We must be careful here that we don't return more than the
2579 allowed number of data bytes. If this means returning fewer than
2580 maxentries then so be it. We assume that the redirector has
2581 enough room for the fixed number of parameter bytes it has
2583 char *params
= *pparams
;
2584 char *pdata
= *ppdata
;
2590 uint16 findnext_flags
;
2591 bool close_after_request
;
2593 bool requires_resume_key
;
2595 bool mask_contains_wcard
= False
;
2596 char *resume_name
= NULL
;
2597 const char *mask
= NULL
;
2598 const char *directory
= NULL
;
2602 int i
, last_entry_off
=0;
2603 bool finished
= False
;
2604 bool dont_descend
= False
;
2605 bool out_of_space
= False
;
2606 int space_remaining
;
2607 struct ea_list
*ea_list
= NULL
;
2608 NTSTATUS ntstatus
= NT_STATUS_OK
;
2609 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2610 TALLOC_CTX
*ctx
= talloc_tos();
2611 struct dptr_struct
*dirptr
;
2612 struct smbd_server_connection
*sconn
= req
->sconn
;
2614 if (total_params
< 13) {
2615 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2619 dptr_num
= SVAL(params
,0);
2620 maxentries
= SVAL(params
,2);
2621 info_level
= SVAL(params
,4);
2622 resume_key
= IVAL(params
,6);
2623 findnext_flags
= SVAL(params
,10);
2624 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2625 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2626 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2627 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2629 if (!continue_bit
) {
2630 /* We only need resume_name if continue_bit is zero. */
2631 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2633 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2634 &mask_contains_wcard
);
2635 if (!NT_STATUS_IS_OK(ntstatus
)) {
2636 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2637 complain (it thinks we're asking for the directory above the shared
2638 path or an invalid name). Catch this as the resume name is only compared, never used in
2639 a file access. JRA. */
2640 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2641 &resume_name
, params
+12,
2645 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2646 reply_nterror(req
, ntstatus
);
2652 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2653 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2654 resume_key = %d resume name = %s continue=%d level = %d\n",
2655 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2656 requires_resume_key
, resume_key
,
2657 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2660 /* W2K3 seems to treat zero as 1. */
2664 switch (info_level
) {
2665 case SMB_FIND_INFO_STANDARD
:
2666 case SMB_FIND_EA_SIZE
:
2667 case SMB_FIND_EA_LIST
:
2668 case SMB_FIND_FILE_DIRECTORY_INFO
:
2669 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2670 case SMB_FIND_FILE_NAMES_INFO
:
2671 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2672 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2673 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2675 case SMB_FIND_FILE_UNIX
:
2676 case SMB_FIND_FILE_UNIX_INFO2
:
2677 /* Always use filesystem for UNIX mtime query. */
2678 ask_sharemode
= false;
2679 if (!lp_unix_extensions()) {
2680 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2685 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2689 if (info_level
== SMB_FIND_EA_LIST
) {
2692 if (total_data
< 4) {
2693 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2697 ea_size
= IVAL(pdata
,0);
2698 if (ea_size
!= total_data
) {
2699 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2700 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2705 if (!lp_ea_support(SNUM(conn
))) {
2706 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2710 /* Pull out the list of names. */
2711 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2713 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2718 *ppdata
= (char *)SMB_REALLOC(
2719 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2720 if(*ppdata
== NULL
) {
2721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2726 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2728 /* Realloc the params space */
2729 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2730 if(*pparams
== NULL
) {
2731 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2737 /* Check that the dptr is valid */
2738 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2739 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2743 directory
= dptr_path(sconn
, dptr_num
);
2745 /* Get the wildcard mask from the dptr */
2746 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2747 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2748 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2754 /* Get the attr mask from the dptr */
2755 dirtype
= dptr_attr(sconn
, dptr_num
);
2757 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2758 dptr_num
, mask
, dirtype
,
2760 dptr_TellDir(dirptr
)));
2762 /* Initialize per TRANS2_FIND_NEXT operation data */
2763 dptr_init_search_op(dirptr
);
2765 /* We don't need to check for VOL here as this is returned by
2766 a different TRANS2 call. */
2768 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2769 directory
,lp_dontdescend(SNUM(conn
))));
2770 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2771 dont_descend
= True
;
2774 space_remaining
= max_data_bytes
;
2775 out_of_space
= False
;
2778 * Seek to the correct position. We no longer use the resume key but
2779 * depend on the last file name instead.
2782 if(!continue_bit
&& resume_name
&& *resume_name
) {
2785 long current_pos
= 0;
2787 * Remember, name_to_8_3 is called by
2788 * get_lanman2_dir_entry(), so the resume name
2789 * could be mangled. Ensure we check the unmangled name.
2792 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2793 char *new_resume_name
= NULL
;
2794 mangle_lookup_name_from_8_3(ctx
,
2798 if (new_resume_name
) {
2799 resume_name
= new_resume_name
;
2804 * Fix for NT redirector problem triggered by resume key indexes
2805 * changing between directory scans. We now return a resume key of 0
2806 * and instead look for the filename to continue from (also given
2807 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2808 * findfirst/findnext (as is usual) then the directory pointer
2809 * should already be at the correct place.
2812 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2813 } /* end if resume_name && !continue_bit */
2815 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2816 bool got_exact_match
= False
;
2818 /* this is a heuristic to avoid seeking the dirptr except when
2819 absolutely necessary. It allows for a filename of about 40 chars */
2820 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2821 out_of_space
= True
;
2824 finished
= !get_lanman2_dir_entry(ctx
,
2828 mask
,dirtype
,info_level
,
2829 requires_resume_key
,dont_descend
,
2832 space_remaining
, &out_of_space
,
2834 &last_entry_off
, ea_list
);
2837 if (finished
&& out_of_space
)
2840 if (!finished
&& !out_of_space
)
2844 * As an optimisation if we know we aren't looking
2845 * for a wildcard name (ie. the name matches the wildcard exactly)
2846 * then we can finish on any (first) match.
2847 * This speeds up large directory searches. JRA.
2853 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2856 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2857 smb_fn_name(req
->cmd
),
2858 mask
, directory
, dirtype
, numentries
) );
2860 /* Check if we can close the dirptr */
2861 if(close_after_request
|| (finished
&& close_if_end
)) {
2862 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2863 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2866 /* Set up the return parameter block */
2867 SSVAL(params
,0,numentries
);
2868 SSVAL(params
,2,finished
);
2869 SSVAL(params
,4,0); /* Never an EA error */
2870 SSVAL(params
,6,last_entry_off
);
2872 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2878 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2880 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2884 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2886 SMB_ASSERT(extended_info
!= NULL
);
2888 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2889 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2890 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2891 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2892 #ifdef SAMBA_VERSION_REVISION
2893 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2895 extended_info
->samba_subversion
= 0;
2896 #ifdef SAMBA_VERSION_RC_RELEASE
2897 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2899 #ifdef SAMBA_VERSION_PRE_RELEASE
2900 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2903 #ifdef SAMBA_VERSION_VENDOR_PATCH
2904 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2906 extended_info
->samba_gitcommitdate
= 0;
2907 #ifdef SAMBA_VERSION_COMMIT_TIME
2908 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2911 memset(extended_info
->samba_version_string
, 0,
2912 sizeof(extended_info
->samba_version_string
));
2914 snprintf (extended_info
->samba_version_string
,
2915 sizeof(extended_info
->samba_version_string
),
2916 "%s", samba_version_string());
2919 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2920 TALLOC_CTX
*mem_ctx
,
2921 uint16_t info_level
,
2923 unsigned int max_data_bytes
,
2927 char *pdata
, *end_data
;
2928 int data_len
= 0, len
;
2929 const char *vname
= volume_label(SNUM(conn
));
2930 int snum
= SNUM(conn
);
2931 char *fstype
= lp_fstype(SNUM(conn
));
2932 uint32 additional_flags
= 0;
2933 struct smb_filename smb_fname_dot
;
2937 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2938 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2939 "info level (0x%x) on IPC$.\n",
2940 (unsigned int)info_level
));
2941 return NT_STATUS_ACCESS_DENIED
;
2945 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2947 ZERO_STRUCT(smb_fname_dot
);
2948 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2950 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2951 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2952 return map_nt_error_from_unix(errno
);
2955 st
= smb_fname_dot
.st
;
2957 *ppdata
= (char *)SMB_REALLOC(
2958 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2959 if (*ppdata
== NULL
) {
2960 return NT_STATUS_NO_MEMORY
;
2964 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2965 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2967 switch (info_level
) {
2968 case SMB_INFO_ALLOCATION
:
2970 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2972 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2973 return map_nt_error_from_unix(errno
);
2976 block_size
= lp_block_size(snum
);
2977 if (bsize
< block_size
) {
2978 uint64_t factor
= block_size
/bsize
;
2983 if (bsize
> block_size
) {
2984 uint64_t factor
= bsize
/block_size
;
2989 bytes_per_sector
= 512;
2990 sectors_per_unit
= bsize
/bytes_per_sector
;
2992 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2993 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2994 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2996 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2997 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2998 SIVAL(pdata
,l1_cUnit
,dsize
);
2999 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3000 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3004 case SMB_INFO_VOLUME
:
3005 /* Return volume name */
3007 * Add volume serial number - hash of a combination of
3008 * the called hostname and the service name.
3010 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3012 * Win2k3 and previous mess this up by sending a name length
3013 * one byte short. I believe only older clients (OS/2 Win9x) use
3014 * this call so try fixing this by adding a terminating null to
3015 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3019 pdata
+l2_vol_szVolLabel
, vname
,
3020 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3021 STR_NOALIGN
|STR_TERMINATE
);
3022 SCVAL(pdata
,l2_vol_cch
,len
);
3023 data_len
= l2_vol_szVolLabel
+ len
;
3024 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3025 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3029 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3030 case SMB_FS_ATTRIBUTE_INFORMATION
:
3032 additional_flags
= 0;
3033 #if defined(HAVE_SYS_QUOTAS)
3034 additional_flags
|= FILE_VOLUME_QUOTAS
;
3037 if(lp_nt_acl_support(SNUM(conn
))) {
3038 additional_flags
|= FILE_PERSISTENT_ACLS
;
3041 /* Capabilities are filled in at connection time through STATVFS call */
3042 additional_flags
|= conn
->fs_capabilities
;
3043 additional_flags
|= lp_parm_int(conn
->params
->service
,
3044 "share", "fake_fscaps",
3047 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3048 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3049 additional_flags
); /* FS ATTRIBUTES */
3051 SIVAL(pdata
,4,255); /* Max filename component length */
3052 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3053 and will think we can't do long filenames */
3054 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3055 PTR_DIFF(end_data
, pdata
+12),
3058 data_len
= 12 + len
;
3061 case SMB_QUERY_FS_LABEL_INFO
:
3062 case SMB_FS_LABEL_INFORMATION
:
3063 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3064 PTR_DIFF(end_data
, pdata
+4), 0);
3069 case SMB_QUERY_FS_VOLUME_INFO
:
3070 case SMB_FS_VOLUME_INFORMATION
:
3073 * Add volume serial number - hash of a combination of
3074 * the called hostname and the service name.
3076 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3077 (str_checksum(get_local_machine_name())<<16));
3079 /* Max label len is 32 characters. */
3080 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3081 PTR_DIFF(end_data
, pdata
+18),
3083 SIVAL(pdata
,12,len
);
3086 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3087 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3090 case SMB_QUERY_FS_SIZE_INFO
:
3091 case SMB_FS_SIZE_INFORMATION
:
3093 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3095 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3096 return map_nt_error_from_unix(errno
);
3098 block_size
= lp_block_size(snum
);
3099 if (bsize
< block_size
) {
3100 uint64_t factor
= block_size
/bsize
;
3105 if (bsize
> block_size
) {
3106 uint64_t factor
= bsize
/block_size
;
3111 bytes_per_sector
= 512;
3112 sectors_per_unit
= bsize
/bytes_per_sector
;
3113 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3114 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3115 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3116 SBIG_UINT(pdata
,0,dsize
);
3117 SBIG_UINT(pdata
,8,dfree
);
3118 SIVAL(pdata
,16,sectors_per_unit
);
3119 SIVAL(pdata
,20,bytes_per_sector
);
3123 case SMB_FS_FULL_SIZE_INFORMATION
:
3125 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3127 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3128 return map_nt_error_from_unix(errno
);
3130 block_size
= lp_block_size(snum
);
3131 if (bsize
< block_size
) {
3132 uint64_t factor
= block_size
/bsize
;
3137 if (bsize
> block_size
) {
3138 uint64_t factor
= bsize
/block_size
;
3143 bytes_per_sector
= 512;
3144 sectors_per_unit
= bsize
/bytes_per_sector
;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3147 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3148 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3149 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3150 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3151 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3152 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3156 case SMB_QUERY_FS_DEVICE_INFO
:
3157 case SMB_FS_DEVICE_INFORMATION
:
3159 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3161 if (!CAN_WRITE(conn
)) {
3162 characteristics
|= FILE_READ_ONLY_DEVICE
;
3165 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3166 SIVAL(pdata
,4,characteristics
);
3170 #ifdef HAVE_SYS_QUOTAS
3171 case SMB_FS_QUOTA_INFORMATION
:
3173 * what we have to send --metze:
3175 * Unknown1: 24 NULL bytes
3176 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3177 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3178 * Quota Flags: 2 byte :
3179 * Unknown3: 6 NULL bytes
3183 * details for Quota Flags:
3185 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3186 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3187 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3188 * 0x0001 Enable Quotas: enable quota for this fs
3192 /* we need to fake up a fsp here,
3193 * because its not send in this call
3196 SMB_NTQUOTA_STRUCT quotas
;
3199 ZERO_STRUCT(quotas
);
3205 if (get_current_uid(conn
) != 0) {
3206 DEBUG(0,("set_user_quota: access_denied "
3207 "service [%s] user [%s]\n",
3208 lp_servicename(SNUM(conn
)),
3209 conn
->session_info
->unix_name
));
3210 return NT_STATUS_ACCESS_DENIED
;
3213 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3214 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3215 return map_nt_error_from_unix(errno
);
3220 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3221 lp_servicename(SNUM(conn
))));
3223 /* Unknown1 24 NULL bytes*/
3224 SBIG_UINT(pdata
,0,(uint64_t)0);
3225 SBIG_UINT(pdata
,8,(uint64_t)0);
3226 SBIG_UINT(pdata
,16,(uint64_t)0);
3228 /* Default Soft Quota 8 bytes */
3229 SBIG_UINT(pdata
,24,quotas
.softlim
);
3231 /* Default Hard Quota 8 bytes */
3232 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3234 /* Quota flag 2 bytes */
3235 SSVAL(pdata
,40,quotas
.qflags
);
3237 /* Unknown3 6 NULL bytes */
3243 #endif /* HAVE_SYS_QUOTAS */
3244 case SMB_FS_OBJECTID_INFORMATION
:
3246 unsigned char objid
[16];
3247 struct smb_extended_info extended_info
;
3248 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3249 samba_extended_info_version (&extended_info
);
3250 SIVAL(pdata
,16,extended_info
.samba_magic
);
3251 SIVAL(pdata
,20,extended_info
.samba_version
);
3252 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3253 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3254 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3260 * Query the version and capabilities of the CIFS UNIX extensions
3264 case SMB_QUERY_CIFS_UNIX_INFO
:
3266 bool large_write
= lp_min_receive_file_size() &&
3267 !srv_is_signing_active(conn
->sconn
);
3268 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3269 int encrypt_caps
= 0;
3271 if (!lp_unix_extensions()) {
3272 return NT_STATUS_INVALID_LEVEL
;
3275 switch (conn
->encrypt_level
) {
3281 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3284 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3285 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3286 large_write
= false;
3292 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3293 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3295 /* We have POSIX ACLs, pathname, encryption,
3296 * large read/write, and locking capability. */
3298 SBIG_UINT(pdata
,4,((uint64_t)(
3299 CIFS_UNIX_POSIX_ACLS_CAP
|
3300 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3301 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3302 CIFS_UNIX_EXTATTR_CAP
|
3303 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3305 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3307 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3311 case SMB_QUERY_POSIX_FS_INFO
:
3314 vfs_statvfs_struct svfs
;
3316 if (!lp_unix_extensions()) {
3317 return NT_STATUS_INVALID_LEVEL
;
3320 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3324 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3325 SIVAL(pdata
,4,svfs
.BlockSize
);
3326 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3327 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3328 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3329 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3330 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3331 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3332 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3334 } else if (rc
== EOPNOTSUPP
) {
3335 return NT_STATUS_INVALID_LEVEL
;
3336 #endif /* EOPNOTSUPP */
3338 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3339 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3344 case SMB_QUERY_POSIX_WHOAMI
:
3350 if (!lp_unix_extensions()) {
3351 return NT_STATUS_INVALID_LEVEL
;
3354 if (max_data_bytes
< 40) {
3355 return NT_STATUS_BUFFER_TOO_SMALL
;
3358 /* We ARE guest if global_sid_Builtin_Guests is
3359 * in our list of SIDs.
3361 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3362 conn
->session_info
->security_token
)) {
3363 flags
|= SMB_WHOAMI_GUEST
;
3366 /* We are NOT guest if global_sid_Authenticated_Users
3367 * is in our list of SIDs.
3369 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3370 conn
->session_info
->security_token
)) {
3371 flags
&= ~SMB_WHOAMI_GUEST
;
3374 /* NOTE: 8 bytes for UID/GID, irrespective of native
3375 * platform size. This matches
3376 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3378 data_len
= 4 /* flags */
3385 + 4 /* pad/reserved */
3386 + (conn
->session_info
->utok
.ngroups
* 8)
3388 + (conn
->session_info
->security_token
->num_sids
*
3392 SIVAL(pdata
, 0, flags
);
3393 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3395 (uint64_t)conn
->session_info
->utok
.uid
);
3396 SBIG_UINT(pdata
, 16,
3397 (uint64_t)conn
->session_info
->utok
.gid
);
3400 if (data_len
>= max_data_bytes
) {
3401 /* Potential overflow, skip the GIDs and SIDs. */
3403 SIVAL(pdata
, 24, 0); /* num_groups */
3404 SIVAL(pdata
, 28, 0); /* num_sids */
3405 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3406 SIVAL(pdata
, 36, 0); /* reserved */
3412 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3413 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3415 /* We walk the SID list twice, but this call is fairly
3416 * infrequent, and I don't expect that it's performance
3417 * sensitive -- jpeach
3419 for (i
= 0, sid_bytes
= 0;
3420 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3421 sid_bytes
+= ndr_size_dom_sid(
3422 &conn
->session_info
->security_token
->sids
[i
],
3426 /* SID list byte count */
3427 SIVAL(pdata
, 32, sid_bytes
);
3429 /* 4 bytes pad/reserved - must be zero */
3430 SIVAL(pdata
, 36, 0);
3434 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3435 SBIG_UINT(pdata
, data_len
,
3436 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3442 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3443 int sid_len
= ndr_size_dom_sid(
3444 &conn
->session_info
->security_token
->sids
[i
],
3447 sid_linearize(pdata
+ data_len
, sid_len
,
3448 &conn
->session_info
->security_token
->sids
[i
]);
3449 data_len
+= sid_len
;
3455 case SMB_MAC_QUERY_FS_INFO
:
3457 * Thursby MAC extension... ONLY on NTFS filesystems
3458 * once we do streams then we don't need this
3460 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3462 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3467 return NT_STATUS_INVALID_LEVEL
;
3470 *ret_data_len
= data_len
;
3471 return NT_STATUS_OK
;
3474 /****************************************************************************
3475 Reply to a TRANS2_QFSINFO (query filesystem info).
3476 ****************************************************************************/
3478 static void call_trans2qfsinfo(connection_struct
*conn
,
3479 struct smb_request
*req
,
3480 char **pparams
, int total_params
,
3481 char **ppdata
, int total_data
,
3482 unsigned int max_data_bytes
)
3484 char *params
= *pparams
;
3485 uint16_t info_level
;
3489 if (total_params
< 2) {
3490 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3494 info_level
= SVAL(params
,0);
3496 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3497 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3498 DEBUG(0,("call_trans2qfsinfo: encryption required "
3499 "and info level 0x%x sent.\n",
3500 (unsigned int)info_level
));
3501 exit_server_cleanly("encryption required "
3507 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3509 status
= smbd_do_qfsinfo(conn
, req
,
3514 if (!NT_STATUS_IS_OK(status
)) {
3515 reply_nterror(req
, status
);
3519 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3522 DEBUG( 4, ( "%s info_level = %d\n",
3523 smb_fn_name(req
->cmd
), info_level
) );
3528 /****************************************************************************
3529 Reply to a TRANS2_SETFSINFO (set filesystem info).
3530 ****************************************************************************/
3532 static void call_trans2setfsinfo(connection_struct
*conn
,
3533 struct smb_request
*req
,
3534 char **pparams
, int total_params
,
3535 char **ppdata
, int total_data
,
3536 unsigned int max_data_bytes
)
3538 char *pdata
= *ppdata
;
3539 char *params
= *pparams
;
3542 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3545 if (total_params
< 4) {
3546 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3548 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3552 info_level
= SVAL(params
,2);
3555 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3556 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3557 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3558 "info level (0x%x) on IPC$.\n",
3559 (unsigned int)info_level
));
3560 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3565 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3566 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3567 DEBUG(0,("call_trans2setfsinfo: encryption required "
3568 "and info level 0x%x sent.\n",
3569 (unsigned int)info_level
));
3570 exit_server_cleanly("encryption required "
3576 switch(info_level
) {
3577 case SMB_SET_CIFS_UNIX_INFO
:
3579 uint16 client_unix_major
;
3580 uint16 client_unix_minor
;
3581 uint32 client_unix_cap_low
;
3582 uint32 client_unix_cap_high
;
3584 if (!lp_unix_extensions()) {
3586 NT_STATUS_INVALID_LEVEL
);
3590 /* There should be 12 bytes of capabilities set. */
3591 if (total_data
< 8) {
3594 NT_STATUS_INVALID_PARAMETER
);
3597 client_unix_major
= SVAL(pdata
,0);
3598 client_unix_minor
= SVAL(pdata
,2);
3599 client_unix_cap_low
= IVAL(pdata
,4);
3600 client_unix_cap_high
= IVAL(pdata
,8);
3601 /* Just print these values for now. */
3602 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3603 cap_low = 0x%x, cap_high = 0x%x\n",
3604 (unsigned int)client_unix_major
,
3605 (unsigned int)client_unix_minor
,
3606 (unsigned int)client_unix_cap_low
,
3607 (unsigned int)client_unix_cap_high
));
3609 /* Here is where we must switch to posix pathname processing... */
3610 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3611 lp_set_posix_pathnames();
3612 mangle_change_to_posix();
3615 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3616 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3617 /* Client that knows how to do posix locks,
3618 * but not posix open/mkdir operations. Set a
3619 * default type for read/write checks. */
3621 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3627 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3630 size_t param_len
= 0;
3631 size_t data_len
= total_data
;
3633 if (!lp_unix_extensions()) {
3636 NT_STATUS_INVALID_LEVEL
);
3640 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3643 NT_STATUS_NOT_SUPPORTED
);
3647 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3648 DEBUG( 2,("call_trans2setfsinfo: "
3649 "request transport encryption disabled"
3650 "with 'fork echo handler = yes'\n"));
3653 NT_STATUS_NOT_SUPPORTED
);
3657 DEBUG( 4,("call_trans2setfsinfo: "
3658 "request transport encryption.\n"));
3660 status
= srv_request_encryption_setup(conn
,
3661 (unsigned char **)ppdata
,
3663 (unsigned char **)pparams
,
3666 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3667 !NT_STATUS_IS_OK(status
)) {
3668 reply_nterror(req
, status
);
3672 send_trans2_replies(conn
, req
,
3679 if (NT_STATUS_IS_OK(status
)) {
3680 /* Server-side transport
3681 * encryption is now *on*. */
3682 status
= srv_encryption_start(conn
);
3683 if (!NT_STATUS_IS_OK(status
)) {
3684 exit_server_cleanly(
3685 "Failure in setting "
3686 "up encrypted transport");
3692 case SMB_FS_QUOTA_INFORMATION
:
3694 files_struct
*fsp
= NULL
;
3695 SMB_NTQUOTA_STRUCT quotas
;
3697 ZERO_STRUCT(quotas
);
3700 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3701 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3702 lp_servicename(SNUM(conn
)),
3703 conn
->session_info
->unix_name
));
3704 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3708 /* note: normaly there're 48 bytes,
3709 * but we didn't use the last 6 bytes for now
3712 fsp
= file_fsp(req
, SVAL(params
,0));
3714 if (!check_fsp_ntquota_handle(conn
, req
,
3716 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3718 req
, NT_STATUS_INVALID_HANDLE
);
3722 if (total_data
< 42) {
3723 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3727 NT_STATUS_INVALID_PARAMETER
);
3731 /* unknown_1 24 NULL bytes in pdata*/
3733 /* the soft quotas 8 bytes (uint64_t)*/
3734 quotas
.softlim
= BVAL(pdata
,24);
3736 /* the hard quotas 8 bytes (uint64_t)*/
3737 quotas
.hardlim
= BVAL(pdata
,32);
3739 /* quota_flags 2 bytes **/
3740 quotas
.qflags
= SVAL(pdata
,40);
3742 /* unknown_2 6 NULL bytes follow*/
3744 /* now set the quotas */
3745 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3746 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3747 reply_nterror(req
, map_nt_error_from_unix(errno
));
3754 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3756 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3762 * sending this reply works fine,
3763 * but I'm not sure it's the same
3764 * like windows do...
3767 reply_outbuf(req
, 10, 0);
3770 #if defined(HAVE_POSIX_ACLS)
3771 /****************************************************************************
3772 Utility function to count the number of entries in a POSIX acl.
3773 ****************************************************************************/
3775 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3777 unsigned int ace_count
= 0;
3778 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3779 SMB_ACL_ENTRY_T entry
;
3781 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3783 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3784 entry_id
= SMB_ACL_NEXT_ENTRY
;
3791 /****************************************************************************
3792 Utility function to marshall a POSIX acl into wire format.
3793 ****************************************************************************/
3795 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
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)) {
3801 SMB_ACL_TAG_T tagtype
;
3802 SMB_ACL_PERMSET_T permset
;
3803 unsigned char perms
= 0;
3804 unsigned int own_grp
;
3807 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3808 entry_id
= SMB_ACL_NEXT_ENTRY
;
3811 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3816 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3817 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3821 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3822 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3823 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3825 SCVAL(pdata
,1,perms
);
3828 case SMB_ACL_USER_OBJ
:
3829 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3830 own_grp
= (unsigned int)pst
->st_ex_uid
;
3831 SIVAL(pdata
,2,own_grp
);
3836 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3838 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3841 own_grp
= (unsigned int)*puid
;
3842 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3843 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3844 SIVAL(pdata
,2,own_grp
);
3848 case SMB_ACL_GROUP_OBJ
:
3849 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3850 own_grp
= (unsigned int)pst
->st_ex_gid
;
3851 SIVAL(pdata
,2,own_grp
);
3856 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3858 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3861 own_grp
= (unsigned int)*pgid
;
3862 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3863 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3864 SIVAL(pdata
,2,own_grp
);
3869 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3870 SIVAL(pdata
,2,0xFFFFFFFF);
3871 SIVAL(pdata
,6,0xFFFFFFFF);
3874 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3875 SIVAL(pdata
,2,0xFFFFFFFF);
3876 SIVAL(pdata
,6,0xFFFFFFFF);
3879 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3882 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3889 /****************************************************************************
3890 Store the FILE_UNIX_BASIC info.
3891 ****************************************************************************/
3893 static char *store_file_unix_basic(connection_struct
*conn
,
3896 const SMB_STRUCT_STAT
*psbuf
)
3898 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3900 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3901 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3903 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3906 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3909 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3910 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3911 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3914 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3918 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3922 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3925 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3929 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3933 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3936 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3940 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3947 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3948 * the chflags(2) (or equivalent) flags.
3950 * XXX: this really should be behind the VFS interface. To do this, we would
3951 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3952 * Each VFS module could then implement its own mapping as appropriate for the
3953 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3955 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3959 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3963 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3967 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3971 { UF_HIDDEN
, EXT_HIDDEN
},
3974 /* Do not remove. We need to guarantee that this array has at least one
3975 * entry to build on HP-UX.
3981 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3982 uint32
*smb_fflags
, uint32
*smb_fmask
)
3986 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3987 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3988 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3989 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3994 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3995 const uint32 smb_fflags
,
3996 const uint32 smb_fmask
,
3999 uint32 max_fmask
= 0;
4002 *stat_fflags
= psbuf
->st_ex_flags
;
4004 /* For each flags requested in smb_fmask, check the state of the
4005 * corresponding flag in smb_fflags and set or clear the matching
4009 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4010 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4011 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4012 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4013 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4015 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4020 /* If smb_fmask is asking to set any bits that are not supported by
4021 * our flag mappings, we should fail.
4023 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4031 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4032 * of file flags and birth (create) time.
4034 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4037 const SMB_STRUCT_STAT
*psbuf
)
4039 uint32 file_flags
= 0;
4040 uint32 flags_mask
= 0;
4042 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4044 /* Create (birth) time 64 bit */
4045 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4048 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4049 SIVAL(pdata
, 0, file_flags
); /* flags */
4050 SIVAL(pdata
, 4, flags_mask
); /* mask */
4056 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4057 const struct stream_struct
*streams
,
4059 unsigned int max_data_bytes
,
4060 unsigned int *data_size
)
4063 unsigned int ofs
= 0;
4065 for (i
= 0; i
< num_streams
; i
++) {
4066 unsigned int next_offset
;
4068 smb_ucs2_t
*namebuf
;
4070 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4071 streams
[i
].name
, &namelen
) ||
4074 return NT_STATUS_INVALID_PARAMETER
;
4078 * name_buf is now null-terminated, we need to marshall as not
4085 * We cannot overflow ...
4087 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4088 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4090 TALLOC_FREE(namebuf
);
4091 return STATUS_BUFFER_OVERFLOW
;
4094 SIVAL(data
, ofs
+4, namelen
);
4095 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4096 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4097 memcpy(data
+ofs
+24, namebuf
, namelen
);
4098 TALLOC_FREE(namebuf
);
4100 next_offset
= ofs
+ 24 + namelen
;
4102 if (i
== num_streams
-1) {
4103 SIVAL(data
, ofs
, 0);
4106 unsigned int align
= ndr_align_size(next_offset
, 8);
4108 if ((next_offset
+ align
) > max_data_bytes
) {
4109 DEBUG(10, ("refusing to overflow align "
4110 "reply at stream %u\n",
4112 TALLOC_FREE(namebuf
);
4113 return STATUS_BUFFER_OVERFLOW
;
4116 memset(data
+next_offset
, 0, align
);
4117 next_offset
+= align
;
4119 SIVAL(data
, ofs
, next_offset
- ofs
);
4126 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4130 return NT_STATUS_OK
;
4133 /****************************************************************************
4134 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4135 ****************************************************************************/
4137 static void call_trans2qpipeinfo(connection_struct
*conn
,
4138 struct smb_request
*req
,
4139 unsigned int tran_call
,
4140 char **pparams
, int total_params
,
4141 char **ppdata
, int total_data
,
4142 unsigned int max_data_bytes
)
4144 char *params
= *pparams
;
4145 char *pdata
= *ppdata
;
4146 unsigned int data_size
= 0;
4147 unsigned int param_size
= 2;
4152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4156 if (total_params
< 4) {
4157 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4161 fsp
= file_fsp(req
, SVAL(params
,0));
4162 if (!fsp_is_np(fsp
)) {
4163 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4167 info_level
= SVAL(params
,2);
4169 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4170 if (*pparams
== NULL
) {
4171 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4176 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4177 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4178 if (*ppdata
== NULL
) {
4179 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4184 switch (info_level
) {
4185 case SMB_FILE_STANDARD_INFORMATION
:
4187 SOFF_T(pdata
,0,4096LL);
4194 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4198 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4204 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4205 TALLOC_CTX
*mem_ctx
,
4206 uint16_t info_level
,
4208 struct smb_filename
*smb_fname
,
4209 bool delete_pending
,
4210 struct timespec write_time_ts
,
4211 struct ea_list
*ea_list
,
4212 int lock_data_count
,
4215 unsigned int max_data_bytes
,
4217 unsigned int *pdata_size
)
4219 char *pdata
= *ppdata
;
4220 char *dstart
, *dend
;
4221 unsigned int data_size
;
4222 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4223 time_t create_time
, mtime
, atime
, c_time
;
4224 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4231 uint64_t file_size
= 0;
4233 uint64_t allocation_size
= 0;
4234 uint64_t file_index
= 0;
4235 uint32_t access_mask
= 0;
4237 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4238 return NT_STATUS_INVALID_LEVEL
;
4241 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4242 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4243 info_level
, max_data_bytes
));
4245 mode
= dos_mode(conn
, smb_fname
);
4246 nlink
= psbuf
->st_ex_nlink
;
4248 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4252 if ((nlink
> 0) && delete_pending
) {
4256 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4257 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4258 if (*ppdata
== NULL
) {
4259 return NT_STATUS_NO_MEMORY
;
4263 dend
= dstart
+ data_size
- 1;
4265 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4266 update_stat_ex_mtime(psbuf
, write_time_ts
);
4269 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4270 mtime_ts
= psbuf
->st_ex_mtime
;
4271 atime_ts
= psbuf
->st_ex_atime
;
4272 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4274 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4275 dos_filetime_timespec(&create_time_ts
);
4276 dos_filetime_timespec(&mtime_ts
);
4277 dos_filetime_timespec(&atime_ts
);
4278 dos_filetime_timespec(&ctime_ts
);
4281 create_time
= convert_timespec_to_time_t(create_time_ts
);
4282 mtime
= convert_timespec_to_time_t(mtime_ts
);
4283 atime
= convert_timespec_to_time_t(atime_ts
);
4284 c_time
= convert_timespec_to_time_t(ctime_ts
);
4286 p
= strrchr_m(smb_fname
->base_name
,'/');
4288 base_name
= smb_fname
->base_name
;
4292 /* NT expects the name to be in an exact form of the *full*
4293 filename. See the trans2 torture test */
4294 if (ISDOT(base_name
)) {
4295 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4297 return NT_STATUS_NO_MEMORY
;
4300 dos_fname
= talloc_asprintf(mem_ctx
,
4302 smb_fname
->base_name
);
4304 return NT_STATUS_NO_MEMORY
;
4306 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4307 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4308 smb_fname
->stream_name
);
4310 return NT_STATUS_NO_MEMORY
;
4314 string_replace(dos_fname
, '/', '\\');
4317 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4320 /* Do we have this path open ? */
4322 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4323 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4324 if (fsp1
&& fsp1
->initial_allocation_size
) {
4325 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4329 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4330 file_size
= get_file_size_stat(psbuf
);
4334 pos
= fsp
->fh
->position_information
;
4338 access_mask
= fsp
->access_mask
;
4340 /* GENERIC_EXECUTE mapping from Windows */
4341 access_mask
= 0x12019F;
4344 /* This should be an index number - looks like
4347 I think this causes us to fail the IFSKIT
4348 BasicFileInformationTest. -tpot */
4349 file_index
= get_FileIndex(conn
, psbuf
);
4351 switch (info_level
) {
4352 case SMB_INFO_STANDARD
:
4353 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4355 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4356 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4357 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4358 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4359 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4360 SSVAL(pdata
,l1_attrFile
,mode
);
4363 case SMB_INFO_QUERY_EA_SIZE
:
4365 unsigned int ea_size
=
4366 estimate_ea_size(conn
, fsp
,
4367 smb_fname
->base_name
);
4368 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4370 srv_put_dos_date2(pdata
,0,create_time
);
4371 srv_put_dos_date2(pdata
,4,atime
);
4372 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4373 SIVAL(pdata
,12,(uint32
)file_size
);
4374 SIVAL(pdata
,16,(uint32
)allocation_size
);
4375 SSVAL(pdata
,20,mode
);
4376 SIVAL(pdata
,22,ea_size
);
4380 case SMB_INFO_IS_NAME_VALID
:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4383 /* os/2 needs this ? really ?*/
4384 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4386 /* This is only reached for qpathinfo */
4390 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4392 size_t total_ea_len
= 0;
4393 struct ea_list
*ea_file_list
= NULL
;
4395 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4398 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4399 smb_fname
->base_name
,
4401 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4403 if (!ea_list
|| (total_ea_len
> data_size
)) {
4405 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4409 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4413 case SMB_INFO_QUERY_ALL_EAS
:
4415 /* We have data_size bytes to put EA's into. */
4416 size_t total_ea_len
= 0;
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4420 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4421 smb_fname
->base_name
,
4423 if (!ea_list
|| (total_ea_len
> data_size
)) {
4425 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4429 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4433 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4435 /* This is FileFullEaInformation - 0xF which maps to
4436 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4438 /* We have data_size bytes to put EA's into. */
4439 size_t total_ea_len
= 0;
4440 struct ea_list
*ea_file_list
= NULL
;
4442 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4444 /*TODO: add filtering and index handling */
4447 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4448 smb_fname
->base_name
,
4450 if (!ea_file_list
) {
4451 return NT_STATUS_NO_EAS_ON_FILE
;
4454 status
= fill_ea_chained_buffer(mem_ctx
,
4458 conn
, ea_file_list
);
4459 if (!NT_STATUS_IS_OK(status
)) {
4465 case SMB_FILE_BASIC_INFORMATION
:
4466 case SMB_QUERY_FILE_BASIC_INFO
:
4468 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4470 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4472 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4476 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4477 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4478 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4479 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4480 SIVAL(pdata
,32,mode
);
4482 DEBUG(5,("SMB_QFBI - "));
4483 DEBUG(5,("create: %s ", ctime(&create_time
)));
4484 DEBUG(5,("access: %s ", ctime(&atime
)));
4485 DEBUG(5,("write: %s ", ctime(&mtime
)));
4486 DEBUG(5,("change: %s ", ctime(&c_time
)));
4487 DEBUG(5,("mode: %x\n", mode
));
4490 case SMB_FILE_STANDARD_INFORMATION
:
4491 case SMB_QUERY_FILE_STANDARD_INFO
:
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4495 SOFF_T(pdata
,0,allocation_size
);
4496 SOFF_T(pdata
,8,file_size
);
4497 SIVAL(pdata
,16,nlink
);
4498 SCVAL(pdata
,20,delete_pending
?1:0);
4499 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4500 SSVAL(pdata
,22,0); /* Padding. */
4503 case SMB_FILE_EA_INFORMATION
:
4504 case SMB_QUERY_FILE_EA_INFO
:
4506 unsigned int ea_size
=
4507 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4510 SIVAL(pdata
,0,ea_size
);
4514 /* Get the 8.3 name - used if NT SMB was negotiated. */
4515 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4516 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4519 char mangled_name
[13];
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4521 if (!name_to_8_3(base_name
,mangled_name
,
4522 True
,conn
->params
)) {
4523 return NT_STATUS_NO_MEMORY
;
4525 len
= srvstr_push(dstart
, flags2
,
4526 pdata
+4, mangled_name
,
4527 PTR_DIFF(dend
, pdata
+4),
4529 data_size
= 4 + len
;
4534 case SMB_QUERY_FILE_NAME_INFO
:
4538 this must be *exactly* right for ACLs on mapped drives to work
4540 len
= srvstr_push(dstart
, flags2
,
4542 PTR_DIFF(dend
, pdata
+4),
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4545 data_size
= 4 + len
;
4550 case SMB_FILE_ALLOCATION_INFORMATION
:
4551 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4554 SOFF_T(pdata
,0,allocation_size
);
4557 case SMB_FILE_END_OF_FILE_INFORMATION
:
4558 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4561 SOFF_T(pdata
,0,file_size
);
4564 case SMB_QUERY_FILE_ALL_INFO
:
4565 case SMB_FILE_ALL_INFORMATION
:
4568 unsigned int ea_size
=
4569 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4571 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4572 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4573 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4574 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4575 SIVAL(pdata
,32,mode
);
4576 SIVAL(pdata
,36,0); /* padding. */
4578 SOFF_T(pdata
,0,allocation_size
);
4579 SOFF_T(pdata
,8,file_size
);
4580 SIVAL(pdata
,16,nlink
);
4581 SCVAL(pdata
,20,delete_pending
);
4582 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4585 SIVAL(pdata
,0,ea_size
);
4586 pdata
+= 4; /* EA info */
4587 len
= srvstr_push(dstart
, flags2
,
4589 PTR_DIFF(dend
, pdata
+4),
4593 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4597 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4600 unsigned int ea_size
=
4601 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4603 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4604 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4605 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4606 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4607 SIVAL(pdata
, 0x20, mode
);
4608 SIVAL(pdata
, 0x24, 0); /* padding. */
4609 SBVAL(pdata
, 0x28, allocation_size
);
4610 SBVAL(pdata
, 0x30, file_size
);
4611 SIVAL(pdata
, 0x38, nlink
);
4612 SCVAL(pdata
, 0x3C, delete_pending
);
4613 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4614 SSVAL(pdata
, 0x3E, 0); /* padding */
4615 SBVAL(pdata
, 0x40, file_index
);
4616 SIVAL(pdata
, 0x48, ea_size
);
4617 SIVAL(pdata
, 0x4C, access_mask
);
4618 SBVAL(pdata
, 0x50, pos
);
4619 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4620 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4624 len
= srvstr_push(dstart
, flags2
,
4626 PTR_DIFF(dend
, pdata
+4),
4630 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4633 case SMB_FILE_INTERNAL_INFORMATION
:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4636 SBVAL(pdata
, 0, file_index
);
4640 case SMB_FILE_ACCESS_INFORMATION
:
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4642 SIVAL(pdata
, 0, access_mask
);
4646 case SMB_FILE_NAME_INFORMATION
:
4647 /* Pathname with leading '\'. */
4650 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4652 SIVAL(pdata
,0,byte_len
);
4653 data_size
= 4 + byte_len
;
4657 case SMB_FILE_DISPOSITION_INFORMATION
:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4660 SCVAL(pdata
,0,delete_pending
);
4663 case SMB_FILE_POSITION_INFORMATION
:
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4666 SOFF_T(pdata
,0,pos
);
4669 case SMB_FILE_MODE_INFORMATION
:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4671 SIVAL(pdata
,0,mode
);
4675 case SMB_FILE_ALIGNMENT_INFORMATION
:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4677 SIVAL(pdata
,0,0); /* No alignment needed. */
4682 * NT4 server just returns "invalid query" to this - if we try
4683 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4686 /* The first statement above is false - verified using Thursby
4687 * client against NT4 -- gcolley.
4689 case SMB_QUERY_FILE_STREAM_INFO
:
4690 case SMB_FILE_STREAM_INFORMATION
: {
4691 unsigned int num_streams
= 0;
4692 struct stream_struct
*streams
= NULL
;
4694 DEBUG(10,("smbd_do_qfilepathinfo: "
4695 "SMB_FILE_STREAM_INFORMATION\n"));
4697 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4698 return NT_STATUS_INVALID_PARAMETER
;
4701 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4702 talloc_tos(), &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
)));
4717 TALLOC_FREE(streams
);
4721 TALLOC_FREE(streams
);
4725 case SMB_QUERY_COMPRESSION_INFO
:
4726 case SMB_FILE_COMPRESSION_INFORMATION
:
4727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4728 SOFF_T(pdata
,0,file_size
);
4729 SIVAL(pdata
,8,0); /* ??? */
4730 SIVAL(pdata
,12,0); /* ??? */
4734 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4736 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4737 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4738 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4739 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4740 SOFF_T(pdata
,32,allocation_size
);
4741 SOFF_T(pdata
,40,file_size
);
4742 SIVAL(pdata
,48,mode
);
4743 SIVAL(pdata
,52,0); /* ??? */
4747 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4749 SIVAL(pdata
,0,mode
);
4755 * CIFS UNIX Extensions.
4758 case SMB_QUERY_FILE_UNIX_BASIC
:
4760 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4761 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4763 DEBUG(4,("smbd_do_qfilepathinfo: "
4764 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4765 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4769 case SMB_QUERY_FILE_UNIX_INFO2
:
4771 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4772 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4776 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4778 for (i
=0; i
<100; i
++)
4779 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4785 case SMB_QUERY_FILE_UNIX_LINK
:
4788 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4791 return NT_STATUS_NO_MEMORY
;
4794 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4796 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4797 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4800 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4802 len
= SMB_VFS_READLINK(conn
,
4803 smb_fname
->base_name
,
4806 return map_nt_error_from_unix(errno
);
4809 len
= srvstr_push(dstart
, flags2
,
4811 PTR_DIFF(dend
, pdata
),
4814 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4819 #if defined(HAVE_POSIX_ACLS)
4820 case SMB_QUERY_POSIX_ACL
:
4822 SMB_ACL_T file_acl
= NULL
;
4823 SMB_ACL_T def_acl
= NULL
;
4824 uint16 num_file_acls
= 0;
4825 uint16 num_def_acls
= 0;
4827 if (fsp
&& fsp
->fh
->fd
!= -1) {
4828 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4831 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4832 smb_fname
->base_name
,
4833 SMB_ACL_TYPE_ACCESS
);
4836 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4837 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4838 "not implemented on "
4839 "filesystem containing %s\n",
4840 smb_fname
->base_name
));
4841 return NT_STATUS_NOT_IMPLEMENTED
;
4844 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4845 if (fsp
&& fsp
->is_directory
) {
4847 SMB_VFS_SYS_ACL_GET_FILE(
4849 fsp
->fsp_name
->base_name
,
4850 SMB_ACL_TYPE_DEFAULT
);
4853 SMB_VFS_SYS_ACL_GET_FILE(
4855 smb_fname
->base_name
,
4856 SMB_ACL_TYPE_DEFAULT
);
4858 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4861 num_file_acls
= count_acl_entries(conn
, file_acl
);
4862 num_def_acls
= count_acl_entries(conn
, def_acl
);
4864 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4865 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4867 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4868 SMB_POSIX_ACL_HEADER_SIZE
) ));
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4873 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4875 return NT_STATUS_BUFFER_TOO_SMALL
;
4878 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4879 SSVAL(pdata
,2,num_file_acls
);
4880 SSVAL(pdata
,4,num_def_acls
);
4881 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4883 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4888 return NT_STATUS_INTERNAL_ERROR
;
4890 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4892 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4895 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4897 return NT_STATUS_INTERNAL_ERROR
;
4901 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4904 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4906 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4912 case SMB_QUERY_POSIX_LOCK
:
4917 enum brl_type lock_type
;
4919 /* We need an open file with a real fd for this. */
4920 if (!fsp
|| fsp
->fh
->fd
== -1) {
4921 return NT_STATUS_INVALID_LEVEL
;
4924 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4925 return NT_STATUS_INVALID_PARAMETER
;
4928 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4929 case POSIX_LOCK_TYPE_READ
:
4930 lock_type
= READ_LOCK
;
4932 case POSIX_LOCK_TYPE_WRITE
:
4933 lock_type
= WRITE_LOCK
;
4935 case POSIX_LOCK_TYPE_UNLOCK
:
4937 /* There's no point in asking for an unlock... */
4938 return NT_STATUS_INVALID_PARAMETER
;
4941 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4942 #if defined(HAVE_LONGLONG)
4943 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4944 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4945 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4946 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4947 #else /* HAVE_LONGLONG */
4948 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4949 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4950 #endif /* HAVE_LONGLONG */
4952 status
= query_lock(fsp
,
4959 if (ERROR_WAS_LOCK_DENIED(status
)) {
4960 /* Here we need to report who has it locked... */
4961 data_size
= POSIX_LOCK_DATA_SIZE
;
4963 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4964 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4965 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4966 #if defined(HAVE_LONGLONG)
4967 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4968 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4969 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4970 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4971 #else /* HAVE_LONGLONG */
4972 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4973 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4974 #endif /* HAVE_LONGLONG */
4976 } else if (NT_STATUS_IS_OK(status
)) {
4977 /* For success we just return a copy of what we sent
4978 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4979 data_size
= POSIX_LOCK_DATA_SIZE
;
4980 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4981 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4989 return NT_STATUS_INVALID_LEVEL
;
4992 *pdata_size
= data_size
;
4993 return NT_STATUS_OK
;
4996 /****************************************************************************
4997 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4998 file name or file id).
4999 ****************************************************************************/
5001 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5002 struct smb_request
*req
,
5003 unsigned int tran_call
,
5004 char **pparams
, int total_params
,
5005 char **ppdata
, int total_data
,
5006 unsigned int max_data_bytes
)
5008 char *params
= *pparams
;
5009 char *pdata
= *ppdata
;
5011 unsigned int data_size
= 0;
5012 unsigned int param_size
= 2;
5013 struct smb_filename
*smb_fname
= NULL
;
5014 bool delete_pending
= False
;
5015 struct timespec write_time_ts
;
5016 files_struct
*fsp
= NULL
;
5017 struct file_id fileid
;
5018 struct ea_list
*ea_list
= NULL
;
5019 int lock_data_count
= 0;
5020 char *lock_data
= NULL
;
5021 NTSTATUS status
= NT_STATUS_OK
;
5024 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5028 ZERO_STRUCT(write_time_ts
);
5030 if (tran_call
== TRANSACT2_QFILEINFO
) {
5031 if (total_params
< 4) {
5032 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5037 call_trans2qpipeinfo(conn
, req
, tran_call
,
5038 pparams
, total_params
,
5044 fsp
= file_fsp(req
, SVAL(params
,0));
5045 info_level
= SVAL(params
,2);
5047 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5049 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5050 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5054 /* Initial check for valid fsp ptr. */
5055 if (!check_fsp_open(conn
, req
, fsp
)) {
5059 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5061 if (!NT_STATUS_IS_OK(status
)) {
5062 reply_nterror(req
, status
);
5066 if(fsp
->fake_file_handle
) {
5068 * This is actually for the QUOTA_FAKE_FILE --metze
5071 /* We know this name is ok, it's already passed the checks. */
5073 } else if(fsp
->fh
->fd
== -1) {
5075 * This is actually a QFILEINFO on a directory
5076 * handle (returned from an NT SMB). NT5.0 seems
5077 * to do this call. JRA.
5080 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5081 /* Always do lstat for UNIX calls. */
5082 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5083 DEBUG(3,("call_trans2qfilepathinfo: "
5084 "SMB_VFS_LSTAT of %s failed "
5086 smb_fname_str_dbg(smb_fname
),
5089 map_nt_error_from_unix(errno
));
5092 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5093 DEBUG(3,("call_trans2qfilepathinfo: "
5094 "SMB_VFS_STAT of %s failed (%s)\n",
5095 smb_fname_str_dbg(smb_fname
),
5098 map_nt_error_from_unix(errno
));
5102 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5103 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5106 * Original code - this is an open file.
5108 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5109 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5110 fsp
->fnum
, strerror(errno
)));
5112 map_nt_error_from_unix(errno
));
5115 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5116 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5122 uint32_t ucf_flags
= 0;
5125 if (total_params
< 7) {
5126 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5130 info_level
= SVAL(params
,0);
5132 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5134 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5135 if (!lp_unix_extensions()) {
5136 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5139 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5140 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5141 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5142 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5146 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5148 STR_TERMINATE
, &status
);
5149 if (!NT_STATUS_IS_OK(status
)) {
5150 reply_nterror(req
, status
);
5154 status
= filename_convert(req
,
5156 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5161 if (!NT_STATUS_IS_OK(status
)) {
5162 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5163 reply_botherror(req
,
5164 NT_STATUS_PATH_NOT_COVERED
,
5165 ERRSRV
, ERRbadpath
);
5168 reply_nterror(req
, status
);
5172 /* If this is a stream, check if there is a delete_pending. */
5173 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5174 && is_ntfs_stream_smb_fname(smb_fname
)) {
5175 struct smb_filename
*smb_fname_base
= NULL
;
5177 /* Create an smb_filename with stream_name == NULL. */
5179 create_synthetic_smb_fname(talloc_tos(),
5180 smb_fname
->base_name
,
5183 if (!NT_STATUS_IS_OK(status
)) {
5184 reply_nterror(req
, status
);
5188 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5189 /* Always do lstat for UNIX calls. */
5190 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5191 DEBUG(3,("call_trans2qfilepathinfo: "
5192 "SMB_VFS_LSTAT of %s failed "
5194 smb_fname_str_dbg(smb_fname_base
),
5196 TALLOC_FREE(smb_fname_base
);
5198 map_nt_error_from_unix(errno
));
5202 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "fileinfo of %s failed "
5206 smb_fname_str_dbg(smb_fname_base
),
5208 TALLOC_FREE(smb_fname_base
);
5210 map_nt_error_from_unix(errno
));
5215 status
= file_name_hash(conn
,
5216 smb_fname_str_dbg(smb_fname_base
),
5218 if (!NT_STATUS_IS_OK(status
)) {
5219 TALLOC_FREE(smb_fname_base
);
5220 reply_nterror(req
, status
);
5224 fileid
= vfs_file_id_from_sbuf(conn
,
5225 &smb_fname_base
->st
);
5226 TALLOC_FREE(smb_fname_base
);
5227 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5228 if (delete_pending
) {
5229 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5234 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5235 /* Always do lstat for UNIX calls. */
5236 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5237 DEBUG(3,("call_trans2qfilepathinfo: "
5238 "SMB_VFS_LSTAT of %s failed (%s)\n",
5239 smb_fname_str_dbg(smb_fname
),
5242 map_nt_error_from_unix(errno
));
5247 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "SMB_VFS_STAT of %s failed (%s)\n",
5250 smb_fname_str_dbg(smb_fname
),
5253 map_nt_error_from_unix(errno
));
5258 status
= file_name_hash(conn
,
5259 smb_fname_str_dbg(smb_fname
),
5261 if (!NT_STATUS_IS_OK(status
)) {
5262 reply_nterror(req
, status
);
5266 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5267 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5268 if (delete_pending
) {
5269 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5274 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5275 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5276 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5278 /* Pull out any data sent here before we realloc. */
5279 switch (info_level
) {
5280 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5282 /* Pull any EA list from the data portion. */
5285 if (total_data
< 4) {
5287 req
, NT_STATUS_INVALID_PARAMETER
);
5290 ea_size
= IVAL(pdata
,0);
5292 if (total_data
> 0 && ea_size
!= total_data
) {
5293 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5294 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5296 req
, NT_STATUS_INVALID_PARAMETER
);
5300 if (!lp_ea_support(SNUM(conn
))) {
5301 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5305 /* Pull out the list of names. */
5306 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5309 req
, NT_STATUS_INVALID_PARAMETER
);
5315 case SMB_QUERY_POSIX_LOCK
:
5317 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5318 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5322 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5324 req
, NT_STATUS_INVALID_PARAMETER
);
5328 /* Copy the lock range data. */
5329 lock_data
= (char *)TALLOC_MEMDUP(
5330 req
, pdata
, total_data
);
5332 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5335 lock_data_count
= total_data
;
5341 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5342 if (*pparams
== NULL
) {
5343 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5350 * draft-leach-cifs-v1-spec-02.txt
5351 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5354 * The requested information is placed in the Data portion of the
5355 * transaction response. For the information levels greater than 0x100,
5356 * the transaction response has 1 parameter word which should be
5357 * ignored by the client.
5359 * However Windows only follows this rule for the IS_NAME_VALID call.
5361 switch (info_level
) {
5362 case SMB_INFO_IS_NAME_VALID
:
5367 if ((info_level
& 0xFF00) == 0xFF00) {
5369 * We use levels that start with 0xFF00
5370 * internally to represent SMB2 specific levels
5372 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5376 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5378 delete_pending
, write_time_ts
,
5380 lock_data_count
, lock_data
,
5381 req
->flags2
, max_data_bytes
,
5382 ppdata
, &data_size
);
5383 if (!NT_STATUS_IS_OK(status
)) {
5384 reply_nterror(req
, status
);
5388 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5394 /****************************************************************************
5395 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5397 ****************************************************************************/
5399 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5400 connection_struct
*conn
,
5401 struct smb_request
*req
,
5402 bool overwrite_if_exists
,
5403 const struct smb_filename
*smb_fname_old
,
5404 struct smb_filename
*smb_fname_new
)
5406 NTSTATUS status
= NT_STATUS_OK
;
5408 /* source must already exist. */
5409 if (!VALID_STAT(smb_fname_old
->st
)) {
5410 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5413 if (VALID_STAT(smb_fname_new
->st
)) {
5414 if (overwrite_if_exists
) {
5415 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5416 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5418 status
= unlink_internals(conn
,
5420 FILE_ATTRIBUTE_NORMAL
,
5423 if (!NT_STATUS_IS_OK(status
)) {
5427 /* Disallow if newname already exists. */
5428 return NT_STATUS_OBJECT_NAME_COLLISION
;
5432 /* No links from a directory. */
5433 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5434 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5437 /* Setting a hardlink to/from a stream isn't currently supported. */
5438 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5439 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5440 return NT_STATUS_INVALID_PARAMETER
;
5443 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5444 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5446 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5447 smb_fname_new
->base_name
) != 0) {
5448 status
= map_nt_error_from_unix(errno
);
5449 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5450 nt_errstr(status
), smb_fname_old
->base_name
,
5451 smb_fname_new
->base_name
));
5456 /****************************************************************************
5457 Deal with setting the time from any of the setfilepathinfo functions.
5458 ****************************************************************************/
5460 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5462 const struct smb_filename
*smb_fname
,
5463 struct smb_file_time
*ft
,
5464 bool setting_write_time
)
5466 struct smb_filename smb_fname_base
;
5468 FILE_NOTIFY_CHANGE_LAST_ACCESS
5469 |FILE_NOTIFY_CHANGE_LAST_WRITE
5470 |FILE_NOTIFY_CHANGE_CREATION
;
5472 if (!VALID_STAT(smb_fname
->st
)) {
5473 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5476 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5477 return NT_STATUS_ACCESS_DENIED
;
5480 /* get some defaults (no modifications) if any info is zero or -1. */
5481 if (null_timespec(ft
->create_time
)) {
5482 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5485 if (null_timespec(ft
->atime
)) {
5486 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5489 if (null_timespec(ft
->mtime
)) {
5490 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5493 if (!setting_write_time
) {
5494 /* ft->mtime comes from change time, not write time. */
5495 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5498 /* Ensure the resolution is the correct for
5499 * what we can store on this filesystem. */
5501 round_timespec(conn
->ts_res
, &ft
->create_time
);
5502 round_timespec(conn
->ts_res
, &ft
->ctime
);
5503 round_timespec(conn
->ts_res
, &ft
->atime
);
5504 round_timespec(conn
->ts_res
, &ft
->mtime
);
5506 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5507 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5508 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5509 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5510 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5511 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5512 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5513 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5515 if (setting_write_time
) {
5517 * This was a Windows setfileinfo on an open file.
5518 * NT does this a lot. We also need to
5519 * set the time here, as it can be read by
5520 * FindFirst/FindNext and with the patch for bug #2045
5521 * in smbd/fileio.c it ensures that this timestamp is
5522 * kept sticky even after a write. We save the request
5523 * away and will set it on file close and after a write. JRA.
5526 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5527 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5530 if (fsp
->base_fsp
) {
5531 set_sticky_write_time_fsp(fsp
->base_fsp
,
5534 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5537 set_sticky_write_time_path(
5538 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5543 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5545 /* Always call ntimes on the base, even if a stream was passed in. */
5546 smb_fname_base
= *smb_fname
;
5547 smb_fname_base
.stream_name
= NULL
;
5549 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5550 return map_nt_error_from_unix(errno
);
5553 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5554 smb_fname
->base_name
);
5555 return NT_STATUS_OK
;
5558 /****************************************************************************
5559 Deal with setting the dosmode from any of the setfilepathinfo functions.
5560 ****************************************************************************/
5562 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5563 const struct smb_filename
*smb_fname
,
5566 struct smb_filename
*smb_fname_base
= NULL
;
5569 if (!VALID_STAT(smb_fname
->st
)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5573 /* Always operate on the base_name, even if a stream was passed in. */
5574 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5575 NULL
, &smb_fname
->st
,
5577 if (!NT_STATUS_IS_OK(status
)) {
5582 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5583 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5585 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5589 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5591 /* check the mode isn't different, before changing it */
5592 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5593 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5594 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5595 (unsigned int)dosmode
));
5597 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5599 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5601 smb_fname_str_dbg(smb_fname_base
),
5603 status
= map_nt_error_from_unix(errno
);
5607 status
= NT_STATUS_OK
;
5609 TALLOC_FREE(smb_fname_base
);
5613 /****************************************************************************
5614 Deal with setting the size from any of the setfilepathinfo functions.
5615 ****************************************************************************/
5617 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5618 struct smb_request
*req
,
5620 const struct smb_filename
*smb_fname
,
5621 const SMB_STRUCT_STAT
*psbuf
,
5623 bool fail_after_createfile
)
5625 NTSTATUS status
= NT_STATUS_OK
;
5626 struct smb_filename
*smb_fname_tmp
= NULL
;
5627 files_struct
*new_fsp
= NULL
;
5629 if (!VALID_STAT(*psbuf
)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5633 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5634 return NT_STATUS_ACCESS_DENIED
;
5637 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5639 if (size
== get_file_size_stat(psbuf
)) {
5640 return NT_STATUS_OK
;
5643 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5644 smb_fname_str_dbg(smb_fname
), (double)size
));
5646 if (fsp
&& fsp
->fh
->fd
!= -1) {
5647 /* Handle based call. */
5648 if (vfs_set_filelen(fsp
, size
) == -1) {
5649 return map_nt_error_from_unix(errno
);
5651 trigger_write_time_update_immediate(fsp
);
5652 return NT_STATUS_OK
;
5655 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5656 if (!NT_STATUS_IS_OK(status
)) {
5660 smb_fname_tmp
->st
= *psbuf
;
5662 status
= SMB_VFS_CREATE_FILE(
5665 0, /* root_dir_fid */
5666 smb_fname_tmp
, /* fname */
5667 FILE_WRITE_DATA
, /* access_mask */
5668 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5670 FILE_OPEN
, /* create_disposition*/
5671 0, /* create_options */
5672 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5673 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5674 0, /* allocation_size */
5675 0, /* private_flags */
5678 &new_fsp
, /* result */
5681 TALLOC_FREE(smb_fname_tmp
);
5683 if (!NT_STATUS_IS_OK(status
)) {
5684 /* NB. We check for open_was_deferred in the caller. */
5688 /* See RAW-SFILEINFO-END-OF-FILE */
5689 if (fail_after_createfile
) {
5690 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5691 return NT_STATUS_INVALID_LEVEL
;
5694 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5695 status
= map_nt_error_from_unix(errno
);
5696 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5700 trigger_write_time_update_immediate(new_fsp
);
5701 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5702 return NT_STATUS_OK
;
5705 /****************************************************************************
5706 Deal with SMB_INFO_SET_EA.
5707 ****************************************************************************/
5709 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5713 const struct smb_filename
*smb_fname
)
5715 struct ea_list
*ea_list
= NULL
;
5716 TALLOC_CTX
*ctx
= NULL
;
5717 NTSTATUS status
= NT_STATUS_OK
;
5719 if (total_data
< 10) {
5721 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5722 length. They seem to have no effect. Bug #3212. JRA */
5724 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5725 /* We're done. We only get EA info in this call. */
5726 return NT_STATUS_OK
;
5729 return NT_STATUS_INVALID_PARAMETER
;
5732 if (IVAL(pdata
,0) > total_data
) {
5733 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5734 IVAL(pdata
,0), (unsigned int)total_data
));
5735 return NT_STATUS_INVALID_PARAMETER
;
5739 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5741 return NT_STATUS_INVALID_PARAMETER
;
5744 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5745 return NT_STATUS_ACCESS_DENIED
;
5748 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5753 /****************************************************************************
5754 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5755 ****************************************************************************/
5757 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5762 struct ea_list
*ea_list
= NULL
;
5766 return NT_STATUS_INVALID_HANDLE
;
5769 if (!lp_ea_support(SNUM(conn
))) {
5770 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5771 "EA's not supported.\n",
5772 (unsigned int)total_data
));
5773 return NT_STATUS_EAS_NOT_SUPPORTED
;
5776 if (total_data
< 10) {
5777 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5779 (unsigned int)total_data
));
5780 return NT_STATUS_INVALID_PARAMETER
;
5783 ea_list
= read_nttrans_ea_list(talloc_tos(),
5788 return NT_STATUS_INVALID_PARAMETER
;
5791 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5792 return NT_STATUS_ACCESS_DENIED
;
5795 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5797 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5798 smb_fname_str_dbg(fsp
->fsp_name
),
5799 nt_errstr(status
) ));
5805 /****************************************************************************
5806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5807 ****************************************************************************/
5809 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5813 struct smb_filename
*smb_fname
)
5815 NTSTATUS status
= NT_STATUS_OK
;
5816 bool delete_on_close
;
5819 if (total_data
< 1) {
5820 return NT_STATUS_INVALID_PARAMETER
;
5824 return NT_STATUS_INVALID_HANDLE
;
5827 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5828 dosmode
= dos_mode(conn
, smb_fname
);
5830 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5831 "delete_on_close = %u\n",
5832 smb_fname_str_dbg(smb_fname
),
5833 (unsigned int)dosmode
,
5834 (unsigned int)delete_on_close
));
5836 if (delete_on_close
) {
5837 status
= can_set_delete_on_close(fsp
, dosmode
);
5838 if (!NT_STATUS_IS_OK(status
)) {
5843 /* The set is across all open files on this dev/inode pair. */
5844 if (!set_delete_on_close(fsp
, delete_on_close
,
5845 conn
->session_info
->security_token
,
5846 &conn
->session_info
->utok
)) {
5847 return NT_STATUS_ACCESS_DENIED
;
5849 return NT_STATUS_OK
;
5852 /****************************************************************************
5853 Deal with SMB_FILE_POSITION_INFORMATION.
5854 ****************************************************************************/
5856 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5861 uint64_t position_information
;
5863 if (total_data
< 8) {
5864 return NT_STATUS_INVALID_PARAMETER
;
5868 /* Ignore on pathname based set. */
5869 return NT_STATUS_OK
;
5872 position_information
= (uint64_t)IVAL(pdata
,0);
5873 #ifdef LARGE_SMB_OFF_T
5874 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5875 #else /* LARGE_SMB_OFF_T */
5876 if (IVAL(pdata
,4) != 0) {
5877 /* more than 32 bits? */
5878 return NT_STATUS_INVALID_PARAMETER
;
5880 #endif /* LARGE_SMB_OFF_T */
5882 DEBUG(10,("smb_file_position_information: Set file position "
5883 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5884 (double)position_information
));
5885 fsp
->fh
->position_information
= position_information
;
5886 return NT_STATUS_OK
;
5889 /****************************************************************************
5890 Deal with SMB_FILE_MODE_INFORMATION.
5891 ****************************************************************************/
5893 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5899 if (total_data
< 4) {
5900 return NT_STATUS_INVALID_PARAMETER
;
5902 mode
= IVAL(pdata
,0);
5903 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5904 return NT_STATUS_INVALID_PARAMETER
;
5906 return NT_STATUS_OK
;
5909 /****************************************************************************
5910 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5911 ****************************************************************************/
5913 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5914 struct smb_request
*req
,
5917 const struct smb_filename
*smb_fname
)
5919 char *link_target
= NULL
;
5920 const char *newname
= smb_fname
->base_name
;
5921 TALLOC_CTX
*ctx
= talloc_tos();
5923 /* Set a symbolic link. */
5924 /* Don't allow this if follow links is false. */
5926 if (total_data
== 0) {
5927 return NT_STATUS_INVALID_PARAMETER
;
5930 if (!lp_symlinks(SNUM(conn
))) {
5931 return NT_STATUS_ACCESS_DENIED
;
5934 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5935 total_data
, STR_TERMINATE
);
5938 return NT_STATUS_INVALID_PARAMETER
;
5941 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5942 newname
, link_target
));
5944 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5945 return map_nt_error_from_unix(errno
);
5948 return NT_STATUS_OK
;
5951 /****************************************************************************
5952 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5953 ****************************************************************************/
5955 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5956 struct smb_request
*req
,
5957 const char *pdata
, int total_data
,
5958 struct smb_filename
*smb_fname_new
)
5960 char *oldname
= NULL
;
5961 struct smb_filename
*smb_fname_old
= NULL
;
5962 TALLOC_CTX
*ctx
= talloc_tos();
5963 NTSTATUS status
= NT_STATUS_OK
;
5965 /* Set a hard link. */
5966 if (total_data
== 0) {
5967 return NT_STATUS_INVALID_PARAMETER
;
5970 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5971 total_data
, STR_TERMINATE
, &status
);
5972 if (!NT_STATUS_IS_OK(status
)) {
5976 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5977 smb_fname_str_dbg(smb_fname_new
), oldname
));
5979 status
= filename_convert(ctx
,
5981 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5986 if (!NT_STATUS_IS_OK(status
)) {
5990 return hardlink_internals(ctx
, conn
, req
, false,
5991 smb_fname_old
, smb_fname_new
);
5994 /****************************************************************************
5995 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5996 ****************************************************************************/
5998 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5999 struct smb_request
*req
,
6003 struct smb_filename
*smb_fname_src
)
6007 char *newname
= NULL
;
6008 struct smb_filename
*smb_fname_dst
= NULL
;
6009 NTSTATUS status
= NT_STATUS_OK
;
6010 TALLOC_CTX
*ctx
= talloc_tos();
6013 return NT_STATUS_INVALID_HANDLE
;
6016 if (total_data
< 20) {
6017 return NT_STATUS_INVALID_PARAMETER
;
6020 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6021 len
= IVAL(pdata
,16);
6023 if (len
> (total_data
- 20) || (len
== 0)) {
6024 return NT_STATUS_INVALID_PARAMETER
;
6027 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6028 &pdata
[20], len
, STR_TERMINATE
,
6030 if (!NT_STATUS_IS_OK(status
)) {
6034 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6037 status
= filename_convert(ctx
,
6039 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6044 if (!NT_STATUS_IS_OK(status
)) {
6048 if (fsp
->base_fsp
) {
6049 /* newname must be a stream name. */
6050 if (newname
[0] != ':') {
6051 return NT_STATUS_NOT_SUPPORTED
;
6054 /* Create an smb_fname to call rename_internals_fsp() with. */
6055 status
= create_synthetic_smb_fname(talloc_tos(),
6056 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6058 if (!NT_STATUS_IS_OK(status
)) {
6063 * Set the original last component, since
6064 * rename_internals_fsp() requires it.
6066 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6068 if (smb_fname_dst
->original_lcomp
== NULL
) {
6069 status
= NT_STATUS_NO_MEMORY
;
6075 DEBUG(10,("smb2_file_rename_information: "
6076 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6077 fsp
->fnum
, fsp_str_dbg(fsp
),
6078 smb_fname_str_dbg(smb_fname_dst
)));
6079 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6080 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6084 TALLOC_FREE(smb_fname_dst
);
6088 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6089 struct smb_request
*req
,
6093 struct smb_filename
*smb_fname_src
)
6097 char *newname
= NULL
;
6098 struct smb_filename
*smb_fname_dst
= NULL
;
6099 NTSTATUS status
= NT_STATUS_OK
;
6100 TALLOC_CTX
*ctx
= talloc_tos();
6103 return NT_STATUS_INVALID_HANDLE
;
6106 if (total_data
< 20) {
6107 return NT_STATUS_INVALID_PARAMETER
;
6110 overwrite
= (CVAL(pdata
,0) ? true : false);
6111 len
= IVAL(pdata
,16);
6113 if (len
> (total_data
- 20) || (len
== 0)) {
6114 return NT_STATUS_INVALID_PARAMETER
;
6117 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6118 &pdata
[20], len
, STR_TERMINATE
,
6120 if (!NT_STATUS_IS_OK(status
)) {
6124 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6127 status
= filename_convert(ctx
,
6129 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6134 if (!NT_STATUS_IS_OK(status
)) {
6138 if (fsp
->base_fsp
) {
6139 /* No stream names. */
6140 return NT_STATUS_NOT_SUPPORTED
;
6143 DEBUG(10,("smb_file_link_information: "
6144 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6145 fsp
->fnum
, fsp_str_dbg(fsp
),
6146 smb_fname_str_dbg(smb_fname_dst
)));
6147 status
= hardlink_internals(ctx
,
6154 TALLOC_FREE(smb_fname_dst
);
6158 /****************************************************************************
6159 Deal with SMB_FILE_RENAME_INFORMATION.
6160 ****************************************************************************/
6162 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6163 struct smb_request
*req
,
6167 struct smb_filename
*smb_fname_src
)
6172 char *newname
= NULL
;
6173 struct smb_filename
*smb_fname_dst
= NULL
;
6174 bool dest_has_wcard
= False
;
6175 NTSTATUS status
= NT_STATUS_OK
;
6177 TALLOC_CTX
*ctx
= talloc_tos();
6179 if (total_data
< 13) {
6180 return NT_STATUS_INVALID_PARAMETER
;
6183 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6184 root_fid
= IVAL(pdata
,4);
6185 len
= IVAL(pdata
,8);
6187 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6188 return NT_STATUS_INVALID_PARAMETER
;
6191 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6194 if (!NT_STATUS_IS_OK(status
)) {
6198 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6201 status
= resolve_dfspath_wcard(ctx
, conn
,
6202 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6207 if (!NT_STATUS_IS_OK(status
)) {
6211 /* Check the new name has no '/' characters. */
6212 if (strchr_m(newname
, '/')) {
6213 return NT_STATUS_NOT_SUPPORTED
;
6216 if (fsp
&& fsp
->base_fsp
) {
6217 /* newname must be a stream name. */
6218 if (newname
[0] != ':') {
6219 return NT_STATUS_NOT_SUPPORTED
;
6222 /* Create an smb_fname to call rename_internals_fsp() with. */
6223 status
= create_synthetic_smb_fname(talloc_tos(),
6224 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6226 if (!NT_STATUS_IS_OK(status
)) {
6231 * Set the original last component, since
6232 * rename_internals_fsp() requires it.
6234 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6236 if (smb_fname_dst
->original_lcomp
== NULL
) {
6237 status
= NT_STATUS_NO_MEMORY
;
6243 * Build up an smb_fname_dst based on the filename passed in.
6244 * We basically just strip off the last component, and put on
6245 * the newname instead.
6247 char *base_name
= NULL
;
6249 /* newname must *not* be a stream name. */
6250 if (newname
[0] == ':') {
6251 return NT_STATUS_NOT_SUPPORTED
;
6255 * Strip off the last component (filename) of the path passed
6258 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6260 return NT_STATUS_NO_MEMORY
;
6262 p
= strrchr_m(base_name
, '/');
6266 base_name
= talloc_strdup(ctx
, "");
6268 return NT_STATUS_NO_MEMORY
;
6271 /* Append the new name. */
6272 base_name
= talloc_asprintf_append(base_name
,
6276 return NT_STATUS_NO_MEMORY
;
6279 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6282 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6285 /* If an error we expect this to be
6286 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6288 if (!NT_STATUS_IS_OK(status
)) {
6289 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6293 /* Create an smb_fname to call rename_internals_fsp() */
6294 status
= create_synthetic_smb_fname(ctx
,
6298 if (!NT_STATUS_IS_OK(status
)) {
6305 DEBUG(10,("smb_file_rename_information: "
6306 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6307 fsp
->fnum
, fsp_str_dbg(fsp
),
6308 smb_fname_str_dbg(smb_fname_dst
)));
6309 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6312 DEBUG(10,("smb_file_rename_information: "
6313 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6314 smb_fname_str_dbg(smb_fname_src
),
6315 smb_fname_str_dbg(smb_fname_dst
)));
6316 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6317 smb_fname_dst
, 0, overwrite
, false,
6319 FILE_WRITE_ATTRIBUTES
);
6322 TALLOC_FREE(smb_fname_dst
);
6326 /****************************************************************************
6327 Deal with SMB_SET_POSIX_ACL.
6328 ****************************************************************************/
6330 #if defined(HAVE_POSIX_ACLS)
6331 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6335 const struct smb_filename
*smb_fname
)
6337 uint16 posix_acl_version
;
6338 uint16 num_file_acls
;
6339 uint16 num_def_acls
;
6340 bool valid_file_acls
= True
;
6341 bool valid_def_acls
= True
;
6343 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6344 return NT_STATUS_INVALID_PARAMETER
;
6346 posix_acl_version
= SVAL(pdata
,0);
6347 num_file_acls
= SVAL(pdata
,2);
6348 num_def_acls
= SVAL(pdata
,4);
6350 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6351 valid_file_acls
= False
;
6355 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6356 valid_def_acls
= False
;
6360 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6361 return NT_STATUS_INVALID_PARAMETER
;
6364 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6365 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6366 return NT_STATUS_INVALID_PARAMETER
;
6369 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6370 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6371 (unsigned int)num_file_acls
,
6372 (unsigned int)num_def_acls
));
6374 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6375 smb_fname
->base_name
, num_file_acls
,
6376 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6377 return map_nt_error_from_unix(errno
);
6380 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6381 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6382 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6383 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6384 return map_nt_error_from_unix(errno
);
6386 return NT_STATUS_OK
;
6390 /****************************************************************************
6391 Deal with SMB_SET_POSIX_LOCK.
6392 ****************************************************************************/
6394 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6395 struct smb_request
*req
,
6403 bool blocking_lock
= False
;
6404 enum brl_type lock_type
;
6406 NTSTATUS status
= NT_STATUS_OK
;
6408 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6409 return NT_STATUS_INVALID_HANDLE
;
6412 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6413 return NT_STATUS_INVALID_PARAMETER
;
6416 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6417 case POSIX_LOCK_TYPE_READ
:
6418 lock_type
= READ_LOCK
;
6420 case POSIX_LOCK_TYPE_WRITE
:
6421 /* Return the right POSIX-mappable error code for files opened read-only. */
6422 if (!fsp
->can_write
) {
6423 return NT_STATUS_INVALID_HANDLE
;
6425 lock_type
= WRITE_LOCK
;
6427 case POSIX_LOCK_TYPE_UNLOCK
:
6428 lock_type
= UNLOCK_LOCK
;
6431 return NT_STATUS_INVALID_PARAMETER
;
6434 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6435 blocking_lock
= False
;
6436 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6437 blocking_lock
= True
;
6439 return NT_STATUS_INVALID_PARAMETER
;
6442 if (!lp_blocking_locks(SNUM(conn
))) {
6443 blocking_lock
= False
;
6446 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6447 #if defined(HAVE_LONGLONG)
6448 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6449 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6450 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6451 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6452 #else /* HAVE_LONGLONG */
6453 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6454 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6455 #endif /* HAVE_LONGLONG */
6457 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6458 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6460 (unsigned int)lock_type
,
6461 (unsigned long long)smblctx
,
6465 if (lock_type
== UNLOCK_LOCK
) {
6466 status
= do_unlock(req
->sconn
->msg_ctx
,
6473 uint64_t block_smblctx
;
6475 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6487 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6489 * A blocking lock was requested. Package up
6490 * this smb into a queued request and push it
6491 * onto the blocking lock queue.
6493 if(push_blocking_lock_request(br_lck
,
6496 -1, /* infinite timeout. */
6504 TALLOC_FREE(br_lck
);
6508 TALLOC_FREE(br_lck
);
6514 /****************************************************************************
6515 Deal with SMB_SET_FILE_BASIC_INFO.
6516 ****************************************************************************/
6518 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6522 const struct smb_filename
*smb_fname
)
6524 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6525 struct smb_file_time ft
;
6527 NTSTATUS status
= NT_STATUS_OK
;
6531 if (total_data
< 36) {
6532 return NT_STATUS_INVALID_PARAMETER
;
6535 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6536 return NT_STATUS_ACCESS_DENIED
;
6539 /* Set the attributes */
6540 dosmode
= IVAL(pdata
,32);
6541 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6542 if (!NT_STATUS_IS_OK(status
)) {
6547 ft
.create_time
= interpret_long_date(pdata
);
6550 ft
.atime
= interpret_long_date(pdata
+8);
6553 ft
.mtime
= interpret_long_date(pdata
+16);
6556 ft
.ctime
= interpret_long_date(pdata
+24);
6558 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6559 smb_fname_str_dbg(smb_fname
)));
6561 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6565 /****************************************************************************
6566 Deal with SMB_INFO_STANDARD.
6567 ****************************************************************************/
6569 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6573 const struct smb_filename
*smb_fname
)
6575 struct smb_file_time ft
;
6579 if (total_data
< 12) {
6580 return NT_STATUS_INVALID_PARAMETER
;
6583 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6584 return NT_STATUS_ACCESS_DENIED
;
6588 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6590 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6592 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6594 DEBUG(10,("smb_set_info_standard: file %s\n",
6595 smb_fname_str_dbg(smb_fname
)));
6597 return smb_set_file_time(conn
,
6604 /****************************************************************************
6605 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6606 ****************************************************************************/
6608 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6609 struct smb_request
*req
,
6613 struct smb_filename
*smb_fname
)
6615 uint64_t allocation_size
= 0;
6616 NTSTATUS status
= NT_STATUS_OK
;
6617 files_struct
*new_fsp
= NULL
;
6619 if (!VALID_STAT(smb_fname
->st
)) {
6620 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6623 if (total_data
< 8) {
6624 return NT_STATUS_INVALID_PARAMETER
;
6627 allocation_size
= (uint64_t)IVAL(pdata
,0);
6628 #ifdef LARGE_SMB_OFF_T
6629 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6630 #else /* LARGE_SMB_OFF_T */
6631 if (IVAL(pdata
,4) != 0) {
6632 /* more than 32 bits? */
6633 return NT_STATUS_INVALID_PARAMETER
;
6635 #endif /* LARGE_SMB_OFF_T */
6637 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6638 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6639 (double)allocation_size
));
6641 if (allocation_size
) {
6642 allocation_size
= smb_roundup(conn
, allocation_size
);
6645 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6646 return NT_STATUS_ACCESS_DENIED
;
6649 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6650 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6651 (double)allocation_size
));
6653 if (fsp
&& fsp
->fh
->fd
!= -1) {
6654 /* Open file handle. */
6655 /* Only change if needed. */
6656 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6657 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6658 return map_nt_error_from_unix(errno
);
6661 /* But always update the time. */
6663 * This is equivalent to a write. Ensure it's seen immediately
6664 * if there are no pending writes.
6666 trigger_write_time_update_immediate(fsp
);
6667 return NT_STATUS_OK
;
6670 /* Pathname or stat or directory file. */
6671 status
= SMB_VFS_CREATE_FILE(
6674 0, /* root_dir_fid */
6675 smb_fname
, /* fname */
6676 FILE_WRITE_DATA
, /* access_mask */
6677 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6679 FILE_OPEN
, /* create_disposition*/
6680 0, /* create_options */
6681 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6682 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6683 0, /* allocation_size */
6684 0, /* private_flags */
6687 &new_fsp
, /* result */
6690 if (!NT_STATUS_IS_OK(status
)) {
6691 /* NB. We check for open_was_deferred in the caller. */
6695 /* Only change if needed. */
6696 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6697 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6698 status
= map_nt_error_from_unix(errno
);
6699 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6704 /* Changing the allocation size should set the last mod time. */
6706 * This is equivalent to a write. Ensure it's seen immediately
6707 * if there are no pending writes.
6709 trigger_write_time_update_immediate(new_fsp
);
6711 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6712 return NT_STATUS_OK
;
6715 /****************************************************************************
6716 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6717 ****************************************************************************/
6719 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6720 struct smb_request
*req
,
6724 const struct smb_filename
*smb_fname
,
6725 bool fail_after_createfile
)
6729 if (total_data
< 8) {
6730 return NT_STATUS_INVALID_PARAMETER
;
6733 size
= IVAL(pdata
,0);
6734 #ifdef LARGE_SMB_OFF_T
6735 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6736 #else /* LARGE_SMB_OFF_T */
6737 if (IVAL(pdata
,4) != 0) {
6738 /* more than 32 bits? */
6739 return NT_STATUS_INVALID_PARAMETER
;
6741 #endif /* LARGE_SMB_OFF_T */
6742 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6743 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6746 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6747 return NT_STATUS_ACCESS_DENIED
;
6750 return smb_set_file_size(conn
, req
,
6755 fail_after_createfile
);
6758 /****************************************************************************
6759 Allow a UNIX info mknod.
6760 ****************************************************************************/
6762 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6765 const struct smb_filename
*smb_fname
)
6767 uint32 file_type
= IVAL(pdata
,56);
6768 #if defined(HAVE_MAKEDEV)
6769 uint32 dev_major
= IVAL(pdata
,60);
6770 uint32 dev_minor
= IVAL(pdata
,68);
6772 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6773 uint32 raw_unixmode
= IVAL(pdata
,84);
6777 if (total_data
< 100) {
6778 return NT_STATUS_INVALID_PARAMETER
;
6781 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6782 PERM_NEW_FILE
, &unixmode
);
6783 if (!NT_STATUS_IS_OK(status
)) {
6787 #if defined(HAVE_MAKEDEV)
6788 dev
= makedev(dev_major
, dev_minor
);
6791 switch (file_type
) {
6792 #if defined(S_IFIFO)
6793 case UNIX_TYPE_FIFO
:
6794 unixmode
|= S_IFIFO
;
6797 #if defined(S_IFSOCK)
6798 case UNIX_TYPE_SOCKET
:
6799 unixmode
|= S_IFSOCK
;
6802 #if defined(S_IFCHR)
6803 case UNIX_TYPE_CHARDEV
:
6804 unixmode
|= S_IFCHR
;
6807 #if defined(S_IFBLK)
6808 case UNIX_TYPE_BLKDEV
:
6809 unixmode
|= S_IFBLK
;
6813 return NT_STATUS_INVALID_PARAMETER
;
6816 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6817 "%.0f mode 0%o for file %s\n", (double)dev
,
6818 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6820 /* Ok - do the mknod. */
6821 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6822 return map_nt_error_from_unix(errno
);
6825 /* If any of the other "set" calls fail we
6826 * don't want to end up with a half-constructed mknod.
6829 if (lp_inherit_perms(SNUM(conn
))) {
6831 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6833 return NT_STATUS_NO_MEMORY
;
6835 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6837 TALLOC_FREE(parent
);
6840 return NT_STATUS_OK
;
6843 /****************************************************************************
6844 Deal with SMB_SET_FILE_UNIX_BASIC.
6845 ****************************************************************************/
6847 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6848 struct smb_request
*req
,
6852 const struct smb_filename
*smb_fname
)
6854 struct smb_file_time ft
;
6855 uint32 raw_unixmode
;
6858 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6859 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6860 NTSTATUS status
= NT_STATUS_OK
;
6861 bool delete_on_fail
= False
;
6862 enum perm_type ptype
;
6863 files_struct
*all_fsps
= NULL
;
6864 bool modify_mtime
= true;
6866 struct smb_filename
*smb_fname_tmp
= NULL
;
6867 SMB_STRUCT_STAT sbuf
;
6871 if (total_data
< 100) {
6872 return NT_STATUS_INVALID_PARAMETER
;
6875 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6876 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6877 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6878 #ifdef LARGE_SMB_OFF_T
6879 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6880 #else /* LARGE_SMB_OFF_T */
6881 if (IVAL(pdata
,4) != 0) {
6882 /* more than 32 bits? */
6883 return NT_STATUS_INVALID_PARAMETER
;
6885 #endif /* LARGE_SMB_OFF_T */
6888 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6889 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6890 set_owner
= (uid_t
)IVAL(pdata
,40);
6891 set_grp
= (gid_t
)IVAL(pdata
,48);
6892 raw_unixmode
= IVAL(pdata
,84);
6894 if (VALID_STAT(smb_fname
->st
)) {
6895 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6896 ptype
= PERM_EXISTING_DIR
;
6898 ptype
= PERM_EXISTING_FILE
;
6901 ptype
= PERM_NEW_FILE
;
6904 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6906 if (!NT_STATUS_IS_OK(status
)) {
6910 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6911 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6912 smb_fname_str_dbg(smb_fname
), (double)size
,
6913 (unsigned int)set_owner
, (unsigned int)set_grp
,
6914 (int)raw_unixmode
));
6916 sbuf
= smb_fname
->st
;
6918 if (!VALID_STAT(sbuf
)) {
6920 * The only valid use of this is to create character and block
6921 * devices, and named pipes. This is deprecated (IMHO) and
6922 * a new info level should be used for mknod. JRA.
6925 status
= smb_unix_mknod(conn
,
6929 if (!NT_STATUS_IS_OK(status
)) {
6933 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6935 if (!NT_STATUS_IS_OK(status
)) {
6939 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6940 status
= map_nt_error_from_unix(errno
);
6941 TALLOC_FREE(smb_fname_tmp
);
6942 SMB_VFS_UNLINK(conn
, smb_fname
);
6946 sbuf
= smb_fname_tmp
->st
;
6947 smb_fname
= smb_fname_tmp
;
6949 /* Ensure we don't try and change anything else. */
6950 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6951 size
= get_file_size_stat(&sbuf
);
6952 ft
.atime
= sbuf
.st_ex_atime
;
6953 ft
.mtime
= sbuf
.st_ex_mtime
;
6955 * We continue here as we might want to change the
6958 delete_on_fail
= True
;
6962 /* Horrible backwards compatibility hack as an old server bug
6963 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6967 size
= get_file_size_stat(&sbuf
);
6972 * Deal with the UNIX specific mode set.
6975 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6976 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6977 "setting mode 0%o for file %s\n",
6978 (unsigned int)unixmode
,
6979 smb_fname_str_dbg(smb_fname
)));
6980 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6981 return map_nt_error_from_unix(errno
);
6986 * Deal with the UNIX specific uid set.
6989 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6990 (sbuf
.st_ex_uid
!= set_owner
)) {
6993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6994 "changing owner %u for path %s\n",
6995 (unsigned int)set_owner
,
6996 smb_fname_str_dbg(smb_fname
)));
6998 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6999 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7000 set_owner
, (gid_t
)-1);
7002 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7003 set_owner
, (gid_t
)-1);
7007 status
= map_nt_error_from_unix(errno
);
7008 if (delete_on_fail
) {
7009 SMB_VFS_UNLINK(conn
, smb_fname
);
7016 * Deal with the UNIX specific gid set.
7019 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7020 (sbuf
.st_ex_gid
!= set_grp
)) {
7021 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7022 "changing group %u for file %s\n",
7023 (unsigned int)set_owner
,
7024 smb_fname_str_dbg(smb_fname
)));
7025 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7027 status
= map_nt_error_from_unix(errno
);
7028 if (delete_on_fail
) {
7029 SMB_VFS_UNLINK(conn
, smb_fname
);
7035 /* Deal with any size changes. */
7037 status
= smb_set_file_size(conn
, req
,
7043 if (!NT_STATUS_IS_OK(status
)) {
7047 /* Deal with any time changes. */
7048 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7049 /* No change, don't cancel anything. */
7053 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7054 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7055 all_fsps
= file_find_di_next(all_fsps
)) {
7057 * We're setting the time explicitly for UNIX.
7058 * Cancel any pending changes over all handles.
7060 all_fsps
->update_write_time_on_close
= false;
7061 TALLOC_FREE(all_fsps
->update_write_time_event
);
7065 * Override the "setting_write_time"
7066 * parameter here as it almost does what
7067 * we need. Just remember if we modified
7068 * mtime and send the notify ourselves.
7070 if (null_timespec(ft
.mtime
)) {
7071 modify_mtime
= false;
7074 status
= smb_set_file_time(conn
,
7080 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7081 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7086 /****************************************************************************
7087 Deal with SMB_SET_FILE_UNIX_INFO2.
7088 ****************************************************************************/
7090 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7091 struct smb_request
*req
,
7095 const struct smb_filename
*smb_fname
)
7101 if (total_data
< 116) {
7102 return NT_STATUS_INVALID_PARAMETER
;
7105 /* Start by setting all the fields that are common between UNIX_BASIC
7108 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7110 if (!NT_STATUS_IS_OK(status
)) {
7114 smb_fflags
= IVAL(pdata
, 108);
7115 smb_fmask
= IVAL(pdata
, 112);
7117 /* NB: We should only attempt to alter the file flags if the client
7118 * sends a non-zero mask.
7120 if (smb_fmask
!= 0) {
7121 int stat_fflags
= 0;
7123 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7124 smb_fmask
, &stat_fflags
)) {
7125 /* Client asked to alter a flag we don't understand. */
7126 return NT_STATUS_INVALID_PARAMETER
;
7129 if (fsp
&& fsp
->fh
->fd
!= -1) {
7130 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7131 return NT_STATUS_NOT_SUPPORTED
;
7133 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7134 stat_fflags
) != 0) {
7135 return map_nt_error_from_unix(errno
);
7140 /* XXX: need to add support for changing the create_time here. You
7141 * can do this for paths on Darwin with setattrlist(2). The right way
7142 * to hook this up is probably by extending the VFS utimes interface.
7145 return NT_STATUS_OK
;
7148 /****************************************************************************
7149 Create a directory with POSIX semantics.
7150 ****************************************************************************/
7152 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7153 struct smb_request
*req
,
7156 struct smb_filename
*smb_fname
,
7157 int *pdata_return_size
)
7159 NTSTATUS status
= NT_STATUS_OK
;
7160 uint32 raw_unixmode
= 0;
7161 uint32 mod_unixmode
= 0;
7162 mode_t unixmode
= (mode_t
)0;
7163 files_struct
*fsp
= NULL
;
7164 uint16 info_level_return
= 0;
7166 char *pdata
= *ppdata
;
7168 if (total_data
< 18) {
7169 return NT_STATUS_INVALID_PARAMETER
;
7172 raw_unixmode
= IVAL(pdata
,8);
7173 /* Next 4 bytes are not yet defined. */
7175 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7176 PERM_NEW_DIR
, &unixmode
);
7177 if (!NT_STATUS_IS_OK(status
)) {
7181 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7183 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7184 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7186 status
= SMB_VFS_CREATE_FILE(
7189 0, /* root_dir_fid */
7190 smb_fname
, /* fname */
7191 FILE_READ_ATTRIBUTES
, /* access_mask */
7192 FILE_SHARE_NONE
, /* share_access */
7193 FILE_CREATE
, /* create_disposition*/
7194 FILE_DIRECTORY_FILE
, /* create_options */
7195 mod_unixmode
, /* file_attributes */
7196 0, /* oplock_request */
7197 0, /* allocation_size */
7198 0, /* private_flags */
7204 if (NT_STATUS_IS_OK(status
)) {
7205 close_file(req
, fsp
, NORMAL_CLOSE
);
7208 info_level_return
= SVAL(pdata
,16);
7210 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7211 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7212 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7213 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7215 *pdata_return_size
= 12;
7218 /* Realloc the data size */
7219 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7220 if (*ppdata
== NULL
) {
7221 *pdata_return_size
= 0;
7222 return NT_STATUS_NO_MEMORY
;
7226 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7227 SSVAL(pdata
,2,0); /* No fnum. */
7228 SIVAL(pdata
,4,info
); /* Was directory created. */
7230 switch (info_level_return
) {
7231 case SMB_QUERY_FILE_UNIX_BASIC
:
7232 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7233 SSVAL(pdata
,10,0); /* Padding. */
7234 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7237 case SMB_QUERY_FILE_UNIX_INFO2
:
7238 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7239 SSVAL(pdata
,10,0); /* Padding. */
7240 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7244 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7245 SSVAL(pdata
,10,0); /* Padding. */
7252 /****************************************************************************
7253 Open/Create a file with POSIX semantics.
7254 ****************************************************************************/
7256 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7257 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7259 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7260 struct smb_request
*req
,
7263 struct smb_filename
*smb_fname
,
7264 int *pdata_return_size
)
7266 bool extended_oplock_granted
= False
;
7267 char *pdata
= *ppdata
;
7269 uint32 wire_open_mode
= 0;
7270 uint32 raw_unixmode
= 0;
7271 uint32 mod_unixmode
= 0;
7272 uint32 create_disp
= 0;
7273 uint32 access_mask
= 0;
7274 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7275 NTSTATUS status
= NT_STATUS_OK
;
7276 mode_t unixmode
= (mode_t
)0;
7277 files_struct
*fsp
= NULL
;
7278 int oplock_request
= 0;
7280 uint16 info_level_return
= 0;
7282 if (total_data
< 18) {
7283 return NT_STATUS_INVALID_PARAMETER
;
7286 flags
= IVAL(pdata
,0);
7287 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7288 if (oplock_request
) {
7289 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7292 wire_open_mode
= IVAL(pdata
,4);
7294 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7295 return smb_posix_mkdir(conn
, req
,
7302 switch (wire_open_mode
& SMB_ACCMODE
) {
7304 access_mask
= SMB_O_RDONLY_MAPPING
;
7307 access_mask
= SMB_O_WRONLY_MAPPING
;
7310 access_mask
= (SMB_O_RDONLY_MAPPING
|
7311 SMB_O_WRONLY_MAPPING
);
7314 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7315 (unsigned int)wire_open_mode
));
7316 return NT_STATUS_INVALID_PARAMETER
;
7319 wire_open_mode
&= ~SMB_ACCMODE
;
7321 /* First take care of O_CREAT|O_EXCL interactions. */
7322 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7323 case (SMB_O_CREAT
| SMB_O_EXCL
):
7324 /* File exists fail. File not exist create. */
7325 create_disp
= FILE_CREATE
;
7328 /* File exists open. File not exist create. */
7329 create_disp
= FILE_OPEN_IF
;
7332 /* File exists open. File not exist fail. */
7333 create_disp
= FILE_OPEN
;
7336 /* O_EXCL on its own without O_CREAT is undefined. */
7338 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7339 (unsigned int)wire_open_mode
));
7340 return NT_STATUS_INVALID_PARAMETER
;
7343 /* Next factor in the effects of O_TRUNC. */
7344 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7346 if (wire_open_mode
& SMB_O_TRUNC
) {
7347 switch (create_disp
) {
7349 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7350 /* Leave create_disp alone as
7351 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7353 /* File exists fail. File not exist create. */
7356 /* SMB_O_CREAT | SMB_O_TRUNC */
7357 /* File exists overwrite. File not exist create. */
7358 create_disp
= FILE_OVERWRITE_IF
;
7362 /* File exists overwrite. File not exist fail. */
7363 create_disp
= FILE_OVERWRITE
;
7366 /* Cannot get here. */
7367 smb_panic("smb_posix_open: logic error");
7368 return NT_STATUS_INVALID_PARAMETER
;
7372 raw_unixmode
= IVAL(pdata
,8);
7373 /* Next 4 bytes are not yet defined. */
7375 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7376 (VALID_STAT(smb_fname
->st
) ?
7377 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7380 if (!NT_STATUS_IS_OK(status
)) {
7384 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7386 if (wire_open_mode
& SMB_O_SYNC
) {
7387 create_options
|= FILE_WRITE_THROUGH
;
7389 if (wire_open_mode
& SMB_O_APPEND
) {
7390 access_mask
|= FILE_APPEND_DATA
;
7392 if (wire_open_mode
& SMB_O_DIRECT
) {
7393 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7396 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7397 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7398 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7399 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7401 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7402 create_options
|= FILE_DIRECTORY_FILE
;
7405 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7406 smb_fname_str_dbg(smb_fname
),
7407 (unsigned int)wire_open_mode
,
7408 (unsigned int)unixmode
));
7410 status
= SMB_VFS_CREATE_FILE(
7413 0, /* root_dir_fid */
7414 smb_fname
, /* fname */
7415 access_mask
, /* access_mask */
7416 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7418 create_disp
, /* create_disposition*/
7419 create_options
, /* create_options */
7420 mod_unixmode
, /* file_attributes */
7421 oplock_request
, /* oplock_request */
7422 0, /* allocation_size */
7423 0, /* private_flags */
7429 if (!NT_STATUS_IS_OK(status
)) {
7433 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7434 extended_oplock_granted
= True
;
7437 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7438 extended_oplock_granted
= True
;
7441 info_level_return
= SVAL(pdata
,16);
7443 /* Allocate the correct return size. */
7445 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7446 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7447 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7448 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7450 *pdata_return_size
= 12;
7453 /* Realloc the data size */
7454 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7455 if (*ppdata
== NULL
) {
7456 close_file(req
, fsp
, ERROR_CLOSE
);
7457 *pdata_return_size
= 0;
7458 return NT_STATUS_NO_MEMORY
;
7462 if (extended_oplock_granted
) {
7463 if (flags
& REQUEST_BATCH_OPLOCK
) {
7464 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7466 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7468 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7469 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7471 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7474 SSVAL(pdata
,2,fsp
->fnum
);
7475 SIVAL(pdata
,4,info
); /* Was file created etc. */
7477 switch (info_level_return
) {
7478 case SMB_QUERY_FILE_UNIX_BASIC
:
7479 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7480 SSVAL(pdata
,10,0); /* padding. */
7481 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7484 case SMB_QUERY_FILE_UNIX_INFO2
:
7485 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7486 SSVAL(pdata
,10,0); /* padding. */
7487 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7491 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7492 SSVAL(pdata
,10,0); /* padding. */
7495 return NT_STATUS_OK
;
7498 /****************************************************************************
7499 Delete a file with POSIX semantics.
7500 ****************************************************************************/
7502 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7503 struct smb_request
*req
,
7506 struct smb_filename
*smb_fname
)
7508 NTSTATUS status
= NT_STATUS_OK
;
7509 files_struct
*fsp
= NULL
;
7513 int create_options
= 0;
7515 struct share_mode_lock
*lck
= NULL
;
7517 if (total_data
< 2) {
7518 return NT_STATUS_INVALID_PARAMETER
;
7521 flags
= SVAL(pdata
,0);
7523 if (!VALID_STAT(smb_fname
->st
)) {
7524 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7527 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7528 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7529 return NT_STATUS_NOT_A_DIRECTORY
;
7532 DEBUG(10,("smb_posix_unlink: %s %s\n",
7533 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7534 smb_fname_str_dbg(smb_fname
)));
7536 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7537 create_options
|= FILE_DIRECTORY_FILE
;
7540 status
= SMB_VFS_CREATE_FILE(
7543 0, /* root_dir_fid */
7544 smb_fname
, /* fname */
7545 DELETE_ACCESS
, /* access_mask */
7546 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7548 FILE_OPEN
, /* create_disposition*/
7549 create_options
, /* create_options */
7550 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7551 0, /* oplock_request */
7552 0, /* allocation_size */
7553 0, /* private_flags */
7559 if (!NT_STATUS_IS_OK(status
)) {
7564 * Don't lie to client. If we can't really delete due to
7565 * non-POSIX opens return SHARING_VIOLATION.
7568 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7571 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7572 "lock for file %s\n", fsp_str_dbg(fsp
)));
7573 close_file(req
, fsp
, NORMAL_CLOSE
);
7574 return NT_STATUS_INVALID_PARAMETER
;
7578 * See if others still have the file open. If this is the case, then
7579 * don't delete. If all opens are POSIX delete we can set the delete
7580 * on close disposition.
7582 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7583 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7584 if (is_valid_share_mode_entry(e
)) {
7585 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7588 /* Fail with sharing violation. */
7589 close_file(req
, fsp
, NORMAL_CLOSE
);
7591 return NT_STATUS_SHARING_VIOLATION
;
7596 * Set the delete on close.
7598 status
= smb_set_file_disposition_info(conn
,
7604 if (!NT_STATUS_IS_OK(status
)) {
7605 close_file(req
, fsp
, NORMAL_CLOSE
);
7610 return close_file(req
, fsp
, NORMAL_CLOSE
);
7613 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7614 struct smb_request
*req
,
7615 TALLOC_CTX
*mem_ctx
,
7616 uint16_t info_level
,
7618 struct smb_filename
*smb_fname
,
7619 char **ppdata
, int total_data
,
7622 char *pdata
= *ppdata
;
7623 NTSTATUS status
= NT_STATUS_OK
;
7624 int data_return_size
= 0;
7628 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7629 return NT_STATUS_INVALID_LEVEL
;
7632 if (!CAN_WRITE(conn
)) {
7633 /* Allow POSIX opens. The open path will deny
7634 * any non-readonly opens. */
7635 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7636 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7640 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7641 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7642 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7644 switch (info_level
) {
7646 case SMB_INFO_STANDARD
:
7648 status
= smb_set_info_standard(conn
,
7656 case SMB_INFO_SET_EA
:
7658 status
= smb_info_set_ea(conn
,
7666 case SMB_SET_FILE_BASIC_INFO
:
7667 case SMB_FILE_BASIC_INFORMATION
:
7669 status
= smb_set_file_basic_info(conn
,
7677 case SMB_FILE_ALLOCATION_INFORMATION
:
7678 case SMB_SET_FILE_ALLOCATION_INFO
:
7680 status
= smb_set_file_allocation_info(conn
, req
,
7688 case SMB_FILE_END_OF_FILE_INFORMATION
:
7689 case SMB_SET_FILE_END_OF_FILE_INFO
:
7692 * XP/Win7 both fail after the createfile with
7693 * SMB_SET_FILE_END_OF_FILE_INFO but not
7694 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7695 * The level is known here, so pass it down
7699 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7701 status
= smb_set_file_end_of_file_info(conn
, req
,
7710 case SMB_FILE_DISPOSITION_INFORMATION
:
7711 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7714 /* JRA - We used to just ignore this on a path ?
7715 * Shouldn't this be invalid level on a pathname
7718 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7719 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7722 status
= smb_set_file_disposition_info(conn
,
7730 case SMB_FILE_POSITION_INFORMATION
:
7732 status
= smb_file_position_information(conn
,
7739 case SMB_FILE_FULL_EA_INFORMATION
:
7741 status
= smb_set_file_full_ea_info(conn
,
7748 /* From tridge Samba4 :
7749 * MODE_INFORMATION in setfileinfo (I have no
7750 * idea what "mode information" on a file is - it takes a value of 0,
7751 * 2, 4 or 6. What could it be?).
7754 case SMB_FILE_MODE_INFORMATION
:
7756 status
= smb_file_mode_information(conn
,
7763 * CIFS UNIX extensions.
7766 case SMB_SET_FILE_UNIX_BASIC
:
7768 status
= smb_set_file_unix_basic(conn
, req
,
7776 case SMB_SET_FILE_UNIX_INFO2
:
7778 status
= smb_set_file_unix_info2(conn
, req
,
7786 case SMB_SET_FILE_UNIX_LINK
:
7789 /* We must have a pathname for this. */
7790 return NT_STATUS_INVALID_LEVEL
;
7792 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7793 total_data
, smb_fname
);
7797 case SMB_SET_FILE_UNIX_HLINK
:
7800 /* We must have a pathname for this. */
7801 return NT_STATUS_INVALID_LEVEL
;
7803 status
= smb_set_file_unix_hlink(conn
, req
,
7809 case SMB_FILE_RENAME_INFORMATION
:
7811 status
= smb_file_rename_information(conn
, req
,
7817 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7819 /* SMB2 rename information. */
7820 status
= smb2_file_rename_information(conn
, req
,
7826 case SMB_FILE_LINK_INFORMATION
:
7828 status
= smb_file_link_information(conn
, req
,
7834 #if defined(HAVE_POSIX_ACLS)
7835 case SMB_SET_POSIX_ACL
:
7837 status
= smb_set_posix_acl(conn
,
7846 case SMB_SET_POSIX_LOCK
:
7849 return NT_STATUS_INVALID_LEVEL
;
7851 status
= smb_set_posix_lock(conn
, req
,
7852 pdata
, total_data
, fsp
);
7856 case SMB_POSIX_PATH_OPEN
:
7859 /* We must have a pathname for this. */
7860 return NT_STATUS_INVALID_LEVEL
;
7863 status
= smb_posix_open(conn
, req
,
7871 case SMB_POSIX_PATH_UNLINK
:
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL
;
7878 status
= smb_posix_unlink(conn
, req
,
7886 return NT_STATUS_INVALID_LEVEL
;
7889 if (!NT_STATUS_IS_OK(status
)) {
7893 *ret_data_size
= data_return_size
;
7894 return NT_STATUS_OK
;
7897 /****************************************************************************
7898 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7899 ****************************************************************************/
7901 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7902 struct smb_request
*req
,
7903 unsigned int tran_call
,
7904 char **pparams
, int total_params
,
7905 char **ppdata
, int total_data
,
7906 unsigned int max_data_bytes
)
7908 char *params
= *pparams
;
7909 char *pdata
= *ppdata
;
7911 struct smb_filename
*smb_fname
= NULL
;
7912 files_struct
*fsp
= NULL
;
7913 NTSTATUS status
= NT_STATUS_OK
;
7914 int data_return_size
= 0;
7917 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7921 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7922 if (total_params
< 4) {
7923 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7927 fsp
= file_fsp(req
, SVAL(params
,0));
7928 /* Basic check for non-null fsp. */
7929 if (!check_fsp_open(conn
, req
, fsp
)) {
7932 info_level
= SVAL(params
,2);
7934 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7936 if (!NT_STATUS_IS_OK(status
)) {
7937 reply_nterror(req
, status
);
7941 if(fsp
->fh
->fd
== -1) {
7943 * This is actually a SETFILEINFO on a directory
7944 * handle (returned from an NT SMB). NT5.0 seems
7945 * to do this call. JRA.
7947 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7948 /* Always do lstat for UNIX calls. */
7949 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7950 DEBUG(3,("call_trans2setfilepathinfo: "
7951 "SMB_VFS_LSTAT of %s failed "
7953 smb_fname_str_dbg(smb_fname
),
7955 reply_nterror(req
, map_nt_error_from_unix(errno
));
7959 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7960 DEBUG(3,("call_trans2setfilepathinfo: "
7961 "fileinfo of %s failed (%s)\n",
7962 smb_fname_str_dbg(smb_fname
),
7964 reply_nterror(req
, map_nt_error_from_unix(errno
));
7968 } else if (fsp
->print_file
) {
7970 * Doing a DELETE_ON_CLOSE should cancel a print job.
7972 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7973 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7975 DEBUG(3,("call_trans2setfilepathinfo: "
7976 "Cancelling print job (%s)\n",
7980 send_trans2_replies(conn
, req
, params
, 2,
7986 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7991 * Original code - this is an open file.
7993 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7994 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7995 "of fnum %d failed (%s)\n", fsp
->fnum
,
7997 reply_nterror(req
, map_nt_error_from_unix(errno
));
8003 uint32_t ucf_flags
= 0;
8006 if (total_params
< 7) {
8007 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8011 info_level
= SVAL(params
,0);
8012 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8013 total_params
- 6, STR_TERMINATE
,
8015 if (!NT_STATUS_IS_OK(status
)) {
8016 reply_nterror(req
, status
);
8020 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8021 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8022 info_level
== SMB_FILE_RENAME_INFORMATION
||
8023 info_level
== SMB_POSIX_PATH_UNLINK
) {
8024 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8027 status
= filename_convert(req
, conn
,
8028 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8033 if (!NT_STATUS_IS_OK(status
)) {
8034 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8035 reply_botherror(req
,
8036 NT_STATUS_PATH_NOT_COVERED
,
8037 ERRSRV
, ERRbadpath
);
8040 reply_nterror(req
, status
);
8044 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8046 * For CIFS UNIX extensions the target name may not exist.
8049 /* Always do lstat for UNIX calls. */
8050 SMB_VFS_LSTAT(conn
, smb_fname
);
8052 } else if (!VALID_STAT(smb_fname
->st
) &&
8053 SMB_VFS_STAT(conn
, smb_fname
)) {
8054 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8056 smb_fname_str_dbg(smb_fname
),
8058 reply_nterror(req
, map_nt_error_from_unix(errno
));
8063 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8064 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8065 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8067 /* Realloc the parameter size */
8068 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8069 if (*pparams
== NULL
) {
8070 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8077 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8083 if (!NT_STATUS_IS_OK(status
)) {
8084 if (open_was_deferred(req
->mid
)) {
8085 /* We have re-scheduled this call. */
8088 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8089 /* We have re-scheduled this call. */
8092 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8093 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8094 ERRSRV
, ERRbadpath
);
8097 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8098 reply_openerror(req
, status
);
8102 reply_nterror(req
, status
);
8106 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8112 /****************************************************************************
8113 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8114 ****************************************************************************/
8116 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8117 char **pparams
, int total_params
,
8118 char **ppdata
, int total_data
,
8119 unsigned int max_data_bytes
)
8121 struct smb_filename
*smb_dname
= NULL
;
8122 char *params
= *pparams
;
8123 char *pdata
= *ppdata
;
8124 char *directory
= NULL
;
8125 NTSTATUS status
= NT_STATUS_OK
;
8126 struct ea_list
*ea_list
= NULL
;
8127 TALLOC_CTX
*ctx
= talloc_tos();
8129 if (!CAN_WRITE(conn
)) {
8130 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8134 if (total_params
< 5) {
8135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8139 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8140 total_params
- 4, STR_TERMINATE
,
8142 if (!NT_STATUS_IS_OK(status
)) {
8143 reply_nterror(req
, status
);
8147 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8149 status
= filename_convert(ctx
,
8151 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8157 if (!NT_STATUS_IS_OK(status
)) {
8158 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8159 reply_botherror(req
,
8160 NT_STATUS_PATH_NOT_COVERED
,
8161 ERRSRV
, ERRbadpath
);
8164 reply_nterror(req
, status
);
8169 * OS/2 workplace shell seems to send SET_EA requests of "null"
8170 * length (4 bytes containing IVAL 4).
8171 * They seem to have no effect. Bug #3212. JRA.
8174 if (total_data
&& (total_data
!= 4)) {
8175 /* Any data in this call is an EA list. */
8176 if (total_data
< 10) {
8177 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8181 if (IVAL(pdata
,0) > total_data
) {
8182 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8183 IVAL(pdata
,0), (unsigned int)total_data
));
8184 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8188 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8191 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8195 if (!lp_ea_support(SNUM(conn
))) {
8196 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8200 /* If total_data == 4 Windows doesn't care what values
8201 * are placed in that field, it just ignores them.
8202 * The System i QNTC IBM SMB client puts bad values here,
8203 * so ignore them. */
8205 status
= create_directory(conn
, req
, smb_dname
);
8207 if (!NT_STATUS_IS_OK(status
)) {
8208 reply_nterror(req
, status
);
8212 /* Try and set any given EA. */
8214 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8215 if (!NT_STATUS_IS_OK(status
)) {
8216 reply_nterror(req
, status
);
8221 /* Realloc the parameter and data sizes */
8222 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8223 if(*pparams
== NULL
) {
8224 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8231 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8234 TALLOC_FREE(smb_dname
);
8238 /****************************************************************************
8239 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8240 We don't actually do this - we just send a null response.
8241 ****************************************************************************/
8243 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8244 struct smb_request
*req
,
8245 char **pparams
, int total_params
,
8246 char **ppdata
, int total_data
,
8247 unsigned int max_data_bytes
)
8249 char *params
= *pparams
;
8252 if (total_params
< 6) {
8253 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8257 info_level
= SVAL(params
,4);
8258 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8260 switch (info_level
) {
8265 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8269 /* Realloc the parameter and data sizes */
8270 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8271 if (*pparams
== NULL
) {
8272 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8277 SSVAL(params
,0,fnf_handle
);
8278 SSVAL(params
,2,0); /* No changes */
8279 SSVAL(params
,4,0); /* No EA errors */
8286 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8291 /****************************************************************************
8292 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8293 changes). Currently this does nothing.
8294 ****************************************************************************/
8296 static void call_trans2findnotifynext(connection_struct
*conn
,
8297 struct smb_request
*req
,
8298 char **pparams
, int total_params
,
8299 char **ppdata
, int total_data
,
8300 unsigned int max_data_bytes
)
8302 char *params
= *pparams
;
8304 DEBUG(3,("call_trans2findnotifynext\n"));
8306 /* Realloc the parameter and data sizes */
8307 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8308 if (*pparams
== NULL
) {
8309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8314 SSVAL(params
,0,0); /* No changes */
8315 SSVAL(params
,2,0); /* No EA errors */
8317 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8322 /****************************************************************************
8323 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8324 ****************************************************************************/
8326 static void call_trans2getdfsreferral(connection_struct
*conn
,
8327 struct smb_request
*req
,
8328 char **pparams
, int total_params
,
8329 char **ppdata
, int total_data
,
8330 unsigned int max_data_bytes
)
8332 char *params
= *pparams
;
8333 char *pathname
= NULL
;
8335 int max_referral_level
;
8336 NTSTATUS status
= NT_STATUS_OK
;
8337 TALLOC_CTX
*ctx
= talloc_tos();
8339 DEBUG(10,("call_trans2getdfsreferral\n"));
8341 if (total_params
< 3) {
8342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8346 max_referral_level
= SVAL(params
,0);
8348 if(!lp_host_msdfs()) {
8349 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8353 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8354 total_params
- 2, STR_TERMINATE
);
8356 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8359 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8360 ppdata
,&status
)) < 0) {
8361 reply_nterror(req
, status
);
8365 SSVAL(req
->inbuf
, smb_flg2
,
8366 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8367 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8372 #define LMCAT_SPL 0x53
8373 #define LMFUNC_GETJOBID 0x60
8375 /****************************************************************************
8376 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8377 ****************************************************************************/
8379 static void call_trans2ioctl(connection_struct
*conn
,
8380 struct smb_request
*req
,
8381 char **pparams
, int total_params
,
8382 char **ppdata
, int total_data
,
8383 unsigned int max_data_bytes
)
8385 char *pdata
= *ppdata
;
8386 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8388 /* check for an invalid fid before proceeding */
8391 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8395 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8396 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8397 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8398 if (*ppdata
== NULL
) {
8399 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8404 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8405 CAN ACCEPT THIS IN UNICODE. JRA. */
8408 if (fsp
->print_file
) {
8409 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8413 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8414 global_myname(), 15,
8415 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8416 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8417 lp_servicename(SNUM(conn
)), 13,
8418 STR_ASCII
|STR_TERMINATE
); /* Service name */
8419 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8424 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8425 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8428 /****************************************************************************
8429 Reply to a SMBfindclose (stop trans2 directory search).
8430 ****************************************************************************/
8432 void reply_findclose(struct smb_request
*req
)
8435 struct smbd_server_connection
*sconn
= req
->sconn
;
8437 START_PROFILE(SMBfindclose
);
8440 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8441 END_PROFILE(SMBfindclose
);
8445 dptr_num
= SVALS(req
->vwv
+0, 0);
8447 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8449 dptr_close(sconn
, &dptr_num
);
8451 reply_outbuf(req
, 0, 0);
8453 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8455 END_PROFILE(SMBfindclose
);
8459 /****************************************************************************
8460 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8461 ****************************************************************************/
8463 void reply_findnclose(struct smb_request
*req
)
8467 START_PROFILE(SMBfindnclose
);
8470 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8471 END_PROFILE(SMBfindnclose
);
8475 dptr_num
= SVAL(req
->vwv
+0, 0);
8477 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8479 /* We never give out valid handles for a
8480 findnotifyfirst - so any dptr_num is ok here.
8483 reply_outbuf(req
, 0, 0);
8485 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8487 END_PROFILE(SMBfindnclose
);
8491 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8492 struct trans_state
*state
)
8494 if (get_Protocol() >= PROTOCOL_NT1
) {
8495 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8496 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8499 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8500 if (state
->call
!= TRANSACT2_QFSINFO
&&
8501 state
->call
!= TRANSACT2_SETFSINFO
) {
8502 DEBUG(0,("handle_trans2: encryption required "
8504 (unsigned int)state
->call
));
8505 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8510 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8512 /* Now we must call the relevant TRANS2 function */
8513 switch(state
->call
) {
8514 case TRANSACT2_OPEN
:
8516 START_PROFILE(Trans2_open
);
8517 call_trans2open(conn
, req
,
8518 &state
->param
, state
->total_param
,
8519 &state
->data
, state
->total_data
,
8520 state
->max_data_return
);
8521 END_PROFILE(Trans2_open
);
8525 case TRANSACT2_FINDFIRST
:
8527 START_PROFILE(Trans2_findfirst
);
8528 call_trans2findfirst(conn
, req
,
8529 &state
->param
, state
->total_param
,
8530 &state
->data
, state
->total_data
,
8531 state
->max_data_return
);
8532 END_PROFILE(Trans2_findfirst
);
8536 case TRANSACT2_FINDNEXT
:
8538 START_PROFILE(Trans2_findnext
);
8539 call_trans2findnext(conn
, req
,
8540 &state
->param
, state
->total_param
,
8541 &state
->data
, state
->total_data
,
8542 state
->max_data_return
);
8543 END_PROFILE(Trans2_findnext
);
8547 case TRANSACT2_QFSINFO
:
8549 START_PROFILE(Trans2_qfsinfo
);
8550 call_trans2qfsinfo(conn
, req
,
8551 &state
->param
, state
->total_param
,
8552 &state
->data
, state
->total_data
,
8553 state
->max_data_return
);
8554 END_PROFILE(Trans2_qfsinfo
);
8558 case TRANSACT2_SETFSINFO
:
8560 START_PROFILE(Trans2_setfsinfo
);
8561 call_trans2setfsinfo(conn
, req
,
8562 &state
->param
, state
->total_param
,
8563 &state
->data
, state
->total_data
,
8564 state
->max_data_return
);
8565 END_PROFILE(Trans2_setfsinfo
);
8569 case TRANSACT2_QPATHINFO
:
8570 case TRANSACT2_QFILEINFO
:
8572 START_PROFILE(Trans2_qpathinfo
);
8573 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8574 &state
->param
, state
->total_param
,
8575 &state
->data
, state
->total_data
,
8576 state
->max_data_return
);
8577 END_PROFILE(Trans2_qpathinfo
);
8581 case TRANSACT2_SETPATHINFO
:
8582 case TRANSACT2_SETFILEINFO
:
8584 START_PROFILE(Trans2_setpathinfo
);
8585 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8586 &state
->param
, state
->total_param
,
8587 &state
->data
, state
->total_data
,
8588 state
->max_data_return
);
8589 END_PROFILE(Trans2_setpathinfo
);
8593 case TRANSACT2_FINDNOTIFYFIRST
:
8595 START_PROFILE(Trans2_findnotifyfirst
);
8596 call_trans2findnotifyfirst(conn
, req
,
8597 &state
->param
, state
->total_param
,
8598 &state
->data
, state
->total_data
,
8599 state
->max_data_return
);
8600 END_PROFILE(Trans2_findnotifyfirst
);
8604 case TRANSACT2_FINDNOTIFYNEXT
:
8606 START_PROFILE(Trans2_findnotifynext
);
8607 call_trans2findnotifynext(conn
, req
,
8608 &state
->param
, state
->total_param
,
8609 &state
->data
, state
->total_data
,
8610 state
->max_data_return
);
8611 END_PROFILE(Trans2_findnotifynext
);
8615 case TRANSACT2_MKDIR
:
8617 START_PROFILE(Trans2_mkdir
);
8618 call_trans2mkdir(conn
, req
,
8619 &state
->param
, state
->total_param
,
8620 &state
->data
, state
->total_data
,
8621 state
->max_data_return
);
8622 END_PROFILE(Trans2_mkdir
);
8626 case TRANSACT2_GET_DFS_REFERRAL
:
8628 START_PROFILE(Trans2_get_dfs_referral
);
8629 call_trans2getdfsreferral(conn
, req
,
8630 &state
->param
, state
->total_param
,
8631 &state
->data
, state
->total_data
,
8632 state
->max_data_return
);
8633 END_PROFILE(Trans2_get_dfs_referral
);
8637 case TRANSACT2_IOCTL
:
8639 START_PROFILE(Trans2_ioctl
);
8640 call_trans2ioctl(conn
, req
,
8641 &state
->param
, state
->total_param
,
8642 &state
->data
, state
->total_data
,
8643 state
->max_data_return
);
8644 END_PROFILE(Trans2_ioctl
);
8649 /* Error in request */
8650 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8651 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8655 /****************************************************************************
8656 Reply to a SMBtrans2.
8657 ****************************************************************************/
8659 void reply_trans2(struct smb_request
*req
)
8661 connection_struct
*conn
= req
->conn
;
8666 unsigned int tran_call
;
8667 struct trans_state
*state
;
8670 START_PROFILE(SMBtrans2
);
8672 if (req
->wct
< 14) {
8673 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8674 END_PROFILE(SMBtrans2
);
8678 dsoff
= SVAL(req
->vwv
+12, 0);
8679 dscnt
= SVAL(req
->vwv
+11, 0);
8680 psoff
= SVAL(req
->vwv
+10, 0);
8681 pscnt
= SVAL(req
->vwv
+9, 0);
8682 tran_call
= SVAL(req
->vwv
+14, 0);
8684 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8685 if (!NT_STATUS_IS_OK(result
)) {
8686 DEBUG(2, ("Got invalid trans2 request: %s\n",
8687 nt_errstr(result
)));
8688 reply_nterror(req
, result
);
8689 END_PROFILE(SMBtrans2
);
8694 switch (tran_call
) {
8695 /* List the allowed trans2 calls on IPC$ */
8696 case TRANSACT2_OPEN
:
8697 case TRANSACT2_GET_DFS_REFERRAL
:
8698 case TRANSACT2_QFILEINFO
:
8699 case TRANSACT2_QFSINFO
:
8700 case TRANSACT2_SETFSINFO
:
8703 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8704 END_PROFILE(SMBtrans2
);
8709 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8710 DEBUG(0, ("talloc failed\n"));
8711 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8712 END_PROFILE(SMBtrans2
);
8716 state
->cmd
= SMBtrans2
;
8718 state
->mid
= req
->mid
;
8719 state
->vuid
= req
->vuid
;
8720 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8721 state
->setup
= NULL
;
8722 state
->total_param
= SVAL(req
->vwv
+0, 0);
8723 state
->param
= NULL
;
8724 state
->total_data
= SVAL(req
->vwv
+1, 0);
8726 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8727 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8728 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8729 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8730 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8732 state
->call
= tran_call
;
8734 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8735 is so as a sanity check */
8736 if (state
->setup_count
!= 1) {
8738 * Need to have rc=0 for ioctl to get job id for OS/2.
8739 * Network printing will fail if function is not successful.
8740 * Similar function in reply.c will be used if protocol
8741 * is LANMAN1.0 instead of LM1.2X002.
8742 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8743 * outbuf doesn't have to be set(only job id is used).
8745 if ( (state
->setup_count
== 4)
8746 && (tran_call
== TRANSACT2_IOCTL
)
8747 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8748 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8749 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8751 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8752 DEBUG(2,("Transaction is %d\n",tran_call
));
8754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8755 END_PROFILE(SMBtrans2
);
8760 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8763 if (state
->total_data
) {
8765 if (trans_oob(state
->total_data
, 0, dscnt
)
8766 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8770 /* Can't use talloc here, the core routines do realloc on the
8771 * params and data. */
8772 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8773 if (state
->data
== NULL
) {
8774 DEBUG(0,("reply_trans2: data malloc fail for %u "
8775 "bytes !\n", (unsigned int)state
->total_data
));
8777 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8778 END_PROFILE(SMBtrans2
);
8782 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8785 if (state
->total_param
) {
8787 if (trans_oob(state
->total_param
, 0, pscnt
)
8788 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8792 /* Can't use talloc here, the core routines do realloc on the
8793 * params and data. */
8794 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8795 if (state
->param
== NULL
) {
8796 DEBUG(0,("reply_trans: param malloc fail for %u "
8797 "bytes !\n", (unsigned int)state
->total_param
));
8798 SAFE_FREE(state
->data
);
8800 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8801 END_PROFILE(SMBtrans2
);
8805 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8808 state
->received_data
= dscnt
;
8809 state
->received_param
= pscnt
;
8811 if ((state
->received_param
== state
->total_param
) &&
8812 (state
->received_data
== state
->total_data
)) {
8814 handle_trans2(conn
, req
, state
);
8816 SAFE_FREE(state
->data
);
8817 SAFE_FREE(state
->param
);
8819 END_PROFILE(SMBtrans2
);
8823 DLIST_ADD(conn
->pending_trans
, state
);
8825 /* We need to send an interim response then receive the rest
8826 of the parameter/data bytes */
8827 reply_outbuf(req
, 0, 0);
8828 show_msg((char *)req
->outbuf
);
8829 END_PROFILE(SMBtrans2
);
8834 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8835 SAFE_FREE(state
->data
);
8836 SAFE_FREE(state
->param
);
8838 END_PROFILE(SMBtrans2
);
8839 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8843 /****************************************************************************
8844 Reply to a SMBtranss2
8845 ****************************************************************************/
8847 void reply_transs2(struct smb_request
*req
)
8849 connection_struct
*conn
= req
->conn
;
8850 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8851 struct trans_state
*state
;
8853 START_PROFILE(SMBtranss2
);
8855 show_msg((char *)req
->inbuf
);
8857 /* Windows clients expect all replies to
8858 a transact secondary (SMBtranss2 0x33)
8859 to have a command code of transact
8860 (SMBtrans2 0x32). See bug #8989
8861 and also [MS-CIFS] section 2.2.4.47.2
8864 req
->cmd
= SMBtrans2
;
8867 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8868 END_PROFILE(SMBtranss2
);
8872 for (state
= conn
->pending_trans
; state
!= NULL
;
8873 state
= state
->next
) {
8874 if (state
->mid
== req
->mid
) {
8879 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8880 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8881 END_PROFILE(SMBtranss2
);
8885 /* Revise state->total_param and state->total_data in case they have
8886 changed downwards */
8888 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8889 state
->total_param
= SVAL(req
->vwv
+0, 0);
8890 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8891 state
->total_data
= SVAL(req
->vwv
+1, 0);
8893 pcnt
= SVAL(req
->vwv
+2, 0);
8894 poff
= SVAL(req
->vwv
+3, 0);
8895 pdisp
= SVAL(req
->vwv
+4, 0);
8897 dcnt
= SVAL(req
->vwv
+5, 0);
8898 doff
= SVAL(req
->vwv
+6, 0);
8899 ddisp
= SVAL(req
->vwv
+7, 0);
8901 state
->received_param
+= pcnt
;
8902 state
->received_data
+= dcnt
;
8904 if ((state
->received_data
> state
->total_data
) ||
8905 (state
->received_param
> state
->total_param
))
8909 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8910 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8913 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8917 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8918 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8921 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8924 if ((state
->received_param
< state
->total_param
) ||
8925 (state
->received_data
< state
->total_data
)) {
8926 END_PROFILE(SMBtranss2
);
8930 handle_trans2(conn
, req
, state
);
8932 DLIST_REMOVE(conn
->pending_trans
, state
);
8933 SAFE_FREE(state
->data
);
8934 SAFE_FREE(state
->param
);
8937 END_PROFILE(SMBtranss2
);
8942 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8943 DLIST_REMOVE(conn
->pending_trans
, state
);
8944 SAFE_FREE(state
->data
);
8945 SAFE_FREE(state
->param
);
8947 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8948 END_PROFILE(SMBtranss2
);