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
);
867 * We might have SMBtrans2s in req which was transferred to
868 * the outbuf, fix that.
870 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
872 /* Set total params and data to be sent */
873 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
874 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
876 /* Calculate how many parameters and data we can fit into
877 * this packet. Parameters get precedence
880 params_sent_thistime
= MIN(params_to_send
,useable_space
);
881 data_sent_thistime
= useable_space
- params_sent_thistime
;
882 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
884 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
886 /* smb_proff is the offset from the start of the SMB header to the
887 parameter bytes, however the first 4 bytes of outbuf are
888 the Netbios over TCP header. Thus use smb_base() to subtract
889 them from the calculation */
891 SSVAL(req
->outbuf
,smb_proff
,
892 ((smb_buf(req
->outbuf
)+alignment_offset
)
893 - smb_base(req
->outbuf
)));
895 if(params_sent_thistime
== 0)
896 SSVAL(req
->outbuf
,smb_prdisp
,0);
898 /* Absolute displacement of param bytes sent in this packet */
899 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
901 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
902 if(data_sent_thistime
== 0) {
903 SSVAL(req
->outbuf
,smb_droff
,0);
904 SSVAL(req
->outbuf
,smb_drdisp
, 0);
906 /* The offset of the data bytes is the offset of the
907 parameter bytes plus the number of parameters being sent this time */
908 SSVAL(req
->outbuf
, smb_droff
,
909 ((smb_buf(req
->outbuf
)+alignment_offset
)
910 - smb_base(req
->outbuf
))
911 + params_sent_thistime
+ data_alignment_offset
);
912 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
915 /* Initialize the padding for alignment */
917 if (alignment_offset
!= 0) {
918 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
921 /* Copy the param bytes into the packet */
923 if(params_sent_thistime
) {
924 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
925 params_sent_thistime
);
928 /* Copy in the data bytes */
929 if(data_sent_thistime
) {
930 if (data_alignment_offset
!= 0) {
931 memset((smb_buf(req
->outbuf
)+alignment_offset
+
932 params_sent_thistime
), 0,
933 data_alignment_offset
);
935 memcpy(smb_buf(req
->outbuf
)+alignment_offset
936 +params_sent_thistime
+data_alignment_offset
,
937 pd
,data_sent_thistime
);
940 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
941 params_sent_thistime
, data_sent_thistime
, useable_space
));
942 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
943 params_to_send
, data_to_send
, paramsize
, datasize
));
946 error_packet_set((char *)req
->outbuf
,
947 ERRDOS
,ERRbufferoverflow
,
948 STATUS_BUFFER_OVERFLOW
,
952 /* Send the packet */
953 show_msg((char *)req
->outbuf
);
954 if (!srv_send_smb(sconn
,
957 IS_CONN_ENCRYPTED(conn
),
959 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
961 TALLOC_FREE(req
->outbuf
);
963 pp
+= params_sent_thistime
;
964 pd
+= data_sent_thistime
;
966 params_to_send
-= params_sent_thistime
;
967 data_to_send
-= data_sent_thistime
;
970 if(params_to_send
< 0 || data_to_send
< 0) {
971 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
972 params_to_send
, data_to_send
));
980 /****************************************************************************
981 Reply to a TRANSACT2_OPEN.
982 ****************************************************************************/
984 static void call_trans2open(connection_struct
*conn
,
985 struct smb_request
*req
,
986 char **pparams
, int total_params
,
987 char **ppdata
, int total_data
,
988 unsigned int max_data_bytes
)
990 struct smb_filename
*smb_fname
= NULL
;
991 char *params
= *pparams
;
992 char *pdata
= *ppdata
;
997 bool return_additional_info
;
1006 int fattr
=0,mtime
=0;
1007 SMB_INO_T inode
= 0;
1010 struct ea_list
*ea_list
= NULL
;
1015 uint32 create_disposition
;
1016 uint32 create_options
= 0;
1017 uint32_t private_flags
= 0;
1018 TALLOC_CTX
*ctx
= talloc_tos();
1021 * Ensure we have enough parameters to perform the operation.
1024 if (total_params
< 29) {
1025 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1029 flags
= SVAL(params
, 0);
1030 deny_mode
= SVAL(params
, 2);
1031 open_attr
= SVAL(params
,6);
1032 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1033 if (oplock_request
) {
1034 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1038 return_additional_info
= BITSETW(params
,0);
1039 open_sattr
= SVAL(params
, 4);
1040 open_time
= make_unix_date3(params
+8);
1042 open_ofun
= SVAL(params
,12);
1043 open_size
= IVAL(params
,14);
1044 pname
= ¶ms
[28];
1047 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1051 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1052 total_params
- 28, STR_TERMINATE
,
1054 if (!NT_STATUS_IS_OK(status
)) {
1055 reply_nterror(req
, status
);
1059 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1060 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1061 (unsigned int)open_ofun
, open_size
));
1063 status
= filename_convert(ctx
,
1065 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1070 if (!NT_STATUS_IS_OK(status
)) {
1071 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1072 reply_botherror(req
,
1073 NT_STATUS_PATH_NOT_COVERED
,
1074 ERRSRV
, ERRbadpath
);
1077 reply_nterror(req
, status
);
1081 if (open_ofun
== 0) {
1082 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1086 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1088 &access_mask
, &share_mode
,
1089 &create_disposition
,
1092 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1096 /* Any data in this call is an EA list. */
1097 if (total_data
&& (total_data
!= 4)) {
1098 if (total_data
< 10) {
1099 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1103 if (IVAL(pdata
,0) > total_data
) {
1104 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1105 IVAL(pdata
,0), (unsigned int)total_data
));
1106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1110 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1113 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1117 if (!lp_ea_support(SNUM(conn
))) {
1118 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1123 status
= SMB_VFS_CREATE_FILE(
1126 0, /* root_dir_fid */
1127 smb_fname
, /* fname */
1128 access_mask
, /* access_mask */
1129 share_mode
, /* share_access */
1130 create_disposition
, /* create_disposition*/
1131 create_options
, /* create_options */
1132 open_attr
, /* file_attributes */
1133 oplock_request
, /* oplock_request */
1134 open_size
, /* allocation_size */
1137 ea_list
, /* ea_list */
1139 &smb_action
); /* psbuf */
1141 if (!NT_STATUS_IS_OK(status
)) {
1142 if (open_was_deferred(req
->mid
)) {
1143 /* We have re-scheduled this call. */
1146 reply_openerror(req
, status
);
1150 size
= get_file_size_stat(&smb_fname
->st
);
1151 fattr
= dos_mode(conn
, smb_fname
);
1152 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1153 inode
= smb_fname
->st
.st_ex_ino
;
1154 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1155 close_file(req
, fsp
, ERROR_CLOSE
);
1156 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1160 /* Realloc the size of parameters and data we will return */
1161 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1162 if(*pparams
== NULL
) {
1163 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1168 SSVAL(params
,0,fsp
->fnum
);
1169 SSVAL(params
,2,fattr
);
1170 srv_put_dos_date2(params
,4, mtime
);
1171 SIVAL(params
,8, (uint32
)size
);
1172 SSVAL(params
,12,deny_mode
);
1173 SSVAL(params
,14,0); /* open_type - file or directory. */
1174 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1176 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1177 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1180 SSVAL(params
,18,smb_action
);
1183 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1185 SIVAL(params
,20,inode
);
1186 SSVAL(params
,24,0); /* Padding. */
1188 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1189 fsp
->fsp_name
->base_name
);
1190 SIVAL(params
, 26, ea_size
);
1192 SIVAL(params
, 26, 0);
1195 /* Send the required number of replies */
1196 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1198 TALLOC_FREE(smb_fname
);
1201 /*********************************************************
1202 Routine to check if a given string matches exactly.
1203 as a special case a mask of "." does NOT match. That
1204 is required for correct wildcard semantics
1205 Case can be significant or not.
1206 **********************************************************/
1208 static bool exact_match(bool has_wild
,
1209 bool case_sensitive
,
1213 if (mask
[0] == '.' && mask
[1] == 0) {
1221 if (case_sensitive
) {
1222 return strcmp(str
,mask
)==0;
1224 return StrCaseCmp(str
,mask
) == 0;
1228 /****************************************************************************
1229 Return the filetype for UNIX extensions.
1230 ****************************************************************************/
1232 static uint32
unix_filetype(mode_t mode
)
1235 return UNIX_TYPE_FILE
;
1236 else if(S_ISDIR(mode
))
1237 return UNIX_TYPE_DIR
;
1239 else if(S_ISLNK(mode
))
1240 return UNIX_TYPE_SYMLINK
;
1243 else if(S_ISCHR(mode
))
1244 return UNIX_TYPE_CHARDEV
;
1247 else if(S_ISBLK(mode
))
1248 return UNIX_TYPE_BLKDEV
;
1251 else if(S_ISFIFO(mode
))
1252 return UNIX_TYPE_FIFO
;
1255 else if(S_ISSOCK(mode
))
1256 return UNIX_TYPE_SOCKET
;
1259 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1260 return UNIX_TYPE_UNKNOWN
;
1263 /****************************************************************************
1264 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1265 ****************************************************************************/
1267 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1269 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1270 const SMB_STRUCT_STAT
*psbuf
,
1272 enum perm_type ptype
,
1277 if (perms
== SMB_MODE_NO_CHANGE
) {
1278 if (!VALID_STAT(*psbuf
)) {
1279 return NT_STATUS_INVALID_PARAMETER
;
1281 *ret_perms
= psbuf
->st_ex_mode
;
1282 return NT_STATUS_OK
;
1286 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1287 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1288 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1289 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1290 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1291 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1292 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1293 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1294 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1296 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1299 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1302 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1307 /* Apply mode mask */
1308 ret
&= lp_create_mask(SNUM(conn
));
1309 /* Add in force bits */
1310 ret
|= lp_force_create_mode(SNUM(conn
));
1313 ret
&= lp_dir_mask(SNUM(conn
));
1314 /* Add in force bits */
1315 ret
|= lp_force_dir_mode(SNUM(conn
));
1317 case PERM_EXISTING_FILE
:
1318 /* Apply mode mask */
1319 ret
&= lp_security_mask(SNUM(conn
));
1320 /* Add in force bits */
1321 ret
|= lp_force_security_mode(SNUM(conn
));
1323 case PERM_EXISTING_DIR
:
1324 /* Apply mode mask */
1325 ret
&= lp_dir_security_mask(SNUM(conn
));
1326 /* Add in force bits */
1327 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1332 return NT_STATUS_OK
;
1335 /****************************************************************************
1336 Needed to show the msdfs symlinks as directories. Modifies psbuf
1337 to be a directory if it's a msdfs link.
1338 ****************************************************************************/
1340 static bool check_msdfs_link(connection_struct
*conn
,
1341 const char *pathname
,
1342 SMB_STRUCT_STAT
*psbuf
)
1344 int saved_errno
= errno
;
1345 if(lp_host_msdfs() &&
1346 lp_msdfs_root(SNUM(conn
)) &&
1347 is_msdfs_link(conn
, pathname
, psbuf
)) {
1349 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1352 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1353 errno
= saved_errno
;
1356 errno
= saved_errno
;
1361 /****************************************************************************
1362 Get a level dependent lanman2 dir entry.
1363 ****************************************************************************/
1365 struct smbd_dirptr_lanman2_state
{
1366 connection_struct
*conn
;
1367 uint32_t info_level
;
1368 bool check_mangled_names
;
1370 bool got_exact_match
;
1373 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1379 struct smbd_dirptr_lanman2_state
*state
=
1380 (struct smbd_dirptr_lanman2_state
*)private_data
;
1382 char mangled_name
[13]; /* mangled 8.3 name. */
1386 /* Mangle fname if it's an illegal name. */
1387 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1388 ok
= name_to_8_3(dname
, mangled_name
,
1389 true, state
->conn
->params
);
1393 fname
= mangled_name
;
1398 got_match
= exact_match(state
->has_wild
,
1399 state
->conn
->case_sensitive
,
1401 state
->got_exact_match
= got_match
;
1403 got_match
= mask_match(fname
, mask
,
1404 state
->conn
->case_sensitive
);
1407 if(!got_match
&& state
->check_mangled_names
&&
1408 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1410 * It turns out that NT matches wildcards against
1411 * both long *and* short names. This may explain some
1412 * of the wildcard wierdness from old DOS clients
1413 * that some people have been seeing.... JRA.
1415 /* Force the mangling into 8.3. */
1416 ok
= name_to_8_3(fname
, mangled_name
,
1417 false, state
->conn
->params
);
1422 got_match
= exact_match(state
->has_wild
,
1423 state
->conn
->case_sensitive
,
1424 mangled_name
, mask
);
1425 state
->got_exact_match
= got_match
;
1427 got_match
= mask_match(mangled_name
, mask
,
1428 state
->conn
->case_sensitive
);
1436 *_fname
= talloc_strdup(ctx
, fname
);
1437 if (*_fname
== NULL
) {
1444 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1446 struct smb_filename
*smb_fname
,
1449 struct smbd_dirptr_lanman2_state
*state
=
1450 (struct smbd_dirptr_lanman2_state
*)private_data
;
1451 bool ms_dfs_link
= false;
1454 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1455 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1456 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1457 "Couldn't lstat [%s] (%s)\n",
1458 smb_fname_str_dbg(smb_fname
),
1462 } else if (!VALID_STAT(smb_fname
->st
) &&
1463 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1464 /* Needed to show the msdfs symlinks as
1467 ms_dfs_link
= check_msdfs_link(state
->conn
,
1468 smb_fname
->base_name
,
1471 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1472 "Couldn't stat [%s] (%s)\n",
1473 smb_fname_str_dbg(smb_fname
),
1480 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1482 mode
= dos_mode(state
->conn
, smb_fname
);
1489 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1490 connection_struct
*conn
,
1492 uint32_t info_level
,
1493 struct ea_list
*name_list
,
1494 bool check_mangled_names
,
1495 bool requires_resume_key
,
1498 const struct smb_filename
*smb_fname
,
1499 int space_remaining
,
1506 uint64_t *last_entry_off
)
1508 char *p
, *q
, *pdata
= *ppdata
;
1510 uint64_t file_size
= 0;
1511 uint64_t allocation_size
= 0;
1512 uint64_t file_index
= 0;
1514 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1515 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1516 time_t c_date
= (time_t)0;
1518 char *last_entry_ptr
;
1523 *out_of_space
= false;
1525 ZERO_STRUCT(mdate_ts
);
1526 ZERO_STRUCT(adate_ts
);
1527 ZERO_STRUCT(create_date_ts
);
1528 ZERO_STRUCT(cdate_ts
);
1530 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1531 file_size
= get_file_size_stat(&smb_fname
->st
);
1533 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1535 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1537 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1538 adate_ts
= smb_fname
->st
.st_ex_atime
;
1539 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1540 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1542 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1543 dos_filetime_timespec(&create_date_ts
);
1544 dos_filetime_timespec(&mdate_ts
);
1545 dos_filetime_timespec(&adate_ts
);
1546 dos_filetime_timespec(&cdate_ts
);
1549 create_date
= convert_timespec_to_time_t(create_date_ts
);
1550 mdate
= convert_timespec_to_time_t(mdate_ts
);
1551 adate
= convert_timespec_to_time_t(adate_ts
);
1552 c_date
= convert_timespec_to_time_t(cdate_ts
);
1554 /* align the record */
1555 SMB_ASSERT(align
>= 1);
1557 off
= (int)PTR_DIFF(pdata
, base_data
);
1558 pad
= (off
+ (align
-1)) & ~(align
-1);
1561 if (pad
&& pad
> space_remaining
) {
1562 *out_of_space
= true;
1563 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1564 "for padding (wanted %u, had %d)\n",
1567 return false; /* Not finished - just out of space */
1571 /* initialize padding to 0 */
1573 memset(pdata
, 0, pad
);
1575 space_remaining
-= pad
;
1577 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1587 switch (info_level
) {
1588 case SMB_FIND_INFO_STANDARD
:
1589 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1590 if(requires_resume_key
) {
1594 srv_put_dos_date2(p
,0,create_date
);
1595 srv_put_dos_date2(p
,4,adate
);
1596 srv_put_dos_date2(p
,8,mdate
);
1597 SIVAL(p
,12,(uint32
)file_size
);
1598 SIVAL(p
,16,(uint32
)allocation_size
);
1602 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1603 p
+= ucs2_align(base_data
, p
, 0);
1605 len
= srvstr_push(base_data
, flags2
, p
,
1606 fname
, PTR_DIFF(end_data
, p
),
1608 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1610 SCVAL(nameptr
, -1, len
- 2);
1612 SCVAL(nameptr
, -1, 0);
1616 SCVAL(nameptr
, -1, len
- 1);
1618 SCVAL(nameptr
, -1, 0);
1624 case SMB_FIND_EA_SIZE
:
1625 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1626 if (requires_resume_key
) {
1630 srv_put_dos_date2(p
,0,create_date
);
1631 srv_put_dos_date2(p
,4,adate
);
1632 srv_put_dos_date2(p
,8,mdate
);
1633 SIVAL(p
,12,(uint32
)file_size
);
1634 SIVAL(p
,16,(uint32
)allocation_size
);
1637 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1638 smb_fname
->base_name
);
1639 SIVAL(p
,22,ea_size
); /* Extended attributes */
1643 len
= srvstr_push(base_data
, flags2
,
1644 p
, fname
, PTR_DIFF(end_data
, p
),
1645 STR_TERMINATE
| STR_NOALIGN
);
1646 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1659 SCVAL(nameptr
,0,len
);
1661 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1664 case SMB_FIND_EA_LIST
:
1666 struct ea_list
*file_list
= NULL
;
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1673 if (requires_resume_key
) {
1677 srv_put_dos_date2(p
,0,create_date
);
1678 srv_put_dos_date2(p
,4,adate
);
1679 srv_put_dos_date2(p
,8,mdate
);
1680 SIVAL(p
,12,(uint32
)file_size
);
1681 SIVAL(p
,16,(uint32
)allocation_size
);
1683 p
+= 22; /* p now points to the EA area. */
1685 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1686 smb_fname
->base_name
,
1688 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1690 /* We need to determine if this entry will fit in the space available. */
1691 /* Max string size is 255 bytes. */
1692 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1693 *out_of_space
= true;
1694 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1695 "(wanted %u, had %d)\n",
1696 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1698 return False
; /* Not finished - just out of space */
1701 /* Push the ea_data followed by the name. */
1702 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1704 len
= srvstr_push(base_data
, flags2
,
1705 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1706 STR_TERMINATE
| STR_NOALIGN
);
1707 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1720 SCVAL(nameptr
,0,len
);
1722 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1726 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1727 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1728 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1730 SIVAL(p
,0,reskey
); p
+= 4;
1731 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1732 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1733 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1734 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1735 SOFF_T(p
,0,file_size
); p
+= 8;
1736 SOFF_T(p
,0,allocation_size
); p
+= 8;
1737 SIVAL(p
,0,mode
); p
+= 4;
1738 q
= p
; p
+= 4; /* q is placeholder for name length. */
1740 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1741 smb_fname
->base_name
);
1742 SIVAL(p
,0,ea_size
); /* Extended attributes */
1745 /* Clear the short name buffer. This is
1746 * IMPORTANT as not doing so will trigger
1747 * a Win2k client bug. JRA.
1749 if (!was_8_3
&& check_mangled_names
) {
1750 char mangled_name
[13]; /* mangled 8.3 name. */
1751 if (!name_to_8_3(fname
,mangled_name
,True
,
1753 /* Error - mangle failed ! */
1754 memset(mangled_name
,'\0',12);
1756 mangled_name
[12] = 0;
1757 len
= srvstr_push(base_data
, flags2
,
1758 p
+2, mangled_name
, 24,
1759 STR_UPPER
|STR_UNICODE
);
1761 memset(p
+ 2 + len
,'\0',24 - len
);
1768 len
= srvstr_push(base_data
, flags2
, p
,
1769 fname
, PTR_DIFF(end_data
, p
),
1770 STR_TERMINATE_ASCII
);
1774 len
= PTR_DIFF(p
, pdata
);
1775 pad
= (len
+ (align
-1)) & ~(align
-1);
1777 * offset to the next entry, the caller
1778 * will overwrite it for the last entry
1779 * that's why we always include the padding
1783 * set padding to zero
1786 memset(p
, 0, pad
- len
);
1793 case SMB_FIND_FILE_DIRECTORY_INFO
:
1794 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1796 SIVAL(p
,0,reskey
); p
+= 4;
1797 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1798 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1799 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1800 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1801 SOFF_T(p
,0,file_size
); p
+= 8;
1802 SOFF_T(p
,0,allocation_size
); p
+= 8;
1803 SIVAL(p
,0,mode
); p
+= 4;
1804 len
= srvstr_push(base_data
, flags2
,
1805 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1806 STR_TERMINATE_ASCII
);
1810 len
= PTR_DIFF(p
, pdata
);
1811 pad
= (len
+ (align
-1)) & ~(align
-1);
1813 * offset to the next entry, the caller
1814 * will overwrite it for the last entry
1815 * that's why we always include the padding
1819 * set padding to zero
1822 memset(p
, 0, pad
- len
);
1829 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1830 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1832 SIVAL(p
,0,reskey
); p
+= 4;
1833 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1834 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1835 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1836 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1837 SOFF_T(p
,0,file_size
); p
+= 8;
1838 SOFF_T(p
,0,allocation_size
); p
+= 8;
1839 SIVAL(p
,0,mode
); p
+= 4;
1840 q
= p
; p
+= 4; /* q is placeholder for name length. */
1842 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1843 smb_fname
->base_name
);
1844 SIVAL(p
,0,ea_size
); /* Extended attributes */
1847 len
= srvstr_push(base_data
, flags2
, p
,
1848 fname
, PTR_DIFF(end_data
, p
),
1849 STR_TERMINATE_ASCII
);
1853 len
= PTR_DIFF(p
, pdata
);
1854 pad
= (len
+ (align
-1)) & ~(align
-1);
1856 * offset to the next entry, the caller
1857 * will overwrite it for the last entry
1858 * that's why we always include the padding
1862 * set padding to zero
1865 memset(p
, 0, pad
- len
);
1872 case SMB_FIND_FILE_NAMES_INFO
:
1873 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1875 SIVAL(p
,0,reskey
); p
+= 4;
1877 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1878 acl on a dir (tridge) */
1879 len
= srvstr_push(base_data
, flags2
, p
,
1880 fname
, PTR_DIFF(end_data
, p
),
1881 STR_TERMINATE_ASCII
);
1885 len
= PTR_DIFF(p
, pdata
);
1886 pad
= (len
+ (align
-1)) & ~(align
-1);
1888 * offset to the next entry, the caller
1889 * will overwrite it for the last entry
1890 * that's why we always include the padding
1894 * set padding to zero
1897 memset(p
, 0, pad
- len
);
1904 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1905 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1907 SIVAL(p
,0,reskey
); p
+= 4;
1908 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1909 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1910 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1911 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1912 SOFF_T(p
,0,file_size
); p
+= 8;
1913 SOFF_T(p
,0,allocation_size
); p
+= 8;
1914 SIVAL(p
,0,mode
); p
+= 4;
1915 q
= p
; p
+= 4; /* q is placeholder for name length. */
1917 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1918 smb_fname
->base_name
);
1919 SIVAL(p
,0,ea_size
); /* Extended attributes */
1922 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1923 SBVAL(p
,0,file_index
); p
+= 8;
1924 len
= srvstr_push(base_data
, flags2
, p
,
1925 fname
, PTR_DIFF(end_data
, p
),
1926 STR_TERMINATE_ASCII
);
1930 len
= PTR_DIFF(p
, pdata
);
1931 pad
= (len
+ (align
-1)) & ~(align
-1);
1933 * offset to the next entry, the caller
1934 * will overwrite it for the last entry
1935 * that's why we always include the padding
1939 * set padding to zero
1942 memset(p
, 0, pad
- len
);
1949 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1950 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1951 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1953 SIVAL(p
,0,reskey
); p
+= 4;
1954 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1955 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1956 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1957 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1958 SOFF_T(p
,0,file_size
); p
+= 8;
1959 SOFF_T(p
,0,allocation_size
); p
+= 8;
1960 SIVAL(p
,0,mode
); p
+= 4;
1961 q
= p
; p
+= 4; /* q is placeholder for name length */
1963 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1964 smb_fname
->base_name
);
1965 SIVAL(p
,0,ea_size
); /* Extended attributes */
1968 /* Clear the short name buffer. This is
1969 * IMPORTANT as not doing so will trigger
1970 * a Win2k client bug. JRA.
1972 if (!was_8_3
&& check_mangled_names
) {
1973 char mangled_name
[13]; /* mangled 8.3 name. */
1974 if (!name_to_8_3(fname
,mangled_name
,True
,
1976 /* Error - mangle failed ! */
1977 memset(mangled_name
,'\0',12);
1979 mangled_name
[12] = 0;
1980 len
= srvstr_push(base_data
, flags2
,
1981 p
+2, mangled_name
, 24,
1982 STR_UPPER
|STR_UNICODE
);
1985 memset(p
+ 2 + len
,'\0',24 - len
);
1992 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1993 SBVAL(p
,0,file_index
); p
+= 8;
1994 len
= srvstr_push(base_data
, flags2
, p
,
1995 fname
, PTR_DIFF(end_data
, p
),
1996 STR_TERMINATE_ASCII
);
2000 len
= PTR_DIFF(p
, pdata
);
2001 pad
= (len
+ (align
-1)) & ~(align
-1);
2003 * offset to the next entry, the caller
2004 * will overwrite it for the last entry
2005 * that's why we always include the padding
2009 * set padding to zero
2012 memset(p
, 0, pad
- len
);
2019 /* CIFS UNIX Extension. */
2021 case SMB_FIND_FILE_UNIX
:
2022 case SMB_FIND_FILE_UNIX_INFO2
:
2024 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2026 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2028 if (info_level
== SMB_FIND_FILE_UNIX
) {
2029 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2030 p
= store_file_unix_basic(conn
, p
,
2031 NULL
, &smb_fname
->st
);
2032 len
= srvstr_push(base_data
, flags2
, p
,
2033 fname
, PTR_DIFF(end_data
, p
),
2036 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2037 p
= store_file_unix_basic_info2(conn
, p
,
2038 NULL
, &smb_fname
->st
);
2041 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2042 PTR_DIFF(end_data
, p
), 0);
2043 SIVAL(nameptr
, 0, len
);
2048 len
= PTR_DIFF(p
, pdata
);
2049 pad
= (len
+ (align
-1)) & ~(align
-1);
2051 * offset to the next entry, the caller
2052 * will overwrite it for the last entry
2053 * that's why we always include the padding
2057 * set padding to zero
2060 memset(p
, 0, pad
- len
);
2065 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2073 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2074 *out_of_space
= true;
2075 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2076 "(wanted %u, had %d)\n",
2077 (unsigned int)PTR_DIFF(p
,pdata
),
2079 return false; /* Not finished - just out of space */
2082 /* Setup the last entry pointer, as an offset from base_data */
2083 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2084 /* Advance the data pointer to the next slot */
2090 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2091 connection_struct
*conn
,
2092 struct dptr_struct
*dirptr
,
2094 const char *path_mask
,
2097 int requires_resume_key
,
2105 int space_remaining
,
2107 bool *got_exact_match
,
2108 int *_last_entry_off
,
2109 struct ea_list
*name_list
)
2112 const char *mask
= NULL
;
2113 long prev_dirpos
= 0;
2116 struct smb_filename
*smb_fname
= NULL
;
2117 struct smbd_dirptr_lanman2_state state
;
2119 uint64_t last_entry_off
= 0;
2123 state
.info_level
= info_level
;
2124 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2125 state
.has_wild
= dptr_has_wild(dirptr
);
2126 state
.got_exact_match
= false;
2128 *out_of_space
= false;
2129 *got_exact_match
= false;
2131 p
= strrchr_m(path_mask
,'/');
2142 ok
= smbd_dirptr_get_entry(ctx
,
2148 smbd_dirptr_lanman2_match_fn
,
2149 smbd_dirptr_lanman2_mode_fn
,
2159 *got_exact_match
= state
.got_exact_match
;
2161 ok
= smbd_marshall_dir_entry(ctx
,
2166 state
.check_mangled_names
,
2167 requires_resume_key
,
2180 TALLOC_FREE(smb_fname
);
2181 if (*out_of_space
) {
2182 dptr_SeekDir(dirptr
, prev_dirpos
);
2189 *_last_entry_off
= last_entry_off
;
2193 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2194 connection_struct
*conn
,
2195 struct dptr_struct
*dirptr
,
2197 const char *path_mask
,
2200 bool requires_resume_key
,
2206 int space_remaining
,
2208 bool *got_exact_match
,
2209 int *last_entry_off
,
2210 struct ea_list
*name_list
)
2213 const bool do_pad
= true;
2215 if (info_level
>= 1 && info_level
<= 3) {
2216 /* No alignment on earlier info levels. */
2220 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2221 path_mask
, dirtype
, info_level
,
2222 requires_resume_key
, dont_descend
, ask_sharemode
,
2224 ppdata
, base_data
, end_data
,
2226 out_of_space
, got_exact_match
,
2227 last_entry_off
, name_list
);
2230 /****************************************************************************
2231 Reply to a TRANS2_FINDFIRST.
2232 ****************************************************************************/
2234 static void call_trans2findfirst(connection_struct
*conn
,
2235 struct smb_request
*req
,
2236 char **pparams
, int total_params
,
2237 char **ppdata
, int total_data
,
2238 unsigned int max_data_bytes
)
2240 /* We must be careful here that we don't return more than the
2241 allowed number of data bytes. If this means returning fewer than
2242 maxentries then so be it. We assume that the redirector has
2243 enough room for the fixed number of parameter bytes it has
2245 struct smb_filename
*smb_dname
= NULL
;
2246 char *params
= *pparams
;
2247 char *pdata
= *ppdata
;
2251 uint16 findfirst_flags
;
2252 bool close_after_first
;
2254 bool requires_resume_key
;
2256 char *directory
= NULL
;
2259 int last_entry_off
=0;
2263 bool finished
= False
;
2264 bool dont_descend
= False
;
2265 bool out_of_space
= False
;
2266 int space_remaining
;
2267 bool mask_contains_wcard
= False
;
2268 struct ea_list
*ea_list
= NULL
;
2269 NTSTATUS ntstatus
= NT_STATUS_OK
;
2270 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2271 TALLOC_CTX
*ctx
= talloc_tos();
2272 struct dptr_struct
*dirptr
= NULL
;
2273 struct smbd_server_connection
*sconn
= req
->sconn
;
2274 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2276 if (total_params
< 13) {
2277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2281 dirtype
= SVAL(params
,0);
2282 maxentries
= SVAL(params
,2);
2283 findfirst_flags
= SVAL(params
,4);
2284 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2285 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2286 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2287 info_level
= SVAL(params
,6);
2289 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2290 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2291 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2292 info_level
, max_data_bytes
));
2295 /* W2K3 seems to treat zero as 1. */
2299 switch (info_level
) {
2300 case SMB_FIND_INFO_STANDARD
:
2301 case SMB_FIND_EA_SIZE
:
2302 case SMB_FIND_EA_LIST
:
2303 case SMB_FIND_FILE_DIRECTORY_INFO
:
2304 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2305 case SMB_FIND_FILE_NAMES_INFO
:
2306 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2307 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2308 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2310 case SMB_FIND_FILE_UNIX
:
2311 case SMB_FIND_FILE_UNIX_INFO2
:
2312 /* Always use filesystem for UNIX mtime query. */
2313 ask_sharemode
= false;
2314 if (!lp_unix_extensions()) {
2315 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2318 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2321 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2325 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2326 params
+12, total_params
- 12,
2327 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2328 if (!NT_STATUS_IS_OK(ntstatus
)) {
2329 reply_nterror(req
, ntstatus
);
2333 ntstatus
= filename_convert(ctx
, conn
,
2334 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2337 &mask_contains_wcard
,
2339 if (!NT_STATUS_IS_OK(ntstatus
)) {
2340 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2341 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2342 ERRSRV
, ERRbadpath
);
2345 reply_nterror(req
, ntstatus
);
2349 mask
= smb_dname
->original_lcomp
;
2351 directory
= smb_dname
->base_name
;
2353 p
= strrchr_m(directory
,'/');
2355 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2356 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2357 mask
= talloc_strdup(ctx
,"*");
2359 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2362 mask_contains_wcard
= True
;
2368 if (p
== NULL
|| p
== directory
) {
2369 /* Ensure we don't have a directory name of "". */
2370 directory
= talloc_strdup(talloc_tos(), ".");
2372 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2377 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2379 if (info_level
== SMB_FIND_EA_LIST
) {
2382 if (total_data
< 4) {
2383 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2387 ea_size
= IVAL(pdata
,0);
2388 if (ea_size
!= total_data
) {
2389 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2390 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2391 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2395 if (!lp_ea_support(SNUM(conn
))) {
2396 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2400 /* Pull out the list of names. */
2401 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2408 *ppdata
= (char *)SMB_REALLOC(
2409 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2410 if(*ppdata
== NULL
) {
2411 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2415 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2417 /* Realloc the params space */
2418 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2419 if (*pparams
== NULL
) {
2420 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2425 /* Save the wildcard match and attribs we are using on this directory -
2426 needed as lanman2 assumes these are being saved between calls */
2428 ntstatus
= dptr_create(conn
,
2435 mask_contains_wcard
,
2439 if (!NT_STATUS_IS_OK(ntstatus
)) {
2440 reply_nterror(req
, ntstatus
);
2444 dptr_num
= dptr_dnum(dirptr
);
2445 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2447 /* Initialize per TRANS2_FIND_FIRST operation data */
2448 dptr_init_search_op(dirptr
);
2450 /* We don't need to check for VOL here as this is returned by
2451 a different TRANS2 call. */
2453 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2454 directory
,lp_dontdescend(SNUM(conn
))));
2455 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2456 dont_descend
= True
;
2459 space_remaining
= max_data_bytes
;
2460 out_of_space
= False
;
2462 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2463 bool got_exact_match
= False
;
2465 /* this is a heuristic to avoid seeking the dirptr except when
2466 absolutely necessary. It allows for a filename of about 40 chars */
2467 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2468 out_of_space
= True
;
2471 finished
= !get_lanman2_dir_entry(ctx
,
2475 mask
,dirtype
,info_level
,
2476 requires_resume_key
,dont_descend
,
2479 space_remaining
, &out_of_space
,
2481 &last_entry_off
, ea_list
);
2484 if (finished
&& out_of_space
)
2487 if (!finished
&& !out_of_space
)
2491 * As an optimisation if we know we aren't looking
2492 * for a wildcard name (ie. the name matches the wildcard exactly)
2493 * then we can finish on any (first) match.
2494 * This speeds up large directory searches. JRA.
2500 /* Ensure space_remaining never goes -ve. */
2501 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2502 space_remaining
= 0;
2503 out_of_space
= true;
2505 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2509 /* Check if we can close the dirptr */
2510 if(close_after_first
|| (finished
&& close_if_end
)) {
2511 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2512 dptr_close(sconn
, &dptr_num
);
2516 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2517 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2518 * the protocol level is less than NT1. Tested with smbclient. JRA.
2519 * This should fix the OS/2 client bug #2335.
2522 if(numentries
== 0) {
2523 dptr_close(sconn
, &dptr_num
);
2524 if (get_Protocol() < PROTOCOL_NT1
) {
2525 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2528 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2529 ERRDOS
, ERRbadfile
);
2534 /* At this point pdata points to numentries directory entries. */
2536 /* Set up the return parameter block */
2537 SSVAL(params
,0,dptr_num
);
2538 SSVAL(params
,2,numentries
);
2539 SSVAL(params
,4,finished
);
2540 SSVAL(params
,6,0); /* Never an EA error */
2541 SSVAL(params
,8,last_entry_off
);
2543 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2546 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2547 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2549 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2553 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2554 smb_fn_name(req
->cmd
),
2555 mask
, directory
, dirtype
, numentries
) );
2558 * Force a name mangle here to ensure that the
2559 * mask as an 8.3 name is top of the mangled cache.
2560 * The reasons for this are subtle. Don't remove
2561 * this code unless you know what you are doing
2562 * (see PR#13758). JRA.
2565 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2566 char mangled_name
[13];
2567 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2570 TALLOC_FREE(smb_dname
);
2574 /****************************************************************************
2575 Reply to a TRANS2_FINDNEXT.
2576 ****************************************************************************/
2578 static void call_trans2findnext(connection_struct
*conn
,
2579 struct smb_request
*req
,
2580 char **pparams
, int total_params
,
2581 char **ppdata
, int total_data
,
2582 unsigned int max_data_bytes
)
2584 /* We must be careful here that we don't return more than the
2585 allowed number of data bytes. If this means returning fewer than
2586 maxentries then so be it. We assume that the redirector has
2587 enough room for the fixed number of parameter bytes it has
2589 char *params
= *pparams
;
2590 char *pdata
= *ppdata
;
2596 uint16 findnext_flags
;
2597 bool close_after_request
;
2599 bool requires_resume_key
;
2601 bool mask_contains_wcard
= False
;
2602 char *resume_name
= NULL
;
2603 const char *mask
= NULL
;
2604 const char *directory
= NULL
;
2608 int i
, last_entry_off
=0;
2609 bool finished
= False
;
2610 bool dont_descend
= False
;
2611 bool out_of_space
= False
;
2612 int space_remaining
;
2613 struct ea_list
*ea_list
= NULL
;
2614 NTSTATUS ntstatus
= NT_STATUS_OK
;
2615 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2616 TALLOC_CTX
*ctx
= talloc_tos();
2617 struct dptr_struct
*dirptr
;
2618 struct smbd_server_connection
*sconn
= req
->sconn
;
2620 if (total_params
< 13) {
2621 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2625 dptr_num
= SVAL(params
,0);
2626 maxentries
= SVAL(params
,2);
2627 info_level
= SVAL(params
,4);
2628 resume_key
= IVAL(params
,6);
2629 findnext_flags
= SVAL(params
,10);
2630 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2631 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2632 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2633 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2635 if (!continue_bit
) {
2636 /* We only need resume_name if continue_bit is zero. */
2637 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2639 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2640 &mask_contains_wcard
);
2641 if (!NT_STATUS_IS_OK(ntstatus
)) {
2642 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2643 complain (it thinks we're asking for the directory above the shared
2644 path or an invalid name). Catch this as the resume name is only compared, never used in
2645 a file access. JRA. */
2646 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2647 &resume_name
, params
+12,
2651 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2652 reply_nterror(req
, ntstatus
);
2658 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2659 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2660 resume_key = %d resume name = %s continue=%d level = %d\n",
2661 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2662 requires_resume_key
, resume_key
,
2663 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2666 /* W2K3 seems to treat zero as 1. */
2670 switch (info_level
) {
2671 case SMB_FIND_INFO_STANDARD
:
2672 case SMB_FIND_EA_SIZE
:
2673 case SMB_FIND_EA_LIST
:
2674 case SMB_FIND_FILE_DIRECTORY_INFO
:
2675 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2676 case SMB_FIND_FILE_NAMES_INFO
:
2677 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2678 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2679 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2681 case SMB_FIND_FILE_UNIX
:
2682 case SMB_FIND_FILE_UNIX_INFO2
:
2683 /* Always use filesystem for UNIX mtime query. */
2684 ask_sharemode
= false;
2685 if (!lp_unix_extensions()) {
2686 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2691 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2695 if (info_level
== SMB_FIND_EA_LIST
) {
2698 if (total_data
< 4) {
2699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2703 ea_size
= IVAL(pdata
,0);
2704 if (ea_size
!= total_data
) {
2705 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2706 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2707 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2711 if (!lp_ea_support(SNUM(conn
))) {
2712 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2716 /* Pull out the list of names. */
2717 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2724 *ppdata
= (char *)SMB_REALLOC(
2725 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2726 if(*ppdata
== NULL
) {
2727 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2732 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2734 /* Realloc the params space */
2735 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2736 if(*pparams
== NULL
) {
2737 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2743 /* Check that the dptr is valid */
2744 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2745 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2749 directory
= dptr_path(sconn
, dptr_num
);
2751 /* Get the wildcard mask from the dptr */
2752 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2753 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2754 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2760 /* Get the attr mask from the dptr */
2761 dirtype
= dptr_attr(sconn
, dptr_num
);
2763 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2764 dptr_num
, mask
, dirtype
,
2766 dptr_TellDir(dirptr
)));
2768 /* Initialize per TRANS2_FIND_NEXT operation data */
2769 dptr_init_search_op(dirptr
);
2771 /* We don't need to check for VOL here as this is returned by
2772 a different TRANS2 call. */
2774 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2775 directory
,lp_dontdescend(SNUM(conn
))));
2776 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2777 dont_descend
= True
;
2780 space_remaining
= max_data_bytes
;
2781 out_of_space
= False
;
2784 * Seek to the correct position. We no longer use the resume key but
2785 * depend on the last file name instead.
2788 if(!continue_bit
&& resume_name
&& *resume_name
) {
2791 long current_pos
= 0;
2793 * Remember, name_to_8_3 is called by
2794 * get_lanman2_dir_entry(), so the resume name
2795 * could be mangled. Ensure we check the unmangled name.
2798 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2799 char *new_resume_name
= NULL
;
2800 mangle_lookup_name_from_8_3(ctx
,
2804 if (new_resume_name
) {
2805 resume_name
= new_resume_name
;
2810 * Fix for NT redirector problem triggered by resume key indexes
2811 * changing between directory scans. We now return a resume key of 0
2812 * and instead look for the filename to continue from (also given
2813 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2814 * findfirst/findnext (as is usual) then the directory pointer
2815 * should already be at the correct place.
2818 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2819 } /* end if resume_name && !continue_bit */
2821 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2822 bool got_exact_match
= False
;
2824 /* this is a heuristic to avoid seeking the dirptr except when
2825 absolutely necessary. It allows for a filename of about 40 chars */
2826 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2827 out_of_space
= True
;
2830 finished
= !get_lanman2_dir_entry(ctx
,
2834 mask
,dirtype
,info_level
,
2835 requires_resume_key
,dont_descend
,
2838 space_remaining
, &out_of_space
,
2840 &last_entry_off
, ea_list
);
2843 if (finished
&& out_of_space
)
2846 if (!finished
&& !out_of_space
)
2850 * As an optimisation if we know we aren't looking
2851 * for a wildcard name (ie. the name matches the wildcard exactly)
2852 * then we can finish on any (first) match.
2853 * This speeds up large directory searches. JRA.
2859 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2862 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2863 smb_fn_name(req
->cmd
),
2864 mask
, directory
, dirtype
, numentries
) );
2866 /* Check if we can close the dirptr */
2867 if(close_after_request
|| (finished
&& close_if_end
)) {
2868 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2869 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2872 /* Set up the return parameter block */
2873 SSVAL(params
,0,numentries
);
2874 SSVAL(params
,2,finished
);
2875 SSVAL(params
,4,0); /* Never an EA error */
2876 SSVAL(params
,6,last_entry_off
);
2878 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2884 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2886 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2890 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2892 SMB_ASSERT(extended_info
!= NULL
);
2894 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2895 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2896 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2897 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2898 #ifdef SAMBA_VERSION_REVISION
2899 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2901 extended_info
->samba_subversion
= 0;
2902 #ifdef SAMBA_VERSION_RC_RELEASE
2903 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2905 #ifdef SAMBA_VERSION_PRE_RELEASE
2906 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2909 #ifdef SAMBA_VERSION_VENDOR_PATCH
2910 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2912 extended_info
->samba_gitcommitdate
= 0;
2913 #ifdef SAMBA_VERSION_COMMIT_TIME
2914 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2917 memset(extended_info
->samba_version_string
, 0,
2918 sizeof(extended_info
->samba_version_string
));
2920 snprintf (extended_info
->samba_version_string
,
2921 sizeof(extended_info
->samba_version_string
),
2922 "%s", samba_version_string());
2925 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2926 TALLOC_CTX
*mem_ctx
,
2927 uint16_t info_level
,
2929 unsigned int max_data_bytes
,
2933 char *pdata
, *end_data
;
2934 int data_len
= 0, len
;
2935 const char *vname
= volume_label(SNUM(conn
));
2936 int snum
= SNUM(conn
);
2937 char *fstype
= lp_fstype(SNUM(conn
));
2938 uint32 additional_flags
= 0;
2939 struct smb_filename smb_fname_dot
;
2943 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2944 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2945 "info level (0x%x) on IPC$.\n",
2946 (unsigned int)info_level
));
2947 return NT_STATUS_ACCESS_DENIED
;
2951 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2953 ZERO_STRUCT(smb_fname_dot
);
2954 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2956 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2957 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2958 return map_nt_error_from_unix(errno
);
2961 st
= smb_fname_dot
.st
;
2963 *ppdata
= (char *)SMB_REALLOC(
2964 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2965 if (*ppdata
== NULL
) {
2966 return NT_STATUS_NO_MEMORY
;
2970 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2971 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2973 switch (info_level
) {
2974 case SMB_INFO_ALLOCATION
:
2976 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2978 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2979 return map_nt_error_from_unix(errno
);
2982 block_size
= lp_block_size(snum
);
2983 if (bsize
< block_size
) {
2984 uint64_t factor
= block_size
/bsize
;
2989 if (bsize
> block_size
) {
2990 uint64_t factor
= bsize
/block_size
;
2995 bytes_per_sector
= 512;
2996 sectors_per_unit
= bsize
/bytes_per_sector
;
2998 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2999 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3000 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3002 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3003 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3004 SIVAL(pdata
,l1_cUnit
,dsize
);
3005 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3006 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3010 case SMB_INFO_VOLUME
:
3011 /* Return volume name */
3013 * Add volume serial number - hash of a combination of
3014 * the called hostname and the service name.
3016 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3018 * Win2k3 and previous mess this up by sending a name length
3019 * one byte short. I believe only older clients (OS/2 Win9x) use
3020 * this call so try fixing this by adding a terminating null to
3021 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3025 pdata
+l2_vol_szVolLabel
, vname
,
3026 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3027 STR_NOALIGN
|STR_TERMINATE
);
3028 SCVAL(pdata
,l2_vol_cch
,len
);
3029 data_len
= l2_vol_szVolLabel
+ len
;
3030 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3031 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3035 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3036 case SMB_FS_ATTRIBUTE_INFORMATION
:
3038 additional_flags
= 0;
3039 #if defined(HAVE_SYS_QUOTAS)
3040 additional_flags
|= FILE_VOLUME_QUOTAS
;
3043 if(lp_nt_acl_support(SNUM(conn
))) {
3044 additional_flags
|= FILE_PERSISTENT_ACLS
;
3047 /* Capabilities are filled in at connection time through STATVFS call */
3048 additional_flags
|= conn
->fs_capabilities
;
3049 additional_flags
|= lp_parm_int(conn
->params
->service
,
3050 "share", "fake_fscaps",
3053 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3054 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3055 additional_flags
); /* FS ATTRIBUTES */
3057 SIVAL(pdata
,4,255); /* Max filename component length */
3058 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3059 and will think we can't do long filenames */
3060 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3061 PTR_DIFF(end_data
, pdata
+12),
3064 data_len
= 12 + len
;
3067 case SMB_QUERY_FS_LABEL_INFO
:
3068 case SMB_FS_LABEL_INFORMATION
:
3069 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3070 PTR_DIFF(end_data
, pdata
+4), 0);
3075 case SMB_QUERY_FS_VOLUME_INFO
:
3076 case SMB_FS_VOLUME_INFORMATION
:
3079 * Add volume serial number - hash of a combination of
3080 * the called hostname and the service name.
3082 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3083 (str_checksum(get_local_machine_name())<<16));
3085 /* Max label len is 32 characters. */
3086 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3087 PTR_DIFF(end_data
, pdata
+18),
3089 SIVAL(pdata
,12,len
);
3092 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3093 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3096 case SMB_QUERY_FS_SIZE_INFO
:
3097 case SMB_FS_SIZE_INFORMATION
:
3099 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3101 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3102 return map_nt_error_from_unix(errno
);
3104 block_size
= lp_block_size(snum
);
3105 if (bsize
< block_size
) {
3106 uint64_t factor
= block_size
/bsize
;
3111 if (bsize
> block_size
) {
3112 uint64_t factor
= bsize
/block_size
;
3117 bytes_per_sector
= 512;
3118 sectors_per_unit
= bsize
/bytes_per_sector
;
3119 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3120 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3121 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3122 SBIG_UINT(pdata
,0,dsize
);
3123 SBIG_UINT(pdata
,8,dfree
);
3124 SIVAL(pdata
,16,sectors_per_unit
);
3125 SIVAL(pdata
,20,bytes_per_sector
);
3129 case SMB_FS_FULL_SIZE_INFORMATION
:
3131 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3133 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3134 return map_nt_error_from_unix(errno
);
3136 block_size
= lp_block_size(snum
);
3137 if (bsize
< block_size
) {
3138 uint64_t factor
= block_size
/bsize
;
3143 if (bsize
> block_size
) {
3144 uint64_t factor
= bsize
/block_size
;
3149 bytes_per_sector
= 512;
3150 sectors_per_unit
= bsize
/bytes_per_sector
;
3151 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3152 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3153 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3154 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3155 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3156 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3157 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3158 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3162 case SMB_QUERY_FS_DEVICE_INFO
:
3163 case SMB_FS_DEVICE_INFORMATION
:
3165 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3167 if (!CAN_WRITE(conn
)) {
3168 characteristics
|= FILE_READ_ONLY_DEVICE
;
3171 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3172 SIVAL(pdata
,4,characteristics
);
3176 #ifdef HAVE_SYS_QUOTAS
3177 case SMB_FS_QUOTA_INFORMATION
:
3179 * what we have to send --metze:
3181 * Unknown1: 24 NULL bytes
3182 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3183 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3184 * Quota Flags: 2 byte :
3185 * Unknown3: 6 NULL bytes
3189 * details for Quota Flags:
3191 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3192 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3193 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3194 * 0x0001 Enable Quotas: enable quota for this fs
3198 /* we need to fake up a fsp here,
3199 * because its not send in this call
3202 SMB_NTQUOTA_STRUCT quotas
;
3205 ZERO_STRUCT(quotas
);
3211 if (get_current_uid(conn
) != 0) {
3212 DEBUG(0,("set_user_quota: access_denied "
3213 "service [%s] user [%s]\n",
3214 lp_servicename(SNUM(conn
)),
3215 conn
->session_info
->unix_name
));
3216 return NT_STATUS_ACCESS_DENIED
;
3219 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3220 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3221 return map_nt_error_from_unix(errno
);
3226 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3227 lp_servicename(SNUM(conn
))));
3229 /* Unknown1 24 NULL bytes*/
3230 SBIG_UINT(pdata
,0,(uint64_t)0);
3231 SBIG_UINT(pdata
,8,(uint64_t)0);
3232 SBIG_UINT(pdata
,16,(uint64_t)0);
3234 /* Default Soft Quota 8 bytes */
3235 SBIG_UINT(pdata
,24,quotas
.softlim
);
3237 /* Default Hard Quota 8 bytes */
3238 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3240 /* Quota flag 2 bytes */
3241 SSVAL(pdata
,40,quotas
.qflags
);
3243 /* Unknown3 6 NULL bytes */
3249 #endif /* HAVE_SYS_QUOTAS */
3250 case SMB_FS_OBJECTID_INFORMATION
:
3252 unsigned char objid
[16];
3253 struct smb_extended_info extended_info
;
3254 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3255 samba_extended_info_version (&extended_info
);
3256 SIVAL(pdata
,16,extended_info
.samba_magic
);
3257 SIVAL(pdata
,20,extended_info
.samba_version
);
3258 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3259 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3260 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3266 * Query the version and capabilities of the CIFS UNIX extensions
3270 case SMB_QUERY_CIFS_UNIX_INFO
:
3272 bool large_write
= lp_min_receive_file_size() &&
3273 !srv_is_signing_active(conn
->sconn
);
3274 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3275 int encrypt_caps
= 0;
3277 if (!lp_unix_extensions()) {
3278 return NT_STATUS_INVALID_LEVEL
;
3281 switch (conn
->encrypt_level
) {
3287 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3290 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3291 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3292 large_write
= false;
3298 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3299 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3301 /* We have POSIX ACLs, pathname, encryption,
3302 * large read/write, and locking capability. */
3304 SBIG_UINT(pdata
,4,((uint64_t)(
3305 CIFS_UNIX_POSIX_ACLS_CAP
|
3306 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3307 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3308 CIFS_UNIX_EXTATTR_CAP
|
3309 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3311 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3313 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3317 case SMB_QUERY_POSIX_FS_INFO
:
3320 vfs_statvfs_struct svfs
;
3322 if (!lp_unix_extensions()) {
3323 return NT_STATUS_INVALID_LEVEL
;
3326 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3330 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3331 SIVAL(pdata
,4,svfs
.BlockSize
);
3332 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3333 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3334 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3335 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3336 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3337 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3338 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3340 } else if (rc
== EOPNOTSUPP
) {
3341 return NT_STATUS_INVALID_LEVEL
;
3342 #endif /* EOPNOTSUPP */
3344 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3345 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3350 case SMB_QUERY_POSIX_WHOAMI
:
3356 if (!lp_unix_extensions()) {
3357 return NT_STATUS_INVALID_LEVEL
;
3360 if (max_data_bytes
< 40) {
3361 return NT_STATUS_BUFFER_TOO_SMALL
;
3364 /* We ARE guest if global_sid_Builtin_Guests is
3365 * in our list of SIDs.
3367 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3368 conn
->session_info
->security_token
)) {
3369 flags
|= SMB_WHOAMI_GUEST
;
3372 /* We are NOT guest if global_sid_Authenticated_Users
3373 * is in our list of SIDs.
3375 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3376 conn
->session_info
->security_token
)) {
3377 flags
&= ~SMB_WHOAMI_GUEST
;
3380 /* NOTE: 8 bytes for UID/GID, irrespective of native
3381 * platform size. This matches
3382 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3384 data_len
= 4 /* flags */
3391 + 4 /* pad/reserved */
3392 + (conn
->session_info
->utok
.ngroups
* 8)
3394 + (conn
->session_info
->security_token
->num_sids
*
3398 SIVAL(pdata
, 0, flags
);
3399 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3401 (uint64_t)conn
->session_info
->utok
.uid
);
3402 SBIG_UINT(pdata
, 16,
3403 (uint64_t)conn
->session_info
->utok
.gid
);
3406 if (data_len
>= max_data_bytes
) {
3407 /* Potential overflow, skip the GIDs and SIDs. */
3409 SIVAL(pdata
, 24, 0); /* num_groups */
3410 SIVAL(pdata
, 28, 0); /* num_sids */
3411 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3412 SIVAL(pdata
, 36, 0); /* reserved */
3418 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3419 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3421 /* We walk the SID list twice, but this call is fairly
3422 * infrequent, and I don't expect that it's performance
3423 * sensitive -- jpeach
3425 for (i
= 0, sid_bytes
= 0;
3426 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3427 sid_bytes
+= ndr_size_dom_sid(
3428 &conn
->session_info
->security_token
->sids
[i
],
3432 /* SID list byte count */
3433 SIVAL(pdata
, 32, sid_bytes
);
3435 /* 4 bytes pad/reserved - must be zero */
3436 SIVAL(pdata
, 36, 0);
3440 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3441 SBIG_UINT(pdata
, data_len
,
3442 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3448 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3449 int sid_len
= ndr_size_dom_sid(
3450 &conn
->session_info
->security_token
->sids
[i
],
3453 sid_linearize(pdata
+ data_len
, sid_len
,
3454 &conn
->session_info
->security_token
->sids
[i
]);
3455 data_len
+= sid_len
;
3461 case SMB_MAC_QUERY_FS_INFO
:
3463 * Thursby MAC extension... ONLY on NTFS filesystems
3464 * once we do streams then we don't need this
3466 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3468 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3473 return NT_STATUS_INVALID_LEVEL
;
3476 *ret_data_len
= data_len
;
3477 return NT_STATUS_OK
;
3480 /****************************************************************************
3481 Reply to a TRANS2_QFSINFO (query filesystem info).
3482 ****************************************************************************/
3484 static void call_trans2qfsinfo(connection_struct
*conn
,
3485 struct smb_request
*req
,
3486 char **pparams
, int total_params
,
3487 char **ppdata
, int total_data
,
3488 unsigned int max_data_bytes
)
3490 char *params
= *pparams
;
3491 uint16_t info_level
;
3495 if (total_params
< 2) {
3496 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3500 info_level
= SVAL(params
,0);
3502 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3503 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3504 DEBUG(0,("call_trans2qfsinfo: encryption required "
3505 "and info level 0x%x sent.\n",
3506 (unsigned int)info_level
));
3507 exit_server_cleanly("encryption required "
3513 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3515 status
= smbd_do_qfsinfo(conn
, req
,
3520 if (!NT_STATUS_IS_OK(status
)) {
3521 reply_nterror(req
, status
);
3525 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3528 DEBUG( 4, ( "%s info_level = %d\n",
3529 smb_fn_name(req
->cmd
), info_level
) );
3534 /****************************************************************************
3535 Reply to a TRANS2_SETFSINFO (set filesystem info).
3536 ****************************************************************************/
3538 static void call_trans2setfsinfo(connection_struct
*conn
,
3539 struct smb_request
*req
,
3540 char **pparams
, int total_params
,
3541 char **ppdata
, int total_data
,
3542 unsigned int max_data_bytes
)
3544 char *pdata
= *ppdata
;
3545 char *params
= *pparams
;
3548 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3551 if (total_params
< 4) {
3552 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3554 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3558 info_level
= SVAL(params
,2);
3561 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3562 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3563 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3564 "info level (0x%x) on IPC$.\n",
3565 (unsigned int)info_level
));
3566 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3571 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3572 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3573 DEBUG(0,("call_trans2setfsinfo: encryption required "
3574 "and info level 0x%x sent.\n",
3575 (unsigned int)info_level
));
3576 exit_server_cleanly("encryption required "
3582 switch(info_level
) {
3583 case SMB_SET_CIFS_UNIX_INFO
:
3585 uint16 client_unix_major
;
3586 uint16 client_unix_minor
;
3587 uint32 client_unix_cap_low
;
3588 uint32 client_unix_cap_high
;
3590 if (!lp_unix_extensions()) {
3592 NT_STATUS_INVALID_LEVEL
);
3596 /* There should be 12 bytes of capabilities set. */
3597 if (total_data
< 8) {
3600 NT_STATUS_INVALID_PARAMETER
);
3603 client_unix_major
= SVAL(pdata
,0);
3604 client_unix_minor
= SVAL(pdata
,2);
3605 client_unix_cap_low
= IVAL(pdata
,4);
3606 client_unix_cap_high
= IVAL(pdata
,8);
3607 /* Just print these values for now. */
3608 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3609 cap_low = 0x%x, cap_high = 0x%x\n",
3610 (unsigned int)client_unix_major
,
3611 (unsigned int)client_unix_minor
,
3612 (unsigned int)client_unix_cap_low
,
3613 (unsigned int)client_unix_cap_high
));
3615 /* Here is where we must switch to posix pathname processing... */
3616 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3617 lp_set_posix_pathnames();
3618 mangle_change_to_posix();
3621 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3622 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3623 /* Client that knows how to do posix locks,
3624 * but not posix open/mkdir operations. Set a
3625 * default type for read/write checks. */
3627 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3633 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3636 size_t param_len
= 0;
3637 size_t data_len
= total_data
;
3639 if (!lp_unix_extensions()) {
3642 NT_STATUS_INVALID_LEVEL
);
3646 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3649 NT_STATUS_NOT_SUPPORTED
);
3653 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3654 DEBUG( 2,("call_trans2setfsinfo: "
3655 "request transport encryption disabled"
3656 "with 'fork echo handler = yes'\n"));
3659 NT_STATUS_NOT_SUPPORTED
);
3663 DEBUG( 4,("call_trans2setfsinfo: "
3664 "request transport encryption.\n"));
3666 status
= srv_request_encryption_setup(conn
,
3667 (unsigned char **)ppdata
,
3669 (unsigned char **)pparams
,
3672 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3673 !NT_STATUS_IS_OK(status
)) {
3674 reply_nterror(req
, status
);
3678 send_trans2_replies(conn
, req
,
3685 if (NT_STATUS_IS_OK(status
)) {
3686 /* Server-side transport
3687 * encryption is now *on*. */
3688 status
= srv_encryption_start(conn
);
3689 if (!NT_STATUS_IS_OK(status
)) {
3690 exit_server_cleanly(
3691 "Failure in setting "
3692 "up encrypted transport");
3698 case SMB_FS_QUOTA_INFORMATION
:
3700 files_struct
*fsp
= NULL
;
3701 SMB_NTQUOTA_STRUCT quotas
;
3703 ZERO_STRUCT(quotas
);
3706 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3707 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3708 lp_servicename(SNUM(conn
)),
3709 conn
->session_info
->unix_name
));
3710 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3714 /* note: normaly there're 48 bytes,
3715 * but we didn't use the last 6 bytes for now
3718 fsp
= file_fsp(req
, SVAL(params
,0));
3720 if (!check_fsp_ntquota_handle(conn
, req
,
3722 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3724 req
, NT_STATUS_INVALID_HANDLE
);
3728 if (total_data
< 42) {
3729 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3733 NT_STATUS_INVALID_PARAMETER
);
3737 /* unknown_1 24 NULL bytes in pdata*/
3739 /* the soft quotas 8 bytes (uint64_t)*/
3740 quotas
.softlim
= BVAL(pdata
,24);
3742 /* the hard quotas 8 bytes (uint64_t)*/
3743 quotas
.hardlim
= BVAL(pdata
,32);
3745 /* quota_flags 2 bytes **/
3746 quotas
.qflags
= SVAL(pdata
,40);
3748 /* unknown_2 6 NULL bytes follow*/
3750 /* now set the quotas */
3751 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3752 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3753 reply_nterror(req
, map_nt_error_from_unix(errno
));
3760 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3762 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3768 * sending this reply works fine,
3769 * but I'm not sure it's the same
3770 * like windows do...
3773 reply_outbuf(req
, 10, 0);
3776 #if defined(HAVE_POSIX_ACLS)
3777 /****************************************************************************
3778 Utility function to count the number of entries in a POSIX acl.
3779 ****************************************************************************/
3781 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3783 unsigned int ace_count
= 0;
3784 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3785 SMB_ACL_ENTRY_T entry
;
3787 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3789 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3790 entry_id
= SMB_ACL_NEXT_ENTRY
;
3797 /****************************************************************************
3798 Utility function to marshall a POSIX acl into wire format.
3799 ****************************************************************************/
3801 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3803 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3804 SMB_ACL_ENTRY_T entry
;
3806 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3807 SMB_ACL_TAG_T tagtype
;
3808 SMB_ACL_PERMSET_T permset
;
3809 unsigned char perms
= 0;
3810 unsigned int own_grp
;
3813 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3814 entry_id
= SMB_ACL_NEXT_ENTRY
;
3817 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3822 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3823 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3827 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3828 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3829 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3831 SCVAL(pdata
,1,perms
);
3834 case SMB_ACL_USER_OBJ
:
3835 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3836 own_grp
= (unsigned int)pst
->st_ex_uid
;
3837 SIVAL(pdata
,2,own_grp
);
3842 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3844 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3847 own_grp
= (unsigned int)*puid
;
3848 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3849 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3850 SIVAL(pdata
,2,own_grp
);
3854 case SMB_ACL_GROUP_OBJ
:
3855 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3856 own_grp
= (unsigned int)pst
->st_ex_gid
;
3857 SIVAL(pdata
,2,own_grp
);
3862 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3864 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3867 own_grp
= (unsigned int)*pgid
;
3868 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3869 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3870 SIVAL(pdata
,2,own_grp
);
3875 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3876 SIVAL(pdata
,2,0xFFFFFFFF);
3877 SIVAL(pdata
,6,0xFFFFFFFF);
3880 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3881 SIVAL(pdata
,2,0xFFFFFFFF);
3882 SIVAL(pdata
,6,0xFFFFFFFF);
3885 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3888 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3895 /****************************************************************************
3896 Store the FILE_UNIX_BASIC info.
3897 ****************************************************************************/
3899 static char *store_file_unix_basic(connection_struct
*conn
,
3902 const SMB_STRUCT_STAT
*psbuf
)
3904 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3906 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3907 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3909 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3912 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3915 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3916 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3917 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3920 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3924 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3928 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3931 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3935 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3939 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3942 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3946 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3953 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3954 * the chflags(2) (or equivalent) flags.
3956 * XXX: this really should be behind the VFS interface. To do this, we would
3957 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3958 * Each VFS module could then implement its own mapping as appropriate for the
3959 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3961 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3965 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3969 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3973 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3977 { UF_HIDDEN
, EXT_HIDDEN
},
3980 /* Do not remove. We need to guarantee that this array has at least one
3981 * entry to build on HP-UX.
3987 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3988 uint32
*smb_fflags
, uint32
*smb_fmask
)
3992 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3993 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3994 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3995 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4000 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4001 const uint32 smb_fflags
,
4002 const uint32 smb_fmask
,
4005 uint32 max_fmask
= 0;
4008 *stat_fflags
= psbuf
->st_ex_flags
;
4010 /* For each flags requested in smb_fmask, check the state of the
4011 * corresponding flag in smb_fflags and set or clear the matching
4015 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4016 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4017 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4018 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4019 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4021 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4026 /* If smb_fmask is asking to set any bits that are not supported by
4027 * our flag mappings, we should fail.
4029 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4037 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4038 * of file flags and birth (create) time.
4040 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4043 const SMB_STRUCT_STAT
*psbuf
)
4045 uint32 file_flags
= 0;
4046 uint32 flags_mask
= 0;
4048 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4050 /* Create (birth) time 64 bit */
4051 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4054 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4055 SIVAL(pdata
, 0, file_flags
); /* flags */
4056 SIVAL(pdata
, 4, flags_mask
); /* mask */
4062 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4063 const struct stream_struct
*streams
,
4065 unsigned int max_data_bytes
,
4066 unsigned int *data_size
)
4069 unsigned int ofs
= 0;
4071 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4072 unsigned int next_offset
;
4074 smb_ucs2_t
*namebuf
;
4076 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4077 streams
[i
].name
, &namelen
) ||
4080 return NT_STATUS_INVALID_PARAMETER
;
4084 * name_buf is now null-terminated, we need to marshall as not
4090 SIVAL(data
, ofs
+4, namelen
);
4091 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4092 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4093 memcpy(data
+ofs
+24, namebuf
, namelen
);
4094 TALLOC_FREE(namebuf
);
4096 next_offset
= ofs
+ 24 + namelen
;
4098 if (i
== num_streams
-1) {
4099 SIVAL(data
, ofs
, 0);
4102 unsigned int align
= ndr_align_size(next_offset
, 8);
4104 memset(data
+next_offset
, 0, align
);
4105 next_offset
+= align
;
4107 SIVAL(data
, ofs
, next_offset
- ofs
);
4116 return NT_STATUS_OK
;
4119 /****************************************************************************
4120 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4121 ****************************************************************************/
4123 static void call_trans2qpipeinfo(connection_struct
*conn
,
4124 struct smb_request
*req
,
4125 unsigned int tran_call
,
4126 char **pparams
, int total_params
,
4127 char **ppdata
, int total_data
,
4128 unsigned int max_data_bytes
)
4130 char *params
= *pparams
;
4131 char *pdata
= *ppdata
;
4132 unsigned int data_size
= 0;
4133 unsigned int param_size
= 2;
4138 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4142 if (total_params
< 4) {
4143 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4147 fsp
= file_fsp(req
, SVAL(params
,0));
4148 if (!fsp_is_np(fsp
)) {
4149 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4153 info_level
= SVAL(params
,2);
4155 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4156 if (*pparams
== NULL
) {
4157 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4162 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4163 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4164 if (*ppdata
== NULL
) {
4165 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4170 switch (info_level
) {
4171 case SMB_FILE_STANDARD_INFORMATION
:
4173 SOFF_T(pdata
,0,4096LL);
4180 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4184 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4190 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4191 TALLOC_CTX
*mem_ctx
,
4192 uint16_t info_level
,
4194 struct smb_filename
*smb_fname
,
4195 bool delete_pending
,
4196 struct timespec write_time_ts
,
4197 struct ea_list
*ea_list
,
4198 int lock_data_count
,
4201 unsigned int max_data_bytes
,
4203 unsigned int *pdata_size
)
4205 char *pdata
= *ppdata
;
4206 char *dstart
, *dend
;
4207 unsigned int data_size
;
4208 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4209 time_t create_time
, mtime
, atime
, c_time
;
4210 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4217 uint64_t file_size
= 0;
4219 uint64_t allocation_size
= 0;
4220 uint64_t file_index
= 0;
4221 uint32_t access_mask
= 0;
4223 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4224 return NT_STATUS_INVALID_LEVEL
;
4227 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4228 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4229 info_level
, max_data_bytes
));
4231 mode
= dos_mode(conn
, smb_fname
);
4232 nlink
= psbuf
->st_ex_nlink
;
4234 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4238 if ((nlink
> 0) && delete_pending
) {
4242 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4243 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4244 if (*ppdata
== NULL
) {
4245 return NT_STATUS_NO_MEMORY
;
4249 dend
= dstart
+ data_size
- 1;
4251 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4252 update_stat_ex_mtime(psbuf
, write_time_ts
);
4255 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4256 mtime_ts
= psbuf
->st_ex_mtime
;
4257 atime_ts
= psbuf
->st_ex_atime
;
4258 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4260 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4261 dos_filetime_timespec(&create_time_ts
);
4262 dos_filetime_timespec(&mtime_ts
);
4263 dos_filetime_timespec(&atime_ts
);
4264 dos_filetime_timespec(&ctime_ts
);
4267 create_time
= convert_timespec_to_time_t(create_time_ts
);
4268 mtime
= convert_timespec_to_time_t(mtime_ts
);
4269 atime
= convert_timespec_to_time_t(atime_ts
);
4270 c_time
= convert_timespec_to_time_t(ctime_ts
);
4272 p
= strrchr_m(smb_fname
->base_name
,'/');
4274 base_name
= smb_fname
->base_name
;
4278 /* NT expects the name to be in an exact form of the *full*
4279 filename. See the trans2 torture test */
4280 if (ISDOT(base_name
)) {
4281 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4283 return NT_STATUS_NO_MEMORY
;
4286 dos_fname
= talloc_asprintf(mem_ctx
,
4288 smb_fname
->base_name
);
4290 return NT_STATUS_NO_MEMORY
;
4292 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4293 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4294 smb_fname
->stream_name
);
4296 return NT_STATUS_NO_MEMORY
;
4300 string_replace(dos_fname
, '/', '\\');
4303 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4306 /* Do we have this path open ? */
4308 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4309 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4310 if (fsp1
&& fsp1
->initial_allocation_size
) {
4311 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4315 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4316 file_size
= get_file_size_stat(psbuf
);
4320 pos
= fsp
->fh
->position_information
;
4324 access_mask
= fsp
->access_mask
;
4326 /* GENERIC_EXECUTE mapping from Windows */
4327 access_mask
= 0x12019F;
4330 /* This should be an index number - looks like
4333 I think this causes us to fail the IFSKIT
4334 BasicFileInformationTest. -tpot */
4335 file_index
= get_FileIndex(conn
, psbuf
);
4337 switch (info_level
) {
4338 case SMB_INFO_STANDARD
:
4339 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4341 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4342 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4343 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4344 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4345 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4346 SSVAL(pdata
,l1_attrFile
,mode
);
4349 case SMB_INFO_QUERY_EA_SIZE
:
4351 unsigned int ea_size
=
4352 estimate_ea_size(conn
, fsp
,
4353 smb_fname
->base_name
);
4354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4356 srv_put_dos_date2(pdata
,0,create_time
);
4357 srv_put_dos_date2(pdata
,4,atime
);
4358 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4359 SIVAL(pdata
,12,(uint32
)file_size
);
4360 SIVAL(pdata
,16,(uint32
)allocation_size
);
4361 SSVAL(pdata
,20,mode
);
4362 SIVAL(pdata
,22,ea_size
);
4366 case SMB_INFO_IS_NAME_VALID
:
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4369 /* os/2 needs this ? really ?*/
4370 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4372 /* This is only reached for qpathinfo */
4376 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4378 size_t total_ea_len
= 0;
4379 struct ea_list
*ea_file_list
= NULL
;
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4384 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4385 smb_fname
->base_name
,
4387 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4389 if (!ea_list
|| (total_ea_len
> data_size
)) {
4391 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4395 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4399 case SMB_INFO_QUERY_ALL_EAS
:
4401 /* We have data_size bytes to put EA's into. */
4402 size_t total_ea_len
= 0;
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4406 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4407 smb_fname
->base_name
,
4409 if (!ea_list
|| (total_ea_len
> data_size
)) {
4411 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4415 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4419 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4421 /* This is FileFullEaInformation - 0xF which maps to
4422 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4424 /* We have data_size bytes to put EA's into. */
4425 size_t total_ea_len
= 0;
4426 struct ea_list
*ea_file_list
= NULL
;
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4430 /*TODO: add filtering and index handling */
4433 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4434 smb_fname
->base_name
,
4436 if (!ea_file_list
) {
4437 return NT_STATUS_NO_EAS_ON_FILE
;
4440 status
= fill_ea_chained_buffer(mem_ctx
,
4444 conn
, ea_file_list
);
4445 if (!NT_STATUS_IS_OK(status
)) {
4451 case SMB_FILE_BASIC_INFORMATION
:
4452 case SMB_QUERY_FILE_BASIC_INFO
:
4454 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4456 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4462 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4463 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4464 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4465 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4466 SIVAL(pdata
,32,mode
);
4468 DEBUG(5,("SMB_QFBI - "));
4469 DEBUG(5,("create: %s ", ctime(&create_time
)));
4470 DEBUG(5,("access: %s ", ctime(&atime
)));
4471 DEBUG(5,("write: %s ", ctime(&mtime
)));
4472 DEBUG(5,("change: %s ", ctime(&c_time
)));
4473 DEBUG(5,("mode: %x\n", mode
));
4476 case SMB_FILE_STANDARD_INFORMATION
:
4477 case SMB_QUERY_FILE_STANDARD_INFO
:
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4481 SOFF_T(pdata
,0,allocation_size
);
4482 SOFF_T(pdata
,8,file_size
);
4483 SIVAL(pdata
,16,nlink
);
4484 SCVAL(pdata
,20,delete_pending
?1:0);
4485 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4486 SSVAL(pdata
,22,0); /* Padding. */
4489 case SMB_FILE_EA_INFORMATION
:
4490 case SMB_QUERY_FILE_EA_INFO
:
4492 unsigned int ea_size
=
4493 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4496 SIVAL(pdata
,0,ea_size
);
4500 /* Get the 8.3 name - used if NT SMB was negotiated. */
4501 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4502 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4505 char mangled_name
[13];
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4507 if (!name_to_8_3(base_name
,mangled_name
,
4508 True
,conn
->params
)) {
4509 return NT_STATUS_NO_MEMORY
;
4511 len
= srvstr_push(dstart
, flags2
,
4512 pdata
+4, mangled_name
,
4513 PTR_DIFF(dend
, pdata
+4),
4515 data_size
= 4 + len
;
4520 case SMB_QUERY_FILE_NAME_INFO
:
4524 this must be *exactly* right for ACLs on mapped drives to work
4526 len
= srvstr_push(dstart
, flags2
,
4528 PTR_DIFF(dend
, pdata
+4),
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4531 data_size
= 4 + len
;
4536 case SMB_FILE_ALLOCATION_INFORMATION
:
4537 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4540 SOFF_T(pdata
,0,allocation_size
);
4543 case SMB_FILE_END_OF_FILE_INFORMATION
:
4544 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4547 SOFF_T(pdata
,0,file_size
);
4550 case SMB_QUERY_FILE_ALL_INFO
:
4551 case SMB_FILE_ALL_INFORMATION
:
4554 unsigned int ea_size
=
4555 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4557 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4558 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4559 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4560 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4561 SIVAL(pdata
,32,mode
);
4562 SIVAL(pdata
,36,0); /* padding. */
4564 SOFF_T(pdata
,0,allocation_size
);
4565 SOFF_T(pdata
,8,file_size
);
4566 SIVAL(pdata
,16,nlink
);
4567 SCVAL(pdata
,20,delete_pending
);
4568 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4571 SIVAL(pdata
,0,ea_size
);
4572 pdata
+= 4; /* EA info */
4573 len
= srvstr_push(dstart
, flags2
,
4575 PTR_DIFF(dend
, pdata
+4),
4579 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4583 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4586 unsigned int ea_size
=
4587 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4589 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4590 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4591 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4592 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4593 SIVAL(pdata
, 0x20, mode
);
4594 SIVAL(pdata
, 0x24, 0); /* padding. */
4595 SBVAL(pdata
, 0x28, allocation_size
);
4596 SBVAL(pdata
, 0x30, file_size
);
4597 SIVAL(pdata
, 0x38, nlink
);
4598 SCVAL(pdata
, 0x3C, delete_pending
);
4599 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4600 SSVAL(pdata
, 0x3E, 0); /* padding */
4601 SBVAL(pdata
, 0x40, file_index
);
4602 SIVAL(pdata
, 0x48, ea_size
);
4603 SIVAL(pdata
, 0x4C, access_mask
);
4604 SBVAL(pdata
, 0x50, pos
);
4605 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4606 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4610 len
= srvstr_push(dstart
, flags2
,
4612 PTR_DIFF(dend
, pdata
+4),
4616 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4619 case SMB_FILE_INTERNAL_INFORMATION
:
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4622 SBVAL(pdata
, 0, file_index
);
4626 case SMB_FILE_ACCESS_INFORMATION
:
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4628 SIVAL(pdata
, 0, access_mask
);
4632 case SMB_FILE_NAME_INFORMATION
:
4633 /* Pathname with leading '\'. */
4636 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4638 SIVAL(pdata
,0,byte_len
);
4639 data_size
= 4 + byte_len
;
4643 case SMB_FILE_DISPOSITION_INFORMATION
:
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4646 SCVAL(pdata
,0,delete_pending
);
4649 case SMB_FILE_POSITION_INFORMATION
:
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4652 SOFF_T(pdata
,0,pos
);
4655 case SMB_FILE_MODE_INFORMATION
:
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4657 SIVAL(pdata
,0,mode
);
4661 case SMB_FILE_ALIGNMENT_INFORMATION
:
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4663 SIVAL(pdata
,0,0); /* No alignment needed. */
4668 * NT4 server just returns "invalid query" to this - if we try
4669 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4672 /* The first statement above is false - verified using Thursby
4673 * client against NT4 -- gcolley.
4675 case SMB_QUERY_FILE_STREAM_INFO
:
4676 case SMB_FILE_STREAM_INFORMATION
: {
4677 unsigned int num_streams
= 0;
4678 struct stream_struct
*streams
= NULL
;
4680 DEBUG(10,("smbd_do_qfilepathinfo: "
4681 "SMB_FILE_STREAM_INFORMATION\n"));
4683 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4684 return NT_STATUS_INVALID_PARAMETER
;
4687 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4688 talloc_tos(), &num_streams
, &streams
);
4690 if (!NT_STATUS_IS_OK(status
)) {
4691 DEBUG(10, ("could not get stream info: %s\n",
4692 nt_errstr(status
)));
4696 status
= marshall_stream_info(num_streams
, streams
,
4697 pdata
, max_data_bytes
,
4700 if (!NT_STATUS_IS_OK(status
)) {
4701 DEBUG(10, ("marshall_stream_info failed: %s\n",
4702 nt_errstr(status
)));
4706 TALLOC_FREE(streams
);
4710 case SMB_QUERY_COMPRESSION_INFO
:
4711 case SMB_FILE_COMPRESSION_INFORMATION
:
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4713 SOFF_T(pdata
,0,file_size
);
4714 SIVAL(pdata
,8,0); /* ??? */
4715 SIVAL(pdata
,12,0); /* ??? */
4719 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4721 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4722 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4723 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4724 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4725 SOFF_T(pdata
,32,allocation_size
);
4726 SOFF_T(pdata
,40,file_size
);
4727 SIVAL(pdata
,48,mode
);
4728 SIVAL(pdata
,52,0); /* ??? */
4732 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4734 SIVAL(pdata
,0,mode
);
4740 * CIFS UNIX Extensions.
4743 case SMB_QUERY_FILE_UNIX_BASIC
:
4745 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4746 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4748 DEBUG(4,("smbd_do_qfilepathinfo: "
4749 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4750 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4754 case SMB_QUERY_FILE_UNIX_INFO2
:
4756 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4757 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4761 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4763 for (i
=0; i
<100; i
++)
4764 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4770 case SMB_QUERY_FILE_UNIX_LINK
:
4773 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4776 return NT_STATUS_NO_MEMORY
;
4779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4781 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4782 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4785 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4787 len
= SMB_VFS_READLINK(conn
,
4788 smb_fname
->base_name
,
4791 return map_nt_error_from_unix(errno
);
4794 len
= srvstr_push(dstart
, flags2
,
4796 PTR_DIFF(dend
, pdata
),
4799 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4804 #if defined(HAVE_POSIX_ACLS)
4805 case SMB_QUERY_POSIX_ACL
:
4807 SMB_ACL_T file_acl
= NULL
;
4808 SMB_ACL_T def_acl
= NULL
;
4809 uint16 num_file_acls
= 0;
4810 uint16 num_def_acls
= 0;
4812 if (fsp
&& fsp
->fh
->fd
!= -1) {
4813 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4816 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4817 smb_fname
->base_name
,
4818 SMB_ACL_TYPE_ACCESS
);
4821 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4822 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4823 "not implemented on "
4824 "filesystem containing %s\n",
4825 smb_fname
->base_name
));
4826 return NT_STATUS_NOT_IMPLEMENTED
;
4829 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4830 if (fsp
&& fsp
->is_directory
) {
4832 SMB_VFS_SYS_ACL_GET_FILE(
4834 fsp
->fsp_name
->base_name
,
4835 SMB_ACL_TYPE_DEFAULT
);
4838 SMB_VFS_SYS_ACL_GET_FILE(
4840 smb_fname
->base_name
,
4841 SMB_ACL_TYPE_DEFAULT
);
4843 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4846 num_file_acls
= count_acl_entries(conn
, file_acl
);
4847 num_def_acls
= count_acl_entries(conn
, def_acl
);
4849 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4850 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4852 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4853 SMB_POSIX_ACL_HEADER_SIZE
) ));
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4860 return NT_STATUS_BUFFER_TOO_SMALL
;
4863 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4864 SSVAL(pdata
,2,num_file_acls
);
4865 SSVAL(pdata
,4,num_def_acls
);
4866 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4871 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4873 return NT_STATUS_INTERNAL_ERROR
;
4875 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4880 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4882 return NT_STATUS_INTERNAL_ERROR
;
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4889 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4891 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4897 case SMB_QUERY_POSIX_LOCK
:
4902 enum brl_type lock_type
;
4904 /* We need an open file with a real fd for this. */
4905 if (!fsp
|| fsp
->fh
->fd
== -1) {
4906 return NT_STATUS_INVALID_LEVEL
;
4909 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4910 return NT_STATUS_INVALID_PARAMETER
;
4913 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4914 case POSIX_LOCK_TYPE_READ
:
4915 lock_type
= READ_LOCK
;
4917 case POSIX_LOCK_TYPE_WRITE
:
4918 lock_type
= WRITE_LOCK
;
4920 case POSIX_LOCK_TYPE_UNLOCK
:
4922 /* There's no point in asking for an unlock... */
4923 return NT_STATUS_INVALID_PARAMETER
;
4926 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4927 #if defined(HAVE_LONGLONG)
4928 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4929 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4930 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4931 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4932 #else /* HAVE_LONGLONG */
4933 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4934 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4935 #endif /* HAVE_LONGLONG */
4937 status
= query_lock(fsp
,
4944 if (ERROR_WAS_LOCK_DENIED(status
)) {
4945 /* Here we need to report who has it locked... */
4946 data_size
= POSIX_LOCK_DATA_SIZE
;
4948 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4949 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4950 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4951 #if defined(HAVE_LONGLONG)
4952 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4953 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4954 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4955 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4956 #else /* HAVE_LONGLONG */
4957 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4958 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4959 #endif /* HAVE_LONGLONG */
4961 } else if (NT_STATUS_IS_OK(status
)) {
4962 /* For success we just return a copy of what we sent
4963 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4964 data_size
= POSIX_LOCK_DATA_SIZE
;
4965 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4966 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4974 return NT_STATUS_INVALID_LEVEL
;
4977 *pdata_size
= data_size
;
4978 return NT_STATUS_OK
;
4981 /****************************************************************************
4982 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4983 file name or file id).
4984 ****************************************************************************/
4986 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4987 struct smb_request
*req
,
4988 unsigned int tran_call
,
4989 char **pparams
, int total_params
,
4990 char **ppdata
, int total_data
,
4991 unsigned int max_data_bytes
)
4993 char *params
= *pparams
;
4994 char *pdata
= *ppdata
;
4996 unsigned int data_size
= 0;
4997 unsigned int param_size
= 2;
4998 struct smb_filename
*smb_fname
= NULL
;
4999 bool delete_pending
= False
;
5000 struct timespec write_time_ts
;
5001 files_struct
*fsp
= NULL
;
5002 struct file_id fileid
;
5003 struct ea_list
*ea_list
= NULL
;
5004 int lock_data_count
= 0;
5005 char *lock_data
= NULL
;
5006 NTSTATUS status
= NT_STATUS_OK
;
5009 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5013 ZERO_STRUCT(write_time_ts
);
5015 if (tran_call
== TRANSACT2_QFILEINFO
) {
5016 if (total_params
< 4) {
5017 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5022 call_trans2qpipeinfo(conn
, req
, tran_call
,
5023 pparams
, total_params
,
5029 fsp
= file_fsp(req
, SVAL(params
,0));
5030 info_level
= SVAL(params
,2);
5032 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5034 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5035 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5039 /* Initial check for valid fsp ptr. */
5040 if (!check_fsp_open(conn
, req
, fsp
)) {
5044 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5046 if (!NT_STATUS_IS_OK(status
)) {
5047 reply_nterror(req
, status
);
5051 if(fsp
->fake_file_handle
) {
5053 * This is actually for the QUOTA_FAKE_FILE --metze
5056 /* We know this name is ok, it's already passed the checks. */
5058 } else if(fsp
->fh
->fd
== -1) {
5060 * This is actually a QFILEINFO on a directory
5061 * handle (returned from an NT SMB). NT5.0 seems
5062 * to do this call. JRA.
5065 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5066 /* Always do lstat for UNIX calls. */
5067 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5068 DEBUG(3,("call_trans2qfilepathinfo: "
5069 "SMB_VFS_LSTAT of %s failed "
5071 smb_fname_str_dbg(smb_fname
),
5074 map_nt_error_from_unix(errno
));
5077 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5078 DEBUG(3,("call_trans2qfilepathinfo: "
5079 "SMB_VFS_STAT of %s failed (%s)\n",
5080 smb_fname_str_dbg(smb_fname
),
5083 map_nt_error_from_unix(errno
));
5087 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5088 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5091 * Original code - this is an open file.
5093 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5094 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5095 fsp
->fnum
, strerror(errno
)));
5097 map_nt_error_from_unix(errno
));
5100 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5101 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5107 uint32_t ucf_flags
= 0;
5110 if (total_params
< 7) {
5111 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5115 info_level
= SVAL(params
,0);
5117 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5119 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5120 if (!lp_unix_extensions()) {
5121 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5124 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5125 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5126 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5127 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5131 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5133 STR_TERMINATE
, &status
);
5134 if (!NT_STATUS_IS_OK(status
)) {
5135 reply_nterror(req
, status
);
5139 status
= filename_convert(req
,
5141 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5146 if (!NT_STATUS_IS_OK(status
)) {
5147 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5148 reply_botherror(req
,
5149 NT_STATUS_PATH_NOT_COVERED
,
5150 ERRSRV
, ERRbadpath
);
5153 reply_nterror(req
, status
);
5157 /* If this is a stream, check if there is a delete_pending. */
5158 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5159 && is_ntfs_stream_smb_fname(smb_fname
)) {
5160 struct smb_filename
*smb_fname_base
= NULL
;
5162 /* Create an smb_filename with stream_name == NULL. */
5164 create_synthetic_smb_fname(talloc_tos(),
5165 smb_fname
->base_name
,
5168 if (!NT_STATUS_IS_OK(status
)) {
5169 reply_nterror(req
, status
);
5173 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5174 /* Always do lstat for UNIX calls. */
5175 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5176 DEBUG(3,("call_trans2qfilepathinfo: "
5177 "SMB_VFS_LSTAT of %s failed "
5179 smb_fname_str_dbg(smb_fname_base
),
5181 TALLOC_FREE(smb_fname_base
);
5183 map_nt_error_from_unix(errno
));
5187 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "fileinfo of %s failed "
5191 smb_fname_str_dbg(smb_fname_base
),
5193 TALLOC_FREE(smb_fname_base
);
5195 map_nt_error_from_unix(errno
));
5200 status
= file_name_hash(conn
,
5201 smb_fname_str_dbg(smb_fname_base
),
5203 if (!NT_STATUS_IS_OK(status
)) {
5204 TALLOC_FREE(smb_fname_base
);
5205 reply_nterror(req
, status
);
5209 fileid
= vfs_file_id_from_sbuf(conn
,
5210 &smb_fname_base
->st
);
5211 TALLOC_FREE(smb_fname_base
);
5212 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5213 if (delete_pending
) {
5214 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5219 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname
),
5227 map_nt_error_from_unix(errno
));
5232 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname
),
5238 map_nt_error_from_unix(errno
));
5243 status
= file_name_hash(conn
,
5244 smb_fname_str_dbg(smb_fname
),
5246 if (!NT_STATUS_IS_OK(status
)) {
5247 reply_nterror(req
, status
);
5251 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5252 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5253 if (delete_pending
) {
5254 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5259 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5260 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5261 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5263 /* Pull out any data sent here before we realloc. */
5264 switch (info_level
) {
5265 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5267 /* Pull any EA list from the data portion. */
5270 if (total_data
< 4) {
5272 req
, NT_STATUS_INVALID_PARAMETER
);
5275 ea_size
= IVAL(pdata
,0);
5277 if (total_data
> 0 && ea_size
!= total_data
) {
5278 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5279 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5281 req
, NT_STATUS_INVALID_PARAMETER
);
5285 if (!lp_ea_support(SNUM(conn
))) {
5286 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5290 /* Pull out the list of names. */
5291 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5294 req
, NT_STATUS_INVALID_PARAMETER
);
5300 case SMB_QUERY_POSIX_LOCK
:
5302 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5303 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5307 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5309 req
, NT_STATUS_INVALID_PARAMETER
);
5313 /* Copy the lock range data. */
5314 lock_data
= (char *)TALLOC_MEMDUP(
5315 req
, pdata
, total_data
);
5317 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5320 lock_data_count
= total_data
;
5326 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5327 if (*pparams
== NULL
) {
5328 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5335 * draft-leach-cifs-v1-spec-02.txt
5336 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5339 * The requested information is placed in the Data portion of the
5340 * transaction response. For the information levels greater than 0x100,
5341 * the transaction response has 1 parameter word which should be
5342 * ignored by the client.
5344 * However Windows only follows this rule for the IS_NAME_VALID call.
5346 switch (info_level
) {
5347 case SMB_INFO_IS_NAME_VALID
:
5352 if ((info_level
& 0xFF00) == 0xFF00) {
5354 * We use levels that start with 0xFF00
5355 * internally to represent SMB2 specific levels
5357 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5361 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5363 delete_pending
, write_time_ts
,
5365 lock_data_count
, lock_data
,
5366 req
->flags2
, max_data_bytes
,
5367 ppdata
, &data_size
);
5368 if (!NT_STATUS_IS_OK(status
)) {
5369 reply_nterror(req
, status
);
5373 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5379 /****************************************************************************
5380 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5382 ****************************************************************************/
5384 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5385 connection_struct
*conn
,
5386 struct smb_request
*req
,
5387 bool overwrite_if_exists
,
5388 const struct smb_filename
*smb_fname_old
,
5389 struct smb_filename
*smb_fname_new
)
5391 NTSTATUS status
= NT_STATUS_OK
;
5393 /* source must already exist. */
5394 if (!VALID_STAT(smb_fname_old
->st
)) {
5395 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5398 if (VALID_STAT(smb_fname_new
->st
)) {
5399 if (overwrite_if_exists
) {
5400 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5401 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5403 status
= unlink_internals(conn
,
5405 FILE_ATTRIBUTE_NORMAL
,
5408 if (!NT_STATUS_IS_OK(status
)) {
5412 /* Disallow if newname already exists. */
5413 return NT_STATUS_OBJECT_NAME_COLLISION
;
5417 /* No links from a directory. */
5418 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5419 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5422 /* Setting a hardlink to/from a stream isn't currently supported. */
5423 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5424 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5425 return NT_STATUS_INVALID_PARAMETER
;
5428 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5429 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5431 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5432 smb_fname_new
->base_name
) != 0) {
5433 status
= map_nt_error_from_unix(errno
);
5434 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5435 nt_errstr(status
), smb_fname_old
->base_name
,
5436 smb_fname_new
->base_name
));
5441 /****************************************************************************
5442 Deal with setting the time from any of the setfilepathinfo functions.
5443 ****************************************************************************/
5445 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5447 const struct smb_filename
*smb_fname
,
5448 struct smb_file_time
*ft
,
5449 bool setting_write_time
)
5451 struct smb_filename smb_fname_base
;
5453 FILE_NOTIFY_CHANGE_LAST_ACCESS
5454 |FILE_NOTIFY_CHANGE_LAST_WRITE
5455 |FILE_NOTIFY_CHANGE_CREATION
;
5457 if (!VALID_STAT(smb_fname
->st
)) {
5458 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5461 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5462 return NT_STATUS_ACCESS_DENIED
;
5465 /* get some defaults (no modifications) if any info is zero or -1. */
5466 if (null_timespec(ft
->create_time
)) {
5467 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5470 if (null_timespec(ft
->atime
)) {
5471 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5474 if (null_timespec(ft
->mtime
)) {
5475 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5478 if (!setting_write_time
) {
5479 /* ft->mtime comes from change time, not write time. */
5480 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5483 /* Ensure the resolution is the correct for
5484 * what we can store on this filesystem. */
5486 round_timespec(conn
->ts_res
, &ft
->create_time
);
5487 round_timespec(conn
->ts_res
, &ft
->ctime
);
5488 round_timespec(conn
->ts_res
, &ft
->atime
);
5489 round_timespec(conn
->ts_res
, &ft
->mtime
);
5491 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5492 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5493 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5494 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5495 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5496 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5497 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5498 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5500 if (setting_write_time
) {
5502 * This was a Windows setfileinfo on an open file.
5503 * NT does this a lot. We also need to
5504 * set the time here, as it can be read by
5505 * FindFirst/FindNext and with the patch for bug #2045
5506 * in smbd/fileio.c it ensures that this timestamp is
5507 * kept sticky even after a write. We save the request
5508 * away and will set it on file close and after a write. JRA.
5511 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5512 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5515 if (fsp
->base_fsp
) {
5516 set_sticky_write_time_fsp(fsp
->base_fsp
,
5519 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5522 set_sticky_write_time_path(
5523 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5528 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5530 /* Always call ntimes on the base, even if a stream was passed in. */
5531 smb_fname_base
= *smb_fname
;
5532 smb_fname_base
.stream_name
= NULL
;
5534 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5535 return map_nt_error_from_unix(errno
);
5538 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5539 smb_fname
->base_name
);
5540 return NT_STATUS_OK
;
5543 /****************************************************************************
5544 Deal with setting the dosmode from any of the setfilepathinfo functions.
5545 ****************************************************************************/
5547 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5548 const struct smb_filename
*smb_fname
,
5551 struct smb_filename
*smb_fname_base
= NULL
;
5554 if (!VALID_STAT(smb_fname
->st
)) {
5555 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5558 /* Always operate on the base_name, even if a stream was passed in. */
5559 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5560 NULL
, &smb_fname
->st
,
5562 if (!NT_STATUS_IS_OK(status
)) {
5567 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5568 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5570 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5574 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5576 /* check the mode isn't different, before changing it */
5577 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5578 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5579 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5580 (unsigned int)dosmode
));
5582 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5584 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5586 smb_fname_str_dbg(smb_fname_base
),
5588 status
= map_nt_error_from_unix(errno
);
5592 status
= NT_STATUS_OK
;
5594 TALLOC_FREE(smb_fname_base
);
5598 /****************************************************************************
5599 Deal with setting the size from any of the setfilepathinfo functions.
5600 ****************************************************************************/
5602 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5603 struct smb_request
*req
,
5605 const struct smb_filename
*smb_fname
,
5606 const SMB_STRUCT_STAT
*psbuf
,
5608 bool fail_after_createfile
)
5610 NTSTATUS status
= NT_STATUS_OK
;
5611 struct smb_filename
*smb_fname_tmp
= NULL
;
5612 files_struct
*new_fsp
= NULL
;
5614 if (!VALID_STAT(*psbuf
)) {
5615 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5618 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5619 return NT_STATUS_ACCESS_DENIED
;
5622 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5624 if (size
== get_file_size_stat(psbuf
)) {
5625 return NT_STATUS_OK
;
5628 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5629 smb_fname_str_dbg(smb_fname
), (double)size
));
5631 if (fsp
&& fsp
->fh
->fd
!= -1) {
5632 /* Handle based call. */
5633 if (vfs_set_filelen(fsp
, size
) == -1) {
5634 return map_nt_error_from_unix(errno
);
5636 trigger_write_time_update_immediate(fsp
);
5637 return NT_STATUS_OK
;
5640 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5641 if (!NT_STATUS_IS_OK(status
)) {
5645 smb_fname_tmp
->st
= *psbuf
;
5647 status
= SMB_VFS_CREATE_FILE(
5650 0, /* root_dir_fid */
5651 smb_fname_tmp
, /* fname */
5652 FILE_WRITE_DATA
, /* access_mask */
5653 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5655 FILE_OPEN
, /* create_disposition*/
5656 0, /* create_options */
5657 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5658 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5659 0, /* allocation_size */
5660 0, /* private_flags */
5663 &new_fsp
, /* result */
5666 TALLOC_FREE(smb_fname_tmp
);
5668 if (!NT_STATUS_IS_OK(status
)) {
5669 /* NB. We check for open_was_deferred in the caller. */
5673 /* See RAW-SFILEINFO-END-OF-FILE */
5674 if (fail_after_createfile
) {
5675 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5676 return NT_STATUS_INVALID_LEVEL
;
5679 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5680 status
= map_nt_error_from_unix(errno
);
5681 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5685 trigger_write_time_update_immediate(new_fsp
);
5686 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5687 return NT_STATUS_OK
;
5690 /****************************************************************************
5691 Deal with SMB_INFO_SET_EA.
5692 ****************************************************************************/
5694 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5698 const struct smb_filename
*smb_fname
)
5700 struct ea_list
*ea_list
= NULL
;
5701 TALLOC_CTX
*ctx
= NULL
;
5702 NTSTATUS status
= NT_STATUS_OK
;
5704 if (total_data
< 10) {
5706 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5707 length. They seem to have no effect. Bug #3212. JRA */
5709 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5710 /* We're done. We only get EA info in this call. */
5711 return NT_STATUS_OK
;
5714 return NT_STATUS_INVALID_PARAMETER
;
5717 if (IVAL(pdata
,0) > total_data
) {
5718 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5719 IVAL(pdata
,0), (unsigned int)total_data
));
5720 return NT_STATUS_INVALID_PARAMETER
;
5724 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5726 return NT_STATUS_INVALID_PARAMETER
;
5729 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5730 return NT_STATUS_ACCESS_DENIED
;
5733 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5738 /****************************************************************************
5739 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5740 ****************************************************************************/
5742 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5747 struct ea_list
*ea_list
= NULL
;
5751 return NT_STATUS_INVALID_HANDLE
;
5754 if (!lp_ea_support(SNUM(conn
))) {
5755 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5756 "EA's not supported.\n",
5757 (unsigned int)total_data
));
5758 return NT_STATUS_EAS_NOT_SUPPORTED
;
5761 if (total_data
< 10) {
5762 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5764 (unsigned int)total_data
));
5765 return NT_STATUS_INVALID_PARAMETER
;
5768 ea_list
= read_nttrans_ea_list(talloc_tos(),
5773 return NT_STATUS_INVALID_PARAMETER
;
5776 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5777 return NT_STATUS_ACCESS_DENIED
;
5780 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5782 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5783 smb_fname_str_dbg(fsp
->fsp_name
),
5784 nt_errstr(status
) ));
5790 /****************************************************************************
5791 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5792 ****************************************************************************/
5794 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5798 struct smb_filename
*smb_fname
)
5800 NTSTATUS status
= NT_STATUS_OK
;
5801 bool delete_on_close
;
5804 if (total_data
< 1) {
5805 return NT_STATUS_INVALID_PARAMETER
;
5809 return NT_STATUS_INVALID_HANDLE
;
5812 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5813 dosmode
= dos_mode(conn
, smb_fname
);
5815 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5816 "delete_on_close = %u\n",
5817 smb_fname_str_dbg(smb_fname
),
5818 (unsigned int)dosmode
,
5819 (unsigned int)delete_on_close
));
5821 if (delete_on_close
) {
5822 status
= can_set_delete_on_close(fsp
, dosmode
);
5823 if (!NT_STATUS_IS_OK(status
)) {
5828 /* The set is across all open files on this dev/inode pair. */
5829 if (!set_delete_on_close(fsp
, delete_on_close
,
5830 &conn
->session_info
->utok
)) {
5831 return NT_STATUS_ACCESS_DENIED
;
5833 return NT_STATUS_OK
;
5836 /****************************************************************************
5837 Deal with SMB_FILE_POSITION_INFORMATION.
5838 ****************************************************************************/
5840 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5845 uint64_t position_information
;
5847 if (total_data
< 8) {
5848 return NT_STATUS_INVALID_PARAMETER
;
5852 /* Ignore on pathname based set. */
5853 return NT_STATUS_OK
;
5856 position_information
= (uint64_t)IVAL(pdata
,0);
5857 #ifdef LARGE_SMB_OFF_T
5858 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5859 #else /* LARGE_SMB_OFF_T */
5860 if (IVAL(pdata
,4) != 0) {
5861 /* more than 32 bits? */
5862 return NT_STATUS_INVALID_PARAMETER
;
5864 #endif /* LARGE_SMB_OFF_T */
5866 DEBUG(10,("smb_file_position_information: Set file position "
5867 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5868 (double)position_information
));
5869 fsp
->fh
->position_information
= position_information
;
5870 return NT_STATUS_OK
;
5873 /****************************************************************************
5874 Deal with SMB_FILE_MODE_INFORMATION.
5875 ****************************************************************************/
5877 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5883 if (total_data
< 4) {
5884 return NT_STATUS_INVALID_PARAMETER
;
5886 mode
= IVAL(pdata
,0);
5887 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5888 return NT_STATUS_INVALID_PARAMETER
;
5890 return NT_STATUS_OK
;
5893 /****************************************************************************
5894 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5895 ****************************************************************************/
5897 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5898 struct smb_request
*req
,
5901 const struct smb_filename
*smb_fname
)
5903 char *link_target
= NULL
;
5904 const char *newname
= smb_fname
->base_name
;
5905 TALLOC_CTX
*ctx
= talloc_tos();
5907 /* Set a symbolic link. */
5908 /* Don't allow this if follow links is false. */
5910 if (total_data
== 0) {
5911 return NT_STATUS_INVALID_PARAMETER
;
5914 if (!lp_symlinks(SNUM(conn
))) {
5915 return NT_STATUS_ACCESS_DENIED
;
5918 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5919 total_data
, STR_TERMINATE
);
5922 return NT_STATUS_INVALID_PARAMETER
;
5925 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5926 newname
, link_target
));
5928 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5929 return map_nt_error_from_unix(errno
);
5932 return NT_STATUS_OK
;
5935 /****************************************************************************
5936 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5937 ****************************************************************************/
5939 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5940 struct smb_request
*req
,
5941 const char *pdata
, int total_data
,
5942 struct smb_filename
*smb_fname_new
)
5944 char *oldname
= NULL
;
5945 struct smb_filename
*smb_fname_old
= NULL
;
5946 TALLOC_CTX
*ctx
= talloc_tos();
5947 NTSTATUS status
= NT_STATUS_OK
;
5949 /* Set a hard link. */
5950 if (total_data
== 0) {
5951 return NT_STATUS_INVALID_PARAMETER
;
5954 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5955 total_data
, STR_TERMINATE
, &status
);
5956 if (!NT_STATUS_IS_OK(status
)) {
5960 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5961 smb_fname_str_dbg(smb_fname_new
), oldname
));
5963 status
= filename_convert(ctx
,
5965 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5970 if (!NT_STATUS_IS_OK(status
)) {
5974 return hardlink_internals(ctx
, conn
, req
, false,
5975 smb_fname_old
, smb_fname_new
);
5978 /****************************************************************************
5979 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5980 ****************************************************************************/
5982 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5983 struct smb_request
*req
,
5987 struct smb_filename
*smb_fname_src
)
5991 char *newname
= NULL
;
5992 struct smb_filename
*smb_fname_dst
= NULL
;
5993 NTSTATUS status
= NT_STATUS_OK
;
5994 TALLOC_CTX
*ctx
= talloc_tos();
5997 return NT_STATUS_INVALID_HANDLE
;
6000 if (total_data
< 20) {
6001 return NT_STATUS_INVALID_PARAMETER
;
6004 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6005 len
= IVAL(pdata
,16);
6007 if (len
> (total_data
- 20) || (len
== 0)) {
6008 return NT_STATUS_INVALID_PARAMETER
;
6011 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6012 &pdata
[20], len
, STR_TERMINATE
,
6014 if (!NT_STATUS_IS_OK(status
)) {
6018 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6021 status
= filename_convert(ctx
,
6023 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6028 if (!NT_STATUS_IS_OK(status
)) {
6032 if (fsp
->base_fsp
) {
6033 /* newname must be a stream name. */
6034 if (newname
[0] != ':') {
6035 return NT_STATUS_NOT_SUPPORTED
;
6038 /* Create an smb_fname to call rename_internals_fsp() with. */
6039 status
= create_synthetic_smb_fname(talloc_tos(),
6040 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6042 if (!NT_STATUS_IS_OK(status
)) {
6047 * Set the original last component, since
6048 * rename_internals_fsp() requires it.
6050 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6052 if (smb_fname_dst
->original_lcomp
== NULL
) {
6053 status
= NT_STATUS_NO_MEMORY
;
6059 DEBUG(10,("smb2_file_rename_information: "
6060 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6061 fsp
->fnum
, fsp_str_dbg(fsp
),
6062 smb_fname_str_dbg(smb_fname_dst
)));
6063 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6064 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6068 TALLOC_FREE(smb_fname_dst
);
6072 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6073 struct smb_request
*req
,
6077 struct smb_filename
*smb_fname_src
)
6081 char *newname
= NULL
;
6082 struct smb_filename
*smb_fname_dst
= NULL
;
6083 NTSTATUS status
= NT_STATUS_OK
;
6084 TALLOC_CTX
*ctx
= talloc_tos();
6087 return NT_STATUS_INVALID_HANDLE
;
6090 if (total_data
< 20) {
6091 return NT_STATUS_INVALID_PARAMETER
;
6094 overwrite
= (CVAL(pdata
,0) ? true : false);
6095 len
= IVAL(pdata
,16);
6097 if (len
> (total_data
- 20) || (len
== 0)) {
6098 return NT_STATUS_INVALID_PARAMETER
;
6101 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6102 &pdata
[20], len
, STR_TERMINATE
,
6104 if (!NT_STATUS_IS_OK(status
)) {
6108 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6111 status
= filename_convert(ctx
,
6113 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6118 if (!NT_STATUS_IS_OK(status
)) {
6122 if (fsp
->base_fsp
) {
6123 /* No stream names. */
6124 return NT_STATUS_NOT_SUPPORTED
;
6127 DEBUG(10,("smb_file_link_information: "
6128 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6129 fsp
->fnum
, fsp_str_dbg(fsp
),
6130 smb_fname_str_dbg(smb_fname_dst
)));
6131 status
= hardlink_internals(ctx
,
6138 TALLOC_FREE(smb_fname_dst
);
6142 /****************************************************************************
6143 Deal with SMB_FILE_RENAME_INFORMATION.
6144 ****************************************************************************/
6146 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6147 struct smb_request
*req
,
6151 struct smb_filename
*smb_fname_src
)
6156 char *newname
= NULL
;
6157 struct smb_filename
*smb_fname_dst
= NULL
;
6158 bool dest_has_wcard
= False
;
6159 NTSTATUS status
= NT_STATUS_OK
;
6161 TALLOC_CTX
*ctx
= talloc_tos();
6163 if (total_data
< 13) {
6164 return NT_STATUS_INVALID_PARAMETER
;
6167 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6168 root_fid
= IVAL(pdata
,4);
6169 len
= IVAL(pdata
,8);
6171 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6172 return NT_STATUS_INVALID_PARAMETER
;
6175 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6178 if (!NT_STATUS_IS_OK(status
)) {
6182 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6185 status
= resolve_dfspath_wcard(ctx
, conn
,
6186 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6191 if (!NT_STATUS_IS_OK(status
)) {
6195 /* Check the new name has no '/' characters. */
6196 if (strchr_m(newname
, '/')) {
6197 return NT_STATUS_NOT_SUPPORTED
;
6200 if (fsp
&& fsp
->base_fsp
) {
6201 /* newname must be a stream name. */
6202 if (newname
[0] != ':') {
6203 return NT_STATUS_NOT_SUPPORTED
;
6206 /* Create an smb_fname to call rename_internals_fsp() with. */
6207 status
= create_synthetic_smb_fname(talloc_tos(),
6208 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6210 if (!NT_STATUS_IS_OK(status
)) {
6215 * Set the original last component, since
6216 * rename_internals_fsp() requires it.
6218 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6220 if (smb_fname_dst
->original_lcomp
== NULL
) {
6221 status
= NT_STATUS_NO_MEMORY
;
6227 * Build up an smb_fname_dst based on the filename passed in.
6228 * We basically just strip off the last component, and put on
6229 * the newname instead.
6231 char *base_name
= NULL
;
6233 /* newname must *not* be a stream name. */
6234 if (newname
[0] == ':') {
6235 return NT_STATUS_NOT_SUPPORTED
;
6239 * Strip off the last component (filename) of the path passed
6242 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6244 return NT_STATUS_NO_MEMORY
;
6246 p
= strrchr_m(base_name
, '/');
6250 base_name
= talloc_strdup(ctx
, "");
6252 return NT_STATUS_NO_MEMORY
;
6255 /* Append the new name. */
6256 base_name
= talloc_asprintf_append(base_name
,
6260 return NT_STATUS_NO_MEMORY
;
6263 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6266 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6269 /* If an error we expect this to be
6270 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6272 if (!NT_STATUS_IS_OK(status
)) {
6273 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6277 /* Create an smb_fname to call rename_internals_fsp() */
6278 status
= create_synthetic_smb_fname(ctx
,
6282 if (!NT_STATUS_IS_OK(status
)) {
6289 DEBUG(10,("smb_file_rename_information: "
6290 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6291 fsp
->fnum
, fsp_str_dbg(fsp
),
6292 smb_fname_str_dbg(smb_fname_dst
)));
6293 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6296 DEBUG(10,("smb_file_rename_information: "
6297 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6298 smb_fname_str_dbg(smb_fname_src
),
6299 smb_fname_str_dbg(smb_fname_dst
)));
6300 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6301 smb_fname_dst
, 0, overwrite
, false,
6303 FILE_WRITE_ATTRIBUTES
);
6306 TALLOC_FREE(smb_fname_dst
);
6310 /****************************************************************************
6311 Deal with SMB_SET_POSIX_ACL.
6312 ****************************************************************************/
6314 #if defined(HAVE_POSIX_ACLS)
6315 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6319 const struct smb_filename
*smb_fname
)
6321 uint16 posix_acl_version
;
6322 uint16 num_file_acls
;
6323 uint16 num_def_acls
;
6324 bool valid_file_acls
= True
;
6325 bool valid_def_acls
= True
;
6327 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6328 return NT_STATUS_INVALID_PARAMETER
;
6330 posix_acl_version
= SVAL(pdata
,0);
6331 num_file_acls
= SVAL(pdata
,2);
6332 num_def_acls
= SVAL(pdata
,4);
6334 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6335 valid_file_acls
= False
;
6339 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6340 valid_def_acls
= False
;
6344 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6345 return NT_STATUS_INVALID_PARAMETER
;
6348 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6349 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6350 return NT_STATUS_INVALID_PARAMETER
;
6353 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6354 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6355 (unsigned int)num_file_acls
,
6356 (unsigned int)num_def_acls
));
6358 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6359 smb_fname
->base_name
, num_file_acls
,
6360 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6361 return map_nt_error_from_unix(errno
);
6364 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6365 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6366 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6367 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6368 return map_nt_error_from_unix(errno
);
6370 return NT_STATUS_OK
;
6374 /****************************************************************************
6375 Deal with SMB_SET_POSIX_LOCK.
6376 ****************************************************************************/
6378 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6379 struct smb_request
*req
,
6387 bool blocking_lock
= False
;
6388 enum brl_type lock_type
;
6390 NTSTATUS status
= NT_STATUS_OK
;
6392 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6393 return NT_STATUS_INVALID_HANDLE
;
6396 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6397 return NT_STATUS_INVALID_PARAMETER
;
6400 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6401 case POSIX_LOCK_TYPE_READ
:
6402 lock_type
= READ_LOCK
;
6404 case POSIX_LOCK_TYPE_WRITE
:
6405 /* Return the right POSIX-mappable error code for files opened read-only. */
6406 if (!fsp
->can_write
) {
6407 return NT_STATUS_INVALID_HANDLE
;
6409 lock_type
= WRITE_LOCK
;
6411 case POSIX_LOCK_TYPE_UNLOCK
:
6412 lock_type
= UNLOCK_LOCK
;
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6419 blocking_lock
= False
;
6420 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6421 blocking_lock
= True
;
6423 return NT_STATUS_INVALID_PARAMETER
;
6426 if (!lp_blocking_locks(SNUM(conn
))) {
6427 blocking_lock
= False
;
6430 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6431 #if defined(HAVE_LONGLONG)
6432 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6433 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6434 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6435 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6436 #else /* HAVE_LONGLONG */
6437 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6438 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6439 #endif /* HAVE_LONGLONG */
6441 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6442 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6444 (unsigned int)lock_type
,
6445 (unsigned long long)smblctx
,
6449 if (lock_type
== UNLOCK_LOCK
) {
6450 status
= do_unlock(req
->sconn
->msg_ctx
,
6457 uint64_t block_smblctx
;
6459 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6471 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6473 * A blocking lock was requested. Package up
6474 * this smb into a queued request and push it
6475 * onto the blocking lock queue.
6477 if(push_blocking_lock_request(br_lck
,
6480 -1, /* infinite timeout. */
6488 TALLOC_FREE(br_lck
);
6492 TALLOC_FREE(br_lck
);
6498 /****************************************************************************
6499 Deal with SMB_SET_FILE_BASIC_INFO.
6500 ****************************************************************************/
6502 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6506 const struct smb_filename
*smb_fname
)
6508 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6509 struct smb_file_time ft
;
6511 NTSTATUS status
= NT_STATUS_OK
;
6515 if (total_data
< 36) {
6516 return NT_STATUS_INVALID_PARAMETER
;
6519 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6520 return NT_STATUS_ACCESS_DENIED
;
6523 /* Set the attributes */
6524 dosmode
= IVAL(pdata
,32);
6525 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6526 if (!NT_STATUS_IS_OK(status
)) {
6531 ft
.create_time
= interpret_long_date(pdata
);
6534 ft
.atime
= interpret_long_date(pdata
+8);
6537 ft
.mtime
= interpret_long_date(pdata
+16);
6540 ft
.ctime
= interpret_long_date(pdata
+24);
6542 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6543 smb_fname_str_dbg(smb_fname
)));
6545 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6549 /****************************************************************************
6550 Deal with SMB_INFO_STANDARD.
6551 ****************************************************************************/
6553 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6557 const struct smb_filename
*smb_fname
)
6559 struct smb_file_time ft
;
6563 if (total_data
< 12) {
6564 return NT_STATUS_INVALID_PARAMETER
;
6567 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6568 return NT_STATUS_ACCESS_DENIED
;
6572 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6574 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6576 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6578 DEBUG(10,("smb_set_info_standard: file %s\n",
6579 smb_fname_str_dbg(smb_fname
)));
6581 return smb_set_file_time(conn
,
6588 /****************************************************************************
6589 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6590 ****************************************************************************/
6592 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6593 struct smb_request
*req
,
6597 struct smb_filename
*smb_fname
)
6599 uint64_t allocation_size
= 0;
6600 NTSTATUS status
= NT_STATUS_OK
;
6601 files_struct
*new_fsp
= NULL
;
6603 if (!VALID_STAT(smb_fname
->st
)) {
6604 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6607 if (total_data
< 8) {
6608 return NT_STATUS_INVALID_PARAMETER
;
6611 allocation_size
= (uint64_t)IVAL(pdata
,0);
6612 #ifdef LARGE_SMB_OFF_T
6613 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6614 #else /* LARGE_SMB_OFF_T */
6615 if (IVAL(pdata
,4) != 0) {
6616 /* more than 32 bits? */
6617 return NT_STATUS_INVALID_PARAMETER
;
6619 #endif /* LARGE_SMB_OFF_T */
6621 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6622 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6623 (double)allocation_size
));
6625 if (allocation_size
) {
6626 allocation_size
= smb_roundup(conn
, allocation_size
);
6629 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6630 return NT_STATUS_ACCESS_DENIED
;
6633 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6634 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6635 (double)allocation_size
));
6637 if (fsp
&& fsp
->fh
->fd
!= -1) {
6638 /* Open file handle. */
6639 /* Only change if needed. */
6640 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6641 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6642 return map_nt_error_from_unix(errno
);
6645 /* But always update the time. */
6647 * This is equivalent to a write. Ensure it's seen immediately
6648 * if there are no pending writes.
6650 trigger_write_time_update_immediate(fsp
);
6651 return NT_STATUS_OK
;
6654 /* Pathname or stat or directory file. */
6655 status
= SMB_VFS_CREATE_FILE(
6658 0, /* root_dir_fid */
6659 smb_fname
, /* fname */
6660 FILE_WRITE_DATA
, /* access_mask */
6661 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6663 FILE_OPEN
, /* create_disposition*/
6664 0, /* create_options */
6665 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6666 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6667 0, /* allocation_size */
6668 0, /* private_flags */
6671 &new_fsp
, /* result */
6674 if (!NT_STATUS_IS_OK(status
)) {
6675 /* NB. We check for open_was_deferred in the caller. */
6679 /* Only change if needed. */
6680 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6681 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6682 status
= map_nt_error_from_unix(errno
);
6683 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6688 /* Changing the allocation size should set the last mod time. */
6690 * This is equivalent to a write. Ensure it's seen immediately
6691 * if there are no pending writes.
6693 trigger_write_time_update_immediate(new_fsp
);
6695 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6696 return NT_STATUS_OK
;
6699 /****************************************************************************
6700 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6701 ****************************************************************************/
6703 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6704 struct smb_request
*req
,
6708 const struct smb_filename
*smb_fname
,
6709 bool fail_after_createfile
)
6713 if (total_data
< 8) {
6714 return NT_STATUS_INVALID_PARAMETER
;
6717 size
= IVAL(pdata
,0);
6718 #ifdef LARGE_SMB_OFF_T
6719 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6720 #else /* LARGE_SMB_OFF_T */
6721 if (IVAL(pdata
,4) != 0) {
6722 /* more than 32 bits? */
6723 return NT_STATUS_INVALID_PARAMETER
;
6725 #endif /* LARGE_SMB_OFF_T */
6726 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6727 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6730 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6731 return NT_STATUS_ACCESS_DENIED
;
6734 return smb_set_file_size(conn
, req
,
6739 fail_after_createfile
);
6742 /****************************************************************************
6743 Allow a UNIX info mknod.
6744 ****************************************************************************/
6746 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6749 const struct smb_filename
*smb_fname
)
6751 uint32 file_type
= IVAL(pdata
,56);
6752 #if defined(HAVE_MAKEDEV)
6753 uint32 dev_major
= IVAL(pdata
,60);
6754 uint32 dev_minor
= IVAL(pdata
,68);
6756 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6757 uint32 raw_unixmode
= IVAL(pdata
,84);
6761 if (total_data
< 100) {
6762 return NT_STATUS_INVALID_PARAMETER
;
6765 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6766 PERM_NEW_FILE
, &unixmode
);
6767 if (!NT_STATUS_IS_OK(status
)) {
6771 #if defined(HAVE_MAKEDEV)
6772 dev
= makedev(dev_major
, dev_minor
);
6775 switch (file_type
) {
6776 #if defined(S_IFIFO)
6777 case UNIX_TYPE_FIFO
:
6778 unixmode
|= S_IFIFO
;
6781 #if defined(S_IFSOCK)
6782 case UNIX_TYPE_SOCKET
:
6783 unixmode
|= S_IFSOCK
;
6786 #if defined(S_IFCHR)
6787 case UNIX_TYPE_CHARDEV
:
6788 unixmode
|= S_IFCHR
;
6791 #if defined(S_IFBLK)
6792 case UNIX_TYPE_BLKDEV
:
6793 unixmode
|= S_IFBLK
;
6797 return NT_STATUS_INVALID_PARAMETER
;
6800 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6801 "%.0f mode 0%o for file %s\n", (double)dev
,
6802 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6804 /* Ok - do the mknod. */
6805 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6806 return map_nt_error_from_unix(errno
);
6809 /* If any of the other "set" calls fail we
6810 * don't want to end up with a half-constructed mknod.
6813 if (lp_inherit_perms(SNUM(conn
))) {
6815 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6817 return NT_STATUS_NO_MEMORY
;
6819 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6821 TALLOC_FREE(parent
);
6824 return NT_STATUS_OK
;
6827 /****************************************************************************
6828 Deal with SMB_SET_FILE_UNIX_BASIC.
6829 ****************************************************************************/
6831 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6832 struct smb_request
*req
,
6836 const struct smb_filename
*smb_fname
)
6838 struct smb_file_time ft
;
6839 uint32 raw_unixmode
;
6842 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6843 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6844 NTSTATUS status
= NT_STATUS_OK
;
6845 bool delete_on_fail
= False
;
6846 enum perm_type ptype
;
6847 files_struct
*all_fsps
= NULL
;
6848 bool modify_mtime
= true;
6850 struct smb_filename
*smb_fname_tmp
= NULL
;
6851 SMB_STRUCT_STAT sbuf
;
6855 if (total_data
< 100) {
6856 return NT_STATUS_INVALID_PARAMETER
;
6859 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6860 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6861 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6862 #ifdef LARGE_SMB_OFF_T
6863 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6864 #else /* LARGE_SMB_OFF_T */
6865 if (IVAL(pdata
,4) != 0) {
6866 /* more than 32 bits? */
6867 return NT_STATUS_INVALID_PARAMETER
;
6869 #endif /* LARGE_SMB_OFF_T */
6872 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6873 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6874 set_owner
= (uid_t
)IVAL(pdata
,40);
6875 set_grp
= (gid_t
)IVAL(pdata
,48);
6876 raw_unixmode
= IVAL(pdata
,84);
6878 if (VALID_STAT(smb_fname
->st
)) {
6879 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6880 ptype
= PERM_EXISTING_DIR
;
6882 ptype
= PERM_EXISTING_FILE
;
6885 ptype
= PERM_NEW_FILE
;
6888 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6890 if (!NT_STATUS_IS_OK(status
)) {
6894 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6895 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6896 smb_fname_str_dbg(smb_fname
), (double)size
,
6897 (unsigned int)set_owner
, (unsigned int)set_grp
,
6898 (int)raw_unixmode
));
6900 sbuf
= smb_fname
->st
;
6902 if (!VALID_STAT(sbuf
)) {
6904 * The only valid use of this is to create character and block
6905 * devices, and named pipes. This is deprecated (IMHO) and
6906 * a new info level should be used for mknod. JRA.
6909 status
= smb_unix_mknod(conn
,
6913 if (!NT_STATUS_IS_OK(status
)) {
6917 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6919 if (!NT_STATUS_IS_OK(status
)) {
6923 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6924 status
= map_nt_error_from_unix(errno
);
6925 TALLOC_FREE(smb_fname_tmp
);
6926 SMB_VFS_UNLINK(conn
, smb_fname
);
6930 sbuf
= smb_fname_tmp
->st
;
6931 smb_fname
= smb_fname_tmp
;
6933 /* Ensure we don't try and change anything else. */
6934 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6935 size
= get_file_size_stat(&sbuf
);
6936 ft
.atime
= sbuf
.st_ex_atime
;
6937 ft
.mtime
= sbuf
.st_ex_mtime
;
6939 * We continue here as we might want to change the
6942 delete_on_fail
= True
;
6946 /* Horrible backwards compatibility hack as an old server bug
6947 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6951 size
= get_file_size_stat(&sbuf
);
6956 * Deal with the UNIX specific mode set.
6959 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6960 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6961 "setting mode 0%o for file %s\n",
6962 (unsigned int)unixmode
,
6963 smb_fname_str_dbg(smb_fname
)));
6964 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6965 return map_nt_error_from_unix(errno
);
6970 * Deal with the UNIX specific uid set.
6973 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6974 (sbuf
.st_ex_uid
!= set_owner
)) {
6977 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6978 "changing owner %u for path %s\n",
6979 (unsigned int)set_owner
,
6980 smb_fname_str_dbg(smb_fname
)));
6982 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6983 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6984 set_owner
, (gid_t
)-1);
6986 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6987 set_owner
, (gid_t
)-1);
6991 status
= map_nt_error_from_unix(errno
);
6992 if (delete_on_fail
) {
6993 SMB_VFS_UNLINK(conn
, smb_fname
);
7000 * Deal with the UNIX specific gid set.
7003 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7004 (sbuf
.st_ex_gid
!= set_grp
)) {
7005 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7006 "changing group %u for file %s\n",
7007 (unsigned int)set_owner
,
7008 smb_fname_str_dbg(smb_fname
)));
7009 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7011 status
= map_nt_error_from_unix(errno
);
7012 if (delete_on_fail
) {
7013 SMB_VFS_UNLINK(conn
, smb_fname
);
7019 /* Deal with any size changes. */
7021 status
= smb_set_file_size(conn
, req
,
7027 if (!NT_STATUS_IS_OK(status
)) {
7031 /* Deal with any time changes. */
7032 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7033 /* No change, don't cancel anything. */
7037 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7038 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7039 all_fsps
= file_find_di_next(all_fsps
)) {
7041 * We're setting the time explicitly for UNIX.
7042 * Cancel any pending changes over all handles.
7044 all_fsps
->update_write_time_on_close
= false;
7045 TALLOC_FREE(all_fsps
->update_write_time_event
);
7049 * Override the "setting_write_time"
7050 * parameter here as it almost does what
7051 * we need. Just remember if we modified
7052 * mtime and send the notify ourselves.
7054 if (null_timespec(ft
.mtime
)) {
7055 modify_mtime
= false;
7058 status
= smb_set_file_time(conn
,
7064 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7065 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7070 /****************************************************************************
7071 Deal with SMB_SET_FILE_UNIX_INFO2.
7072 ****************************************************************************/
7074 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7075 struct smb_request
*req
,
7079 const struct smb_filename
*smb_fname
)
7085 if (total_data
< 116) {
7086 return NT_STATUS_INVALID_PARAMETER
;
7089 /* Start by setting all the fields that are common between UNIX_BASIC
7092 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7094 if (!NT_STATUS_IS_OK(status
)) {
7098 smb_fflags
= IVAL(pdata
, 108);
7099 smb_fmask
= IVAL(pdata
, 112);
7101 /* NB: We should only attempt to alter the file flags if the client
7102 * sends a non-zero mask.
7104 if (smb_fmask
!= 0) {
7105 int stat_fflags
= 0;
7107 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7108 smb_fmask
, &stat_fflags
)) {
7109 /* Client asked to alter a flag we don't understand. */
7110 return NT_STATUS_INVALID_PARAMETER
;
7113 if (fsp
&& fsp
->fh
->fd
!= -1) {
7114 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7115 return NT_STATUS_NOT_SUPPORTED
;
7117 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7118 stat_fflags
) != 0) {
7119 return map_nt_error_from_unix(errno
);
7124 /* XXX: need to add support for changing the create_time here. You
7125 * can do this for paths on Darwin with setattrlist(2). The right way
7126 * to hook this up is probably by extending the VFS utimes interface.
7129 return NT_STATUS_OK
;
7132 /****************************************************************************
7133 Create a directory with POSIX semantics.
7134 ****************************************************************************/
7136 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7137 struct smb_request
*req
,
7140 struct smb_filename
*smb_fname
,
7141 int *pdata_return_size
)
7143 NTSTATUS status
= NT_STATUS_OK
;
7144 uint32 raw_unixmode
= 0;
7145 uint32 mod_unixmode
= 0;
7146 mode_t unixmode
= (mode_t
)0;
7147 files_struct
*fsp
= NULL
;
7148 uint16 info_level_return
= 0;
7150 char *pdata
= *ppdata
;
7152 if (total_data
< 18) {
7153 return NT_STATUS_INVALID_PARAMETER
;
7156 raw_unixmode
= IVAL(pdata
,8);
7157 /* Next 4 bytes are not yet defined. */
7159 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7160 PERM_NEW_DIR
, &unixmode
);
7161 if (!NT_STATUS_IS_OK(status
)) {
7165 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7167 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7168 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7170 status
= SMB_VFS_CREATE_FILE(
7173 0, /* root_dir_fid */
7174 smb_fname
, /* fname */
7175 FILE_READ_ATTRIBUTES
, /* access_mask */
7176 FILE_SHARE_NONE
, /* share_access */
7177 FILE_CREATE
, /* create_disposition*/
7178 FILE_DIRECTORY_FILE
, /* create_options */
7179 mod_unixmode
, /* file_attributes */
7180 0, /* oplock_request */
7181 0, /* allocation_size */
7182 0, /* private_flags */
7188 if (NT_STATUS_IS_OK(status
)) {
7189 close_file(req
, fsp
, NORMAL_CLOSE
);
7192 info_level_return
= SVAL(pdata
,16);
7194 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7195 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7196 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7197 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7199 *pdata_return_size
= 12;
7202 /* Realloc the data size */
7203 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7204 if (*ppdata
== NULL
) {
7205 *pdata_return_size
= 0;
7206 return NT_STATUS_NO_MEMORY
;
7210 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7211 SSVAL(pdata
,2,0); /* No fnum. */
7212 SIVAL(pdata
,4,info
); /* Was directory created. */
7214 switch (info_level_return
) {
7215 case SMB_QUERY_FILE_UNIX_BASIC
:
7216 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7217 SSVAL(pdata
,10,0); /* Padding. */
7218 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7221 case SMB_QUERY_FILE_UNIX_INFO2
:
7222 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7223 SSVAL(pdata
,10,0); /* Padding. */
7224 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7228 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7229 SSVAL(pdata
,10,0); /* Padding. */
7236 /****************************************************************************
7237 Open/Create a file with POSIX semantics.
7238 ****************************************************************************/
7240 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7241 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7243 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7244 struct smb_request
*req
,
7247 struct smb_filename
*smb_fname
,
7248 int *pdata_return_size
)
7250 bool extended_oplock_granted
= False
;
7251 char *pdata
= *ppdata
;
7253 uint32 wire_open_mode
= 0;
7254 uint32 raw_unixmode
= 0;
7255 uint32 mod_unixmode
= 0;
7256 uint32 create_disp
= 0;
7257 uint32 access_mask
= 0;
7258 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7259 NTSTATUS status
= NT_STATUS_OK
;
7260 mode_t unixmode
= (mode_t
)0;
7261 files_struct
*fsp
= NULL
;
7262 int oplock_request
= 0;
7264 uint16 info_level_return
= 0;
7266 if (total_data
< 18) {
7267 return NT_STATUS_INVALID_PARAMETER
;
7270 flags
= IVAL(pdata
,0);
7271 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7272 if (oplock_request
) {
7273 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7276 wire_open_mode
= IVAL(pdata
,4);
7278 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7279 return smb_posix_mkdir(conn
, req
,
7286 switch (wire_open_mode
& SMB_ACCMODE
) {
7288 access_mask
= SMB_O_RDONLY_MAPPING
;
7291 access_mask
= SMB_O_WRONLY_MAPPING
;
7294 access_mask
= (SMB_O_RDONLY_MAPPING
|
7295 SMB_O_WRONLY_MAPPING
);
7298 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7299 (unsigned int)wire_open_mode
));
7300 return NT_STATUS_INVALID_PARAMETER
;
7303 wire_open_mode
&= ~SMB_ACCMODE
;
7305 /* First take care of O_CREAT|O_EXCL interactions. */
7306 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7307 case (SMB_O_CREAT
| SMB_O_EXCL
):
7308 /* File exists fail. File not exist create. */
7309 create_disp
= FILE_CREATE
;
7312 /* File exists open. File not exist create. */
7313 create_disp
= FILE_OPEN_IF
;
7316 /* File exists open. File not exist fail. */
7317 create_disp
= FILE_OPEN
;
7320 /* O_EXCL on its own without O_CREAT is undefined. */
7322 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7323 (unsigned int)wire_open_mode
));
7324 return NT_STATUS_INVALID_PARAMETER
;
7327 /* Next factor in the effects of O_TRUNC. */
7328 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7330 if (wire_open_mode
& SMB_O_TRUNC
) {
7331 switch (create_disp
) {
7333 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7334 /* Leave create_disp alone as
7335 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7337 /* File exists fail. File not exist create. */
7340 /* SMB_O_CREAT | SMB_O_TRUNC */
7341 /* File exists overwrite. File not exist create. */
7342 create_disp
= FILE_OVERWRITE_IF
;
7346 /* File exists overwrite. File not exist fail. */
7347 create_disp
= FILE_OVERWRITE
;
7350 /* Cannot get here. */
7351 smb_panic("smb_posix_open: logic error");
7352 return NT_STATUS_INVALID_PARAMETER
;
7356 raw_unixmode
= IVAL(pdata
,8);
7357 /* Next 4 bytes are not yet defined. */
7359 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7360 (VALID_STAT(smb_fname
->st
) ?
7361 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7364 if (!NT_STATUS_IS_OK(status
)) {
7368 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7370 if (wire_open_mode
& SMB_O_SYNC
) {
7371 create_options
|= FILE_WRITE_THROUGH
;
7373 if (wire_open_mode
& SMB_O_APPEND
) {
7374 access_mask
|= FILE_APPEND_DATA
;
7376 if (wire_open_mode
& SMB_O_DIRECT
) {
7377 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7380 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7381 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7382 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7383 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7385 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7386 create_options
|= FILE_DIRECTORY_FILE
;
7389 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7390 smb_fname_str_dbg(smb_fname
),
7391 (unsigned int)wire_open_mode
,
7392 (unsigned int)unixmode
));
7394 status
= SMB_VFS_CREATE_FILE(
7397 0, /* root_dir_fid */
7398 smb_fname
, /* fname */
7399 access_mask
, /* access_mask */
7400 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7402 create_disp
, /* create_disposition*/
7403 create_options
, /* create_options */
7404 mod_unixmode
, /* file_attributes */
7405 oplock_request
, /* oplock_request */
7406 0, /* allocation_size */
7407 0, /* private_flags */
7413 if (!NT_STATUS_IS_OK(status
)) {
7417 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7418 extended_oplock_granted
= True
;
7421 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7422 extended_oplock_granted
= True
;
7425 info_level_return
= SVAL(pdata
,16);
7427 /* Allocate the correct return size. */
7429 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7430 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7431 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7432 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7434 *pdata_return_size
= 12;
7437 /* Realloc the data size */
7438 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7439 if (*ppdata
== NULL
) {
7440 close_file(req
, fsp
, ERROR_CLOSE
);
7441 *pdata_return_size
= 0;
7442 return NT_STATUS_NO_MEMORY
;
7446 if (extended_oplock_granted
) {
7447 if (flags
& REQUEST_BATCH_OPLOCK
) {
7448 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7450 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7452 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7453 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7455 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7458 SSVAL(pdata
,2,fsp
->fnum
);
7459 SIVAL(pdata
,4,info
); /* Was file created etc. */
7461 switch (info_level_return
) {
7462 case SMB_QUERY_FILE_UNIX_BASIC
:
7463 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7464 SSVAL(pdata
,10,0); /* padding. */
7465 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7468 case SMB_QUERY_FILE_UNIX_INFO2
:
7469 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7470 SSVAL(pdata
,10,0); /* padding. */
7471 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7475 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7476 SSVAL(pdata
,10,0); /* padding. */
7479 return NT_STATUS_OK
;
7482 /****************************************************************************
7483 Delete a file with POSIX semantics.
7484 ****************************************************************************/
7486 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7487 struct smb_request
*req
,
7490 struct smb_filename
*smb_fname
)
7492 NTSTATUS status
= NT_STATUS_OK
;
7493 files_struct
*fsp
= NULL
;
7497 int create_options
= 0;
7499 struct share_mode_lock
*lck
= NULL
;
7501 if (total_data
< 2) {
7502 return NT_STATUS_INVALID_PARAMETER
;
7505 flags
= SVAL(pdata
,0);
7507 if (!VALID_STAT(smb_fname
->st
)) {
7508 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7511 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7512 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7513 return NT_STATUS_NOT_A_DIRECTORY
;
7516 DEBUG(10,("smb_posix_unlink: %s %s\n",
7517 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7518 smb_fname_str_dbg(smb_fname
)));
7520 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7521 create_options
|= FILE_DIRECTORY_FILE
;
7524 status
= SMB_VFS_CREATE_FILE(
7527 0, /* root_dir_fid */
7528 smb_fname
, /* fname */
7529 DELETE_ACCESS
, /* access_mask */
7530 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7532 FILE_OPEN
, /* create_disposition*/
7533 create_options
, /* create_options */
7534 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7535 0, /* oplock_request */
7536 0, /* allocation_size */
7537 0, /* private_flags */
7543 if (!NT_STATUS_IS_OK(status
)) {
7548 * Don't lie to client. If we can't really delete due to
7549 * non-POSIX opens return SHARING_VIOLATION.
7552 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7555 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7556 "lock for file %s\n", fsp_str_dbg(fsp
)));
7557 close_file(req
, fsp
, NORMAL_CLOSE
);
7558 return NT_STATUS_INVALID_PARAMETER
;
7562 * See if others still have the file open. If this is the case, then
7563 * don't delete. If all opens are POSIX delete we can set the delete
7564 * on close disposition.
7566 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7567 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7568 if (is_valid_share_mode_entry(e
)) {
7569 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7572 /* Fail with sharing violation. */
7573 close_file(req
, fsp
, NORMAL_CLOSE
);
7575 return NT_STATUS_SHARING_VIOLATION
;
7580 * Set the delete on close.
7582 status
= smb_set_file_disposition_info(conn
,
7588 if (!NT_STATUS_IS_OK(status
)) {
7589 close_file(req
, fsp
, NORMAL_CLOSE
);
7594 return close_file(req
, fsp
, NORMAL_CLOSE
);
7597 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7598 struct smb_request
*req
,
7599 TALLOC_CTX
*mem_ctx
,
7600 uint16_t info_level
,
7602 struct smb_filename
*smb_fname
,
7603 char **ppdata
, int total_data
,
7606 char *pdata
= *ppdata
;
7607 NTSTATUS status
= NT_STATUS_OK
;
7608 int data_return_size
= 0;
7612 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7613 return NT_STATUS_INVALID_LEVEL
;
7616 if (!CAN_WRITE(conn
)) {
7617 /* Allow POSIX opens. The open path will deny
7618 * any non-readonly opens. */
7619 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7620 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7624 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7625 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7626 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7628 switch (info_level
) {
7630 case SMB_INFO_STANDARD
:
7632 status
= smb_set_info_standard(conn
,
7640 case SMB_INFO_SET_EA
:
7642 status
= smb_info_set_ea(conn
,
7650 case SMB_SET_FILE_BASIC_INFO
:
7651 case SMB_FILE_BASIC_INFORMATION
:
7653 status
= smb_set_file_basic_info(conn
,
7661 case SMB_FILE_ALLOCATION_INFORMATION
:
7662 case SMB_SET_FILE_ALLOCATION_INFO
:
7664 status
= smb_set_file_allocation_info(conn
, req
,
7672 case SMB_FILE_END_OF_FILE_INFORMATION
:
7673 case SMB_SET_FILE_END_OF_FILE_INFO
:
7676 * XP/Win7 both fail after the createfile with
7677 * SMB_SET_FILE_END_OF_FILE_INFO but not
7678 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7679 * The level is known here, so pass it down
7683 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7685 status
= smb_set_file_end_of_file_info(conn
, req
,
7694 case SMB_FILE_DISPOSITION_INFORMATION
:
7695 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7698 /* JRA - We used to just ignore this on a path ?
7699 * Shouldn't this be invalid level on a pathname
7702 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7703 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7706 status
= smb_set_file_disposition_info(conn
,
7714 case SMB_FILE_POSITION_INFORMATION
:
7716 status
= smb_file_position_information(conn
,
7723 case SMB_FILE_FULL_EA_INFORMATION
:
7725 status
= smb_set_file_full_ea_info(conn
,
7732 /* From tridge Samba4 :
7733 * MODE_INFORMATION in setfileinfo (I have no
7734 * idea what "mode information" on a file is - it takes a value of 0,
7735 * 2, 4 or 6. What could it be?).
7738 case SMB_FILE_MODE_INFORMATION
:
7740 status
= smb_file_mode_information(conn
,
7747 * CIFS UNIX extensions.
7750 case SMB_SET_FILE_UNIX_BASIC
:
7752 status
= smb_set_file_unix_basic(conn
, req
,
7760 case SMB_SET_FILE_UNIX_INFO2
:
7762 status
= smb_set_file_unix_info2(conn
, req
,
7770 case SMB_SET_FILE_UNIX_LINK
:
7773 /* We must have a pathname for this. */
7774 return NT_STATUS_INVALID_LEVEL
;
7776 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7777 total_data
, smb_fname
);
7781 case SMB_SET_FILE_UNIX_HLINK
:
7784 /* We must have a pathname for this. */
7785 return NT_STATUS_INVALID_LEVEL
;
7787 status
= smb_set_file_unix_hlink(conn
, req
,
7793 case SMB_FILE_RENAME_INFORMATION
:
7795 status
= smb_file_rename_information(conn
, req
,
7801 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7803 /* SMB2 rename information. */
7804 status
= smb2_file_rename_information(conn
, req
,
7810 case SMB_FILE_LINK_INFORMATION
:
7812 status
= smb_file_link_information(conn
, req
,
7818 #if defined(HAVE_POSIX_ACLS)
7819 case SMB_SET_POSIX_ACL
:
7821 status
= smb_set_posix_acl(conn
,
7830 case SMB_SET_POSIX_LOCK
:
7833 return NT_STATUS_INVALID_LEVEL
;
7835 status
= smb_set_posix_lock(conn
, req
,
7836 pdata
, total_data
, fsp
);
7840 case SMB_POSIX_PATH_OPEN
:
7843 /* We must have a pathname for this. */
7844 return NT_STATUS_INVALID_LEVEL
;
7847 status
= smb_posix_open(conn
, req
,
7855 case SMB_POSIX_PATH_UNLINK
:
7858 /* We must have a pathname for this. */
7859 return NT_STATUS_INVALID_LEVEL
;
7862 status
= smb_posix_unlink(conn
, req
,
7870 return NT_STATUS_INVALID_LEVEL
;
7873 if (!NT_STATUS_IS_OK(status
)) {
7877 *ret_data_size
= data_return_size
;
7878 return NT_STATUS_OK
;
7881 /****************************************************************************
7882 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7883 ****************************************************************************/
7885 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7886 struct smb_request
*req
,
7887 unsigned int tran_call
,
7888 char **pparams
, int total_params
,
7889 char **ppdata
, int total_data
,
7890 unsigned int max_data_bytes
)
7892 char *params
= *pparams
;
7893 char *pdata
= *ppdata
;
7895 struct smb_filename
*smb_fname
= NULL
;
7896 files_struct
*fsp
= NULL
;
7897 NTSTATUS status
= NT_STATUS_OK
;
7898 int data_return_size
= 0;
7901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7905 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7906 if (total_params
< 4) {
7907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7911 fsp
= file_fsp(req
, SVAL(params
,0));
7912 /* Basic check for non-null fsp. */
7913 if (!check_fsp_open(conn
, req
, fsp
)) {
7916 info_level
= SVAL(params
,2);
7918 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7920 if (!NT_STATUS_IS_OK(status
)) {
7921 reply_nterror(req
, status
);
7925 if(fsp
->fh
->fd
== -1) {
7927 * This is actually a SETFILEINFO on a directory
7928 * handle (returned from an NT SMB). NT5.0 seems
7929 * to do this call. JRA.
7931 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7932 /* Always do lstat for UNIX calls. */
7933 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7934 DEBUG(3,("call_trans2setfilepathinfo: "
7935 "SMB_VFS_LSTAT of %s failed "
7937 smb_fname_str_dbg(smb_fname
),
7939 reply_nterror(req
, map_nt_error_from_unix(errno
));
7943 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7944 DEBUG(3,("call_trans2setfilepathinfo: "
7945 "fileinfo of %s failed (%s)\n",
7946 smb_fname_str_dbg(smb_fname
),
7948 reply_nterror(req
, map_nt_error_from_unix(errno
));
7952 } else if (fsp
->print_file
) {
7954 * Doing a DELETE_ON_CLOSE should cancel a print job.
7956 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7957 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7959 DEBUG(3,("call_trans2setfilepathinfo: "
7960 "Cancelling print job (%s)\n",
7964 send_trans2_replies(conn
, req
, params
, 2,
7970 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7975 * Original code - this is an open file.
7977 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7978 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7979 "of fnum %d failed (%s)\n", fsp
->fnum
,
7981 reply_nterror(req
, map_nt_error_from_unix(errno
));
7987 uint32_t ucf_flags
= 0;
7990 if (total_params
< 7) {
7991 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7995 info_level
= SVAL(params
,0);
7996 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7997 total_params
- 6, STR_TERMINATE
,
7999 if (!NT_STATUS_IS_OK(status
)) {
8000 reply_nterror(req
, status
);
8004 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8005 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8006 info_level
== SMB_FILE_RENAME_INFORMATION
||
8007 info_level
== SMB_POSIX_PATH_UNLINK
) {
8008 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8011 status
= filename_convert(req
, conn
,
8012 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8017 if (!NT_STATUS_IS_OK(status
)) {
8018 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8019 reply_botherror(req
,
8020 NT_STATUS_PATH_NOT_COVERED
,
8021 ERRSRV
, ERRbadpath
);
8024 reply_nterror(req
, status
);
8028 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8030 * For CIFS UNIX extensions the target name may not exist.
8033 /* Always do lstat for UNIX calls. */
8034 SMB_VFS_LSTAT(conn
, smb_fname
);
8036 } else if (!VALID_STAT(smb_fname
->st
) &&
8037 SMB_VFS_STAT(conn
, smb_fname
)) {
8038 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8040 smb_fname_str_dbg(smb_fname
),
8042 reply_nterror(req
, map_nt_error_from_unix(errno
));
8047 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8048 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8049 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8051 /* Realloc the parameter size */
8052 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8053 if (*pparams
== NULL
) {
8054 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8061 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8067 if (!NT_STATUS_IS_OK(status
)) {
8068 if (open_was_deferred(req
->mid
)) {
8069 /* We have re-scheduled this call. */
8072 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8073 /* We have re-scheduled this call. */
8076 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8077 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8078 ERRSRV
, ERRbadpath
);
8081 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8082 reply_openerror(req
, status
);
8086 reply_nterror(req
, status
);
8090 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8096 /****************************************************************************
8097 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8098 ****************************************************************************/
8100 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8101 char **pparams
, int total_params
,
8102 char **ppdata
, int total_data
,
8103 unsigned int max_data_bytes
)
8105 struct smb_filename
*smb_dname
= NULL
;
8106 char *params
= *pparams
;
8107 char *pdata
= *ppdata
;
8108 char *directory
= NULL
;
8109 NTSTATUS status
= NT_STATUS_OK
;
8110 struct ea_list
*ea_list
= NULL
;
8111 TALLOC_CTX
*ctx
= talloc_tos();
8113 if (!CAN_WRITE(conn
)) {
8114 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8118 if (total_params
< 5) {
8119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8123 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8124 total_params
- 4, STR_TERMINATE
,
8126 if (!NT_STATUS_IS_OK(status
)) {
8127 reply_nterror(req
, status
);
8131 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8133 status
= filename_convert(ctx
,
8135 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8141 if (!NT_STATUS_IS_OK(status
)) {
8142 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8143 reply_botherror(req
,
8144 NT_STATUS_PATH_NOT_COVERED
,
8145 ERRSRV
, ERRbadpath
);
8148 reply_nterror(req
, status
);
8153 * OS/2 workplace shell seems to send SET_EA requests of "null"
8154 * length (4 bytes containing IVAL 4).
8155 * They seem to have no effect. Bug #3212. JRA.
8158 if (total_data
&& (total_data
!= 4)) {
8159 /* Any data in this call is an EA list. */
8160 if (total_data
< 10) {
8161 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8165 if (IVAL(pdata
,0) > total_data
) {
8166 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8167 IVAL(pdata
,0), (unsigned int)total_data
));
8168 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8172 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8179 if (!lp_ea_support(SNUM(conn
))) {
8180 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8184 /* If total_data == 4 Windows doesn't care what values
8185 * are placed in that field, it just ignores them.
8186 * The System i QNTC IBM SMB client puts bad values here,
8187 * so ignore them. */
8189 status
= create_directory(conn
, req
, smb_dname
);
8191 if (!NT_STATUS_IS_OK(status
)) {
8192 reply_nterror(req
, status
);
8196 /* Try and set any given EA. */
8198 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8199 if (!NT_STATUS_IS_OK(status
)) {
8200 reply_nterror(req
, status
);
8205 /* Realloc the parameter and data sizes */
8206 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8207 if(*pparams
== NULL
) {
8208 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8215 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8218 TALLOC_FREE(smb_dname
);
8222 /****************************************************************************
8223 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8224 We don't actually do this - we just send a null response.
8225 ****************************************************************************/
8227 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8228 struct smb_request
*req
,
8229 char **pparams
, int total_params
,
8230 char **ppdata
, int total_data
,
8231 unsigned int max_data_bytes
)
8233 char *params
= *pparams
;
8236 if (total_params
< 6) {
8237 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8241 info_level
= SVAL(params
,4);
8242 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8244 switch (info_level
) {
8249 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8253 /* Realloc the parameter and data sizes */
8254 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8255 if (*pparams
== NULL
) {
8256 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8261 SSVAL(params
,0,fnf_handle
);
8262 SSVAL(params
,2,0); /* No changes */
8263 SSVAL(params
,4,0); /* No EA errors */
8270 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8275 /****************************************************************************
8276 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8277 changes). Currently this does nothing.
8278 ****************************************************************************/
8280 static void call_trans2findnotifynext(connection_struct
*conn
,
8281 struct smb_request
*req
,
8282 char **pparams
, int total_params
,
8283 char **ppdata
, int total_data
,
8284 unsigned int max_data_bytes
)
8286 char *params
= *pparams
;
8288 DEBUG(3,("call_trans2findnotifynext\n"));
8290 /* Realloc the parameter and data sizes */
8291 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8292 if (*pparams
== NULL
) {
8293 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8298 SSVAL(params
,0,0); /* No changes */
8299 SSVAL(params
,2,0); /* No EA errors */
8301 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8306 /****************************************************************************
8307 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8308 ****************************************************************************/
8310 static void call_trans2getdfsreferral(connection_struct
*conn
,
8311 struct smb_request
*req
,
8312 char **pparams
, int total_params
,
8313 char **ppdata
, int total_data
,
8314 unsigned int max_data_bytes
)
8316 char *params
= *pparams
;
8317 char *pathname
= NULL
;
8319 int max_referral_level
;
8320 NTSTATUS status
= NT_STATUS_OK
;
8321 TALLOC_CTX
*ctx
= talloc_tos();
8323 DEBUG(10,("call_trans2getdfsreferral\n"));
8325 if (total_params
< 3) {
8326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8330 max_referral_level
= SVAL(params
,0);
8332 if(!lp_host_msdfs()) {
8333 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8337 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8338 total_params
- 2, STR_TERMINATE
);
8340 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8343 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8344 ppdata
,&status
)) < 0) {
8345 reply_nterror(req
, status
);
8349 SSVAL(req
->inbuf
, smb_flg2
,
8350 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8351 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8356 #define LMCAT_SPL 0x53
8357 #define LMFUNC_GETJOBID 0x60
8359 /****************************************************************************
8360 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8361 ****************************************************************************/
8363 static void call_trans2ioctl(connection_struct
*conn
,
8364 struct smb_request
*req
,
8365 char **pparams
, int total_params
,
8366 char **ppdata
, int total_data
,
8367 unsigned int max_data_bytes
)
8369 char *pdata
= *ppdata
;
8370 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8372 /* check for an invalid fid before proceeding */
8375 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8379 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8380 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8381 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8382 if (*ppdata
== NULL
) {
8383 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8388 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8389 CAN ACCEPT THIS IN UNICODE. JRA. */
8392 if (fsp
->print_file
) {
8393 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8397 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8398 global_myname(), 15,
8399 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8400 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8401 lp_servicename(SNUM(conn
)), 13,
8402 STR_ASCII
|STR_TERMINATE
); /* Service name */
8403 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8408 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8409 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8412 /****************************************************************************
8413 Reply to a SMBfindclose (stop trans2 directory search).
8414 ****************************************************************************/
8416 void reply_findclose(struct smb_request
*req
)
8419 struct smbd_server_connection
*sconn
= req
->sconn
;
8421 START_PROFILE(SMBfindclose
);
8424 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8425 END_PROFILE(SMBfindclose
);
8429 dptr_num
= SVALS(req
->vwv
+0, 0);
8431 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8433 dptr_close(sconn
, &dptr_num
);
8435 reply_outbuf(req
, 0, 0);
8437 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8439 END_PROFILE(SMBfindclose
);
8443 /****************************************************************************
8444 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8445 ****************************************************************************/
8447 void reply_findnclose(struct smb_request
*req
)
8451 START_PROFILE(SMBfindnclose
);
8454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8455 END_PROFILE(SMBfindnclose
);
8459 dptr_num
= SVAL(req
->vwv
+0, 0);
8461 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8463 /* We never give out valid handles for a
8464 findnotifyfirst - so any dptr_num is ok here.
8467 reply_outbuf(req
, 0, 0);
8469 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8471 END_PROFILE(SMBfindnclose
);
8475 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8476 struct trans_state
*state
)
8478 if (get_Protocol() >= PROTOCOL_NT1
) {
8479 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8480 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8483 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8484 if (state
->call
!= TRANSACT2_QFSINFO
&&
8485 state
->call
!= TRANSACT2_SETFSINFO
) {
8486 DEBUG(0,("handle_trans2: encryption required "
8488 (unsigned int)state
->call
));
8489 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8494 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8496 /* Now we must call the relevant TRANS2 function */
8497 switch(state
->call
) {
8498 case TRANSACT2_OPEN
:
8500 START_PROFILE(Trans2_open
);
8501 call_trans2open(conn
, req
,
8502 &state
->param
, state
->total_param
,
8503 &state
->data
, state
->total_data
,
8504 state
->max_data_return
);
8505 END_PROFILE(Trans2_open
);
8509 case TRANSACT2_FINDFIRST
:
8511 START_PROFILE(Trans2_findfirst
);
8512 call_trans2findfirst(conn
, req
,
8513 &state
->param
, state
->total_param
,
8514 &state
->data
, state
->total_data
,
8515 state
->max_data_return
);
8516 END_PROFILE(Trans2_findfirst
);
8520 case TRANSACT2_FINDNEXT
:
8522 START_PROFILE(Trans2_findnext
);
8523 call_trans2findnext(conn
, req
,
8524 &state
->param
, state
->total_param
,
8525 &state
->data
, state
->total_data
,
8526 state
->max_data_return
);
8527 END_PROFILE(Trans2_findnext
);
8531 case TRANSACT2_QFSINFO
:
8533 START_PROFILE(Trans2_qfsinfo
);
8534 call_trans2qfsinfo(conn
, req
,
8535 &state
->param
, state
->total_param
,
8536 &state
->data
, state
->total_data
,
8537 state
->max_data_return
);
8538 END_PROFILE(Trans2_qfsinfo
);
8542 case TRANSACT2_SETFSINFO
:
8544 START_PROFILE(Trans2_setfsinfo
);
8545 call_trans2setfsinfo(conn
, req
,
8546 &state
->param
, state
->total_param
,
8547 &state
->data
, state
->total_data
,
8548 state
->max_data_return
);
8549 END_PROFILE(Trans2_setfsinfo
);
8553 case TRANSACT2_QPATHINFO
:
8554 case TRANSACT2_QFILEINFO
:
8556 START_PROFILE(Trans2_qpathinfo
);
8557 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8558 &state
->param
, state
->total_param
,
8559 &state
->data
, state
->total_data
,
8560 state
->max_data_return
);
8561 END_PROFILE(Trans2_qpathinfo
);
8565 case TRANSACT2_SETPATHINFO
:
8566 case TRANSACT2_SETFILEINFO
:
8568 START_PROFILE(Trans2_setpathinfo
);
8569 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8570 &state
->param
, state
->total_param
,
8571 &state
->data
, state
->total_data
,
8572 state
->max_data_return
);
8573 END_PROFILE(Trans2_setpathinfo
);
8577 case TRANSACT2_FINDNOTIFYFIRST
:
8579 START_PROFILE(Trans2_findnotifyfirst
);
8580 call_trans2findnotifyfirst(conn
, req
,
8581 &state
->param
, state
->total_param
,
8582 &state
->data
, state
->total_data
,
8583 state
->max_data_return
);
8584 END_PROFILE(Trans2_findnotifyfirst
);
8588 case TRANSACT2_FINDNOTIFYNEXT
:
8590 START_PROFILE(Trans2_findnotifynext
);
8591 call_trans2findnotifynext(conn
, req
,
8592 &state
->param
, state
->total_param
,
8593 &state
->data
, state
->total_data
,
8594 state
->max_data_return
);
8595 END_PROFILE(Trans2_findnotifynext
);
8599 case TRANSACT2_MKDIR
:
8601 START_PROFILE(Trans2_mkdir
);
8602 call_trans2mkdir(conn
, req
,
8603 &state
->param
, state
->total_param
,
8604 &state
->data
, state
->total_data
,
8605 state
->max_data_return
);
8606 END_PROFILE(Trans2_mkdir
);
8610 case TRANSACT2_GET_DFS_REFERRAL
:
8612 START_PROFILE(Trans2_get_dfs_referral
);
8613 call_trans2getdfsreferral(conn
, req
,
8614 &state
->param
, state
->total_param
,
8615 &state
->data
, state
->total_data
,
8616 state
->max_data_return
);
8617 END_PROFILE(Trans2_get_dfs_referral
);
8621 case TRANSACT2_IOCTL
:
8623 START_PROFILE(Trans2_ioctl
);
8624 call_trans2ioctl(conn
, req
,
8625 &state
->param
, state
->total_param
,
8626 &state
->data
, state
->total_data
,
8627 state
->max_data_return
);
8628 END_PROFILE(Trans2_ioctl
);
8633 /* Error in request */
8634 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8635 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8639 /****************************************************************************
8640 Reply to a SMBtrans2.
8641 ****************************************************************************/
8643 void reply_trans2(struct smb_request
*req
)
8645 connection_struct
*conn
= req
->conn
;
8650 unsigned int tran_call
;
8651 struct trans_state
*state
;
8654 START_PROFILE(SMBtrans2
);
8656 if (req
->wct
< 14) {
8657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8658 END_PROFILE(SMBtrans2
);
8662 dsoff
= SVAL(req
->vwv
+12, 0);
8663 dscnt
= SVAL(req
->vwv
+11, 0);
8664 psoff
= SVAL(req
->vwv
+10, 0);
8665 pscnt
= SVAL(req
->vwv
+9, 0);
8666 tran_call
= SVAL(req
->vwv
+14, 0);
8668 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8669 if (!NT_STATUS_IS_OK(result
)) {
8670 DEBUG(2, ("Got invalid trans2 request: %s\n",
8671 nt_errstr(result
)));
8672 reply_nterror(req
, result
);
8673 END_PROFILE(SMBtrans2
);
8678 switch (tran_call
) {
8679 /* List the allowed trans2 calls on IPC$ */
8680 case TRANSACT2_OPEN
:
8681 case TRANSACT2_GET_DFS_REFERRAL
:
8682 case TRANSACT2_QFILEINFO
:
8683 case TRANSACT2_QFSINFO
:
8684 case TRANSACT2_SETFSINFO
:
8687 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8688 END_PROFILE(SMBtrans2
);
8693 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8694 DEBUG(0, ("talloc failed\n"));
8695 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8696 END_PROFILE(SMBtrans2
);
8700 state
->cmd
= SMBtrans2
;
8702 state
->mid
= req
->mid
;
8703 state
->vuid
= req
->vuid
;
8704 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8705 state
->setup
= NULL
;
8706 state
->total_param
= SVAL(req
->vwv
+0, 0);
8707 state
->param
= NULL
;
8708 state
->total_data
= SVAL(req
->vwv
+1, 0);
8710 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8711 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8712 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8713 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8714 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8716 state
->call
= tran_call
;
8718 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8719 is so as a sanity check */
8720 if (state
->setup_count
!= 1) {
8722 * Need to have rc=0 for ioctl to get job id for OS/2.
8723 * Network printing will fail if function is not successful.
8724 * Similar function in reply.c will be used if protocol
8725 * is LANMAN1.0 instead of LM1.2X002.
8726 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8727 * outbuf doesn't have to be set(only job id is used).
8729 if ( (state
->setup_count
== 4)
8730 && (tran_call
== TRANSACT2_IOCTL
)
8731 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8732 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8733 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8735 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8736 DEBUG(2,("Transaction is %d\n",tran_call
));
8738 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8739 END_PROFILE(SMBtrans2
);
8744 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8747 if (state
->total_data
) {
8749 if (trans_oob(state
->total_data
, 0, dscnt
)
8750 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8754 /* Can't use talloc here, the core routines do realloc on the
8755 * params and data. */
8756 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8757 if (state
->data
== NULL
) {
8758 DEBUG(0,("reply_trans2: data malloc fail for %u "
8759 "bytes !\n", (unsigned int)state
->total_data
));
8761 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8762 END_PROFILE(SMBtrans2
);
8766 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8769 if (state
->total_param
) {
8771 if (trans_oob(state
->total_param
, 0, pscnt
)
8772 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8776 /* Can't use talloc here, the core routines do realloc on the
8777 * params and data. */
8778 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8779 if (state
->param
== NULL
) {
8780 DEBUG(0,("reply_trans: param malloc fail for %u "
8781 "bytes !\n", (unsigned int)state
->total_param
));
8782 SAFE_FREE(state
->data
);
8784 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8785 END_PROFILE(SMBtrans2
);
8789 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8792 state
->received_data
= dscnt
;
8793 state
->received_param
= pscnt
;
8795 if ((state
->received_param
== state
->total_param
) &&
8796 (state
->received_data
== state
->total_data
)) {
8798 handle_trans2(conn
, req
, state
);
8800 SAFE_FREE(state
->data
);
8801 SAFE_FREE(state
->param
);
8803 END_PROFILE(SMBtrans2
);
8807 DLIST_ADD(conn
->pending_trans
, state
);
8809 /* We need to send an interim response then receive the rest
8810 of the parameter/data bytes */
8811 reply_outbuf(req
, 0, 0);
8812 show_msg((char *)req
->outbuf
);
8813 END_PROFILE(SMBtrans2
);
8818 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8819 SAFE_FREE(state
->data
);
8820 SAFE_FREE(state
->param
);
8822 END_PROFILE(SMBtrans2
);
8823 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8827 /****************************************************************************
8828 Reply to a SMBtranss2
8829 ****************************************************************************/
8831 void reply_transs2(struct smb_request
*req
)
8833 connection_struct
*conn
= req
->conn
;
8834 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8835 struct trans_state
*state
;
8837 START_PROFILE(SMBtranss2
);
8839 show_msg((char *)req
->inbuf
);
8842 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8843 END_PROFILE(SMBtranss2
);
8847 for (state
= conn
->pending_trans
; state
!= NULL
;
8848 state
= state
->next
) {
8849 if (state
->mid
== req
->mid
) {
8854 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8855 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8856 END_PROFILE(SMBtranss2
);
8860 /* Revise state->total_param and state->total_data in case they have
8861 changed downwards */
8863 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8864 state
->total_param
= SVAL(req
->vwv
+0, 0);
8865 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8866 state
->total_data
= SVAL(req
->vwv
+1, 0);
8868 pcnt
= SVAL(req
->vwv
+2, 0);
8869 poff
= SVAL(req
->vwv
+3, 0);
8870 pdisp
= SVAL(req
->vwv
+4, 0);
8872 dcnt
= SVAL(req
->vwv
+5, 0);
8873 doff
= SVAL(req
->vwv
+6, 0);
8874 ddisp
= SVAL(req
->vwv
+7, 0);
8876 state
->received_param
+= pcnt
;
8877 state
->received_data
+= dcnt
;
8879 if ((state
->received_data
> state
->total_data
) ||
8880 (state
->received_param
> state
->total_param
))
8884 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8885 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8888 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8892 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8893 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8896 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8899 if ((state
->received_param
< state
->total_param
) ||
8900 (state
->received_data
< state
->total_data
)) {
8901 END_PROFILE(SMBtranss2
);
8905 handle_trans2(conn
, req
, state
);
8907 DLIST_REMOVE(conn
->pending_trans
, state
);
8908 SAFE_FREE(state
->data
);
8909 SAFE_FREE(state
->param
);
8912 END_PROFILE(SMBtranss2
);
8917 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8918 DLIST_REMOVE(conn
->pending_trans
, state
);
8919 SAFE_FREE(state
->data
);
8920 SAFE_FREE(state
->param
);
8922 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8923 END_PROFILE(SMBtranss2
);