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
;
2275 if (total_params
< 13) {
2276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2280 dirtype
= SVAL(params
,0);
2281 maxentries
= SVAL(params
,2);
2282 findfirst_flags
= SVAL(params
,4);
2283 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2284 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2285 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2286 info_level
= SVAL(params
,6);
2288 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2289 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2290 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2291 info_level
, max_data_bytes
));
2294 /* W2K3 seems to treat zero as 1. */
2298 switch (info_level
) {
2299 case SMB_FIND_INFO_STANDARD
:
2300 case SMB_FIND_EA_SIZE
:
2301 case SMB_FIND_EA_LIST
:
2302 case SMB_FIND_FILE_DIRECTORY_INFO
:
2303 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2304 case SMB_FIND_FILE_NAMES_INFO
:
2305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2306 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2307 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2309 case SMB_FIND_FILE_UNIX
:
2310 case SMB_FIND_FILE_UNIX_INFO2
:
2311 /* Always use filesystem for UNIX mtime query. */
2312 ask_sharemode
= false;
2313 if (!lp_unix_extensions()) {
2314 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2319 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2323 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2324 params
+12, total_params
- 12,
2325 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2326 if (!NT_STATUS_IS_OK(ntstatus
)) {
2327 reply_nterror(req
, ntstatus
);
2331 ntstatus
= filename_convert(ctx
, conn
,
2332 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2335 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2336 &mask_contains_wcard
,
2338 if (!NT_STATUS_IS_OK(ntstatus
)) {
2339 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2340 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2341 ERRSRV
, ERRbadpath
);
2344 reply_nterror(req
, ntstatus
);
2348 mask
= smb_dname
->original_lcomp
;
2350 directory
= smb_dname
->base_name
;
2352 p
= strrchr_m(directory
,'/');
2354 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2355 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2356 mask
= talloc_strdup(ctx
,"*");
2358 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2361 mask_contains_wcard
= True
;
2367 if (p
== NULL
|| p
== directory
) {
2368 /* Ensure we don't have a directory name of "". */
2369 directory
= talloc_strdup(talloc_tos(), ".");
2371 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2376 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2378 if (info_level
== SMB_FIND_EA_LIST
) {
2381 if (total_data
< 4) {
2382 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2386 ea_size
= IVAL(pdata
,0);
2387 if (ea_size
!= total_data
) {
2388 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2389 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2390 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2394 if (!lp_ea_support(SNUM(conn
))) {
2395 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2399 /* Pull out the list of names. */
2400 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2402 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2407 *ppdata
= (char *)SMB_REALLOC(
2408 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2409 if(*ppdata
== NULL
) {
2410 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2414 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2416 /* Realloc the params space */
2417 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2418 if (*pparams
== NULL
) {
2419 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2424 /* Save the wildcard match and attribs we are using on this directory -
2425 needed as lanman2 assumes these are being saved between calls */
2427 ntstatus
= dptr_create(conn
,
2434 mask_contains_wcard
,
2438 if (!NT_STATUS_IS_OK(ntstatus
)) {
2439 reply_nterror(req
, ntstatus
);
2443 dptr_num
= dptr_dnum(dirptr
);
2444 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2446 /* Initialize per TRANS2_FIND_FIRST operation data */
2447 dptr_init_search_op(dirptr
);
2449 /* We don't need to check for VOL here as this is returned by
2450 a different TRANS2 call. */
2452 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2453 directory
,lp_dontdescend(SNUM(conn
))));
2454 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2455 dont_descend
= True
;
2458 space_remaining
= max_data_bytes
;
2459 out_of_space
= False
;
2461 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2462 bool got_exact_match
= False
;
2464 /* this is a heuristic to avoid seeking the dirptr except when
2465 absolutely necessary. It allows for a filename of about 40 chars */
2466 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2467 out_of_space
= True
;
2470 finished
= !get_lanman2_dir_entry(ctx
,
2474 mask
,dirtype
,info_level
,
2475 requires_resume_key
,dont_descend
,
2478 space_remaining
, &out_of_space
,
2480 &last_entry_off
, ea_list
);
2483 if (finished
&& out_of_space
)
2486 if (!finished
&& !out_of_space
)
2490 * As an optimisation if we know we aren't looking
2491 * for a wildcard name (ie. the name matches the wildcard exactly)
2492 * then we can finish on any (first) match.
2493 * This speeds up large directory searches. JRA.
2499 /* Ensure space_remaining never goes -ve. */
2500 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2501 space_remaining
= 0;
2502 out_of_space
= true;
2504 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2508 /* Check if we can close the dirptr */
2509 if(close_after_first
|| (finished
&& close_if_end
)) {
2510 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2511 dptr_close(sconn
, &dptr_num
);
2515 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2516 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2517 * the protocol level is less than NT1. Tested with smbclient. JRA.
2518 * This should fix the OS/2 client bug #2335.
2521 if(numentries
== 0) {
2522 dptr_close(sconn
, &dptr_num
);
2523 if (get_Protocol() < PROTOCOL_NT1
) {
2524 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2527 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2528 ERRDOS
, ERRbadfile
);
2533 /* At this point pdata points to numentries directory entries. */
2535 /* Set up the return parameter block */
2536 SSVAL(params
,0,dptr_num
);
2537 SSVAL(params
,2,numentries
);
2538 SSVAL(params
,4,finished
);
2539 SSVAL(params
,6,0); /* Never an EA error */
2540 SSVAL(params
,8,last_entry_off
);
2542 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2545 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2546 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2548 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2552 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2553 smb_fn_name(req
->cmd
),
2554 mask
, directory
, dirtype
, numentries
) );
2557 * Force a name mangle here to ensure that the
2558 * mask as an 8.3 name is top of the mangled cache.
2559 * The reasons for this are subtle. Don't remove
2560 * this code unless you know what you are doing
2561 * (see PR#13758). JRA.
2564 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2565 char mangled_name
[13];
2566 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2569 TALLOC_FREE(smb_dname
);
2573 /****************************************************************************
2574 Reply to a TRANS2_FINDNEXT.
2575 ****************************************************************************/
2577 static void call_trans2findnext(connection_struct
*conn
,
2578 struct smb_request
*req
,
2579 char **pparams
, int total_params
,
2580 char **ppdata
, int total_data
,
2581 unsigned int max_data_bytes
)
2583 /* We must be careful here that we don't return more than the
2584 allowed number of data bytes. If this means returning fewer than
2585 maxentries then so be it. We assume that the redirector has
2586 enough room for the fixed number of parameter bytes it has
2588 char *params
= *pparams
;
2589 char *pdata
= *ppdata
;
2595 uint16 findnext_flags
;
2596 bool close_after_request
;
2598 bool requires_resume_key
;
2600 bool mask_contains_wcard
= False
;
2601 char *resume_name
= NULL
;
2602 const char *mask
= NULL
;
2603 const char *directory
= NULL
;
2607 int i
, last_entry_off
=0;
2608 bool finished
= False
;
2609 bool dont_descend
= False
;
2610 bool out_of_space
= False
;
2611 int space_remaining
;
2612 struct ea_list
*ea_list
= NULL
;
2613 NTSTATUS ntstatus
= NT_STATUS_OK
;
2614 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2615 TALLOC_CTX
*ctx
= talloc_tos();
2616 struct dptr_struct
*dirptr
;
2617 struct smbd_server_connection
*sconn
= req
->sconn
;
2619 if (total_params
< 13) {
2620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2624 dptr_num
= SVAL(params
,0);
2625 maxentries
= SVAL(params
,2);
2626 info_level
= SVAL(params
,4);
2627 resume_key
= IVAL(params
,6);
2628 findnext_flags
= SVAL(params
,10);
2629 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2630 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2631 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2632 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2634 if (!continue_bit
) {
2635 /* We only need resume_name if continue_bit is zero. */
2636 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2638 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2639 &mask_contains_wcard
);
2640 if (!NT_STATUS_IS_OK(ntstatus
)) {
2641 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2642 complain (it thinks we're asking for the directory above the shared
2643 path or an invalid name). Catch this as the resume name is only compared, never used in
2644 a file access. JRA. */
2645 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2646 &resume_name
, params
+12,
2650 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2651 reply_nterror(req
, ntstatus
);
2657 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2658 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2659 resume_key = %d resume name = %s continue=%d level = %d\n",
2660 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2661 requires_resume_key
, resume_key
,
2662 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2665 /* W2K3 seems to treat zero as 1. */
2669 switch (info_level
) {
2670 case SMB_FIND_INFO_STANDARD
:
2671 case SMB_FIND_EA_SIZE
:
2672 case SMB_FIND_EA_LIST
:
2673 case SMB_FIND_FILE_DIRECTORY_INFO
:
2674 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2675 case SMB_FIND_FILE_NAMES_INFO
:
2676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2677 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2678 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2680 case SMB_FIND_FILE_UNIX
:
2681 case SMB_FIND_FILE_UNIX_INFO2
:
2682 /* Always use filesystem for UNIX mtime query. */
2683 ask_sharemode
= false;
2684 if (!lp_unix_extensions()) {
2685 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2690 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2694 if (info_level
== SMB_FIND_EA_LIST
) {
2697 if (total_data
< 4) {
2698 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2702 ea_size
= IVAL(pdata
,0);
2703 if (ea_size
!= total_data
) {
2704 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2705 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2706 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2710 if (!lp_ea_support(SNUM(conn
))) {
2711 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2715 /* Pull out the list of names. */
2716 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2723 *ppdata
= (char *)SMB_REALLOC(
2724 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2725 if(*ppdata
== NULL
) {
2726 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2731 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2733 /* Realloc the params space */
2734 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2735 if(*pparams
== NULL
) {
2736 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2742 /* Check that the dptr is valid */
2743 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2744 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2748 directory
= dptr_path(sconn
, dptr_num
);
2750 /* Get the wildcard mask from the dptr */
2751 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2752 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2753 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2759 /* Get the attr mask from the dptr */
2760 dirtype
= dptr_attr(sconn
, dptr_num
);
2762 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2763 dptr_num
, mask
, dirtype
,
2765 dptr_TellDir(dirptr
)));
2767 /* Initialize per TRANS2_FIND_NEXT operation data */
2768 dptr_init_search_op(dirptr
);
2770 /* We don't need to check for VOL here as this is returned by
2771 a different TRANS2 call. */
2773 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2774 directory
,lp_dontdescend(SNUM(conn
))));
2775 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2776 dont_descend
= True
;
2779 space_remaining
= max_data_bytes
;
2780 out_of_space
= False
;
2783 * Seek to the correct position. We no longer use the resume key but
2784 * depend on the last file name instead.
2787 if(!continue_bit
&& resume_name
&& *resume_name
) {
2790 long current_pos
= 0;
2792 * Remember, name_to_8_3 is called by
2793 * get_lanman2_dir_entry(), so the resume name
2794 * could be mangled. Ensure we check the unmangled name.
2797 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2798 char *new_resume_name
= NULL
;
2799 mangle_lookup_name_from_8_3(ctx
,
2803 if (new_resume_name
) {
2804 resume_name
= new_resume_name
;
2809 * Fix for NT redirector problem triggered by resume key indexes
2810 * changing between directory scans. We now return a resume key of 0
2811 * and instead look for the filename to continue from (also given
2812 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2813 * findfirst/findnext (as is usual) then the directory pointer
2814 * should already be at the correct place.
2817 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2818 } /* end if resume_name && !continue_bit */
2820 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2821 bool got_exact_match
= False
;
2823 /* this is a heuristic to avoid seeking the dirptr except when
2824 absolutely necessary. It allows for a filename of about 40 chars */
2825 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2826 out_of_space
= True
;
2829 finished
= !get_lanman2_dir_entry(ctx
,
2833 mask
,dirtype
,info_level
,
2834 requires_resume_key
,dont_descend
,
2837 space_remaining
, &out_of_space
,
2839 &last_entry_off
, ea_list
);
2842 if (finished
&& out_of_space
)
2845 if (!finished
&& !out_of_space
)
2849 * As an optimisation if we know we aren't looking
2850 * for a wildcard name (ie. the name matches the wildcard exactly)
2851 * then we can finish on any (first) match.
2852 * This speeds up large directory searches. JRA.
2858 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2861 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2862 smb_fn_name(req
->cmd
),
2863 mask
, directory
, dirtype
, numentries
) );
2865 /* Check if we can close the dirptr */
2866 if(close_after_request
|| (finished
&& close_if_end
)) {
2867 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2868 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2871 /* Set up the return parameter block */
2872 SSVAL(params
,0,numentries
);
2873 SSVAL(params
,2,finished
);
2874 SSVAL(params
,4,0); /* Never an EA error */
2875 SSVAL(params
,6,last_entry_off
);
2877 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2883 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2885 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2889 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2891 SMB_ASSERT(extended_info
!= NULL
);
2893 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2894 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2895 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2896 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2897 #ifdef SAMBA_VERSION_REVISION
2898 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2900 extended_info
->samba_subversion
= 0;
2901 #ifdef SAMBA_VERSION_RC_RELEASE
2902 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2904 #ifdef SAMBA_VERSION_PRE_RELEASE
2905 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2908 #ifdef SAMBA_VERSION_VENDOR_PATCH
2909 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2911 extended_info
->samba_gitcommitdate
= 0;
2912 #ifdef SAMBA_VERSION_COMMIT_TIME
2913 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2916 memset(extended_info
->samba_version_string
, 0,
2917 sizeof(extended_info
->samba_version_string
));
2919 snprintf (extended_info
->samba_version_string
,
2920 sizeof(extended_info
->samba_version_string
),
2921 "%s", samba_version_string());
2924 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2925 TALLOC_CTX
*mem_ctx
,
2926 uint16_t info_level
,
2928 unsigned int max_data_bytes
,
2932 char *pdata
, *end_data
;
2933 int data_len
= 0, len
;
2934 const char *vname
= volume_label(SNUM(conn
));
2935 int snum
= SNUM(conn
);
2936 char *fstype
= lp_fstype(SNUM(conn
));
2937 uint32 additional_flags
= 0;
2938 struct smb_filename smb_fname_dot
;
2942 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2943 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2944 "info level (0x%x) on IPC$.\n",
2945 (unsigned int)info_level
));
2946 return NT_STATUS_ACCESS_DENIED
;
2950 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2952 ZERO_STRUCT(smb_fname_dot
);
2953 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2955 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2956 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2957 return map_nt_error_from_unix(errno
);
2960 st
= smb_fname_dot
.st
;
2962 *ppdata
= (char *)SMB_REALLOC(
2963 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2964 if (*ppdata
== NULL
) {
2965 return NT_STATUS_NO_MEMORY
;
2969 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2970 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2972 switch (info_level
) {
2973 case SMB_INFO_ALLOCATION
:
2975 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2977 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2978 return map_nt_error_from_unix(errno
);
2981 block_size
= lp_block_size(snum
);
2982 if (bsize
< block_size
) {
2983 uint64_t factor
= block_size
/bsize
;
2988 if (bsize
> block_size
) {
2989 uint64_t factor
= bsize
/block_size
;
2994 bytes_per_sector
= 512;
2995 sectors_per_unit
= bsize
/bytes_per_sector
;
2997 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2998 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2999 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3001 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3002 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3003 SIVAL(pdata
,l1_cUnit
,dsize
);
3004 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3005 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3009 case SMB_INFO_VOLUME
:
3010 /* Return volume name */
3012 * Add volume serial number - hash of a combination of
3013 * the called hostname and the service name.
3015 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3017 * Win2k3 and previous mess this up by sending a name length
3018 * one byte short. I believe only older clients (OS/2 Win9x) use
3019 * this call so try fixing this by adding a terminating null to
3020 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3024 pdata
+l2_vol_szVolLabel
, vname
,
3025 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3026 STR_NOALIGN
|STR_TERMINATE
);
3027 SCVAL(pdata
,l2_vol_cch
,len
);
3028 data_len
= l2_vol_szVolLabel
+ len
;
3029 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3030 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3034 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3035 case SMB_FS_ATTRIBUTE_INFORMATION
:
3037 additional_flags
= 0;
3038 #if defined(HAVE_SYS_QUOTAS)
3039 additional_flags
|= FILE_VOLUME_QUOTAS
;
3042 if(lp_nt_acl_support(SNUM(conn
))) {
3043 additional_flags
|= FILE_PERSISTENT_ACLS
;
3046 /* Capabilities are filled in at connection time through STATVFS call */
3047 additional_flags
|= conn
->fs_capabilities
;
3048 additional_flags
|= lp_parm_int(conn
->params
->service
,
3049 "share", "fake_fscaps",
3052 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3053 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3054 additional_flags
); /* FS ATTRIBUTES */
3056 SIVAL(pdata
,4,255); /* Max filename component length */
3057 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3058 and will think we can't do long filenames */
3059 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3060 PTR_DIFF(end_data
, pdata
+12),
3063 data_len
= 12 + len
;
3066 case SMB_QUERY_FS_LABEL_INFO
:
3067 case SMB_FS_LABEL_INFORMATION
:
3068 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3069 PTR_DIFF(end_data
, pdata
+4), 0);
3074 case SMB_QUERY_FS_VOLUME_INFO
:
3075 case SMB_FS_VOLUME_INFORMATION
:
3078 * Add volume serial number - hash of a combination of
3079 * the called hostname and the service name.
3081 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3082 (str_checksum(get_local_machine_name())<<16));
3084 /* Max label len is 32 characters. */
3085 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3086 PTR_DIFF(end_data
, pdata
+18),
3088 SIVAL(pdata
,12,len
);
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3092 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3095 case SMB_QUERY_FS_SIZE_INFO
:
3096 case SMB_FS_SIZE_INFORMATION
:
3098 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3100 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3101 return map_nt_error_from_unix(errno
);
3103 block_size
= lp_block_size(snum
);
3104 if (bsize
< block_size
) {
3105 uint64_t factor
= block_size
/bsize
;
3110 if (bsize
> block_size
) {
3111 uint64_t factor
= bsize
/block_size
;
3116 bytes_per_sector
= 512;
3117 sectors_per_unit
= bsize
/bytes_per_sector
;
3118 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3119 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3120 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3121 SBIG_UINT(pdata
,0,dsize
);
3122 SBIG_UINT(pdata
,8,dfree
);
3123 SIVAL(pdata
,16,sectors_per_unit
);
3124 SIVAL(pdata
,20,bytes_per_sector
);
3128 case SMB_FS_FULL_SIZE_INFORMATION
:
3130 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3132 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3133 return map_nt_error_from_unix(errno
);
3135 block_size
= lp_block_size(snum
);
3136 if (bsize
< block_size
) {
3137 uint64_t factor
= block_size
/bsize
;
3142 if (bsize
> block_size
) {
3143 uint64_t factor
= bsize
/block_size
;
3148 bytes_per_sector
= 512;
3149 sectors_per_unit
= bsize
/bytes_per_sector
;
3150 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3151 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3152 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3153 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3154 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3155 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3156 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3157 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3161 case SMB_QUERY_FS_DEVICE_INFO
:
3162 case SMB_FS_DEVICE_INFORMATION
:
3164 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3166 if (!CAN_WRITE(conn
)) {
3167 characteristics
|= FILE_READ_ONLY_DEVICE
;
3170 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3171 SIVAL(pdata
,4,characteristics
);
3175 #ifdef HAVE_SYS_QUOTAS
3176 case SMB_FS_QUOTA_INFORMATION
:
3178 * what we have to send --metze:
3180 * Unknown1: 24 NULL bytes
3181 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3182 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3183 * Quota Flags: 2 byte :
3184 * Unknown3: 6 NULL bytes
3188 * details for Quota Flags:
3190 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3191 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3192 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3193 * 0x0001 Enable Quotas: enable quota for this fs
3197 /* we need to fake up a fsp here,
3198 * because its not send in this call
3201 SMB_NTQUOTA_STRUCT quotas
;
3204 ZERO_STRUCT(quotas
);
3210 if (get_current_uid(conn
) != 0) {
3211 DEBUG(0,("set_user_quota: access_denied "
3212 "service [%s] user [%s]\n",
3213 lp_servicename(SNUM(conn
)),
3214 conn
->session_info
->unix_name
));
3215 return NT_STATUS_ACCESS_DENIED
;
3218 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3219 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3220 return map_nt_error_from_unix(errno
);
3225 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3226 lp_servicename(SNUM(conn
))));
3228 /* Unknown1 24 NULL bytes*/
3229 SBIG_UINT(pdata
,0,(uint64_t)0);
3230 SBIG_UINT(pdata
,8,(uint64_t)0);
3231 SBIG_UINT(pdata
,16,(uint64_t)0);
3233 /* Default Soft Quota 8 bytes */
3234 SBIG_UINT(pdata
,24,quotas
.softlim
);
3236 /* Default Hard Quota 8 bytes */
3237 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3239 /* Quota flag 2 bytes */
3240 SSVAL(pdata
,40,quotas
.qflags
);
3242 /* Unknown3 6 NULL bytes */
3248 #endif /* HAVE_SYS_QUOTAS */
3249 case SMB_FS_OBJECTID_INFORMATION
:
3251 unsigned char objid
[16];
3252 struct smb_extended_info extended_info
;
3253 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3254 samba_extended_info_version (&extended_info
);
3255 SIVAL(pdata
,16,extended_info
.samba_magic
);
3256 SIVAL(pdata
,20,extended_info
.samba_version
);
3257 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3258 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3259 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3265 * Query the version and capabilities of the CIFS UNIX extensions
3269 case SMB_QUERY_CIFS_UNIX_INFO
:
3271 bool large_write
= lp_min_receive_file_size() &&
3272 !srv_is_signing_active(conn
->sconn
);
3273 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3274 int encrypt_caps
= 0;
3276 if (!lp_unix_extensions()) {
3277 return NT_STATUS_INVALID_LEVEL
;
3280 switch (conn
->encrypt_level
) {
3286 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3289 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3290 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3291 large_write
= false;
3297 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3298 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3300 /* We have POSIX ACLs, pathname, encryption,
3301 * large read/write, and locking capability. */
3303 SBIG_UINT(pdata
,4,((uint64_t)(
3304 CIFS_UNIX_POSIX_ACLS_CAP
|
3305 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3306 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3307 CIFS_UNIX_EXTATTR_CAP
|
3308 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3310 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3312 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3316 case SMB_QUERY_POSIX_FS_INFO
:
3319 vfs_statvfs_struct svfs
;
3321 if (!lp_unix_extensions()) {
3322 return NT_STATUS_INVALID_LEVEL
;
3325 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3329 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3330 SIVAL(pdata
,4,svfs
.BlockSize
);
3331 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3332 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3333 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3334 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3335 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3336 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3337 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3339 } else if (rc
== EOPNOTSUPP
) {
3340 return NT_STATUS_INVALID_LEVEL
;
3341 #endif /* EOPNOTSUPP */
3343 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3344 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3349 case SMB_QUERY_POSIX_WHOAMI
:
3355 if (!lp_unix_extensions()) {
3356 return NT_STATUS_INVALID_LEVEL
;
3359 if (max_data_bytes
< 40) {
3360 return NT_STATUS_BUFFER_TOO_SMALL
;
3363 /* We ARE guest if global_sid_Builtin_Guests is
3364 * in our list of SIDs.
3366 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3367 conn
->session_info
->security_token
)) {
3368 flags
|= SMB_WHOAMI_GUEST
;
3371 /* We are NOT guest if global_sid_Authenticated_Users
3372 * is in our list of SIDs.
3374 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3375 conn
->session_info
->security_token
)) {
3376 flags
&= ~SMB_WHOAMI_GUEST
;
3379 /* NOTE: 8 bytes for UID/GID, irrespective of native
3380 * platform size. This matches
3381 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3383 data_len
= 4 /* flags */
3390 + 4 /* pad/reserved */
3391 + (conn
->session_info
->utok
.ngroups
* 8)
3393 + (conn
->session_info
->security_token
->num_sids
*
3397 SIVAL(pdata
, 0, flags
);
3398 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3400 (uint64_t)conn
->session_info
->utok
.uid
);
3401 SBIG_UINT(pdata
, 16,
3402 (uint64_t)conn
->session_info
->utok
.gid
);
3405 if (data_len
>= max_data_bytes
) {
3406 /* Potential overflow, skip the GIDs and SIDs. */
3408 SIVAL(pdata
, 24, 0); /* num_groups */
3409 SIVAL(pdata
, 28, 0); /* num_sids */
3410 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3411 SIVAL(pdata
, 36, 0); /* reserved */
3417 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3418 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3420 /* We walk the SID list twice, but this call is fairly
3421 * infrequent, and I don't expect that it's performance
3422 * sensitive -- jpeach
3424 for (i
= 0, sid_bytes
= 0;
3425 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3426 sid_bytes
+= ndr_size_dom_sid(
3427 &conn
->session_info
->security_token
->sids
[i
],
3431 /* SID list byte count */
3432 SIVAL(pdata
, 32, sid_bytes
);
3434 /* 4 bytes pad/reserved - must be zero */
3435 SIVAL(pdata
, 36, 0);
3439 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3440 SBIG_UINT(pdata
, data_len
,
3441 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3447 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3448 int sid_len
= ndr_size_dom_sid(
3449 &conn
->session_info
->security_token
->sids
[i
],
3452 sid_linearize(pdata
+ data_len
, sid_len
,
3453 &conn
->session_info
->security_token
->sids
[i
]);
3454 data_len
+= sid_len
;
3460 case SMB_MAC_QUERY_FS_INFO
:
3462 * Thursby MAC extension... ONLY on NTFS filesystems
3463 * once we do streams then we don't need this
3465 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3467 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3472 return NT_STATUS_INVALID_LEVEL
;
3475 *ret_data_len
= data_len
;
3476 return NT_STATUS_OK
;
3479 /****************************************************************************
3480 Reply to a TRANS2_QFSINFO (query filesystem info).
3481 ****************************************************************************/
3483 static void call_trans2qfsinfo(connection_struct
*conn
,
3484 struct smb_request
*req
,
3485 char **pparams
, int total_params
,
3486 char **ppdata
, int total_data
,
3487 unsigned int max_data_bytes
)
3489 char *params
= *pparams
;
3490 uint16_t info_level
;
3494 if (total_params
< 2) {
3495 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3499 info_level
= SVAL(params
,0);
3501 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3502 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3503 DEBUG(0,("call_trans2qfsinfo: encryption required "
3504 "and info level 0x%x sent.\n",
3505 (unsigned int)info_level
));
3506 exit_server_cleanly("encryption required "
3512 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3514 status
= smbd_do_qfsinfo(conn
, req
,
3519 if (!NT_STATUS_IS_OK(status
)) {
3520 reply_nterror(req
, status
);
3524 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3527 DEBUG( 4, ( "%s info_level = %d\n",
3528 smb_fn_name(req
->cmd
), info_level
) );
3533 /****************************************************************************
3534 Reply to a TRANS2_SETFSINFO (set filesystem info).
3535 ****************************************************************************/
3537 static void call_trans2setfsinfo(connection_struct
*conn
,
3538 struct smb_request
*req
,
3539 char **pparams
, int total_params
,
3540 char **ppdata
, int total_data
,
3541 unsigned int max_data_bytes
)
3543 char *pdata
= *ppdata
;
3544 char *params
= *pparams
;
3547 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3550 if (total_params
< 4) {
3551 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3557 info_level
= SVAL(params
,2);
3560 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3561 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3562 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3563 "info level (0x%x) on IPC$.\n",
3564 (unsigned int)info_level
));
3565 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3570 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3571 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3572 DEBUG(0,("call_trans2setfsinfo: encryption required "
3573 "and info level 0x%x sent.\n",
3574 (unsigned int)info_level
));
3575 exit_server_cleanly("encryption required "
3581 switch(info_level
) {
3582 case SMB_SET_CIFS_UNIX_INFO
:
3584 uint16 client_unix_major
;
3585 uint16 client_unix_minor
;
3586 uint32 client_unix_cap_low
;
3587 uint32 client_unix_cap_high
;
3589 if (!lp_unix_extensions()) {
3591 NT_STATUS_INVALID_LEVEL
);
3595 /* There should be 12 bytes of capabilities set. */
3596 if (total_data
< 8) {
3599 NT_STATUS_INVALID_PARAMETER
);
3602 client_unix_major
= SVAL(pdata
,0);
3603 client_unix_minor
= SVAL(pdata
,2);
3604 client_unix_cap_low
= IVAL(pdata
,4);
3605 client_unix_cap_high
= IVAL(pdata
,8);
3606 /* Just print these values for now. */
3607 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3608 cap_low = 0x%x, cap_high = 0x%x\n",
3609 (unsigned int)client_unix_major
,
3610 (unsigned int)client_unix_minor
,
3611 (unsigned int)client_unix_cap_low
,
3612 (unsigned int)client_unix_cap_high
));
3614 /* Here is where we must switch to posix pathname processing... */
3615 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3616 lp_set_posix_pathnames();
3617 mangle_change_to_posix();
3620 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3621 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3622 /* Client that knows how to do posix locks,
3623 * but not posix open/mkdir operations. Set a
3624 * default type for read/write checks. */
3626 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3632 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3635 size_t param_len
= 0;
3636 size_t data_len
= total_data
;
3638 if (!lp_unix_extensions()) {
3641 NT_STATUS_INVALID_LEVEL
);
3645 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3648 NT_STATUS_NOT_SUPPORTED
);
3652 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3653 DEBUG( 2,("call_trans2setfsinfo: "
3654 "request transport encryption disabled"
3655 "with 'fork echo handler = yes'\n"));
3658 NT_STATUS_NOT_SUPPORTED
);
3662 DEBUG( 4,("call_trans2setfsinfo: "
3663 "request transport encryption.\n"));
3665 status
= srv_request_encryption_setup(conn
,
3666 (unsigned char **)ppdata
,
3668 (unsigned char **)pparams
,
3671 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3672 !NT_STATUS_IS_OK(status
)) {
3673 reply_nterror(req
, status
);
3677 send_trans2_replies(conn
, req
,
3684 if (NT_STATUS_IS_OK(status
)) {
3685 /* Server-side transport
3686 * encryption is now *on*. */
3687 status
= srv_encryption_start(conn
);
3688 if (!NT_STATUS_IS_OK(status
)) {
3689 exit_server_cleanly(
3690 "Failure in setting "
3691 "up encrypted transport");
3697 case SMB_FS_QUOTA_INFORMATION
:
3699 files_struct
*fsp
= NULL
;
3700 SMB_NTQUOTA_STRUCT quotas
;
3702 ZERO_STRUCT(quotas
);
3705 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3706 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3707 lp_servicename(SNUM(conn
)),
3708 conn
->session_info
->unix_name
));
3709 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3713 /* note: normaly there're 48 bytes,
3714 * but we didn't use the last 6 bytes for now
3717 fsp
= file_fsp(req
, SVAL(params
,0));
3719 if (!check_fsp_ntquota_handle(conn
, req
,
3721 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3723 req
, NT_STATUS_INVALID_HANDLE
);
3727 if (total_data
< 42) {
3728 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3732 NT_STATUS_INVALID_PARAMETER
);
3736 /* unknown_1 24 NULL bytes in pdata*/
3738 /* the soft quotas 8 bytes (uint64_t)*/
3739 quotas
.softlim
= BVAL(pdata
,24);
3741 /* the hard quotas 8 bytes (uint64_t)*/
3742 quotas
.hardlim
= BVAL(pdata
,32);
3744 /* quota_flags 2 bytes **/
3745 quotas
.qflags
= SVAL(pdata
,40);
3747 /* unknown_2 6 NULL bytes follow*/
3749 /* now set the quotas */
3750 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3751 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3752 reply_nterror(req
, map_nt_error_from_unix(errno
));
3759 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3761 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3767 * sending this reply works fine,
3768 * but I'm not sure it's the same
3769 * like windows do...
3772 reply_outbuf(req
, 10, 0);
3775 #if defined(HAVE_POSIX_ACLS)
3776 /****************************************************************************
3777 Utility function to count the number of entries in a POSIX acl.
3778 ****************************************************************************/
3780 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3782 unsigned int ace_count
= 0;
3783 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3784 SMB_ACL_ENTRY_T entry
;
3786 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3788 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3789 entry_id
= SMB_ACL_NEXT_ENTRY
;
3796 /****************************************************************************
3797 Utility function to marshall a POSIX acl into wire format.
3798 ****************************************************************************/
3800 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3802 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3803 SMB_ACL_ENTRY_T entry
;
3805 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3806 SMB_ACL_TAG_T tagtype
;
3807 SMB_ACL_PERMSET_T permset
;
3808 unsigned char perms
= 0;
3809 unsigned int own_grp
;
3812 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3813 entry_id
= SMB_ACL_NEXT_ENTRY
;
3816 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3817 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3821 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3822 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3826 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3827 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3828 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3830 SCVAL(pdata
,1,perms
);
3833 case SMB_ACL_USER_OBJ
:
3834 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3835 own_grp
= (unsigned int)pst
->st_ex_uid
;
3836 SIVAL(pdata
,2,own_grp
);
3841 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3843 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3846 own_grp
= (unsigned int)*puid
;
3847 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3848 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3849 SIVAL(pdata
,2,own_grp
);
3853 case SMB_ACL_GROUP_OBJ
:
3854 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3855 own_grp
= (unsigned int)pst
->st_ex_gid
;
3856 SIVAL(pdata
,2,own_grp
);
3861 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3863 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3866 own_grp
= (unsigned int)*pgid
;
3867 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3868 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3869 SIVAL(pdata
,2,own_grp
);
3874 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3875 SIVAL(pdata
,2,0xFFFFFFFF);
3876 SIVAL(pdata
,6,0xFFFFFFFF);
3879 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3880 SIVAL(pdata
,2,0xFFFFFFFF);
3881 SIVAL(pdata
,6,0xFFFFFFFF);
3884 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3887 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3894 /****************************************************************************
3895 Store the FILE_UNIX_BASIC info.
3896 ****************************************************************************/
3898 static char *store_file_unix_basic(connection_struct
*conn
,
3901 const SMB_STRUCT_STAT
*psbuf
)
3903 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3905 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3906 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3908 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3911 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3914 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3915 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3916 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3919 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3923 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3927 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3930 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3934 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3938 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3941 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3945 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3952 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3953 * the chflags(2) (or equivalent) flags.
3955 * XXX: this really should be behind the VFS interface. To do this, we would
3956 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3957 * Each VFS module could then implement its own mapping as appropriate for the
3958 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3960 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3964 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3968 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3972 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3976 { UF_HIDDEN
, EXT_HIDDEN
},
3979 /* Do not remove. We need to guarantee that this array has at least one
3980 * entry to build on HP-UX.
3986 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3987 uint32
*smb_fflags
, uint32
*smb_fmask
)
3991 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3992 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3993 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3994 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3999 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4000 const uint32 smb_fflags
,
4001 const uint32 smb_fmask
,
4004 uint32 max_fmask
= 0;
4007 *stat_fflags
= psbuf
->st_ex_flags
;
4009 /* For each flags requested in smb_fmask, check the state of the
4010 * corresponding flag in smb_fflags and set or clear the matching
4014 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4015 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4016 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4017 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4018 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4020 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4025 /* If smb_fmask is asking to set any bits that are not supported by
4026 * our flag mappings, we should fail.
4028 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4036 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4037 * of file flags and birth (create) time.
4039 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4042 const SMB_STRUCT_STAT
*psbuf
)
4044 uint32 file_flags
= 0;
4045 uint32 flags_mask
= 0;
4047 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4049 /* Create (birth) time 64 bit */
4050 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4053 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4054 SIVAL(pdata
, 0, file_flags
); /* flags */
4055 SIVAL(pdata
, 4, flags_mask
); /* mask */
4061 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4062 const struct stream_struct
*streams
,
4064 unsigned int max_data_bytes
,
4065 unsigned int *data_size
)
4068 unsigned int ofs
= 0;
4070 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4071 unsigned int next_offset
;
4073 smb_ucs2_t
*namebuf
;
4075 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4076 streams
[i
].name
, &namelen
) ||
4079 return NT_STATUS_INVALID_PARAMETER
;
4083 * name_buf is now null-terminated, we need to marshall as not
4089 SIVAL(data
, ofs
+4, namelen
);
4090 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4091 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4092 memcpy(data
+ofs
+24, namebuf
, namelen
);
4093 TALLOC_FREE(namebuf
);
4095 next_offset
= ofs
+ 24 + namelen
;
4097 if (i
== num_streams
-1) {
4098 SIVAL(data
, ofs
, 0);
4101 unsigned int align
= ndr_align_size(next_offset
, 8);
4103 memset(data
+next_offset
, 0, align
);
4104 next_offset
+= align
;
4106 SIVAL(data
, ofs
, next_offset
- ofs
);
4115 return NT_STATUS_OK
;
4118 /****************************************************************************
4119 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4120 ****************************************************************************/
4122 static void call_trans2qpipeinfo(connection_struct
*conn
,
4123 struct smb_request
*req
,
4124 unsigned int tran_call
,
4125 char **pparams
, int total_params
,
4126 char **ppdata
, int total_data
,
4127 unsigned int max_data_bytes
)
4129 char *params
= *pparams
;
4130 char *pdata
= *ppdata
;
4131 unsigned int data_size
= 0;
4132 unsigned int param_size
= 2;
4137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4141 if (total_params
< 4) {
4142 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4146 fsp
= file_fsp(req
, SVAL(params
,0));
4147 if (!fsp_is_np(fsp
)) {
4148 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4152 info_level
= SVAL(params
,2);
4154 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4155 if (*pparams
== NULL
) {
4156 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4161 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4162 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4163 if (*ppdata
== NULL
) {
4164 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4169 switch (info_level
) {
4170 case SMB_FILE_STANDARD_INFORMATION
:
4172 SOFF_T(pdata
,0,4096LL);
4179 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4183 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4189 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4190 TALLOC_CTX
*mem_ctx
,
4191 uint16_t info_level
,
4193 struct smb_filename
*smb_fname
,
4194 bool delete_pending
,
4195 struct timespec write_time_ts
,
4196 struct ea_list
*ea_list
,
4197 int lock_data_count
,
4200 unsigned int max_data_bytes
,
4202 unsigned int *pdata_size
)
4204 char *pdata
= *ppdata
;
4205 char *dstart
, *dend
;
4206 unsigned int data_size
;
4207 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4208 time_t create_time
, mtime
, atime
, c_time
;
4209 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4216 uint64_t file_size
= 0;
4218 uint64_t allocation_size
= 0;
4219 uint64_t file_index
= 0;
4220 uint32_t access_mask
= 0;
4222 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4223 return NT_STATUS_INVALID_LEVEL
;
4226 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4227 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4228 info_level
, max_data_bytes
));
4230 mode
= dos_mode(conn
, smb_fname
);
4231 nlink
= psbuf
->st_ex_nlink
;
4233 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4237 if ((nlink
> 0) && delete_pending
) {
4241 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4242 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4243 if (*ppdata
== NULL
) {
4244 return NT_STATUS_NO_MEMORY
;
4248 dend
= dstart
+ data_size
- 1;
4250 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4251 update_stat_ex_mtime(psbuf
, write_time_ts
);
4254 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4255 mtime_ts
= psbuf
->st_ex_mtime
;
4256 atime_ts
= psbuf
->st_ex_atime
;
4257 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4259 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4260 dos_filetime_timespec(&create_time_ts
);
4261 dos_filetime_timespec(&mtime_ts
);
4262 dos_filetime_timespec(&atime_ts
);
4263 dos_filetime_timespec(&ctime_ts
);
4266 create_time
= convert_timespec_to_time_t(create_time_ts
);
4267 mtime
= convert_timespec_to_time_t(mtime_ts
);
4268 atime
= convert_timespec_to_time_t(atime_ts
);
4269 c_time
= convert_timespec_to_time_t(ctime_ts
);
4271 p
= strrchr_m(smb_fname
->base_name
,'/');
4273 base_name
= smb_fname
->base_name
;
4277 /* NT expects the name to be in an exact form of the *full*
4278 filename. See the trans2 torture test */
4279 if (ISDOT(base_name
)) {
4280 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4282 return NT_STATUS_NO_MEMORY
;
4285 dos_fname
= talloc_asprintf(mem_ctx
,
4287 smb_fname
->base_name
);
4289 return NT_STATUS_NO_MEMORY
;
4291 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4292 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4293 smb_fname
->stream_name
);
4295 return NT_STATUS_NO_MEMORY
;
4299 string_replace(dos_fname
, '/', '\\');
4302 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4305 /* Do we have this path open ? */
4307 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4308 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4309 if (fsp1
&& fsp1
->initial_allocation_size
) {
4310 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4314 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4315 file_size
= get_file_size_stat(psbuf
);
4319 pos
= fsp
->fh
->position_information
;
4323 access_mask
= fsp
->access_mask
;
4325 /* GENERIC_EXECUTE mapping from Windows */
4326 access_mask
= 0x12019F;
4329 /* This should be an index number - looks like
4332 I think this causes us to fail the IFSKIT
4333 BasicFileInformationTest. -tpot */
4334 file_index
= get_FileIndex(conn
, psbuf
);
4336 switch (info_level
) {
4337 case SMB_INFO_STANDARD
:
4338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4340 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4341 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4342 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4343 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4344 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4345 SSVAL(pdata
,l1_attrFile
,mode
);
4348 case SMB_INFO_QUERY_EA_SIZE
:
4350 unsigned int ea_size
=
4351 estimate_ea_size(conn
, fsp
,
4352 smb_fname
->base_name
);
4353 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4355 srv_put_dos_date2(pdata
,0,create_time
);
4356 srv_put_dos_date2(pdata
,4,atime
);
4357 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4358 SIVAL(pdata
,12,(uint32
)file_size
);
4359 SIVAL(pdata
,16,(uint32
)allocation_size
);
4360 SSVAL(pdata
,20,mode
);
4361 SIVAL(pdata
,22,ea_size
);
4365 case SMB_INFO_IS_NAME_VALID
:
4366 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4368 /* os/2 needs this ? really ?*/
4369 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4371 /* This is only reached for qpathinfo */
4375 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4377 size_t total_ea_len
= 0;
4378 struct ea_list
*ea_file_list
= NULL
;
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4383 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4384 smb_fname
->base_name
,
4386 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4388 if (!ea_list
|| (total_ea_len
> data_size
)) {
4390 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4394 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4398 case SMB_INFO_QUERY_ALL_EAS
:
4400 /* We have data_size bytes to put EA's into. */
4401 size_t total_ea_len
= 0;
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4405 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4406 smb_fname
->base_name
,
4408 if (!ea_list
|| (total_ea_len
> data_size
)) {
4410 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4414 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4418 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4420 /* This is FileFullEaInformation - 0xF which maps to
4421 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4423 /* We have data_size bytes to put EA's into. */
4424 size_t total_ea_len
= 0;
4425 struct ea_list
*ea_file_list
= NULL
;
4427 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4429 /*TODO: add filtering and index handling */
4432 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4433 smb_fname
->base_name
,
4435 if (!ea_file_list
) {
4436 return NT_STATUS_NO_EAS_ON_FILE
;
4439 status
= fill_ea_chained_buffer(mem_ctx
,
4443 conn
, ea_file_list
);
4444 if (!NT_STATUS_IS_OK(status
)) {
4450 case SMB_FILE_BASIC_INFORMATION
:
4451 case SMB_QUERY_FILE_BASIC_INFO
:
4453 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4455 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4457 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4461 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4462 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4463 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4464 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4465 SIVAL(pdata
,32,mode
);
4467 DEBUG(5,("SMB_QFBI - "));
4468 DEBUG(5,("create: %s ", ctime(&create_time
)));
4469 DEBUG(5,("access: %s ", ctime(&atime
)));
4470 DEBUG(5,("write: %s ", ctime(&mtime
)));
4471 DEBUG(5,("change: %s ", ctime(&c_time
)));
4472 DEBUG(5,("mode: %x\n", mode
));
4475 case SMB_FILE_STANDARD_INFORMATION
:
4476 case SMB_QUERY_FILE_STANDARD_INFO
:
4478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4480 SOFF_T(pdata
,0,allocation_size
);
4481 SOFF_T(pdata
,8,file_size
);
4482 SIVAL(pdata
,16,nlink
);
4483 SCVAL(pdata
,20,delete_pending
?1:0);
4484 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4485 SSVAL(pdata
,22,0); /* Padding. */
4488 case SMB_FILE_EA_INFORMATION
:
4489 case SMB_QUERY_FILE_EA_INFO
:
4491 unsigned int ea_size
=
4492 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4495 SIVAL(pdata
,0,ea_size
);
4499 /* Get the 8.3 name - used if NT SMB was negotiated. */
4500 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4501 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4504 char mangled_name
[13];
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4506 if (!name_to_8_3(base_name
,mangled_name
,
4507 True
,conn
->params
)) {
4508 return NT_STATUS_NO_MEMORY
;
4510 len
= srvstr_push(dstart
, flags2
,
4511 pdata
+4, mangled_name
,
4512 PTR_DIFF(dend
, pdata
+4),
4514 data_size
= 4 + len
;
4519 case SMB_QUERY_FILE_NAME_INFO
:
4523 this must be *exactly* right for ACLs on mapped drives to work
4525 len
= srvstr_push(dstart
, flags2
,
4527 PTR_DIFF(dend
, pdata
+4),
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4530 data_size
= 4 + len
;
4535 case SMB_FILE_ALLOCATION_INFORMATION
:
4536 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4539 SOFF_T(pdata
,0,allocation_size
);
4542 case SMB_FILE_END_OF_FILE_INFORMATION
:
4543 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4546 SOFF_T(pdata
,0,file_size
);
4549 case SMB_QUERY_FILE_ALL_INFO
:
4550 case SMB_FILE_ALL_INFORMATION
:
4553 unsigned int ea_size
=
4554 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4556 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4557 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4558 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4559 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4560 SIVAL(pdata
,32,mode
);
4561 SIVAL(pdata
,36,0); /* padding. */
4563 SOFF_T(pdata
,0,allocation_size
);
4564 SOFF_T(pdata
,8,file_size
);
4565 SIVAL(pdata
,16,nlink
);
4566 SCVAL(pdata
,20,delete_pending
);
4567 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4570 SIVAL(pdata
,0,ea_size
);
4571 pdata
+= 4; /* EA info */
4572 len
= srvstr_push(dstart
, flags2
,
4574 PTR_DIFF(dend
, pdata
+4),
4578 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4582 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4585 unsigned int ea_size
=
4586 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4588 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4589 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4590 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4591 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4592 SIVAL(pdata
, 0x20, mode
);
4593 SIVAL(pdata
, 0x24, 0); /* padding. */
4594 SBVAL(pdata
, 0x28, allocation_size
);
4595 SBVAL(pdata
, 0x30, file_size
);
4596 SIVAL(pdata
, 0x38, nlink
);
4597 SCVAL(pdata
, 0x3C, delete_pending
);
4598 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4599 SSVAL(pdata
, 0x3E, 0); /* padding */
4600 SBVAL(pdata
, 0x40, file_index
);
4601 SIVAL(pdata
, 0x48, ea_size
);
4602 SIVAL(pdata
, 0x4C, access_mask
);
4603 SBVAL(pdata
, 0x50, pos
);
4604 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4605 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4609 len
= srvstr_push(dstart
, flags2
,
4611 PTR_DIFF(dend
, pdata
+4),
4615 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4618 case SMB_FILE_INTERNAL_INFORMATION
:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4621 SBVAL(pdata
, 0, file_index
);
4625 case SMB_FILE_ACCESS_INFORMATION
:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4627 SIVAL(pdata
, 0, access_mask
);
4631 case SMB_FILE_NAME_INFORMATION
:
4632 /* Pathname with leading '\'. */
4635 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4637 SIVAL(pdata
,0,byte_len
);
4638 data_size
= 4 + byte_len
;
4642 case SMB_FILE_DISPOSITION_INFORMATION
:
4643 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4645 SCVAL(pdata
,0,delete_pending
);
4648 case SMB_FILE_POSITION_INFORMATION
:
4649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4651 SOFF_T(pdata
,0,pos
);
4654 case SMB_FILE_MODE_INFORMATION
:
4655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4656 SIVAL(pdata
,0,mode
);
4660 case SMB_FILE_ALIGNMENT_INFORMATION
:
4661 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4662 SIVAL(pdata
,0,0); /* No alignment needed. */
4667 * NT4 server just returns "invalid query" to this - if we try
4668 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4671 /* The first statement above is false - verified using Thursby
4672 * client against NT4 -- gcolley.
4674 case SMB_QUERY_FILE_STREAM_INFO
:
4675 case SMB_FILE_STREAM_INFORMATION
: {
4676 unsigned int num_streams
;
4677 struct stream_struct
*streams
;
4679 DEBUG(10,("smbd_do_qfilepathinfo: "
4680 "SMB_FILE_STREAM_INFORMATION\n"));
4682 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4683 return NT_STATUS_INVALID_PARAMETER
;
4686 status
= SMB_VFS_STREAMINFO(
4687 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4688 &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
);
5109 if (total_params
< 7) {
5110 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5114 info_level
= SVAL(params
,0);
5116 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5118 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5119 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5123 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5125 STR_TERMINATE
, &status
);
5126 if (!NT_STATUS_IS_OK(status
)) {
5127 reply_nterror(req
, status
);
5131 status
= filename_convert(req
,
5133 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5138 if (!NT_STATUS_IS_OK(status
)) {
5139 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5140 reply_botherror(req
,
5141 NT_STATUS_PATH_NOT_COVERED
,
5142 ERRSRV
, ERRbadpath
);
5145 reply_nterror(req
, status
);
5149 /* If this is a stream, check if there is a delete_pending. */
5150 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5151 && is_ntfs_stream_smb_fname(smb_fname
)) {
5152 struct smb_filename
*smb_fname_base
= NULL
;
5154 /* Create an smb_filename with stream_name == NULL. */
5156 create_synthetic_smb_fname(talloc_tos(),
5157 smb_fname
->base_name
,
5160 if (!NT_STATUS_IS_OK(status
)) {
5161 reply_nterror(req
, status
);
5165 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5166 /* Always do lstat for UNIX calls. */
5167 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5168 DEBUG(3,("call_trans2qfilepathinfo: "
5169 "SMB_VFS_LSTAT of %s failed "
5171 smb_fname_str_dbg(smb_fname_base
),
5173 TALLOC_FREE(smb_fname_base
);
5175 map_nt_error_from_unix(errno
));
5179 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5180 DEBUG(3,("call_trans2qfilepathinfo: "
5181 "fileinfo of %s failed "
5183 smb_fname_str_dbg(smb_fname_base
),
5185 TALLOC_FREE(smb_fname_base
);
5187 map_nt_error_from_unix(errno
));
5192 status
= file_name_hash(conn
,
5193 smb_fname_str_dbg(smb_fname_base
),
5195 if (!NT_STATUS_IS_OK(status
)) {
5196 TALLOC_FREE(smb_fname_base
);
5197 reply_nterror(req
, status
);
5201 fileid
= vfs_file_id_from_sbuf(conn
,
5202 &smb_fname_base
->st
);
5203 TALLOC_FREE(smb_fname_base
);
5204 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5205 if (delete_pending
) {
5206 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5211 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5212 /* Always do lstat for UNIX calls. */
5213 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5214 DEBUG(3,("call_trans2qfilepathinfo: "
5215 "SMB_VFS_LSTAT of %s failed (%s)\n",
5216 smb_fname_str_dbg(smb_fname
),
5219 map_nt_error_from_unix(errno
));
5224 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5225 DEBUG(3,("call_trans2qfilepathinfo: "
5226 "SMB_VFS_STAT of %s failed (%s)\n",
5227 smb_fname_str_dbg(smb_fname
),
5230 map_nt_error_from_unix(errno
));
5235 status
= file_name_hash(conn
,
5236 smb_fname_str_dbg(smb_fname
),
5238 if (!NT_STATUS_IS_OK(status
)) {
5239 reply_nterror(req
, status
);
5243 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5244 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5245 if (delete_pending
) {
5246 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5251 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5252 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5253 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5255 /* Pull out any data sent here before we realloc. */
5256 switch (info_level
) {
5257 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5259 /* Pull any EA list from the data portion. */
5262 if (total_data
< 4) {
5264 req
, NT_STATUS_INVALID_PARAMETER
);
5267 ea_size
= IVAL(pdata
,0);
5269 if (total_data
> 0 && ea_size
!= total_data
) {
5270 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5271 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5273 req
, NT_STATUS_INVALID_PARAMETER
);
5277 if (!lp_ea_support(SNUM(conn
))) {
5278 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5282 /* Pull out the list of names. */
5283 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5286 req
, NT_STATUS_INVALID_PARAMETER
);
5292 case SMB_QUERY_POSIX_LOCK
:
5294 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5295 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5299 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5301 req
, NT_STATUS_INVALID_PARAMETER
);
5305 /* Copy the lock range data. */
5306 lock_data
= (char *)TALLOC_MEMDUP(
5307 req
, pdata
, total_data
);
5309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5312 lock_data_count
= total_data
;
5318 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5319 if (*pparams
== NULL
) {
5320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5327 * draft-leach-cifs-v1-spec-02.txt
5328 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5331 * The requested information is placed in the Data portion of the
5332 * transaction response. For the information levels greater than 0x100,
5333 * the transaction response has 1 parameter word which should be
5334 * ignored by the client.
5336 * However Windows only follows this rule for the IS_NAME_VALID call.
5338 switch (info_level
) {
5339 case SMB_INFO_IS_NAME_VALID
:
5344 if ((info_level
& 0xFF00) == 0xFF00) {
5346 * We use levels that start with 0xFF00
5347 * internally to represent SMB2 specific levels
5349 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5353 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5355 delete_pending
, write_time_ts
,
5357 lock_data_count
, lock_data
,
5358 req
->flags2
, max_data_bytes
,
5359 ppdata
, &data_size
);
5360 if (!NT_STATUS_IS_OK(status
)) {
5361 reply_nterror(req
, status
);
5365 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5371 /****************************************************************************
5372 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5374 ****************************************************************************/
5376 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5377 connection_struct
*conn
,
5378 struct smb_request
*req
,
5379 bool overwrite_if_exists
,
5380 const struct smb_filename
*smb_fname_old
,
5381 struct smb_filename
*smb_fname_new
)
5383 NTSTATUS status
= NT_STATUS_OK
;
5385 /* source must already exist. */
5386 if (!VALID_STAT(smb_fname_old
->st
)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5390 if (VALID_STAT(smb_fname_new
->st
)) {
5391 if (overwrite_if_exists
) {
5392 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5393 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5395 status
= unlink_internals(conn
,
5397 FILE_ATTRIBUTE_NORMAL
,
5400 if (!NT_STATUS_IS_OK(status
)) {
5404 /* Disallow if newname already exists. */
5405 return NT_STATUS_OBJECT_NAME_COLLISION
;
5409 /* No links from a directory. */
5410 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5411 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5414 /* Setting a hardlink to/from a stream isn't currently supported. */
5415 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5416 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5417 return NT_STATUS_INVALID_PARAMETER
;
5420 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5421 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5423 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5424 smb_fname_new
->base_name
) != 0) {
5425 status
= map_nt_error_from_unix(errno
);
5426 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5427 nt_errstr(status
), smb_fname_old
->base_name
,
5428 smb_fname_new
->base_name
));
5433 /****************************************************************************
5434 Deal with setting the time from any of the setfilepathinfo functions.
5435 ****************************************************************************/
5437 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5439 const struct smb_filename
*smb_fname
,
5440 struct smb_file_time
*ft
,
5441 bool setting_write_time
)
5443 struct smb_filename smb_fname_base
;
5445 FILE_NOTIFY_CHANGE_LAST_ACCESS
5446 |FILE_NOTIFY_CHANGE_LAST_WRITE
5447 |FILE_NOTIFY_CHANGE_CREATION
;
5449 if (!VALID_STAT(smb_fname
->st
)) {
5450 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5453 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5454 return NT_STATUS_ACCESS_DENIED
;
5457 /* get some defaults (no modifications) if any info is zero or -1. */
5458 if (null_timespec(ft
->create_time
)) {
5459 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5462 if (null_timespec(ft
->atime
)) {
5463 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5466 if (null_timespec(ft
->mtime
)) {
5467 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5470 if (!setting_write_time
) {
5471 /* ft->mtime comes from change time, not write time. */
5472 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5475 /* Ensure the resolution is the correct for
5476 * what we can store on this filesystem. */
5478 round_timespec(conn
->ts_res
, &ft
->create_time
);
5479 round_timespec(conn
->ts_res
, &ft
->ctime
);
5480 round_timespec(conn
->ts_res
, &ft
->atime
);
5481 round_timespec(conn
->ts_res
, &ft
->mtime
);
5483 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5485 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5487 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5488 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5489 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5490 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5492 if (setting_write_time
) {
5494 * This was a Windows setfileinfo on an open file.
5495 * NT does this a lot. We also need to
5496 * set the time here, as it can be read by
5497 * FindFirst/FindNext and with the patch for bug #2045
5498 * in smbd/fileio.c it ensures that this timestamp is
5499 * kept sticky even after a write. We save the request
5500 * away and will set it on file close and after a write. JRA.
5503 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5504 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5507 if (fsp
->base_fsp
) {
5508 set_sticky_write_time_fsp(fsp
->base_fsp
,
5511 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5514 set_sticky_write_time_path(
5515 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5520 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5522 /* Always call ntimes on the base, even if a stream was passed in. */
5523 smb_fname_base
= *smb_fname
;
5524 smb_fname_base
.stream_name
= NULL
;
5526 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5527 return map_nt_error_from_unix(errno
);
5530 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5531 smb_fname
->base_name
);
5532 return NT_STATUS_OK
;
5535 /****************************************************************************
5536 Deal with setting the dosmode from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5540 const struct smb_filename
*smb_fname
,
5543 struct smb_filename
*smb_fname_base
= NULL
;
5546 if (!VALID_STAT(smb_fname
->st
)) {
5547 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5550 /* Always operate on the base_name, even if a stream was passed in. */
5551 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5552 NULL
, &smb_fname
->st
,
5554 if (!NT_STATUS_IS_OK(status
)) {
5559 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5560 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5562 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5566 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5568 /* check the mode isn't different, before changing it */
5569 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5570 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5571 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5572 (unsigned int)dosmode
));
5574 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5576 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5578 smb_fname_str_dbg(smb_fname_base
),
5580 status
= map_nt_error_from_unix(errno
);
5584 status
= NT_STATUS_OK
;
5586 TALLOC_FREE(smb_fname_base
);
5590 /****************************************************************************
5591 Deal with setting the size from any of the setfilepathinfo functions.
5592 ****************************************************************************/
5594 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5595 struct smb_request
*req
,
5597 const struct smb_filename
*smb_fname
,
5598 const SMB_STRUCT_STAT
*psbuf
,
5600 bool fail_after_createfile
)
5602 NTSTATUS status
= NT_STATUS_OK
;
5603 struct smb_filename
*smb_fname_tmp
= NULL
;
5604 files_struct
*new_fsp
= NULL
;
5606 if (!VALID_STAT(*psbuf
)) {
5607 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5610 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5611 return NT_STATUS_ACCESS_DENIED
;
5614 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5616 if (size
== get_file_size_stat(psbuf
)) {
5617 return NT_STATUS_OK
;
5620 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5621 smb_fname_str_dbg(smb_fname
), (double)size
));
5623 if (fsp
&& fsp
->fh
->fd
!= -1) {
5624 /* Handle based call. */
5625 if (vfs_set_filelen(fsp
, size
) == -1) {
5626 return map_nt_error_from_unix(errno
);
5628 trigger_write_time_update_immediate(fsp
);
5629 return NT_STATUS_OK
;
5632 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5633 if (!NT_STATUS_IS_OK(status
)) {
5637 smb_fname_tmp
->st
= *psbuf
;
5639 status
= SMB_VFS_CREATE_FILE(
5642 0, /* root_dir_fid */
5643 smb_fname_tmp
, /* fname */
5644 FILE_WRITE_DATA
, /* access_mask */
5645 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5647 FILE_OPEN
, /* create_disposition*/
5648 0, /* create_options */
5649 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5650 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5651 0, /* allocation_size */
5652 0, /* private_flags */
5655 &new_fsp
, /* result */
5658 TALLOC_FREE(smb_fname_tmp
);
5660 if (!NT_STATUS_IS_OK(status
)) {
5661 /* NB. We check for open_was_deferred in the caller. */
5665 /* See RAW-SFILEINFO-END-OF-FILE */
5666 if (fail_after_createfile
) {
5667 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5668 return NT_STATUS_INVALID_LEVEL
;
5671 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5672 status
= map_nt_error_from_unix(errno
);
5673 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5677 trigger_write_time_update_immediate(new_fsp
);
5678 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5679 return NT_STATUS_OK
;
5682 /****************************************************************************
5683 Deal with SMB_INFO_SET_EA.
5684 ****************************************************************************/
5686 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5690 const struct smb_filename
*smb_fname
)
5692 struct ea_list
*ea_list
= NULL
;
5693 TALLOC_CTX
*ctx
= NULL
;
5694 NTSTATUS status
= NT_STATUS_OK
;
5696 if (total_data
< 10) {
5698 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5699 length. They seem to have no effect. Bug #3212. JRA */
5701 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5702 /* We're done. We only get EA info in this call. */
5703 return NT_STATUS_OK
;
5706 return NT_STATUS_INVALID_PARAMETER
;
5709 if (IVAL(pdata
,0) > total_data
) {
5710 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5711 IVAL(pdata
,0), (unsigned int)total_data
));
5712 return NT_STATUS_INVALID_PARAMETER
;
5716 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5718 return NT_STATUS_INVALID_PARAMETER
;
5721 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5722 return NT_STATUS_ACCESS_DENIED
;
5725 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5730 /****************************************************************************
5731 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5732 ****************************************************************************/
5734 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5739 struct ea_list
*ea_list
= NULL
;
5743 return NT_STATUS_INVALID_HANDLE
;
5746 if (!lp_ea_support(SNUM(conn
))) {
5747 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5748 "EA's not supported.\n",
5749 (unsigned int)total_data
));
5750 return NT_STATUS_EAS_NOT_SUPPORTED
;
5753 if (total_data
< 10) {
5754 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5756 (unsigned int)total_data
));
5757 return NT_STATUS_INVALID_PARAMETER
;
5760 ea_list
= read_nttrans_ea_list(talloc_tos(),
5765 return NT_STATUS_INVALID_PARAMETER
;
5768 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5769 return NT_STATUS_ACCESS_DENIED
;
5772 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5774 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5775 smb_fname_str_dbg(fsp
->fsp_name
),
5776 nt_errstr(status
) ));
5782 /****************************************************************************
5783 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5784 ****************************************************************************/
5786 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5790 struct smb_filename
*smb_fname
)
5792 NTSTATUS status
= NT_STATUS_OK
;
5793 bool delete_on_close
;
5796 if (total_data
< 1) {
5797 return NT_STATUS_INVALID_PARAMETER
;
5801 return NT_STATUS_INVALID_HANDLE
;
5804 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5805 dosmode
= dos_mode(conn
, smb_fname
);
5807 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5808 "delete_on_close = %u\n",
5809 smb_fname_str_dbg(smb_fname
),
5810 (unsigned int)dosmode
,
5811 (unsigned int)delete_on_close
));
5813 if (delete_on_close
) {
5814 status
= can_set_delete_on_close(fsp
, dosmode
);
5815 if (!NT_STATUS_IS_OK(status
)) {
5820 /* The set is across all open files on this dev/inode pair. */
5821 if (!set_delete_on_close(fsp
, delete_on_close
,
5822 &conn
->session_info
->utok
)) {
5823 return NT_STATUS_ACCESS_DENIED
;
5825 return NT_STATUS_OK
;
5828 /****************************************************************************
5829 Deal with SMB_FILE_POSITION_INFORMATION.
5830 ****************************************************************************/
5832 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5837 uint64_t position_information
;
5839 if (total_data
< 8) {
5840 return NT_STATUS_INVALID_PARAMETER
;
5844 /* Ignore on pathname based set. */
5845 return NT_STATUS_OK
;
5848 position_information
= (uint64_t)IVAL(pdata
,0);
5849 #ifdef LARGE_SMB_OFF_T
5850 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5851 #else /* LARGE_SMB_OFF_T */
5852 if (IVAL(pdata
,4) != 0) {
5853 /* more than 32 bits? */
5854 return NT_STATUS_INVALID_PARAMETER
;
5856 #endif /* LARGE_SMB_OFF_T */
5858 DEBUG(10,("smb_file_position_information: Set file position "
5859 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5860 (double)position_information
));
5861 fsp
->fh
->position_information
= position_information
;
5862 return NT_STATUS_OK
;
5865 /****************************************************************************
5866 Deal with SMB_FILE_MODE_INFORMATION.
5867 ****************************************************************************/
5869 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5875 if (total_data
< 4) {
5876 return NT_STATUS_INVALID_PARAMETER
;
5878 mode
= IVAL(pdata
,0);
5879 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5880 return NT_STATUS_INVALID_PARAMETER
;
5882 return NT_STATUS_OK
;
5885 /****************************************************************************
5886 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5887 ****************************************************************************/
5889 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5890 struct smb_request
*req
,
5893 const struct smb_filename
*smb_fname
)
5895 char *link_target
= NULL
;
5896 const char *newname
= smb_fname
->base_name
;
5897 TALLOC_CTX
*ctx
= talloc_tos();
5899 /* Set a symbolic link. */
5900 /* Don't allow this if follow links is false. */
5902 if (total_data
== 0) {
5903 return NT_STATUS_INVALID_PARAMETER
;
5906 if (!lp_symlinks(SNUM(conn
))) {
5907 return NT_STATUS_ACCESS_DENIED
;
5910 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5911 total_data
, STR_TERMINATE
);
5914 return NT_STATUS_INVALID_PARAMETER
;
5917 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5918 newname
, link_target
));
5920 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5921 return map_nt_error_from_unix(errno
);
5924 return NT_STATUS_OK
;
5927 /****************************************************************************
5928 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5929 ****************************************************************************/
5931 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5932 struct smb_request
*req
,
5933 const char *pdata
, int total_data
,
5934 struct smb_filename
*smb_fname_new
)
5936 char *oldname
= NULL
;
5937 struct smb_filename
*smb_fname_old
= NULL
;
5938 TALLOC_CTX
*ctx
= talloc_tos();
5939 NTSTATUS status
= NT_STATUS_OK
;
5941 /* Set a hard link. */
5942 if (total_data
== 0) {
5943 return NT_STATUS_INVALID_PARAMETER
;
5946 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5947 total_data
, STR_TERMINATE
, &status
);
5948 if (!NT_STATUS_IS_OK(status
)) {
5952 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5953 smb_fname_str_dbg(smb_fname_new
), oldname
));
5955 status
= filename_convert(ctx
,
5957 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5962 if (!NT_STATUS_IS_OK(status
)) {
5966 return hardlink_internals(ctx
, conn
, req
, false,
5967 smb_fname_old
, smb_fname_new
);
5970 /****************************************************************************
5971 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5972 ****************************************************************************/
5974 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5975 struct smb_request
*req
,
5979 struct smb_filename
*smb_fname_src
)
5983 char *newname
= NULL
;
5984 struct smb_filename
*smb_fname_dst
= NULL
;
5985 NTSTATUS status
= NT_STATUS_OK
;
5986 TALLOC_CTX
*ctx
= talloc_tos();
5989 return NT_STATUS_INVALID_HANDLE
;
5992 if (total_data
< 20) {
5993 return NT_STATUS_INVALID_PARAMETER
;
5996 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5997 len
= IVAL(pdata
,16);
5999 if (len
> (total_data
- 20) || (len
== 0)) {
6000 return NT_STATUS_INVALID_PARAMETER
;
6003 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6004 &pdata
[20], len
, STR_TERMINATE
,
6006 if (!NT_STATUS_IS_OK(status
)) {
6010 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6013 status
= filename_convert(ctx
,
6015 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6020 if (!NT_STATUS_IS_OK(status
)) {
6024 if (fsp
->base_fsp
) {
6025 /* newname must be a stream name. */
6026 if (newname
[0] != ':') {
6027 return NT_STATUS_NOT_SUPPORTED
;
6030 /* Create an smb_fname to call rename_internals_fsp() with. */
6031 status
= create_synthetic_smb_fname(talloc_tos(),
6032 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6034 if (!NT_STATUS_IS_OK(status
)) {
6039 * Set the original last component, since
6040 * rename_internals_fsp() requires it.
6042 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6044 if (smb_fname_dst
->original_lcomp
== NULL
) {
6045 status
= NT_STATUS_NO_MEMORY
;
6051 DEBUG(10,("smb2_file_rename_information: "
6052 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6053 fsp
->fnum
, fsp_str_dbg(fsp
),
6054 smb_fname_str_dbg(smb_fname_dst
)));
6055 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6056 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6060 TALLOC_FREE(smb_fname_dst
);
6064 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6065 struct smb_request
*req
,
6069 struct smb_filename
*smb_fname_src
)
6073 char *newname
= NULL
;
6074 struct smb_filename
*smb_fname_dst
= NULL
;
6075 NTSTATUS status
= NT_STATUS_OK
;
6076 TALLOC_CTX
*ctx
= talloc_tos();
6079 return NT_STATUS_INVALID_HANDLE
;
6082 if (total_data
< 20) {
6083 return NT_STATUS_INVALID_PARAMETER
;
6086 overwrite
= (CVAL(pdata
,0) ? true : false);
6087 len
= IVAL(pdata
,16);
6089 if (len
> (total_data
- 20) || (len
== 0)) {
6090 return NT_STATUS_INVALID_PARAMETER
;
6093 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6094 &pdata
[20], len
, STR_TERMINATE
,
6096 if (!NT_STATUS_IS_OK(status
)) {
6100 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6103 status
= filename_convert(ctx
,
6105 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6110 if (!NT_STATUS_IS_OK(status
)) {
6114 if (fsp
->base_fsp
) {
6115 /* No stream names. */
6116 return NT_STATUS_NOT_SUPPORTED
;
6119 DEBUG(10,("smb_file_link_information: "
6120 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6121 fsp
->fnum
, fsp_str_dbg(fsp
),
6122 smb_fname_str_dbg(smb_fname_dst
)));
6123 status
= hardlink_internals(ctx
,
6130 TALLOC_FREE(smb_fname_dst
);
6134 /****************************************************************************
6135 Deal with SMB_FILE_RENAME_INFORMATION.
6136 ****************************************************************************/
6138 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6139 struct smb_request
*req
,
6143 struct smb_filename
*smb_fname_src
)
6148 char *newname
= NULL
;
6149 struct smb_filename
*smb_fname_dst
= NULL
;
6150 bool dest_has_wcard
= False
;
6151 NTSTATUS status
= NT_STATUS_OK
;
6153 TALLOC_CTX
*ctx
= talloc_tos();
6155 if (total_data
< 13) {
6156 return NT_STATUS_INVALID_PARAMETER
;
6159 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6160 root_fid
= IVAL(pdata
,4);
6161 len
= IVAL(pdata
,8);
6163 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6164 return NT_STATUS_INVALID_PARAMETER
;
6167 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6170 if (!NT_STATUS_IS_OK(status
)) {
6174 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6177 status
= resolve_dfspath_wcard(ctx
, conn
,
6178 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6183 if (!NT_STATUS_IS_OK(status
)) {
6187 /* Check the new name has no '/' characters. */
6188 if (strchr_m(newname
, '/')) {
6189 return NT_STATUS_NOT_SUPPORTED
;
6192 if (fsp
&& fsp
->base_fsp
) {
6193 /* newname must be a stream name. */
6194 if (newname
[0] != ':') {
6195 return NT_STATUS_NOT_SUPPORTED
;
6198 /* Create an smb_fname to call rename_internals_fsp() with. */
6199 status
= create_synthetic_smb_fname(talloc_tos(),
6200 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6202 if (!NT_STATUS_IS_OK(status
)) {
6207 * Set the original last component, since
6208 * rename_internals_fsp() requires it.
6210 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6212 if (smb_fname_dst
->original_lcomp
== NULL
) {
6213 status
= NT_STATUS_NO_MEMORY
;
6219 * Build up an smb_fname_dst based on the filename passed in.
6220 * We basically just strip off the last component, and put on
6221 * the newname instead.
6223 char *base_name
= NULL
;
6225 /* newname must *not* be a stream name. */
6226 if (newname
[0] == ':') {
6227 return NT_STATUS_NOT_SUPPORTED
;
6231 * Strip off the last component (filename) of the path passed
6234 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6236 return NT_STATUS_NO_MEMORY
;
6238 p
= strrchr_m(base_name
, '/');
6242 base_name
= talloc_strdup(ctx
, "");
6244 return NT_STATUS_NO_MEMORY
;
6247 /* Append the new name. */
6248 base_name
= talloc_asprintf_append(base_name
,
6252 return NT_STATUS_NO_MEMORY
;
6255 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6258 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6261 /* If an error we expect this to be
6262 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6264 if (!NT_STATUS_IS_OK(status
)) {
6265 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6269 /* Create an smb_fname to call rename_internals_fsp() */
6270 status
= create_synthetic_smb_fname(ctx
,
6274 if (!NT_STATUS_IS_OK(status
)) {
6281 DEBUG(10,("smb_file_rename_information: "
6282 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6283 fsp
->fnum
, fsp_str_dbg(fsp
),
6284 smb_fname_str_dbg(smb_fname_dst
)));
6285 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6288 DEBUG(10,("smb_file_rename_information: "
6289 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6290 smb_fname_str_dbg(smb_fname_src
),
6291 smb_fname_str_dbg(smb_fname_dst
)));
6292 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6293 smb_fname_dst
, 0, overwrite
, false,
6295 FILE_WRITE_ATTRIBUTES
);
6298 TALLOC_FREE(smb_fname_dst
);
6302 /****************************************************************************
6303 Deal with SMB_SET_POSIX_ACL.
6304 ****************************************************************************/
6306 #if defined(HAVE_POSIX_ACLS)
6307 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6311 const struct smb_filename
*smb_fname
)
6313 uint16 posix_acl_version
;
6314 uint16 num_file_acls
;
6315 uint16 num_def_acls
;
6316 bool valid_file_acls
= True
;
6317 bool valid_def_acls
= True
;
6319 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6320 return NT_STATUS_INVALID_PARAMETER
;
6322 posix_acl_version
= SVAL(pdata
,0);
6323 num_file_acls
= SVAL(pdata
,2);
6324 num_def_acls
= SVAL(pdata
,4);
6326 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6327 valid_file_acls
= False
;
6331 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6332 valid_def_acls
= False
;
6336 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6337 return NT_STATUS_INVALID_PARAMETER
;
6340 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6341 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6342 return NT_STATUS_INVALID_PARAMETER
;
6345 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6346 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6347 (unsigned int)num_file_acls
,
6348 (unsigned int)num_def_acls
));
6350 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6351 smb_fname
->base_name
, num_file_acls
,
6352 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6353 return map_nt_error_from_unix(errno
);
6356 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6357 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6358 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6359 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6360 return map_nt_error_from_unix(errno
);
6362 return NT_STATUS_OK
;
6366 /****************************************************************************
6367 Deal with SMB_SET_POSIX_LOCK.
6368 ****************************************************************************/
6370 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6371 struct smb_request
*req
,
6379 bool blocking_lock
= False
;
6380 enum brl_type lock_type
;
6382 NTSTATUS status
= NT_STATUS_OK
;
6384 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6385 return NT_STATUS_INVALID_HANDLE
;
6388 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6389 return NT_STATUS_INVALID_PARAMETER
;
6392 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6393 case POSIX_LOCK_TYPE_READ
:
6394 lock_type
= READ_LOCK
;
6396 case POSIX_LOCK_TYPE_WRITE
:
6397 /* Return the right POSIX-mappable error code for files opened read-only. */
6398 if (!fsp
->can_write
) {
6399 return NT_STATUS_INVALID_HANDLE
;
6401 lock_type
= WRITE_LOCK
;
6403 case POSIX_LOCK_TYPE_UNLOCK
:
6404 lock_type
= UNLOCK_LOCK
;
6407 return NT_STATUS_INVALID_PARAMETER
;
6410 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6411 blocking_lock
= False
;
6412 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6413 blocking_lock
= True
;
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 if (!lp_blocking_locks(SNUM(conn
))) {
6419 blocking_lock
= False
;
6422 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6423 #if defined(HAVE_LONGLONG)
6424 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6425 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6426 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6427 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6428 #else /* HAVE_LONGLONG */
6429 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6430 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6431 #endif /* HAVE_LONGLONG */
6433 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6434 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6436 (unsigned int)lock_type
,
6437 (unsigned long long)smblctx
,
6441 if (lock_type
== UNLOCK_LOCK
) {
6442 status
= do_unlock(req
->sconn
->msg_ctx
,
6449 uint64_t block_smblctx
;
6451 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6463 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6465 * A blocking lock was requested. Package up
6466 * this smb into a queued request and push it
6467 * onto the blocking lock queue.
6469 if(push_blocking_lock_request(br_lck
,
6472 -1, /* infinite timeout. */
6480 TALLOC_FREE(br_lck
);
6484 TALLOC_FREE(br_lck
);
6490 /****************************************************************************
6491 Deal with SMB_SET_FILE_BASIC_INFO.
6492 ****************************************************************************/
6494 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6498 const struct smb_filename
*smb_fname
)
6500 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6501 struct smb_file_time ft
;
6503 NTSTATUS status
= NT_STATUS_OK
;
6507 if (total_data
< 36) {
6508 return NT_STATUS_INVALID_PARAMETER
;
6511 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6512 return NT_STATUS_ACCESS_DENIED
;
6515 /* Set the attributes */
6516 dosmode
= IVAL(pdata
,32);
6517 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6518 if (!NT_STATUS_IS_OK(status
)) {
6523 ft
.create_time
= interpret_long_date(pdata
);
6526 ft
.atime
= interpret_long_date(pdata
+8);
6529 ft
.mtime
= interpret_long_date(pdata
+16);
6532 ft
.ctime
= interpret_long_date(pdata
+24);
6534 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6535 smb_fname_str_dbg(smb_fname
)));
6537 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6541 /****************************************************************************
6542 Deal with SMB_INFO_STANDARD.
6543 ****************************************************************************/
6545 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6549 const struct smb_filename
*smb_fname
)
6551 struct smb_file_time ft
;
6555 if (total_data
< 12) {
6556 return NT_STATUS_INVALID_PARAMETER
;
6559 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6560 return NT_STATUS_ACCESS_DENIED
;
6564 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6566 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6568 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6570 DEBUG(10,("smb_set_info_standard: file %s\n",
6571 smb_fname_str_dbg(smb_fname
)));
6573 return smb_set_file_time(conn
,
6580 /****************************************************************************
6581 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6582 ****************************************************************************/
6584 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6585 struct smb_request
*req
,
6589 struct smb_filename
*smb_fname
)
6591 uint64_t allocation_size
= 0;
6592 NTSTATUS status
= NT_STATUS_OK
;
6593 files_struct
*new_fsp
= NULL
;
6595 if (!VALID_STAT(smb_fname
->st
)) {
6596 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6599 if (total_data
< 8) {
6600 return NT_STATUS_INVALID_PARAMETER
;
6603 allocation_size
= (uint64_t)IVAL(pdata
,0);
6604 #ifdef LARGE_SMB_OFF_T
6605 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6606 #else /* LARGE_SMB_OFF_T */
6607 if (IVAL(pdata
,4) != 0) {
6608 /* more than 32 bits? */
6609 return NT_STATUS_INVALID_PARAMETER
;
6611 #endif /* LARGE_SMB_OFF_T */
6613 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6614 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6615 (double)allocation_size
));
6617 if (allocation_size
) {
6618 allocation_size
= smb_roundup(conn
, allocation_size
);
6621 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6622 return NT_STATUS_ACCESS_DENIED
;
6625 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6626 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6627 (double)allocation_size
));
6629 if (fsp
&& fsp
->fh
->fd
!= -1) {
6630 /* Open file handle. */
6631 /* Only change if needed. */
6632 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6633 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6634 return map_nt_error_from_unix(errno
);
6637 /* But always update the time. */
6639 * This is equivalent to a write. Ensure it's seen immediately
6640 * if there are no pending writes.
6642 trigger_write_time_update_immediate(fsp
);
6643 return NT_STATUS_OK
;
6646 /* Pathname or stat or directory file. */
6647 status
= SMB_VFS_CREATE_FILE(
6650 0, /* root_dir_fid */
6651 smb_fname
, /* fname */
6652 FILE_WRITE_DATA
, /* access_mask */
6653 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6655 FILE_OPEN
, /* create_disposition*/
6656 0, /* create_options */
6657 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6658 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6659 0, /* allocation_size */
6660 0, /* private_flags */
6663 &new_fsp
, /* result */
6666 if (!NT_STATUS_IS_OK(status
)) {
6667 /* NB. We check for open_was_deferred in the caller. */
6671 /* Only change if needed. */
6672 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6673 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6674 status
= map_nt_error_from_unix(errno
);
6675 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6680 /* Changing the allocation size should set the last mod time. */
6682 * This is equivalent to a write. Ensure it's seen immediately
6683 * if there are no pending writes.
6685 trigger_write_time_update_immediate(new_fsp
);
6687 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6688 return NT_STATUS_OK
;
6691 /****************************************************************************
6692 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6693 ****************************************************************************/
6695 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6696 struct smb_request
*req
,
6700 const struct smb_filename
*smb_fname
,
6701 bool fail_after_createfile
)
6705 if (total_data
< 8) {
6706 return NT_STATUS_INVALID_PARAMETER
;
6709 size
= IVAL(pdata
,0);
6710 #ifdef LARGE_SMB_OFF_T
6711 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6712 #else /* LARGE_SMB_OFF_T */
6713 if (IVAL(pdata
,4) != 0) {
6714 /* more than 32 bits? */
6715 return NT_STATUS_INVALID_PARAMETER
;
6717 #endif /* LARGE_SMB_OFF_T */
6718 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6719 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6722 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6723 return NT_STATUS_ACCESS_DENIED
;
6726 return smb_set_file_size(conn
, req
,
6731 fail_after_createfile
);
6734 /****************************************************************************
6735 Allow a UNIX info mknod.
6736 ****************************************************************************/
6738 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6741 const struct smb_filename
*smb_fname
)
6743 uint32 file_type
= IVAL(pdata
,56);
6744 #if defined(HAVE_MAKEDEV)
6745 uint32 dev_major
= IVAL(pdata
,60);
6746 uint32 dev_minor
= IVAL(pdata
,68);
6748 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6749 uint32 raw_unixmode
= IVAL(pdata
,84);
6753 if (total_data
< 100) {
6754 return NT_STATUS_INVALID_PARAMETER
;
6757 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6758 PERM_NEW_FILE
, &unixmode
);
6759 if (!NT_STATUS_IS_OK(status
)) {
6763 #if defined(HAVE_MAKEDEV)
6764 dev
= makedev(dev_major
, dev_minor
);
6767 switch (file_type
) {
6768 #if defined(S_IFIFO)
6769 case UNIX_TYPE_FIFO
:
6770 unixmode
|= S_IFIFO
;
6773 #if defined(S_IFSOCK)
6774 case UNIX_TYPE_SOCKET
:
6775 unixmode
|= S_IFSOCK
;
6778 #if defined(S_IFCHR)
6779 case UNIX_TYPE_CHARDEV
:
6780 unixmode
|= S_IFCHR
;
6783 #if defined(S_IFBLK)
6784 case UNIX_TYPE_BLKDEV
:
6785 unixmode
|= S_IFBLK
;
6789 return NT_STATUS_INVALID_PARAMETER
;
6792 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6793 "%.0f mode 0%o for file %s\n", (double)dev
,
6794 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6796 /* Ok - do the mknod. */
6797 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6798 return map_nt_error_from_unix(errno
);
6801 /* If any of the other "set" calls fail we
6802 * don't want to end up with a half-constructed mknod.
6805 if (lp_inherit_perms(SNUM(conn
))) {
6807 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6809 return NT_STATUS_NO_MEMORY
;
6811 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6813 TALLOC_FREE(parent
);
6816 return NT_STATUS_OK
;
6819 /****************************************************************************
6820 Deal with SMB_SET_FILE_UNIX_BASIC.
6821 ****************************************************************************/
6823 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6824 struct smb_request
*req
,
6828 const struct smb_filename
*smb_fname
)
6830 struct smb_file_time ft
;
6831 uint32 raw_unixmode
;
6834 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6835 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6836 NTSTATUS status
= NT_STATUS_OK
;
6837 bool delete_on_fail
= False
;
6838 enum perm_type ptype
;
6839 files_struct
*all_fsps
= NULL
;
6840 bool modify_mtime
= true;
6842 struct smb_filename
*smb_fname_tmp
= NULL
;
6843 SMB_STRUCT_STAT sbuf
;
6847 if (total_data
< 100) {
6848 return NT_STATUS_INVALID_PARAMETER
;
6851 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6852 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6853 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6854 #ifdef LARGE_SMB_OFF_T
6855 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6856 #else /* LARGE_SMB_OFF_T */
6857 if (IVAL(pdata
,4) != 0) {
6858 /* more than 32 bits? */
6859 return NT_STATUS_INVALID_PARAMETER
;
6861 #endif /* LARGE_SMB_OFF_T */
6864 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6865 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6866 set_owner
= (uid_t
)IVAL(pdata
,40);
6867 set_grp
= (gid_t
)IVAL(pdata
,48);
6868 raw_unixmode
= IVAL(pdata
,84);
6870 if (VALID_STAT(smb_fname
->st
)) {
6871 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6872 ptype
= PERM_EXISTING_DIR
;
6874 ptype
= PERM_EXISTING_FILE
;
6877 ptype
= PERM_NEW_FILE
;
6880 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6882 if (!NT_STATUS_IS_OK(status
)) {
6886 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6887 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6888 smb_fname_str_dbg(smb_fname
), (double)size
,
6889 (unsigned int)set_owner
, (unsigned int)set_grp
,
6890 (int)raw_unixmode
));
6892 sbuf
= smb_fname
->st
;
6894 if (!VALID_STAT(sbuf
)) {
6896 * The only valid use of this is to create character and block
6897 * devices, and named pipes. This is deprecated (IMHO) and
6898 * a new info level should be used for mknod. JRA.
6901 status
= smb_unix_mknod(conn
,
6905 if (!NT_STATUS_IS_OK(status
)) {
6909 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6911 if (!NT_STATUS_IS_OK(status
)) {
6915 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6916 status
= map_nt_error_from_unix(errno
);
6917 TALLOC_FREE(smb_fname_tmp
);
6918 SMB_VFS_UNLINK(conn
, smb_fname
);
6922 sbuf
= smb_fname_tmp
->st
;
6923 smb_fname
= smb_fname_tmp
;
6925 /* Ensure we don't try and change anything else. */
6926 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6927 size
= get_file_size_stat(&sbuf
);
6928 ft
.atime
= sbuf
.st_ex_atime
;
6929 ft
.mtime
= sbuf
.st_ex_mtime
;
6931 * We continue here as we might want to change the
6934 delete_on_fail
= True
;
6938 /* Horrible backwards compatibility hack as an old server bug
6939 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6943 size
= get_file_size_stat(&sbuf
);
6948 * Deal with the UNIX specific mode set.
6951 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6952 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6953 "setting mode 0%o for file %s\n",
6954 (unsigned int)unixmode
,
6955 smb_fname_str_dbg(smb_fname
)));
6956 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6957 return map_nt_error_from_unix(errno
);
6962 * Deal with the UNIX specific uid set.
6965 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6966 (sbuf
.st_ex_uid
!= set_owner
)) {
6969 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6970 "changing owner %u for path %s\n",
6971 (unsigned int)set_owner
,
6972 smb_fname_str_dbg(smb_fname
)));
6974 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6975 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6976 set_owner
, (gid_t
)-1);
6978 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6979 set_owner
, (gid_t
)-1);
6983 status
= map_nt_error_from_unix(errno
);
6984 if (delete_on_fail
) {
6985 SMB_VFS_UNLINK(conn
, smb_fname
);
6992 * Deal with the UNIX specific gid set.
6995 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6996 (sbuf
.st_ex_gid
!= set_grp
)) {
6997 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6998 "changing group %u for file %s\n",
6999 (unsigned int)set_owner
,
7000 smb_fname_str_dbg(smb_fname
)));
7001 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7003 status
= map_nt_error_from_unix(errno
);
7004 if (delete_on_fail
) {
7005 SMB_VFS_UNLINK(conn
, smb_fname
);
7011 /* Deal with any size changes. */
7013 status
= smb_set_file_size(conn
, req
,
7019 if (!NT_STATUS_IS_OK(status
)) {
7023 /* Deal with any time changes. */
7024 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7025 /* No change, don't cancel anything. */
7029 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7030 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7031 all_fsps
= file_find_di_next(all_fsps
)) {
7033 * We're setting the time explicitly for UNIX.
7034 * Cancel any pending changes over all handles.
7036 all_fsps
->update_write_time_on_close
= false;
7037 TALLOC_FREE(all_fsps
->update_write_time_event
);
7041 * Override the "setting_write_time"
7042 * parameter here as it almost does what
7043 * we need. Just remember if we modified
7044 * mtime and send the notify ourselves.
7046 if (null_timespec(ft
.mtime
)) {
7047 modify_mtime
= false;
7050 status
= smb_set_file_time(conn
,
7056 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7057 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7062 /****************************************************************************
7063 Deal with SMB_SET_FILE_UNIX_INFO2.
7064 ****************************************************************************/
7066 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7067 struct smb_request
*req
,
7071 const struct smb_filename
*smb_fname
)
7077 if (total_data
< 116) {
7078 return NT_STATUS_INVALID_PARAMETER
;
7081 /* Start by setting all the fields that are common between UNIX_BASIC
7084 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7086 if (!NT_STATUS_IS_OK(status
)) {
7090 smb_fflags
= IVAL(pdata
, 108);
7091 smb_fmask
= IVAL(pdata
, 112);
7093 /* NB: We should only attempt to alter the file flags if the client
7094 * sends a non-zero mask.
7096 if (smb_fmask
!= 0) {
7097 int stat_fflags
= 0;
7099 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7100 smb_fmask
, &stat_fflags
)) {
7101 /* Client asked to alter a flag we don't understand. */
7102 return NT_STATUS_INVALID_PARAMETER
;
7105 if (fsp
&& fsp
->fh
->fd
!= -1) {
7106 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7107 return NT_STATUS_NOT_SUPPORTED
;
7109 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7110 stat_fflags
) != 0) {
7111 return map_nt_error_from_unix(errno
);
7116 /* XXX: need to add support for changing the create_time here. You
7117 * can do this for paths on Darwin with setattrlist(2). The right way
7118 * to hook this up is probably by extending the VFS utimes interface.
7121 return NT_STATUS_OK
;
7124 /****************************************************************************
7125 Create a directory with POSIX semantics.
7126 ****************************************************************************/
7128 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7129 struct smb_request
*req
,
7132 struct smb_filename
*smb_fname
,
7133 int *pdata_return_size
)
7135 NTSTATUS status
= NT_STATUS_OK
;
7136 uint32 raw_unixmode
= 0;
7137 uint32 mod_unixmode
= 0;
7138 mode_t unixmode
= (mode_t
)0;
7139 files_struct
*fsp
= NULL
;
7140 uint16 info_level_return
= 0;
7142 char *pdata
= *ppdata
;
7144 if (total_data
< 18) {
7145 return NT_STATUS_INVALID_PARAMETER
;
7148 raw_unixmode
= IVAL(pdata
,8);
7149 /* Next 4 bytes are not yet defined. */
7151 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7152 PERM_NEW_DIR
, &unixmode
);
7153 if (!NT_STATUS_IS_OK(status
)) {
7157 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7159 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7160 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7162 status
= SMB_VFS_CREATE_FILE(
7165 0, /* root_dir_fid */
7166 smb_fname
, /* fname */
7167 FILE_READ_ATTRIBUTES
, /* access_mask */
7168 FILE_SHARE_NONE
, /* share_access */
7169 FILE_CREATE
, /* create_disposition*/
7170 FILE_DIRECTORY_FILE
, /* create_options */
7171 mod_unixmode
, /* file_attributes */
7172 0, /* oplock_request */
7173 0, /* allocation_size */
7174 0, /* private_flags */
7180 if (NT_STATUS_IS_OK(status
)) {
7181 close_file(req
, fsp
, NORMAL_CLOSE
);
7184 info_level_return
= SVAL(pdata
,16);
7186 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7187 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7188 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7189 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7191 *pdata_return_size
= 12;
7194 /* Realloc the data size */
7195 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7196 if (*ppdata
== NULL
) {
7197 *pdata_return_size
= 0;
7198 return NT_STATUS_NO_MEMORY
;
7202 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7203 SSVAL(pdata
,2,0); /* No fnum. */
7204 SIVAL(pdata
,4,info
); /* Was directory created. */
7206 switch (info_level_return
) {
7207 case SMB_QUERY_FILE_UNIX_BASIC
:
7208 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7209 SSVAL(pdata
,10,0); /* Padding. */
7210 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7213 case SMB_QUERY_FILE_UNIX_INFO2
:
7214 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7215 SSVAL(pdata
,10,0); /* Padding. */
7216 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7220 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7221 SSVAL(pdata
,10,0); /* Padding. */
7228 /****************************************************************************
7229 Open/Create a file with POSIX semantics.
7230 ****************************************************************************/
7232 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7233 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7235 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7236 struct smb_request
*req
,
7239 struct smb_filename
*smb_fname
,
7240 int *pdata_return_size
)
7242 bool extended_oplock_granted
= False
;
7243 char *pdata
= *ppdata
;
7245 uint32 wire_open_mode
= 0;
7246 uint32 raw_unixmode
= 0;
7247 uint32 mod_unixmode
= 0;
7248 uint32 create_disp
= 0;
7249 uint32 access_mask
= 0;
7250 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7251 NTSTATUS status
= NT_STATUS_OK
;
7252 mode_t unixmode
= (mode_t
)0;
7253 files_struct
*fsp
= NULL
;
7254 int oplock_request
= 0;
7256 uint16 info_level_return
= 0;
7258 if (total_data
< 18) {
7259 return NT_STATUS_INVALID_PARAMETER
;
7262 flags
= IVAL(pdata
,0);
7263 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7264 if (oplock_request
) {
7265 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7268 wire_open_mode
= IVAL(pdata
,4);
7270 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7271 return smb_posix_mkdir(conn
, req
,
7278 switch (wire_open_mode
& SMB_ACCMODE
) {
7280 access_mask
= SMB_O_RDONLY_MAPPING
;
7283 access_mask
= SMB_O_WRONLY_MAPPING
;
7286 access_mask
= (SMB_O_RDONLY_MAPPING
|
7287 SMB_O_WRONLY_MAPPING
);
7290 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7291 (unsigned int)wire_open_mode
));
7292 return NT_STATUS_INVALID_PARAMETER
;
7295 wire_open_mode
&= ~SMB_ACCMODE
;
7297 /* First take care of O_CREAT|O_EXCL interactions. */
7298 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7299 case (SMB_O_CREAT
| SMB_O_EXCL
):
7300 /* File exists fail. File not exist create. */
7301 create_disp
= FILE_CREATE
;
7304 /* File exists open. File not exist create. */
7305 create_disp
= FILE_OPEN_IF
;
7308 /* File exists open. File not exist fail. */
7309 create_disp
= FILE_OPEN
;
7312 /* O_EXCL on its own without O_CREAT is undefined. */
7314 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7315 (unsigned int)wire_open_mode
));
7316 return NT_STATUS_INVALID_PARAMETER
;
7319 /* Next factor in the effects of O_TRUNC. */
7320 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7322 if (wire_open_mode
& SMB_O_TRUNC
) {
7323 switch (create_disp
) {
7325 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7326 /* Leave create_disp alone as
7327 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7329 /* File exists fail. File not exist create. */
7332 /* SMB_O_CREAT | SMB_O_TRUNC */
7333 /* File exists overwrite. File not exist create. */
7334 create_disp
= FILE_OVERWRITE_IF
;
7338 /* File exists overwrite. File not exist fail. */
7339 create_disp
= FILE_OVERWRITE
;
7342 /* Cannot get here. */
7343 smb_panic("smb_posix_open: logic error");
7344 return NT_STATUS_INVALID_PARAMETER
;
7348 raw_unixmode
= IVAL(pdata
,8);
7349 /* Next 4 bytes are not yet defined. */
7351 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7352 (VALID_STAT(smb_fname
->st
) ?
7353 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7356 if (!NT_STATUS_IS_OK(status
)) {
7360 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7362 if (wire_open_mode
& SMB_O_SYNC
) {
7363 create_options
|= FILE_WRITE_THROUGH
;
7365 if (wire_open_mode
& SMB_O_APPEND
) {
7366 access_mask
|= FILE_APPEND_DATA
;
7368 if (wire_open_mode
& SMB_O_DIRECT
) {
7369 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7372 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7373 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7374 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7375 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7377 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7378 create_options
|= FILE_DIRECTORY_FILE
;
7381 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7382 smb_fname_str_dbg(smb_fname
),
7383 (unsigned int)wire_open_mode
,
7384 (unsigned int)unixmode
));
7386 status
= SMB_VFS_CREATE_FILE(
7389 0, /* root_dir_fid */
7390 smb_fname
, /* fname */
7391 access_mask
, /* access_mask */
7392 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7394 create_disp
, /* create_disposition*/
7395 create_options
, /* create_options */
7396 mod_unixmode
, /* file_attributes */
7397 oplock_request
, /* oplock_request */
7398 0, /* allocation_size */
7399 0, /* private_flags */
7405 if (!NT_STATUS_IS_OK(status
)) {
7409 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7410 extended_oplock_granted
= True
;
7413 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7414 extended_oplock_granted
= True
;
7417 info_level_return
= SVAL(pdata
,16);
7419 /* Allocate the correct return size. */
7421 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7422 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7423 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7424 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7426 *pdata_return_size
= 12;
7429 /* Realloc the data size */
7430 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7431 if (*ppdata
== NULL
) {
7432 close_file(req
, fsp
, ERROR_CLOSE
);
7433 *pdata_return_size
= 0;
7434 return NT_STATUS_NO_MEMORY
;
7438 if (extended_oplock_granted
) {
7439 if (flags
& REQUEST_BATCH_OPLOCK
) {
7440 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7442 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7444 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7445 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7447 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7450 SSVAL(pdata
,2,fsp
->fnum
);
7451 SIVAL(pdata
,4,info
); /* Was file created etc. */
7453 switch (info_level_return
) {
7454 case SMB_QUERY_FILE_UNIX_BASIC
:
7455 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7456 SSVAL(pdata
,10,0); /* padding. */
7457 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7460 case SMB_QUERY_FILE_UNIX_INFO2
:
7461 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7462 SSVAL(pdata
,10,0); /* padding. */
7463 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7467 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7468 SSVAL(pdata
,10,0); /* padding. */
7471 return NT_STATUS_OK
;
7474 /****************************************************************************
7475 Delete a file with POSIX semantics.
7476 ****************************************************************************/
7478 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7479 struct smb_request
*req
,
7482 struct smb_filename
*smb_fname
)
7484 NTSTATUS status
= NT_STATUS_OK
;
7485 files_struct
*fsp
= NULL
;
7489 int create_options
= 0;
7491 struct share_mode_lock
*lck
= NULL
;
7493 if (total_data
< 2) {
7494 return NT_STATUS_INVALID_PARAMETER
;
7497 flags
= SVAL(pdata
,0);
7499 if (!VALID_STAT(smb_fname
->st
)) {
7500 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7503 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7504 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7505 return NT_STATUS_NOT_A_DIRECTORY
;
7508 DEBUG(10,("smb_posix_unlink: %s %s\n",
7509 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7510 smb_fname_str_dbg(smb_fname
)));
7512 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7513 create_options
|= FILE_DIRECTORY_FILE
;
7516 status
= SMB_VFS_CREATE_FILE(
7519 0, /* root_dir_fid */
7520 smb_fname
, /* fname */
7521 DELETE_ACCESS
, /* access_mask */
7522 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7524 FILE_OPEN
, /* create_disposition*/
7525 create_options
, /* create_options */
7526 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7527 0, /* oplock_request */
7528 0, /* allocation_size */
7529 0, /* private_flags */
7535 if (!NT_STATUS_IS_OK(status
)) {
7540 * Don't lie to client. If we can't really delete due to
7541 * non-POSIX opens return SHARING_VIOLATION.
7544 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7547 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7548 "lock for file %s\n", fsp_str_dbg(fsp
)));
7549 close_file(req
, fsp
, NORMAL_CLOSE
);
7550 return NT_STATUS_INVALID_PARAMETER
;
7554 * See if others still have the file open. If this is the case, then
7555 * don't delete. If all opens are POSIX delete we can set the delete
7556 * on close disposition.
7558 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7559 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7560 if (is_valid_share_mode_entry(e
)) {
7561 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7564 /* Fail with sharing violation. */
7565 close_file(req
, fsp
, NORMAL_CLOSE
);
7567 return NT_STATUS_SHARING_VIOLATION
;
7572 * Set the delete on close.
7574 status
= smb_set_file_disposition_info(conn
,
7580 if (!NT_STATUS_IS_OK(status
)) {
7581 close_file(req
, fsp
, NORMAL_CLOSE
);
7586 return close_file(req
, fsp
, NORMAL_CLOSE
);
7589 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7590 struct smb_request
*req
,
7591 TALLOC_CTX
*mem_ctx
,
7592 uint16_t info_level
,
7594 struct smb_filename
*smb_fname
,
7595 char **ppdata
, int total_data
,
7598 char *pdata
= *ppdata
;
7599 NTSTATUS status
= NT_STATUS_OK
;
7600 int data_return_size
= 0;
7604 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7605 return NT_STATUS_INVALID_LEVEL
;
7608 if (!CAN_WRITE(conn
)) {
7609 /* Allow POSIX opens. The open path will deny
7610 * any non-readonly opens. */
7611 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7612 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7616 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7617 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7618 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7620 switch (info_level
) {
7622 case SMB_INFO_STANDARD
:
7624 status
= smb_set_info_standard(conn
,
7632 case SMB_INFO_SET_EA
:
7634 status
= smb_info_set_ea(conn
,
7642 case SMB_SET_FILE_BASIC_INFO
:
7643 case SMB_FILE_BASIC_INFORMATION
:
7645 status
= smb_set_file_basic_info(conn
,
7653 case SMB_FILE_ALLOCATION_INFORMATION
:
7654 case SMB_SET_FILE_ALLOCATION_INFO
:
7656 status
= smb_set_file_allocation_info(conn
, req
,
7664 case SMB_FILE_END_OF_FILE_INFORMATION
:
7665 case SMB_SET_FILE_END_OF_FILE_INFO
:
7668 * XP/Win7 both fail after the createfile with
7669 * SMB_SET_FILE_END_OF_FILE_INFO but not
7670 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7671 * The level is known here, so pass it down
7675 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7677 status
= smb_set_file_end_of_file_info(conn
, req
,
7686 case SMB_FILE_DISPOSITION_INFORMATION
:
7687 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7690 /* JRA - We used to just ignore this on a path ?
7691 * Shouldn't this be invalid level on a pathname
7694 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7695 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7698 status
= smb_set_file_disposition_info(conn
,
7706 case SMB_FILE_POSITION_INFORMATION
:
7708 status
= smb_file_position_information(conn
,
7715 case SMB_FILE_FULL_EA_INFORMATION
:
7717 status
= smb_set_file_full_ea_info(conn
,
7724 /* From tridge Samba4 :
7725 * MODE_INFORMATION in setfileinfo (I have no
7726 * idea what "mode information" on a file is - it takes a value of 0,
7727 * 2, 4 or 6. What could it be?).
7730 case SMB_FILE_MODE_INFORMATION
:
7732 status
= smb_file_mode_information(conn
,
7739 * CIFS UNIX extensions.
7742 case SMB_SET_FILE_UNIX_BASIC
:
7744 status
= smb_set_file_unix_basic(conn
, req
,
7752 case SMB_SET_FILE_UNIX_INFO2
:
7754 status
= smb_set_file_unix_info2(conn
, req
,
7762 case SMB_SET_FILE_UNIX_LINK
:
7765 /* We must have a pathname for this. */
7766 return NT_STATUS_INVALID_LEVEL
;
7768 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7769 total_data
, smb_fname
);
7773 case SMB_SET_FILE_UNIX_HLINK
:
7776 /* We must have a pathname for this. */
7777 return NT_STATUS_INVALID_LEVEL
;
7779 status
= smb_set_file_unix_hlink(conn
, req
,
7785 case SMB_FILE_RENAME_INFORMATION
:
7787 status
= smb_file_rename_information(conn
, req
,
7793 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7795 /* SMB2 rename information. */
7796 status
= smb2_file_rename_information(conn
, req
,
7802 case SMB_FILE_LINK_INFORMATION
:
7804 status
= smb_file_link_information(conn
, req
,
7810 #if defined(HAVE_POSIX_ACLS)
7811 case SMB_SET_POSIX_ACL
:
7813 status
= smb_set_posix_acl(conn
,
7822 case SMB_SET_POSIX_LOCK
:
7825 return NT_STATUS_INVALID_LEVEL
;
7827 status
= smb_set_posix_lock(conn
, req
,
7828 pdata
, total_data
, fsp
);
7832 case SMB_POSIX_PATH_OPEN
:
7835 /* We must have a pathname for this. */
7836 return NT_STATUS_INVALID_LEVEL
;
7839 status
= smb_posix_open(conn
, req
,
7847 case SMB_POSIX_PATH_UNLINK
:
7850 /* We must have a pathname for this. */
7851 return NT_STATUS_INVALID_LEVEL
;
7854 status
= smb_posix_unlink(conn
, req
,
7862 return NT_STATUS_INVALID_LEVEL
;
7865 if (!NT_STATUS_IS_OK(status
)) {
7869 *ret_data_size
= data_return_size
;
7870 return NT_STATUS_OK
;
7873 /****************************************************************************
7874 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7875 ****************************************************************************/
7877 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7878 struct smb_request
*req
,
7879 unsigned int tran_call
,
7880 char **pparams
, int total_params
,
7881 char **ppdata
, int total_data
,
7882 unsigned int max_data_bytes
)
7884 char *params
= *pparams
;
7885 char *pdata
= *ppdata
;
7887 struct smb_filename
*smb_fname
= NULL
;
7888 files_struct
*fsp
= NULL
;
7889 NTSTATUS status
= NT_STATUS_OK
;
7890 int data_return_size
= 0;
7893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7897 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7898 if (total_params
< 4) {
7899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7903 fsp
= file_fsp(req
, SVAL(params
,0));
7904 /* Basic check for non-null fsp. */
7905 if (!check_fsp_open(conn
, req
, fsp
)) {
7908 info_level
= SVAL(params
,2);
7910 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7912 if (!NT_STATUS_IS_OK(status
)) {
7913 reply_nterror(req
, status
);
7917 if(fsp
->fh
->fd
== -1) {
7919 * This is actually a SETFILEINFO on a directory
7920 * handle (returned from an NT SMB). NT5.0 seems
7921 * to do this call. JRA.
7923 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7924 /* Always do lstat for UNIX calls. */
7925 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7926 DEBUG(3,("call_trans2setfilepathinfo: "
7927 "SMB_VFS_LSTAT of %s failed "
7929 smb_fname_str_dbg(smb_fname
),
7931 reply_nterror(req
, map_nt_error_from_unix(errno
));
7935 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7936 DEBUG(3,("call_trans2setfilepathinfo: "
7937 "fileinfo of %s failed (%s)\n",
7938 smb_fname_str_dbg(smb_fname
),
7940 reply_nterror(req
, map_nt_error_from_unix(errno
));
7944 } else if (fsp
->print_file
) {
7946 * Doing a DELETE_ON_CLOSE should cancel a print job.
7948 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7949 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7951 DEBUG(3,("call_trans2setfilepathinfo: "
7952 "Cancelling print job (%s)\n",
7956 send_trans2_replies(conn
, req
, params
, 2,
7962 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7967 * Original code - this is an open file.
7969 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7970 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7971 "of fnum %d failed (%s)\n", fsp
->fnum
,
7973 reply_nterror(req
, map_nt_error_from_unix(errno
));
7981 if (total_params
< 7) {
7982 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7986 info_level
= SVAL(params
,0);
7987 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7988 total_params
- 6, STR_TERMINATE
,
7990 if (!NT_STATUS_IS_OK(status
)) {
7991 reply_nterror(req
, status
);
7995 status
= filename_convert(req
, conn
,
7996 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8001 if (!NT_STATUS_IS_OK(status
)) {
8002 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8003 reply_botherror(req
,
8004 NT_STATUS_PATH_NOT_COVERED
,
8005 ERRSRV
, ERRbadpath
);
8008 reply_nterror(req
, status
);
8012 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8014 * For CIFS UNIX extensions the target name may not exist.
8017 /* Always do lstat for UNIX calls. */
8018 SMB_VFS_LSTAT(conn
, smb_fname
);
8020 } else if (!VALID_STAT(smb_fname
->st
) &&
8021 SMB_VFS_STAT(conn
, smb_fname
)) {
8022 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8024 smb_fname_str_dbg(smb_fname
),
8026 reply_nterror(req
, map_nt_error_from_unix(errno
));
8031 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8032 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8033 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8035 /* Realloc the parameter size */
8036 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8037 if (*pparams
== NULL
) {
8038 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8045 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8051 if (!NT_STATUS_IS_OK(status
)) {
8052 if (open_was_deferred(req
->mid
)) {
8053 /* We have re-scheduled this call. */
8056 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8057 /* We have re-scheduled this call. */
8060 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8061 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8062 ERRSRV
, ERRbadpath
);
8065 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8066 reply_openerror(req
, status
);
8070 reply_nterror(req
, status
);
8074 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8080 /****************************************************************************
8081 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8082 ****************************************************************************/
8084 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8085 char **pparams
, int total_params
,
8086 char **ppdata
, int total_data
,
8087 unsigned int max_data_bytes
)
8089 struct smb_filename
*smb_dname
= NULL
;
8090 char *params
= *pparams
;
8091 char *pdata
= *ppdata
;
8092 char *directory
= NULL
;
8093 NTSTATUS status
= NT_STATUS_OK
;
8094 struct ea_list
*ea_list
= NULL
;
8095 TALLOC_CTX
*ctx
= talloc_tos();
8097 if (!CAN_WRITE(conn
)) {
8098 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8102 if (total_params
< 5) {
8103 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8107 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8108 total_params
- 4, STR_TERMINATE
,
8110 if (!NT_STATUS_IS_OK(status
)) {
8111 reply_nterror(req
, status
);
8115 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8117 status
= filename_convert(ctx
,
8119 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8125 if (!NT_STATUS_IS_OK(status
)) {
8126 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8127 reply_botherror(req
,
8128 NT_STATUS_PATH_NOT_COVERED
,
8129 ERRSRV
, ERRbadpath
);
8132 reply_nterror(req
, status
);
8137 * OS/2 workplace shell seems to send SET_EA requests of "null"
8138 * length (4 bytes containing IVAL 4).
8139 * They seem to have no effect. Bug #3212. JRA.
8142 if (total_data
&& (total_data
!= 4)) {
8143 /* Any data in this call is an EA list. */
8144 if (total_data
< 10) {
8145 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8149 if (IVAL(pdata
,0) > total_data
) {
8150 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8151 IVAL(pdata
,0), (unsigned int)total_data
));
8152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8156 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8159 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8163 if (!lp_ea_support(SNUM(conn
))) {
8164 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8168 /* If total_data == 4 Windows doesn't care what values
8169 * are placed in that field, it just ignores them.
8170 * The System i QNTC IBM SMB client puts bad values here,
8171 * so ignore them. */
8173 status
= create_directory(conn
, req
, smb_dname
);
8175 if (!NT_STATUS_IS_OK(status
)) {
8176 reply_nterror(req
, status
);
8180 /* Try and set any given EA. */
8182 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8183 if (!NT_STATUS_IS_OK(status
)) {
8184 reply_nterror(req
, status
);
8189 /* Realloc the parameter and data sizes */
8190 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8191 if(*pparams
== NULL
) {
8192 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8199 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8202 TALLOC_FREE(smb_dname
);
8206 /****************************************************************************
8207 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8208 We don't actually do this - we just send a null response.
8209 ****************************************************************************/
8211 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8212 struct smb_request
*req
,
8213 char **pparams
, int total_params
,
8214 char **ppdata
, int total_data
,
8215 unsigned int max_data_bytes
)
8217 char *params
= *pparams
;
8220 if (total_params
< 6) {
8221 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8225 info_level
= SVAL(params
,4);
8226 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8228 switch (info_level
) {
8233 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8237 /* Realloc the parameter and data sizes */
8238 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8239 if (*pparams
== NULL
) {
8240 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8245 SSVAL(params
,0,fnf_handle
);
8246 SSVAL(params
,2,0); /* No changes */
8247 SSVAL(params
,4,0); /* No EA errors */
8254 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8259 /****************************************************************************
8260 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8261 changes). Currently this does nothing.
8262 ****************************************************************************/
8264 static void call_trans2findnotifynext(connection_struct
*conn
,
8265 struct smb_request
*req
,
8266 char **pparams
, int total_params
,
8267 char **ppdata
, int total_data
,
8268 unsigned int max_data_bytes
)
8270 char *params
= *pparams
;
8272 DEBUG(3,("call_trans2findnotifynext\n"));
8274 /* Realloc the parameter and data sizes */
8275 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8276 if (*pparams
== NULL
) {
8277 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8282 SSVAL(params
,0,0); /* No changes */
8283 SSVAL(params
,2,0); /* No EA errors */
8285 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8290 /****************************************************************************
8291 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8292 ****************************************************************************/
8294 static void call_trans2getdfsreferral(connection_struct
*conn
,
8295 struct smb_request
*req
,
8296 char **pparams
, int total_params
,
8297 char **ppdata
, int total_data
,
8298 unsigned int max_data_bytes
)
8300 char *params
= *pparams
;
8301 char *pathname
= NULL
;
8303 int max_referral_level
;
8304 NTSTATUS status
= NT_STATUS_OK
;
8305 TALLOC_CTX
*ctx
= talloc_tos();
8307 DEBUG(10,("call_trans2getdfsreferral\n"));
8309 if (total_params
< 3) {
8310 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8314 max_referral_level
= SVAL(params
,0);
8316 if(!lp_host_msdfs()) {
8317 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8321 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8322 total_params
- 2, STR_TERMINATE
);
8324 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8327 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8328 ppdata
,&status
)) < 0) {
8329 reply_nterror(req
, status
);
8333 SSVAL(req
->inbuf
, smb_flg2
,
8334 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8335 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8340 #define LMCAT_SPL 0x53
8341 #define LMFUNC_GETJOBID 0x60
8343 /****************************************************************************
8344 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8345 ****************************************************************************/
8347 static void call_trans2ioctl(connection_struct
*conn
,
8348 struct smb_request
*req
,
8349 char **pparams
, int total_params
,
8350 char **ppdata
, int total_data
,
8351 unsigned int max_data_bytes
)
8353 char *pdata
= *ppdata
;
8354 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8356 /* check for an invalid fid before proceeding */
8359 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8363 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8364 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8365 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8366 if (*ppdata
== NULL
) {
8367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8372 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8373 CAN ACCEPT THIS IN UNICODE. JRA. */
8376 if (fsp
->print_file
) {
8377 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8381 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8382 global_myname(), 15,
8383 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8384 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8385 lp_servicename(SNUM(conn
)), 13,
8386 STR_ASCII
|STR_TERMINATE
); /* Service name */
8387 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8392 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8393 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8396 /****************************************************************************
8397 Reply to a SMBfindclose (stop trans2 directory search).
8398 ****************************************************************************/
8400 void reply_findclose(struct smb_request
*req
)
8403 struct smbd_server_connection
*sconn
= req
->sconn
;
8405 START_PROFILE(SMBfindclose
);
8408 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8409 END_PROFILE(SMBfindclose
);
8413 dptr_num
= SVALS(req
->vwv
+0, 0);
8415 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8417 dptr_close(sconn
, &dptr_num
);
8419 reply_outbuf(req
, 0, 0);
8421 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8423 END_PROFILE(SMBfindclose
);
8427 /****************************************************************************
8428 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8429 ****************************************************************************/
8431 void reply_findnclose(struct smb_request
*req
)
8435 START_PROFILE(SMBfindnclose
);
8438 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8439 END_PROFILE(SMBfindnclose
);
8443 dptr_num
= SVAL(req
->vwv
+0, 0);
8445 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8447 /* We never give out valid handles for a
8448 findnotifyfirst - so any dptr_num is ok here.
8451 reply_outbuf(req
, 0, 0);
8453 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8455 END_PROFILE(SMBfindnclose
);
8459 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8460 struct trans_state
*state
)
8462 if (get_Protocol() >= PROTOCOL_NT1
) {
8463 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8464 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8467 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8468 if (state
->call
!= TRANSACT2_QFSINFO
&&
8469 state
->call
!= TRANSACT2_SETFSINFO
) {
8470 DEBUG(0,("handle_trans2: encryption required "
8472 (unsigned int)state
->call
));
8473 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8478 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8480 /* Now we must call the relevant TRANS2 function */
8481 switch(state
->call
) {
8482 case TRANSACT2_OPEN
:
8484 START_PROFILE(Trans2_open
);
8485 call_trans2open(conn
, req
,
8486 &state
->param
, state
->total_param
,
8487 &state
->data
, state
->total_data
,
8488 state
->max_data_return
);
8489 END_PROFILE(Trans2_open
);
8493 case TRANSACT2_FINDFIRST
:
8495 START_PROFILE(Trans2_findfirst
);
8496 call_trans2findfirst(conn
, req
,
8497 &state
->param
, state
->total_param
,
8498 &state
->data
, state
->total_data
,
8499 state
->max_data_return
);
8500 END_PROFILE(Trans2_findfirst
);
8504 case TRANSACT2_FINDNEXT
:
8506 START_PROFILE(Trans2_findnext
);
8507 call_trans2findnext(conn
, req
,
8508 &state
->param
, state
->total_param
,
8509 &state
->data
, state
->total_data
,
8510 state
->max_data_return
);
8511 END_PROFILE(Trans2_findnext
);
8515 case TRANSACT2_QFSINFO
:
8517 START_PROFILE(Trans2_qfsinfo
);
8518 call_trans2qfsinfo(conn
, req
,
8519 &state
->param
, state
->total_param
,
8520 &state
->data
, state
->total_data
,
8521 state
->max_data_return
);
8522 END_PROFILE(Trans2_qfsinfo
);
8526 case TRANSACT2_SETFSINFO
:
8528 START_PROFILE(Trans2_setfsinfo
);
8529 call_trans2setfsinfo(conn
, req
,
8530 &state
->param
, state
->total_param
,
8531 &state
->data
, state
->total_data
,
8532 state
->max_data_return
);
8533 END_PROFILE(Trans2_setfsinfo
);
8537 case TRANSACT2_QPATHINFO
:
8538 case TRANSACT2_QFILEINFO
:
8540 START_PROFILE(Trans2_qpathinfo
);
8541 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8542 &state
->param
, state
->total_param
,
8543 &state
->data
, state
->total_data
,
8544 state
->max_data_return
);
8545 END_PROFILE(Trans2_qpathinfo
);
8549 case TRANSACT2_SETPATHINFO
:
8550 case TRANSACT2_SETFILEINFO
:
8552 START_PROFILE(Trans2_setpathinfo
);
8553 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8554 &state
->param
, state
->total_param
,
8555 &state
->data
, state
->total_data
,
8556 state
->max_data_return
);
8557 END_PROFILE(Trans2_setpathinfo
);
8561 case TRANSACT2_FINDNOTIFYFIRST
:
8563 START_PROFILE(Trans2_findnotifyfirst
);
8564 call_trans2findnotifyfirst(conn
, req
,
8565 &state
->param
, state
->total_param
,
8566 &state
->data
, state
->total_data
,
8567 state
->max_data_return
);
8568 END_PROFILE(Trans2_findnotifyfirst
);
8572 case TRANSACT2_FINDNOTIFYNEXT
:
8574 START_PROFILE(Trans2_findnotifynext
);
8575 call_trans2findnotifynext(conn
, req
,
8576 &state
->param
, state
->total_param
,
8577 &state
->data
, state
->total_data
,
8578 state
->max_data_return
);
8579 END_PROFILE(Trans2_findnotifynext
);
8583 case TRANSACT2_MKDIR
:
8585 START_PROFILE(Trans2_mkdir
);
8586 call_trans2mkdir(conn
, req
,
8587 &state
->param
, state
->total_param
,
8588 &state
->data
, state
->total_data
,
8589 state
->max_data_return
);
8590 END_PROFILE(Trans2_mkdir
);
8594 case TRANSACT2_GET_DFS_REFERRAL
:
8596 START_PROFILE(Trans2_get_dfs_referral
);
8597 call_trans2getdfsreferral(conn
, req
,
8598 &state
->param
, state
->total_param
,
8599 &state
->data
, state
->total_data
,
8600 state
->max_data_return
);
8601 END_PROFILE(Trans2_get_dfs_referral
);
8605 case TRANSACT2_IOCTL
:
8607 START_PROFILE(Trans2_ioctl
);
8608 call_trans2ioctl(conn
, req
,
8609 &state
->param
, state
->total_param
,
8610 &state
->data
, state
->total_data
,
8611 state
->max_data_return
);
8612 END_PROFILE(Trans2_ioctl
);
8617 /* Error in request */
8618 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8619 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8623 /****************************************************************************
8624 Reply to a SMBtrans2.
8625 ****************************************************************************/
8627 void reply_trans2(struct smb_request
*req
)
8629 connection_struct
*conn
= req
->conn
;
8634 unsigned int tran_call
;
8635 struct trans_state
*state
;
8638 START_PROFILE(SMBtrans2
);
8640 if (req
->wct
< 14) {
8641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8642 END_PROFILE(SMBtrans2
);
8646 dsoff
= SVAL(req
->vwv
+12, 0);
8647 dscnt
= SVAL(req
->vwv
+11, 0);
8648 psoff
= SVAL(req
->vwv
+10, 0);
8649 pscnt
= SVAL(req
->vwv
+9, 0);
8650 tran_call
= SVAL(req
->vwv
+14, 0);
8652 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8653 if (!NT_STATUS_IS_OK(result
)) {
8654 DEBUG(2, ("Got invalid trans2 request: %s\n",
8655 nt_errstr(result
)));
8656 reply_nterror(req
, result
);
8657 END_PROFILE(SMBtrans2
);
8662 switch (tran_call
) {
8663 /* List the allowed trans2 calls on IPC$ */
8664 case TRANSACT2_OPEN
:
8665 case TRANSACT2_GET_DFS_REFERRAL
:
8666 case TRANSACT2_QFILEINFO
:
8667 case TRANSACT2_QFSINFO
:
8668 case TRANSACT2_SETFSINFO
:
8671 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8672 END_PROFILE(SMBtrans2
);
8677 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8678 DEBUG(0, ("talloc failed\n"));
8679 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8680 END_PROFILE(SMBtrans2
);
8684 state
->cmd
= SMBtrans2
;
8686 state
->mid
= req
->mid
;
8687 state
->vuid
= req
->vuid
;
8688 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8689 state
->setup
= NULL
;
8690 state
->total_param
= SVAL(req
->vwv
+0, 0);
8691 state
->param
= NULL
;
8692 state
->total_data
= SVAL(req
->vwv
+1, 0);
8694 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8695 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8696 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8697 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8698 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8700 state
->call
= tran_call
;
8702 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8703 is so as a sanity check */
8704 if (state
->setup_count
!= 1) {
8706 * Need to have rc=0 for ioctl to get job id for OS/2.
8707 * Network printing will fail if function is not successful.
8708 * Similar function in reply.c will be used if protocol
8709 * is LANMAN1.0 instead of LM1.2X002.
8710 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8711 * outbuf doesn't have to be set(only job id is used).
8713 if ( (state
->setup_count
== 4)
8714 && (tran_call
== TRANSACT2_IOCTL
)
8715 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8716 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8717 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8719 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8720 DEBUG(2,("Transaction is %d\n",tran_call
));
8722 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8723 END_PROFILE(SMBtrans2
);
8728 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8731 if (state
->total_data
) {
8733 if (trans_oob(state
->total_data
, 0, dscnt
)
8734 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8738 /* Can't use talloc here, the core routines do realloc on the
8739 * params and data. */
8740 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8741 if (state
->data
== NULL
) {
8742 DEBUG(0,("reply_trans2: data malloc fail for %u "
8743 "bytes !\n", (unsigned int)state
->total_data
));
8745 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8746 END_PROFILE(SMBtrans2
);
8750 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8753 if (state
->total_param
) {
8755 if (trans_oob(state
->total_param
, 0, pscnt
)
8756 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8760 /* Can't use talloc here, the core routines do realloc on the
8761 * params and data. */
8762 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8763 if (state
->param
== NULL
) {
8764 DEBUG(0,("reply_trans: param malloc fail for %u "
8765 "bytes !\n", (unsigned int)state
->total_param
));
8766 SAFE_FREE(state
->data
);
8768 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8769 END_PROFILE(SMBtrans2
);
8773 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8776 state
->received_data
= dscnt
;
8777 state
->received_param
= pscnt
;
8779 if ((state
->received_param
== state
->total_param
) &&
8780 (state
->received_data
== state
->total_data
)) {
8782 handle_trans2(conn
, req
, state
);
8784 SAFE_FREE(state
->data
);
8785 SAFE_FREE(state
->param
);
8787 END_PROFILE(SMBtrans2
);
8791 DLIST_ADD(conn
->pending_trans
, state
);
8793 /* We need to send an interim response then receive the rest
8794 of the parameter/data bytes */
8795 reply_outbuf(req
, 0, 0);
8796 show_msg((char *)req
->outbuf
);
8797 END_PROFILE(SMBtrans2
);
8802 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8803 SAFE_FREE(state
->data
);
8804 SAFE_FREE(state
->param
);
8806 END_PROFILE(SMBtrans2
);
8807 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8811 /****************************************************************************
8812 Reply to a SMBtranss2
8813 ****************************************************************************/
8815 void reply_transs2(struct smb_request
*req
)
8817 connection_struct
*conn
= req
->conn
;
8818 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8819 struct trans_state
*state
;
8821 START_PROFILE(SMBtranss2
);
8823 show_msg((char *)req
->inbuf
);
8826 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8827 END_PROFILE(SMBtranss2
);
8831 for (state
= conn
->pending_trans
; state
!= NULL
;
8832 state
= state
->next
) {
8833 if (state
->mid
== req
->mid
) {
8838 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8839 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8840 END_PROFILE(SMBtranss2
);
8844 /* Revise state->total_param and state->total_data in case they have
8845 changed downwards */
8847 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8848 state
->total_param
= SVAL(req
->vwv
+0, 0);
8849 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8850 state
->total_data
= SVAL(req
->vwv
+1, 0);
8852 pcnt
= SVAL(req
->vwv
+2, 0);
8853 poff
= SVAL(req
->vwv
+3, 0);
8854 pdisp
= SVAL(req
->vwv
+4, 0);
8856 dcnt
= SVAL(req
->vwv
+5, 0);
8857 doff
= SVAL(req
->vwv
+6, 0);
8858 ddisp
= SVAL(req
->vwv
+7, 0);
8860 state
->received_param
+= pcnt
;
8861 state
->received_data
+= dcnt
;
8863 if ((state
->received_data
> state
->total_data
) ||
8864 (state
->received_param
> state
->total_param
))
8868 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8869 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8872 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8876 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8877 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8880 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8883 if ((state
->received_param
< state
->total_param
) ||
8884 (state
->received_data
< state
->total_data
)) {
8885 END_PROFILE(SMBtranss2
);
8889 handle_trans2(conn
, req
, state
);
8891 DLIST_REMOVE(conn
->pending_trans
, state
);
8892 SAFE_FREE(state
->data
);
8893 SAFE_FREE(state
->param
);
8896 END_PROFILE(SMBtranss2
);
8901 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8902 DLIST_REMOVE(conn
->pending_trans
, state
);
8903 SAFE_FREE(state
->data
);
8904 SAFE_FREE(state
->param
);
8906 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8907 END_PROFILE(SMBtranss2
);