2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct
*conn
,
38 const SMB_STRUCT_STAT
*psbuf
);
40 static char *store_file_unix_basic_info2(connection_struct
*conn
,
43 const SMB_STRUCT_STAT
*psbuf
);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
52 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type
= get_remote_arch();
56 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
57 val
= SMB_ROUNDUP(val
,rval
);
62 /********************************************************************
63 Create a 64 bit FileIndex. If the file is on the same device as
64 the root of the share, just return the 64-bit inode. If it isn't,
65 mangle as we used to do.
66 ********************************************************************/
68 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
71 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
72 return (uint64_t)psbuf
->st_ex_ino
;
74 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
75 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static bool samba_private_attr_name(const char *unix_ea_name
)
89 static const char * const prohibited_ea_names
[] = {
90 SAMBA_POSIX_INHERITANCE_EA_NAME
,
91 SAMBA_XATTR_DOS_ATTRIB
,
99 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
100 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
103 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
104 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
110 /****************************************************************************
111 Get one EA value. Fill in a struct ea_struct.
112 ****************************************************************************/
114 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
115 files_struct
*fsp
, const char *fname
,
116 const char *ea_name
, struct ea_struct
*pea
)
118 /* Get the value of this xattr. Max size is 64k. */
119 size_t attr_size
= 256;
125 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
127 return NT_STATUS_NO_MEMORY
;
130 if (fsp
&& fsp
->fh
->fd
!= -1) {
131 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
133 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
136 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
142 return map_nt_error_from_unix(errno
);
145 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
146 dump_data(10, (uint8
*)val
, sizeret
);
149 if (strnequal(ea_name
, "user.", 5)) {
150 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
152 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
154 if (pea
->name
== NULL
) {
156 return NT_STATUS_NO_MEMORY
;
158 pea
->value
.data
= (unsigned char *)val
;
159 pea
->value
.length
= (size_t)sizeret
;
163 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
164 files_struct
*fsp
, const char *fname
,
165 char ***pnames
, size_t *pnum_names
)
167 /* Get a list of all xattrs. Max namesize is 64k. */
168 size_t ea_namelist_size
= 1024;
169 char *ea_namelist
= NULL
;
174 ssize_t sizeret
= -1;
176 if (!lp_ea_support(SNUM(conn
))) {
185 * TALLOC the result early to get the talloc hierarchy right.
188 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
190 DEBUG(0, ("talloc failed\n"));
191 return NT_STATUS_NO_MEMORY
;
194 while (ea_namelist_size
<= 65536) {
196 ea_namelist
= TALLOC_REALLOC_ARRAY(
197 names
, ea_namelist
, char, ea_namelist_size
);
198 if (ea_namelist
== NULL
) {
199 DEBUG(0, ("talloc failed\n"));
201 return NT_STATUS_NO_MEMORY
;
204 if (fsp
&& fsp
->fh
->fd
!= -1) {
205 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
208 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
212 if ((sizeret
== -1) && (errno
== ERANGE
)) {
213 ea_namelist_size
*= 2;
222 return map_nt_error_from_unix(errno
);
225 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
226 (unsigned int)sizeret
));
238 * Ensure the result is 0-terminated
241 if (ea_namelist
[sizeret
-1] != '\0') {
243 return NT_STATUS_INTERNAL_ERROR
;
251 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
255 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
257 DEBUG(0, ("talloc failed\n"));
259 return NT_STATUS_NO_MEMORY
;
265 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
266 names
[num_names
++] = p
;
274 *pnum_names
= num_names
;
278 /****************************************************************************
279 Return a linked list of the total EA's. Plus the total size
280 ****************************************************************************/
282 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
283 const char *fname
, size_t *pea_total_len
)
285 /* Get a list of all xattrs. Max namesize is 64k. */
288 struct ea_list
*ea_list_head
= NULL
;
293 if (!lp_ea_support(SNUM(conn
))) {
297 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
300 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
304 for (i
=0; i
<num_names
; i
++) {
305 struct ea_list
*listp
;
308 if (strnequal(names
[i
], "system.", 7)
309 || samba_private_attr_name(names
[i
]))
312 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
317 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
323 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
326 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
328 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
329 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
330 (unsigned int)listp
->ea
.value
.length
));
332 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
336 /* Add on 4 for total length. */
337 if (*pea_total_len
) {
341 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
342 (unsigned int)*pea_total_len
));
347 /****************************************************************************
348 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
350 ****************************************************************************/
352 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
353 connection_struct
*conn
, struct ea_list
*ea_list
)
355 unsigned int ret_data_size
= 4;
358 SMB_ASSERT(total_data_size
>= 4);
360 if (!lp_ea_support(SNUM(conn
))) {
365 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
368 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
369 dos_namelen
= strlen(dos_ea_name
);
370 if (dos_namelen
> 255 || dos_namelen
== 0) {
373 if (ea_list
->ea
.value
.length
> 65535) {
376 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
380 /* We know we have room. */
381 SCVAL(p
,0,ea_list
->ea
.flags
);
382 SCVAL(p
,1,dos_namelen
);
383 SSVAL(p
,2,ea_list
->ea
.value
.length
);
384 fstrcpy(p
+4, dos_ea_name
);
385 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
387 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
388 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
391 ret_data_size
= PTR_DIFF(p
, pdata
);
392 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
393 SIVAL(pdata
,0,ret_data_size
);
394 return ret_data_size
;
397 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
399 unsigned int total_data_size
,
400 unsigned int *ret_data_size
,
401 connection_struct
*conn
,
402 struct ea_list
*ea_list
)
404 uint8_t *p
= (uint8_t *)pdata
;
405 uint8_t *last_start
= NULL
;
409 if (!lp_ea_support(SNUM(conn
))) {
410 return NT_STATUS_NO_EAS_ON_FILE
;
413 for (; ea_list
; ea_list
= ea_list
->next
) {
419 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
423 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
424 dos_namelen
= strlen(dos_ea_name
);
425 if (dos_namelen
> 255 || dos_namelen
== 0) {
426 return NT_STATUS_INTERNAL_ERROR
;
428 if (ea_list
->ea
.value
.length
> 65535) {
429 return NT_STATUS_INTERNAL_ERROR
;
432 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
435 size_t pad
= 4 - (this_size
% 4);
439 if (this_size
> total_data_size
) {
440 return NT_STATUS_INFO_LENGTH_MISMATCH
;
443 /* We know we have room. */
444 SIVAL(p
, 0x00, 0); /* next offset */
445 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
446 SCVAL(p
, 0x05, dos_namelen
);
447 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
448 fstrcpy((char *)(p
+0x08), dos_ea_name
);
449 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
451 total_data_size
-= this_size
;
455 *ret_data_size
= PTR_DIFF(p
, pdata
);
456 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
460 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
462 size_t total_ea_len
= 0;
463 TALLOC_CTX
*mem_ctx
= NULL
;
465 if (!lp_ea_support(SNUM(conn
))) {
468 mem_ctx
= talloc_tos();
469 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
473 /****************************************************************************
474 Ensure the EA name is case insensitive by matching any existing EA name.
475 ****************************************************************************/
477 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
480 TALLOC_CTX
*mem_ctx
= talloc_tos();
481 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
483 for (; ea_list
; ea_list
= ea_list
->next
) {
484 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
485 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
486 &unix_ea_name
[5], ea_list
->ea
.name
));
487 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
493 /****************************************************************************
494 Set or delete an extended attribute.
495 ****************************************************************************/
497 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
498 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
502 if (!lp_ea_support(SNUM(conn
))) {
503 return NT_STATUS_EAS_NOT_SUPPORTED
;
506 /* For now setting EAs on streams isn't supported. */
507 fname
= smb_fname
->base_name
;
509 for (;ea_list
; ea_list
= ea_list
->next
) {
511 fstring unix_ea_name
;
513 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
514 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
516 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
518 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
520 if (samba_private_attr_name(unix_ea_name
)) {
521 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
522 return NT_STATUS_ACCESS_DENIED
;
525 if (ea_list
->ea
.value
.length
== 0) {
526 /* Remove the attribute. */
527 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
528 DEBUG(10,("set_ea: deleting ea name %s on "
529 "file %s by file descriptor.\n",
530 unix_ea_name
, fsp_str_dbg(fsp
)));
531 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
533 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
534 unix_ea_name
, fname
));
535 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
538 /* Removing a non existent attribute always succeeds. */
539 if (ret
== -1 && errno
== ENOATTR
) {
540 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
546 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
547 DEBUG(10,("set_ea: setting ea name %s on file "
548 "%s by file descriptor.\n",
549 unix_ea_name
, fsp_str_dbg(fsp
)));
550 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
551 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
553 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
554 unix_ea_name
, fname
));
555 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
556 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
562 if (errno
== ENOTSUP
) {
563 return NT_STATUS_EAS_NOT_SUPPORTED
;
566 return map_nt_error_from_unix(errno
);
572 /****************************************************************************
573 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
574 ****************************************************************************/
576 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
578 struct ea_list
*ea_list_head
= NULL
;
579 size_t converted_size
, offset
= 0;
581 while (offset
+ 2 < data_size
) {
582 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
583 unsigned int namelen
= CVAL(pdata
,offset
);
585 offset
++; /* Go past the namelen byte. */
587 /* integer wrap paranioa. */
588 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
589 (offset
> data_size
) || (namelen
> data_size
) ||
590 (offset
+ namelen
>= data_size
)) {
593 /* Ensure the name is null terminated. */
594 if (pdata
[offset
+ namelen
] != '\0') {
597 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
599 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
600 "failed: %s", strerror(errno
)));
606 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
607 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
608 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
614 /****************************************************************************
615 Read one EA list entry from the buffer.
616 ****************************************************************************/
618 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
620 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
622 unsigned int namelen
;
623 size_t converted_size
;
633 eal
->ea
.flags
= CVAL(pdata
,0);
634 namelen
= CVAL(pdata
,1);
635 val_len
= SVAL(pdata
,2);
637 if (4 + namelen
+ 1 + val_len
> data_size
) {
641 /* Ensure the name is null terminated. */
642 if (pdata
[namelen
+ 4] != '\0') {
645 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
646 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
653 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
654 if (!eal
->ea
.value
.data
) {
658 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
660 /* Ensure we're null terminated just in case we print the value. */
661 eal
->ea
.value
.data
[val_len
] = '\0';
662 /* But don't count the null. */
663 eal
->ea
.value
.length
--;
666 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
669 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
670 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
675 /****************************************************************************
676 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
677 ****************************************************************************/
679 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
681 struct ea_list
*ea_list_head
= NULL
;
683 size_t bytes_used
= 0;
685 while (offset
< data_size
) {
686 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
692 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
693 offset
+= bytes_used
;
699 /****************************************************************************
700 Count the total EA size needed.
701 ****************************************************************************/
703 static size_t ea_list_size(struct ea_list
*ealist
)
706 struct ea_list
*listp
;
709 for (listp
= ealist
; listp
; listp
= listp
->next
) {
710 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
711 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
713 /* Add on 4 for total length. */
721 /****************************************************************************
722 Return a union of EA's from a file list and a list of names.
723 The TALLOC context for the two lists *MUST* be identical as we steal
724 memory from one list to add to another. JRA.
725 ****************************************************************************/
727 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
729 struct ea_list
*nlistp
, *flistp
;
731 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
732 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
733 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
739 /* Copy the data from this entry. */
740 nlistp
->ea
.flags
= flistp
->ea
.flags
;
741 nlistp
->ea
.value
= flistp
->ea
.value
;
744 nlistp
->ea
.flags
= 0;
745 ZERO_STRUCT(nlistp
->ea
.value
);
749 *total_ea_len
= ea_list_size(name_list
);
753 /****************************************************************************
754 Send the required number of replies back.
755 We assume all fields other than the data fields are
756 set correctly for the type of call.
757 HACK ! Always assumes smb_setup field is zero.
758 ****************************************************************************/
760 void send_trans2_replies(connection_struct
*conn
,
761 struct smb_request
*req
,
768 /* As we are using a protocol > LANMAN1 then the max_send
769 variable must have been set in the sessetupX call.
770 This takes precedence over the max_xmit field in the
771 global struct. These different max_xmit variables should
772 be merged as this is now too confusing */
774 int data_to_send
= datasize
;
775 int params_to_send
= paramsize
;
777 const char *pp
= params
;
778 const char *pd
= pdata
;
779 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
780 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
781 int data_alignment_offset
= 0;
782 bool overflow
= False
;
783 struct smbd_server_connection
*sconn
= req
->sconn
;
784 int max_send
= sconn
->smb1
.sessions
.max_send
;
786 /* Modify the data_to_send and datasize and set the error if
787 we're trying to send more than max_data_bytes. We still send
788 the part of the packet(s) that fit. Strange, but needed
791 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
792 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
793 max_data_bytes
, datasize
));
794 datasize
= data_to_send
= max_data_bytes
;
798 /* If there genuinely are no parameters or data to send just send the empty packet */
800 if(params_to_send
== 0 && data_to_send
== 0) {
801 reply_outbuf(req
, 10, 0);
802 show_msg((char *)req
->outbuf
);
803 if (!srv_send_smb(smbd_server_fd(),
806 IS_CONN_ENCRYPTED(conn
),
808 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
810 TALLOC_FREE(req
->outbuf
);
814 /* When sending params and data ensure that both are nicely aligned */
815 /* Only do this alignment when there is also data to send - else
816 can cause NT redirector problems. */
818 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
819 data_alignment_offset
= 4 - (params_to_send
% 4);
821 /* Space is bufsize minus Netbios over TCP header minus SMB header */
822 /* The alignment_offset is to align the param bytes on an even byte
823 boundary. NT 4.0 Beta needs this to work correctly. */
825 useable_space
= max_send
- (smb_size
828 + data_alignment_offset
);
830 if (useable_space
< 0) {
831 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
832 "= %d!!!", useable_space
));
833 exit_server_cleanly("send_trans2_replies: Not enough space");
836 while (params_to_send
|| data_to_send
) {
837 /* Calculate whether we will totally or partially fill this packet */
839 total_sent_thistime
= params_to_send
+ data_to_send
;
841 /* We can never send more than useable_space */
843 * Note that 'useable_space' does not include the alignment offsets,
844 * but we must include the alignment offsets in the calculation of
845 * the length of the data we send over the wire, as the alignment offsets
846 * are sent here. Fix from Marc_Jacobsen@hp.com.
849 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
851 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
852 + data_alignment_offset
);
855 * We might have SMBtrans2s in req which was transferred to
856 * the outbuf, fix that.
858 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
860 /* Set total params and data to be sent */
861 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
862 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
864 /* Calculate how many parameters and data we can fit into
865 * this packet. Parameters get precedence
868 params_sent_thistime
= MIN(params_to_send
,useable_space
);
869 data_sent_thistime
= useable_space
- params_sent_thistime
;
870 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
872 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
874 /* smb_proff is the offset from the start of the SMB header to the
875 parameter bytes, however the first 4 bytes of outbuf are
876 the Netbios over TCP header. Thus use smb_base() to subtract
877 them from the calculation */
879 SSVAL(req
->outbuf
,smb_proff
,
880 ((smb_buf(req
->outbuf
)+alignment_offset
)
881 - smb_base(req
->outbuf
)));
883 if(params_sent_thistime
== 0)
884 SSVAL(req
->outbuf
,smb_prdisp
,0);
886 /* Absolute displacement of param bytes sent in this packet */
887 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
889 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
890 if(data_sent_thistime
== 0) {
891 SSVAL(req
->outbuf
,smb_droff
,0);
892 SSVAL(req
->outbuf
,smb_drdisp
, 0);
894 /* The offset of the data bytes is the offset of the
895 parameter bytes plus the number of parameters being sent this time */
896 SSVAL(req
->outbuf
, smb_droff
,
897 ((smb_buf(req
->outbuf
)+alignment_offset
)
898 - smb_base(req
->outbuf
))
899 + params_sent_thistime
+ data_alignment_offset
);
900 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
903 /* Initialize the padding for alignment */
905 if (alignment_offset
!= 0) {
906 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
909 /* Copy the param bytes into the packet */
911 if(params_sent_thistime
) {
912 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
913 params_sent_thistime
);
916 /* Copy in the data bytes */
917 if(data_sent_thistime
) {
918 if (data_alignment_offset
!= 0) {
919 memset((smb_buf(req
->outbuf
)+alignment_offset
+
920 params_sent_thistime
), 0,
921 data_alignment_offset
);
923 memcpy(smb_buf(req
->outbuf
)+alignment_offset
924 +params_sent_thistime
+data_alignment_offset
,
925 pd
,data_sent_thistime
);
928 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
929 params_sent_thistime
, data_sent_thistime
, useable_space
));
930 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
931 params_to_send
, data_to_send
, paramsize
, datasize
));
934 error_packet_set((char *)req
->outbuf
,
935 ERRDOS
,ERRbufferoverflow
,
936 STATUS_BUFFER_OVERFLOW
,
940 /* Send the packet */
941 show_msg((char *)req
->outbuf
);
942 if (!srv_send_smb(smbd_server_fd(),
945 IS_CONN_ENCRYPTED(conn
),
947 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
949 TALLOC_FREE(req
->outbuf
);
951 pp
+= params_sent_thistime
;
952 pd
+= data_sent_thistime
;
954 params_to_send
-= params_sent_thistime
;
955 data_to_send
-= data_sent_thistime
;
958 if(params_to_send
< 0 || data_to_send
< 0) {
959 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
960 params_to_send
, data_to_send
));
968 /****************************************************************************
969 Reply to a TRANSACT2_OPEN.
970 ****************************************************************************/
972 static void call_trans2open(connection_struct
*conn
,
973 struct smb_request
*req
,
974 char **pparams
, int total_params
,
975 char **ppdata
, int total_data
,
976 unsigned int max_data_bytes
)
978 struct smb_filename
*smb_fname
= NULL
;
979 char *params
= *pparams
;
980 char *pdata
= *ppdata
;
985 bool return_additional_info
;
998 struct ea_list
*ea_list
= NULL
;
1003 uint32 create_disposition
;
1004 uint32 create_options
= 0;
1005 uint32_t private_flags
= 0;
1006 TALLOC_CTX
*ctx
= talloc_tos();
1009 * Ensure we have enough parameters to perform the operation.
1012 if (total_params
< 29) {
1013 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1017 flags
= SVAL(params
, 0);
1018 deny_mode
= SVAL(params
, 2);
1019 open_attr
= SVAL(params
,6);
1020 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1021 if (oplock_request
) {
1022 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1026 return_additional_info
= BITSETW(params
,0);
1027 open_sattr
= SVAL(params
, 4);
1028 open_time
= make_unix_date3(params
+8);
1030 open_ofun
= SVAL(params
,12);
1031 open_size
= IVAL(params
,14);
1032 pname
= ¶ms
[28];
1035 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1039 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1040 total_params
- 28, STR_TERMINATE
,
1042 if (!NT_STATUS_IS_OK(status
)) {
1043 reply_nterror(req
, status
);
1047 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1048 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1049 (unsigned int)open_ofun
, open_size
));
1051 status
= filename_convert(ctx
,
1053 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1058 if (!NT_STATUS_IS_OK(status
)) {
1059 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1060 reply_botherror(req
,
1061 NT_STATUS_PATH_NOT_COVERED
,
1062 ERRSRV
, ERRbadpath
);
1065 reply_nterror(req
, status
);
1069 if (open_ofun
== 0) {
1070 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1074 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1075 &access_mask
, &share_mode
,
1076 &create_disposition
,
1079 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1083 /* Any data in this call is an EA list. */
1084 if (total_data
&& (total_data
!= 4)) {
1085 if (total_data
< 10) {
1086 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1090 if (IVAL(pdata
,0) > total_data
) {
1091 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1092 IVAL(pdata
,0), (unsigned int)total_data
));
1093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1097 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1100 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1104 if (!lp_ea_support(SNUM(conn
))) {
1105 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1110 status
= SMB_VFS_CREATE_FILE(
1113 0, /* root_dir_fid */
1114 smb_fname
, /* fname */
1115 access_mask
, /* access_mask */
1116 share_mode
, /* share_access */
1117 create_disposition
, /* create_disposition*/
1118 create_options
, /* create_options */
1119 open_attr
, /* file_attributes */
1120 oplock_request
, /* oplock_request */
1121 open_size
, /* allocation_size */
1124 ea_list
, /* ea_list */
1126 &smb_action
); /* psbuf */
1128 if (!NT_STATUS_IS_OK(status
)) {
1129 if (open_was_deferred(req
->mid
)) {
1130 /* We have re-scheduled this call. */
1133 reply_openerror(req
, status
);
1137 size
= get_file_size_stat(&smb_fname
->st
);
1138 fattr
= dos_mode(conn
, smb_fname
);
1139 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1140 inode
= smb_fname
->st
.st_ex_ino
;
1142 close_file(req
, fsp
, ERROR_CLOSE
);
1143 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1147 /* Realloc the size of parameters and data we will return */
1148 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1149 if(*pparams
== NULL
) {
1150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1155 SSVAL(params
,0,fsp
->fnum
);
1156 SSVAL(params
,2,fattr
);
1157 srv_put_dos_date2(params
,4, mtime
);
1158 SIVAL(params
,8, (uint32
)size
);
1159 SSVAL(params
,12,deny_mode
);
1160 SSVAL(params
,14,0); /* open_type - file or directory. */
1161 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1163 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1164 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1167 SSVAL(params
,18,smb_action
);
1170 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1172 SIVAL(params
,20,inode
);
1173 SSVAL(params
,24,0); /* Padding. */
1175 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1176 fsp
->fsp_name
->base_name
);
1177 SIVAL(params
, 26, ea_size
);
1179 SIVAL(params
, 26, 0);
1182 /* Send the required number of replies */
1183 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1185 TALLOC_FREE(smb_fname
);
1188 /*********************************************************
1189 Routine to check if a given string matches exactly.
1190 as a special case a mask of "." does NOT match. That
1191 is required for correct wildcard semantics
1192 Case can be significant or not.
1193 **********************************************************/
1195 static bool exact_match(bool has_wild
,
1196 bool case_sensitive
,
1200 if (mask
[0] == '.' && mask
[1] == 0) {
1208 if (case_sensitive
) {
1209 return strcmp(str
,mask
)==0;
1211 return StrCaseCmp(str
,mask
) == 0;
1215 /****************************************************************************
1216 Return the filetype for UNIX extensions.
1217 ****************************************************************************/
1219 static uint32
unix_filetype(mode_t mode
)
1222 return UNIX_TYPE_FILE
;
1223 else if(S_ISDIR(mode
))
1224 return UNIX_TYPE_DIR
;
1226 else if(S_ISLNK(mode
))
1227 return UNIX_TYPE_SYMLINK
;
1230 else if(S_ISCHR(mode
))
1231 return UNIX_TYPE_CHARDEV
;
1234 else if(S_ISBLK(mode
))
1235 return UNIX_TYPE_BLKDEV
;
1238 else if(S_ISFIFO(mode
))
1239 return UNIX_TYPE_FIFO
;
1242 else if(S_ISSOCK(mode
))
1243 return UNIX_TYPE_SOCKET
;
1246 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1247 return UNIX_TYPE_UNKNOWN
;
1250 /****************************************************************************
1251 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1252 ****************************************************************************/
1254 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1256 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1257 const SMB_STRUCT_STAT
*psbuf
,
1259 enum perm_type ptype
,
1264 if (perms
== SMB_MODE_NO_CHANGE
) {
1265 if (!VALID_STAT(*psbuf
)) {
1266 return NT_STATUS_INVALID_PARAMETER
;
1268 *ret_perms
= psbuf
->st_ex_mode
;
1269 return NT_STATUS_OK
;
1273 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1274 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1275 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1276 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1277 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1278 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1279 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1280 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1281 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1283 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1286 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1289 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1294 /* Apply mode mask */
1295 ret
&= lp_create_mask(SNUM(conn
));
1296 /* Add in force bits */
1297 ret
|= lp_force_create_mode(SNUM(conn
));
1300 ret
&= lp_dir_mask(SNUM(conn
));
1301 /* Add in force bits */
1302 ret
|= lp_force_dir_mode(SNUM(conn
));
1304 case PERM_EXISTING_FILE
:
1305 /* Apply mode mask */
1306 ret
&= lp_security_mask(SNUM(conn
));
1307 /* Add in force bits */
1308 ret
|= lp_force_security_mode(SNUM(conn
));
1310 case PERM_EXISTING_DIR
:
1311 /* Apply mode mask */
1312 ret
&= lp_dir_security_mask(SNUM(conn
));
1313 /* Add in force bits */
1314 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1319 return NT_STATUS_OK
;
1322 /****************************************************************************
1323 Needed to show the msdfs symlinks as directories. Modifies psbuf
1324 to be a directory if it's a msdfs link.
1325 ****************************************************************************/
1327 static bool check_msdfs_link(connection_struct
*conn
,
1328 const char *pathname
,
1329 SMB_STRUCT_STAT
*psbuf
)
1331 int saved_errno
= errno
;
1332 if(lp_host_msdfs() &&
1333 lp_msdfs_root(SNUM(conn
)) &&
1334 is_msdfs_link(conn
, pathname
, psbuf
)) {
1336 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1339 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1340 errno
= saved_errno
;
1343 errno
= saved_errno
;
1348 /****************************************************************************
1349 Get a level dependent lanman2 dir entry.
1350 ****************************************************************************/
1352 struct smbd_dirptr_lanman2_state
{
1353 connection_struct
*conn
;
1354 uint32_t info_level
;
1355 bool check_mangled_names
;
1357 bool got_exact_match
;
1360 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1366 struct smbd_dirptr_lanman2_state
*state
=
1367 (struct smbd_dirptr_lanman2_state
*)private_data
;
1369 char mangled_name
[13]; /* mangled 8.3 name. */
1373 /* Mangle fname if it's an illegal name. */
1374 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1375 ok
= name_to_8_3(dname
, mangled_name
,
1376 true, state
->conn
->params
);
1380 fname
= mangled_name
;
1385 got_match
= exact_match(state
->has_wild
,
1386 state
->conn
->case_sensitive
,
1388 state
->got_exact_match
= got_match
;
1390 got_match
= mask_match(fname
, mask
,
1391 state
->conn
->case_sensitive
);
1394 if(!got_match
&& state
->check_mangled_names
&&
1395 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1397 * It turns out that NT matches wildcards against
1398 * both long *and* short names. This may explain some
1399 * of the wildcard wierdness from old DOS clients
1400 * that some people have been seeing.... JRA.
1402 /* Force the mangling into 8.3. */
1403 ok
= name_to_8_3(fname
, mangled_name
,
1404 false, state
->conn
->params
);
1409 got_match
= exact_match(state
->has_wild
,
1410 state
->conn
->case_sensitive
,
1411 mangled_name
, mask
);
1412 state
->got_exact_match
= got_match
;
1414 got_match
= mask_match(mangled_name
, mask
,
1415 state
->conn
->case_sensitive
);
1423 *_fname
= talloc_strdup(ctx
, fname
);
1424 if (*_fname
== NULL
) {
1431 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1433 struct smb_filename
*smb_fname
,
1436 struct smbd_dirptr_lanman2_state
*state
=
1437 (struct smbd_dirptr_lanman2_state
*)private_data
;
1438 bool ms_dfs_link
= false;
1441 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1442 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1443 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1444 "Couldn't lstat [%s] (%s)\n",
1445 smb_fname_str_dbg(smb_fname
),
1449 } else if (!VALID_STAT(smb_fname
->st
) &&
1450 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1451 /* Needed to show the msdfs symlinks as
1454 ms_dfs_link
= check_msdfs_link(state
->conn
,
1455 smb_fname
->base_name
,
1458 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1459 "Couldn't stat [%s] (%s)\n",
1460 smb_fname_str_dbg(smb_fname
),
1467 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1469 mode
= dos_mode(state
->conn
, smb_fname
);
1476 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1477 connection_struct
*conn
,
1479 uint32_t info_level
,
1480 struct ea_list
*name_list
,
1481 bool check_mangled_names
,
1482 bool requires_resume_key
,
1485 const struct smb_filename
*smb_fname
,
1486 int space_remaining
,
1493 uint64_t *last_entry_off
)
1495 char *p
, *q
, *pdata
= *ppdata
;
1497 uint64_t file_size
= 0;
1498 uint64_t allocation_size
= 0;
1499 uint64_t file_index
= 0;
1501 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1502 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1503 time_t c_date
= (time_t)0;
1505 char *last_entry_ptr
;
1510 *out_of_space
= false;
1512 ZERO_STRUCT(mdate_ts
);
1513 ZERO_STRUCT(adate_ts
);
1514 ZERO_STRUCT(create_date_ts
);
1515 ZERO_STRUCT(cdate_ts
);
1517 if (!(mode
& aDIR
)) {
1518 file_size
= get_file_size_stat(&smb_fname
->st
);
1520 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1522 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1524 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1525 adate_ts
= smb_fname
->st
.st_ex_atime
;
1526 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1527 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1529 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1530 dos_filetime_timespec(&create_date_ts
);
1531 dos_filetime_timespec(&mdate_ts
);
1532 dos_filetime_timespec(&adate_ts
);
1533 dos_filetime_timespec(&cdate_ts
);
1536 create_date
= convert_timespec_to_time_t(create_date_ts
);
1537 mdate
= convert_timespec_to_time_t(mdate_ts
);
1538 adate
= convert_timespec_to_time_t(adate_ts
);
1539 c_date
= convert_timespec_to_time_t(cdate_ts
);
1541 /* align the record */
1542 SMB_ASSERT(align
>= 1);
1544 off
= (int)PTR_DIFF(pdata
, base_data
);
1545 pad
= (off
+ (align
-1)) & ~(align
-1);
1548 if (pad
&& pad
> space_remaining
) {
1549 *out_of_space
= true;
1550 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1551 "for padding (wanted %u, had %d)\n",
1554 return false; /* Not finished - just out of space */
1558 /* initialize padding to 0 */
1560 memset(pdata
, 0, pad
);
1562 space_remaining
-= pad
;
1564 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1574 switch (info_level
) {
1575 case SMB_FIND_INFO_STANDARD
:
1576 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1577 if(requires_resume_key
) {
1581 srv_put_dos_date2(p
,0,create_date
);
1582 srv_put_dos_date2(p
,4,adate
);
1583 srv_put_dos_date2(p
,8,mdate
);
1584 SIVAL(p
,12,(uint32
)file_size
);
1585 SIVAL(p
,16,(uint32
)allocation_size
);
1589 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1590 p
+= ucs2_align(base_data
, p
, 0);
1592 len
= srvstr_push(base_data
, flags2
, p
,
1593 fname
, PTR_DIFF(end_data
, p
),
1595 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1597 SCVAL(nameptr
, -1, len
- 2);
1599 SCVAL(nameptr
, -1, 0);
1603 SCVAL(nameptr
, -1, len
- 1);
1605 SCVAL(nameptr
, -1, 0);
1611 case SMB_FIND_EA_SIZE
:
1612 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1613 if (requires_resume_key
) {
1617 srv_put_dos_date2(p
,0,create_date
);
1618 srv_put_dos_date2(p
,4,adate
);
1619 srv_put_dos_date2(p
,8,mdate
);
1620 SIVAL(p
,12,(uint32
)file_size
);
1621 SIVAL(p
,16,(uint32
)allocation_size
);
1624 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1625 smb_fname
->base_name
);
1626 SIVAL(p
,22,ea_size
); /* Extended attributes */
1630 len
= srvstr_push(base_data
, flags2
,
1631 p
, fname
, PTR_DIFF(end_data
, p
),
1632 STR_TERMINATE
| STR_NOALIGN
);
1633 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1646 SCVAL(nameptr
,0,len
);
1648 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1651 case SMB_FIND_EA_LIST
:
1653 struct ea_list
*file_list
= NULL
;
1656 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1660 if (requires_resume_key
) {
1664 srv_put_dos_date2(p
,0,create_date
);
1665 srv_put_dos_date2(p
,4,adate
);
1666 srv_put_dos_date2(p
,8,mdate
);
1667 SIVAL(p
,12,(uint32
)file_size
);
1668 SIVAL(p
,16,(uint32
)allocation_size
);
1670 p
+= 22; /* p now points to the EA area. */
1672 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1673 smb_fname
->base_name
,
1675 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1677 /* We need to determine if this entry will fit in the space available. */
1678 /* Max string size is 255 bytes. */
1679 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1680 *out_of_space
= true;
1681 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1682 "(wanted %u, had %d)\n",
1683 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1685 return False
; /* Not finished - just out of space */
1688 /* Push the ea_data followed by the name. */
1689 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1691 len
= srvstr_push(base_data
, flags2
,
1692 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1693 STR_TERMINATE
| STR_NOALIGN
);
1694 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1707 SCVAL(nameptr
,0,len
);
1709 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1714 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1715 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1717 SIVAL(p
,0,reskey
); p
+= 4;
1718 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1719 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1720 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1721 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1722 SOFF_T(p
,0,file_size
); p
+= 8;
1723 SOFF_T(p
,0,allocation_size
); p
+= 8;
1724 SIVAL(p
,0,mode
); p
+= 4;
1725 q
= p
; p
+= 4; /* q is placeholder for name length. */
1727 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1728 smb_fname
->base_name
);
1729 SIVAL(p
,0,ea_size
); /* Extended attributes */
1732 /* Clear the short name buffer. This is
1733 * IMPORTANT as not doing so will trigger
1734 * a Win2k client bug. JRA.
1736 if (!was_8_3
&& check_mangled_names
) {
1737 char mangled_name
[13]; /* mangled 8.3 name. */
1738 if (!name_to_8_3(fname
,mangled_name
,True
,
1740 /* Error - mangle failed ! */
1741 memset(mangled_name
,'\0',12);
1743 mangled_name
[12] = 0;
1744 len
= srvstr_push(base_data
, flags2
,
1745 p
+2, mangled_name
, 24,
1746 STR_UPPER
|STR_UNICODE
);
1748 memset(p
+ 2 + len
,'\0',24 - len
);
1755 len
= srvstr_push(base_data
, flags2
, p
,
1756 fname
, PTR_DIFF(end_data
, p
),
1757 STR_TERMINATE_ASCII
);
1761 len
= PTR_DIFF(p
, pdata
);
1762 pad
= (len
+ (align
-1)) & ~(align
-1);
1764 * offset to the next entry, the caller
1765 * will overwrite it for the last entry
1766 * that's why we always include the padding
1770 * set padding to zero
1773 memset(p
, 0, pad
- len
);
1780 case SMB_FIND_FILE_DIRECTORY_INFO
:
1781 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1783 SIVAL(p
,0,reskey
); p
+= 4;
1784 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1787 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1788 SOFF_T(p
,0,file_size
); p
+= 8;
1789 SOFF_T(p
,0,allocation_size
); p
+= 8;
1790 SIVAL(p
,0,mode
); p
+= 4;
1791 len
= srvstr_push(base_data
, flags2
,
1792 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1793 STR_TERMINATE_ASCII
);
1797 len
= PTR_DIFF(p
, pdata
);
1798 pad
= (len
+ (align
-1)) & ~(align
-1);
1800 * offset to the next entry, the caller
1801 * will overwrite it for the last entry
1802 * that's why we always include the padding
1806 * set padding to zero
1809 memset(p
, 0, pad
- len
);
1816 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1817 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1819 SIVAL(p
,0,reskey
); p
+= 4;
1820 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1821 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1822 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1823 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1824 SOFF_T(p
,0,file_size
); p
+= 8;
1825 SOFF_T(p
,0,allocation_size
); p
+= 8;
1826 SIVAL(p
,0,mode
); p
+= 4;
1827 q
= p
; p
+= 4; /* q is placeholder for name length. */
1829 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1830 smb_fname
->base_name
);
1831 SIVAL(p
,0,ea_size
); /* Extended attributes */
1834 len
= srvstr_push(base_data
, flags2
, p
,
1835 fname
, PTR_DIFF(end_data
, p
),
1836 STR_TERMINATE_ASCII
);
1840 len
= PTR_DIFF(p
, pdata
);
1841 pad
= (len
+ (align
-1)) & ~(align
-1);
1843 * offset to the next entry, the caller
1844 * will overwrite it for the last entry
1845 * that's why we always include the padding
1849 * set padding to zero
1852 memset(p
, 0, pad
- len
);
1859 case SMB_FIND_FILE_NAMES_INFO
:
1860 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1862 SIVAL(p
,0,reskey
); p
+= 4;
1864 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1865 acl on a dir (tridge) */
1866 len
= srvstr_push(base_data
, flags2
, p
,
1867 fname
, PTR_DIFF(end_data
, p
),
1868 STR_TERMINATE_ASCII
);
1872 len
= PTR_DIFF(p
, pdata
);
1873 pad
= (len
+ (align
-1)) & ~(align
-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1881 * set padding to zero
1884 memset(p
, 0, pad
- len
);
1891 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1894 SIVAL(p
,0,reskey
); p
+= 4;
1895 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1896 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1897 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1898 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1899 SOFF_T(p
,0,file_size
); p
+= 8;
1900 SOFF_T(p
,0,allocation_size
); p
+= 8;
1901 SIVAL(p
,0,mode
); p
+= 4;
1902 q
= p
; p
+= 4; /* q is placeholder for name length. */
1904 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1905 smb_fname
->base_name
);
1906 SIVAL(p
,0,ea_size
); /* Extended attributes */
1909 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1910 SBVAL(p
,0,file_index
); p
+= 8;
1911 len
= srvstr_push(base_data
, flags2
, p
,
1912 fname
, PTR_DIFF(end_data
, p
),
1913 STR_TERMINATE_ASCII
);
1917 len
= PTR_DIFF(p
, pdata
);
1918 pad
= (len
+ (align
-1)) & ~(align
-1);
1920 * offset to the next entry, the caller
1921 * will overwrite it for the last entry
1922 * that's why we always include the padding
1926 * set padding to zero
1929 memset(p
, 0, pad
- len
);
1936 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1937 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1938 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1940 SIVAL(p
,0,reskey
); p
+= 4;
1941 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1942 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1943 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1944 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1945 SOFF_T(p
,0,file_size
); p
+= 8;
1946 SOFF_T(p
,0,allocation_size
); p
+= 8;
1947 SIVAL(p
,0,mode
); p
+= 4;
1948 q
= p
; p
+= 4; /* q is placeholder for name length */
1950 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1951 smb_fname
->base_name
);
1952 SIVAL(p
,0,ea_size
); /* Extended attributes */
1955 /* Clear the short name buffer. This is
1956 * IMPORTANT as not doing so will trigger
1957 * a Win2k client bug. JRA.
1959 if (!was_8_3
&& check_mangled_names
) {
1960 char mangled_name
[13]; /* mangled 8.3 name. */
1961 if (!name_to_8_3(fname
,mangled_name
,True
,
1963 /* Error - mangle failed ! */
1964 memset(mangled_name
,'\0',12);
1966 mangled_name
[12] = 0;
1967 len
= srvstr_push(base_data
, flags2
,
1968 p
+2, mangled_name
, 24,
1969 STR_UPPER
|STR_UNICODE
);
1972 memset(p
+ 2 + len
,'\0',24 - len
);
1979 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1980 SBVAL(p
,0,file_index
); p
+= 8;
1981 len
= srvstr_push(base_data
, flags2
, p
,
1982 fname
, PTR_DIFF(end_data
, p
),
1983 STR_TERMINATE_ASCII
);
1987 len
= PTR_DIFF(p
, pdata
);
1988 pad
= (len
+ (align
-1)) & ~(align
-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1996 * set padding to zero
1999 memset(p
, 0, pad
- len
);
2006 /* CIFS UNIX Extension. */
2008 case SMB_FIND_FILE_UNIX
:
2009 case SMB_FIND_FILE_UNIX_INFO2
:
2011 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2013 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2015 if (info_level
== SMB_FIND_FILE_UNIX
) {
2016 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2017 p
= store_file_unix_basic(conn
, p
,
2018 NULL
, &smb_fname
->st
);
2019 len
= srvstr_push(base_data
, flags2
, p
,
2020 fname
, PTR_DIFF(end_data
, p
),
2023 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2024 p
= store_file_unix_basic_info2(conn
, p
,
2025 NULL
, &smb_fname
->st
);
2028 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2029 PTR_DIFF(end_data
, p
), 0);
2030 SIVAL(nameptr
, 0, len
);
2035 len
= PTR_DIFF(p
, pdata
);
2036 pad
= (len
+ (align
-1)) & ~(align
-1);
2038 * offset to the next entry, the caller
2039 * will overwrite it for the last entry
2040 * that's why we always include the padding
2044 * set padding to zero
2047 memset(p
, 0, pad
- len
);
2052 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2060 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2061 *out_of_space
= true;
2062 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2063 "(wanted %u, had %d)\n",
2064 (unsigned int)PTR_DIFF(p
,pdata
),
2066 return false; /* Not finished - just out of space */
2069 /* Setup the last entry pointer, as an offset from base_data */
2070 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2071 /* Advance the data pointer to the next slot */
2077 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2078 connection_struct
*conn
,
2079 struct dptr_struct
*dirptr
,
2081 const char *path_mask
,
2084 int requires_resume_key
,
2092 int space_remaining
,
2094 bool *got_exact_match
,
2095 int *_last_entry_off
,
2096 struct ea_list
*name_list
)
2099 const char *mask
= NULL
;
2100 long prev_dirpos
= 0;
2103 struct smb_filename
*smb_fname
= NULL
;
2104 struct smbd_dirptr_lanman2_state state
;
2106 uint64_t last_entry_off
= 0;
2110 state
.info_level
= info_level
;
2111 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2112 state
.has_wild
= dptr_has_wild(dirptr
);
2113 state
.got_exact_match
= false;
2115 *out_of_space
= false;
2116 *got_exact_match
= false;
2118 p
= strrchr_m(path_mask
,'/');
2129 ok
= smbd_dirptr_get_entry(ctx
,
2135 smbd_dirptr_lanman2_match_fn
,
2136 smbd_dirptr_lanman2_mode_fn
,
2146 *got_exact_match
= state
.got_exact_match
;
2148 ok
= smbd_marshall_dir_entry(ctx
,
2153 state
.check_mangled_names
,
2154 requires_resume_key
,
2167 TALLOC_FREE(smb_fname
);
2168 if (*out_of_space
) {
2169 dptr_SeekDir(dirptr
, prev_dirpos
);
2176 *_last_entry_off
= last_entry_off
;
2180 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2181 connection_struct
*conn
,
2182 struct dptr_struct
*dirptr
,
2184 const char *path_mask
,
2187 bool requires_resume_key
,
2193 int space_remaining
,
2195 bool *got_exact_match
,
2196 int *last_entry_off
,
2197 struct ea_list
*name_list
)
2200 const bool do_pad
= true;
2202 if (info_level
>= 1 && info_level
<= 3) {
2203 /* No alignment on earlier info levels. */
2207 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2208 path_mask
, dirtype
, info_level
,
2209 requires_resume_key
, dont_descend
, ask_sharemode
,
2211 ppdata
, base_data
, end_data
,
2213 out_of_space
, got_exact_match
,
2214 last_entry_off
, name_list
);
2217 /****************************************************************************
2218 Reply to a TRANS2_FINDFIRST.
2219 ****************************************************************************/
2221 static void call_trans2findfirst(connection_struct
*conn
,
2222 struct smb_request
*req
,
2223 char **pparams
, int total_params
,
2224 char **ppdata
, int total_data
,
2225 unsigned int max_data_bytes
)
2227 /* We must be careful here that we don't return more than the
2228 allowed number of data bytes. If this means returning fewer than
2229 maxentries then so be it. We assume that the redirector has
2230 enough room for the fixed number of parameter bytes it has
2232 struct smb_filename
*smb_dname
= NULL
;
2233 char *params
= *pparams
;
2234 char *pdata
= *ppdata
;
2238 uint16 findfirst_flags
;
2239 bool close_after_first
;
2241 bool requires_resume_key
;
2243 char *directory
= NULL
;
2246 int last_entry_off
=0;
2250 bool finished
= False
;
2251 bool dont_descend
= False
;
2252 bool out_of_space
= False
;
2253 int space_remaining
;
2254 bool mask_contains_wcard
= False
;
2255 struct ea_list
*ea_list
= NULL
;
2256 NTSTATUS ntstatus
= NT_STATUS_OK
;
2257 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2258 TALLOC_CTX
*ctx
= talloc_tos();
2259 struct dptr_struct
*dirptr
= NULL
;
2260 struct smbd_server_connection
*sconn
= req
->sconn
;
2262 if (total_params
< 13) {
2263 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2267 dirtype
= SVAL(params
,0);
2268 maxentries
= SVAL(params
,2);
2269 findfirst_flags
= SVAL(params
,4);
2270 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2271 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2272 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2273 info_level
= SVAL(params
,6);
2275 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2276 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2277 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2278 info_level
, max_data_bytes
));
2281 /* W2K3 seems to treat zero as 1. */
2285 switch (info_level
) {
2286 case SMB_FIND_INFO_STANDARD
:
2287 case SMB_FIND_EA_SIZE
:
2288 case SMB_FIND_EA_LIST
:
2289 case SMB_FIND_FILE_DIRECTORY_INFO
:
2290 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2291 case SMB_FIND_FILE_NAMES_INFO
:
2292 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2293 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2294 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2296 case SMB_FIND_FILE_UNIX
:
2297 case SMB_FIND_FILE_UNIX_INFO2
:
2298 /* Always use filesystem for UNIX mtime query. */
2299 ask_sharemode
= false;
2300 if (!lp_unix_extensions()) {
2301 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2306 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2310 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2311 params
+12, total_params
- 12,
2312 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2313 if (!NT_STATUS_IS_OK(ntstatus
)) {
2314 reply_nterror(req
, ntstatus
);
2318 ntstatus
= filename_convert(ctx
, conn
,
2319 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2322 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2323 &mask_contains_wcard
,
2325 if (!NT_STATUS_IS_OK(ntstatus
)) {
2326 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2327 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2328 ERRSRV
, ERRbadpath
);
2331 reply_nterror(req
, ntstatus
);
2335 mask
= smb_dname
->original_lcomp
;
2337 directory
= smb_dname
->base_name
;
2339 p
= strrchr_m(directory
,'/');
2341 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2342 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2343 mask
= talloc_strdup(ctx
,"*");
2345 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2348 mask_contains_wcard
= True
;
2350 directory
= talloc_strdup(talloc_tos(), "./");
2352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2359 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2361 if (info_level
== SMB_FIND_EA_LIST
) {
2364 if (total_data
< 4) {
2365 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2369 ea_size
= IVAL(pdata
,0);
2370 if (ea_size
!= total_data
) {
2371 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2372 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2373 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2377 if (!lp_ea_support(SNUM(conn
))) {
2378 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2382 /* Pull out the list of names. */
2383 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2390 *ppdata
= (char *)SMB_REALLOC(
2391 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2392 if(*ppdata
== NULL
) {
2393 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2397 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2399 /* Realloc the params space */
2400 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2401 if (*pparams
== NULL
) {
2402 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2407 /* Save the wildcard match and attribs we are using on this directory -
2408 needed as lanman2 assumes these are being saved between calls */
2410 ntstatus
= dptr_create(conn
,
2416 mask_contains_wcard
,
2420 if (!NT_STATUS_IS_OK(ntstatus
)) {
2421 reply_nterror(req
, ntstatus
);
2425 dptr_num
= dptr_dnum(dirptr
);
2426 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2428 /* Initialize per TRANS2_FIND_FIRST operation data */
2429 dptr_init_search_op(dirptr
);
2431 /* We don't need to check for VOL here as this is returned by
2432 a different TRANS2 call. */
2434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2435 directory
,lp_dontdescend(SNUM(conn
))));
2436 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2437 dont_descend
= True
;
2440 space_remaining
= max_data_bytes
;
2441 out_of_space
= False
;
2443 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2444 bool got_exact_match
= False
;
2446 /* this is a heuristic to avoid seeking the dirptr except when
2447 absolutely necessary. It allows for a filename of about 40 chars */
2448 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2449 out_of_space
= True
;
2452 finished
= !get_lanman2_dir_entry(ctx
,
2456 mask
,dirtype
,info_level
,
2457 requires_resume_key
,dont_descend
,
2460 space_remaining
, &out_of_space
,
2462 &last_entry_off
, ea_list
);
2465 if (finished
&& out_of_space
)
2468 if (!finished
&& !out_of_space
)
2472 * As an optimisation if we know we aren't looking
2473 * for a wildcard name (ie. the name matches the wildcard exactly)
2474 * then we can finish on any (first) match.
2475 * This speeds up large directory searches. JRA.
2481 /* Ensure space_remaining never goes -ve. */
2482 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2483 space_remaining
= 0;
2484 out_of_space
= true;
2486 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2490 /* Check if we can close the dirptr */
2491 if(close_after_first
|| (finished
&& close_if_end
)) {
2492 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2493 dptr_close(sconn
, &dptr_num
);
2497 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2498 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2499 * the protocol level is less than NT1. Tested with smbclient. JRA.
2500 * This should fix the OS/2 client bug #2335.
2503 if(numentries
== 0) {
2504 dptr_close(sconn
, &dptr_num
);
2505 if (get_Protocol() < PROTOCOL_NT1
) {
2506 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2509 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2510 ERRDOS
, ERRbadfile
);
2515 /* At this point pdata points to numentries directory entries. */
2517 /* Set up the return parameter block */
2518 SSVAL(params
,0,dptr_num
);
2519 SSVAL(params
,2,numentries
);
2520 SSVAL(params
,4,finished
);
2521 SSVAL(params
,6,0); /* Never an EA error */
2522 SSVAL(params
,8,last_entry_off
);
2524 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2527 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2528 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2530 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2534 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2535 smb_fn_name(req
->cmd
),
2536 mask
, directory
, dirtype
, numentries
) );
2539 * Force a name mangle here to ensure that the
2540 * mask as an 8.3 name is top of the mangled cache.
2541 * The reasons for this are subtle. Don't remove
2542 * this code unless you know what you are doing
2543 * (see PR#13758). JRA.
2546 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2547 char mangled_name
[13];
2548 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2551 TALLOC_FREE(smb_dname
);
2555 /****************************************************************************
2556 Reply to a TRANS2_FINDNEXT.
2557 ****************************************************************************/
2559 static void call_trans2findnext(connection_struct
*conn
,
2560 struct smb_request
*req
,
2561 char **pparams
, int total_params
,
2562 char **ppdata
, int total_data
,
2563 unsigned int max_data_bytes
)
2565 /* We must be careful here that we don't return more than the
2566 allowed number of data bytes. If this means returning fewer than
2567 maxentries then so be it. We assume that the redirector has
2568 enough room for the fixed number of parameter bytes it has
2570 char *params
= *pparams
;
2571 char *pdata
= *ppdata
;
2577 uint16 findnext_flags
;
2578 bool close_after_request
;
2580 bool requires_resume_key
;
2582 bool mask_contains_wcard
= False
;
2583 char *resume_name
= NULL
;
2584 const char *mask
= NULL
;
2585 const char *directory
= NULL
;
2589 int i
, last_entry_off
=0;
2590 bool finished
= False
;
2591 bool dont_descend
= False
;
2592 bool out_of_space
= False
;
2593 int space_remaining
;
2594 struct ea_list
*ea_list
= NULL
;
2595 NTSTATUS ntstatus
= NT_STATUS_OK
;
2596 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2597 TALLOC_CTX
*ctx
= talloc_tos();
2598 struct dptr_struct
*dirptr
;
2599 struct smbd_server_connection
*sconn
= req
->sconn
;
2601 if (total_params
< 13) {
2602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2606 dptr_num
= SVAL(params
,0);
2607 maxentries
= SVAL(params
,2);
2608 info_level
= SVAL(params
,4);
2609 resume_key
= IVAL(params
,6);
2610 findnext_flags
= SVAL(params
,10);
2611 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2612 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2613 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2614 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2616 if (!continue_bit
) {
2617 /* We only need resume_name if continue_bit is zero. */
2618 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2620 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2621 &mask_contains_wcard
);
2622 if (!NT_STATUS_IS_OK(ntstatus
)) {
2623 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2624 complain (it thinks we're asking for the directory above the shared
2625 path or an invalid name). Catch this as the resume name is only compared, never used in
2626 a file access. JRA. */
2627 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2628 &resume_name
, params
+12,
2632 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2633 reply_nterror(req
, ntstatus
);
2639 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2640 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2641 resume_key = %d resume name = %s continue=%d level = %d\n",
2642 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2643 requires_resume_key
, resume_key
,
2644 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2647 /* W2K3 seems to treat zero as 1. */
2651 switch (info_level
) {
2652 case SMB_FIND_INFO_STANDARD
:
2653 case SMB_FIND_EA_SIZE
:
2654 case SMB_FIND_EA_LIST
:
2655 case SMB_FIND_FILE_DIRECTORY_INFO
:
2656 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2657 case SMB_FIND_FILE_NAMES_INFO
:
2658 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2659 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2660 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2662 case SMB_FIND_FILE_UNIX
:
2663 case SMB_FIND_FILE_UNIX_INFO2
:
2664 /* Always use filesystem for UNIX mtime query. */
2665 ask_sharemode
= false;
2666 if (!lp_unix_extensions()) {
2667 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2672 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2676 if (info_level
== SMB_FIND_EA_LIST
) {
2679 if (total_data
< 4) {
2680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2684 ea_size
= IVAL(pdata
,0);
2685 if (ea_size
!= total_data
) {
2686 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2687 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2692 if (!lp_ea_support(SNUM(conn
))) {
2693 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2697 /* Pull out the list of names. */
2698 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2700 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2705 *ppdata
= (char *)SMB_REALLOC(
2706 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2707 if(*ppdata
== NULL
) {
2708 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2713 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2715 /* Realloc the params space */
2716 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2717 if(*pparams
== NULL
) {
2718 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2724 /* Check that the dptr is valid */
2725 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2726 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2730 directory
= dptr_path(sconn
, dptr_num
);
2732 /* Get the wildcard mask from the dptr */
2733 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2734 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2735 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2741 /* Get the attr mask from the dptr */
2742 dirtype
= dptr_attr(sconn
, dptr_num
);
2744 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2745 dptr_num
, mask
, dirtype
,
2747 dptr_TellDir(dirptr
)));
2749 /* Initialize per TRANS2_FIND_NEXT operation data */
2750 dptr_init_search_op(dirptr
);
2752 /* We don't need to check for VOL here as this is returned by
2753 a different TRANS2 call. */
2755 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2756 directory
,lp_dontdescend(SNUM(conn
))));
2757 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2758 dont_descend
= True
;
2761 space_remaining
= max_data_bytes
;
2762 out_of_space
= False
;
2765 * Seek to the correct position. We no longer use the resume key but
2766 * depend on the last file name instead.
2769 if(!continue_bit
&& resume_name
&& *resume_name
) {
2772 long current_pos
= 0;
2774 * Remember, name_to_8_3 is called by
2775 * get_lanman2_dir_entry(), so the resume name
2776 * could be mangled. Ensure we check the unmangled name.
2779 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2780 char *new_resume_name
= NULL
;
2781 mangle_lookup_name_from_8_3(ctx
,
2785 if (new_resume_name
) {
2786 resume_name
= new_resume_name
;
2791 * Fix for NT redirector problem triggered by resume key indexes
2792 * changing between directory scans. We now return a resume key of 0
2793 * and instead look for the filename to continue from (also given
2794 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2795 * findfirst/findnext (as is usual) then the directory pointer
2796 * should already be at the correct place.
2799 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2800 } /* end if resume_name && !continue_bit */
2802 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2803 bool got_exact_match
= False
;
2805 /* this is a heuristic to avoid seeking the dirptr except when
2806 absolutely necessary. It allows for a filename of about 40 chars */
2807 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2808 out_of_space
= True
;
2811 finished
= !get_lanman2_dir_entry(ctx
,
2815 mask
,dirtype
,info_level
,
2816 requires_resume_key
,dont_descend
,
2819 space_remaining
, &out_of_space
,
2821 &last_entry_off
, ea_list
);
2824 if (finished
&& out_of_space
)
2827 if (!finished
&& !out_of_space
)
2831 * As an optimisation if we know we aren't looking
2832 * for a wildcard name (ie. the name matches the wildcard exactly)
2833 * then we can finish on any (first) match.
2834 * This speeds up large directory searches. JRA.
2840 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2843 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2844 smb_fn_name(req
->cmd
),
2845 mask
, directory
, dirtype
, numentries
) );
2847 /* Check if we can close the dirptr */
2848 if(close_after_request
|| (finished
&& close_if_end
)) {
2849 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2850 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2853 /* Set up the return parameter block */
2854 SSVAL(params
,0,numentries
);
2855 SSVAL(params
,2,finished
);
2856 SSVAL(params
,4,0); /* Never an EA error */
2857 SSVAL(params
,6,last_entry_off
);
2859 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2865 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2867 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2871 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2873 SMB_ASSERT(extended_info
!= NULL
);
2875 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2876 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2877 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2878 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2879 #ifdef SAMBA_VERSION_REVISION
2880 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2882 extended_info
->samba_subversion
= 0;
2883 #ifdef SAMBA_VERSION_RC_RELEASE
2884 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2886 #ifdef SAMBA_VERSION_PRE_RELEASE
2887 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2890 #ifdef SAMBA_VERSION_VENDOR_PATCH
2891 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2893 extended_info
->samba_gitcommitdate
= 0;
2894 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2895 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2898 memset(extended_info
->samba_version_string
, 0,
2899 sizeof(extended_info
->samba_version_string
));
2901 snprintf (extended_info
->samba_version_string
,
2902 sizeof(extended_info
->samba_version_string
),
2903 "%s", samba_version_string());
2906 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2907 TALLOC_CTX
*mem_ctx
,
2908 uint16_t info_level
,
2910 unsigned int max_data_bytes
,
2914 char *pdata
, *end_data
;
2915 int data_len
= 0, len
;
2916 const char *vname
= volume_label(SNUM(conn
));
2917 int snum
= SNUM(conn
);
2918 char *fstype
= lp_fstype(SNUM(conn
));
2919 uint32 additional_flags
= 0;
2920 struct smb_filename smb_fname_dot
;
2924 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2925 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2926 "info level (0x%x) on IPC$.\n",
2927 (unsigned int)info_level
));
2928 return NT_STATUS_ACCESS_DENIED
;
2932 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2934 ZERO_STRUCT(smb_fname_dot
);
2935 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2937 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2938 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2939 return map_nt_error_from_unix(errno
);
2942 st
= smb_fname_dot
.st
;
2944 *ppdata
= (char *)SMB_REALLOC(
2945 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2946 if (*ppdata
== NULL
) {
2947 return NT_STATUS_NO_MEMORY
;
2951 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2952 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2954 switch (info_level
) {
2955 case SMB_INFO_ALLOCATION
:
2957 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2959 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2960 return map_nt_error_from_unix(errno
);
2963 block_size
= lp_block_size(snum
);
2964 if (bsize
< block_size
) {
2965 uint64_t factor
= block_size
/bsize
;
2970 if (bsize
> block_size
) {
2971 uint64_t factor
= bsize
/block_size
;
2976 bytes_per_sector
= 512;
2977 sectors_per_unit
= bsize
/bytes_per_sector
;
2979 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2980 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2981 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2983 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2984 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2985 SIVAL(pdata
,l1_cUnit
,dsize
);
2986 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2987 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2991 case SMB_INFO_VOLUME
:
2992 /* Return volume name */
2994 * Add volume serial number - hash of a combination of
2995 * the called hostname and the service name.
2997 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2999 * Win2k3 and previous mess this up by sending a name length
3000 * one byte short. I believe only older clients (OS/2 Win9x) use
3001 * this call so try fixing this by adding a terminating null to
3002 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3006 pdata
+l2_vol_szVolLabel
, vname
,
3007 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3008 STR_NOALIGN
|STR_TERMINATE
);
3009 SCVAL(pdata
,l2_vol_cch
,len
);
3010 data_len
= l2_vol_szVolLabel
+ len
;
3011 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3012 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3016 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3017 case SMB_FS_ATTRIBUTE_INFORMATION
:
3019 additional_flags
= 0;
3020 #if defined(HAVE_SYS_QUOTAS)
3021 additional_flags
|= FILE_VOLUME_QUOTAS
;
3024 if(lp_nt_acl_support(SNUM(conn
))) {
3025 additional_flags
|= FILE_PERSISTENT_ACLS
;
3028 /* Capabilities are filled in at connection time through STATVFS call */
3029 additional_flags
|= conn
->fs_capabilities
;
3030 additional_flags
|= lp_parm_int(conn
->params
->service
,
3031 "share", "fake_fscaps",
3034 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3035 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3036 additional_flags
); /* FS ATTRIBUTES */
3038 SIVAL(pdata
,4,255); /* Max filename component length */
3039 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3040 and will think we can't do long filenames */
3041 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3042 PTR_DIFF(end_data
, pdata
+12),
3045 data_len
= 12 + len
;
3048 case SMB_QUERY_FS_LABEL_INFO
:
3049 case SMB_FS_LABEL_INFORMATION
:
3050 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3051 PTR_DIFF(end_data
, pdata
+4), 0);
3056 case SMB_QUERY_FS_VOLUME_INFO
:
3057 case SMB_FS_VOLUME_INFORMATION
:
3060 * Add volume serial number - hash of a combination of
3061 * the called hostname and the service name.
3063 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3064 (str_checksum(get_local_machine_name())<<16));
3066 /* Max label len is 32 characters. */
3067 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3068 PTR_DIFF(end_data
, pdata
+18),
3070 SIVAL(pdata
,12,len
);
3073 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3074 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3077 case SMB_QUERY_FS_SIZE_INFO
:
3078 case SMB_FS_SIZE_INFORMATION
:
3080 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3082 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno
);
3085 block_size
= lp_block_size(snum
);
3086 if (bsize
< block_size
) {
3087 uint64_t factor
= block_size
/bsize
;
3092 if (bsize
> block_size
) {
3093 uint64_t factor
= bsize
/block_size
;
3098 bytes_per_sector
= 512;
3099 sectors_per_unit
= bsize
/bytes_per_sector
;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3102 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3103 SBIG_UINT(pdata
,0,dsize
);
3104 SBIG_UINT(pdata
,8,dfree
);
3105 SIVAL(pdata
,16,sectors_per_unit
);
3106 SIVAL(pdata
,20,bytes_per_sector
);
3110 case SMB_FS_FULL_SIZE_INFORMATION
:
3112 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3114 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3115 return map_nt_error_from_unix(errno
);
3117 block_size
= lp_block_size(snum
);
3118 if (bsize
< block_size
) {
3119 uint64_t factor
= block_size
/bsize
;
3124 if (bsize
> block_size
) {
3125 uint64_t factor
= bsize
/block_size
;
3130 bytes_per_sector
= 512;
3131 sectors_per_unit
= bsize
/bytes_per_sector
;
3132 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3133 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3134 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3135 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3136 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3137 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3138 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3139 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3143 case SMB_QUERY_FS_DEVICE_INFO
:
3144 case SMB_FS_DEVICE_INFORMATION
:
3146 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3148 if (!CAN_WRITE(conn
)) {
3149 characteristics
|= FILE_READ_ONLY_DEVICE
;
3152 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3153 SIVAL(pdata
,4,characteristics
);
3157 #ifdef HAVE_SYS_QUOTAS
3158 case SMB_FS_QUOTA_INFORMATION
:
3160 * what we have to send --metze:
3162 * Unknown1: 24 NULL bytes
3163 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3164 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3165 * Quota Flags: 2 byte :
3166 * Unknown3: 6 NULL bytes
3170 * details for Quota Flags:
3172 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3173 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3174 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3175 * 0x0001 Enable Quotas: enable quota for this fs
3179 /* we need to fake up a fsp here,
3180 * because its not send in this call
3183 SMB_NTQUOTA_STRUCT quotas
;
3186 ZERO_STRUCT(quotas
);
3192 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3193 DEBUG(0,("set_user_quota: access_denied "
3194 "service [%s] user [%s]\n",
3195 lp_servicename(SNUM(conn
)),
3196 conn
->server_info
->unix_name
));
3197 return NT_STATUS_ACCESS_DENIED
;
3200 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3201 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3202 return map_nt_error_from_unix(errno
);
3207 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3208 lp_servicename(SNUM(conn
))));
3210 /* Unknown1 24 NULL bytes*/
3211 SBIG_UINT(pdata
,0,(uint64_t)0);
3212 SBIG_UINT(pdata
,8,(uint64_t)0);
3213 SBIG_UINT(pdata
,16,(uint64_t)0);
3215 /* Default Soft Quota 8 bytes */
3216 SBIG_UINT(pdata
,24,quotas
.softlim
);
3218 /* Default Hard Quota 8 bytes */
3219 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3221 /* Quota flag 2 bytes */
3222 SSVAL(pdata
,40,quotas
.qflags
);
3224 /* Unknown3 6 NULL bytes */
3230 #endif /* HAVE_SYS_QUOTAS */
3231 case SMB_FS_OBJECTID_INFORMATION
:
3233 unsigned char objid
[16];
3234 struct smb_extended_info extended_info
;
3235 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3236 samba_extended_info_version (&extended_info
);
3237 SIVAL(pdata
,16,extended_info
.samba_magic
);
3238 SIVAL(pdata
,20,extended_info
.samba_version
);
3239 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3240 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3241 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3247 * Query the version and capabilities of the CIFS UNIX extensions
3251 case SMB_QUERY_CIFS_UNIX_INFO
:
3253 bool large_write
= lp_min_receive_file_size() &&
3254 !srv_is_signing_active(smbd_server_conn
);
3255 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3256 int encrypt_caps
= 0;
3258 if (!lp_unix_extensions()) {
3259 return NT_STATUS_INVALID_LEVEL
;
3262 switch (conn
->encrypt_level
) {
3268 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3271 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3272 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3273 large_write
= false;
3279 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3280 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3282 /* We have POSIX ACLs, pathname, encryption,
3283 * large read/write, and locking capability. */
3285 SBIG_UINT(pdata
,4,((uint64_t)(
3286 CIFS_UNIX_POSIX_ACLS_CAP
|
3287 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3288 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3289 CIFS_UNIX_EXTATTR_CAP
|
3290 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3292 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3294 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3298 case SMB_QUERY_POSIX_FS_INFO
:
3301 vfs_statvfs_struct svfs
;
3303 if (!lp_unix_extensions()) {
3304 return NT_STATUS_INVALID_LEVEL
;
3307 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3311 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3312 SIVAL(pdata
,4,svfs
.BlockSize
);
3313 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3314 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3315 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3316 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3317 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3318 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3321 } else if (rc
== EOPNOTSUPP
) {
3322 return NT_STATUS_INVALID_LEVEL
;
3323 #endif /* EOPNOTSUPP */
3325 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3326 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3331 case SMB_QUERY_POSIX_WHOAMI
:
3337 if (!lp_unix_extensions()) {
3338 return NT_STATUS_INVALID_LEVEL
;
3341 if (max_data_bytes
< 40) {
3342 return NT_STATUS_BUFFER_TOO_SMALL
;
3345 /* We ARE guest if global_sid_Builtin_Guests is
3346 * in our list of SIDs.
3348 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3349 conn
->server_info
->ptok
)) {
3350 flags
|= SMB_WHOAMI_GUEST
;
3353 /* We are NOT guest if global_sid_Authenticated_Users
3354 * is in our list of SIDs.
3356 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3357 conn
->server_info
->ptok
)) {
3358 flags
&= ~SMB_WHOAMI_GUEST
;
3361 /* NOTE: 8 bytes for UID/GID, irrespective of native
3362 * platform size. This matches
3363 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3365 data_len
= 4 /* flags */
3372 + 4 /* pad/reserved */
3373 + (conn
->server_info
->utok
.ngroups
* 8)
3375 + (conn
->server_info
->ptok
->num_sids
*
3379 SIVAL(pdata
, 0, flags
);
3380 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3382 (uint64_t)conn
->server_info
->utok
.uid
);
3383 SBIG_UINT(pdata
, 16,
3384 (uint64_t)conn
->server_info
->utok
.gid
);
3387 if (data_len
>= max_data_bytes
) {
3388 /* Potential overflow, skip the GIDs and SIDs. */
3390 SIVAL(pdata
, 24, 0); /* num_groups */
3391 SIVAL(pdata
, 28, 0); /* num_sids */
3392 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3393 SIVAL(pdata
, 36, 0); /* reserved */
3399 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3400 SIVAL(pdata
, 28, conn
->server_info
->ptok
->num_sids
);
3402 /* We walk the SID list twice, but this call is fairly
3403 * infrequent, and I don't expect that it's performance
3404 * sensitive -- jpeach
3406 for (i
= 0, sid_bytes
= 0;
3407 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3408 sid_bytes
+= ndr_size_dom_sid(
3409 &conn
->server_info
->ptok
->user_sids
[i
],
3413 /* SID list byte count */
3414 SIVAL(pdata
, 32, sid_bytes
);
3416 /* 4 bytes pad/reserved - must be zero */
3417 SIVAL(pdata
, 36, 0);
3421 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3422 SBIG_UINT(pdata
, data_len
,
3423 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3429 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3430 int sid_len
= ndr_size_dom_sid(
3431 &conn
->server_info
->ptok
->user_sids
[i
],
3434 sid_linearize(pdata
+ data_len
, sid_len
,
3435 &conn
->server_info
->ptok
->user_sids
[i
]);
3436 data_len
+= sid_len
;
3442 case SMB_MAC_QUERY_FS_INFO
:
3444 * Thursby MAC extension... ONLY on NTFS filesystems
3445 * once we do streams then we don't need this
3447 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3449 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3454 return NT_STATUS_INVALID_LEVEL
;
3457 *ret_data_len
= data_len
;
3458 return NT_STATUS_OK
;
3461 /****************************************************************************
3462 Reply to a TRANS2_QFSINFO (query filesystem info).
3463 ****************************************************************************/
3465 static void call_trans2qfsinfo(connection_struct
*conn
,
3466 struct smb_request
*req
,
3467 char **pparams
, int total_params
,
3468 char **ppdata
, int total_data
,
3469 unsigned int max_data_bytes
)
3471 char *params
= *pparams
;
3472 uint16_t info_level
;
3476 if (total_params
< 2) {
3477 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3481 info_level
= SVAL(params
,0);
3483 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3484 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3485 DEBUG(0,("call_trans2qfsinfo: encryption required "
3486 "and info level 0x%x sent.\n",
3487 (unsigned int)info_level
));
3488 exit_server_cleanly("encryption required "
3494 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3496 status
= smbd_do_qfsinfo(conn
, req
,
3501 if (!NT_STATUS_IS_OK(status
)) {
3502 reply_nterror(req
, status
);
3506 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3509 DEBUG( 4, ( "%s info_level = %d\n",
3510 smb_fn_name(req
->cmd
), info_level
) );
3515 /****************************************************************************
3516 Reply to a TRANS2_SETFSINFO (set filesystem info).
3517 ****************************************************************************/
3519 static void call_trans2setfsinfo(connection_struct
*conn
,
3520 struct smb_request
*req
,
3521 char **pparams
, int total_params
,
3522 char **ppdata
, int total_data
,
3523 unsigned int max_data_bytes
)
3525 char *pdata
= *ppdata
;
3526 char *params
= *pparams
;
3529 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3532 if (total_params
< 4) {
3533 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3539 info_level
= SVAL(params
,2);
3542 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3543 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3544 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3545 "info level (0x%x) on IPC$.\n",
3546 (unsigned int)info_level
));
3547 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3552 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3553 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3554 DEBUG(0,("call_trans2setfsinfo: encryption required "
3555 "and info level 0x%x sent.\n",
3556 (unsigned int)info_level
));
3557 exit_server_cleanly("encryption required "
3563 switch(info_level
) {
3564 case SMB_SET_CIFS_UNIX_INFO
:
3566 uint16 client_unix_major
;
3567 uint16 client_unix_minor
;
3568 uint32 client_unix_cap_low
;
3569 uint32 client_unix_cap_high
;
3571 if (!lp_unix_extensions()) {
3573 NT_STATUS_INVALID_LEVEL
);
3577 /* There should be 12 bytes of capabilities set. */
3578 if (total_data
< 8) {
3581 NT_STATUS_INVALID_PARAMETER
);
3584 client_unix_major
= SVAL(pdata
,0);
3585 client_unix_minor
= SVAL(pdata
,2);
3586 client_unix_cap_low
= IVAL(pdata
,4);
3587 client_unix_cap_high
= IVAL(pdata
,8);
3588 /* Just print these values for now. */
3589 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3590 cap_low = 0x%x, cap_high = 0x%x\n",
3591 (unsigned int)client_unix_major
,
3592 (unsigned int)client_unix_minor
,
3593 (unsigned int)client_unix_cap_low
,
3594 (unsigned int)client_unix_cap_high
));
3596 /* Here is where we must switch to posix pathname processing... */
3597 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3598 lp_set_posix_pathnames();
3599 mangle_change_to_posix();
3602 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3603 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3604 /* Client that knows how to do posix locks,
3605 * but not posix open/mkdir operations. Set a
3606 * default type for read/write checks. */
3608 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3614 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3617 size_t param_len
= 0;
3618 size_t data_len
= total_data
;
3620 if (!lp_unix_extensions()) {
3623 NT_STATUS_INVALID_LEVEL
);
3627 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3630 NT_STATUS_NOT_SUPPORTED
);
3634 if (smbd_server_conn
->smb1
.echo_handler
.trusted_fde
) {
3635 DEBUG( 2,("call_trans2setfsinfo: "
3636 "request transport encryption disabled"
3637 "with 'fork echo handler = yes'\n"));
3640 NT_STATUS_NOT_SUPPORTED
);
3644 DEBUG( 4,("call_trans2setfsinfo: "
3645 "request transport encryption.\n"));
3647 status
= srv_request_encryption_setup(conn
,
3648 (unsigned char **)ppdata
,
3650 (unsigned char **)pparams
,
3653 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3654 !NT_STATUS_IS_OK(status
)) {
3655 reply_nterror(req
, status
);
3659 send_trans2_replies(conn
, req
,
3666 if (NT_STATUS_IS_OK(status
)) {
3667 /* Server-side transport
3668 * encryption is now *on*. */
3669 status
= srv_encryption_start(conn
);
3670 if (!NT_STATUS_IS_OK(status
)) {
3671 exit_server_cleanly(
3672 "Failure in setting "
3673 "up encrypted transport");
3679 case SMB_FS_QUOTA_INFORMATION
:
3681 files_struct
*fsp
= NULL
;
3682 SMB_NTQUOTA_STRUCT quotas
;
3684 ZERO_STRUCT(quotas
);
3687 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3688 ||!CAN_WRITE(conn
)) {
3689 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3690 lp_servicename(SNUM(conn
)),
3691 conn
->server_info
->unix_name
));
3692 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3696 /* note: normaly there're 48 bytes,
3697 * but we didn't use the last 6 bytes for now
3700 fsp
= file_fsp(req
, SVAL(params
,0));
3702 if (!check_fsp_ntquota_handle(conn
, req
,
3704 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3706 req
, NT_STATUS_INVALID_HANDLE
);
3710 if (total_data
< 42) {
3711 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3715 NT_STATUS_INVALID_PARAMETER
);
3719 /* unknown_1 24 NULL bytes in pdata*/
3721 /* the soft quotas 8 bytes (uint64_t)*/
3722 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3723 #ifdef LARGE_SMB_OFF_T
3724 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3725 #else /* LARGE_SMB_OFF_T */
3726 if ((IVAL(pdata
,28) != 0)&&
3727 ((quotas
.softlim
!= 0xFFFFFFFF)||
3728 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3729 /* more than 32 bits? */
3732 NT_STATUS_INVALID_PARAMETER
);
3735 #endif /* LARGE_SMB_OFF_T */
3737 /* the hard quotas 8 bytes (uint64_t)*/
3738 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3739 #ifdef LARGE_SMB_OFF_T
3740 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3741 #else /* LARGE_SMB_OFF_T */
3742 if ((IVAL(pdata
,36) != 0)&&
3743 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3744 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3745 /* more than 32 bits? */
3748 NT_STATUS_INVALID_PARAMETER
);
3751 #endif /* LARGE_SMB_OFF_T */
3753 /* quota_flags 2 bytes **/
3754 quotas
.qflags
= SVAL(pdata
,40);
3756 /* unknown_2 6 NULL bytes follow*/
3758 /* now set the quotas */
3759 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3760 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3761 reply_nterror(req
, map_nt_error_from_unix(errno
));
3768 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3770 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3776 * sending this reply works fine,
3777 * but I'm not sure it's the same
3778 * like windows do...
3781 reply_outbuf(req
, 10, 0);
3784 #if defined(HAVE_POSIX_ACLS)
3785 /****************************************************************************
3786 Utility function to count the number of entries in a POSIX acl.
3787 ****************************************************************************/
3789 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3791 unsigned int ace_count
= 0;
3792 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3793 SMB_ACL_ENTRY_T entry
;
3795 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3797 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3798 entry_id
= SMB_ACL_NEXT_ENTRY
;
3805 /****************************************************************************
3806 Utility function to marshall a POSIX acl into wire format.
3807 ****************************************************************************/
3809 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3811 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3812 SMB_ACL_ENTRY_T entry
;
3814 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3815 SMB_ACL_TAG_T tagtype
;
3816 SMB_ACL_PERMSET_T permset
;
3817 unsigned char perms
= 0;
3818 unsigned int own_grp
;
3821 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3822 entry_id
= SMB_ACL_NEXT_ENTRY
;
3825 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3830 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3835 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3836 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3837 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3839 SCVAL(pdata
,1,perms
);
3842 case SMB_ACL_USER_OBJ
:
3843 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3844 own_grp
= (unsigned int)pst
->st_ex_uid
;
3845 SIVAL(pdata
,2,own_grp
);
3850 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3852 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3855 own_grp
= (unsigned int)*puid
;
3856 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3857 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3858 SIVAL(pdata
,2,own_grp
);
3862 case SMB_ACL_GROUP_OBJ
:
3863 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3864 own_grp
= (unsigned int)pst
->st_ex_gid
;
3865 SIVAL(pdata
,2,own_grp
);
3870 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3875 own_grp
= (unsigned int)*pgid
;
3876 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3877 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3878 SIVAL(pdata
,2,own_grp
);
3883 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3884 SIVAL(pdata
,2,0xFFFFFFFF);
3885 SIVAL(pdata
,6,0xFFFFFFFF);
3888 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3889 SIVAL(pdata
,2,0xFFFFFFFF);
3890 SIVAL(pdata
,6,0xFFFFFFFF);
3893 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3896 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3903 /****************************************************************************
3904 Store the FILE_UNIX_BASIC info.
3905 ****************************************************************************/
3907 static char *store_file_unix_basic(connection_struct
*conn
,
3910 const SMB_STRUCT_STAT
*psbuf
)
3912 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3914 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3915 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3917 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3920 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3923 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3925 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3928 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3932 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3936 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3939 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3943 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3947 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
3950 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3954 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3961 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3962 * the chflags(2) (or equivalent) flags.
3964 * XXX: this really should be behind the VFS interface. To do this, we would
3965 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3966 * Each VFS module could then implement its own mapping as appropriate for the
3967 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3969 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3973 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3977 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3981 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3985 { UF_HIDDEN
, EXT_HIDDEN
},
3988 /* Do not remove. We need to guarantee that this array has at least one
3989 * entry to build on HP-UX.
3995 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3996 uint32
*smb_fflags
, uint32
*smb_fmask
)
4000 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4001 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4002 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4003 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4008 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4009 const uint32 smb_fflags
,
4010 const uint32 smb_fmask
,
4013 uint32 max_fmask
= 0;
4016 *stat_fflags
= psbuf
->st_ex_flags
;
4018 /* For each flags requested in smb_fmask, check the state of the
4019 * corresponding flag in smb_fflags and set or clear the matching
4023 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4024 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4025 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4026 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4027 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4029 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4034 /* If smb_fmask is asking to set any bits that are not supported by
4035 * our flag mappings, we should fail.
4037 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4045 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4046 * of file flags and birth (create) time.
4048 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4051 const SMB_STRUCT_STAT
*psbuf
)
4053 uint32 file_flags
= 0;
4054 uint32 flags_mask
= 0;
4056 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4058 /* Create (birth) time 64 bit */
4059 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4062 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4063 SIVAL(pdata
, 0, file_flags
); /* flags */
4064 SIVAL(pdata
, 4, flags_mask
); /* mask */
4070 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4071 const struct stream_struct
*streams
,
4073 unsigned int max_data_bytes
,
4074 unsigned int *data_size
)
4077 unsigned int ofs
= 0;
4079 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4080 unsigned int next_offset
;
4082 smb_ucs2_t
*namebuf
;
4084 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4085 streams
[i
].name
, &namelen
) ||
4088 return NT_STATUS_INVALID_PARAMETER
;
4092 * name_buf is now null-terminated, we need to marshall as not
4098 SIVAL(data
, ofs
+4, namelen
);
4099 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4100 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4101 memcpy(data
+ofs
+24, namebuf
, namelen
);
4102 TALLOC_FREE(namebuf
);
4104 next_offset
= ofs
+ 24 + namelen
;
4106 if (i
== num_streams
-1) {
4107 SIVAL(data
, ofs
, 0);
4110 unsigned int align
= ndr_align_size(next_offset
, 8);
4112 memset(data
+next_offset
, 0, align
);
4113 next_offset
+= align
;
4115 SIVAL(data
, ofs
, next_offset
- ofs
);
4124 return NT_STATUS_OK
;
4127 /****************************************************************************
4128 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4129 ****************************************************************************/
4131 static void call_trans2qpipeinfo(connection_struct
*conn
,
4132 struct smb_request
*req
,
4133 unsigned int tran_call
,
4134 char **pparams
, int total_params
,
4135 char **ppdata
, int total_data
,
4136 unsigned int max_data_bytes
)
4138 char *params
= *pparams
;
4139 char *pdata
= *ppdata
;
4140 unsigned int data_size
= 0;
4141 unsigned int param_size
= 2;
4146 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4150 if (total_params
< 4) {
4151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4155 fsp
= file_fsp(req
, SVAL(params
,0));
4156 if (!fsp_is_np(fsp
)) {
4157 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4161 info_level
= SVAL(params
,2);
4163 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4164 if (*pparams
== NULL
) {
4165 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4170 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4171 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4172 if (*ppdata
== NULL
) {
4173 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4178 switch (info_level
) {
4179 case SMB_FILE_STANDARD_INFORMATION
:
4181 SOFF_T(pdata
,0,4096LL);
4188 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4192 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4198 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4199 TALLOC_CTX
*mem_ctx
,
4200 uint16_t info_level
,
4202 struct smb_filename
*smb_fname
,
4203 bool delete_pending
,
4204 struct timespec write_time_ts
,
4205 struct ea_list
*ea_list
,
4206 int lock_data_count
,
4209 unsigned int max_data_bytes
,
4211 unsigned int *pdata_size
)
4213 char *pdata
= *ppdata
;
4214 char *dstart
, *dend
;
4215 unsigned int data_size
;
4216 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4217 time_t create_time
, mtime
, atime
, c_time
;
4218 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4225 uint64_t file_size
= 0;
4227 uint64_t allocation_size
= 0;
4228 uint64_t file_index
= 0;
4229 uint32_t access_mask
= 0;
4231 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4232 return NT_STATUS_INVALID_LEVEL
;
4235 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4236 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4237 info_level
, max_data_bytes
));
4239 mode
= dos_mode(conn
, smb_fname
);
4240 nlink
= psbuf
->st_ex_nlink
;
4242 if (nlink
&& (mode
&aDIR
)) {
4246 if ((nlink
> 0) && delete_pending
) {
4250 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4251 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4252 if (*ppdata
== NULL
) {
4253 return NT_STATUS_NO_MEMORY
;
4257 dend
= dstart
+ data_size
- 1;
4259 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4260 update_stat_ex_mtime(psbuf
, write_time_ts
);
4263 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4264 mtime_ts
= psbuf
->st_ex_mtime
;
4265 atime_ts
= psbuf
->st_ex_atime
;
4266 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4268 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4269 dos_filetime_timespec(&create_time_ts
);
4270 dos_filetime_timespec(&mtime_ts
);
4271 dos_filetime_timespec(&atime_ts
);
4272 dos_filetime_timespec(&ctime_ts
);
4275 create_time
= convert_timespec_to_time_t(create_time_ts
);
4276 mtime
= convert_timespec_to_time_t(mtime_ts
);
4277 atime
= convert_timespec_to_time_t(atime_ts
);
4278 c_time
= convert_timespec_to_time_t(ctime_ts
);
4280 p
= strrchr_m(smb_fname
->base_name
,'/');
4282 base_name
= smb_fname
->base_name
;
4286 /* NT expects the name to be in an exact form of the *full*
4287 filename. See the trans2 torture test */
4288 if (ISDOT(base_name
)) {
4289 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4291 return NT_STATUS_NO_MEMORY
;
4294 dos_fname
= talloc_asprintf(mem_ctx
,
4296 smb_fname
->base_name
);
4298 return NT_STATUS_NO_MEMORY
;
4300 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4301 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4302 smb_fname
->stream_name
);
4304 return NT_STATUS_NO_MEMORY
;
4308 string_replace(dos_fname
, '/', '\\');
4311 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4314 /* Do we have this path open ? */
4316 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4317 fsp1
= file_find_di_first(fileid
);
4318 if (fsp1
&& fsp1
->initial_allocation_size
) {
4319 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4323 if (!(mode
& aDIR
)) {
4324 file_size
= get_file_size_stat(psbuf
);
4328 pos
= fsp
->fh
->position_information
;
4332 access_mask
= fsp
->access_mask
;
4334 /* GENERIC_EXECUTE mapping from Windows */
4335 access_mask
= 0x12019F;
4338 /* This should be an index number - looks like
4341 I think this causes us to fail the IFSKIT
4342 BasicFileInformationTest. -tpot */
4343 file_index
= get_FileIndex(conn
, psbuf
);
4345 switch (info_level
) {
4346 case SMB_INFO_STANDARD
:
4347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4349 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4350 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4351 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4352 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4353 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4354 SSVAL(pdata
,l1_attrFile
,mode
);
4357 case SMB_INFO_QUERY_EA_SIZE
:
4359 unsigned int ea_size
=
4360 estimate_ea_size(conn
, fsp
,
4361 smb_fname
->base_name
);
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4364 srv_put_dos_date2(pdata
,0,create_time
);
4365 srv_put_dos_date2(pdata
,4,atime
);
4366 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4367 SIVAL(pdata
,12,(uint32
)file_size
);
4368 SIVAL(pdata
,16,(uint32
)allocation_size
);
4369 SSVAL(pdata
,20,mode
);
4370 SIVAL(pdata
,22,ea_size
);
4374 case SMB_INFO_IS_NAME_VALID
:
4375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4377 /* os/2 needs this ? really ?*/
4378 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4380 /* This is only reached for qpathinfo */
4384 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4386 size_t total_ea_len
= 0;
4387 struct ea_list
*ea_file_list
= NULL
;
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4392 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4393 smb_fname
->base_name
,
4395 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4397 if (!ea_list
|| (total_ea_len
> data_size
)) {
4399 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4403 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4407 case SMB_INFO_QUERY_ALL_EAS
:
4409 /* We have data_size bytes to put EA's into. */
4410 size_t total_ea_len
= 0;
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4414 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4415 smb_fname
->base_name
,
4417 if (!ea_list
|| (total_ea_len
> data_size
)) {
4419 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4423 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4427 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4429 /* This is FileFullEaInformation - 0xF which maps to
4430 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4432 /* We have data_size bytes to put EA's into. */
4433 size_t total_ea_len
= 0;
4434 struct ea_list
*ea_file_list
= NULL
;
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4438 /*TODO: add filtering and index handling */
4441 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4442 smb_fname
->base_name
,
4444 if (!ea_file_list
) {
4445 return NT_STATUS_NO_EAS_ON_FILE
;
4448 status
= fill_ea_chained_buffer(mem_ctx
,
4452 conn
, ea_file_list
);
4453 if (!NT_STATUS_IS_OK(status
)) {
4459 case SMB_FILE_BASIC_INFORMATION
:
4460 case SMB_QUERY_FILE_BASIC_INFO
:
4462 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4464 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4470 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4471 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4472 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4473 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4474 SIVAL(pdata
,32,mode
);
4476 DEBUG(5,("SMB_QFBI - "));
4477 DEBUG(5,("create: %s ", ctime(&create_time
)));
4478 DEBUG(5,("access: %s ", ctime(&atime
)));
4479 DEBUG(5,("write: %s ", ctime(&mtime
)));
4480 DEBUG(5,("change: %s ", ctime(&c_time
)));
4481 DEBUG(5,("mode: %x\n", mode
));
4484 case SMB_FILE_STANDARD_INFORMATION
:
4485 case SMB_QUERY_FILE_STANDARD_INFO
:
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4489 SOFF_T(pdata
,0,allocation_size
);
4490 SOFF_T(pdata
,8,file_size
);
4491 SIVAL(pdata
,16,nlink
);
4492 SCVAL(pdata
,20,delete_pending
?1:0);
4493 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4494 SSVAL(pdata
,22,0); /* Padding. */
4497 case SMB_FILE_EA_INFORMATION
:
4498 case SMB_QUERY_FILE_EA_INFO
:
4500 unsigned int ea_size
=
4501 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4504 SIVAL(pdata
,0,ea_size
);
4508 /* Get the 8.3 name - used if NT SMB was negotiated. */
4509 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4510 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4513 char mangled_name
[13];
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4515 if (!name_to_8_3(base_name
,mangled_name
,
4516 True
,conn
->params
)) {
4517 return NT_STATUS_NO_MEMORY
;
4519 len
= srvstr_push(dstart
, flags2
,
4520 pdata
+4, mangled_name
,
4521 PTR_DIFF(dend
, pdata
+4),
4523 data_size
= 4 + len
;
4528 case SMB_QUERY_FILE_NAME_INFO
:
4532 this must be *exactly* right for ACLs on mapped drives to work
4534 len
= srvstr_push(dstart
, flags2
,
4536 PTR_DIFF(dend
, pdata
+4),
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4539 data_size
= 4 + len
;
4544 case SMB_FILE_ALLOCATION_INFORMATION
:
4545 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4548 SOFF_T(pdata
,0,allocation_size
);
4551 case SMB_FILE_END_OF_FILE_INFORMATION
:
4552 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4555 SOFF_T(pdata
,0,file_size
);
4558 case SMB_QUERY_FILE_ALL_INFO
:
4559 case SMB_FILE_ALL_INFORMATION
:
4562 unsigned int ea_size
=
4563 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4565 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4566 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4567 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4568 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4569 SIVAL(pdata
,32,mode
);
4570 SIVAL(pdata
,36,0); /* padding. */
4572 SOFF_T(pdata
,0,allocation_size
);
4573 SOFF_T(pdata
,8,file_size
);
4574 SIVAL(pdata
,16,nlink
);
4575 SCVAL(pdata
,20,delete_pending
);
4576 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4579 SIVAL(pdata
,0,ea_size
);
4580 pdata
+= 4; /* EA info */
4581 len
= srvstr_push(dstart
, flags2
,
4583 PTR_DIFF(dend
, pdata
+4),
4587 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4591 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4594 unsigned int ea_size
=
4595 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4597 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4598 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4599 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4600 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4601 SIVAL(pdata
, 0x20, mode
);
4602 SIVAL(pdata
, 0x24, 0); /* padding. */
4603 SBVAL(pdata
, 0x28, allocation_size
);
4604 SBVAL(pdata
, 0x30, file_size
);
4605 SIVAL(pdata
, 0x38, nlink
);
4606 SCVAL(pdata
, 0x3C, delete_pending
);
4607 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4608 SSVAL(pdata
, 0x3E, 0); /* padding */
4609 SBVAL(pdata
, 0x40, file_index
);
4610 SIVAL(pdata
, 0x48, ea_size
);
4611 SIVAL(pdata
, 0x4C, access_mask
);
4612 SBVAL(pdata
, 0x50, pos
);
4613 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4614 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4618 len
= srvstr_push(dstart
, flags2
,
4620 PTR_DIFF(dend
, pdata
+4),
4624 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4627 case SMB_FILE_INTERNAL_INFORMATION
:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4630 SBVAL(pdata
, 0, file_index
);
4634 case SMB_FILE_ACCESS_INFORMATION
:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4636 SIVAL(pdata
, 0, access_mask
);
4640 case SMB_FILE_NAME_INFORMATION
:
4641 /* Pathname with leading '\'. */
4644 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4646 SIVAL(pdata
,0,byte_len
);
4647 data_size
= 4 + byte_len
;
4651 case SMB_FILE_DISPOSITION_INFORMATION
:
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4654 SCVAL(pdata
,0,delete_pending
);
4657 case SMB_FILE_POSITION_INFORMATION
:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4660 SOFF_T(pdata
,0,pos
);
4663 case SMB_FILE_MODE_INFORMATION
:
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4665 SIVAL(pdata
,0,mode
);
4669 case SMB_FILE_ALIGNMENT_INFORMATION
:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4671 SIVAL(pdata
,0,0); /* No alignment needed. */
4676 * NT4 server just returns "invalid query" to this - if we try
4677 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4680 /* The first statement above is false - verified using Thursby
4681 * client against NT4 -- gcolley.
4683 case SMB_QUERY_FILE_STREAM_INFO
:
4684 case SMB_FILE_STREAM_INFORMATION
: {
4685 unsigned int num_streams
;
4686 struct stream_struct
*streams
;
4688 DEBUG(10,("smbd_do_qfilepathinfo: "
4689 "SMB_FILE_STREAM_INFORMATION\n"));
4691 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4692 return NT_STATUS_INVALID_PARAMETER
;
4695 status
= SMB_VFS_STREAMINFO(
4696 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4697 &num_streams
, &streams
);
4699 if (!NT_STATUS_IS_OK(status
)) {
4700 DEBUG(10, ("could not get stream info: %s\n",
4701 nt_errstr(status
)));
4705 status
= marshall_stream_info(num_streams
, streams
,
4706 pdata
, max_data_bytes
,
4709 if (!NT_STATUS_IS_OK(status
)) {
4710 DEBUG(10, ("marshall_stream_info failed: %s\n",
4711 nt_errstr(status
)));
4715 TALLOC_FREE(streams
);
4719 case SMB_QUERY_COMPRESSION_INFO
:
4720 case SMB_FILE_COMPRESSION_INFORMATION
:
4721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4722 SOFF_T(pdata
,0,file_size
);
4723 SIVAL(pdata
,8,0); /* ??? */
4724 SIVAL(pdata
,12,0); /* ??? */
4728 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4730 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4731 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4732 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4733 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4734 SOFF_T(pdata
,32,allocation_size
);
4735 SOFF_T(pdata
,40,file_size
);
4736 SIVAL(pdata
,48,mode
);
4737 SIVAL(pdata
,52,0); /* ??? */
4741 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4743 SIVAL(pdata
,0,mode
);
4749 * CIFS UNIX Extensions.
4752 case SMB_QUERY_FILE_UNIX_BASIC
:
4754 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4755 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4759 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4761 for (i
=0; i
<100; i
++)
4762 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4768 case SMB_QUERY_FILE_UNIX_INFO2
:
4770 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4771 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4775 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4777 for (i
=0; i
<100; i
++)
4778 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4784 case SMB_QUERY_FILE_UNIX_LINK
:
4787 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4790 return NT_STATUS_NO_MEMORY
;
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4795 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4796 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4799 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4801 len
= SMB_VFS_READLINK(conn
,
4802 smb_fname
->base_name
,
4805 return map_nt_error_from_unix(errno
);
4808 len
= srvstr_push(dstart
, flags2
,
4810 PTR_DIFF(dend
, pdata
),
4813 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4818 #if defined(HAVE_POSIX_ACLS)
4819 case SMB_QUERY_POSIX_ACL
:
4821 SMB_ACL_T file_acl
= NULL
;
4822 SMB_ACL_T def_acl
= NULL
;
4823 uint16 num_file_acls
= 0;
4824 uint16 num_def_acls
= 0;
4826 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4827 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4830 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4831 smb_fname
->base_name
,
4832 SMB_ACL_TYPE_ACCESS
);
4835 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4836 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4837 "not implemented on "
4838 "filesystem containing %s\n",
4839 smb_fname
->base_name
));
4840 return NT_STATUS_NOT_IMPLEMENTED
;
4843 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4844 if (fsp
&& fsp
->is_directory
) {
4846 SMB_VFS_SYS_ACL_GET_FILE(
4848 fsp
->fsp_name
->base_name
,
4849 SMB_ACL_TYPE_DEFAULT
);
4852 SMB_VFS_SYS_ACL_GET_FILE(
4854 smb_fname
->base_name
,
4855 SMB_ACL_TYPE_DEFAULT
);
4857 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4860 num_file_acls
= count_acl_entries(conn
, file_acl
);
4861 num_def_acls
= count_acl_entries(conn
, def_acl
);
4863 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4864 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4866 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4867 SMB_POSIX_ACL_HEADER_SIZE
) ));
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4872 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4874 return NT_STATUS_BUFFER_TOO_SMALL
;
4877 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4878 SSVAL(pdata
,2,num_file_acls
);
4879 SSVAL(pdata
,4,num_def_acls
);
4880 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4887 return NT_STATUS_INTERNAL_ERROR
;
4889 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4896 return NT_STATUS_INTERNAL_ERROR
;
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4905 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4911 case SMB_QUERY_POSIX_LOCK
:
4916 enum brl_type lock_type
;
4918 /* We need an open file with a real fd for this. */
4919 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4920 return NT_STATUS_INVALID_LEVEL
;
4923 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4924 return NT_STATUS_INVALID_PARAMETER
;
4927 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4928 case POSIX_LOCK_TYPE_READ
:
4929 lock_type
= READ_LOCK
;
4931 case POSIX_LOCK_TYPE_WRITE
:
4932 lock_type
= WRITE_LOCK
;
4934 case POSIX_LOCK_TYPE_UNLOCK
:
4936 /* There's no point in asking for an unlock... */
4937 return NT_STATUS_INVALID_PARAMETER
;
4940 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4941 #if defined(HAVE_LONGLONG)
4942 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4943 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4944 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4945 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4946 #else /* HAVE_LONGLONG */
4947 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4948 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4949 #endif /* HAVE_LONGLONG */
4951 status
= query_lock(fsp
,
4958 if (ERROR_WAS_LOCK_DENIED(status
)) {
4959 /* Here we need to report who has it locked... */
4960 data_size
= POSIX_LOCK_DATA_SIZE
;
4962 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4963 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4964 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4965 #if defined(HAVE_LONGLONG)
4966 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4967 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4968 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4969 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4970 #else /* HAVE_LONGLONG */
4971 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4972 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4973 #endif /* HAVE_LONGLONG */
4975 } else if (NT_STATUS_IS_OK(status
)) {
4976 /* For success we just return a copy of what we sent
4977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4978 data_size
= POSIX_LOCK_DATA_SIZE
;
4979 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4980 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4988 return NT_STATUS_INVALID_LEVEL
;
4991 *pdata_size
= data_size
;
4992 return NT_STATUS_OK
;
4995 /****************************************************************************
4996 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4997 file name or file id).
4998 ****************************************************************************/
5000 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5001 struct smb_request
*req
,
5002 unsigned int tran_call
,
5003 char **pparams
, int total_params
,
5004 char **ppdata
, int total_data
,
5005 unsigned int max_data_bytes
)
5007 char *params
= *pparams
;
5008 char *pdata
= *ppdata
;
5010 unsigned int data_size
= 0;
5011 unsigned int param_size
= 2;
5012 struct smb_filename
*smb_fname
= NULL
;
5013 bool delete_pending
= False
;
5014 struct timespec write_time_ts
;
5015 files_struct
*fsp
= NULL
;
5016 struct file_id fileid
;
5017 struct ea_list
*ea_list
= NULL
;
5018 int lock_data_count
= 0;
5019 char *lock_data
= NULL
;
5020 NTSTATUS status
= NT_STATUS_OK
;
5023 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5027 ZERO_STRUCT(write_time_ts
);
5029 if (tran_call
== TRANSACT2_QFILEINFO
) {
5030 if (total_params
< 4) {
5031 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5036 call_trans2qpipeinfo(conn
, req
, tran_call
,
5037 pparams
, total_params
,
5043 fsp
= file_fsp(req
, SVAL(params
,0));
5044 info_level
= SVAL(params
,2);
5046 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5048 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5049 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5053 /* Initial check for valid fsp ptr. */
5054 if (!check_fsp_open(conn
, req
, fsp
)) {
5058 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5060 if (!NT_STATUS_IS_OK(status
)) {
5061 reply_nterror(req
, status
);
5065 if(fsp
->fake_file_handle
) {
5067 * This is actually for the QUOTA_FAKE_FILE --metze
5070 /* We know this name is ok, it's already passed the checks. */
5072 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5074 * This is actually a QFILEINFO on a directory
5075 * handle (returned from an NT SMB). NT5.0 seems
5076 * to do this call. JRA.
5079 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5080 /* Always do lstat for UNIX calls. */
5081 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5082 DEBUG(3,("call_trans2qfilepathinfo: "
5083 "SMB_VFS_LSTAT of %s failed "
5085 smb_fname_str_dbg(smb_fname
),
5088 map_nt_error_from_unix(errno
));
5091 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5092 DEBUG(3,("call_trans2qfilepathinfo: "
5093 "SMB_VFS_STAT of %s failed (%s)\n",
5094 smb_fname_str_dbg(smb_fname
),
5097 map_nt_error_from_unix(errno
));
5101 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5102 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5105 * Original code - this is an open file.
5107 if (!check_fsp(conn
, req
, fsp
)) {
5111 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5112 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5113 fsp
->fnum
, strerror(errno
)));
5115 map_nt_error_from_unix(errno
));
5118 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5119 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5126 if (total_params
< 7) {
5127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5131 info_level
= SVAL(params
,0);
5133 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5135 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5136 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5140 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5142 STR_TERMINATE
, &status
);
5143 if (!NT_STATUS_IS_OK(status
)) {
5144 reply_nterror(req
, status
);
5148 status
= filename_convert(req
,
5150 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5155 if (!NT_STATUS_IS_OK(status
)) {
5156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5157 reply_botherror(req
,
5158 NT_STATUS_PATH_NOT_COVERED
,
5159 ERRSRV
, ERRbadpath
);
5162 reply_nterror(req
, status
);
5166 /* If this is a stream, check if there is a delete_pending. */
5167 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5168 && is_ntfs_stream_smb_fname(smb_fname
)) {
5169 struct smb_filename
*smb_fname_base
= NULL
;
5171 /* Create an smb_filename with stream_name == NULL. */
5173 create_synthetic_smb_fname(talloc_tos(),
5174 smb_fname
->base_name
,
5177 if (!NT_STATUS_IS_OK(status
)) {
5178 reply_nterror(req
, status
);
5182 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed "
5188 smb_fname_str_dbg(smb_fname_base
),
5190 TALLOC_FREE(smb_fname_base
);
5192 map_nt_error_from_unix(errno
));
5196 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "fileinfo of %s failed "
5200 smb_fname_str_dbg(smb_fname_base
),
5202 TALLOC_FREE(smb_fname_base
);
5204 map_nt_error_from_unix(errno
));
5209 fileid
= vfs_file_id_from_sbuf(conn
,
5210 &smb_fname_base
->st
);
5211 TALLOC_FREE(smb_fname_base
);
5212 get_file_infos(fileid
, &delete_pending
, NULL
);
5213 if (delete_pending
) {
5214 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5219 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname
),
5227 map_nt_error_from_unix(errno
));
5232 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname
),
5238 map_nt_error_from_unix(errno
));
5243 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5244 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5245 if (delete_pending
) {
5246 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5251 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5252 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5253 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5255 /* Pull out any data sent here before we realloc. */
5256 switch (info_level
) {
5257 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5259 /* Pull any EA list from the data portion. */
5262 if (total_data
< 4) {
5264 req
, NT_STATUS_INVALID_PARAMETER
);
5267 ea_size
= IVAL(pdata
,0);
5269 if (total_data
> 0 && ea_size
!= total_data
) {
5270 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5271 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5273 req
, NT_STATUS_INVALID_PARAMETER
);
5277 if (!lp_ea_support(SNUM(conn
))) {
5278 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5282 /* Pull out the list of names. */
5283 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5286 req
, NT_STATUS_INVALID_PARAMETER
);
5292 case SMB_QUERY_POSIX_LOCK
:
5294 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5295 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5299 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5301 req
, NT_STATUS_INVALID_PARAMETER
);
5305 /* Copy the lock range data. */
5306 lock_data
= (char *)TALLOC_MEMDUP(
5307 req
, pdata
, total_data
);
5309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5312 lock_data_count
= total_data
;
5318 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5319 if (*pparams
== NULL
) {
5320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5327 * draft-leach-cifs-v1-spec-02.txt
5328 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5331 * The requested information is placed in the Data portion of the
5332 * transaction response. For the information levels greater than 0x100,
5333 * the transaction response has 1 parameter word which should be
5334 * ignored by the client.
5336 * However Windows only follows this rule for the IS_NAME_VALID call.
5338 switch (info_level
) {
5339 case SMB_INFO_IS_NAME_VALID
:
5344 if ((info_level
& 0xFF00) == 0xFF00) {
5346 * We use levels that start with 0xFF00
5347 * internally to represent SMB2 specific levels
5349 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5353 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5355 delete_pending
, write_time_ts
,
5357 lock_data_count
, lock_data
,
5358 req
->flags2
, max_data_bytes
,
5359 ppdata
, &data_size
);
5360 if (!NT_STATUS_IS_OK(status
)) {
5361 reply_nterror(req
, status
);
5365 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5371 /****************************************************************************
5372 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5374 ****************************************************************************/
5376 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5377 connection_struct
*conn
,
5378 struct smb_request
*req
,
5379 bool overwrite_if_exists
,
5380 const struct smb_filename
*smb_fname_old
,
5381 struct smb_filename
*smb_fname_new
)
5383 NTSTATUS status
= NT_STATUS_OK
;
5385 /* source must already exist. */
5386 if (!VALID_STAT(smb_fname_old
->st
)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5390 if (VALID_STAT(smb_fname_new
->st
)) {
5391 if (overwrite_if_exists
) {
5392 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5393 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5395 status
= unlink_internals(conn
,
5397 FILE_ATTRIBUTE_NORMAL
,
5400 if (!NT_STATUS_IS_OK(status
)) {
5404 /* Disallow if newname already exists. */
5405 return NT_STATUS_OBJECT_NAME_COLLISION
;
5409 /* No links from a directory. */
5410 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5411 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5414 /* Setting a hardlink to/from a stream isn't currently supported. */
5415 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5416 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5417 return NT_STATUS_INVALID_PARAMETER
;
5420 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5421 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5423 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5424 smb_fname_new
->base_name
) != 0) {
5425 status
= map_nt_error_from_unix(errno
);
5426 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5427 nt_errstr(status
), smb_fname_old
->base_name
,
5428 smb_fname_new
->base_name
));
5433 /****************************************************************************
5434 Deal with setting the time from any of the setfilepathinfo functions.
5435 ****************************************************************************/
5437 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5439 const struct smb_filename
*smb_fname
,
5440 struct smb_file_time
*ft
,
5441 bool setting_write_time
)
5443 struct smb_filename smb_fname_base
;
5445 FILE_NOTIFY_CHANGE_LAST_ACCESS
5446 |FILE_NOTIFY_CHANGE_LAST_WRITE
5447 |FILE_NOTIFY_CHANGE_CREATION
;
5449 if (!VALID_STAT(smb_fname
->st
)) {
5450 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5453 /* get some defaults (no modifications) if any info is zero or -1. */
5454 if (null_timespec(ft
->create_time
)) {
5455 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5458 if (null_timespec(ft
->atime
)) {
5459 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5462 if (null_timespec(ft
->mtime
)) {
5463 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5466 if (!setting_write_time
) {
5467 /* ft->mtime comes from change time, not write time. */
5468 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5471 /* Ensure the resolution is the correct for
5472 * what we can store on this filesystem. */
5474 round_timespec(conn
->ts_res
, &ft
->create_time
);
5475 round_timespec(conn
->ts_res
, &ft
->ctime
);
5476 round_timespec(conn
->ts_res
, &ft
->atime
);
5477 round_timespec(conn
->ts_res
, &ft
->mtime
);
5479 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5480 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5481 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5482 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5483 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5485 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5488 if (setting_write_time
) {
5490 * This was a Windows setfileinfo on an open file.
5491 * NT does this a lot. We also need to
5492 * set the time here, as it can be read by
5493 * FindFirst/FindNext and with the patch for bug #2045
5494 * in smbd/fileio.c it ensures that this timestamp is
5495 * kept sticky even after a write. We save the request
5496 * away and will set it on file close and after a write. JRA.
5499 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5500 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5503 if (fsp
->base_fsp
) {
5504 set_sticky_write_time_fsp(fsp
->base_fsp
,
5507 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5510 set_sticky_write_time_path(
5511 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5516 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5518 /* Always call ntimes on the base, even if a stream was passed in. */
5519 smb_fname_base
= *smb_fname
;
5520 smb_fname_base
.stream_name
= NULL
;
5522 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5523 return map_nt_error_from_unix(errno
);
5526 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5527 smb_fname
->base_name
);
5528 return NT_STATUS_OK
;
5531 /****************************************************************************
5532 Deal with setting the dosmode from any of the setfilepathinfo functions.
5533 ****************************************************************************/
5535 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5536 const struct smb_filename
*smb_fname
,
5539 struct smb_filename
*smb_fname_base
= NULL
;
5542 if (!VALID_STAT(smb_fname
->st
)) {
5543 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5546 /* Always operate on the base_name, even if a stream was passed in. */
5547 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5548 NULL
, &smb_fname
->st
,
5550 if (!NT_STATUS_IS_OK(status
)) {
5555 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5562 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5564 /* check the mode isn't different, before changing it */
5565 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5566 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5567 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5568 (unsigned int)dosmode
));
5570 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5572 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5574 smb_fname_str_dbg(smb_fname_base
),
5576 status
= map_nt_error_from_unix(errno
);
5580 status
= NT_STATUS_OK
;
5582 TALLOC_FREE(smb_fname_base
);
5586 /****************************************************************************
5587 Deal with setting the size from any of the setfilepathinfo functions.
5588 ****************************************************************************/
5590 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5591 struct smb_request
*req
,
5593 const struct smb_filename
*smb_fname
,
5594 const SMB_STRUCT_STAT
*psbuf
,
5596 bool fail_after_createfile
)
5598 NTSTATUS status
= NT_STATUS_OK
;
5599 struct smb_filename
*smb_fname_tmp
= NULL
;
5600 files_struct
*new_fsp
= NULL
;
5602 if (!VALID_STAT(*psbuf
)) {
5603 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5606 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5608 if (size
== get_file_size_stat(psbuf
)) {
5609 return NT_STATUS_OK
;
5612 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5613 smb_fname_str_dbg(smb_fname
), (double)size
));
5615 if (fsp
&& fsp
->fh
->fd
!= -1) {
5616 /* Handle based call. */
5617 if (vfs_set_filelen(fsp
, size
) == -1) {
5618 return map_nt_error_from_unix(errno
);
5620 trigger_write_time_update_immediate(fsp
);
5621 return NT_STATUS_OK
;
5624 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5625 if (!NT_STATUS_IS_OK(status
)) {
5629 smb_fname_tmp
->st
= *psbuf
;
5631 status
= SMB_VFS_CREATE_FILE(
5634 0, /* root_dir_fid */
5635 smb_fname_tmp
, /* fname */
5636 FILE_WRITE_DATA
, /* access_mask */
5637 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5639 FILE_OPEN
, /* create_disposition*/
5640 0, /* create_options */
5641 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5642 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5643 0, /* allocation_size */
5644 0, /* private_flags */
5647 &new_fsp
, /* result */
5650 TALLOC_FREE(smb_fname_tmp
);
5652 if (!NT_STATUS_IS_OK(status
)) {
5653 /* NB. We check for open_was_deferred in the caller. */
5657 /* See RAW-SFILEINFO-END-OF-FILE */
5658 if (fail_after_createfile
) {
5659 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5660 return NT_STATUS_INVALID_LEVEL
;
5663 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5664 status
= map_nt_error_from_unix(errno
);
5665 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5669 trigger_write_time_update_immediate(new_fsp
);
5670 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5671 return NT_STATUS_OK
;
5674 /****************************************************************************
5675 Deal with SMB_INFO_SET_EA.
5676 ****************************************************************************/
5678 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5682 const struct smb_filename
*smb_fname
)
5684 struct ea_list
*ea_list
= NULL
;
5685 TALLOC_CTX
*ctx
= NULL
;
5686 NTSTATUS status
= NT_STATUS_OK
;
5688 if (total_data
< 10) {
5690 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5691 length. They seem to have no effect. Bug #3212. JRA */
5693 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5694 /* We're done. We only get EA info in this call. */
5695 return NT_STATUS_OK
;
5698 return NT_STATUS_INVALID_PARAMETER
;
5701 if (IVAL(pdata
,0) > total_data
) {
5702 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5703 IVAL(pdata
,0), (unsigned int)total_data
));
5704 return NT_STATUS_INVALID_PARAMETER
;
5708 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5710 return NT_STATUS_INVALID_PARAMETER
;
5712 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5717 /****************************************************************************
5718 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5719 ****************************************************************************/
5721 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5726 struct ea_list
*ea_list
= NULL
;
5730 return NT_STATUS_INVALID_HANDLE
;
5733 if (!lp_ea_support(SNUM(conn
))) {
5734 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5735 "EA's not supported.\n",
5736 (unsigned int)total_data
));
5737 return NT_STATUS_EAS_NOT_SUPPORTED
;
5740 if (total_data
< 10) {
5741 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5743 (unsigned int)total_data
));
5744 return NT_STATUS_INVALID_PARAMETER
;
5747 ea_list
= read_nttrans_ea_list(talloc_tos(),
5752 return NT_STATUS_INVALID_PARAMETER
;
5754 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5756 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5757 smb_fname_str_dbg(fsp
->fsp_name
),
5758 nt_errstr(status
) ));
5764 /****************************************************************************
5765 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5766 ****************************************************************************/
5768 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5772 struct smb_filename
*smb_fname
)
5774 NTSTATUS status
= NT_STATUS_OK
;
5775 bool delete_on_close
;
5778 if (total_data
< 1) {
5779 return NT_STATUS_INVALID_PARAMETER
;
5783 return NT_STATUS_INVALID_HANDLE
;
5786 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5787 dosmode
= dos_mode(conn
, smb_fname
);
5789 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5790 "delete_on_close = %u\n",
5791 smb_fname_str_dbg(smb_fname
),
5792 (unsigned int)dosmode
,
5793 (unsigned int)delete_on_close
));
5795 if (delete_on_close
) {
5796 status
= can_set_delete_on_close(fsp
, dosmode
);
5797 if (!NT_STATUS_IS_OK(status
)) {
5802 /* The set is across all open files on this dev/inode pair. */
5803 if (!set_delete_on_close(fsp
, delete_on_close
,
5804 &conn
->server_info
->utok
)) {
5805 return NT_STATUS_ACCESS_DENIED
;
5807 return NT_STATUS_OK
;
5810 /****************************************************************************
5811 Deal with SMB_FILE_POSITION_INFORMATION.
5812 ****************************************************************************/
5814 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5819 uint64_t position_information
;
5821 if (total_data
< 8) {
5822 return NT_STATUS_INVALID_PARAMETER
;
5826 /* Ignore on pathname based set. */
5827 return NT_STATUS_OK
;
5830 position_information
= (uint64_t)IVAL(pdata
,0);
5831 #ifdef LARGE_SMB_OFF_T
5832 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5833 #else /* LARGE_SMB_OFF_T */
5834 if (IVAL(pdata
,4) != 0) {
5835 /* more than 32 bits? */
5836 return NT_STATUS_INVALID_PARAMETER
;
5838 #endif /* LARGE_SMB_OFF_T */
5840 DEBUG(10,("smb_file_position_information: Set file position "
5841 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5842 (double)position_information
));
5843 fsp
->fh
->position_information
= position_information
;
5844 return NT_STATUS_OK
;
5847 /****************************************************************************
5848 Deal with SMB_FILE_MODE_INFORMATION.
5849 ****************************************************************************/
5851 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5857 if (total_data
< 4) {
5858 return NT_STATUS_INVALID_PARAMETER
;
5860 mode
= IVAL(pdata
,0);
5861 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5862 return NT_STATUS_INVALID_PARAMETER
;
5864 return NT_STATUS_OK
;
5867 /****************************************************************************
5868 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5869 ****************************************************************************/
5871 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5872 struct smb_request
*req
,
5875 const struct smb_filename
*smb_fname
)
5877 char *link_target
= NULL
;
5878 const char *newname
= smb_fname
->base_name
;
5879 TALLOC_CTX
*ctx
= talloc_tos();
5881 /* Set a symbolic link. */
5882 /* Don't allow this if follow links is false. */
5884 if (total_data
== 0) {
5885 return NT_STATUS_INVALID_PARAMETER
;
5888 if (!lp_symlinks(SNUM(conn
))) {
5889 return NT_STATUS_ACCESS_DENIED
;
5892 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5893 total_data
, STR_TERMINATE
);
5896 return NT_STATUS_INVALID_PARAMETER
;
5899 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5900 newname
, link_target
));
5902 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5903 return map_nt_error_from_unix(errno
);
5906 return NT_STATUS_OK
;
5909 /****************************************************************************
5910 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5911 ****************************************************************************/
5913 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5914 struct smb_request
*req
,
5915 const char *pdata
, int total_data
,
5916 struct smb_filename
*smb_fname_new
)
5918 char *oldname
= NULL
;
5919 struct smb_filename
*smb_fname_old
= NULL
;
5920 TALLOC_CTX
*ctx
= talloc_tos();
5921 NTSTATUS status
= NT_STATUS_OK
;
5923 /* Set a hard link. */
5924 if (total_data
== 0) {
5925 return NT_STATUS_INVALID_PARAMETER
;
5928 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5929 total_data
, STR_TERMINATE
, &status
);
5930 if (!NT_STATUS_IS_OK(status
)) {
5934 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5935 smb_fname_str_dbg(smb_fname_new
), oldname
));
5937 status
= filename_convert(ctx
,
5939 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5944 if (!NT_STATUS_IS_OK(status
)) {
5948 return hardlink_internals(ctx
, conn
, req
, false,
5949 smb_fname_old
, smb_fname_new
);
5952 /****************************************************************************
5953 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5954 ****************************************************************************/
5956 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
5957 struct smb_request
*req
,
5961 struct smb_filename
*smb_fname_src
)
5965 char *newname
= NULL
;
5966 struct smb_filename
*smb_fname_dst
= NULL
;
5967 NTSTATUS status
= NT_STATUS_OK
;
5968 TALLOC_CTX
*ctx
= talloc_tos();
5971 return NT_STATUS_INVALID_HANDLE
;
5974 if (total_data
< 20) {
5975 return NT_STATUS_INVALID_PARAMETER
;
5978 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5979 len
= IVAL(pdata
,16);
5981 if (len
> (total_data
- 20) || (len
== 0)) {
5982 return NT_STATUS_INVALID_PARAMETER
;
5985 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
5986 &pdata
[20], len
, STR_TERMINATE
,
5988 if (!NT_STATUS_IS_OK(status
)) {
5992 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5995 status
= filename_convert(ctx
,
5997 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6002 if (!NT_STATUS_IS_OK(status
)) {
6006 if (fsp
->base_fsp
) {
6007 /* newname must be a stream name. */
6008 if (newname
[0] != ':') {
6009 return NT_STATUS_NOT_SUPPORTED
;
6012 /* Create an smb_fname to call rename_internals_fsp() with. */
6013 status
= create_synthetic_smb_fname(talloc_tos(),
6014 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6016 if (!NT_STATUS_IS_OK(status
)) {
6021 * Set the original last component, since
6022 * rename_internals_fsp() requires it.
6024 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6026 if (smb_fname_dst
->original_lcomp
== NULL
) {
6027 status
= NT_STATUS_NO_MEMORY
;
6033 DEBUG(10,("smb2_file_rename_information: "
6034 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6035 fsp
->fnum
, fsp_str_dbg(fsp
),
6036 smb_fname_str_dbg(smb_fname_dst
)));
6037 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6041 TALLOC_FREE(smb_fname_dst
);
6045 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6046 struct smb_request
*req
,
6050 struct smb_filename
*smb_fname_src
)
6054 char *newname
= NULL
;
6055 struct smb_filename
*smb_fname_dst
= NULL
;
6056 NTSTATUS status
= NT_STATUS_OK
;
6057 TALLOC_CTX
*ctx
= talloc_tos();
6060 return NT_STATUS_INVALID_HANDLE
;
6063 if (total_data
< 20) {
6064 return NT_STATUS_INVALID_PARAMETER
;
6067 overwrite
= (CVAL(pdata
,0) ? true : false);
6068 len
= IVAL(pdata
,16);
6070 if (len
> (total_data
- 20) || (len
== 0)) {
6071 return NT_STATUS_INVALID_PARAMETER
;
6074 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6075 &pdata
[20], len
, STR_TERMINATE
,
6077 if (!NT_STATUS_IS_OK(status
)) {
6081 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6084 status
= filename_convert(ctx
,
6086 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6091 if (!NT_STATUS_IS_OK(status
)) {
6095 if (fsp
->base_fsp
) {
6096 /* No stream names. */
6097 return NT_STATUS_NOT_SUPPORTED
;
6100 DEBUG(10,("smb_file_link_information: "
6101 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6102 fsp
->fnum
, fsp_str_dbg(fsp
),
6103 smb_fname_str_dbg(smb_fname_dst
)));
6104 status
= hardlink_internals(ctx
,
6111 TALLOC_FREE(smb_fname_dst
);
6115 /****************************************************************************
6116 Deal with SMB_FILE_RENAME_INFORMATION.
6117 ****************************************************************************/
6119 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6120 struct smb_request
*req
,
6124 struct smb_filename
*smb_fname_src
)
6129 char *newname
= NULL
;
6130 struct smb_filename
*smb_fname_dst
= NULL
;
6131 bool dest_has_wcard
= False
;
6132 NTSTATUS status
= NT_STATUS_OK
;
6134 TALLOC_CTX
*ctx
= talloc_tos();
6136 if (total_data
< 13) {
6137 return NT_STATUS_INVALID_PARAMETER
;
6140 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6141 root_fid
= IVAL(pdata
,4);
6142 len
= IVAL(pdata
,8);
6144 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6145 return NT_STATUS_INVALID_PARAMETER
;
6148 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6151 if (!NT_STATUS_IS_OK(status
)) {
6155 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6158 status
= resolve_dfspath_wcard(ctx
, conn
,
6159 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6164 if (!NT_STATUS_IS_OK(status
)) {
6168 /* Check the new name has no '/' characters. */
6169 if (strchr_m(newname
, '/')) {
6170 return NT_STATUS_NOT_SUPPORTED
;
6173 if (fsp
&& fsp
->base_fsp
) {
6174 /* newname must be a stream name. */
6175 if (newname
[0] != ':') {
6176 return NT_STATUS_NOT_SUPPORTED
;
6179 /* Create an smb_fname to call rename_internals_fsp() with. */
6180 status
= create_synthetic_smb_fname(talloc_tos(),
6181 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6183 if (!NT_STATUS_IS_OK(status
)) {
6188 * Set the original last component, since
6189 * rename_internals_fsp() requires it.
6191 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6193 if (smb_fname_dst
->original_lcomp
== NULL
) {
6194 status
= NT_STATUS_NO_MEMORY
;
6200 * Build up an smb_fname_dst based on the filename passed in.
6201 * We basically just strip off the last component, and put on
6202 * the newname instead.
6204 char *base_name
= NULL
;
6206 /* newname must *not* be a stream name. */
6207 if (newname
[0] == ':') {
6208 return NT_STATUS_NOT_SUPPORTED
;
6212 * Strip off the last component (filename) of the path passed
6215 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6217 return NT_STATUS_NO_MEMORY
;
6219 p
= strrchr_m(base_name
, '/');
6223 base_name
= talloc_strdup(ctx
, "./");
6225 return NT_STATUS_NO_MEMORY
;
6228 /* Append the new name. */
6229 base_name
= talloc_asprintf_append(base_name
,
6233 return NT_STATUS_NO_MEMORY
;
6236 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6239 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6242 /* If an error we expect this to be
6243 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6245 if (!NT_STATUS_IS_OK(status
)) {
6246 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6250 /* Create an smb_fname to call rename_internals_fsp() */
6251 status
= create_synthetic_smb_fname(ctx
,
6255 if (!NT_STATUS_IS_OK(status
)) {
6262 DEBUG(10,("smb_file_rename_information: "
6263 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6264 fsp
->fnum
, fsp_str_dbg(fsp
),
6265 smb_fname_str_dbg(smb_fname_dst
)));
6266 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6269 DEBUG(10,("smb_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6271 smb_fname_str_dbg(smb_fname_src
),
6272 smb_fname_str_dbg(smb_fname_dst
)));
6273 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6274 smb_fname_dst
, 0, overwrite
, false,
6276 FILE_WRITE_ATTRIBUTES
);
6279 TALLOC_FREE(smb_fname_dst
);
6283 /****************************************************************************
6284 Deal with SMB_SET_POSIX_ACL.
6285 ****************************************************************************/
6287 #if defined(HAVE_POSIX_ACLS)
6288 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6292 const struct smb_filename
*smb_fname
)
6294 uint16 posix_acl_version
;
6295 uint16 num_file_acls
;
6296 uint16 num_def_acls
;
6297 bool valid_file_acls
= True
;
6298 bool valid_def_acls
= True
;
6300 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6301 return NT_STATUS_INVALID_PARAMETER
;
6303 posix_acl_version
= SVAL(pdata
,0);
6304 num_file_acls
= SVAL(pdata
,2);
6305 num_def_acls
= SVAL(pdata
,4);
6307 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6308 valid_file_acls
= False
;
6312 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6313 valid_def_acls
= False
;
6317 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6318 return NT_STATUS_INVALID_PARAMETER
;
6321 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6322 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6323 return NT_STATUS_INVALID_PARAMETER
;
6326 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6327 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6328 (unsigned int)num_file_acls
,
6329 (unsigned int)num_def_acls
));
6331 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6332 smb_fname
->base_name
, num_file_acls
,
6333 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6334 return map_nt_error_from_unix(errno
);
6337 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6338 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6339 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6340 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6341 return map_nt_error_from_unix(errno
);
6343 return NT_STATUS_OK
;
6347 /****************************************************************************
6348 Deal with SMB_SET_POSIX_LOCK.
6349 ****************************************************************************/
6351 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6352 struct smb_request
*req
,
6360 bool blocking_lock
= False
;
6361 enum brl_type lock_type
;
6363 NTSTATUS status
= NT_STATUS_OK
;
6365 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6366 return NT_STATUS_INVALID_HANDLE
;
6369 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6370 return NT_STATUS_INVALID_PARAMETER
;
6373 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6374 case POSIX_LOCK_TYPE_READ
:
6375 lock_type
= READ_LOCK
;
6377 case POSIX_LOCK_TYPE_WRITE
:
6378 /* Return the right POSIX-mappable error code for files opened read-only. */
6379 if (!fsp
->can_write
) {
6380 return NT_STATUS_INVALID_HANDLE
;
6382 lock_type
= WRITE_LOCK
;
6384 case POSIX_LOCK_TYPE_UNLOCK
:
6385 lock_type
= UNLOCK_LOCK
;
6388 return NT_STATUS_INVALID_PARAMETER
;
6391 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6392 blocking_lock
= False
;
6393 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6394 blocking_lock
= True
;
6396 return NT_STATUS_INVALID_PARAMETER
;
6399 if (!lp_blocking_locks(SNUM(conn
))) {
6400 blocking_lock
= False
;
6403 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6404 #if defined(HAVE_LONGLONG)
6405 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6406 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6407 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6408 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6409 #else /* HAVE_LONGLONG */
6410 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6411 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6412 #endif /* HAVE_LONGLONG */
6414 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6415 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6417 (unsigned int)lock_type
,
6418 (unsigned long long)smblctx
,
6422 if (lock_type
== UNLOCK_LOCK
) {
6423 status
= do_unlock(smbd_messaging_context(),
6430 uint64_t block_smblctx
;
6432 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6444 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6446 * A blocking lock was requested. Package up
6447 * this smb into a queued request and push it
6448 * onto the blocking lock queue.
6450 if(push_blocking_lock_request(br_lck
,
6453 -1, /* infinite timeout. */
6461 TALLOC_FREE(br_lck
);
6465 TALLOC_FREE(br_lck
);
6471 /****************************************************************************
6472 Deal with SMB_SET_FILE_BASIC_INFO.
6473 ****************************************************************************/
6475 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6479 const struct smb_filename
*smb_fname
)
6481 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6482 struct smb_file_time ft
;
6484 NTSTATUS status
= NT_STATUS_OK
;
6488 if (total_data
< 36) {
6489 return NT_STATUS_INVALID_PARAMETER
;
6492 /* Set the attributes */
6493 dosmode
= IVAL(pdata
,32);
6494 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6495 if (!NT_STATUS_IS_OK(status
)) {
6500 ft
.create_time
= interpret_long_date(pdata
);
6503 ft
.atime
= interpret_long_date(pdata
+8);
6506 ft
.mtime
= interpret_long_date(pdata
+16);
6509 ft
.ctime
= interpret_long_date(pdata
+24);
6511 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6512 smb_fname_str_dbg(smb_fname
)));
6514 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6518 /****************************************************************************
6519 Deal with SMB_INFO_STANDARD.
6520 ****************************************************************************/
6522 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6526 const struct smb_filename
*smb_fname
)
6528 struct smb_file_time ft
;
6532 if (total_data
< 12) {
6533 return NT_STATUS_INVALID_PARAMETER
;
6537 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6539 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6541 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6543 DEBUG(10,("smb_set_info_standard: file %s\n",
6544 smb_fname_str_dbg(smb_fname
)));
6546 return smb_set_file_time(conn
,
6553 /****************************************************************************
6554 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6555 ****************************************************************************/
6557 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6558 struct smb_request
*req
,
6562 struct smb_filename
*smb_fname
)
6564 uint64_t allocation_size
= 0;
6565 NTSTATUS status
= NT_STATUS_OK
;
6566 files_struct
*new_fsp
= NULL
;
6568 if (!VALID_STAT(smb_fname
->st
)) {
6569 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6572 if (total_data
< 8) {
6573 return NT_STATUS_INVALID_PARAMETER
;
6576 allocation_size
= (uint64_t)IVAL(pdata
,0);
6577 #ifdef LARGE_SMB_OFF_T
6578 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6579 #else /* LARGE_SMB_OFF_T */
6580 if (IVAL(pdata
,4) != 0) {
6581 /* more than 32 bits? */
6582 return NT_STATUS_INVALID_PARAMETER
;
6584 #endif /* LARGE_SMB_OFF_T */
6586 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6587 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6588 (double)allocation_size
));
6590 if (allocation_size
) {
6591 allocation_size
= smb_roundup(conn
, allocation_size
);
6594 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6595 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6596 (double)allocation_size
));
6598 if (fsp
&& fsp
->fh
->fd
!= -1) {
6599 /* Open file handle. */
6600 /* Only change if needed. */
6601 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6602 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6603 return map_nt_error_from_unix(errno
);
6606 /* But always update the time. */
6608 * This is equivalent to a write. Ensure it's seen immediately
6609 * if there are no pending writes.
6611 trigger_write_time_update_immediate(fsp
);
6612 return NT_STATUS_OK
;
6615 /* Pathname or stat or directory file. */
6616 status
= SMB_VFS_CREATE_FILE(
6619 0, /* root_dir_fid */
6620 smb_fname
, /* fname */
6621 FILE_WRITE_DATA
, /* access_mask */
6622 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6624 FILE_OPEN
, /* create_disposition*/
6625 0, /* create_options */
6626 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6627 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6628 0, /* allocation_size */
6629 0, /* private_flags */
6632 &new_fsp
, /* result */
6635 if (!NT_STATUS_IS_OK(status
)) {
6636 /* NB. We check for open_was_deferred in the caller. */
6640 /* Only change if needed. */
6641 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6642 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6643 status
= map_nt_error_from_unix(errno
);
6644 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6649 /* Changing the allocation size should set the last mod time. */
6651 * This is equivalent to a write. Ensure it's seen immediately
6652 * if there are no pending writes.
6654 trigger_write_time_update_immediate(new_fsp
);
6656 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6657 return NT_STATUS_OK
;
6660 /****************************************************************************
6661 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6662 ****************************************************************************/
6664 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6665 struct smb_request
*req
,
6669 const struct smb_filename
*smb_fname
,
6670 bool fail_after_createfile
)
6674 if (total_data
< 8) {
6675 return NT_STATUS_INVALID_PARAMETER
;
6678 size
= IVAL(pdata
,0);
6679 #ifdef LARGE_SMB_OFF_T
6680 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6681 #else /* LARGE_SMB_OFF_T */
6682 if (IVAL(pdata
,4) != 0) {
6683 /* more than 32 bits? */
6684 return NT_STATUS_INVALID_PARAMETER
;
6686 #endif /* LARGE_SMB_OFF_T */
6687 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6688 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6691 return smb_set_file_size(conn
, req
,
6696 fail_after_createfile
);
6699 /****************************************************************************
6700 Allow a UNIX info mknod.
6701 ****************************************************************************/
6703 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6706 const struct smb_filename
*smb_fname
)
6708 uint32 file_type
= IVAL(pdata
,56);
6709 #if defined(HAVE_MAKEDEV)
6710 uint32 dev_major
= IVAL(pdata
,60);
6711 uint32 dev_minor
= IVAL(pdata
,68);
6713 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6714 uint32 raw_unixmode
= IVAL(pdata
,84);
6718 if (total_data
< 100) {
6719 return NT_STATUS_INVALID_PARAMETER
;
6722 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6723 PERM_NEW_FILE
, &unixmode
);
6724 if (!NT_STATUS_IS_OK(status
)) {
6728 #if defined(HAVE_MAKEDEV)
6729 dev
= makedev(dev_major
, dev_minor
);
6732 switch (file_type
) {
6733 #if defined(S_IFIFO)
6734 case UNIX_TYPE_FIFO
:
6735 unixmode
|= S_IFIFO
;
6738 #if defined(S_IFSOCK)
6739 case UNIX_TYPE_SOCKET
:
6740 unixmode
|= S_IFSOCK
;
6743 #if defined(S_IFCHR)
6744 case UNIX_TYPE_CHARDEV
:
6745 unixmode
|= S_IFCHR
;
6748 #if defined(S_IFBLK)
6749 case UNIX_TYPE_BLKDEV
:
6750 unixmode
|= S_IFBLK
;
6754 return NT_STATUS_INVALID_PARAMETER
;
6757 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6758 "%.0f mode 0%o for file %s\n", (double)dev
,
6759 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6761 /* Ok - do the mknod. */
6762 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6763 return map_nt_error_from_unix(errno
);
6766 /* If any of the other "set" calls fail we
6767 * don't want to end up with a half-constructed mknod.
6770 if (lp_inherit_perms(SNUM(conn
))) {
6772 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6774 return NT_STATUS_NO_MEMORY
;
6776 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6778 TALLOC_FREE(parent
);
6781 return NT_STATUS_OK
;
6784 /****************************************************************************
6785 Deal with SMB_SET_FILE_UNIX_BASIC.
6786 ****************************************************************************/
6788 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6789 struct smb_request
*req
,
6793 const struct smb_filename
*smb_fname
)
6795 struct smb_file_time ft
;
6796 uint32 raw_unixmode
;
6799 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6800 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6801 NTSTATUS status
= NT_STATUS_OK
;
6802 bool delete_on_fail
= False
;
6803 enum perm_type ptype
;
6804 files_struct
*all_fsps
= NULL
;
6805 bool modify_mtime
= true;
6807 SMB_STRUCT_STAT sbuf
;
6811 if (total_data
< 100) {
6812 return NT_STATUS_INVALID_PARAMETER
;
6815 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6816 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6817 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6818 #ifdef LARGE_SMB_OFF_T
6819 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6820 #else /* LARGE_SMB_OFF_T */
6821 if (IVAL(pdata
,4) != 0) {
6822 /* more than 32 bits? */
6823 return NT_STATUS_INVALID_PARAMETER
;
6825 #endif /* LARGE_SMB_OFF_T */
6828 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6829 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6830 set_owner
= (uid_t
)IVAL(pdata
,40);
6831 set_grp
= (gid_t
)IVAL(pdata
,48);
6832 raw_unixmode
= IVAL(pdata
,84);
6834 if (VALID_STAT(smb_fname
->st
)) {
6835 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6836 ptype
= PERM_EXISTING_DIR
;
6838 ptype
= PERM_EXISTING_FILE
;
6841 ptype
= PERM_NEW_FILE
;
6844 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6846 if (!NT_STATUS_IS_OK(status
)) {
6850 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6851 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6852 smb_fname_str_dbg(smb_fname
), (double)size
,
6853 (unsigned int)set_owner
, (unsigned int)set_grp
,
6854 (int)raw_unixmode
));
6856 sbuf
= smb_fname
->st
;
6858 if (!VALID_STAT(sbuf
)) {
6859 struct smb_filename
*smb_fname_tmp
= NULL
;
6861 * The only valid use of this is to create character and block
6862 * devices, and named pipes. This is deprecated (IMHO) and
6863 * a new info level should be used for mknod. JRA.
6866 status
= smb_unix_mknod(conn
,
6870 if (!NT_STATUS_IS_OK(status
)) {
6874 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6876 if (!NT_STATUS_IS_OK(status
)) {
6880 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6881 status
= map_nt_error_from_unix(errno
);
6882 TALLOC_FREE(smb_fname_tmp
);
6883 SMB_VFS_UNLINK(conn
, smb_fname
);
6887 sbuf
= smb_fname_tmp
->st
;
6888 TALLOC_FREE(smb_fname_tmp
);
6890 /* Ensure we don't try and change anything else. */
6891 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6892 size
= get_file_size_stat(&sbuf
);
6893 ft
.atime
= sbuf
.st_ex_atime
;
6894 ft
.mtime
= sbuf
.st_ex_mtime
;
6896 * We continue here as we might want to change the
6899 delete_on_fail
= True
;
6903 /* Horrible backwards compatibility hack as an old server bug
6904 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6908 size
= get_file_size_stat(&sbuf
);
6913 * Deal with the UNIX specific mode set.
6916 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6917 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6918 "setting mode 0%o for file %s\n",
6919 (unsigned int)unixmode
,
6920 smb_fname_str_dbg(smb_fname
)));
6921 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6922 return map_nt_error_from_unix(errno
);
6927 * Deal with the UNIX specific uid set.
6930 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6931 (sbuf
.st_ex_uid
!= set_owner
)) {
6934 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6935 "changing owner %u for path %s\n",
6936 (unsigned int)set_owner
,
6937 smb_fname_str_dbg(smb_fname
)));
6939 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6940 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6941 set_owner
, (gid_t
)-1);
6943 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6944 set_owner
, (gid_t
)-1);
6948 status
= map_nt_error_from_unix(errno
);
6949 if (delete_on_fail
) {
6950 SMB_VFS_UNLINK(conn
, smb_fname
);
6957 * Deal with the UNIX specific gid set.
6960 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6961 (sbuf
.st_ex_gid
!= set_grp
)) {
6962 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6963 "changing group %u for file %s\n",
6964 (unsigned int)set_owner
,
6965 smb_fname_str_dbg(smb_fname
)));
6966 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6968 status
= map_nt_error_from_unix(errno
);
6969 if (delete_on_fail
) {
6970 SMB_VFS_UNLINK(conn
, smb_fname
);
6976 /* Deal with any size changes. */
6978 status
= smb_set_file_size(conn
, req
,
6984 if (!NT_STATUS_IS_OK(status
)) {
6988 /* Deal with any time changes. */
6989 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6990 /* No change, don't cancel anything. */
6994 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6995 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6996 all_fsps
= file_find_di_next(all_fsps
)) {
6998 * We're setting the time explicitly for UNIX.
6999 * Cancel any pending changes over all handles.
7001 all_fsps
->update_write_time_on_close
= false;
7002 TALLOC_FREE(all_fsps
->update_write_time_event
);
7006 * Override the "setting_write_time"
7007 * parameter here as it almost does what
7008 * we need. Just remember if we modified
7009 * mtime and send the notify ourselves.
7011 if (null_timespec(ft
.mtime
)) {
7012 modify_mtime
= false;
7015 status
= smb_set_file_time(conn
,
7021 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7022 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7027 /****************************************************************************
7028 Deal with SMB_SET_FILE_UNIX_INFO2.
7029 ****************************************************************************/
7031 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7032 struct smb_request
*req
,
7036 const struct smb_filename
*smb_fname
)
7042 if (total_data
< 116) {
7043 return NT_STATUS_INVALID_PARAMETER
;
7046 /* Start by setting all the fields that are common between UNIX_BASIC
7049 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7051 if (!NT_STATUS_IS_OK(status
)) {
7055 smb_fflags
= IVAL(pdata
, 108);
7056 smb_fmask
= IVAL(pdata
, 112);
7058 /* NB: We should only attempt to alter the file flags if the client
7059 * sends a non-zero mask.
7061 if (smb_fmask
!= 0) {
7062 int stat_fflags
= 0;
7064 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7065 smb_fmask
, &stat_fflags
)) {
7066 /* Client asked to alter a flag we don't understand. */
7067 return NT_STATUS_INVALID_PARAMETER
;
7070 if (fsp
&& fsp
->fh
->fd
!= -1) {
7071 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7072 return NT_STATUS_NOT_SUPPORTED
;
7074 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7075 stat_fflags
) != 0) {
7076 return map_nt_error_from_unix(errno
);
7081 /* XXX: need to add support for changing the create_time here. You
7082 * can do this for paths on Darwin with setattrlist(2). The right way
7083 * to hook this up is probably by extending the VFS utimes interface.
7086 return NT_STATUS_OK
;
7089 /****************************************************************************
7090 Create a directory with POSIX semantics.
7091 ****************************************************************************/
7093 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7094 struct smb_request
*req
,
7097 struct smb_filename
*smb_fname
,
7098 int *pdata_return_size
)
7100 NTSTATUS status
= NT_STATUS_OK
;
7101 uint32 raw_unixmode
= 0;
7102 uint32 mod_unixmode
= 0;
7103 mode_t unixmode
= (mode_t
)0;
7104 files_struct
*fsp
= NULL
;
7105 uint16 info_level_return
= 0;
7107 char *pdata
= *ppdata
;
7109 if (total_data
< 18) {
7110 return NT_STATUS_INVALID_PARAMETER
;
7113 raw_unixmode
= IVAL(pdata
,8);
7114 /* Next 4 bytes are not yet defined. */
7116 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7117 PERM_NEW_DIR
, &unixmode
);
7118 if (!NT_STATUS_IS_OK(status
)) {
7122 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7124 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7125 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7127 status
= SMB_VFS_CREATE_FILE(
7130 0, /* root_dir_fid */
7131 smb_fname
, /* fname */
7132 FILE_READ_ATTRIBUTES
, /* access_mask */
7133 FILE_SHARE_NONE
, /* share_access */
7134 FILE_CREATE
, /* create_disposition*/
7135 FILE_DIRECTORY_FILE
, /* create_options */
7136 mod_unixmode
, /* file_attributes */
7137 0, /* oplock_request */
7138 0, /* allocation_size */
7139 0, /* private_flags */
7145 if (NT_STATUS_IS_OK(status
)) {
7146 close_file(req
, fsp
, NORMAL_CLOSE
);
7149 info_level_return
= SVAL(pdata
,16);
7151 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7152 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7153 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7154 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7156 *pdata_return_size
= 12;
7159 /* Realloc the data size */
7160 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7161 if (*ppdata
== NULL
) {
7162 *pdata_return_size
= 0;
7163 return NT_STATUS_NO_MEMORY
;
7167 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7168 SSVAL(pdata
,2,0); /* No fnum. */
7169 SIVAL(pdata
,4,info
); /* Was directory created. */
7171 switch (info_level_return
) {
7172 case SMB_QUERY_FILE_UNIX_BASIC
:
7173 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7174 SSVAL(pdata
,10,0); /* Padding. */
7175 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7178 case SMB_QUERY_FILE_UNIX_INFO2
:
7179 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7180 SSVAL(pdata
,10,0); /* Padding. */
7181 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7185 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7186 SSVAL(pdata
,10,0); /* Padding. */
7193 /****************************************************************************
7194 Open/Create a file with POSIX semantics.
7195 ****************************************************************************/
7197 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7198 struct smb_request
*req
,
7201 struct smb_filename
*smb_fname
,
7202 int *pdata_return_size
)
7204 bool extended_oplock_granted
= False
;
7205 char *pdata
= *ppdata
;
7207 uint32 wire_open_mode
= 0;
7208 uint32 raw_unixmode
= 0;
7209 uint32 mod_unixmode
= 0;
7210 uint32 create_disp
= 0;
7211 uint32 access_mask
= 0;
7212 uint32 create_options
= 0;
7213 NTSTATUS status
= NT_STATUS_OK
;
7214 mode_t unixmode
= (mode_t
)0;
7215 files_struct
*fsp
= NULL
;
7216 int oplock_request
= 0;
7218 uint16 info_level_return
= 0;
7220 if (total_data
< 18) {
7221 return NT_STATUS_INVALID_PARAMETER
;
7224 flags
= IVAL(pdata
,0);
7225 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7226 if (oplock_request
) {
7227 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7230 wire_open_mode
= IVAL(pdata
,4);
7232 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7233 return smb_posix_mkdir(conn
, req
,
7240 switch (wire_open_mode
& SMB_ACCMODE
) {
7242 access_mask
= FILE_READ_DATA
;
7245 access_mask
= FILE_WRITE_DATA
;
7248 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7251 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7252 (unsigned int)wire_open_mode
));
7253 return NT_STATUS_INVALID_PARAMETER
;
7256 wire_open_mode
&= ~SMB_ACCMODE
;
7258 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7259 create_disp
= FILE_CREATE
;
7260 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7261 create_disp
= FILE_OVERWRITE_IF
;
7262 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7263 create_disp
= FILE_OPEN_IF
;
7264 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7265 create_disp
= FILE_OPEN
;
7267 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7268 (unsigned int)wire_open_mode
));
7269 return NT_STATUS_INVALID_PARAMETER
;
7272 raw_unixmode
= IVAL(pdata
,8);
7273 /* Next 4 bytes are not yet defined. */
7275 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7276 (VALID_STAT(smb_fname
->st
) ?
7277 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7280 if (!NT_STATUS_IS_OK(status
)) {
7284 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7286 if (wire_open_mode
& SMB_O_SYNC
) {
7287 create_options
|= FILE_WRITE_THROUGH
;
7289 if (wire_open_mode
& SMB_O_APPEND
) {
7290 access_mask
|= FILE_APPEND_DATA
;
7292 if (wire_open_mode
& SMB_O_DIRECT
) {
7293 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7296 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7297 smb_fname_str_dbg(smb_fname
),
7298 (unsigned int)wire_open_mode
,
7299 (unsigned int)unixmode
));
7301 status
= SMB_VFS_CREATE_FILE(
7304 0, /* root_dir_fid */
7305 smb_fname
, /* fname */
7306 access_mask
, /* access_mask */
7307 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7309 create_disp
, /* create_disposition*/
7310 FILE_NON_DIRECTORY_FILE
, /* create_options */
7311 mod_unixmode
, /* file_attributes */
7312 oplock_request
, /* oplock_request */
7313 0, /* allocation_size */
7314 0, /* private_flags */
7320 if (!NT_STATUS_IS_OK(status
)) {
7324 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7325 extended_oplock_granted
= True
;
7328 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7329 extended_oplock_granted
= True
;
7332 info_level_return
= SVAL(pdata
,16);
7334 /* Allocate the correct return size. */
7336 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7337 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7338 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7339 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7341 *pdata_return_size
= 12;
7344 /* Realloc the data size */
7345 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7346 if (*ppdata
== NULL
) {
7347 close_file(req
, fsp
, ERROR_CLOSE
);
7348 *pdata_return_size
= 0;
7349 return NT_STATUS_NO_MEMORY
;
7353 if (extended_oplock_granted
) {
7354 if (flags
& REQUEST_BATCH_OPLOCK
) {
7355 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7357 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7359 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7360 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7362 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7365 SSVAL(pdata
,2,fsp
->fnum
);
7366 SIVAL(pdata
,4,info
); /* Was file created etc. */
7368 switch (info_level_return
) {
7369 case SMB_QUERY_FILE_UNIX_BASIC
:
7370 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7371 SSVAL(pdata
,10,0); /* padding. */
7372 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7375 case SMB_QUERY_FILE_UNIX_INFO2
:
7376 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7377 SSVAL(pdata
,10,0); /* padding. */
7378 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7382 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7383 SSVAL(pdata
,10,0); /* padding. */
7386 return NT_STATUS_OK
;
7389 /****************************************************************************
7390 Delete a file with POSIX semantics.
7391 ****************************************************************************/
7393 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7394 struct smb_request
*req
,
7397 struct smb_filename
*smb_fname
)
7399 NTSTATUS status
= NT_STATUS_OK
;
7400 files_struct
*fsp
= NULL
;
7404 int create_options
= 0;
7406 struct share_mode_lock
*lck
= NULL
;
7408 if (total_data
< 2) {
7409 return NT_STATUS_INVALID_PARAMETER
;
7412 flags
= SVAL(pdata
,0);
7414 if (!VALID_STAT(smb_fname
->st
)) {
7415 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7418 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7419 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7420 return NT_STATUS_NOT_A_DIRECTORY
;
7423 DEBUG(10,("smb_posix_unlink: %s %s\n",
7424 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7425 smb_fname_str_dbg(smb_fname
)));
7427 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7428 create_options
|= FILE_DIRECTORY_FILE
;
7431 status
= SMB_VFS_CREATE_FILE(
7434 0, /* root_dir_fid */
7435 smb_fname
, /* fname */
7436 DELETE_ACCESS
, /* access_mask */
7437 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7439 FILE_OPEN
, /* create_disposition*/
7440 create_options
, /* create_options */
7441 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7442 0, /* oplock_request */
7443 0, /* allocation_size */
7444 0, /* private_flags */
7450 if (!NT_STATUS_IS_OK(status
)) {
7455 * Don't lie to client. If we can't really delete due to
7456 * non-POSIX opens return SHARING_VIOLATION.
7459 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7462 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7463 "lock for file %s\n", fsp_str_dbg(fsp
)));
7464 close_file(req
, fsp
, NORMAL_CLOSE
);
7465 return NT_STATUS_INVALID_PARAMETER
;
7469 * See if others still have the file open. If this is the case, then
7470 * don't delete. If all opens are POSIX delete we can set the delete
7471 * on close disposition.
7473 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7474 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7475 if (is_valid_share_mode_entry(e
)) {
7476 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7479 /* Fail with sharing violation. */
7480 close_file(req
, fsp
, NORMAL_CLOSE
);
7482 return NT_STATUS_SHARING_VIOLATION
;
7487 * Set the delete on close.
7489 status
= smb_set_file_disposition_info(conn
,
7495 if (!NT_STATUS_IS_OK(status
)) {
7496 close_file(req
, fsp
, NORMAL_CLOSE
);
7501 return close_file(req
, fsp
, NORMAL_CLOSE
);
7504 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7505 struct smb_request
*req
,
7506 TALLOC_CTX
*mem_ctx
,
7507 uint16_t info_level
,
7509 struct smb_filename
*smb_fname
,
7510 char **ppdata
, int total_data
,
7513 char *pdata
= *ppdata
;
7514 NTSTATUS status
= NT_STATUS_OK
;
7515 int data_return_size
= 0;
7519 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7520 return NT_STATUS_INVALID_LEVEL
;
7523 if (!CAN_WRITE(conn
)) {
7524 /* Allow POSIX opens. The open path will deny
7525 * any non-readonly opens. */
7526 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7527 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7531 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7532 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7533 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7535 switch (info_level
) {
7537 case SMB_INFO_STANDARD
:
7539 status
= smb_set_info_standard(conn
,
7547 case SMB_INFO_SET_EA
:
7549 status
= smb_info_set_ea(conn
,
7557 case SMB_SET_FILE_BASIC_INFO
:
7558 case SMB_FILE_BASIC_INFORMATION
:
7560 status
= smb_set_file_basic_info(conn
,
7568 case SMB_FILE_ALLOCATION_INFORMATION
:
7569 case SMB_SET_FILE_ALLOCATION_INFO
:
7571 status
= smb_set_file_allocation_info(conn
, req
,
7579 case SMB_FILE_END_OF_FILE_INFORMATION
:
7580 case SMB_SET_FILE_END_OF_FILE_INFO
:
7583 * XP/Win7 both fail after the createfile with
7584 * SMB_SET_FILE_END_OF_FILE_INFO but not
7585 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7586 * The level is known here, so pass it down
7590 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7592 status
= smb_set_file_end_of_file_info(conn
, req
,
7601 case SMB_FILE_DISPOSITION_INFORMATION
:
7602 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7605 /* JRA - We used to just ignore this on a path ?
7606 * Shouldn't this be invalid level on a pathname
7609 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7610 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7613 status
= smb_set_file_disposition_info(conn
,
7621 case SMB_FILE_POSITION_INFORMATION
:
7623 status
= smb_file_position_information(conn
,
7630 case SMB_FILE_FULL_EA_INFORMATION
:
7632 status
= smb_set_file_full_ea_info(conn
,
7639 /* From tridge Samba4 :
7640 * MODE_INFORMATION in setfileinfo (I have no
7641 * idea what "mode information" on a file is - it takes a value of 0,
7642 * 2, 4 or 6. What could it be?).
7645 case SMB_FILE_MODE_INFORMATION
:
7647 status
= smb_file_mode_information(conn
,
7654 * CIFS UNIX extensions.
7657 case SMB_SET_FILE_UNIX_BASIC
:
7659 status
= smb_set_file_unix_basic(conn
, req
,
7667 case SMB_SET_FILE_UNIX_INFO2
:
7669 status
= smb_set_file_unix_info2(conn
, req
,
7677 case SMB_SET_FILE_UNIX_LINK
:
7680 /* We must have a pathname for this. */
7681 return NT_STATUS_INVALID_LEVEL
;
7683 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7684 total_data
, smb_fname
);
7688 case SMB_SET_FILE_UNIX_HLINK
:
7691 /* We must have a pathname for this. */
7692 return NT_STATUS_INVALID_LEVEL
;
7694 status
= smb_set_file_unix_hlink(conn
, req
,
7700 case SMB_FILE_RENAME_INFORMATION
:
7702 status
= smb_file_rename_information(conn
, req
,
7708 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7710 /* SMB2 rename information. */
7711 status
= smb2_file_rename_information(conn
, req
,
7717 case SMB_FILE_LINK_INFORMATION
:
7719 status
= smb_file_link_information(conn
, req
,
7725 #if defined(HAVE_POSIX_ACLS)
7726 case SMB_SET_POSIX_ACL
:
7728 status
= smb_set_posix_acl(conn
,
7737 case SMB_SET_POSIX_LOCK
:
7740 return NT_STATUS_INVALID_LEVEL
;
7742 status
= smb_set_posix_lock(conn
, req
,
7743 pdata
, total_data
, fsp
);
7747 case SMB_POSIX_PATH_OPEN
:
7750 /* We must have a pathname for this. */
7751 return NT_STATUS_INVALID_LEVEL
;
7754 status
= smb_posix_open(conn
, req
,
7762 case SMB_POSIX_PATH_UNLINK
:
7765 /* We must have a pathname for this. */
7766 return NT_STATUS_INVALID_LEVEL
;
7769 status
= smb_posix_unlink(conn
, req
,
7777 return NT_STATUS_INVALID_LEVEL
;
7780 if (!NT_STATUS_IS_OK(status
)) {
7784 *ret_data_size
= data_return_size
;
7785 return NT_STATUS_OK
;
7788 /****************************************************************************
7789 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7790 ****************************************************************************/
7792 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7793 struct smb_request
*req
,
7794 unsigned int tran_call
,
7795 char **pparams
, int total_params
,
7796 char **ppdata
, int total_data
,
7797 unsigned int max_data_bytes
)
7799 char *params
= *pparams
;
7800 char *pdata
= *ppdata
;
7802 struct smb_filename
*smb_fname
= NULL
;
7803 files_struct
*fsp
= NULL
;
7804 NTSTATUS status
= NT_STATUS_OK
;
7805 int data_return_size
= 0;
7808 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7812 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7813 if (total_params
< 4) {
7814 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7818 fsp
= file_fsp(req
, SVAL(params
,0));
7819 /* Basic check for non-null fsp. */
7820 if (!check_fsp_open(conn
, req
, fsp
)) {
7823 info_level
= SVAL(params
,2);
7825 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7827 if (!NT_STATUS_IS_OK(status
)) {
7828 reply_nterror(req
, status
);
7832 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7834 * This is actually a SETFILEINFO on a directory
7835 * handle (returned from an NT SMB). NT5.0 seems
7836 * to do this call. JRA.
7838 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7839 /* Always do lstat for UNIX calls. */
7840 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7841 DEBUG(3,("call_trans2setfilepathinfo: "
7842 "SMB_VFS_LSTAT of %s failed "
7844 smb_fname_str_dbg(smb_fname
),
7846 reply_nterror(req
, map_nt_error_from_unix(errno
));
7850 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7851 DEBUG(3,("call_trans2setfilepathinfo: "
7852 "fileinfo of %s failed (%s)\n",
7853 smb_fname_str_dbg(smb_fname
),
7855 reply_nterror(req
, map_nt_error_from_unix(errno
));
7859 } else if (fsp
->print_file
) {
7861 * Doing a DELETE_ON_CLOSE should cancel a print job.
7863 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7864 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
7866 DEBUG(3,("call_trans2setfilepathinfo: "
7867 "Cancelling print job (%s)\n",
7871 send_trans2_replies(conn
, req
, params
, 2,
7877 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7882 * Original code - this is an open file.
7884 if (!check_fsp(conn
, req
, fsp
)) {
7888 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7889 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7890 "of fnum %d failed (%s)\n", fsp
->fnum
,
7892 reply_nterror(req
, map_nt_error_from_unix(errno
));
7900 if (total_params
< 7) {
7901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7905 info_level
= SVAL(params
,0);
7906 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7907 total_params
- 6, STR_TERMINATE
,
7909 if (!NT_STATUS_IS_OK(status
)) {
7910 reply_nterror(req
, status
);
7914 status
= filename_convert(req
, conn
,
7915 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7920 if (!NT_STATUS_IS_OK(status
)) {
7921 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7922 reply_botherror(req
,
7923 NT_STATUS_PATH_NOT_COVERED
,
7924 ERRSRV
, ERRbadpath
);
7927 reply_nterror(req
, status
);
7931 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7933 * For CIFS UNIX extensions the target name may not exist.
7936 /* Always do lstat for UNIX calls. */
7937 SMB_VFS_LSTAT(conn
, smb_fname
);
7939 } else if (!VALID_STAT(smb_fname
->st
) &&
7940 SMB_VFS_STAT(conn
, smb_fname
)) {
7941 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7943 smb_fname_str_dbg(smb_fname
),
7945 reply_nterror(req
, map_nt_error_from_unix(errno
));
7950 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7951 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7952 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7954 /* Realloc the parameter size */
7955 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7956 if (*pparams
== NULL
) {
7957 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7964 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7970 if (!NT_STATUS_IS_OK(status
)) {
7971 if (open_was_deferred(req
->mid
)) {
7972 /* We have re-scheduled this call. */
7975 if (blocking_lock_was_deferred_smb1(req
->mid
)) {
7976 /* We have re-scheduled this call. */
7979 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7980 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7981 ERRSRV
, ERRbadpath
);
7984 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7985 reply_openerror(req
, status
);
7989 reply_nterror(req
, status
);
7993 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7999 /****************************************************************************
8000 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8001 ****************************************************************************/
8003 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8004 char **pparams
, int total_params
,
8005 char **ppdata
, int total_data
,
8006 unsigned int max_data_bytes
)
8008 struct smb_filename
*smb_dname
= NULL
;
8009 char *params
= *pparams
;
8010 char *pdata
= *ppdata
;
8011 char *directory
= NULL
;
8012 NTSTATUS status
= NT_STATUS_OK
;
8013 struct ea_list
*ea_list
= NULL
;
8014 TALLOC_CTX
*ctx
= talloc_tos();
8016 if (!CAN_WRITE(conn
)) {
8017 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8021 if (total_params
< 5) {
8022 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8026 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8027 total_params
- 4, STR_TERMINATE
,
8029 if (!NT_STATUS_IS_OK(status
)) {
8030 reply_nterror(req
, status
);
8034 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8036 status
= filename_convert(ctx
,
8038 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8044 if (!NT_STATUS_IS_OK(status
)) {
8045 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8046 reply_botherror(req
,
8047 NT_STATUS_PATH_NOT_COVERED
,
8048 ERRSRV
, ERRbadpath
);
8051 reply_nterror(req
, status
);
8056 * OS/2 workplace shell seems to send SET_EA requests of "null"
8057 * length (4 bytes containing IVAL 4).
8058 * They seem to have no effect. Bug #3212. JRA.
8061 if (total_data
&& (total_data
!= 4)) {
8062 /* Any data in this call is an EA list. */
8063 if (total_data
< 10) {
8064 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8068 if (IVAL(pdata
,0) > total_data
) {
8069 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8070 IVAL(pdata
,0), (unsigned int)total_data
));
8071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8075 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8078 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8082 if (!lp_ea_support(SNUM(conn
))) {
8083 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8087 /* If total_data == 4 Windows doesn't care what values
8088 * are placed in that field, it just ignores them.
8089 * The System i QNTC IBM SMB client puts bad values here,
8090 * so ignore them. */
8092 status
= create_directory(conn
, req
, smb_dname
);
8094 if (!NT_STATUS_IS_OK(status
)) {
8095 reply_nterror(req
, status
);
8099 /* Try and set any given EA. */
8101 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8102 if (!NT_STATUS_IS_OK(status
)) {
8103 reply_nterror(req
, status
);
8108 /* Realloc the parameter and data sizes */
8109 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8110 if(*pparams
== NULL
) {
8111 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8118 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8121 TALLOC_FREE(smb_dname
);
8125 /****************************************************************************
8126 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8127 We don't actually do this - we just send a null response.
8128 ****************************************************************************/
8130 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8131 struct smb_request
*req
,
8132 char **pparams
, int total_params
,
8133 char **ppdata
, int total_data
,
8134 unsigned int max_data_bytes
)
8136 char *params
= *pparams
;
8139 if (total_params
< 6) {
8140 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8144 info_level
= SVAL(params
,4);
8145 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8147 switch (info_level
) {
8152 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8156 /* Realloc the parameter and data sizes */
8157 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8158 if (*pparams
== NULL
) {
8159 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8164 SSVAL(params
,0,fnf_handle
);
8165 SSVAL(params
,2,0); /* No changes */
8166 SSVAL(params
,4,0); /* No EA errors */
8173 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8178 /****************************************************************************
8179 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8180 changes). Currently this does nothing.
8181 ****************************************************************************/
8183 static void call_trans2findnotifynext(connection_struct
*conn
,
8184 struct smb_request
*req
,
8185 char **pparams
, int total_params
,
8186 char **ppdata
, int total_data
,
8187 unsigned int max_data_bytes
)
8189 char *params
= *pparams
;
8191 DEBUG(3,("call_trans2findnotifynext\n"));
8193 /* Realloc the parameter and data sizes */
8194 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8195 if (*pparams
== NULL
) {
8196 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8201 SSVAL(params
,0,0); /* No changes */
8202 SSVAL(params
,2,0); /* No EA errors */
8204 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8209 /****************************************************************************
8210 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8211 ****************************************************************************/
8213 static void call_trans2getdfsreferral(connection_struct
*conn
,
8214 struct smb_request
*req
,
8215 char **pparams
, int total_params
,
8216 char **ppdata
, int total_data
,
8217 unsigned int max_data_bytes
)
8219 char *params
= *pparams
;
8220 char *pathname
= NULL
;
8222 int max_referral_level
;
8223 NTSTATUS status
= NT_STATUS_OK
;
8224 TALLOC_CTX
*ctx
= talloc_tos();
8226 DEBUG(10,("call_trans2getdfsreferral\n"));
8228 if (total_params
< 3) {
8229 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8233 max_referral_level
= SVAL(params
,0);
8235 if(!lp_host_msdfs()) {
8236 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8240 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8241 total_params
- 2, STR_TERMINATE
);
8243 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8246 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8247 ppdata
,&status
)) < 0) {
8248 reply_nterror(req
, status
);
8252 SSVAL(req
->inbuf
, smb_flg2
,
8253 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8254 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8259 #define LMCAT_SPL 0x53
8260 #define LMFUNC_GETJOBID 0x60
8262 /****************************************************************************
8263 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8264 ****************************************************************************/
8266 static void call_trans2ioctl(connection_struct
*conn
,
8267 struct smb_request
*req
,
8268 char **pparams
, int total_params
,
8269 char **ppdata
, int total_data
,
8270 unsigned int max_data_bytes
)
8272 char *pdata
= *ppdata
;
8273 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8275 /* check for an invalid fid before proceeding */
8278 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8282 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8283 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8284 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8285 if (*ppdata
== NULL
) {
8286 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8291 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8292 CAN ACCEPT THIS IN UNICODE. JRA. */
8295 if (fsp
->print_file
) {
8296 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8300 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8301 global_myname(), 15,
8302 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8303 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8304 lp_servicename(SNUM(conn
)), 13,
8305 STR_ASCII
|STR_TERMINATE
); /* Service name */
8306 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8311 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8312 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8315 /****************************************************************************
8316 Reply to a SMBfindclose (stop trans2 directory search).
8317 ****************************************************************************/
8319 void reply_findclose(struct smb_request
*req
)
8322 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8324 START_PROFILE(SMBfindclose
);
8327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8328 END_PROFILE(SMBfindclose
);
8332 dptr_num
= SVALS(req
->vwv
+0, 0);
8334 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8336 dptr_close(sconn
, &dptr_num
);
8338 reply_outbuf(req
, 0, 0);
8340 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8342 END_PROFILE(SMBfindclose
);
8346 /****************************************************************************
8347 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8348 ****************************************************************************/
8350 void reply_findnclose(struct smb_request
*req
)
8354 START_PROFILE(SMBfindnclose
);
8357 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8358 END_PROFILE(SMBfindnclose
);
8362 dptr_num
= SVAL(req
->vwv
+0, 0);
8364 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8366 /* We never give out valid handles for a
8367 findnotifyfirst - so any dptr_num is ok here.
8370 reply_outbuf(req
, 0, 0);
8372 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8374 END_PROFILE(SMBfindnclose
);
8378 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8379 struct trans_state
*state
)
8381 if (get_Protocol() >= PROTOCOL_NT1
) {
8382 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8383 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8386 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8387 if (state
->call
!= TRANSACT2_QFSINFO
&&
8388 state
->call
!= TRANSACT2_SETFSINFO
) {
8389 DEBUG(0,("handle_trans2: encryption required "
8391 (unsigned int)state
->call
));
8392 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8397 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8399 /* Now we must call the relevant TRANS2 function */
8400 switch(state
->call
) {
8401 case TRANSACT2_OPEN
:
8403 START_PROFILE(Trans2_open
);
8404 call_trans2open(conn
, req
,
8405 &state
->param
, state
->total_param
,
8406 &state
->data
, state
->total_data
,
8407 state
->max_data_return
);
8408 END_PROFILE(Trans2_open
);
8412 case TRANSACT2_FINDFIRST
:
8414 START_PROFILE(Trans2_findfirst
);
8415 call_trans2findfirst(conn
, req
,
8416 &state
->param
, state
->total_param
,
8417 &state
->data
, state
->total_data
,
8418 state
->max_data_return
);
8419 END_PROFILE(Trans2_findfirst
);
8423 case TRANSACT2_FINDNEXT
:
8425 START_PROFILE(Trans2_findnext
);
8426 call_trans2findnext(conn
, req
,
8427 &state
->param
, state
->total_param
,
8428 &state
->data
, state
->total_data
,
8429 state
->max_data_return
);
8430 END_PROFILE(Trans2_findnext
);
8434 case TRANSACT2_QFSINFO
:
8436 START_PROFILE(Trans2_qfsinfo
);
8437 call_trans2qfsinfo(conn
, req
,
8438 &state
->param
, state
->total_param
,
8439 &state
->data
, state
->total_data
,
8440 state
->max_data_return
);
8441 END_PROFILE(Trans2_qfsinfo
);
8445 case TRANSACT2_SETFSINFO
:
8447 START_PROFILE(Trans2_setfsinfo
);
8448 call_trans2setfsinfo(conn
, req
,
8449 &state
->param
, state
->total_param
,
8450 &state
->data
, state
->total_data
,
8451 state
->max_data_return
);
8452 END_PROFILE(Trans2_setfsinfo
);
8456 case TRANSACT2_QPATHINFO
:
8457 case TRANSACT2_QFILEINFO
:
8459 START_PROFILE(Trans2_qpathinfo
);
8460 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8461 &state
->param
, state
->total_param
,
8462 &state
->data
, state
->total_data
,
8463 state
->max_data_return
);
8464 END_PROFILE(Trans2_qpathinfo
);
8468 case TRANSACT2_SETPATHINFO
:
8469 case TRANSACT2_SETFILEINFO
:
8471 START_PROFILE(Trans2_setpathinfo
);
8472 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8473 &state
->param
, state
->total_param
,
8474 &state
->data
, state
->total_data
,
8475 state
->max_data_return
);
8476 END_PROFILE(Trans2_setpathinfo
);
8480 case TRANSACT2_FINDNOTIFYFIRST
:
8482 START_PROFILE(Trans2_findnotifyfirst
);
8483 call_trans2findnotifyfirst(conn
, req
,
8484 &state
->param
, state
->total_param
,
8485 &state
->data
, state
->total_data
,
8486 state
->max_data_return
);
8487 END_PROFILE(Trans2_findnotifyfirst
);
8491 case TRANSACT2_FINDNOTIFYNEXT
:
8493 START_PROFILE(Trans2_findnotifynext
);
8494 call_trans2findnotifynext(conn
, req
,
8495 &state
->param
, state
->total_param
,
8496 &state
->data
, state
->total_data
,
8497 state
->max_data_return
);
8498 END_PROFILE(Trans2_findnotifynext
);
8502 case TRANSACT2_MKDIR
:
8504 START_PROFILE(Trans2_mkdir
);
8505 call_trans2mkdir(conn
, req
,
8506 &state
->param
, state
->total_param
,
8507 &state
->data
, state
->total_data
,
8508 state
->max_data_return
);
8509 END_PROFILE(Trans2_mkdir
);
8513 case TRANSACT2_GET_DFS_REFERRAL
:
8515 START_PROFILE(Trans2_get_dfs_referral
);
8516 call_trans2getdfsreferral(conn
, req
,
8517 &state
->param
, state
->total_param
,
8518 &state
->data
, state
->total_data
,
8519 state
->max_data_return
);
8520 END_PROFILE(Trans2_get_dfs_referral
);
8524 case TRANSACT2_IOCTL
:
8526 START_PROFILE(Trans2_ioctl
);
8527 call_trans2ioctl(conn
, req
,
8528 &state
->param
, state
->total_param
,
8529 &state
->data
, state
->total_data
,
8530 state
->max_data_return
);
8531 END_PROFILE(Trans2_ioctl
);
8536 /* Error in request */
8537 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8538 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8542 /****************************************************************************
8543 Reply to a SMBtrans2.
8544 ****************************************************************************/
8546 void reply_trans2(struct smb_request
*req
)
8548 connection_struct
*conn
= req
->conn
;
8553 unsigned int tran_call
;
8554 struct trans_state
*state
;
8557 START_PROFILE(SMBtrans2
);
8559 if (req
->wct
< 14) {
8560 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8561 END_PROFILE(SMBtrans2
);
8565 dsoff
= SVAL(req
->vwv
+12, 0);
8566 dscnt
= SVAL(req
->vwv
+11, 0);
8567 psoff
= SVAL(req
->vwv
+10, 0);
8568 pscnt
= SVAL(req
->vwv
+9, 0);
8569 tran_call
= SVAL(req
->vwv
+14, 0);
8571 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8572 if (!NT_STATUS_IS_OK(result
)) {
8573 DEBUG(2, ("Got invalid trans2 request: %s\n",
8574 nt_errstr(result
)));
8575 reply_nterror(req
, result
);
8576 END_PROFILE(SMBtrans2
);
8581 switch (tran_call
) {
8582 /* List the allowed trans2 calls on IPC$ */
8583 case TRANSACT2_OPEN
:
8584 case TRANSACT2_GET_DFS_REFERRAL
:
8585 case TRANSACT2_QFILEINFO
:
8586 case TRANSACT2_QFSINFO
:
8587 case TRANSACT2_SETFSINFO
:
8590 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8591 END_PROFILE(SMBtrans2
);
8596 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8597 DEBUG(0, ("talloc failed\n"));
8598 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8599 END_PROFILE(SMBtrans2
);
8603 state
->cmd
= SMBtrans2
;
8605 state
->mid
= req
->mid
;
8606 state
->vuid
= req
->vuid
;
8607 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8608 state
->setup
= NULL
;
8609 state
->total_param
= SVAL(req
->vwv
+0, 0);
8610 state
->param
= NULL
;
8611 state
->total_data
= SVAL(req
->vwv
+1, 0);
8613 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8614 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8615 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8616 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8617 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8619 state
->call
= tran_call
;
8621 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8622 is so as a sanity check */
8623 if (state
->setup_count
!= 1) {
8625 * Need to have rc=0 for ioctl to get job id for OS/2.
8626 * Network printing will fail if function is not successful.
8627 * Similar function in reply.c will be used if protocol
8628 * is LANMAN1.0 instead of LM1.2X002.
8629 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8630 * outbuf doesn't have to be set(only job id is used).
8632 if ( (state
->setup_count
== 4)
8633 && (tran_call
== TRANSACT2_IOCTL
)
8634 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8635 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8636 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8638 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8639 DEBUG(2,("Transaction is %d\n",tran_call
));
8641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8642 END_PROFILE(SMBtrans2
);
8647 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8650 if (state
->total_data
) {
8652 if (trans_oob(state
->total_data
, 0, dscnt
)
8653 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8657 /* Can't use talloc here, the core routines do realloc on the
8658 * params and data. */
8659 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8660 if (state
->data
== NULL
) {
8661 DEBUG(0,("reply_trans2: data malloc fail for %u "
8662 "bytes !\n", (unsigned int)state
->total_data
));
8664 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8665 END_PROFILE(SMBtrans2
);
8669 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8672 if (state
->total_param
) {
8674 if (trans_oob(state
->total_param
, 0, pscnt
)
8675 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8679 /* Can't use talloc here, the core routines do realloc on the
8680 * params and data. */
8681 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8682 if (state
->param
== NULL
) {
8683 DEBUG(0,("reply_trans: param malloc fail for %u "
8684 "bytes !\n", (unsigned int)state
->total_param
));
8685 SAFE_FREE(state
->data
);
8687 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8688 END_PROFILE(SMBtrans2
);
8692 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8695 state
->received_data
= dscnt
;
8696 state
->received_param
= pscnt
;
8698 if ((state
->received_param
== state
->total_param
) &&
8699 (state
->received_data
== state
->total_data
)) {
8701 handle_trans2(conn
, req
, state
);
8703 SAFE_FREE(state
->data
);
8704 SAFE_FREE(state
->param
);
8706 END_PROFILE(SMBtrans2
);
8710 DLIST_ADD(conn
->pending_trans
, state
);
8712 /* We need to send an interim response then receive the rest
8713 of the parameter/data bytes */
8714 reply_outbuf(req
, 0, 0);
8715 show_msg((char *)req
->outbuf
);
8716 END_PROFILE(SMBtrans2
);
8721 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8722 SAFE_FREE(state
->data
);
8723 SAFE_FREE(state
->param
);
8725 END_PROFILE(SMBtrans2
);
8726 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8730 /****************************************************************************
8731 Reply to a SMBtranss2
8732 ****************************************************************************/
8734 void reply_transs2(struct smb_request
*req
)
8736 connection_struct
*conn
= req
->conn
;
8737 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8738 struct trans_state
*state
;
8740 START_PROFILE(SMBtranss2
);
8742 show_msg((char *)req
->inbuf
);
8745 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8746 END_PROFILE(SMBtranss2
);
8750 for (state
= conn
->pending_trans
; state
!= NULL
;
8751 state
= state
->next
) {
8752 if (state
->mid
== req
->mid
) {
8757 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8758 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8759 END_PROFILE(SMBtranss2
);
8763 /* Revise state->total_param and state->total_data in case they have
8764 changed downwards */
8766 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8767 state
->total_param
= SVAL(req
->vwv
+0, 0);
8768 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8769 state
->total_data
= SVAL(req
->vwv
+1, 0);
8771 pcnt
= SVAL(req
->vwv
+2, 0);
8772 poff
= SVAL(req
->vwv
+3, 0);
8773 pdisp
= SVAL(req
->vwv
+4, 0);
8775 dcnt
= SVAL(req
->vwv
+5, 0);
8776 doff
= SVAL(req
->vwv
+6, 0);
8777 ddisp
= SVAL(req
->vwv
+7, 0);
8779 state
->received_param
+= pcnt
;
8780 state
->received_data
+= dcnt
;
8782 if ((state
->received_data
> state
->total_data
) ||
8783 (state
->received_param
> state
->total_param
))
8787 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8788 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8791 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8795 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8796 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8799 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8802 if ((state
->received_param
< state
->total_param
) ||
8803 (state
->received_data
< state
->total_data
)) {
8804 END_PROFILE(SMBtranss2
);
8808 handle_trans2(conn
, req
, state
);
8810 DLIST_REMOVE(conn
->pending_trans
, state
);
8811 SAFE_FREE(state
->data
);
8812 SAFE_FREE(state
->param
);
8815 END_PROFILE(SMBtranss2
);
8820 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8821 DLIST_REMOVE(conn
->pending_trans
, state
);
8822 SAFE_FREE(state
->data
);
8823 SAFE_FREE(state
->param
);
8825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8826 END_PROFILE(SMBtranss2
);