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
, deny_mode
, open_ofun
,
1087 &access_mask
, &share_mode
,
1088 &create_disposition
,
1091 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1095 /* Any data in this call is an EA list. */
1096 if (total_data
&& (total_data
!= 4)) {
1097 if (total_data
< 10) {
1098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1102 if (IVAL(pdata
,0) > total_data
) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata
,0), (unsigned int)total_data
));
1105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1109 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1116 if (!lp_ea_support(SNUM(conn
))) {
1117 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1122 status
= SMB_VFS_CREATE_FILE(
1125 0, /* root_dir_fid */
1126 smb_fname
, /* fname */
1127 access_mask
, /* access_mask */
1128 share_mode
, /* share_access */
1129 create_disposition
, /* create_disposition*/
1130 create_options
, /* create_options */
1131 open_attr
, /* file_attributes */
1132 oplock_request
, /* oplock_request */
1133 open_size
, /* allocation_size */
1136 ea_list
, /* ea_list */
1138 &smb_action
); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status
)) {
1141 if (open_was_deferred(req
->mid
)) {
1142 /* We have re-scheduled this call. */
1145 reply_openerror(req
, status
);
1149 size
= get_file_size_stat(&smb_fname
->st
);
1150 fattr
= dos_mode(conn
, smb_fname
);
1151 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1152 inode
= smb_fname
->st
.st_ex_ino
;
1153 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1154 close_file(req
, fsp
, ERROR_CLOSE
);
1155 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1161 if(*pparams
== NULL
) {
1162 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1167 SSVAL(params
,0,fsp
->fnum
);
1168 SSVAL(params
,2,fattr
);
1169 srv_put_dos_date2(params
,4, mtime
);
1170 SIVAL(params
,8, (uint32
)size
);
1171 SSVAL(params
,12,deny_mode
);
1172 SSVAL(params
,14,0); /* open_type - file or directory. */
1173 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1176 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1179 SSVAL(params
,18,smb_action
);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params
,20,inode
);
1185 SSVAL(params
,24,0); /* Padding. */
1187 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1188 fsp
->fsp_name
->base_name
);
1189 SIVAL(params
, 26, ea_size
);
1191 SIVAL(params
, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1197 TALLOC_FREE(smb_fname
);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild
,
1208 bool case_sensitive
,
1212 if (mask
[0] == '.' && mask
[1] == 0) {
1220 if (case_sensitive
) {
1221 return strcmp(str
,mask
)==0;
1223 return StrCaseCmp(str
,mask
) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32
unix_filetype(mode_t mode
)
1234 return UNIX_TYPE_FILE
;
1235 else if(S_ISDIR(mode
))
1236 return UNIX_TYPE_DIR
;
1238 else if(S_ISLNK(mode
))
1239 return UNIX_TYPE_SYMLINK
;
1242 else if(S_ISCHR(mode
))
1243 return UNIX_TYPE_CHARDEV
;
1246 else if(S_ISBLK(mode
))
1247 return UNIX_TYPE_BLKDEV
;
1250 else if(S_ISFIFO(mode
))
1251 return UNIX_TYPE_FIFO
;
1254 else if(S_ISSOCK(mode
))
1255 return UNIX_TYPE_SOCKET
;
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1259 return UNIX_TYPE_UNKNOWN
;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1268 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1269 const SMB_STRUCT_STAT
*psbuf
,
1271 enum perm_type ptype
,
1276 if (perms
== SMB_MODE_NO_CHANGE
) {
1277 if (!VALID_STAT(*psbuf
)) {
1278 return NT_STATUS_INVALID_PARAMETER
;
1280 *ret_perms
= psbuf
->st_ex_mode
;
1281 return NT_STATUS_OK
;
1285 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1286 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1287 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1288 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1289 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1290 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1291 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1292 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1293 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1295 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1298 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1301 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1306 /* Apply mode mask */
1307 ret
&= lp_create_mask(SNUM(conn
));
1308 /* Add in force bits */
1309 ret
|= lp_force_create_mode(SNUM(conn
));
1312 ret
&= lp_dir_mask(SNUM(conn
));
1313 /* Add in force bits */
1314 ret
|= lp_force_dir_mode(SNUM(conn
));
1316 case PERM_EXISTING_FILE
:
1317 /* Apply mode mask */
1318 ret
&= lp_security_mask(SNUM(conn
));
1319 /* Add in force bits */
1320 ret
|= lp_force_security_mode(SNUM(conn
));
1322 case PERM_EXISTING_DIR
:
1323 /* Apply mode mask */
1324 ret
&= lp_dir_security_mask(SNUM(conn
));
1325 /* Add in force bits */
1326 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1331 return NT_STATUS_OK
;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct
*conn
,
1340 const char *pathname
,
1341 SMB_STRUCT_STAT
*psbuf
)
1343 int saved_errno
= errno
;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn
)) &&
1346 is_msdfs_link(conn
, pathname
, psbuf
)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1351 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1352 errno
= saved_errno
;
1355 errno
= saved_errno
;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state
{
1365 connection_struct
*conn
;
1366 uint32_t info_level
;
1367 bool check_mangled_names
;
1369 bool got_exact_match
;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1378 struct smbd_dirptr_lanman2_state
*state
=
1379 (struct smbd_dirptr_lanman2_state
*)private_data
;
1381 char mangled_name
[13]; /* mangled 8.3 name. */
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1387 ok
= name_to_8_3(dname
, mangled_name
,
1388 true, state
->conn
->params
);
1392 fname
= mangled_name
;
1397 got_match
= exact_match(state
->has_wild
,
1398 state
->conn
->case_sensitive
,
1400 state
->got_exact_match
= got_match
;
1402 got_match
= mask_match(fname
, mask
,
1403 state
->conn
->case_sensitive
);
1406 if(!got_match
&& state
->check_mangled_names
&&
1407 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok
= name_to_8_3(fname
, mangled_name
,
1416 false, state
->conn
->params
);
1421 got_match
= exact_match(state
->has_wild
,
1422 state
->conn
->case_sensitive
,
1423 mangled_name
, mask
);
1424 state
->got_exact_match
= got_match
;
1426 got_match
= mask_match(mangled_name
, mask
,
1427 state
->conn
->case_sensitive
);
1435 *_fname
= talloc_strdup(ctx
, fname
);
1436 if (*_fname
== NULL
) {
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1445 struct smb_filename
*smb_fname
,
1448 struct smbd_dirptr_lanman2_state
*state
=
1449 (struct smbd_dirptr_lanman2_state
*)private_data
;
1450 bool ms_dfs_link
= false;
1453 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1454 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname
),
1461 } else if (!VALID_STAT(smb_fname
->st
) &&
1462 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1463 /* Needed to show the msdfs symlinks as
1466 ms_dfs_link
= check_msdfs_link(state
->conn
,
1467 smb_fname
->base_name
,
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname
),
1479 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1481 mode
= dos_mode(state
->conn
, smb_fname
);
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1489 connection_struct
*conn
,
1491 uint32_t info_level
,
1492 struct ea_list
*name_list
,
1493 bool check_mangled_names
,
1494 bool requires_resume_key
,
1497 const struct smb_filename
*smb_fname
,
1498 int space_remaining
,
1505 uint64_t *last_entry_off
)
1507 char *p
, *q
, *pdata
= *ppdata
;
1509 uint64_t file_size
= 0;
1510 uint64_t allocation_size
= 0;
1511 uint64_t file_index
= 0;
1513 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1514 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1515 time_t c_date
= (time_t)0;
1517 char *last_entry_ptr
;
1522 *out_of_space
= false;
1524 ZERO_STRUCT(mdate_ts
);
1525 ZERO_STRUCT(adate_ts
);
1526 ZERO_STRUCT(create_date_ts
);
1527 ZERO_STRUCT(cdate_ts
);
1529 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1530 file_size
= get_file_size_stat(&smb_fname
->st
);
1532 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1534 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1536 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1537 adate_ts
= smb_fname
->st
.st_ex_atime
;
1538 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1539 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1541 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1542 dos_filetime_timespec(&create_date_ts
);
1543 dos_filetime_timespec(&mdate_ts
);
1544 dos_filetime_timespec(&adate_ts
);
1545 dos_filetime_timespec(&cdate_ts
);
1548 create_date
= convert_timespec_to_time_t(create_date_ts
);
1549 mdate
= convert_timespec_to_time_t(mdate_ts
);
1550 adate
= convert_timespec_to_time_t(adate_ts
);
1551 c_date
= convert_timespec_to_time_t(cdate_ts
);
1553 /* align the record */
1554 SMB_ASSERT(align
>= 1);
1556 off
= (int)PTR_DIFF(pdata
, base_data
);
1557 pad
= (off
+ (align
-1)) & ~(align
-1);
1560 if (pad
&& pad
> space_remaining
) {
1561 *out_of_space
= true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1566 return false; /* Not finished - just out of space */
1570 /* initialize padding to 0 */
1572 memset(pdata
, 0, pad
);
1574 space_remaining
-= pad
;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1586 switch (info_level
) {
1587 case SMB_FIND_INFO_STANDARD
:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key
) {
1593 srv_put_dos_date2(p
,0,create_date
);
1594 srv_put_dos_date2(p
,4,adate
);
1595 srv_put_dos_date2(p
,8,mdate
);
1596 SIVAL(p
,12,(uint32
)file_size
);
1597 SIVAL(p
,16,(uint32
)allocation_size
);
1601 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1602 p
+= ucs2_align(base_data
, p
, 0);
1604 len
= srvstr_push(base_data
, flags2
, p
,
1605 fname
, PTR_DIFF(end_data
, p
),
1607 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1609 SCVAL(nameptr
, -1, len
- 2);
1611 SCVAL(nameptr
, -1, 0);
1615 SCVAL(nameptr
, -1, len
- 1);
1617 SCVAL(nameptr
, -1, 0);
1623 case SMB_FIND_EA_SIZE
:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key
) {
1629 srv_put_dos_date2(p
,0,create_date
);
1630 srv_put_dos_date2(p
,4,adate
);
1631 srv_put_dos_date2(p
,8,mdate
);
1632 SIVAL(p
,12,(uint32
)file_size
);
1633 SIVAL(p
,16,(uint32
)allocation_size
);
1636 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1637 smb_fname
->base_name
);
1638 SIVAL(p
,22,ea_size
); /* Extended attributes */
1642 len
= srvstr_push(base_data
, flags2
,
1643 p
, fname
, PTR_DIFF(end_data
, p
),
1644 STR_TERMINATE
| STR_NOALIGN
);
1645 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1658 SCVAL(nameptr
,0,len
);
1660 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1663 case SMB_FIND_EA_LIST
:
1665 struct ea_list
*file_list
= NULL
;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1672 if (requires_resume_key
) {
1676 srv_put_dos_date2(p
,0,create_date
);
1677 srv_put_dos_date2(p
,4,adate
);
1678 srv_put_dos_date2(p
,8,mdate
);
1679 SIVAL(p
,12,(uint32
)file_size
);
1680 SIVAL(p
,16,(uint32
)allocation_size
);
1682 p
+= 22; /* p now points to the EA area. */
1684 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1685 smb_fname
->base_name
,
1687 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1692 *out_of_space
= true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1697 return False
; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1703 len
= srvstr_push(base_data
, flags2
,
1704 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1705 STR_TERMINATE
| STR_NOALIGN
);
1706 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1719 SCVAL(nameptr
,0,len
);
1721 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1729 SIVAL(p
,0,reskey
); p
+= 4;
1730 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1731 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1732 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1733 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1734 SOFF_T(p
,0,file_size
); p
+= 8;
1735 SOFF_T(p
,0,allocation_size
); p
+= 8;
1736 SIVAL(p
,0,mode
); p
+= 4;
1737 q
= p
; p
+= 4; /* q is placeholder for name length. */
1739 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1740 smb_fname
->base_name
);
1741 SIVAL(p
,0,ea_size
); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3
&& check_mangled_names
) {
1749 char mangled_name
[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname
,mangled_name
,True
,
1752 /* Error - mangle failed ! */
1753 memset(mangled_name
,'\0',12);
1755 mangled_name
[12] = 0;
1756 len
= srvstr_push(base_data
, flags2
,
1757 p
+2, mangled_name
, 24,
1758 STR_UPPER
|STR_UNICODE
);
1760 memset(p
+ 2 + len
,'\0',24 - len
);
1767 len
= srvstr_push(base_data
, flags2
, p
,
1768 fname
, PTR_DIFF(end_data
, p
),
1769 STR_TERMINATE_ASCII
);
1773 len
= PTR_DIFF(p
, pdata
);
1774 pad
= (len
+ (align
-1)) & ~(align
-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1782 * set padding to zero
1785 memset(p
, 0, pad
- len
);
1792 case SMB_FIND_FILE_DIRECTORY_INFO
:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1795 SIVAL(p
,0,reskey
); p
+= 4;
1796 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1797 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1798 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1799 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1800 SOFF_T(p
,0,file_size
); p
+= 8;
1801 SOFF_T(p
,0,allocation_size
); p
+= 8;
1802 SIVAL(p
,0,mode
); p
+= 4;
1803 len
= srvstr_push(base_data
, flags2
,
1804 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1805 STR_TERMINATE_ASCII
);
1809 len
= PTR_DIFF(p
, pdata
);
1810 pad
= (len
+ (align
-1)) & ~(align
-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1818 * set padding to zero
1821 memset(p
, 0, pad
- len
);
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1831 SIVAL(p
,0,reskey
); p
+= 4;
1832 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1833 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1834 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1835 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1836 SOFF_T(p
,0,file_size
); p
+= 8;
1837 SOFF_T(p
,0,allocation_size
); p
+= 8;
1838 SIVAL(p
,0,mode
); p
+= 4;
1839 q
= p
; p
+= 4; /* q is placeholder for name length. */
1841 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1842 smb_fname
->base_name
);
1843 SIVAL(p
,0,ea_size
); /* Extended attributes */
1846 len
= srvstr_push(base_data
, flags2
, p
,
1847 fname
, PTR_DIFF(end_data
, p
),
1848 STR_TERMINATE_ASCII
);
1852 len
= PTR_DIFF(p
, pdata
);
1853 pad
= (len
+ (align
-1)) & ~(align
-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1861 * set padding to zero
1864 memset(p
, 0, pad
- len
);
1871 case SMB_FIND_FILE_NAMES_INFO
:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1874 SIVAL(p
,0,reskey
); p
+= 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len
= srvstr_push(base_data
, flags2
, p
,
1879 fname
, PTR_DIFF(end_data
, p
),
1880 STR_TERMINATE_ASCII
);
1884 len
= PTR_DIFF(p
, pdata
);
1885 pad
= (len
+ (align
-1)) & ~(align
-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1893 * set padding to zero
1896 memset(p
, 0, pad
- len
);
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1906 SIVAL(p
,0,reskey
); p
+= 4;
1907 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1908 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1909 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1910 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1911 SOFF_T(p
,0,file_size
); p
+= 8;
1912 SOFF_T(p
,0,allocation_size
); p
+= 8;
1913 SIVAL(p
,0,mode
); p
+= 4;
1914 q
= p
; p
+= 4; /* q is placeholder for name length. */
1916 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1917 smb_fname
->base_name
);
1918 SIVAL(p
,0,ea_size
); /* Extended attributes */
1921 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1922 SBVAL(p
,0,file_index
); p
+= 8;
1923 len
= srvstr_push(base_data
, flags2
, p
,
1924 fname
, PTR_DIFF(end_data
, p
),
1925 STR_TERMINATE_ASCII
);
1929 len
= PTR_DIFF(p
, pdata
);
1930 pad
= (len
+ (align
-1)) & ~(align
-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1938 * set padding to zero
1941 memset(p
, 0, pad
- len
);
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1952 SIVAL(p
,0,reskey
); p
+= 4;
1953 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1954 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1955 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1956 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1957 SOFF_T(p
,0,file_size
); p
+= 8;
1958 SOFF_T(p
,0,allocation_size
); p
+= 8;
1959 SIVAL(p
,0,mode
); p
+= 4;
1960 q
= p
; p
+= 4; /* q is placeholder for name length */
1962 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1963 smb_fname
->base_name
);
1964 SIVAL(p
,0,ea_size
); /* Extended attributes */
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3
&& check_mangled_names
) {
1972 char mangled_name
[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname
,mangled_name
,True
,
1975 /* Error - mangle failed ! */
1976 memset(mangled_name
,'\0',12);
1978 mangled_name
[12] = 0;
1979 len
= srvstr_push(base_data
, flags2
,
1980 p
+2, mangled_name
, 24,
1981 STR_UPPER
|STR_UNICODE
);
1984 memset(p
+ 2 + len
,'\0',24 - len
);
1991 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1992 SBVAL(p
,0,file_index
); p
+= 8;
1993 len
= srvstr_push(base_data
, flags2
, p
,
1994 fname
, PTR_DIFF(end_data
, p
),
1995 STR_TERMINATE_ASCII
);
1999 len
= PTR_DIFF(p
, pdata
);
2000 pad
= (len
+ (align
-1)) & ~(align
-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p
, 0, pad
- len
);
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX
:
2021 case SMB_FIND_FILE_UNIX_INFO2
:
2023 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level
== SMB_FIND_FILE_UNIX
) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p
= store_file_unix_basic(conn
, p
,
2030 NULL
, &smb_fname
->st
);
2031 len
= srvstr_push(base_data
, flags2
, p
,
2032 fname
, PTR_DIFF(end_data
, p
),
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p
= store_file_unix_basic_info2(conn
, p
,
2037 NULL
, &smb_fname
->st
);
2040 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2041 PTR_DIFF(end_data
, p
), 0);
2042 SIVAL(nameptr
, 0, len
);
2047 len
= PTR_DIFF(p
, pdata
);
2048 pad
= (len
+ (align
-1)) & ~(align
-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2056 * set padding to zero
2059 memset(p
, 0, pad
- len
);
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2073 *out_of_space
= true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p
,pdata
),
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2083 /* Advance the data pointer to the next slot */
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2090 connection_struct
*conn
,
2091 struct dptr_struct
*dirptr
,
2093 const char *path_mask
,
2096 int requires_resume_key
,
2104 int space_remaining
,
2106 bool *got_exact_match
,
2107 int *_last_entry_off
,
2108 struct ea_list
*name_list
)
2111 const char *mask
= NULL
;
2112 long prev_dirpos
= 0;
2115 struct smb_filename
*smb_fname
= NULL
;
2116 struct smbd_dirptr_lanman2_state state
;
2118 uint64_t last_entry_off
= 0;
2122 state
.info_level
= info_level
;
2123 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2124 state
.has_wild
= dptr_has_wild(dirptr
);
2125 state
.got_exact_match
= false;
2127 *out_of_space
= false;
2128 *got_exact_match
= false;
2130 p
= strrchr_m(path_mask
,'/');
2141 ok
= smbd_dirptr_get_entry(ctx
,
2147 smbd_dirptr_lanman2_match_fn
,
2148 smbd_dirptr_lanman2_mode_fn
,
2158 *got_exact_match
= state
.got_exact_match
;
2160 ok
= smbd_marshall_dir_entry(ctx
,
2165 state
.check_mangled_names
,
2166 requires_resume_key
,
2179 TALLOC_FREE(smb_fname
);
2180 if (*out_of_space
) {
2181 dptr_SeekDir(dirptr
, prev_dirpos
);
2188 *_last_entry_off
= last_entry_off
;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2193 connection_struct
*conn
,
2194 struct dptr_struct
*dirptr
,
2196 const char *path_mask
,
2199 bool requires_resume_key
,
2205 int space_remaining
,
2207 bool *got_exact_match
,
2208 int *last_entry_off
,
2209 struct ea_list
*name_list
)
2212 const bool do_pad
= true;
2214 if (info_level
>= 1 && info_level
<= 3) {
2215 /* No alignment on earlier info levels. */
2219 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2220 path_mask
, dirtype
, info_level
,
2221 requires_resume_key
, dont_descend
, ask_sharemode
,
2223 ppdata
, base_data
, end_data
,
2225 out_of_space
, got_exact_match
,
2226 last_entry_off
, name_list
);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct
*conn
,
2234 struct smb_request
*req
,
2235 char **pparams
, int total_params
,
2236 char **ppdata
, int total_data
,
2237 unsigned int max_data_bytes
)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2244 struct smb_filename
*smb_dname
= NULL
;
2245 char *params
= *pparams
;
2246 char *pdata
= *ppdata
;
2250 uint16 findfirst_flags
;
2251 bool close_after_first
;
2253 bool requires_resume_key
;
2255 char *directory
= NULL
;
2258 int last_entry_off
=0;
2262 bool finished
= False
;
2263 bool dont_descend
= False
;
2264 bool out_of_space
= False
;
2265 int space_remaining
;
2266 bool mask_contains_wcard
= False
;
2267 struct ea_list
*ea_list
= NULL
;
2268 NTSTATUS ntstatus
= NT_STATUS_OK
;
2269 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX
*ctx
= talloc_tos();
2271 struct dptr_struct
*dirptr
= NULL
;
2272 struct smbd_server_connection
*sconn
= req
->sconn
;
2274 if (total_params
< 13) {
2275 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2279 dirtype
= SVAL(params
,0);
2280 maxentries
= SVAL(params
,2);
2281 findfirst_flags
= SVAL(params
,4);
2282 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2283 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2284 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2285 info_level
= SVAL(params
,6);
2287 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2288 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2289 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2290 info_level
, max_data_bytes
));
2293 /* W2K3 seems to treat zero as 1. */
2297 switch (info_level
) {
2298 case SMB_FIND_INFO_STANDARD
:
2299 case SMB_FIND_EA_SIZE
:
2300 case SMB_FIND_EA_LIST
:
2301 case SMB_FIND_FILE_DIRECTORY_INFO
:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2303 case SMB_FIND_FILE_NAMES_INFO
:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2308 case SMB_FIND_FILE_UNIX
:
2309 case SMB_FIND_FILE_UNIX_INFO2
:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode
= false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2318 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2322 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2323 params
+12, total_params
- 12,
2324 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2325 if (!NT_STATUS_IS_OK(ntstatus
)) {
2326 reply_nterror(req
, ntstatus
);
2330 ntstatus
= filename_convert(ctx
, conn
,
2331 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2334 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2335 &mask_contains_wcard
,
2337 if (!NT_STATUS_IS_OK(ntstatus
)) {
2338 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2339 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2340 ERRSRV
, ERRbadpath
);
2343 reply_nterror(req
, ntstatus
);
2347 mask
= smb_dname
->original_lcomp
;
2349 directory
= smb_dname
->base_name
;
2351 p
= strrchr_m(directory
,'/');
2353 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2354 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2355 mask
= talloc_strdup(ctx
,"*");
2357 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2360 mask_contains_wcard
= True
;
2366 if (p
== NULL
|| p
== directory
) {
2367 /* Ensure we don't have a directory name of "". */
2368 directory
= talloc_strdup(talloc_tos(), ".");
2370 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2375 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2377 if (info_level
== SMB_FIND_EA_LIST
) {
2380 if (total_data
< 4) {
2381 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2385 ea_size
= IVAL(pdata
,0);
2386 if (ea_size
!= total_data
) {
2387 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2388 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2389 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2393 if (!lp_ea_support(SNUM(conn
))) {
2394 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2398 /* Pull out the list of names. */
2399 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2401 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2406 *ppdata
= (char *)SMB_REALLOC(
2407 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2408 if(*ppdata
== NULL
) {
2409 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2413 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2415 /* Realloc the params space */
2416 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2417 if (*pparams
== NULL
) {
2418 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2423 /* Save the wildcard match and attribs we are using on this directory -
2424 needed as lanman2 assumes these are being saved between calls */
2426 ntstatus
= dptr_create(conn
,
2433 mask_contains_wcard
,
2437 if (!NT_STATUS_IS_OK(ntstatus
)) {
2438 reply_nterror(req
, ntstatus
);
2442 dptr_num
= dptr_dnum(dirptr
);
2443 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2445 /* Initialize per TRANS2_FIND_FIRST operation data */
2446 dptr_init_search_op(dirptr
);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2452 directory
,lp_dontdescend(SNUM(conn
))));
2453 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2454 dont_descend
= True
;
2457 space_remaining
= max_data_bytes
;
2458 out_of_space
= False
;
2460 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2461 bool got_exact_match
= False
;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2466 out_of_space
= True
;
2469 finished
= !get_lanman2_dir_entry(ctx
,
2473 mask
,dirtype
,info_level
,
2474 requires_resume_key
,dont_descend
,
2477 space_remaining
, &out_of_space
,
2479 &last_entry_off
, ea_list
);
2482 if (finished
&& out_of_space
)
2485 if (!finished
&& !out_of_space
)
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2498 /* Ensure space_remaining never goes -ve. */
2499 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2500 space_remaining
= 0;
2501 out_of_space
= true;
2503 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2507 /* Check if we can close the dirptr */
2508 if(close_after_first
|| (finished
&& close_if_end
)) {
2509 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2510 dptr_close(sconn
, &dptr_num
);
2514 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2515 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2516 * the protocol level is less than NT1. Tested with smbclient. JRA.
2517 * This should fix the OS/2 client bug #2335.
2520 if(numentries
== 0) {
2521 dptr_close(sconn
, &dptr_num
);
2522 if (get_Protocol() < PROTOCOL_NT1
) {
2523 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2526 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2527 ERRDOS
, ERRbadfile
);
2532 /* At this point pdata points to numentries directory entries. */
2534 /* Set up the return parameter block */
2535 SSVAL(params
,0,dptr_num
);
2536 SSVAL(params
,2,numentries
);
2537 SSVAL(params
,4,finished
);
2538 SSVAL(params
,6,0); /* Never an EA error */
2539 SSVAL(params
,8,last_entry_off
);
2541 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2544 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2545 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2547 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2551 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2552 smb_fn_name(req
->cmd
),
2553 mask
, directory
, dirtype
, numentries
) );
2556 * Force a name mangle here to ensure that the
2557 * mask as an 8.3 name is top of the mangled cache.
2558 * The reasons for this are subtle. Don't remove
2559 * this code unless you know what you are doing
2560 * (see PR#13758). JRA.
2563 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2564 char mangled_name
[13];
2565 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2568 TALLOC_FREE(smb_dname
);
2572 /****************************************************************************
2573 Reply to a TRANS2_FINDNEXT.
2574 ****************************************************************************/
2576 static void call_trans2findnext(connection_struct
*conn
,
2577 struct smb_request
*req
,
2578 char **pparams
, int total_params
,
2579 char **ppdata
, int total_data
,
2580 unsigned int max_data_bytes
)
2582 /* We must be careful here that we don't return more than the
2583 allowed number of data bytes. If this means returning fewer than
2584 maxentries then so be it. We assume that the redirector has
2585 enough room for the fixed number of parameter bytes it has
2587 char *params
= *pparams
;
2588 char *pdata
= *ppdata
;
2594 uint16 findnext_flags
;
2595 bool close_after_request
;
2597 bool requires_resume_key
;
2599 bool mask_contains_wcard
= False
;
2600 char *resume_name
= NULL
;
2601 const char *mask
= NULL
;
2602 const char *directory
= NULL
;
2606 int i
, last_entry_off
=0;
2607 bool finished
= False
;
2608 bool dont_descend
= False
;
2609 bool out_of_space
= False
;
2610 int space_remaining
;
2611 struct ea_list
*ea_list
= NULL
;
2612 NTSTATUS ntstatus
= NT_STATUS_OK
;
2613 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2614 TALLOC_CTX
*ctx
= talloc_tos();
2615 struct dptr_struct
*dirptr
;
2616 struct smbd_server_connection
*sconn
= req
->sconn
;
2618 if (total_params
< 13) {
2619 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2623 dptr_num
= SVAL(params
,0);
2624 maxentries
= SVAL(params
,2);
2625 info_level
= SVAL(params
,4);
2626 resume_key
= IVAL(params
,6);
2627 findnext_flags
= SVAL(params
,10);
2628 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2629 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2630 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2631 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2633 if (!continue_bit
) {
2634 /* We only need resume_name if continue_bit is zero. */
2635 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2637 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2638 &mask_contains_wcard
);
2639 if (!NT_STATUS_IS_OK(ntstatus
)) {
2640 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2641 complain (it thinks we're asking for the directory above the shared
2642 path or an invalid name). Catch this as the resume name is only compared, never used in
2643 a file access. JRA. */
2644 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2645 &resume_name
, params
+12,
2649 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2650 reply_nterror(req
, ntstatus
);
2656 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2657 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2658 resume_key = %d resume name = %s continue=%d level = %d\n",
2659 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2660 requires_resume_key
, resume_key
,
2661 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2664 /* W2K3 seems to treat zero as 1. */
2668 switch (info_level
) {
2669 case SMB_FIND_INFO_STANDARD
:
2670 case SMB_FIND_EA_SIZE
:
2671 case SMB_FIND_EA_LIST
:
2672 case SMB_FIND_FILE_DIRECTORY_INFO
:
2673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2674 case SMB_FIND_FILE_NAMES_INFO
:
2675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2676 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2677 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2679 case SMB_FIND_FILE_UNIX
:
2680 case SMB_FIND_FILE_UNIX_INFO2
:
2681 /* Always use filesystem for UNIX mtime query. */
2682 ask_sharemode
= false;
2683 if (!lp_unix_extensions()) {
2684 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2689 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2693 if (info_level
== SMB_FIND_EA_LIST
) {
2696 if (total_data
< 4) {
2697 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2701 ea_size
= IVAL(pdata
,0);
2702 if (ea_size
!= total_data
) {
2703 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2704 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2709 if (!lp_ea_support(SNUM(conn
))) {
2710 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2714 /* Pull out the list of names. */
2715 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2717 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2722 *ppdata
= (char *)SMB_REALLOC(
2723 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2724 if(*ppdata
== NULL
) {
2725 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2730 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2732 /* Realloc the params space */
2733 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2734 if(*pparams
== NULL
) {
2735 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2741 /* Check that the dptr is valid */
2742 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2743 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2747 directory
= dptr_path(sconn
, dptr_num
);
2749 /* Get the wildcard mask from the dptr */
2750 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2751 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2752 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2758 /* Get the attr mask from the dptr */
2759 dirtype
= dptr_attr(sconn
, dptr_num
);
2761 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2762 dptr_num
, mask
, dirtype
,
2764 dptr_TellDir(dirptr
)));
2766 /* Initialize per TRANS2_FIND_NEXT operation data */
2767 dptr_init_search_op(dirptr
);
2769 /* We don't need to check for VOL here as this is returned by
2770 a different TRANS2 call. */
2772 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2773 directory
,lp_dontdescend(SNUM(conn
))));
2774 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2775 dont_descend
= True
;
2778 space_remaining
= max_data_bytes
;
2779 out_of_space
= False
;
2782 * Seek to the correct position. We no longer use the resume key but
2783 * depend on the last file name instead.
2786 if(!continue_bit
&& resume_name
&& *resume_name
) {
2789 long current_pos
= 0;
2791 * Remember, name_to_8_3 is called by
2792 * get_lanman2_dir_entry(), so the resume name
2793 * could be mangled. Ensure we check the unmangled name.
2796 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2797 char *new_resume_name
= NULL
;
2798 mangle_lookup_name_from_8_3(ctx
,
2802 if (new_resume_name
) {
2803 resume_name
= new_resume_name
;
2808 * Fix for NT redirector problem triggered by resume key indexes
2809 * changing between directory scans. We now return a resume key of 0
2810 * and instead look for the filename to continue from (also given
2811 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2812 * findfirst/findnext (as is usual) then the directory pointer
2813 * should already be at the correct place.
2816 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2817 } /* end if resume_name && !continue_bit */
2819 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2820 bool got_exact_match
= False
;
2822 /* this is a heuristic to avoid seeking the dirptr except when
2823 absolutely necessary. It allows for a filename of about 40 chars */
2824 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2825 out_of_space
= True
;
2828 finished
= !get_lanman2_dir_entry(ctx
,
2832 mask
,dirtype
,info_level
,
2833 requires_resume_key
,dont_descend
,
2836 space_remaining
, &out_of_space
,
2838 &last_entry_off
, ea_list
);
2841 if (finished
&& out_of_space
)
2844 if (!finished
&& !out_of_space
)
2848 * As an optimisation if we know we aren't looking
2849 * for a wildcard name (ie. the name matches the wildcard exactly)
2850 * then we can finish on any (first) match.
2851 * This speeds up large directory searches. JRA.
2857 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2860 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2861 smb_fn_name(req
->cmd
),
2862 mask
, directory
, dirtype
, numentries
) );
2864 /* Check if we can close the dirptr */
2865 if(close_after_request
|| (finished
&& close_if_end
)) {
2866 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2867 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2870 /* Set up the return parameter block */
2871 SSVAL(params
,0,numentries
);
2872 SSVAL(params
,2,finished
);
2873 SSVAL(params
,4,0); /* Never an EA error */
2874 SSVAL(params
,6,last_entry_off
);
2876 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2882 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2884 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2888 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2890 SMB_ASSERT(extended_info
!= NULL
);
2892 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2893 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2894 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2895 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2896 #ifdef SAMBA_VERSION_REVISION
2897 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2899 extended_info
->samba_subversion
= 0;
2900 #ifdef SAMBA_VERSION_RC_RELEASE
2901 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2903 #ifdef SAMBA_VERSION_PRE_RELEASE
2904 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2907 #ifdef SAMBA_VERSION_VENDOR_PATCH
2908 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2910 extended_info
->samba_gitcommitdate
= 0;
2911 #ifdef SAMBA_VERSION_COMMIT_TIME
2912 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2915 memset(extended_info
->samba_version_string
, 0,
2916 sizeof(extended_info
->samba_version_string
));
2918 snprintf (extended_info
->samba_version_string
,
2919 sizeof(extended_info
->samba_version_string
),
2920 "%s", samba_version_string());
2923 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2924 TALLOC_CTX
*mem_ctx
,
2925 uint16_t info_level
,
2927 unsigned int max_data_bytes
,
2931 char *pdata
, *end_data
;
2932 int data_len
= 0, len
;
2933 const char *vname
= volume_label(SNUM(conn
));
2934 int snum
= SNUM(conn
);
2935 char *fstype
= lp_fstype(SNUM(conn
));
2936 uint32 additional_flags
= 0;
2937 struct smb_filename smb_fname_dot
;
2941 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2942 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2943 "info level (0x%x) on IPC$.\n",
2944 (unsigned int)info_level
));
2945 return NT_STATUS_ACCESS_DENIED
;
2949 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2951 ZERO_STRUCT(smb_fname_dot
);
2952 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2954 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2955 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2956 return map_nt_error_from_unix(errno
);
2959 st
= smb_fname_dot
.st
;
2961 *ppdata
= (char *)SMB_REALLOC(
2962 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2963 if (*ppdata
== NULL
) {
2964 return NT_STATUS_NO_MEMORY
;
2968 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2969 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2971 switch (info_level
) {
2972 case SMB_INFO_ALLOCATION
:
2974 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2976 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2977 return map_nt_error_from_unix(errno
);
2980 block_size
= lp_block_size(snum
);
2981 if (bsize
< block_size
) {
2982 uint64_t factor
= block_size
/bsize
;
2987 if (bsize
> block_size
) {
2988 uint64_t factor
= bsize
/block_size
;
2993 bytes_per_sector
= 512;
2994 sectors_per_unit
= bsize
/bytes_per_sector
;
2996 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2997 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2998 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3000 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3001 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3002 SIVAL(pdata
,l1_cUnit
,dsize
);
3003 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3004 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3008 case SMB_INFO_VOLUME
:
3009 /* Return volume name */
3011 * Add volume serial number - hash of a combination of
3012 * the called hostname and the service name.
3014 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3016 * Win2k3 and previous mess this up by sending a name length
3017 * one byte short. I believe only older clients (OS/2 Win9x) use
3018 * this call so try fixing this by adding a terminating null to
3019 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3023 pdata
+l2_vol_szVolLabel
, vname
,
3024 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3025 STR_NOALIGN
|STR_TERMINATE
);
3026 SCVAL(pdata
,l2_vol_cch
,len
);
3027 data_len
= l2_vol_szVolLabel
+ len
;
3028 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3029 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3033 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3034 case SMB_FS_ATTRIBUTE_INFORMATION
:
3036 additional_flags
= 0;
3037 #if defined(HAVE_SYS_QUOTAS)
3038 additional_flags
|= FILE_VOLUME_QUOTAS
;
3041 if(lp_nt_acl_support(SNUM(conn
))) {
3042 additional_flags
|= FILE_PERSISTENT_ACLS
;
3045 /* Capabilities are filled in at connection time through STATVFS call */
3046 additional_flags
|= conn
->fs_capabilities
;
3047 additional_flags
|= lp_parm_int(conn
->params
->service
,
3048 "share", "fake_fscaps",
3051 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3052 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3053 additional_flags
); /* FS ATTRIBUTES */
3055 SIVAL(pdata
,4,255); /* Max filename component length */
3056 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3057 and will think we can't do long filenames */
3058 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3059 PTR_DIFF(end_data
, pdata
+12),
3062 data_len
= 12 + len
;
3065 case SMB_QUERY_FS_LABEL_INFO
:
3066 case SMB_FS_LABEL_INFORMATION
:
3067 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3068 PTR_DIFF(end_data
, pdata
+4), 0);
3073 case SMB_QUERY_FS_VOLUME_INFO
:
3074 case SMB_FS_VOLUME_INFORMATION
:
3077 * Add volume serial number - hash of a combination of
3078 * the called hostname and the service name.
3080 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3081 (str_checksum(get_local_machine_name())<<16));
3083 /* Max label len is 32 characters. */
3084 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3085 PTR_DIFF(end_data
, pdata
+18),
3087 SIVAL(pdata
,12,len
);
3090 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3091 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3094 case SMB_QUERY_FS_SIZE_INFO
:
3095 case SMB_FS_SIZE_INFORMATION
:
3097 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3099 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3100 return map_nt_error_from_unix(errno
);
3102 block_size
= lp_block_size(snum
);
3103 if (bsize
< block_size
) {
3104 uint64_t factor
= block_size
/bsize
;
3109 if (bsize
> block_size
) {
3110 uint64_t factor
= bsize
/block_size
;
3115 bytes_per_sector
= 512;
3116 sectors_per_unit
= bsize
/bytes_per_sector
;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3118 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3119 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3120 SBIG_UINT(pdata
,0,dsize
);
3121 SBIG_UINT(pdata
,8,dfree
);
3122 SIVAL(pdata
,16,sectors_per_unit
);
3123 SIVAL(pdata
,20,bytes_per_sector
);
3127 case SMB_FS_FULL_SIZE_INFORMATION
:
3129 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3131 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno
);
3134 block_size
= lp_block_size(snum
);
3135 if (bsize
< block_size
) {
3136 uint64_t factor
= block_size
/bsize
;
3141 if (bsize
> block_size
) {
3142 uint64_t factor
= bsize
/block_size
;
3147 bytes_per_sector
= 512;
3148 sectors_per_unit
= bsize
/bytes_per_sector
;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3151 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3152 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3153 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3154 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3155 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3156 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3160 case SMB_QUERY_FS_DEVICE_INFO
:
3161 case SMB_FS_DEVICE_INFORMATION
:
3163 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3165 if (!CAN_WRITE(conn
)) {
3166 characteristics
|= FILE_READ_ONLY_DEVICE
;
3169 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3170 SIVAL(pdata
,4,characteristics
);
3174 #ifdef HAVE_SYS_QUOTAS
3175 case SMB_FS_QUOTA_INFORMATION
:
3177 * what we have to send --metze:
3179 * Unknown1: 24 NULL bytes
3180 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3181 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3182 * Quota Flags: 2 byte :
3183 * Unknown3: 6 NULL bytes
3187 * details for Quota Flags:
3189 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3190 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3191 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3192 * 0x0001 Enable Quotas: enable quota for this fs
3196 /* we need to fake up a fsp here,
3197 * because its not send in this call
3200 SMB_NTQUOTA_STRUCT quotas
;
3203 ZERO_STRUCT(quotas
);
3209 if (get_current_uid(conn
) != 0) {
3210 DEBUG(0,("set_user_quota: access_denied "
3211 "service [%s] user [%s]\n",
3212 lp_servicename(SNUM(conn
)),
3213 conn
->session_info
->unix_name
));
3214 return NT_STATUS_ACCESS_DENIED
;
3217 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3218 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3219 return map_nt_error_from_unix(errno
);
3224 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3225 lp_servicename(SNUM(conn
))));
3227 /* Unknown1 24 NULL bytes*/
3228 SBIG_UINT(pdata
,0,(uint64_t)0);
3229 SBIG_UINT(pdata
,8,(uint64_t)0);
3230 SBIG_UINT(pdata
,16,(uint64_t)0);
3232 /* Default Soft Quota 8 bytes */
3233 SBIG_UINT(pdata
,24,quotas
.softlim
);
3235 /* Default Hard Quota 8 bytes */
3236 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3238 /* Quota flag 2 bytes */
3239 SSVAL(pdata
,40,quotas
.qflags
);
3241 /* Unknown3 6 NULL bytes */
3247 #endif /* HAVE_SYS_QUOTAS */
3248 case SMB_FS_OBJECTID_INFORMATION
:
3250 unsigned char objid
[16];
3251 struct smb_extended_info extended_info
;
3252 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3253 samba_extended_info_version (&extended_info
);
3254 SIVAL(pdata
,16,extended_info
.samba_magic
);
3255 SIVAL(pdata
,20,extended_info
.samba_version
);
3256 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3257 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3258 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3264 * Query the version and capabilities of the CIFS UNIX extensions
3268 case SMB_QUERY_CIFS_UNIX_INFO
:
3270 bool large_write
= lp_min_receive_file_size() &&
3271 !srv_is_signing_active(conn
->sconn
);
3272 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3273 int encrypt_caps
= 0;
3275 if (!lp_unix_extensions()) {
3276 return NT_STATUS_INVALID_LEVEL
;
3279 switch (conn
->encrypt_level
) {
3285 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3288 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3289 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3290 large_write
= false;
3296 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3297 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3299 /* We have POSIX ACLs, pathname, encryption,
3300 * large read/write, and locking capability. */
3302 SBIG_UINT(pdata
,4,((uint64_t)(
3303 CIFS_UNIX_POSIX_ACLS_CAP
|
3304 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3305 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3306 CIFS_UNIX_EXTATTR_CAP
|
3307 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3309 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3311 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3315 case SMB_QUERY_POSIX_FS_INFO
:
3318 vfs_statvfs_struct svfs
;
3320 if (!lp_unix_extensions()) {
3321 return NT_STATUS_INVALID_LEVEL
;
3324 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3328 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3329 SIVAL(pdata
,4,svfs
.BlockSize
);
3330 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3331 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3332 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3333 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3334 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3335 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3338 } else if (rc
== EOPNOTSUPP
) {
3339 return NT_STATUS_INVALID_LEVEL
;
3340 #endif /* EOPNOTSUPP */
3342 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3343 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3348 case SMB_QUERY_POSIX_WHOAMI
:
3354 if (!lp_unix_extensions()) {
3355 return NT_STATUS_INVALID_LEVEL
;
3358 if (max_data_bytes
< 40) {
3359 return NT_STATUS_BUFFER_TOO_SMALL
;
3362 /* We ARE guest if global_sid_Builtin_Guests is
3363 * in our list of SIDs.
3365 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3366 conn
->session_info
->security_token
)) {
3367 flags
|= SMB_WHOAMI_GUEST
;
3370 /* We are NOT guest if global_sid_Authenticated_Users
3371 * is in our list of SIDs.
3373 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3374 conn
->session_info
->security_token
)) {
3375 flags
&= ~SMB_WHOAMI_GUEST
;
3378 /* NOTE: 8 bytes for UID/GID, irrespective of native
3379 * platform size. This matches
3380 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3382 data_len
= 4 /* flags */
3389 + 4 /* pad/reserved */
3390 + (conn
->session_info
->utok
.ngroups
* 8)
3392 + (conn
->session_info
->security_token
->num_sids
*
3396 SIVAL(pdata
, 0, flags
);
3397 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3399 (uint64_t)conn
->session_info
->utok
.uid
);
3400 SBIG_UINT(pdata
, 16,
3401 (uint64_t)conn
->session_info
->utok
.gid
);
3404 if (data_len
>= max_data_bytes
) {
3405 /* Potential overflow, skip the GIDs and SIDs. */
3407 SIVAL(pdata
, 24, 0); /* num_groups */
3408 SIVAL(pdata
, 28, 0); /* num_sids */
3409 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3410 SIVAL(pdata
, 36, 0); /* reserved */
3416 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3417 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3419 /* We walk the SID list twice, but this call is fairly
3420 * infrequent, and I don't expect that it's performance
3421 * sensitive -- jpeach
3423 for (i
= 0, sid_bytes
= 0;
3424 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3425 sid_bytes
+= ndr_size_dom_sid(
3426 &conn
->session_info
->security_token
->sids
[i
],
3430 /* SID list byte count */
3431 SIVAL(pdata
, 32, sid_bytes
);
3433 /* 4 bytes pad/reserved - must be zero */
3434 SIVAL(pdata
, 36, 0);
3438 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3439 SBIG_UINT(pdata
, data_len
,
3440 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3446 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3447 int sid_len
= ndr_size_dom_sid(
3448 &conn
->session_info
->security_token
->sids
[i
],
3451 sid_linearize(pdata
+ data_len
, sid_len
,
3452 &conn
->session_info
->security_token
->sids
[i
]);
3453 data_len
+= sid_len
;
3459 case SMB_MAC_QUERY_FS_INFO
:
3461 * Thursby MAC extension... ONLY on NTFS filesystems
3462 * once we do streams then we don't need this
3464 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3466 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3471 return NT_STATUS_INVALID_LEVEL
;
3474 *ret_data_len
= data_len
;
3475 return NT_STATUS_OK
;
3478 /****************************************************************************
3479 Reply to a TRANS2_QFSINFO (query filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2qfsinfo(connection_struct
*conn
,
3483 struct smb_request
*req
,
3484 char **pparams
, int total_params
,
3485 char **ppdata
, int total_data
,
3486 unsigned int max_data_bytes
)
3488 char *params
= *pparams
;
3489 uint16_t info_level
;
3493 if (total_params
< 2) {
3494 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3498 info_level
= SVAL(params
,0);
3500 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3501 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3502 DEBUG(0,("call_trans2qfsinfo: encryption required "
3503 "and info level 0x%x sent.\n",
3504 (unsigned int)info_level
));
3505 exit_server_cleanly("encryption required "
3511 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3513 status
= smbd_do_qfsinfo(conn
, req
,
3518 if (!NT_STATUS_IS_OK(status
)) {
3519 reply_nterror(req
, status
);
3523 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3526 DEBUG( 4, ( "%s info_level = %d\n",
3527 smb_fn_name(req
->cmd
), info_level
) );
3532 /****************************************************************************
3533 Reply to a TRANS2_SETFSINFO (set filesystem info).
3534 ****************************************************************************/
3536 static void call_trans2setfsinfo(connection_struct
*conn
,
3537 struct smb_request
*req
,
3538 char **pparams
, int total_params
,
3539 char **ppdata
, int total_data
,
3540 unsigned int max_data_bytes
)
3542 char *pdata
= *ppdata
;
3543 char *params
= *pparams
;
3546 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3549 if (total_params
< 4) {
3550 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3552 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3556 info_level
= SVAL(params
,2);
3559 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3560 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3561 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3562 "info level (0x%x) on IPC$.\n",
3563 (unsigned int)info_level
));
3564 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3569 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3570 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3571 DEBUG(0,("call_trans2setfsinfo: encryption required "
3572 "and info level 0x%x sent.\n",
3573 (unsigned int)info_level
));
3574 exit_server_cleanly("encryption required "
3580 switch(info_level
) {
3581 case SMB_SET_CIFS_UNIX_INFO
:
3583 uint16 client_unix_major
;
3584 uint16 client_unix_minor
;
3585 uint32 client_unix_cap_low
;
3586 uint32 client_unix_cap_high
;
3588 if (!lp_unix_extensions()) {
3590 NT_STATUS_INVALID_LEVEL
);
3594 /* There should be 12 bytes of capabilities set. */
3595 if (total_data
< 8) {
3598 NT_STATUS_INVALID_PARAMETER
);
3601 client_unix_major
= SVAL(pdata
,0);
3602 client_unix_minor
= SVAL(pdata
,2);
3603 client_unix_cap_low
= IVAL(pdata
,4);
3604 client_unix_cap_high
= IVAL(pdata
,8);
3605 /* Just print these values for now. */
3606 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3607 cap_low = 0x%x, cap_high = 0x%x\n",
3608 (unsigned int)client_unix_major
,
3609 (unsigned int)client_unix_minor
,
3610 (unsigned int)client_unix_cap_low
,
3611 (unsigned int)client_unix_cap_high
));
3613 /* Here is where we must switch to posix pathname processing... */
3614 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3615 lp_set_posix_pathnames();
3616 mangle_change_to_posix();
3619 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3620 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3621 /* Client that knows how to do posix locks,
3622 * but not posix open/mkdir operations. Set a
3623 * default type for read/write checks. */
3625 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3631 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3634 size_t param_len
= 0;
3635 size_t data_len
= total_data
;
3637 if (!lp_unix_extensions()) {
3640 NT_STATUS_INVALID_LEVEL
);
3644 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3647 NT_STATUS_NOT_SUPPORTED
);
3651 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3652 DEBUG( 2,("call_trans2setfsinfo: "
3653 "request transport encryption disabled"
3654 "with 'fork echo handler = yes'\n"));
3657 NT_STATUS_NOT_SUPPORTED
);
3661 DEBUG( 4,("call_trans2setfsinfo: "
3662 "request transport encryption.\n"));
3664 status
= srv_request_encryption_setup(conn
,
3665 (unsigned char **)ppdata
,
3667 (unsigned char **)pparams
,
3670 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3671 !NT_STATUS_IS_OK(status
)) {
3672 reply_nterror(req
, status
);
3676 send_trans2_replies(conn
, req
,
3683 if (NT_STATUS_IS_OK(status
)) {
3684 /* Server-side transport
3685 * encryption is now *on*. */
3686 status
= srv_encryption_start(conn
);
3687 if (!NT_STATUS_IS_OK(status
)) {
3688 exit_server_cleanly(
3689 "Failure in setting "
3690 "up encrypted transport");
3696 case SMB_FS_QUOTA_INFORMATION
:
3698 files_struct
*fsp
= NULL
;
3699 SMB_NTQUOTA_STRUCT quotas
;
3701 ZERO_STRUCT(quotas
);
3704 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3705 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3706 lp_servicename(SNUM(conn
)),
3707 conn
->session_info
->unix_name
));
3708 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3712 /* note: normaly there're 48 bytes,
3713 * but we didn't use the last 6 bytes for now
3716 fsp
= file_fsp(req
, SVAL(params
,0));
3718 if (!check_fsp_ntquota_handle(conn
, req
,
3720 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3722 req
, NT_STATUS_INVALID_HANDLE
);
3726 if (total_data
< 42) {
3727 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3731 NT_STATUS_INVALID_PARAMETER
);
3735 /* unknown_1 24 NULL bytes in pdata*/
3737 /* the soft quotas 8 bytes (uint64_t)*/
3738 quotas
.softlim
= BVAL(pdata
,24);
3740 /* the hard quotas 8 bytes (uint64_t)*/
3741 quotas
.hardlim
= BVAL(pdata
,32);
3743 /* quota_flags 2 bytes **/
3744 quotas
.qflags
= SVAL(pdata
,40);
3746 /* unknown_2 6 NULL bytes follow*/
3748 /* now set the quotas */
3749 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3750 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3751 reply_nterror(req
, map_nt_error_from_unix(errno
));
3758 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3760 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3766 * sending this reply works fine,
3767 * but I'm not sure it's the same
3768 * like windows do...
3771 reply_outbuf(req
, 10, 0);
3774 #if defined(HAVE_POSIX_ACLS)
3775 /****************************************************************************
3776 Utility function to count the number of entries in a POSIX acl.
3777 ****************************************************************************/
3779 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3781 unsigned int ace_count
= 0;
3782 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3783 SMB_ACL_ENTRY_T entry
;
3785 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3787 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3788 entry_id
= SMB_ACL_NEXT_ENTRY
;
3795 /****************************************************************************
3796 Utility function to marshall a POSIX acl into wire format.
3797 ****************************************************************************/
3799 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3801 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3802 SMB_ACL_ENTRY_T entry
;
3804 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3805 SMB_ACL_TAG_T tagtype
;
3806 SMB_ACL_PERMSET_T permset
;
3807 unsigned char perms
= 0;
3808 unsigned int own_grp
;
3811 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3812 entry_id
= SMB_ACL_NEXT_ENTRY
;
3815 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3816 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3820 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3821 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3825 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3826 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3827 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3829 SCVAL(pdata
,1,perms
);
3832 case SMB_ACL_USER_OBJ
:
3833 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3834 own_grp
= (unsigned int)pst
->st_ex_uid
;
3835 SIVAL(pdata
,2,own_grp
);
3840 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3842 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3845 own_grp
= (unsigned int)*puid
;
3846 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3847 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3848 SIVAL(pdata
,2,own_grp
);
3852 case SMB_ACL_GROUP_OBJ
:
3853 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3854 own_grp
= (unsigned int)pst
->st_ex_gid
;
3855 SIVAL(pdata
,2,own_grp
);
3860 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3862 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3865 own_grp
= (unsigned int)*pgid
;
3866 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3867 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3868 SIVAL(pdata
,2,own_grp
);
3873 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3874 SIVAL(pdata
,2,0xFFFFFFFF);
3875 SIVAL(pdata
,6,0xFFFFFFFF);
3878 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3879 SIVAL(pdata
,2,0xFFFFFFFF);
3880 SIVAL(pdata
,6,0xFFFFFFFF);
3883 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3886 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3893 /****************************************************************************
3894 Store the FILE_UNIX_BASIC info.
3895 ****************************************************************************/
3897 static char *store_file_unix_basic(connection_struct
*conn
,
3900 const SMB_STRUCT_STAT
*psbuf
)
3902 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3904 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3905 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3907 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3910 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3913 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3914 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3915 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3918 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3922 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3926 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3929 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3933 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3937 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3940 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3944 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3951 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3952 * the chflags(2) (or equivalent) flags.
3954 * XXX: this really should be behind the VFS interface. To do this, we would
3955 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3956 * Each VFS module could then implement its own mapping as appropriate for the
3957 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3959 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3963 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3967 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3971 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3975 { UF_HIDDEN
, EXT_HIDDEN
},
3978 /* Do not remove. We need to guarantee that this array has at least one
3979 * entry to build on HP-UX.
3985 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3986 uint32
*smb_fflags
, uint32
*smb_fmask
)
3990 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3991 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3992 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3993 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3998 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3999 const uint32 smb_fflags
,
4000 const uint32 smb_fmask
,
4003 uint32 max_fmask
= 0;
4006 *stat_fflags
= psbuf
->st_ex_flags
;
4008 /* For each flags requested in smb_fmask, check the state of the
4009 * corresponding flag in smb_fflags and set or clear the matching
4013 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4014 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4015 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4016 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4017 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4019 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4024 /* If smb_fmask is asking to set any bits that are not supported by
4025 * our flag mappings, we should fail.
4027 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4035 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4036 * of file flags and birth (create) time.
4038 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4041 const SMB_STRUCT_STAT
*psbuf
)
4043 uint32 file_flags
= 0;
4044 uint32 flags_mask
= 0;
4046 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4048 /* Create (birth) time 64 bit */
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4052 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4053 SIVAL(pdata
, 0, file_flags
); /* flags */
4054 SIVAL(pdata
, 4, flags_mask
); /* mask */
4060 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4061 const struct stream_struct
*streams
,
4063 unsigned int max_data_bytes
,
4064 unsigned int *data_size
)
4067 unsigned int ofs
= 0;
4069 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4070 unsigned int next_offset
;
4072 smb_ucs2_t
*namebuf
;
4074 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4075 streams
[i
].name
, &namelen
) ||
4078 return NT_STATUS_INVALID_PARAMETER
;
4082 * name_buf is now null-terminated, we need to marshall as not
4088 SIVAL(data
, ofs
+4, namelen
);
4089 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4090 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4091 memcpy(data
+ofs
+24, namebuf
, namelen
);
4092 TALLOC_FREE(namebuf
);
4094 next_offset
= ofs
+ 24 + namelen
;
4096 if (i
== num_streams
-1) {
4097 SIVAL(data
, ofs
, 0);
4100 unsigned int align
= ndr_align_size(next_offset
, 8);
4102 memset(data
+next_offset
, 0, align
);
4103 next_offset
+= align
;
4105 SIVAL(data
, ofs
, next_offset
- ofs
);
4114 return NT_STATUS_OK
;
4117 /****************************************************************************
4118 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4119 ****************************************************************************/
4121 static void call_trans2qpipeinfo(connection_struct
*conn
,
4122 struct smb_request
*req
,
4123 unsigned int tran_call
,
4124 char **pparams
, int total_params
,
4125 char **ppdata
, int total_data
,
4126 unsigned int max_data_bytes
)
4128 char *params
= *pparams
;
4129 char *pdata
= *ppdata
;
4130 unsigned int data_size
= 0;
4131 unsigned int param_size
= 2;
4136 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4140 if (total_params
< 4) {
4141 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4145 fsp
= file_fsp(req
, SVAL(params
,0));
4146 if (!fsp_is_np(fsp
)) {
4147 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4151 info_level
= SVAL(params
,2);
4153 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4154 if (*pparams
== NULL
) {
4155 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4160 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4161 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4162 if (*ppdata
== NULL
) {
4163 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4168 switch (info_level
) {
4169 case SMB_FILE_STANDARD_INFORMATION
:
4171 SOFF_T(pdata
,0,4096LL);
4178 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4182 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4188 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4189 TALLOC_CTX
*mem_ctx
,
4190 uint16_t info_level
,
4192 struct smb_filename
*smb_fname
,
4193 bool delete_pending
,
4194 struct timespec write_time_ts
,
4195 struct ea_list
*ea_list
,
4196 int lock_data_count
,
4199 unsigned int max_data_bytes
,
4201 unsigned int *pdata_size
)
4203 char *pdata
= *ppdata
;
4204 char *dstart
, *dend
;
4205 unsigned int data_size
;
4206 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4207 time_t create_time
, mtime
, atime
, c_time
;
4208 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4215 uint64_t file_size
= 0;
4217 uint64_t allocation_size
= 0;
4218 uint64_t file_index
= 0;
4219 uint32_t access_mask
= 0;
4221 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4222 return NT_STATUS_INVALID_LEVEL
;
4225 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4226 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4227 info_level
, max_data_bytes
));
4229 mode
= dos_mode(conn
, smb_fname
);
4230 nlink
= psbuf
->st_ex_nlink
;
4232 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4236 if ((nlink
> 0) && delete_pending
) {
4240 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4241 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4242 if (*ppdata
== NULL
) {
4243 return NT_STATUS_NO_MEMORY
;
4247 dend
= dstart
+ data_size
- 1;
4249 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4250 update_stat_ex_mtime(psbuf
, write_time_ts
);
4253 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4254 mtime_ts
= psbuf
->st_ex_mtime
;
4255 atime_ts
= psbuf
->st_ex_atime
;
4256 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4258 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4259 dos_filetime_timespec(&create_time_ts
);
4260 dos_filetime_timespec(&mtime_ts
);
4261 dos_filetime_timespec(&atime_ts
);
4262 dos_filetime_timespec(&ctime_ts
);
4265 create_time
= convert_timespec_to_time_t(create_time_ts
);
4266 mtime
= convert_timespec_to_time_t(mtime_ts
);
4267 atime
= convert_timespec_to_time_t(atime_ts
);
4268 c_time
= convert_timespec_to_time_t(ctime_ts
);
4270 p
= strrchr_m(smb_fname
->base_name
,'/');
4272 base_name
= smb_fname
->base_name
;
4276 /* NT expects the name to be in an exact form of the *full*
4277 filename. See the trans2 torture test */
4278 if (ISDOT(base_name
)) {
4279 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4281 return NT_STATUS_NO_MEMORY
;
4284 dos_fname
= talloc_asprintf(mem_ctx
,
4286 smb_fname
->base_name
);
4288 return NT_STATUS_NO_MEMORY
;
4290 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4291 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4292 smb_fname
->stream_name
);
4294 return NT_STATUS_NO_MEMORY
;
4298 string_replace(dos_fname
, '/', '\\');
4301 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4304 /* Do we have this path open ? */
4306 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4307 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4308 if (fsp1
&& fsp1
->initial_allocation_size
) {
4309 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4313 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4314 file_size
= get_file_size_stat(psbuf
);
4318 pos
= fsp
->fh
->position_information
;
4322 access_mask
= fsp
->access_mask
;
4324 /* GENERIC_EXECUTE mapping from Windows */
4325 access_mask
= 0x12019F;
4328 /* This should be an index number - looks like
4331 I think this causes us to fail the IFSKIT
4332 BasicFileInformationTest. -tpot */
4333 file_index
= get_FileIndex(conn
, psbuf
);
4335 switch (info_level
) {
4336 case SMB_INFO_STANDARD
:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4339 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4340 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4341 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4342 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4343 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4344 SSVAL(pdata
,l1_attrFile
,mode
);
4347 case SMB_INFO_QUERY_EA_SIZE
:
4349 unsigned int ea_size
=
4350 estimate_ea_size(conn
, fsp
,
4351 smb_fname
->base_name
);
4352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4354 srv_put_dos_date2(pdata
,0,create_time
);
4355 srv_put_dos_date2(pdata
,4,atime
);
4356 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4357 SIVAL(pdata
,12,(uint32
)file_size
);
4358 SIVAL(pdata
,16,(uint32
)allocation_size
);
4359 SSVAL(pdata
,20,mode
);
4360 SIVAL(pdata
,22,ea_size
);
4364 case SMB_INFO_IS_NAME_VALID
:
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4367 /* os/2 needs this ? really ?*/
4368 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4370 /* This is only reached for qpathinfo */
4374 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4376 size_t total_ea_len
= 0;
4377 struct ea_list
*ea_file_list
= NULL
;
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4382 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4383 smb_fname
->base_name
,
4385 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4387 if (!ea_list
|| (total_ea_len
> data_size
)) {
4389 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4393 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4397 case SMB_INFO_QUERY_ALL_EAS
:
4399 /* We have data_size bytes to put EA's into. */
4400 size_t total_ea_len
= 0;
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4404 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4405 smb_fname
->base_name
,
4407 if (!ea_list
|| (total_ea_len
> data_size
)) {
4409 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4413 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4417 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4419 /* This is FileFullEaInformation - 0xF which maps to
4420 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4422 /* We have data_size bytes to put EA's into. */
4423 size_t total_ea_len
= 0;
4424 struct ea_list
*ea_file_list
= NULL
;
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4428 /*TODO: add filtering and index handling */
4431 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4432 smb_fname
->base_name
,
4434 if (!ea_file_list
) {
4435 return NT_STATUS_NO_EAS_ON_FILE
;
4438 status
= fill_ea_chained_buffer(mem_ctx
,
4442 conn
, ea_file_list
);
4443 if (!NT_STATUS_IS_OK(status
)) {
4449 case SMB_FILE_BASIC_INFORMATION
:
4450 case SMB_QUERY_FILE_BASIC_INFO
:
4452 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4454 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4460 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4461 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4462 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4463 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4464 SIVAL(pdata
,32,mode
);
4466 DEBUG(5,("SMB_QFBI - "));
4467 DEBUG(5,("create: %s ", ctime(&create_time
)));
4468 DEBUG(5,("access: %s ", ctime(&atime
)));
4469 DEBUG(5,("write: %s ", ctime(&mtime
)));
4470 DEBUG(5,("change: %s ", ctime(&c_time
)));
4471 DEBUG(5,("mode: %x\n", mode
));
4474 case SMB_FILE_STANDARD_INFORMATION
:
4475 case SMB_QUERY_FILE_STANDARD_INFO
:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4479 SOFF_T(pdata
,0,allocation_size
);
4480 SOFF_T(pdata
,8,file_size
);
4481 SIVAL(pdata
,16,nlink
);
4482 SCVAL(pdata
,20,delete_pending
?1:0);
4483 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4484 SSVAL(pdata
,22,0); /* Padding. */
4487 case SMB_FILE_EA_INFORMATION
:
4488 case SMB_QUERY_FILE_EA_INFO
:
4490 unsigned int ea_size
=
4491 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4494 SIVAL(pdata
,0,ea_size
);
4498 /* Get the 8.3 name - used if NT SMB was negotiated. */
4499 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4500 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4503 char mangled_name
[13];
4504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4505 if (!name_to_8_3(base_name
,mangled_name
,
4506 True
,conn
->params
)) {
4507 return NT_STATUS_NO_MEMORY
;
4509 len
= srvstr_push(dstart
, flags2
,
4510 pdata
+4, mangled_name
,
4511 PTR_DIFF(dend
, pdata
+4),
4513 data_size
= 4 + len
;
4518 case SMB_QUERY_FILE_NAME_INFO
:
4522 this must be *exactly* right for ACLs on mapped drives to work
4524 len
= srvstr_push(dstart
, flags2
,
4526 PTR_DIFF(dend
, pdata
+4),
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4529 data_size
= 4 + len
;
4534 case SMB_FILE_ALLOCATION_INFORMATION
:
4535 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4538 SOFF_T(pdata
,0,allocation_size
);
4541 case SMB_FILE_END_OF_FILE_INFORMATION
:
4542 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4545 SOFF_T(pdata
,0,file_size
);
4548 case SMB_QUERY_FILE_ALL_INFO
:
4549 case SMB_FILE_ALL_INFORMATION
:
4552 unsigned int ea_size
=
4553 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4555 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4556 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4557 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4558 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4559 SIVAL(pdata
,32,mode
);
4560 SIVAL(pdata
,36,0); /* padding. */
4562 SOFF_T(pdata
,0,allocation_size
);
4563 SOFF_T(pdata
,8,file_size
);
4564 SIVAL(pdata
,16,nlink
);
4565 SCVAL(pdata
,20,delete_pending
);
4566 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4569 SIVAL(pdata
,0,ea_size
);
4570 pdata
+= 4; /* EA info */
4571 len
= srvstr_push(dstart
, flags2
,
4573 PTR_DIFF(dend
, pdata
+4),
4577 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4581 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4584 unsigned int ea_size
=
4585 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4587 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4588 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4589 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4590 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4591 SIVAL(pdata
, 0x20, mode
);
4592 SIVAL(pdata
, 0x24, 0); /* padding. */
4593 SBVAL(pdata
, 0x28, allocation_size
);
4594 SBVAL(pdata
, 0x30, file_size
);
4595 SIVAL(pdata
, 0x38, nlink
);
4596 SCVAL(pdata
, 0x3C, delete_pending
);
4597 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4598 SSVAL(pdata
, 0x3E, 0); /* padding */
4599 SBVAL(pdata
, 0x40, file_index
);
4600 SIVAL(pdata
, 0x48, ea_size
);
4601 SIVAL(pdata
, 0x4C, access_mask
);
4602 SBVAL(pdata
, 0x50, pos
);
4603 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4604 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4608 len
= srvstr_push(dstart
, flags2
,
4610 PTR_DIFF(dend
, pdata
+4),
4614 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4617 case SMB_FILE_INTERNAL_INFORMATION
:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4620 SBVAL(pdata
, 0, file_index
);
4624 case SMB_FILE_ACCESS_INFORMATION
:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4626 SIVAL(pdata
, 0, access_mask
);
4630 case SMB_FILE_NAME_INFORMATION
:
4631 /* Pathname with leading '\'. */
4634 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4636 SIVAL(pdata
,0,byte_len
);
4637 data_size
= 4 + byte_len
;
4641 case SMB_FILE_DISPOSITION_INFORMATION
:
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4644 SCVAL(pdata
,0,delete_pending
);
4647 case SMB_FILE_POSITION_INFORMATION
:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4650 SOFF_T(pdata
,0,pos
);
4653 case SMB_FILE_MODE_INFORMATION
:
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4655 SIVAL(pdata
,0,mode
);
4659 case SMB_FILE_ALIGNMENT_INFORMATION
:
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4661 SIVAL(pdata
,0,0); /* No alignment needed. */
4666 * NT4 server just returns "invalid query" to this - if we try
4667 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4670 /* The first statement above is false - verified using Thursby
4671 * client against NT4 -- gcolley.
4673 case SMB_QUERY_FILE_STREAM_INFO
:
4674 case SMB_FILE_STREAM_INFORMATION
: {
4675 unsigned int num_streams
;
4676 struct stream_struct
*streams
;
4678 DEBUG(10,("smbd_do_qfilepathinfo: "
4679 "SMB_FILE_STREAM_INFORMATION\n"));
4681 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4682 return NT_STATUS_INVALID_PARAMETER
;
4685 status
= SMB_VFS_STREAMINFO(
4686 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4687 &num_streams
, &streams
);
4689 if (!NT_STATUS_IS_OK(status
)) {
4690 DEBUG(10, ("could not get stream info: %s\n",
4691 nt_errstr(status
)));
4695 status
= marshall_stream_info(num_streams
, streams
,
4696 pdata
, max_data_bytes
,
4699 if (!NT_STATUS_IS_OK(status
)) {
4700 DEBUG(10, ("marshall_stream_info failed: %s\n",
4701 nt_errstr(status
)));
4705 TALLOC_FREE(streams
);
4709 case SMB_QUERY_COMPRESSION_INFO
:
4710 case SMB_FILE_COMPRESSION_INFORMATION
:
4711 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4712 SOFF_T(pdata
,0,file_size
);
4713 SIVAL(pdata
,8,0); /* ??? */
4714 SIVAL(pdata
,12,0); /* ??? */
4718 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4720 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4721 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4722 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4723 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4724 SOFF_T(pdata
,32,allocation_size
);
4725 SOFF_T(pdata
,40,file_size
);
4726 SIVAL(pdata
,48,mode
);
4727 SIVAL(pdata
,52,0); /* ??? */
4731 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4733 SIVAL(pdata
,0,mode
);
4739 * CIFS UNIX Extensions.
4742 case SMB_QUERY_FILE_UNIX_BASIC
:
4744 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4745 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4747 DEBUG(4,("smbd_do_qfilepathinfo: "
4748 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4749 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4753 case SMB_QUERY_FILE_UNIX_INFO2
:
4755 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4756 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4760 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4762 for (i
=0; i
<100; i
++)
4763 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4769 case SMB_QUERY_FILE_UNIX_LINK
:
4772 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4775 return NT_STATUS_NO_MEMORY
;
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4780 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4781 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4784 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4786 len
= SMB_VFS_READLINK(conn
,
4787 smb_fname
->base_name
,
4790 return map_nt_error_from_unix(errno
);
4793 len
= srvstr_push(dstart
, flags2
,
4795 PTR_DIFF(dend
, pdata
),
4798 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4803 #if defined(HAVE_POSIX_ACLS)
4804 case SMB_QUERY_POSIX_ACL
:
4806 SMB_ACL_T file_acl
= NULL
;
4807 SMB_ACL_T def_acl
= NULL
;
4808 uint16 num_file_acls
= 0;
4809 uint16 num_def_acls
= 0;
4811 if (fsp
&& fsp
->fh
->fd
!= -1) {
4812 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4815 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4816 smb_fname
->base_name
,
4817 SMB_ACL_TYPE_ACCESS
);
4820 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4821 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4822 "not implemented on "
4823 "filesystem containing %s\n",
4824 smb_fname
->base_name
));
4825 return NT_STATUS_NOT_IMPLEMENTED
;
4828 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4829 if (fsp
&& fsp
->is_directory
) {
4831 SMB_VFS_SYS_ACL_GET_FILE(
4833 fsp
->fsp_name
->base_name
,
4834 SMB_ACL_TYPE_DEFAULT
);
4837 SMB_VFS_SYS_ACL_GET_FILE(
4839 smb_fname
->base_name
,
4840 SMB_ACL_TYPE_DEFAULT
);
4842 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4845 num_file_acls
= count_acl_entries(conn
, file_acl
);
4846 num_def_acls
= count_acl_entries(conn
, def_acl
);
4848 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4849 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4851 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4852 SMB_POSIX_ACL_HEADER_SIZE
) ));
4854 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4859 return NT_STATUS_BUFFER_TOO_SMALL
;
4862 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4863 SSVAL(pdata
,2,num_file_acls
);
4864 SSVAL(pdata
,4,num_def_acls
);
4865 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4867 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4872 return NT_STATUS_INTERNAL_ERROR
;
4874 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4876 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4879 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4881 return NT_STATUS_INTERNAL_ERROR
;
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4888 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4890 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4896 case SMB_QUERY_POSIX_LOCK
:
4901 enum brl_type lock_type
;
4903 /* We need an open file with a real fd for this. */
4904 if (!fsp
|| fsp
->fh
->fd
== -1) {
4905 return NT_STATUS_INVALID_LEVEL
;
4908 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4909 return NT_STATUS_INVALID_PARAMETER
;
4912 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4913 case POSIX_LOCK_TYPE_READ
:
4914 lock_type
= READ_LOCK
;
4916 case POSIX_LOCK_TYPE_WRITE
:
4917 lock_type
= WRITE_LOCK
;
4919 case POSIX_LOCK_TYPE_UNLOCK
:
4921 /* There's no point in asking for an unlock... */
4922 return NT_STATUS_INVALID_PARAMETER
;
4925 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4926 #if defined(HAVE_LONGLONG)
4927 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4928 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4929 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4930 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4931 #else /* HAVE_LONGLONG */
4932 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4933 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4934 #endif /* HAVE_LONGLONG */
4936 status
= query_lock(fsp
,
4943 if (ERROR_WAS_LOCK_DENIED(status
)) {
4944 /* Here we need to report who has it locked... */
4945 data_size
= POSIX_LOCK_DATA_SIZE
;
4947 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4948 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4949 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4950 #if defined(HAVE_LONGLONG)
4951 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4952 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4953 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4954 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4955 #else /* HAVE_LONGLONG */
4956 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4957 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4958 #endif /* HAVE_LONGLONG */
4960 } else if (NT_STATUS_IS_OK(status
)) {
4961 /* For success we just return a copy of what we sent
4962 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4963 data_size
= POSIX_LOCK_DATA_SIZE
;
4964 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4965 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4973 return NT_STATUS_INVALID_LEVEL
;
4976 *pdata_size
= data_size
;
4977 return NT_STATUS_OK
;
4980 /****************************************************************************
4981 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4982 file name or file id).
4983 ****************************************************************************/
4985 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4986 struct smb_request
*req
,
4987 unsigned int tran_call
,
4988 char **pparams
, int total_params
,
4989 char **ppdata
, int total_data
,
4990 unsigned int max_data_bytes
)
4992 char *params
= *pparams
;
4993 char *pdata
= *ppdata
;
4995 unsigned int data_size
= 0;
4996 unsigned int param_size
= 2;
4997 struct smb_filename
*smb_fname
= NULL
;
4998 bool delete_pending
= False
;
4999 struct timespec write_time_ts
;
5000 files_struct
*fsp
= NULL
;
5001 struct file_id fileid
;
5002 struct ea_list
*ea_list
= NULL
;
5003 int lock_data_count
= 0;
5004 char *lock_data
= NULL
;
5005 NTSTATUS status
= NT_STATUS_OK
;
5008 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5012 ZERO_STRUCT(write_time_ts
);
5014 if (tran_call
== TRANSACT2_QFILEINFO
) {
5015 if (total_params
< 4) {
5016 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5021 call_trans2qpipeinfo(conn
, req
, tran_call
,
5022 pparams
, total_params
,
5028 fsp
= file_fsp(req
, SVAL(params
,0));
5029 info_level
= SVAL(params
,2);
5031 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5033 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5034 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5038 /* Initial check for valid fsp ptr. */
5039 if (!check_fsp_open(conn
, req
, fsp
)) {
5043 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5045 if (!NT_STATUS_IS_OK(status
)) {
5046 reply_nterror(req
, status
);
5050 if(fsp
->fake_file_handle
) {
5052 * This is actually for the QUOTA_FAKE_FILE --metze
5055 /* We know this name is ok, it's already passed the checks. */
5057 } else if(fsp
->fh
->fd
== -1) {
5059 * This is actually a QFILEINFO on a directory
5060 * handle (returned from an NT SMB). NT5.0 seems
5061 * to do this call. JRA.
5064 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5065 /* Always do lstat for UNIX calls. */
5066 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5067 DEBUG(3,("call_trans2qfilepathinfo: "
5068 "SMB_VFS_LSTAT of %s failed "
5070 smb_fname_str_dbg(smb_fname
),
5073 map_nt_error_from_unix(errno
));
5076 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5077 DEBUG(3,("call_trans2qfilepathinfo: "
5078 "SMB_VFS_STAT of %s failed (%s)\n",
5079 smb_fname_str_dbg(smb_fname
),
5082 map_nt_error_from_unix(errno
));
5086 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5087 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5090 * Original code - this is an open file.
5092 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5093 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5094 fsp
->fnum
, strerror(errno
)));
5096 map_nt_error_from_unix(errno
));
5099 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5100 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5108 if (total_params
< 7) {
5109 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5113 info_level
= SVAL(params
,0);
5115 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5117 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5118 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5122 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5124 STR_TERMINATE
, &status
);
5125 if (!NT_STATUS_IS_OK(status
)) {
5126 reply_nterror(req
, status
);
5130 status
= filename_convert(req
,
5132 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5137 if (!NT_STATUS_IS_OK(status
)) {
5138 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5139 reply_botherror(req
,
5140 NT_STATUS_PATH_NOT_COVERED
,
5141 ERRSRV
, ERRbadpath
);
5144 reply_nterror(req
, status
);
5148 /* If this is a stream, check if there is a delete_pending. */
5149 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5150 && is_ntfs_stream_smb_fname(smb_fname
)) {
5151 struct smb_filename
*smb_fname_base
= NULL
;
5153 /* Create an smb_filename with stream_name == NULL. */
5155 create_synthetic_smb_fname(talloc_tos(),
5156 smb_fname
->base_name
,
5159 if (!NT_STATUS_IS_OK(status
)) {
5160 reply_nterror(req
, status
);
5164 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5165 /* Always do lstat for UNIX calls. */
5166 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5167 DEBUG(3,("call_trans2qfilepathinfo: "
5168 "SMB_VFS_LSTAT of %s failed "
5170 smb_fname_str_dbg(smb_fname_base
),
5172 TALLOC_FREE(smb_fname_base
);
5174 map_nt_error_from_unix(errno
));
5178 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5179 DEBUG(3,("call_trans2qfilepathinfo: "
5180 "fileinfo of %s failed "
5182 smb_fname_str_dbg(smb_fname_base
),
5184 TALLOC_FREE(smb_fname_base
);
5186 map_nt_error_from_unix(errno
));
5191 status
= file_name_hash(conn
,
5192 smb_fname_str_dbg(smb_fname_base
),
5194 if (!NT_STATUS_IS_OK(status
)) {
5195 TALLOC_FREE(smb_fname_base
);
5196 reply_nterror(req
, status
);
5200 fileid
= vfs_file_id_from_sbuf(conn
,
5201 &smb_fname_base
->st
);
5202 TALLOC_FREE(smb_fname_base
);
5203 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5204 if (delete_pending
) {
5205 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5210 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5211 /* Always do lstat for UNIX calls. */
5212 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5213 DEBUG(3,("call_trans2qfilepathinfo: "
5214 "SMB_VFS_LSTAT of %s failed (%s)\n",
5215 smb_fname_str_dbg(smb_fname
),
5218 map_nt_error_from_unix(errno
));
5223 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5224 DEBUG(3,("call_trans2qfilepathinfo: "
5225 "SMB_VFS_STAT of %s failed (%s)\n",
5226 smb_fname_str_dbg(smb_fname
),
5229 map_nt_error_from_unix(errno
));
5234 status
= file_name_hash(conn
,
5235 smb_fname_str_dbg(smb_fname
),
5237 if (!NT_STATUS_IS_OK(status
)) {
5238 reply_nterror(req
, status
);
5242 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5243 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5244 if (delete_pending
) {
5245 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5250 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5251 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5252 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5254 /* Pull out any data sent here before we realloc. */
5255 switch (info_level
) {
5256 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5258 /* Pull any EA list from the data portion. */
5261 if (total_data
< 4) {
5263 req
, NT_STATUS_INVALID_PARAMETER
);
5266 ea_size
= IVAL(pdata
,0);
5268 if (total_data
> 0 && ea_size
!= total_data
) {
5269 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5270 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5272 req
, NT_STATUS_INVALID_PARAMETER
);
5276 if (!lp_ea_support(SNUM(conn
))) {
5277 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5281 /* Pull out the list of names. */
5282 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5285 req
, NT_STATUS_INVALID_PARAMETER
);
5291 case SMB_QUERY_POSIX_LOCK
:
5293 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5294 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5298 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5300 req
, NT_STATUS_INVALID_PARAMETER
);
5304 /* Copy the lock range data. */
5305 lock_data
= (char *)TALLOC_MEMDUP(
5306 req
, pdata
, total_data
);
5308 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5311 lock_data_count
= total_data
;
5317 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5318 if (*pparams
== NULL
) {
5319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5326 * draft-leach-cifs-v1-spec-02.txt
5327 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5330 * The requested information is placed in the Data portion of the
5331 * transaction response. For the information levels greater than 0x100,
5332 * the transaction response has 1 parameter word which should be
5333 * ignored by the client.
5335 * However Windows only follows this rule for the IS_NAME_VALID call.
5337 switch (info_level
) {
5338 case SMB_INFO_IS_NAME_VALID
:
5343 if ((info_level
& 0xFF00) == 0xFF00) {
5345 * We use levels that start with 0xFF00
5346 * internally to represent SMB2 specific levels
5348 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5352 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5354 delete_pending
, write_time_ts
,
5356 lock_data_count
, lock_data
,
5357 req
->flags2
, max_data_bytes
,
5358 ppdata
, &data_size
);
5359 if (!NT_STATUS_IS_OK(status
)) {
5360 reply_nterror(req
, status
);
5364 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5370 /****************************************************************************
5371 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5373 ****************************************************************************/
5375 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5376 connection_struct
*conn
,
5377 struct smb_request
*req
,
5378 bool overwrite_if_exists
,
5379 const struct smb_filename
*smb_fname_old
,
5380 struct smb_filename
*smb_fname_new
)
5382 NTSTATUS status
= NT_STATUS_OK
;
5384 /* source must already exist. */
5385 if (!VALID_STAT(smb_fname_old
->st
)) {
5386 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5389 if (VALID_STAT(smb_fname_new
->st
)) {
5390 if (overwrite_if_exists
) {
5391 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5392 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5394 status
= unlink_internals(conn
,
5396 FILE_ATTRIBUTE_NORMAL
,
5399 if (!NT_STATUS_IS_OK(status
)) {
5403 /* Disallow if newname already exists. */
5404 return NT_STATUS_OBJECT_NAME_COLLISION
;
5408 /* No links from a directory. */
5409 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5410 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5413 /* Setting a hardlink to/from a stream isn't currently supported. */
5414 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5415 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5416 return NT_STATUS_INVALID_PARAMETER
;
5419 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5420 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5422 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5423 smb_fname_new
->base_name
) != 0) {
5424 status
= map_nt_error_from_unix(errno
);
5425 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5426 nt_errstr(status
), smb_fname_old
->base_name
,
5427 smb_fname_new
->base_name
));
5432 /****************************************************************************
5433 Deal with setting the time from any of the setfilepathinfo functions.
5434 ****************************************************************************/
5436 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5438 const struct smb_filename
*smb_fname
,
5439 struct smb_file_time
*ft
,
5440 bool setting_write_time
)
5442 struct smb_filename smb_fname_base
;
5444 FILE_NOTIFY_CHANGE_LAST_ACCESS
5445 |FILE_NOTIFY_CHANGE_LAST_WRITE
5446 |FILE_NOTIFY_CHANGE_CREATION
;
5448 if (!VALID_STAT(smb_fname
->st
)) {
5449 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5452 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5453 return NT_STATUS_ACCESS_DENIED
;
5456 /* get some defaults (no modifications) if any info is zero or -1. */
5457 if (null_timespec(ft
->create_time
)) {
5458 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5461 if (null_timespec(ft
->atime
)) {
5462 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5465 if (null_timespec(ft
->mtime
)) {
5466 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5469 if (!setting_write_time
) {
5470 /* ft->mtime comes from change time, not write time. */
5471 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5474 /* Ensure the resolution is the correct for
5475 * what we can store on this filesystem. */
5477 round_timespec(conn
->ts_res
, &ft
->create_time
);
5478 round_timespec(conn
->ts_res
, &ft
->ctime
);
5479 round_timespec(conn
->ts_res
, &ft
->atime
);
5480 round_timespec(conn
->ts_res
, &ft
->mtime
);
5482 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5484 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5486 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5487 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5488 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5489 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5491 if (setting_write_time
) {
5493 * This was a Windows setfileinfo on an open file.
5494 * NT does this a lot. We also need to
5495 * set the time here, as it can be read by
5496 * FindFirst/FindNext and with the patch for bug #2045
5497 * in smbd/fileio.c it ensures that this timestamp is
5498 * kept sticky even after a write. We save the request
5499 * away and will set it on file close and after a write. JRA.
5502 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5503 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5506 if (fsp
->base_fsp
) {
5507 set_sticky_write_time_fsp(fsp
->base_fsp
,
5510 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5513 set_sticky_write_time_path(
5514 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5519 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5521 /* Always call ntimes on the base, even if a stream was passed in. */
5522 smb_fname_base
= *smb_fname
;
5523 smb_fname_base
.stream_name
= NULL
;
5525 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5526 return map_nt_error_from_unix(errno
);
5529 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5530 smb_fname
->base_name
);
5531 return NT_STATUS_OK
;
5534 /****************************************************************************
5535 Deal with setting the dosmode from any of the setfilepathinfo functions.
5536 ****************************************************************************/
5538 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5539 const struct smb_filename
*smb_fname
,
5542 struct smb_filename
*smb_fname_base
= NULL
;
5545 if (!VALID_STAT(smb_fname
->st
)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5549 /* Always operate on the base_name, even if a stream was passed in. */
5550 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5551 NULL
, &smb_fname
->st
,
5553 if (!NT_STATUS_IS_OK(status
)) {
5558 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5559 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5561 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5565 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5567 /* check the mode isn't different, before changing it */
5568 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5569 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5570 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5571 (unsigned int)dosmode
));
5573 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5575 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5577 smb_fname_str_dbg(smb_fname_base
),
5579 status
= map_nt_error_from_unix(errno
);
5583 status
= NT_STATUS_OK
;
5585 TALLOC_FREE(smb_fname_base
);
5589 /****************************************************************************
5590 Deal with setting the size from any of the setfilepathinfo functions.
5591 ****************************************************************************/
5593 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5594 struct smb_request
*req
,
5596 const struct smb_filename
*smb_fname
,
5597 const SMB_STRUCT_STAT
*psbuf
,
5599 bool fail_after_createfile
)
5601 NTSTATUS status
= NT_STATUS_OK
;
5602 struct smb_filename
*smb_fname_tmp
= NULL
;
5603 files_struct
*new_fsp
= NULL
;
5605 if (!VALID_STAT(*psbuf
)) {
5606 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5609 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5610 return NT_STATUS_ACCESS_DENIED
;
5613 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5615 if (size
== get_file_size_stat(psbuf
)) {
5616 return NT_STATUS_OK
;
5619 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5620 smb_fname_str_dbg(smb_fname
), (double)size
));
5622 if (fsp
&& fsp
->fh
->fd
!= -1) {
5623 /* Handle based call. */
5624 if (vfs_set_filelen(fsp
, size
) == -1) {
5625 return map_nt_error_from_unix(errno
);
5627 trigger_write_time_update_immediate(fsp
);
5628 return NT_STATUS_OK
;
5631 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5632 if (!NT_STATUS_IS_OK(status
)) {
5636 smb_fname_tmp
->st
= *psbuf
;
5638 status
= SMB_VFS_CREATE_FILE(
5641 0, /* root_dir_fid */
5642 smb_fname_tmp
, /* fname */
5643 FILE_WRITE_DATA
, /* access_mask */
5644 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5646 FILE_OPEN
, /* create_disposition*/
5647 0, /* create_options */
5648 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5649 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5650 0, /* allocation_size */
5651 0, /* private_flags */
5654 &new_fsp
, /* result */
5657 TALLOC_FREE(smb_fname_tmp
);
5659 if (!NT_STATUS_IS_OK(status
)) {
5660 /* NB. We check for open_was_deferred in the caller. */
5664 /* See RAW-SFILEINFO-END-OF-FILE */
5665 if (fail_after_createfile
) {
5666 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5667 return NT_STATUS_INVALID_LEVEL
;
5670 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5671 status
= map_nt_error_from_unix(errno
);
5672 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5676 trigger_write_time_update_immediate(new_fsp
);
5677 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5678 return NT_STATUS_OK
;
5681 /****************************************************************************
5682 Deal with SMB_INFO_SET_EA.
5683 ****************************************************************************/
5685 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5689 const struct smb_filename
*smb_fname
)
5691 struct ea_list
*ea_list
= NULL
;
5692 TALLOC_CTX
*ctx
= NULL
;
5693 NTSTATUS status
= NT_STATUS_OK
;
5695 if (total_data
< 10) {
5697 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5698 length. They seem to have no effect. Bug #3212. JRA */
5700 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5701 /* We're done. We only get EA info in this call. */
5702 return NT_STATUS_OK
;
5705 return NT_STATUS_INVALID_PARAMETER
;
5708 if (IVAL(pdata
,0) > total_data
) {
5709 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5710 IVAL(pdata
,0), (unsigned int)total_data
));
5711 return NT_STATUS_INVALID_PARAMETER
;
5715 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5717 return NT_STATUS_INVALID_PARAMETER
;
5720 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5721 return NT_STATUS_ACCESS_DENIED
;
5724 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5729 /****************************************************************************
5730 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5731 ****************************************************************************/
5733 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5738 struct ea_list
*ea_list
= NULL
;
5742 return NT_STATUS_INVALID_HANDLE
;
5745 if (!lp_ea_support(SNUM(conn
))) {
5746 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5747 "EA's not supported.\n",
5748 (unsigned int)total_data
));
5749 return NT_STATUS_EAS_NOT_SUPPORTED
;
5752 if (total_data
< 10) {
5753 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5755 (unsigned int)total_data
));
5756 return NT_STATUS_INVALID_PARAMETER
;
5759 ea_list
= read_nttrans_ea_list(talloc_tos(),
5764 return NT_STATUS_INVALID_PARAMETER
;
5767 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5768 return NT_STATUS_ACCESS_DENIED
;
5771 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5773 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5774 smb_fname_str_dbg(fsp
->fsp_name
),
5775 nt_errstr(status
) ));
5781 /****************************************************************************
5782 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5783 ****************************************************************************/
5785 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5789 struct smb_filename
*smb_fname
)
5791 NTSTATUS status
= NT_STATUS_OK
;
5792 bool delete_on_close
;
5795 if (total_data
< 1) {
5796 return NT_STATUS_INVALID_PARAMETER
;
5800 return NT_STATUS_INVALID_HANDLE
;
5803 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5804 dosmode
= dos_mode(conn
, smb_fname
);
5806 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5807 "delete_on_close = %u\n",
5808 smb_fname_str_dbg(smb_fname
),
5809 (unsigned int)dosmode
,
5810 (unsigned int)delete_on_close
));
5812 if (delete_on_close
) {
5813 status
= can_set_delete_on_close(fsp
, dosmode
);
5814 if (!NT_STATUS_IS_OK(status
)) {
5819 /* The set is across all open files on this dev/inode pair. */
5820 if (!set_delete_on_close(fsp
, delete_on_close
,
5821 &conn
->session_info
->utok
)) {
5822 return NT_STATUS_ACCESS_DENIED
;
5824 return NT_STATUS_OK
;
5827 /****************************************************************************
5828 Deal with SMB_FILE_POSITION_INFORMATION.
5829 ****************************************************************************/
5831 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5836 uint64_t position_information
;
5838 if (total_data
< 8) {
5839 return NT_STATUS_INVALID_PARAMETER
;
5843 /* Ignore on pathname based set. */
5844 return NT_STATUS_OK
;
5847 position_information
= (uint64_t)IVAL(pdata
,0);
5848 #ifdef LARGE_SMB_OFF_T
5849 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5850 #else /* LARGE_SMB_OFF_T */
5851 if (IVAL(pdata
,4) != 0) {
5852 /* more than 32 bits? */
5853 return NT_STATUS_INVALID_PARAMETER
;
5855 #endif /* LARGE_SMB_OFF_T */
5857 DEBUG(10,("smb_file_position_information: Set file position "
5858 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5859 (double)position_information
));
5860 fsp
->fh
->position_information
= position_information
;
5861 return NT_STATUS_OK
;
5864 /****************************************************************************
5865 Deal with SMB_FILE_MODE_INFORMATION.
5866 ****************************************************************************/
5868 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5874 if (total_data
< 4) {
5875 return NT_STATUS_INVALID_PARAMETER
;
5877 mode
= IVAL(pdata
,0);
5878 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5879 return NT_STATUS_INVALID_PARAMETER
;
5881 return NT_STATUS_OK
;
5884 /****************************************************************************
5885 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5886 ****************************************************************************/
5888 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5889 struct smb_request
*req
,
5892 const struct smb_filename
*smb_fname
)
5894 char *link_target
= NULL
;
5895 const char *newname
= smb_fname
->base_name
;
5896 TALLOC_CTX
*ctx
= talloc_tos();
5898 /* Set a symbolic link. */
5899 /* Don't allow this if follow links is false. */
5901 if (total_data
== 0) {
5902 return NT_STATUS_INVALID_PARAMETER
;
5905 if (!lp_symlinks(SNUM(conn
))) {
5906 return NT_STATUS_ACCESS_DENIED
;
5909 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5910 total_data
, STR_TERMINATE
);
5913 return NT_STATUS_INVALID_PARAMETER
;
5916 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5917 newname
, link_target
));
5919 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5920 return map_nt_error_from_unix(errno
);
5923 return NT_STATUS_OK
;
5926 /****************************************************************************
5927 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5928 ****************************************************************************/
5930 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5931 struct smb_request
*req
,
5932 const char *pdata
, int total_data
,
5933 struct smb_filename
*smb_fname_new
)
5935 char *oldname
= NULL
;
5936 struct smb_filename
*smb_fname_old
= NULL
;
5937 TALLOC_CTX
*ctx
= talloc_tos();
5938 NTSTATUS status
= NT_STATUS_OK
;
5940 /* Set a hard link. */
5941 if (total_data
== 0) {
5942 return NT_STATUS_INVALID_PARAMETER
;
5945 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5946 total_data
, STR_TERMINATE
, &status
);
5947 if (!NT_STATUS_IS_OK(status
)) {
5951 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5952 smb_fname_str_dbg(smb_fname_new
), oldname
));
5954 status
= filename_convert(ctx
,
5956 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5961 if (!NT_STATUS_IS_OK(status
)) {
5965 return hardlink_internals(ctx
, conn
, req
, false,
5966 smb_fname_old
, smb_fname_new
);
5969 /****************************************************************************
5970 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5971 ****************************************************************************/
5973 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5974 struct smb_request
*req
,
5978 struct smb_filename
*smb_fname_src
)
5982 char *newname
= NULL
;
5983 struct smb_filename
*smb_fname_dst
= NULL
;
5984 NTSTATUS status
= NT_STATUS_OK
;
5985 TALLOC_CTX
*ctx
= talloc_tos();
5988 return NT_STATUS_INVALID_HANDLE
;
5991 if (total_data
< 20) {
5992 return NT_STATUS_INVALID_PARAMETER
;
5995 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5996 len
= IVAL(pdata
,16);
5998 if (len
> (total_data
- 20) || (len
== 0)) {
5999 return NT_STATUS_INVALID_PARAMETER
;
6002 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6003 &pdata
[20], len
, STR_TERMINATE
,
6005 if (!NT_STATUS_IS_OK(status
)) {
6009 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6012 status
= filename_convert(ctx
,
6014 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6019 if (!NT_STATUS_IS_OK(status
)) {
6023 if (fsp
->base_fsp
) {
6024 /* newname must be a stream name. */
6025 if (newname
[0] != ':') {
6026 return NT_STATUS_NOT_SUPPORTED
;
6029 /* Create an smb_fname to call rename_internals_fsp() with. */
6030 status
= create_synthetic_smb_fname(talloc_tos(),
6031 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6033 if (!NT_STATUS_IS_OK(status
)) {
6038 * Set the original last component, since
6039 * rename_internals_fsp() requires it.
6041 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6043 if (smb_fname_dst
->original_lcomp
== NULL
) {
6044 status
= NT_STATUS_NO_MEMORY
;
6050 DEBUG(10,("smb2_file_rename_information: "
6051 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6052 fsp
->fnum
, fsp_str_dbg(fsp
),
6053 smb_fname_str_dbg(smb_fname_dst
)));
6054 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6058 TALLOC_FREE(smb_fname_dst
);
6062 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6063 struct smb_request
*req
,
6067 struct smb_filename
*smb_fname_src
)
6071 char *newname
= NULL
;
6072 struct smb_filename
*smb_fname_dst
= NULL
;
6073 NTSTATUS status
= NT_STATUS_OK
;
6074 TALLOC_CTX
*ctx
= talloc_tos();
6077 return NT_STATUS_INVALID_HANDLE
;
6080 if (total_data
< 20) {
6081 return NT_STATUS_INVALID_PARAMETER
;
6084 overwrite
= (CVAL(pdata
,0) ? true : false);
6085 len
= IVAL(pdata
,16);
6087 if (len
> (total_data
- 20) || (len
== 0)) {
6088 return NT_STATUS_INVALID_PARAMETER
;
6091 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6092 &pdata
[20], len
, STR_TERMINATE
,
6094 if (!NT_STATUS_IS_OK(status
)) {
6098 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6101 status
= filename_convert(ctx
,
6103 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6108 if (!NT_STATUS_IS_OK(status
)) {
6112 if (fsp
->base_fsp
) {
6113 /* No stream names. */
6114 return NT_STATUS_NOT_SUPPORTED
;
6117 DEBUG(10,("smb_file_link_information: "
6118 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6119 fsp
->fnum
, fsp_str_dbg(fsp
),
6120 smb_fname_str_dbg(smb_fname_dst
)));
6121 status
= hardlink_internals(ctx
,
6128 TALLOC_FREE(smb_fname_dst
);
6132 /****************************************************************************
6133 Deal with SMB_FILE_RENAME_INFORMATION.
6134 ****************************************************************************/
6136 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6137 struct smb_request
*req
,
6141 struct smb_filename
*smb_fname_src
)
6146 char *newname
= NULL
;
6147 struct smb_filename
*smb_fname_dst
= NULL
;
6148 bool dest_has_wcard
= False
;
6149 NTSTATUS status
= NT_STATUS_OK
;
6151 TALLOC_CTX
*ctx
= talloc_tos();
6153 if (total_data
< 13) {
6154 return NT_STATUS_INVALID_PARAMETER
;
6157 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6158 root_fid
= IVAL(pdata
,4);
6159 len
= IVAL(pdata
,8);
6161 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6162 return NT_STATUS_INVALID_PARAMETER
;
6165 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6168 if (!NT_STATUS_IS_OK(status
)) {
6172 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6175 status
= resolve_dfspath_wcard(ctx
, conn
,
6176 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6181 if (!NT_STATUS_IS_OK(status
)) {
6185 /* Check the new name has no '/' characters. */
6186 if (strchr_m(newname
, '/')) {
6187 return NT_STATUS_NOT_SUPPORTED
;
6190 if (fsp
&& fsp
->base_fsp
) {
6191 /* newname must be a stream name. */
6192 if (newname
[0] != ':') {
6193 return NT_STATUS_NOT_SUPPORTED
;
6196 /* Create an smb_fname to call rename_internals_fsp() with. */
6197 status
= create_synthetic_smb_fname(talloc_tos(),
6198 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6200 if (!NT_STATUS_IS_OK(status
)) {
6205 * Set the original last component, since
6206 * rename_internals_fsp() requires it.
6208 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6210 if (smb_fname_dst
->original_lcomp
== NULL
) {
6211 status
= NT_STATUS_NO_MEMORY
;
6217 * Build up an smb_fname_dst based on the filename passed in.
6218 * We basically just strip off the last component, and put on
6219 * the newname instead.
6221 char *base_name
= NULL
;
6223 /* newname must *not* be a stream name. */
6224 if (newname
[0] == ':') {
6225 return NT_STATUS_NOT_SUPPORTED
;
6229 * Strip off the last component (filename) of the path passed
6232 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6234 return NT_STATUS_NO_MEMORY
;
6236 p
= strrchr_m(base_name
, '/');
6240 base_name
= talloc_strdup(ctx
, "");
6242 return NT_STATUS_NO_MEMORY
;
6245 /* Append the new name. */
6246 base_name
= talloc_asprintf_append(base_name
,
6250 return NT_STATUS_NO_MEMORY
;
6253 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6256 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6259 /* If an error we expect this to be
6260 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6262 if (!NT_STATUS_IS_OK(status
)) {
6263 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6267 /* Create an smb_fname to call rename_internals_fsp() */
6268 status
= create_synthetic_smb_fname(ctx
,
6272 if (!NT_STATUS_IS_OK(status
)) {
6279 DEBUG(10,("smb_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6281 fsp
->fnum
, fsp_str_dbg(fsp
),
6282 smb_fname_str_dbg(smb_fname_dst
)));
6283 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6286 DEBUG(10,("smb_file_rename_information: "
6287 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6288 smb_fname_str_dbg(smb_fname_src
),
6289 smb_fname_str_dbg(smb_fname_dst
)));
6290 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6291 smb_fname_dst
, 0, overwrite
, false,
6293 FILE_WRITE_ATTRIBUTES
);
6296 TALLOC_FREE(smb_fname_dst
);
6300 /****************************************************************************
6301 Deal with SMB_SET_POSIX_ACL.
6302 ****************************************************************************/
6304 #if defined(HAVE_POSIX_ACLS)
6305 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6309 const struct smb_filename
*smb_fname
)
6311 uint16 posix_acl_version
;
6312 uint16 num_file_acls
;
6313 uint16 num_def_acls
;
6314 bool valid_file_acls
= True
;
6315 bool valid_def_acls
= True
;
6317 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6318 return NT_STATUS_INVALID_PARAMETER
;
6320 posix_acl_version
= SVAL(pdata
,0);
6321 num_file_acls
= SVAL(pdata
,2);
6322 num_def_acls
= SVAL(pdata
,4);
6324 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6325 valid_file_acls
= False
;
6329 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6330 valid_def_acls
= False
;
6334 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6335 return NT_STATUS_INVALID_PARAMETER
;
6338 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6339 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6340 return NT_STATUS_INVALID_PARAMETER
;
6343 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6344 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6345 (unsigned int)num_file_acls
,
6346 (unsigned int)num_def_acls
));
6348 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6349 smb_fname
->base_name
, num_file_acls
,
6350 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6351 return map_nt_error_from_unix(errno
);
6354 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6355 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6356 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6357 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6358 return map_nt_error_from_unix(errno
);
6360 return NT_STATUS_OK
;
6364 /****************************************************************************
6365 Deal with SMB_SET_POSIX_LOCK.
6366 ****************************************************************************/
6368 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6369 struct smb_request
*req
,
6377 bool blocking_lock
= False
;
6378 enum brl_type lock_type
;
6380 NTSTATUS status
= NT_STATUS_OK
;
6382 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6383 return NT_STATUS_INVALID_HANDLE
;
6386 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6387 return NT_STATUS_INVALID_PARAMETER
;
6390 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6391 case POSIX_LOCK_TYPE_READ
:
6392 lock_type
= READ_LOCK
;
6394 case POSIX_LOCK_TYPE_WRITE
:
6395 /* Return the right POSIX-mappable error code for files opened read-only. */
6396 if (!fsp
->can_write
) {
6397 return NT_STATUS_INVALID_HANDLE
;
6399 lock_type
= WRITE_LOCK
;
6401 case POSIX_LOCK_TYPE_UNLOCK
:
6402 lock_type
= UNLOCK_LOCK
;
6405 return NT_STATUS_INVALID_PARAMETER
;
6408 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6409 blocking_lock
= False
;
6410 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6411 blocking_lock
= True
;
6413 return NT_STATUS_INVALID_PARAMETER
;
6416 if (!lp_blocking_locks(SNUM(conn
))) {
6417 blocking_lock
= False
;
6420 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6421 #if defined(HAVE_LONGLONG)
6422 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6423 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6424 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6425 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6426 #else /* HAVE_LONGLONG */
6427 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6428 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6429 #endif /* HAVE_LONGLONG */
6431 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6432 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6434 (unsigned int)lock_type
,
6435 (unsigned long long)smblctx
,
6439 if (lock_type
== UNLOCK_LOCK
) {
6440 status
= do_unlock(req
->sconn
->msg_ctx
,
6447 uint64_t block_smblctx
;
6449 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6461 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6463 * A blocking lock was requested. Package up
6464 * this smb into a queued request and push it
6465 * onto the blocking lock queue.
6467 if(push_blocking_lock_request(br_lck
,
6470 -1, /* infinite timeout. */
6478 TALLOC_FREE(br_lck
);
6482 TALLOC_FREE(br_lck
);
6488 /****************************************************************************
6489 Deal with SMB_SET_FILE_BASIC_INFO.
6490 ****************************************************************************/
6492 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6496 const struct smb_filename
*smb_fname
)
6498 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6499 struct smb_file_time ft
;
6501 NTSTATUS status
= NT_STATUS_OK
;
6505 if (total_data
< 36) {
6506 return NT_STATUS_INVALID_PARAMETER
;
6509 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6510 return NT_STATUS_ACCESS_DENIED
;
6513 /* Set the attributes */
6514 dosmode
= IVAL(pdata
,32);
6515 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6516 if (!NT_STATUS_IS_OK(status
)) {
6521 ft
.create_time
= interpret_long_date(pdata
);
6524 ft
.atime
= interpret_long_date(pdata
+8);
6527 ft
.mtime
= interpret_long_date(pdata
+16);
6530 ft
.ctime
= interpret_long_date(pdata
+24);
6532 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6533 smb_fname_str_dbg(smb_fname
)));
6535 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6539 /****************************************************************************
6540 Deal with SMB_INFO_STANDARD.
6541 ****************************************************************************/
6543 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6547 const struct smb_filename
*smb_fname
)
6549 struct smb_file_time ft
;
6553 if (total_data
< 12) {
6554 return NT_STATUS_INVALID_PARAMETER
;
6557 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6558 return NT_STATUS_ACCESS_DENIED
;
6562 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6564 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6566 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6568 DEBUG(10,("smb_set_info_standard: file %s\n",
6569 smb_fname_str_dbg(smb_fname
)));
6571 return smb_set_file_time(conn
,
6578 /****************************************************************************
6579 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6580 ****************************************************************************/
6582 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6583 struct smb_request
*req
,
6587 struct smb_filename
*smb_fname
)
6589 uint64_t allocation_size
= 0;
6590 NTSTATUS status
= NT_STATUS_OK
;
6591 files_struct
*new_fsp
= NULL
;
6593 if (!VALID_STAT(smb_fname
->st
)) {
6594 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6597 if (total_data
< 8) {
6598 return NT_STATUS_INVALID_PARAMETER
;
6601 allocation_size
= (uint64_t)IVAL(pdata
,0);
6602 #ifdef LARGE_SMB_OFF_T
6603 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6604 #else /* LARGE_SMB_OFF_T */
6605 if (IVAL(pdata
,4) != 0) {
6606 /* more than 32 bits? */
6607 return NT_STATUS_INVALID_PARAMETER
;
6609 #endif /* LARGE_SMB_OFF_T */
6611 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6612 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6613 (double)allocation_size
));
6615 if (allocation_size
) {
6616 allocation_size
= smb_roundup(conn
, allocation_size
);
6619 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6620 return NT_STATUS_ACCESS_DENIED
;
6623 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6624 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6625 (double)allocation_size
));
6627 if (fsp
&& fsp
->fh
->fd
!= -1) {
6628 /* Open file handle. */
6629 /* Only change if needed. */
6630 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6631 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6632 return map_nt_error_from_unix(errno
);
6635 /* But always update the time. */
6637 * This is equivalent to a write. Ensure it's seen immediately
6638 * if there are no pending writes.
6640 trigger_write_time_update_immediate(fsp
);
6641 return NT_STATUS_OK
;
6644 /* Pathname or stat or directory file. */
6645 status
= SMB_VFS_CREATE_FILE(
6648 0, /* root_dir_fid */
6649 smb_fname
, /* fname */
6650 FILE_WRITE_DATA
, /* access_mask */
6651 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6653 FILE_OPEN
, /* create_disposition*/
6654 0, /* create_options */
6655 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6656 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6657 0, /* allocation_size */
6658 0, /* private_flags */
6661 &new_fsp
, /* result */
6664 if (!NT_STATUS_IS_OK(status
)) {
6665 /* NB. We check for open_was_deferred in the caller. */
6669 /* Only change if needed. */
6670 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6671 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6672 status
= map_nt_error_from_unix(errno
);
6673 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6678 /* Changing the allocation size should set the last mod time. */
6680 * This is equivalent to a write. Ensure it's seen immediately
6681 * if there are no pending writes.
6683 trigger_write_time_update_immediate(new_fsp
);
6685 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6686 return NT_STATUS_OK
;
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6694 struct smb_request
*req
,
6698 const struct smb_filename
*smb_fname
,
6699 bool fail_after_createfile
)
6703 if (total_data
< 8) {
6704 return NT_STATUS_INVALID_PARAMETER
;
6707 size
= IVAL(pdata
,0);
6708 #ifdef LARGE_SMB_OFF_T
6709 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6710 #else /* LARGE_SMB_OFF_T */
6711 if (IVAL(pdata
,4) != 0) {
6712 /* more than 32 bits? */
6713 return NT_STATUS_INVALID_PARAMETER
;
6715 #endif /* LARGE_SMB_OFF_T */
6716 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6717 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6720 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6721 return NT_STATUS_ACCESS_DENIED
;
6724 return smb_set_file_size(conn
, req
,
6729 fail_after_createfile
);
6732 /****************************************************************************
6733 Allow a UNIX info mknod.
6734 ****************************************************************************/
6736 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6739 const struct smb_filename
*smb_fname
)
6741 uint32 file_type
= IVAL(pdata
,56);
6742 #if defined(HAVE_MAKEDEV)
6743 uint32 dev_major
= IVAL(pdata
,60);
6744 uint32 dev_minor
= IVAL(pdata
,68);
6746 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6747 uint32 raw_unixmode
= IVAL(pdata
,84);
6751 if (total_data
< 100) {
6752 return NT_STATUS_INVALID_PARAMETER
;
6755 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6756 PERM_NEW_FILE
, &unixmode
);
6757 if (!NT_STATUS_IS_OK(status
)) {
6761 #if defined(HAVE_MAKEDEV)
6762 dev
= makedev(dev_major
, dev_minor
);
6765 switch (file_type
) {
6766 #if defined(S_IFIFO)
6767 case UNIX_TYPE_FIFO
:
6768 unixmode
|= S_IFIFO
;
6771 #if defined(S_IFSOCK)
6772 case UNIX_TYPE_SOCKET
:
6773 unixmode
|= S_IFSOCK
;
6776 #if defined(S_IFCHR)
6777 case UNIX_TYPE_CHARDEV
:
6778 unixmode
|= S_IFCHR
;
6781 #if defined(S_IFBLK)
6782 case UNIX_TYPE_BLKDEV
:
6783 unixmode
|= S_IFBLK
;
6787 return NT_STATUS_INVALID_PARAMETER
;
6790 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6791 "%.0f mode 0%o for file %s\n", (double)dev
,
6792 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6794 /* Ok - do the mknod. */
6795 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6796 return map_nt_error_from_unix(errno
);
6799 /* If any of the other "set" calls fail we
6800 * don't want to end up with a half-constructed mknod.
6803 if (lp_inherit_perms(SNUM(conn
))) {
6805 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6807 return NT_STATUS_NO_MEMORY
;
6809 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6811 TALLOC_FREE(parent
);
6814 return NT_STATUS_OK
;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_UNIX_BASIC.
6819 ****************************************************************************/
6821 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6822 struct smb_request
*req
,
6826 const struct smb_filename
*smb_fname
)
6828 struct smb_file_time ft
;
6829 uint32 raw_unixmode
;
6832 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6833 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6834 NTSTATUS status
= NT_STATUS_OK
;
6835 bool delete_on_fail
= False
;
6836 enum perm_type ptype
;
6837 files_struct
*all_fsps
= NULL
;
6838 bool modify_mtime
= true;
6840 struct smb_filename
*smb_fname_tmp
= NULL
;
6841 SMB_STRUCT_STAT sbuf
;
6845 if (total_data
< 100) {
6846 return NT_STATUS_INVALID_PARAMETER
;
6849 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6850 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6851 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6852 #ifdef LARGE_SMB_OFF_T
6853 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6854 #else /* LARGE_SMB_OFF_T */
6855 if (IVAL(pdata
,4) != 0) {
6856 /* more than 32 bits? */
6857 return NT_STATUS_INVALID_PARAMETER
;
6859 #endif /* LARGE_SMB_OFF_T */
6862 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6863 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6864 set_owner
= (uid_t
)IVAL(pdata
,40);
6865 set_grp
= (gid_t
)IVAL(pdata
,48);
6866 raw_unixmode
= IVAL(pdata
,84);
6868 if (VALID_STAT(smb_fname
->st
)) {
6869 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6870 ptype
= PERM_EXISTING_DIR
;
6872 ptype
= PERM_EXISTING_FILE
;
6875 ptype
= PERM_NEW_FILE
;
6878 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6880 if (!NT_STATUS_IS_OK(status
)) {
6884 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6885 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6886 smb_fname_str_dbg(smb_fname
), (double)size
,
6887 (unsigned int)set_owner
, (unsigned int)set_grp
,
6888 (int)raw_unixmode
));
6890 sbuf
= smb_fname
->st
;
6892 if (!VALID_STAT(sbuf
)) {
6894 * The only valid use of this is to create character and block
6895 * devices, and named pipes. This is deprecated (IMHO) and
6896 * a new info level should be used for mknod. JRA.
6899 status
= smb_unix_mknod(conn
,
6903 if (!NT_STATUS_IS_OK(status
)) {
6907 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6909 if (!NT_STATUS_IS_OK(status
)) {
6913 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6914 status
= map_nt_error_from_unix(errno
);
6915 TALLOC_FREE(smb_fname_tmp
);
6916 SMB_VFS_UNLINK(conn
, smb_fname
);
6920 sbuf
= smb_fname_tmp
->st
;
6921 smb_fname
= smb_fname_tmp
;
6923 /* Ensure we don't try and change anything else. */
6924 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6925 size
= get_file_size_stat(&sbuf
);
6926 ft
.atime
= sbuf
.st_ex_atime
;
6927 ft
.mtime
= sbuf
.st_ex_mtime
;
6929 * We continue here as we might want to change the
6932 delete_on_fail
= True
;
6936 /* Horrible backwards compatibility hack as an old server bug
6937 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6941 size
= get_file_size_stat(&sbuf
);
6946 * Deal with the UNIX specific mode set.
6949 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6950 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6951 "setting mode 0%o for file %s\n",
6952 (unsigned int)unixmode
,
6953 smb_fname_str_dbg(smb_fname
)));
6954 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6955 return map_nt_error_from_unix(errno
);
6960 * Deal with the UNIX specific uid set.
6963 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6964 (sbuf
.st_ex_uid
!= set_owner
)) {
6967 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6968 "changing owner %u for path %s\n",
6969 (unsigned int)set_owner
,
6970 smb_fname_str_dbg(smb_fname
)));
6972 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6973 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6974 set_owner
, (gid_t
)-1);
6976 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6977 set_owner
, (gid_t
)-1);
6981 status
= map_nt_error_from_unix(errno
);
6982 if (delete_on_fail
) {
6983 SMB_VFS_UNLINK(conn
, smb_fname
);
6990 * Deal with the UNIX specific gid set.
6993 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6994 (sbuf
.st_ex_gid
!= set_grp
)) {
6995 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6996 "changing group %u for file %s\n",
6997 (unsigned int)set_owner
,
6998 smb_fname_str_dbg(smb_fname
)));
6999 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7001 status
= map_nt_error_from_unix(errno
);
7002 if (delete_on_fail
) {
7003 SMB_VFS_UNLINK(conn
, smb_fname
);
7009 /* Deal with any size changes. */
7011 status
= smb_set_file_size(conn
, req
,
7017 if (!NT_STATUS_IS_OK(status
)) {
7021 /* Deal with any time changes. */
7022 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7023 /* No change, don't cancel anything. */
7027 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7028 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7029 all_fsps
= file_find_di_next(all_fsps
)) {
7031 * We're setting the time explicitly for UNIX.
7032 * Cancel any pending changes over all handles.
7034 all_fsps
->update_write_time_on_close
= false;
7035 TALLOC_FREE(all_fsps
->update_write_time_event
);
7039 * Override the "setting_write_time"
7040 * parameter here as it almost does what
7041 * we need. Just remember if we modified
7042 * mtime and send the notify ourselves.
7044 if (null_timespec(ft
.mtime
)) {
7045 modify_mtime
= false;
7048 status
= smb_set_file_time(conn
,
7054 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7055 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7060 /****************************************************************************
7061 Deal with SMB_SET_FILE_UNIX_INFO2.
7062 ****************************************************************************/
7064 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7065 struct smb_request
*req
,
7069 const struct smb_filename
*smb_fname
)
7075 if (total_data
< 116) {
7076 return NT_STATUS_INVALID_PARAMETER
;
7079 /* Start by setting all the fields that are common between UNIX_BASIC
7082 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7084 if (!NT_STATUS_IS_OK(status
)) {
7088 smb_fflags
= IVAL(pdata
, 108);
7089 smb_fmask
= IVAL(pdata
, 112);
7091 /* NB: We should only attempt to alter the file flags if the client
7092 * sends a non-zero mask.
7094 if (smb_fmask
!= 0) {
7095 int stat_fflags
= 0;
7097 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7098 smb_fmask
, &stat_fflags
)) {
7099 /* Client asked to alter a flag we don't understand. */
7100 return NT_STATUS_INVALID_PARAMETER
;
7103 if (fsp
&& fsp
->fh
->fd
!= -1) {
7104 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7105 return NT_STATUS_NOT_SUPPORTED
;
7107 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7108 stat_fflags
) != 0) {
7109 return map_nt_error_from_unix(errno
);
7114 /* XXX: need to add support for changing the create_time here. You
7115 * can do this for paths on Darwin with setattrlist(2). The right way
7116 * to hook this up is probably by extending the VFS utimes interface.
7119 return NT_STATUS_OK
;
7122 /****************************************************************************
7123 Create a directory with POSIX semantics.
7124 ****************************************************************************/
7126 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7127 struct smb_request
*req
,
7130 struct smb_filename
*smb_fname
,
7131 int *pdata_return_size
)
7133 NTSTATUS status
= NT_STATUS_OK
;
7134 uint32 raw_unixmode
= 0;
7135 uint32 mod_unixmode
= 0;
7136 mode_t unixmode
= (mode_t
)0;
7137 files_struct
*fsp
= NULL
;
7138 uint16 info_level_return
= 0;
7140 char *pdata
= *ppdata
;
7142 if (total_data
< 18) {
7143 return NT_STATUS_INVALID_PARAMETER
;
7146 raw_unixmode
= IVAL(pdata
,8);
7147 /* Next 4 bytes are not yet defined. */
7149 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7150 PERM_NEW_DIR
, &unixmode
);
7151 if (!NT_STATUS_IS_OK(status
)) {
7155 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7157 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7158 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7160 status
= SMB_VFS_CREATE_FILE(
7163 0, /* root_dir_fid */
7164 smb_fname
, /* fname */
7165 FILE_READ_ATTRIBUTES
, /* access_mask */
7166 FILE_SHARE_NONE
, /* share_access */
7167 FILE_CREATE
, /* create_disposition*/
7168 FILE_DIRECTORY_FILE
, /* create_options */
7169 mod_unixmode
, /* file_attributes */
7170 0, /* oplock_request */
7171 0, /* allocation_size */
7172 0, /* private_flags */
7178 if (NT_STATUS_IS_OK(status
)) {
7179 close_file(req
, fsp
, NORMAL_CLOSE
);
7182 info_level_return
= SVAL(pdata
,16);
7184 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7185 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7186 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7187 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7189 *pdata_return_size
= 12;
7192 /* Realloc the data size */
7193 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7194 if (*ppdata
== NULL
) {
7195 *pdata_return_size
= 0;
7196 return NT_STATUS_NO_MEMORY
;
7200 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7201 SSVAL(pdata
,2,0); /* No fnum. */
7202 SIVAL(pdata
,4,info
); /* Was directory created. */
7204 switch (info_level_return
) {
7205 case SMB_QUERY_FILE_UNIX_BASIC
:
7206 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7207 SSVAL(pdata
,10,0); /* Padding. */
7208 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7211 case SMB_QUERY_FILE_UNIX_INFO2
:
7212 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7213 SSVAL(pdata
,10,0); /* Padding. */
7214 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7218 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7219 SSVAL(pdata
,10,0); /* Padding. */
7226 /****************************************************************************
7227 Open/Create a file with POSIX semantics.
7228 ****************************************************************************/
7230 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7231 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7233 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7234 struct smb_request
*req
,
7237 struct smb_filename
*smb_fname
,
7238 int *pdata_return_size
)
7240 bool extended_oplock_granted
= False
;
7241 char *pdata
= *ppdata
;
7243 uint32 wire_open_mode
= 0;
7244 uint32 raw_unixmode
= 0;
7245 uint32 mod_unixmode
= 0;
7246 uint32 create_disp
= 0;
7247 uint32 access_mask
= 0;
7248 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7249 NTSTATUS status
= NT_STATUS_OK
;
7250 mode_t unixmode
= (mode_t
)0;
7251 files_struct
*fsp
= NULL
;
7252 int oplock_request
= 0;
7254 uint16 info_level_return
= 0;
7256 if (total_data
< 18) {
7257 return NT_STATUS_INVALID_PARAMETER
;
7260 flags
= IVAL(pdata
,0);
7261 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7262 if (oplock_request
) {
7263 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7266 wire_open_mode
= IVAL(pdata
,4);
7268 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7269 return smb_posix_mkdir(conn
, req
,
7276 switch (wire_open_mode
& SMB_ACCMODE
) {
7278 access_mask
= SMB_O_RDONLY_MAPPING
;
7281 access_mask
= SMB_O_WRONLY_MAPPING
;
7284 access_mask
= (SMB_O_RDONLY_MAPPING
|
7285 SMB_O_WRONLY_MAPPING
);
7288 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7289 (unsigned int)wire_open_mode
));
7290 return NT_STATUS_INVALID_PARAMETER
;
7293 wire_open_mode
&= ~SMB_ACCMODE
;
7295 /* First take care of O_CREAT|O_EXCL interactions. */
7296 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7297 case (SMB_O_CREAT
| SMB_O_EXCL
):
7298 /* File exists fail. File not exist create. */
7299 create_disp
= FILE_CREATE
;
7302 /* File exists open. File not exist create. */
7303 create_disp
= FILE_OPEN_IF
;
7306 /* File exists open. File not exist fail. */
7307 create_disp
= FILE_OPEN
;
7310 /* O_EXCL on its own without O_CREAT is undefined. */
7312 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7313 (unsigned int)wire_open_mode
));
7314 return NT_STATUS_INVALID_PARAMETER
;
7317 /* Next factor in the effects of O_TRUNC. */
7318 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7320 if (wire_open_mode
& SMB_O_TRUNC
) {
7321 switch (create_disp
) {
7323 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7324 /* Leave create_disp alone as
7325 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7327 /* File exists fail. File not exist create. */
7330 /* SMB_O_CREAT | SMB_O_TRUNC */
7331 /* File exists overwrite. File not exist create. */
7332 create_disp
= FILE_OVERWRITE_IF
;
7336 /* File exists overwrite. File not exist fail. */
7337 create_disp
= FILE_OVERWRITE
;
7340 /* Cannot get here. */
7341 smb_panic("smb_posix_open: logic error");
7342 return NT_STATUS_INVALID_PARAMETER
;
7346 raw_unixmode
= IVAL(pdata
,8);
7347 /* Next 4 bytes are not yet defined. */
7349 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7350 (VALID_STAT(smb_fname
->st
) ?
7351 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7354 if (!NT_STATUS_IS_OK(status
)) {
7358 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7360 if (wire_open_mode
& SMB_O_SYNC
) {
7361 create_options
|= FILE_WRITE_THROUGH
;
7363 if (wire_open_mode
& SMB_O_APPEND
) {
7364 access_mask
|= FILE_APPEND_DATA
;
7366 if (wire_open_mode
& SMB_O_DIRECT
) {
7367 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7370 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7371 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7372 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7373 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7375 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7376 create_options
|= FILE_DIRECTORY_FILE
;
7379 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7380 smb_fname_str_dbg(smb_fname
),
7381 (unsigned int)wire_open_mode
,
7382 (unsigned int)unixmode
));
7384 status
= SMB_VFS_CREATE_FILE(
7387 0, /* root_dir_fid */
7388 smb_fname
, /* fname */
7389 access_mask
, /* access_mask */
7390 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7392 create_disp
, /* create_disposition*/
7393 create_options
, /* create_options */
7394 mod_unixmode
, /* file_attributes */
7395 oplock_request
, /* oplock_request */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7403 if (!NT_STATUS_IS_OK(status
)) {
7407 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7408 extended_oplock_granted
= True
;
7411 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7412 extended_oplock_granted
= True
;
7415 info_level_return
= SVAL(pdata
,16);
7417 /* Allocate the correct return size. */
7419 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7420 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7421 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7422 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7424 *pdata_return_size
= 12;
7427 /* Realloc the data size */
7428 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7429 if (*ppdata
== NULL
) {
7430 close_file(req
, fsp
, ERROR_CLOSE
);
7431 *pdata_return_size
= 0;
7432 return NT_STATUS_NO_MEMORY
;
7436 if (extended_oplock_granted
) {
7437 if (flags
& REQUEST_BATCH_OPLOCK
) {
7438 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7440 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7442 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7443 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7445 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7448 SSVAL(pdata
,2,fsp
->fnum
);
7449 SIVAL(pdata
,4,info
); /* Was file created etc. */
7451 switch (info_level_return
) {
7452 case SMB_QUERY_FILE_UNIX_BASIC
:
7453 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7454 SSVAL(pdata
,10,0); /* padding. */
7455 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7458 case SMB_QUERY_FILE_UNIX_INFO2
:
7459 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7460 SSVAL(pdata
,10,0); /* padding. */
7461 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7465 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7466 SSVAL(pdata
,10,0); /* padding. */
7469 return NT_STATUS_OK
;
7472 /****************************************************************************
7473 Delete a file with POSIX semantics.
7474 ****************************************************************************/
7476 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7477 struct smb_request
*req
,
7480 struct smb_filename
*smb_fname
)
7482 NTSTATUS status
= NT_STATUS_OK
;
7483 files_struct
*fsp
= NULL
;
7487 int create_options
= 0;
7489 struct share_mode_lock
*lck
= NULL
;
7491 if (total_data
< 2) {
7492 return NT_STATUS_INVALID_PARAMETER
;
7495 flags
= SVAL(pdata
,0);
7497 if (!VALID_STAT(smb_fname
->st
)) {
7498 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7501 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7502 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7503 return NT_STATUS_NOT_A_DIRECTORY
;
7506 DEBUG(10,("smb_posix_unlink: %s %s\n",
7507 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7508 smb_fname_str_dbg(smb_fname
)));
7510 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7511 create_options
|= FILE_DIRECTORY_FILE
;
7514 status
= SMB_VFS_CREATE_FILE(
7517 0, /* root_dir_fid */
7518 smb_fname
, /* fname */
7519 DELETE_ACCESS
, /* access_mask */
7520 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7522 FILE_OPEN
, /* create_disposition*/
7523 create_options
, /* create_options */
7524 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7525 0, /* oplock_request */
7526 0, /* allocation_size */
7527 0, /* private_flags */
7533 if (!NT_STATUS_IS_OK(status
)) {
7538 * Don't lie to client. If we can't really delete due to
7539 * non-POSIX opens return SHARING_VIOLATION.
7542 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7545 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7546 "lock for file %s\n", fsp_str_dbg(fsp
)));
7547 close_file(req
, fsp
, NORMAL_CLOSE
);
7548 return NT_STATUS_INVALID_PARAMETER
;
7552 * See if others still have the file open. If this is the case, then
7553 * don't delete. If all opens are POSIX delete we can set the delete
7554 * on close disposition.
7556 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7557 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7558 if (is_valid_share_mode_entry(e
)) {
7559 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7562 /* Fail with sharing violation. */
7563 close_file(req
, fsp
, NORMAL_CLOSE
);
7565 return NT_STATUS_SHARING_VIOLATION
;
7570 * Set the delete on close.
7572 status
= smb_set_file_disposition_info(conn
,
7578 if (!NT_STATUS_IS_OK(status
)) {
7579 close_file(req
, fsp
, NORMAL_CLOSE
);
7584 return close_file(req
, fsp
, NORMAL_CLOSE
);
7587 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7588 struct smb_request
*req
,
7589 TALLOC_CTX
*mem_ctx
,
7590 uint16_t info_level
,
7592 struct smb_filename
*smb_fname
,
7593 char **ppdata
, int total_data
,
7596 char *pdata
= *ppdata
;
7597 NTSTATUS status
= NT_STATUS_OK
;
7598 int data_return_size
= 0;
7602 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7603 return NT_STATUS_INVALID_LEVEL
;
7606 if (!CAN_WRITE(conn
)) {
7607 /* Allow POSIX opens. The open path will deny
7608 * any non-readonly opens. */
7609 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7610 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7614 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7615 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7616 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7618 switch (info_level
) {
7620 case SMB_INFO_STANDARD
:
7622 status
= smb_set_info_standard(conn
,
7630 case SMB_INFO_SET_EA
:
7632 status
= smb_info_set_ea(conn
,
7640 case SMB_SET_FILE_BASIC_INFO
:
7641 case SMB_FILE_BASIC_INFORMATION
:
7643 status
= smb_set_file_basic_info(conn
,
7651 case SMB_FILE_ALLOCATION_INFORMATION
:
7652 case SMB_SET_FILE_ALLOCATION_INFO
:
7654 status
= smb_set_file_allocation_info(conn
, req
,
7662 case SMB_FILE_END_OF_FILE_INFORMATION
:
7663 case SMB_SET_FILE_END_OF_FILE_INFO
:
7666 * XP/Win7 both fail after the createfile with
7667 * SMB_SET_FILE_END_OF_FILE_INFO but not
7668 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7669 * The level is known here, so pass it down
7673 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7675 status
= smb_set_file_end_of_file_info(conn
, req
,
7684 case SMB_FILE_DISPOSITION_INFORMATION
:
7685 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7688 /* JRA - We used to just ignore this on a path ?
7689 * Shouldn't this be invalid level on a pathname
7692 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7693 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7696 status
= smb_set_file_disposition_info(conn
,
7704 case SMB_FILE_POSITION_INFORMATION
:
7706 status
= smb_file_position_information(conn
,
7713 case SMB_FILE_FULL_EA_INFORMATION
:
7715 status
= smb_set_file_full_ea_info(conn
,
7722 /* From tridge Samba4 :
7723 * MODE_INFORMATION in setfileinfo (I have no
7724 * idea what "mode information" on a file is - it takes a value of 0,
7725 * 2, 4 or 6. What could it be?).
7728 case SMB_FILE_MODE_INFORMATION
:
7730 status
= smb_file_mode_information(conn
,
7737 * CIFS UNIX extensions.
7740 case SMB_SET_FILE_UNIX_BASIC
:
7742 status
= smb_set_file_unix_basic(conn
, req
,
7750 case SMB_SET_FILE_UNIX_INFO2
:
7752 status
= smb_set_file_unix_info2(conn
, req
,
7760 case SMB_SET_FILE_UNIX_LINK
:
7763 /* We must have a pathname for this. */
7764 return NT_STATUS_INVALID_LEVEL
;
7766 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7767 total_data
, smb_fname
);
7771 case SMB_SET_FILE_UNIX_HLINK
:
7774 /* We must have a pathname for this. */
7775 return NT_STATUS_INVALID_LEVEL
;
7777 status
= smb_set_file_unix_hlink(conn
, req
,
7783 case SMB_FILE_RENAME_INFORMATION
:
7785 status
= smb_file_rename_information(conn
, req
,
7791 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7793 /* SMB2 rename information. */
7794 status
= smb2_file_rename_information(conn
, req
,
7800 case SMB_FILE_LINK_INFORMATION
:
7802 status
= smb_file_link_information(conn
, req
,
7808 #if defined(HAVE_POSIX_ACLS)
7809 case SMB_SET_POSIX_ACL
:
7811 status
= smb_set_posix_acl(conn
,
7820 case SMB_SET_POSIX_LOCK
:
7823 return NT_STATUS_INVALID_LEVEL
;
7825 status
= smb_set_posix_lock(conn
, req
,
7826 pdata
, total_data
, fsp
);
7830 case SMB_POSIX_PATH_OPEN
:
7833 /* We must have a pathname for this. */
7834 return NT_STATUS_INVALID_LEVEL
;
7837 status
= smb_posix_open(conn
, req
,
7845 case SMB_POSIX_PATH_UNLINK
:
7848 /* We must have a pathname for this. */
7849 return NT_STATUS_INVALID_LEVEL
;
7852 status
= smb_posix_unlink(conn
, req
,
7860 return NT_STATUS_INVALID_LEVEL
;
7863 if (!NT_STATUS_IS_OK(status
)) {
7867 *ret_data_size
= data_return_size
;
7868 return NT_STATUS_OK
;
7871 /****************************************************************************
7872 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7873 ****************************************************************************/
7875 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7876 struct smb_request
*req
,
7877 unsigned int tran_call
,
7878 char **pparams
, int total_params
,
7879 char **ppdata
, int total_data
,
7880 unsigned int max_data_bytes
)
7882 char *params
= *pparams
;
7883 char *pdata
= *ppdata
;
7885 struct smb_filename
*smb_fname
= NULL
;
7886 files_struct
*fsp
= NULL
;
7887 NTSTATUS status
= NT_STATUS_OK
;
7888 int data_return_size
= 0;
7891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7895 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7896 if (total_params
< 4) {
7897 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7901 fsp
= file_fsp(req
, SVAL(params
,0));
7902 /* Basic check for non-null fsp. */
7903 if (!check_fsp_open(conn
, req
, fsp
)) {
7906 info_level
= SVAL(params
,2);
7908 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7910 if (!NT_STATUS_IS_OK(status
)) {
7911 reply_nterror(req
, status
);
7915 if(fsp
->fh
->fd
== -1) {
7917 * This is actually a SETFILEINFO on a directory
7918 * handle (returned from an NT SMB). NT5.0 seems
7919 * to do this call. JRA.
7921 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7922 /* Always do lstat for UNIX calls. */
7923 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7924 DEBUG(3,("call_trans2setfilepathinfo: "
7925 "SMB_VFS_LSTAT of %s failed "
7927 smb_fname_str_dbg(smb_fname
),
7929 reply_nterror(req
, map_nt_error_from_unix(errno
));
7933 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7934 DEBUG(3,("call_trans2setfilepathinfo: "
7935 "fileinfo of %s failed (%s)\n",
7936 smb_fname_str_dbg(smb_fname
),
7938 reply_nterror(req
, map_nt_error_from_unix(errno
));
7942 } else if (fsp
->print_file
) {
7944 * Doing a DELETE_ON_CLOSE should cancel a print job.
7946 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7947 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7949 DEBUG(3,("call_trans2setfilepathinfo: "
7950 "Cancelling print job (%s)\n",
7954 send_trans2_replies(conn
, req
, params
, 2,
7960 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7965 * Original code - this is an open file.
7967 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7968 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7969 "of fnum %d failed (%s)\n", fsp
->fnum
,
7971 reply_nterror(req
, map_nt_error_from_unix(errno
));
7979 if (total_params
< 7) {
7980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7984 info_level
= SVAL(params
,0);
7985 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7986 total_params
- 6, STR_TERMINATE
,
7988 if (!NT_STATUS_IS_OK(status
)) {
7989 reply_nterror(req
, status
);
7993 status
= filename_convert(req
, conn
,
7994 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7999 if (!NT_STATUS_IS_OK(status
)) {
8000 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8001 reply_botherror(req
,
8002 NT_STATUS_PATH_NOT_COVERED
,
8003 ERRSRV
, ERRbadpath
);
8006 reply_nterror(req
, status
);
8010 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8012 * For CIFS UNIX extensions the target name may not exist.
8015 /* Always do lstat for UNIX calls. */
8016 SMB_VFS_LSTAT(conn
, smb_fname
);
8018 } else if (!VALID_STAT(smb_fname
->st
) &&
8019 SMB_VFS_STAT(conn
, smb_fname
)) {
8020 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8022 smb_fname_str_dbg(smb_fname
),
8024 reply_nterror(req
, map_nt_error_from_unix(errno
));
8029 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8030 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8031 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8033 /* Realloc the parameter size */
8034 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8035 if (*pparams
== NULL
) {
8036 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8043 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8049 if (!NT_STATUS_IS_OK(status
)) {
8050 if (open_was_deferred(req
->mid
)) {
8051 /* We have re-scheduled this call. */
8054 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8055 /* We have re-scheduled this call. */
8058 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8059 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8060 ERRSRV
, ERRbadpath
);
8063 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8064 reply_openerror(req
, status
);
8068 reply_nterror(req
, status
);
8072 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8078 /****************************************************************************
8079 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8080 ****************************************************************************/
8082 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8083 char **pparams
, int total_params
,
8084 char **ppdata
, int total_data
,
8085 unsigned int max_data_bytes
)
8087 struct smb_filename
*smb_dname
= NULL
;
8088 char *params
= *pparams
;
8089 char *pdata
= *ppdata
;
8090 char *directory
= NULL
;
8091 NTSTATUS status
= NT_STATUS_OK
;
8092 struct ea_list
*ea_list
= NULL
;
8093 TALLOC_CTX
*ctx
= talloc_tos();
8095 if (!CAN_WRITE(conn
)) {
8096 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8100 if (total_params
< 5) {
8101 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8105 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8106 total_params
- 4, STR_TERMINATE
,
8108 if (!NT_STATUS_IS_OK(status
)) {
8109 reply_nterror(req
, status
);
8113 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8115 status
= filename_convert(ctx
,
8117 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8123 if (!NT_STATUS_IS_OK(status
)) {
8124 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8125 reply_botherror(req
,
8126 NT_STATUS_PATH_NOT_COVERED
,
8127 ERRSRV
, ERRbadpath
);
8130 reply_nterror(req
, status
);
8135 * OS/2 workplace shell seems to send SET_EA requests of "null"
8136 * length (4 bytes containing IVAL 4).
8137 * They seem to have no effect. Bug #3212. JRA.
8140 if (total_data
&& (total_data
!= 4)) {
8141 /* Any data in this call is an EA list. */
8142 if (total_data
< 10) {
8143 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8147 if (IVAL(pdata
,0) > total_data
) {
8148 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8149 IVAL(pdata
,0), (unsigned int)total_data
));
8150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8154 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8157 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8161 if (!lp_ea_support(SNUM(conn
))) {
8162 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8166 /* If total_data == 4 Windows doesn't care what values
8167 * are placed in that field, it just ignores them.
8168 * The System i QNTC IBM SMB client puts bad values here,
8169 * so ignore them. */
8171 status
= create_directory(conn
, req
, smb_dname
);
8173 if (!NT_STATUS_IS_OK(status
)) {
8174 reply_nterror(req
, status
);
8178 /* Try and set any given EA. */
8180 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8181 if (!NT_STATUS_IS_OK(status
)) {
8182 reply_nterror(req
, status
);
8187 /* Realloc the parameter and data sizes */
8188 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8189 if(*pparams
== NULL
) {
8190 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8197 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8200 TALLOC_FREE(smb_dname
);
8204 /****************************************************************************
8205 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8206 We don't actually do this - we just send a null response.
8207 ****************************************************************************/
8209 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8210 struct smb_request
*req
,
8211 char **pparams
, int total_params
,
8212 char **ppdata
, int total_data
,
8213 unsigned int max_data_bytes
)
8215 char *params
= *pparams
;
8218 if (total_params
< 6) {
8219 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8223 info_level
= SVAL(params
,4);
8224 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8226 switch (info_level
) {
8231 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8235 /* Realloc the parameter and data sizes */
8236 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8237 if (*pparams
== NULL
) {
8238 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8243 SSVAL(params
,0,fnf_handle
);
8244 SSVAL(params
,2,0); /* No changes */
8245 SSVAL(params
,4,0); /* No EA errors */
8252 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8257 /****************************************************************************
8258 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8259 changes). Currently this does nothing.
8260 ****************************************************************************/
8262 static void call_trans2findnotifynext(connection_struct
*conn
,
8263 struct smb_request
*req
,
8264 char **pparams
, int total_params
,
8265 char **ppdata
, int total_data
,
8266 unsigned int max_data_bytes
)
8268 char *params
= *pparams
;
8270 DEBUG(3,("call_trans2findnotifynext\n"));
8272 /* Realloc the parameter and data sizes */
8273 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8274 if (*pparams
== NULL
) {
8275 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8280 SSVAL(params
,0,0); /* No changes */
8281 SSVAL(params
,2,0); /* No EA errors */
8283 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8288 /****************************************************************************
8289 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8290 ****************************************************************************/
8292 static void call_trans2getdfsreferral(connection_struct
*conn
,
8293 struct smb_request
*req
,
8294 char **pparams
, int total_params
,
8295 char **ppdata
, int total_data
,
8296 unsigned int max_data_bytes
)
8298 char *params
= *pparams
;
8299 char *pathname
= NULL
;
8301 int max_referral_level
;
8302 NTSTATUS status
= NT_STATUS_OK
;
8303 TALLOC_CTX
*ctx
= talloc_tos();
8305 DEBUG(10,("call_trans2getdfsreferral\n"));
8307 if (total_params
< 3) {
8308 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8312 max_referral_level
= SVAL(params
,0);
8314 if(!lp_host_msdfs()) {
8315 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8319 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8320 total_params
- 2, STR_TERMINATE
);
8322 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8325 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8326 ppdata
,&status
)) < 0) {
8327 reply_nterror(req
, status
);
8331 SSVAL(req
->inbuf
, smb_flg2
,
8332 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8333 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8338 #define LMCAT_SPL 0x53
8339 #define LMFUNC_GETJOBID 0x60
8341 /****************************************************************************
8342 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8343 ****************************************************************************/
8345 static void call_trans2ioctl(connection_struct
*conn
,
8346 struct smb_request
*req
,
8347 char **pparams
, int total_params
,
8348 char **ppdata
, int total_data
,
8349 unsigned int max_data_bytes
)
8351 char *pdata
= *ppdata
;
8352 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8354 /* check for an invalid fid before proceeding */
8357 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8361 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8362 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8363 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8364 if (*ppdata
== NULL
) {
8365 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8370 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8371 CAN ACCEPT THIS IN UNICODE. JRA. */
8374 if (fsp
->print_file
) {
8375 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8379 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8380 global_myname(), 15,
8381 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8382 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8383 lp_servicename(SNUM(conn
)), 13,
8384 STR_ASCII
|STR_TERMINATE
); /* Service name */
8385 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8390 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8391 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8394 /****************************************************************************
8395 Reply to a SMBfindclose (stop trans2 directory search).
8396 ****************************************************************************/
8398 void reply_findclose(struct smb_request
*req
)
8401 struct smbd_server_connection
*sconn
= req
->sconn
;
8403 START_PROFILE(SMBfindclose
);
8406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8407 END_PROFILE(SMBfindclose
);
8411 dptr_num
= SVALS(req
->vwv
+0, 0);
8413 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8415 dptr_close(sconn
, &dptr_num
);
8417 reply_outbuf(req
, 0, 0);
8419 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8421 END_PROFILE(SMBfindclose
);
8425 /****************************************************************************
8426 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8427 ****************************************************************************/
8429 void reply_findnclose(struct smb_request
*req
)
8433 START_PROFILE(SMBfindnclose
);
8436 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8437 END_PROFILE(SMBfindnclose
);
8441 dptr_num
= SVAL(req
->vwv
+0, 0);
8443 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8445 /* We never give out valid handles for a
8446 findnotifyfirst - so any dptr_num is ok here.
8449 reply_outbuf(req
, 0, 0);
8451 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8453 END_PROFILE(SMBfindnclose
);
8457 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8458 struct trans_state
*state
)
8460 if (get_Protocol() >= PROTOCOL_NT1
) {
8461 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8462 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8465 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8466 if (state
->call
!= TRANSACT2_QFSINFO
&&
8467 state
->call
!= TRANSACT2_SETFSINFO
) {
8468 DEBUG(0,("handle_trans2: encryption required "
8470 (unsigned int)state
->call
));
8471 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8476 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8478 /* Now we must call the relevant TRANS2 function */
8479 switch(state
->call
) {
8480 case TRANSACT2_OPEN
:
8482 START_PROFILE(Trans2_open
);
8483 call_trans2open(conn
, req
,
8484 &state
->param
, state
->total_param
,
8485 &state
->data
, state
->total_data
,
8486 state
->max_data_return
);
8487 END_PROFILE(Trans2_open
);
8491 case TRANSACT2_FINDFIRST
:
8493 START_PROFILE(Trans2_findfirst
);
8494 call_trans2findfirst(conn
, req
,
8495 &state
->param
, state
->total_param
,
8496 &state
->data
, state
->total_data
,
8497 state
->max_data_return
);
8498 END_PROFILE(Trans2_findfirst
);
8502 case TRANSACT2_FINDNEXT
:
8504 START_PROFILE(Trans2_findnext
);
8505 call_trans2findnext(conn
, req
,
8506 &state
->param
, state
->total_param
,
8507 &state
->data
, state
->total_data
,
8508 state
->max_data_return
);
8509 END_PROFILE(Trans2_findnext
);
8513 case TRANSACT2_QFSINFO
:
8515 START_PROFILE(Trans2_qfsinfo
);
8516 call_trans2qfsinfo(conn
, req
,
8517 &state
->param
, state
->total_param
,
8518 &state
->data
, state
->total_data
,
8519 state
->max_data_return
);
8520 END_PROFILE(Trans2_qfsinfo
);
8524 case TRANSACT2_SETFSINFO
:
8526 START_PROFILE(Trans2_setfsinfo
);
8527 call_trans2setfsinfo(conn
, req
,
8528 &state
->param
, state
->total_param
,
8529 &state
->data
, state
->total_data
,
8530 state
->max_data_return
);
8531 END_PROFILE(Trans2_setfsinfo
);
8535 case TRANSACT2_QPATHINFO
:
8536 case TRANSACT2_QFILEINFO
:
8538 START_PROFILE(Trans2_qpathinfo
);
8539 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8540 &state
->param
, state
->total_param
,
8541 &state
->data
, state
->total_data
,
8542 state
->max_data_return
);
8543 END_PROFILE(Trans2_qpathinfo
);
8547 case TRANSACT2_SETPATHINFO
:
8548 case TRANSACT2_SETFILEINFO
:
8550 START_PROFILE(Trans2_setpathinfo
);
8551 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8552 &state
->param
, state
->total_param
,
8553 &state
->data
, state
->total_data
,
8554 state
->max_data_return
);
8555 END_PROFILE(Trans2_setpathinfo
);
8559 case TRANSACT2_FINDNOTIFYFIRST
:
8561 START_PROFILE(Trans2_findnotifyfirst
);
8562 call_trans2findnotifyfirst(conn
, req
,
8563 &state
->param
, state
->total_param
,
8564 &state
->data
, state
->total_data
,
8565 state
->max_data_return
);
8566 END_PROFILE(Trans2_findnotifyfirst
);
8570 case TRANSACT2_FINDNOTIFYNEXT
:
8572 START_PROFILE(Trans2_findnotifynext
);
8573 call_trans2findnotifynext(conn
, req
,
8574 &state
->param
, state
->total_param
,
8575 &state
->data
, state
->total_data
,
8576 state
->max_data_return
);
8577 END_PROFILE(Trans2_findnotifynext
);
8581 case TRANSACT2_MKDIR
:
8583 START_PROFILE(Trans2_mkdir
);
8584 call_trans2mkdir(conn
, req
,
8585 &state
->param
, state
->total_param
,
8586 &state
->data
, state
->total_data
,
8587 state
->max_data_return
);
8588 END_PROFILE(Trans2_mkdir
);
8592 case TRANSACT2_GET_DFS_REFERRAL
:
8594 START_PROFILE(Trans2_get_dfs_referral
);
8595 call_trans2getdfsreferral(conn
, req
,
8596 &state
->param
, state
->total_param
,
8597 &state
->data
, state
->total_data
,
8598 state
->max_data_return
);
8599 END_PROFILE(Trans2_get_dfs_referral
);
8603 case TRANSACT2_IOCTL
:
8605 START_PROFILE(Trans2_ioctl
);
8606 call_trans2ioctl(conn
, req
,
8607 &state
->param
, state
->total_param
,
8608 &state
->data
, state
->total_data
,
8609 state
->max_data_return
);
8610 END_PROFILE(Trans2_ioctl
);
8615 /* Error in request */
8616 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8617 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8621 /****************************************************************************
8622 Reply to a SMBtrans2.
8623 ****************************************************************************/
8625 void reply_trans2(struct smb_request
*req
)
8627 connection_struct
*conn
= req
->conn
;
8632 unsigned int tran_call
;
8633 struct trans_state
*state
;
8636 START_PROFILE(SMBtrans2
);
8638 if (req
->wct
< 14) {
8639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8640 END_PROFILE(SMBtrans2
);
8644 dsoff
= SVAL(req
->vwv
+12, 0);
8645 dscnt
= SVAL(req
->vwv
+11, 0);
8646 psoff
= SVAL(req
->vwv
+10, 0);
8647 pscnt
= SVAL(req
->vwv
+9, 0);
8648 tran_call
= SVAL(req
->vwv
+14, 0);
8650 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8651 if (!NT_STATUS_IS_OK(result
)) {
8652 DEBUG(2, ("Got invalid trans2 request: %s\n",
8653 nt_errstr(result
)));
8654 reply_nterror(req
, result
);
8655 END_PROFILE(SMBtrans2
);
8660 switch (tran_call
) {
8661 /* List the allowed trans2 calls on IPC$ */
8662 case TRANSACT2_OPEN
:
8663 case TRANSACT2_GET_DFS_REFERRAL
:
8664 case TRANSACT2_QFILEINFO
:
8665 case TRANSACT2_QFSINFO
:
8666 case TRANSACT2_SETFSINFO
:
8669 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8670 END_PROFILE(SMBtrans2
);
8675 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8676 DEBUG(0, ("talloc failed\n"));
8677 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8678 END_PROFILE(SMBtrans2
);
8682 state
->cmd
= SMBtrans2
;
8684 state
->mid
= req
->mid
;
8685 state
->vuid
= req
->vuid
;
8686 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8687 state
->setup
= NULL
;
8688 state
->total_param
= SVAL(req
->vwv
+0, 0);
8689 state
->param
= NULL
;
8690 state
->total_data
= SVAL(req
->vwv
+1, 0);
8692 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8693 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8694 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8695 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8696 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8698 state
->call
= tran_call
;
8700 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8701 is so as a sanity check */
8702 if (state
->setup_count
!= 1) {
8704 * Need to have rc=0 for ioctl to get job id for OS/2.
8705 * Network printing will fail if function is not successful.
8706 * Similar function in reply.c will be used if protocol
8707 * is LANMAN1.0 instead of LM1.2X002.
8708 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8709 * outbuf doesn't have to be set(only job id is used).
8711 if ( (state
->setup_count
== 4)
8712 && (tran_call
== TRANSACT2_IOCTL
)
8713 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8714 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8715 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8717 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8718 DEBUG(2,("Transaction is %d\n",tran_call
));
8720 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8721 END_PROFILE(SMBtrans2
);
8726 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8729 if (state
->total_data
) {
8731 if (trans_oob(state
->total_data
, 0, dscnt
)
8732 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8736 /* Can't use talloc here, the core routines do realloc on the
8737 * params and data. */
8738 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8739 if (state
->data
== NULL
) {
8740 DEBUG(0,("reply_trans2: data malloc fail for %u "
8741 "bytes !\n", (unsigned int)state
->total_data
));
8743 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8744 END_PROFILE(SMBtrans2
);
8748 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8751 if (state
->total_param
) {
8753 if (trans_oob(state
->total_param
, 0, pscnt
)
8754 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8758 /* Can't use talloc here, the core routines do realloc on the
8759 * params and data. */
8760 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8761 if (state
->param
== NULL
) {
8762 DEBUG(0,("reply_trans: param malloc fail for %u "
8763 "bytes !\n", (unsigned int)state
->total_param
));
8764 SAFE_FREE(state
->data
);
8766 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8767 END_PROFILE(SMBtrans2
);
8771 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8774 state
->received_data
= dscnt
;
8775 state
->received_param
= pscnt
;
8777 if ((state
->received_param
== state
->total_param
) &&
8778 (state
->received_data
== state
->total_data
)) {
8780 handle_trans2(conn
, req
, state
);
8782 SAFE_FREE(state
->data
);
8783 SAFE_FREE(state
->param
);
8785 END_PROFILE(SMBtrans2
);
8789 DLIST_ADD(conn
->pending_trans
, state
);
8791 /* We need to send an interim response then receive the rest
8792 of the parameter/data bytes */
8793 reply_outbuf(req
, 0, 0);
8794 show_msg((char *)req
->outbuf
);
8795 END_PROFILE(SMBtrans2
);
8800 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8801 SAFE_FREE(state
->data
);
8802 SAFE_FREE(state
->param
);
8804 END_PROFILE(SMBtrans2
);
8805 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8809 /****************************************************************************
8810 Reply to a SMBtranss2
8811 ****************************************************************************/
8813 void reply_transs2(struct smb_request
*req
)
8815 connection_struct
*conn
= req
->conn
;
8816 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8817 struct trans_state
*state
;
8819 START_PROFILE(SMBtranss2
);
8821 show_msg((char *)req
->inbuf
);
8824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8825 END_PROFILE(SMBtranss2
);
8829 for (state
= conn
->pending_trans
; state
!= NULL
;
8830 state
= state
->next
) {
8831 if (state
->mid
== req
->mid
) {
8836 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8837 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8838 END_PROFILE(SMBtranss2
);
8842 /* Revise state->total_param and state->total_data in case they have
8843 changed downwards */
8845 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8846 state
->total_param
= SVAL(req
->vwv
+0, 0);
8847 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8848 state
->total_data
= SVAL(req
->vwv
+1, 0);
8850 pcnt
= SVAL(req
->vwv
+2, 0);
8851 poff
= SVAL(req
->vwv
+3, 0);
8852 pdisp
= SVAL(req
->vwv
+4, 0);
8854 dcnt
= SVAL(req
->vwv
+5, 0);
8855 doff
= SVAL(req
->vwv
+6, 0);
8856 ddisp
= SVAL(req
->vwv
+7, 0);
8858 state
->received_param
+= pcnt
;
8859 state
->received_data
+= dcnt
;
8861 if ((state
->received_data
> state
->total_data
) ||
8862 (state
->received_param
> state
->total_param
))
8866 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8867 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8870 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8874 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8875 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8878 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8881 if ((state
->received_param
< state
->total_param
) ||
8882 (state
->received_data
< state
->total_data
)) {
8883 END_PROFILE(SMBtranss2
);
8887 handle_trans2(conn
, req
, state
);
8889 DLIST_REMOVE(conn
->pending_trans
, state
);
8890 SAFE_FREE(state
->data
);
8891 SAFE_FREE(state
->param
);
8894 END_PROFILE(SMBtranss2
);
8899 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8900 DLIST_REMOVE(conn
->pending_trans
, state
);
8901 SAFE_FREE(state
->data
);
8902 SAFE_FREE(state
->param
);
8904 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8905 END_PROFILE(SMBtranss2
);