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"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct
*conn
,
36 const SMB_STRUCT_STAT
*psbuf
);
38 static char *store_file_unix_basic_info2(connection_struct
*conn
,
41 const SMB_STRUCT_STAT
*psbuf
);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
50 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type
= get_remote_arch();
54 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
55 val
= SMB_ROUNDUP(val
,rval
);
60 /****************************************************************************
61 Utility functions for dealing with extended attributes.
62 ****************************************************************************/
64 /****************************************************************************
65 Refuse to allow clients to overwrite our private xattrs.
66 ****************************************************************************/
68 static bool samba_private_attr_name(const char *unix_ea_name
)
70 static const char * const prohibited_ea_names
[] = {
71 SAMBA_POSIX_INHERITANCE_EA_NAME
,
72 SAMBA_XATTR_DOS_ATTRIB
,
80 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
81 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
84 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
96 files_struct
*fsp
, const char *fname
,
97 const char *ea_name
, struct ea_struct
*pea
)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size
= 256;
106 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
108 return NT_STATUS_NO_MEMORY
;
111 if (fsp
&& fsp
->fh
->fd
!= -1) {
112 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
114 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
117 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
123 return map_nt_error_from_unix(errno
);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
127 dump_data(10, (uint8
*)val
, sizeret
);
130 if (strnequal(ea_name
, "user.", 5)) {
131 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
133 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
135 if (pea
->name
== NULL
) {
137 return NT_STATUS_NO_MEMORY
;
139 pea
->value
.data
= (unsigned char *)val
;
140 pea
->value
.length
= (size_t)sizeret
;
144 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
145 files_struct
*fsp
, const char *fname
,
146 char ***pnames
, size_t *pnum_names
)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size
= 1024;
150 char *ea_namelist
= NULL
;
155 ssize_t sizeret
= -1;
157 if (!lp_ea_support(SNUM(conn
))) {
166 * TALLOC the result early to get the talloc hierarchy right.
169 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
171 DEBUG(0, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY
;
175 while (ea_namelist_size
<= 65536) {
177 ea_namelist
= TALLOC_REALLOC_ARRAY(
178 names
, ea_namelist
, char, ea_namelist_size
);
179 if (ea_namelist
== NULL
) {
180 DEBUG(0, ("talloc failed\n"));
182 return NT_STATUS_NO_MEMORY
;
185 if (fsp
&& fsp
->fh
->fd
!= -1) {
186 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
189 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
193 if ((sizeret
== -1) && (errno
== ERANGE
)) {
194 ea_namelist_size
*= 2;
203 return map_nt_error_from_unix(errno
);
206 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
207 (unsigned int)sizeret
));
219 * Ensure the result is 0-terminated
222 if (ea_namelist
[sizeret
-1] != '\0') {
224 return NT_STATUS_INTERNAL_ERROR
;
232 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
236 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
238 DEBUG(0, ("talloc failed\n"));
240 return NT_STATUS_NO_MEMORY
;
246 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
247 names
[num_names
++] = p
;
255 *pnum_names
= num_names
;
259 /****************************************************************************
260 Return a linked list of the total EA's. Plus the total size
261 ****************************************************************************/
263 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
264 const char *fname
, size_t *pea_total_len
)
266 /* Get a list of all xattrs. Max namesize is 64k. */
269 struct ea_list
*ea_list_head
= NULL
;
274 if (!lp_ea_support(SNUM(conn
))) {
278 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
281 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
285 for (i
=0; i
<num_names
; i
++) {
286 struct ea_list
*listp
;
289 if (strnequal(names
[i
], "system.", 7)
290 || samba_private_attr_name(names
[i
]))
293 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
298 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
304 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
307 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
309 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
310 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
311 (unsigned int)listp
->ea
.value
.length
));
313 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
317 /* Add on 4 for total length. */
318 if (*pea_total_len
) {
322 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
323 (unsigned int)*pea_total_len
));
328 /****************************************************************************
329 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
331 ****************************************************************************/
333 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
334 connection_struct
*conn
, struct ea_list
*ea_list
)
336 unsigned int ret_data_size
= 4;
339 SMB_ASSERT(total_data_size
>= 4);
341 if (!lp_ea_support(SNUM(conn
))) {
346 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
349 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
350 dos_namelen
= strlen(dos_ea_name
);
351 if (dos_namelen
> 255 || dos_namelen
== 0) {
354 if (ea_list
->ea
.value
.length
> 65535) {
357 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
361 /* We know we have room. */
362 SCVAL(p
,0,ea_list
->ea
.flags
);
363 SCVAL(p
,1,dos_namelen
);
364 SSVAL(p
,2,ea_list
->ea
.value
.length
);
365 fstrcpy(p
+4, dos_ea_name
);
366 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
368 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
369 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
372 ret_data_size
= PTR_DIFF(p
, pdata
);
373 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
374 SIVAL(pdata
,0,ret_data_size
);
375 return ret_data_size
;
378 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
380 unsigned int total_data_size
,
381 unsigned int *ret_data_size
,
382 connection_struct
*conn
,
383 struct ea_list
*ea_list
)
385 uint8_t *p
= (uint8_t *)pdata
;
386 uint8_t *last_start
= NULL
;
390 if (!lp_ea_support(SNUM(conn
))) {
391 return NT_STATUS_NO_EAS_ON_FILE
;
394 for (; ea_list
; ea_list
= ea_list
->next
) {
400 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
404 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
405 dos_namelen
= strlen(dos_ea_name
);
406 if (dos_namelen
> 255 || dos_namelen
== 0) {
407 return NT_STATUS_INTERNAL_ERROR
;
409 if (ea_list
->ea
.value
.length
> 65535) {
410 return NT_STATUS_INTERNAL_ERROR
;
413 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
416 size_t pad
= 4 - (this_size
% 4);
420 if (this_size
> total_data_size
) {
421 return NT_STATUS_INFO_LENGTH_MISMATCH
;
424 /* We know we have room. */
425 SIVAL(p
, 0x00, 0); /* next offset */
426 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
427 SCVAL(p
, 0x05, dos_namelen
);
428 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
429 fstrcpy((char *)(p
+0x08), dos_ea_name
);
430 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
432 total_data_size
-= this_size
;
436 *ret_data_size
= PTR_DIFF(p
, pdata
);
437 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
441 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
443 size_t total_ea_len
= 0;
444 TALLOC_CTX
*mem_ctx
= NULL
;
446 if (!lp_ea_support(SNUM(conn
))) {
449 mem_ctx
= talloc_tos();
450 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
454 /****************************************************************************
455 Ensure the EA name is case insensitive by matching any existing EA name.
456 ****************************************************************************/
458 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
461 TALLOC_CTX
*mem_ctx
= talloc_tos();
462 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
464 for (; ea_list
; ea_list
= ea_list
->next
) {
465 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
466 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
467 &unix_ea_name
[5], ea_list
->ea
.name
));
468 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
474 /****************************************************************************
475 Set or delete an extended attribute.
476 ****************************************************************************/
478 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
479 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
483 if (!lp_ea_support(SNUM(conn
))) {
484 return NT_STATUS_EAS_NOT_SUPPORTED
;
487 /* For now setting EAs on streams isn't supported. */
488 fname
= smb_fname
->base_name
;
490 for (;ea_list
; ea_list
= ea_list
->next
) {
492 fstring unix_ea_name
;
494 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
495 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
497 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
499 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
501 if (samba_private_attr_name(unix_ea_name
)) {
502 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
503 return NT_STATUS_ACCESS_DENIED
;
506 if (ea_list
->ea
.value
.length
== 0) {
507 /* Remove the attribute. */
508 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
509 DEBUG(10,("set_ea: deleting ea name %s on "
510 "file %s by file descriptor.\n",
511 unix_ea_name
, fsp_str_dbg(fsp
)));
512 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
514 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
515 unix_ea_name
, fname
));
516 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
519 /* Removing a non existent attribute always succeeds. */
520 if (ret
== -1 && errno
== ENOATTR
) {
521 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
527 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
528 DEBUG(10,("set_ea: setting ea name %s on file "
529 "%s by file descriptor.\n",
530 unix_ea_name
, fsp_str_dbg(fsp
)));
531 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
532 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
534 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
535 unix_ea_name
, fname
));
536 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
537 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
543 if (errno
== ENOTSUP
) {
544 return NT_STATUS_EAS_NOT_SUPPORTED
;
547 return map_nt_error_from_unix(errno
);
553 /****************************************************************************
554 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
555 ****************************************************************************/
557 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
559 struct ea_list
*ea_list_head
= NULL
;
560 size_t converted_size
, offset
= 0;
562 while (offset
+ 2 < data_size
) {
563 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
564 unsigned int namelen
= CVAL(pdata
,offset
);
566 offset
++; /* Go past the namelen byte. */
568 /* integer wrap paranioa. */
569 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
570 (offset
> data_size
) || (namelen
> data_size
) ||
571 (offset
+ namelen
>= data_size
)) {
574 /* Ensure the name is null terminated. */
575 if (pdata
[offset
+ namelen
] != '\0') {
578 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
580 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
581 "failed: %s", strerror(errno
)));
587 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
588 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
589 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
595 /****************************************************************************
596 Read one EA list entry from the buffer.
597 ****************************************************************************/
599 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
601 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
603 unsigned int namelen
;
604 size_t converted_size
;
614 eal
->ea
.flags
= CVAL(pdata
,0);
615 namelen
= CVAL(pdata
,1);
616 val_len
= SVAL(pdata
,2);
618 if (4 + namelen
+ 1 + val_len
> data_size
) {
622 /* Ensure the name is null terminated. */
623 if (pdata
[namelen
+ 4] != '\0') {
626 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
627 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
634 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
635 if (!eal
->ea
.value
.data
) {
639 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
641 /* Ensure we're null terminated just in case we print the value. */
642 eal
->ea
.value
.data
[val_len
] = '\0';
643 /* But don't count the null. */
644 eal
->ea
.value
.length
--;
647 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
650 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
651 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
656 /****************************************************************************
657 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
658 ****************************************************************************/
660 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
662 struct ea_list
*ea_list_head
= NULL
;
664 size_t bytes_used
= 0;
666 while (offset
< data_size
) {
667 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
673 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
674 offset
+= bytes_used
;
680 /****************************************************************************
681 Count the total EA size needed.
682 ****************************************************************************/
684 static size_t ea_list_size(struct ea_list
*ealist
)
687 struct ea_list
*listp
;
690 for (listp
= ealist
; listp
; listp
= listp
->next
) {
691 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
692 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
694 /* Add on 4 for total length. */
702 /****************************************************************************
703 Return a union of EA's from a file list and a list of names.
704 The TALLOC context for the two lists *MUST* be identical as we steal
705 memory from one list to add to another. JRA.
706 ****************************************************************************/
708 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
710 struct ea_list
*nlistp
, *flistp
;
712 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
713 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
714 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
720 /* Copy the data from this entry. */
721 nlistp
->ea
.flags
= flistp
->ea
.flags
;
722 nlistp
->ea
.value
= flistp
->ea
.value
;
725 nlistp
->ea
.flags
= 0;
726 ZERO_STRUCT(nlistp
->ea
.value
);
730 *total_ea_len
= ea_list_size(name_list
);
734 /****************************************************************************
735 Send the required number of replies back.
736 We assume all fields other than the data fields are
737 set correctly for the type of call.
738 HACK ! Always assumes smb_setup field is zero.
739 ****************************************************************************/
741 void send_trans2_replies(connection_struct
*conn
,
742 struct smb_request
*req
,
749 /* As we are using a protocol > LANMAN1 then the max_send
750 variable must have been set in the sessetupX call.
751 This takes precedence over the max_xmit field in the
752 global struct. These different max_xmit variables should
753 be merged as this is now too confusing */
755 int data_to_send
= datasize
;
756 int params_to_send
= paramsize
;
758 const char *pp
= params
;
759 const char *pd
= pdata
;
760 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
761 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
762 int data_alignment_offset
= 0;
763 bool overflow
= False
;
764 struct smbd_server_connection
*sconn
= smbd_server_conn
;
765 int max_send
= sconn
->smb1
.sessions
.max_send
;
767 /* Modify the data_to_send and datasize and set the error if
768 we're trying to send more than max_data_bytes. We still send
769 the part of the packet(s) that fit. Strange, but needed
772 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
773 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
774 max_data_bytes
, datasize
));
775 datasize
= data_to_send
= max_data_bytes
;
779 /* If there genuinely are no parameters or data to send just send the empty packet */
781 if(params_to_send
== 0 && data_to_send
== 0) {
782 reply_outbuf(req
, 10, 0);
783 show_msg((char *)req
->outbuf
);
784 if (!srv_send_smb(smbd_server_fd(),
787 IS_CONN_ENCRYPTED(conn
),
789 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
791 TALLOC_FREE(req
->outbuf
);
795 /* When sending params and data ensure that both are nicely aligned */
796 /* Only do this alignment when there is also data to send - else
797 can cause NT redirector problems. */
799 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
800 data_alignment_offset
= 4 - (params_to_send
% 4);
802 /* Space is bufsize minus Netbios over TCP header minus SMB header */
803 /* The alignment_offset is to align the param bytes on an even byte
804 boundary. NT 4.0 Beta needs this to work correctly. */
806 useable_space
= max_send
- (smb_size
809 + data_alignment_offset
);
811 if (useable_space
< 0) {
812 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
813 "= %d!!!", useable_space
));
814 exit_server_cleanly("send_trans2_replies: Not enough space");
817 while (params_to_send
|| data_to_send
) {
818 /* Calculate whether we will totally or partially fill this packet */
820 total_sent_thistime
= params_to_send
+ data_to_send
;
822 /* We can never send more than useable_space */
824 * Note that 'useable_space' does not include the alignment offsets,
825 * but we must include the alignment offsets in the calculation of
826 * the length of the data we send over the wire, as the alignment offsets
827 * are sent here. Fix from Marc_Jacobsen@hp.com.
830 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
832 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
833 + data_alignment_offset
);
836 * We might have SMBtrans2s in req which was transferred to
837 * the outbuf, fix that.
839 SCVAL(req
->outbuf
, smb_com
, SMBtrans2
);
841 /* Set total params and data to be sent */
842 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
843 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
845 /* Calculate how many parameters and data we can fit into
846 * this packet. Parameters get precedence
849 params_sent_thistime
= MIN(params_to_send
,useable_space
);
850 data_sent_thistime
= useable_space
- params_sent_thistime
;
851 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
853 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
855 /* smb_proff is the offset from the start of the SMB header to the
856 parameter bytes, however the first 4 bytes of outbuf are
857 the Netbios over TCP header. Thus use smb_base() to subtract
858 them from the calculation */
860 SSVAL(req
->outbuf
,smb_proff
,
861 ((smb_buf(req
->outbuf
)+alignment_offset
)
862 - smb_base(req
->outbuf
)));
864 if(params_sent_thistime
== 0)
865 SSVAL(req
->outbuf
,smb_prdisp
,0);
867 /* Absolute displacement of param bytes sent in this packet */
868 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
870 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
871 if(data_sent_thistime
== 0) {
872 SSVAL(req
->outbuf
,smb_droff
,0);
873 SSVAL(req
->outbuf
,smb_drdisp
, 0);
875 /* The offset of the data bytes is the offset of the
876 parameter bytes plus the number of parameters being sent this time */
877 SSVAL(req
->outbuf
, smb_droff
,
878 ((smb_buf(req
->outbuf
)+alignment_offset
)
879 - smb_base(req
->outbuf
))
880 + params_sent_thistime
+ data_alignment_offset
);
881 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
884 /* Initialize the padding for alignment */
886 if (alignment_offset
!= 0) {
887 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
890 /* Copy the param bytes into the packet */
892 if(params_sent_thistime
) {
893 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
894 params_sent_thistime
);
897 /* Copy in the data bytes */
898 if(data_sent_thistime
) {
899 if (data_alignment_offset
!= 0) {
900 memset((smb_buf(req
->outbuf
)+alignment_offset
+
901 params_sent_thistime
), 0,
902 data_alignment_offset
);
904 memcpy(smb_buf(req
->outbuf
)+alignment_offset
905 +params_sent_thistime
+data_alignment_offset
,
906 pd
,data_sent_thistime
);
909 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
910 params_sent_thistime
, data_sent_thistime
, useable_space
));
911 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
912 params_to_send
, data_to_send
, paramsize
, datasize
));
915 error_packet_set((char *)req
->outbuf
,
916 ERRDOS
,ERRbufferoverflow
,
917 STATUS_BUFFER_OVERFLOW
,
921 /* Send the packet */
922 show_msg((char *)req
->outbuf
);
923 if (!srv_send_smb(smbd_server_fd(),
926 IS_CONN_ENCRYPTED(conn
),
928 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
930 TALLOC_FREE(req
->outbuf
);
932 pp
+= params_sent_thistime
;
933 pd
+= data_sent_thistime
;
935 params_to_send
-= params_sent_thistime
;
936 data_to_send
-= data_sent_thistime
;
939 if(params_to_send
< 0 || data_to_send
< 0) {
940 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
941 params_to_send
, data_to_send
));
949 /****************************************************************************
950 Reply to a TRANSACT2_OPEN.
951 ****************************************************************************/
953 static void call_trans2open(connection_struct
*conn
,
954 struct smb_request
*req
,
955 char **pparams
, int total_params
,
956 char **ppdata
, int total_data
,
957 unsigned int max_data_bytes
)
959 struct smb_filename
*smb_fname
= NULL
;
960 char *params
= *pparams
;
961 char *pdata
= *ppdata
;
966 bool return_additional_info
;
979 struct ea_list
*ea_list
= NULL
;
984 uint32 create_disposition
;
985 uint32 create_options
= 0;
986 TALLOC_CTX
*ctx
= talloc_tos();
989 * Ensure we have enough parameters to perform the operation.
992 if (total_params
< 29) {
993 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
997 flags
= SVAL(params
, 0);
998 deny_mode
= SVAL(params
, 2);
999 open_attr
= SVAL(params
,6);
1000 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1001 if (oplock_request
) {
1002 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1006 return_additional_info
= BITSETW(params
,0);
1007 open_sattr
= SVAL(params
, 4);
1008 open_time
= make_unix_date3(params
+8);
1010 open_ofun
= SVAL(params
,12);
1011 open_size
= IVAL(params
,14);
1012 pname
= ¶ms
[28];
1015 reply_doserror(req
, ERRSRV
, ERRaccess
);
1019 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1020 total_params
- 28, STR_TERMINATE
,
1022 if (!NT_STATUS_IS_OK(status
)) {
1023 reply_nterror(req
, status
);
1027 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1028 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1029 (unsigned int)open_ofun
, open_size
));
1031 status
= filename_convert(ctx
,
1033 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1038 if (!NT_STATUS_IS_OK(status
)) {
1039 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1040 reply_botherror(req
,
1041 NT_STATUS_PATH_NOT_COVERED
,
1042 ERRSRV
, ERRbadpath
);
1045 reply_nterror(req
, status
);
1049 if (open_ofun
== 0) {
1050 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1054 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, open_ofun
,
1055 &access_mask
, &share_mode
,
1056 &create_disposition
,
1058 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
1062 /* Any data in this call is an EA list. */
1063 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
1064 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1068 if (total_data
!= 4) {
1069 if (total_data
< 10) {
1070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1074 if (IVAL(pdata
,0) > total_data
) {
1075 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1076 IVAL(pdata
,0), (unsigned int)total_data
));
1077 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1081 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1087 } else if (IVAL(pdata
,0) != 4) {
1088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1092 status
= SMB_VFS_CREATE_FILE(
1095 0, /* root_dir_fid */
1096 smb_fname
, /* fname */
1097 access_mask
, /* access_mask */
1098 share_mode
, /* share_access */
1099 create_disposition
, /* create_disposition*/
1100 create_options
, /* create_options */
1101 open_attr
, /* file_attributes */
1102 oplock_request
, /* oplock_request */
1103 open_size
, /* allocation_size */
1105 ea_list
, /* ea_list */
1107 &smb_action
); /* psbuf */
1109 if (!NT_STATUS_IS_OK(status
)) {
1110 if (open_was_deferred(req
->mid
)) {
1111 /* We have re-scheduled this call. */
1114 reply_openerror(req
, status
);
1118 size
= get_file_size_stat(&smb_fname
->st
);
1119 fattr
= dos_mode(conn
, smb_fname
);
1120 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1121 inode
= smb_fname
->st
.st_ex_ino
;
1123 close_file(req
, fsp
, ERROR_CLOSE
);
1124 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1128 /* Realloc the size of parameters and data we will return */
1129 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1130 if(*pparams
== NULL
) {
1131 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1136 SSVAL(params
,0,fsp
->fnum
);
1137 SSVAL(params
,2,fattr
);
1138 srv_put_dos_date2(params
,4, mtime
);
1139 SIVAL(params
,8, (uint32
)size
);
1140 SSVAL(params
,12,deny_mode
);
1141 SSVAL(params
,14,0); /* open_type - file or directory. */
1142 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1144 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1145 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1148 SSVAL(params
,18,smb_action
);
1151 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1153 SIVAL(params
,20,inode
);
1154 SSVAL(params
,24,0); /* Padding. */
1156 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1157 fsp
->fsp_name
->base_name
);
1158 SIVAL(params
, 26, ea_size
);
1160 SIVAL(params
, 26, 0);
1163 /* Send the required number of replies */
1164 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1166 TALLOC_FREE(smb_fname
);
1169 /*********************************************************
1170 Routine to check if a given string matches exactly.
1171 as a special case a mask of "." does NOT match. That
1172 is required for correct wildcard semantics
1173 Case can be significant or not.
1174 **********************************************************/
1176 static bool exact_match(bool has_wild
,
1177 bool case_sensitive
,
1181 if (mask
[0] == '.' && mask
[1] == 0) {
1189 if (case_sensitive
) {
1190 return strcmp(str
,mask
)==0;
1192 return StrCaseCmp(str
,mask
) == 0;
1196 /****************************************************************************
1197 Return the filetype for UNIX extensions.
1198 ****************************************************************************/
1200 static uint32
unix_filetype(mode_t mode
)
1203 return UNIX_TYPE_FILE
;
1204 else if(S_ISDIR(mode
))
1205 return UNIX_TYPE_DIR
;
1207 else if(S_ISLNK(mode
))
1208 return UNIX_TYPE_SYMLINK
;
1211 else if(S_ISCHR(mode
))
1212 return UNIX_TYPE_CHARDEV
;
1215 else if(S_ISBLK(mode
))
1216 return UNIX_TYPE_BLKDEV
;
1219 else if(S_ISFIFO(mode
))
1220 return UNIX_TYPE_FIFO
;
1223 else if(S_ISSOCK(mode
))
1224 return UNIX_TYPE_SOCKET
;
1227 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1228 return UNIX_TYPE_UNKNOWN
;
1231 /****************************************************************************
1232 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1233 ****************************************************************************/
1235 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1237 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1238 const SMB_STRUCT_STAT
*psbuf
,
1240 enum perm_type ptype
,
1245 if (perms
== SMB_MODE_NO_CHANGE
) {
1246 if (!VALID_STAT(*psbuf
)) {
1247 return NT_STATUS_INVALID_PARAMETER
;
1249 *ret_perms
= psbuf
->st_ex_mode
;
1250 return NT_STATUS_OK
;
1254 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1255 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1256 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1257 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1258 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1259 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1260 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1261 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1262 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1264 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1267 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1270 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1275 /* Apply mode mask */
1276 ret
&= lp_create_mask(SNUM(conn
));
1277 /* Add in force bits */
1278 ret
|= lp_force_create_mode(SNUM(conn
));
1281 ret
&= lp_dir_mask(SNUM(conn
));
1282 /* Add in force bits */
1283 ret
|= lp_force_dir_mode(SNUM(conn
));
1285 case PERM_EXISTING_FILE
:
1286 /* Apply mode mask */
1287 ret
&= lp_security_mask(SNUM(conn
));
1288 /* Add in force bits */
1289 ret
|= lp_force_security_mode(SNUM(conn
));
1291 case PERM_EXISTING_DIR
:
1292 /* Apply mode mask */
1293 ret
&= lp_dir_security_mask(SNUM(conn
));
1294 /* Add in force bits */
1295 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1300 return NT_STATUS_OK
;
1303 /****************************************************************************
1304 Needed to show the msdfs symlinks as directories. Modifies psbuf
1305 to be a directory if it's a msdfs link.
1306 ****************************************************************************/
1308 static bool check_msdfs_link(connection_struct
*conn
,
1309 const char *pathname
,
1310 SMB_STRUCT_STAT
*psbuf
)
1312 int saved_errno
= errno
;
1313 if(lp_host_msdfs() &&
1314 lp_msdfs_root(SNUM(conn
)) &&
1315 is_msdfs_link(conn
, pathname
, psbuf
)) {
1317 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1320 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1321 errno
= saved_errno
;
1324 errno
= saved_errno
;
1329 /****************************************************************************
1330 Get a level dependent lanman2 dir entry.
1331 ****************************************************************************/
1333 struct smbd_dirptr_lanman2_state
{
1334 connection_struct
*conn
;
1335 uint32_t info_level
;
1336 bool check_mangled_names
;
1338 bool got_exact_match
;
1341 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1347 struct smbd_dirptr_lanman2_state
*state
=
1348 (struct smbd_dirptr_lanman2_state
*)private_data
;
1350 char mangled_name
[13]; /* mangled 8.3 name. */
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1356 ok
= name_to_8_3(dname
, mangled_name
,
1357 true, state
->conn
->params
);
1361 fname
= mangled_name
;
1366 got_match
= exact_match(state
->has_wild
,
1367 state
->conn
->case_sensitive
,
1369 state
->got_exact_match
= got_match
;
1371 got_match
= mask_match(fname
, mask
,
1372 state
->conn
->case_sensitive
);
1375 if(!got_match
&& state
->check_mangled_names
&&
1376 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1378 * It turns out that NT matches wildcards against
1379 * both long *and* short names. This may explain some
1380 * of the wildcard wierdness from old DOS clients
1381 * that some people have been seeing.... JRA.
1383 /* Force the mangling into 8.3. */
1384 ok
= name_to_8_3(fname
, mangled_name
,
1385 false, state
->conn
->params
);
1390 got_match
= exact_match(state
->has_wild
,
1391 state
->conn
->case_sensitive
,
1392 mangled_name
, mask
);
1393 state
->got_exact_match
= got_match
;
1395 got_match
= mask_match(mangled_name
, mask
,
1396 state
->conn
->case_sensitive
);
1404 *_fname
= talloc_strdup(ctx
, fname
);
1405 if (*_fname
== NULL
) {
1412 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1414 struct smb_filename
*smb_fname
,
1417 struct smbd_dirptr_lanman2_state
*state
=
1418 (struct smbd_dirptr_lanman2_state
*)private_data
;
1419 bool ms_dfs_link
= false;
1422 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1423 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1424 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1425 "Couldn't lstat [%s] (%s)\n",
1426 smb_fname_str_dbg(smb_fname
),
1430 } else if (!VALID_STAT(smb_fname
->st
) &&
1431 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1432 /* Needed to show the msdfs symlinks as
1435 ms_dfs_link
= check_msdfs_link(state
->conn
,
1436 smb_fname
->base_name
,
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't stat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname
),
1448 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1450 mode
= dos_mode(state
->conn
, smb_fname
);
1457 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1458 connection_struct
*conn
,
1460 uint32_t info_level
,
1461 struct ea_list
*name_list
,
1462 bool check_mangled_names
,
1463 bool requires_resume_key
,
1466 const struct smb_filename
*smb_fname
,
1467 uint64_t space_remaining
,
1474 uint64_t *last_entry_off
)
1476 char *p
, *q
, *pdata
= *ppdata
;
1478 uint64_t file_size
= 0;
1479 uint64_t allocation_size
= 0;
1481 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1482 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1483 time_t c_date
= (time_t)0;
1485 char *last_entry_ptr
;
1490 *out_of_space
= false;
1492 ZERO_STRUCT(mdate_ts
);
1493 ZERO_STRUCT(adate_ts
);
1494 ZERO_STRUCT(create_date_ts
);
1495 ZERO_STRUCT(cdate_ts
);
1497 if (!(mode
& aDIR
)) {
1498 file_size
= get_file_size_stat(&smb_fname
->st
);
1500 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1502 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1503 adate_ts
= smb_fname
->st
.st_ex_atime
;
1504 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1505 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1507 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1508 dos_filetime_timespec(&create_date_ts
);
1509 dos_filetime_timespec(&mdate_ts
);
1510 dos_filetime_timespec(&adate_ts
);
1511 dos_filetime_timespec(&cdate_ts
);
1514 create_date
= convert_timespec_to_time_t(create_date_ts
);
1515 mdate
= convert_timespec_to_time_t(mdate_ts
);
1516 adate
= convert_timespec_to_time_t(adate_ts
);
1517 c_date
= convert_timespec_to_time_t(cdate_ts
);
1519 /* align the record */
1520 off
= PTR_DIFF(pdata
, base_data
);
1521 pad
= (off
+ (align
-1)) & ~(align
-1);
1524 /* initialize padding to 0 */
1526 memset(pdata
, 0, pad
);
1528 space_remaining
-= pad
;
1537 switch (info_level
) {
1538 case SMB_FIND_INFO_STANDARD
:
1539 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1540 if(requires_resume_key
) {
1544 srv_put_dos_date2(p
,0,create_date
);
1545 srv_put_dos_date2(p
,4,adate
);
1546 srv_put_dos_date2(p
,8,mdate
);
1547 SIVAL(p
,12,(uint32
)file_size
);
1548 SIVAL(p
,16,(uint32
)allocation_size
);
1552 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1553 p
+= ucs2_align(base_data
, p
, 0);
1555 len
= srvstr_push(base_data
, flags2
, p
,
1556 fname
, PTR_DIFF(end_data
, p
),
1558 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1560 SCVAL(nameptr
, -1, len
- 2);
1562 SCVAL(nameptr
, -1, 0);
1566 SCVAL(nameptr
, -1, len
- 1);
1568 SCVAL(nameptr
, -1, 0);
1574 case SMB_FIND_EA_SIZE
:
1575 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1576 if (requires_resume_key
) {
1580 srv_put_dos_date2(p
,0,create_date
);
1581 srv_put_dos_date2(p
,4,adate
);
1582 srv_put_dos_date2(p
,8,mdate
);
1583 SIVAL(p
,12,(uint32
)file_size
);
1584 SIVAL(p
,16,(uint32
)allocation_size
);
1587 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1588 smb_fname
->base_name
);
1589 SIVAL(p
,22,ea_size
); /* Extended attributes */
1593 len
= srvstr_push(base_data
, flags2
,
1594 p
, fname
, PTR_DIFF(end_data
, p
),
1595 STR_TERMINATE
| STR_NOALIGN
);
1596 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1609 SCVAL(nameptr
,0,len
);
1611 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1614 case SMB_FIND_EA_LIST
:
1616 struct ea_list
*file_list
= NULL
;
1619 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1623 if (requires_resume_key
) {
1627 srv_put_dos_date2(p
,0,create_date
);
1628 srv_put_dos_date2(p
,4,adate
);
1629 srv_put_dos_date2(p
,8,mdate
);
1630 SIVAL(p
,12,(uint32
)file_size
);
1631 SIVAL(p
,16,(uint32
)allocation_size
);
1633 p
+= 22; /* p now points to the EA area. */
1635 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1636 smb_fname
->base_name
,
1638 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1640 /* We need to determine if this entry will fit in the space available. */
1641 /* Max string size is 255 bytes. */
1642 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1643 *out_of_space
= true;
1644 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1645 return False
; /* Not finished - just out of space */
1648 /* Push the ea_data followed by the name. */
1649 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1651 len
= srvstr_push(base_data
, flags2
,
1652 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1653 STR_TERMINATE
| STR_NOALIGN
);
1654 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1667 SCVAL(nameptr
,0,len
);
1669 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1675 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1677 SIVAL(p
,0,reskey
); p
+= 4;
1678 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1679 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1680 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1681 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1682 SOFF_T(p
,0,file_size
); p
+= 8;
1683 SOFF_T(p
,0,allocation_size
); p
+= 8;
1684 SIVAL(p
,0,mode
); p
+= 4;
1685 q
= p
; p
+= 4; /* q is placeholder for name length. */
1687 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1688 smb_fname
->base_name
);
1689 SIVAL(p
,0,ea_size
); /* Extended attributes */
1692 /* Clear the short name buffer. This is
1693 * IMPORTANT as not doing so will trigger
1694 * a Win2k client bug. JRA.
1696 if (!was_8_3
&& check_mangled_names
) {
1697 char mangled_name
[13]; /* mangled 8.3 name. */
1698 if (!name_to_8_3(fname
,mangled_name
,True
,
1700 /* Error - mangle failed ! */
1701 memset(mangled_name
,'\0',12);
1703 mangled_name
[12] = 0;
1704 len
= srvstr_push(base_data
, flags2
,
1705 p
+2, mangled_name
, 24,
1706 STR_UPPER
|STR_UNICODE
);
1708 memset(p
+ 2 + len
,'\0',24 - len
);
1715 len
= srvstr_push(base_data
, flags2
, p
,
1716 fname
, PTR_DIFF(end_data
, p
),
1717 STR_TERMINATE_ASCII
);
1721 len
= PTR_DIFF(p
, pdata
);
1722 pad
= (len
+ (align
-1)) & ~(align
-1);
1724 * offset to the next entry, the caller
1725 * will overwrite it for the last entry
1726 * that's why we always include the padding
1730 * set padding to zero
1733 memset(p
, 0, pad
- len
);
1740 case SMB_FIND_FILE_DIRECTORY_INFO
:
1741 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1743 SIVAL(p
,0,reskey
); p
+= 4;
1744 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1745 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1746 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1747 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1748 SOFF_T(p
,0,file_size
); p
+= 8;
1749 SOFF_T(p
,0,allocation_size
); p
+= 8;
1750 SIVAL(p
,0,mode
); p
+= 4;
1751 len
= srvstr_push(base_data
, flags2
,
1752 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1753 STR_TERMINATE_ASCII
);
1757 len
= PTR_DIFF(p
, pdata
);
1758 pad
= (len
+ (align
-1)) & ~(align
-1);
1760 * offset to the next entry, the caller
1761 * will overwrite it for the last entry
1762 * that's why we always include the padding
1766 * set padding to zero
1769 memset(p
, 0, pad
- len
);
1776 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1777 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1779 SIVAL(p
,0,reskey
); p
+= 4;
1780 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1781 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1782 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1783 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1784 SOFF_T(p
,0,file_size
); p
+= 8;
1785 SOFF_T(p
,0,allocation_size
); p
+= 8;
1786 SIVAL(p
,0,mode
); p
+= 4;
1787 q
= p
; p
+= 4; /* q is placeholder for name length. */
1789 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1790 smb_fname
->base_name
);
1791 SIVAL(p
,0,ea_size
); /* Extended attributes */
1794 len
= srvstr_push(base_data
, flags2
, p
,
1795 fname
, PTR_DIFF(end_data
, p
),
1796 STR_TERMINATE_ASCII
);
1800 len
= PTR_DIFF(p
, pdata
);
1801 pad
= (len
+ (align
-1)) & ~(align
-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1809 * set padding to zero
1812 memset(p
, 0, pad
- len
);
1819 case SMB_FIND_FILE_NAMES_INFO
:
1820 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1822 SIVAL(p
,0,reskey
); p
+= 4;
1824 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1825 acl on a dir (tridge) */
1826 len
= srvstr_push(base_data
, flags2
, p
,
1827 fname
, PTR_DIFF(end_data
, p
),
1828 STR_TERMINATE_ASCII
);
1832 len
= PTR_DIFF(p
, pdata
);
1833 pad
= (len
+ (align
-1)) & ~(align
-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1841 * set padding to zero
1844 memset(p
, 0, pad
- len
);
1851 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1852 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1854 SIVAL(p
,0,reskey
); p
+= 4;
1855 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1856 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1857 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1858 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1859 SOFF_T(p
,0,file_size
); p
+= 8;
1860 SOFF_T(p
,0,allocation_size
); p
+= 8;
1861 SIVAL(p
,0,mode
); p
+= 4;
1862 q
= p
; p
+= 4; /* q is placeholder for name length. */
1864 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1865 smb_fname
->base_name
);
1866 SIVAL(p
,0,ea_size
); /* Extended attributes */
1869 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1870 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1871 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1872 len
= srvstr_push(base_data
, flags2
, p
,
1873 fname
, PTR_DIFF(end_data
, p
),
1874 STR_TERMINATE_ASCII
);
1878 len
= PTR_DIFF(p
, pdata
);
1879 pad
= (len
+ (align
-1)) & ~(align
-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1887 * set padding to zero
1890 memset(p
, 0, pad
- len
);
1897 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1899 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1901 SIVAL(p
,0,reskey
); p
+= 4;
1902 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1903 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1904 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1905 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1906 SOFF_T(p
,0,file_size
); p
+= 8;
1907 SOFF_T(p
,0,allocation_size
); p
+= 8;
1908 SIVAL(p
,0,mode
); p
+= 4;
1909 q
= p
; p
+= 4; /* q is placeholder for name length */
1911 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1912 smb_fname
->base_name
);
1913 SIVAL(p
,0,ea_size
); /* Extended attributes */
1916 /* Clear the short name buffer. This is
1917 * IMPORTANT as not doing so will trigger
1918 * a Win2k client bug. JRA.
1920 if (!was_8_3
&& check_mangled_names
) {
1921 char mangled_name
[13]; /* mangled 8.3 name. */
1922 if (!name_to_8_3(fname
,mangled_name
,True
,
1924 /* Error - mangle failed ! */
1925 memset(mangled_name
,'\0',12);
1927 mangled_name
[12] = 0;
1928 len
= srvstr_push(base_data
, flags2
,
1929 p
+2, mangled_name
, 24,
1930 STR_UPPER
|STR_UNICODE
);
1933 memset(p
+ 2 + len
,'\0',24 - len
);
1940 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1941 SIVAL(p
,0,smb_fname
->st
.st_ex_ino
); p
+= 4; /* FileIndexLow */
1942 SIVAL(p
,0,smb_fname
->st
.st_ex_dev
); p
+= 4; /* FileIndexHigh */
1943 len
= srvstr_push(base_data
, flags2
, p
,
1944 fname
, PTR_DIFF(end_data
, p
),
1945 STR_TERMINATE_ASCII
);
1949 len
= PTR_DIFF(p
, pdata
);
1950 pad
= (len
+ (align
-1)) & ~(align
-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1958 * set padding to zero
1961 memset(p
, 0, pad
- len
);
1968 /* CIFS UNIX Extension. */
1970 case SMB_FIND_FILE_UNIX
:
1971 case SMB_FIND_FILE_UNIX_INFO2
:
1973 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1975 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (info_level
== SMB_FIND_FILE_UNIX
) {
1978 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1979 p
= store_file_unix_basic(conn
, p
,
1980 NULL
, &smb_fname
->st
);
1981 len
= srvstr_push(base_data
, flags2
, p
,
1982 fname
, PTR_DIFF(end_data
, p
),
1985 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1986 p
= store_file_unix_basic_info2(conn
, p
,
1987 NULL
, &smb_fname
->st
);
1990 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1991 PTR_DIFF(end_data
, p
), 0);
1992 SIVAL(nameptr
, 0, len
);
1997 len
= PTR_DIFF(p
, pdata
);
1998 pad
= (len
+ (align
-1)) & ~(align
-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2006 * set padding to zero
2009 memset(p
, 0, pad
- len
);
2014 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2022 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2023 *out_of_space
= true;
2024 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2025 return false; /* Not finished - just out of space */
2028 /* Setup the last entry pointer, as an offset from base_data */
2029 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2030 /* Advance the data pointer to the next slot */
2036 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2037 connection_struct
*conn
,
2038 struct dptr_struct
*dirptr
,
2040 const char *path_mask
,
2043 int requires_resume_key
,
2051 int space_remaining
,
2053 bool *got_exact_match
,
2054 int *_last_entry_off
,
2055 struct ea_list
*name_list
)
2058 const char *mask
= NULL
;
2059 long prev_dirpos
= 0;
2062 struct smb_filename
*smb_fname
= NULL
;
2063 struct smbd_dirptr_lanman2_state state
;
2065 uint64_t last_entry_off
= 0;
2069 state
.info_level
= info_level
;
2070 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2071 state
.has_wild
= dptr_has_wild(dirptr
);
2072 state
.got_exact_match
= false;
2074 *out_of_space
= false;
2075 *got_exact_match
= false;
2077 p
= strrchr_m(path_mask
,'/');
2088 ok
= smbd_dirptr_get_entry(ctx
,
2094 smbd_dirptr_lanman2_match_fn
,
2095 smbd_dirptr_lanman2_mode_fn
,
2105 *got_exact_match
= state
.got_exact_match
;
2107 ok
= smbd_marshall_dir_entry(ctx
,
2112 state
.check_mangled_names
,
2113 requires_resume_key
,
2126 TALLOC_FREE(smb_fname
);
2127 if (*out_of_space
) {
2128 dptr_SeekDir(dirptr
, prev_dirpos
);
2135 *_last_entry_off
= last_entry_off
;
2139 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2140 connection_struct
*conn
,
2141 struct dptr_struct
*dirptr
,
2143 const char *path_mask
,
2146 bool requires_resume_key
,
2152 int space_remaining
,
2154 bool *got_exact_match
,
2155 int *last_entry_off
,
2156 struct ea_list
*name_list
)
2159 const bool do_pad
= true;
2161 if (info_level
>= 1 && info_level
<= 3) {
2162 /* No alignment on earlier info levels. */
2166 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2167 path_mask
, dirtype
, info_level
,
2168 requires_resume_key
, dont_descend
, ask_sharemode
,
2170 ppdata
, base_data
, end_data
,
2172 out_of_space
, got_exact_match
,
2173 last_entry_off
, name_list
);
2176 /****************************************************************************
2177 Reply to a TRANS2_FINDFIRST.
2178 ****************************************************************************/
2180 static void call_trans2findfirst(connection_struct
*conn
,
2181 struct smb_request
*req
,
2182 char **pparams
, int total_params
,
2183 char **ppdata
, int total_data
,
2184 unsigned int max_data_bytes
)
2186 /* We must be careful here that we don't return more than the
2187 allowed number of data bytes. If this means returning fewer than
2188 maxentries then so be it. We assume that the redirector has
2189 enough room for the fixed number of parameter bytes it has
2191 struct smb_filename
*smb_dname
= NULL
;
2192 char *params
= *pparams
;
2193 char *pdata
= *ppdata
;
2197 uint16 findfirst_flags
;
2198 bool close_after_first
;
2200 bool requires_resume_key
;
2202 char *directory
= NULL
;
2205 int last_entry_off
=0;
2209 bool finished
= False
;
2210 bool dont_descend
= False
;
2211 bool out_of_space
= False
;
2212 int space_remaining
;
2213 bool mask_contains_wcard
= False
;
2214 struct ea_list
*ea_list
= NULL
;
2215 NTSTATUS ntstatus
= NT_STATUS_OK
;
2216 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2217 TALLOC_CTX
*ctx
= talloc_tos();
2218 struct dptr_struct
*dirptr
= NULL
;
2219 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2221 if (total_params
< 13) {
2222 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2226 dirtype
= SVAL(params
,0);
2227 maxentries
= SVAL(params
,2);
2228 findfirst_flags
= SVAL(params
,4);
2229 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2230 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2231 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2232 info_level
= SVAL(params
,6);
2234 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2235 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2236 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2237 info_level
, max_data_bytes
));
2240 /* W2K3 seems to treat zero as 1. */
2244 switch (info_level
) {
2245 case SMB_FIND_INFO_STANDARD
:
2246 case SMB_FIND_EA_SIZE
:
2247 case SMB_FIND_EA_LIST
:
2248 case SMB_FIND_FILE_DIRECTORY_INFO
:
2249 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2250 case SMB_FIND_FILE_NAMES_INFO
:
2251 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2253 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2255 case SMB_FIND_FILE_UNIX
:
2256 case SMB_FIND_FILE_UNIX_INFO2
:
2257 /* Always use filesystem for UNIX mtime query. */
2258 ask_sharemode
= false;
2259 if (!lp_unix_extensions()) {
2260 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2265 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2269 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2270 params
+12, total_params
- 12,
2271 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2272 if (!NT_STATUS_IS_OK(ntstatus
)) {
2273 reply_nterror(req
, ntstatus
);
2277 ntstatus
= filename_convert(ctx
, conn
,
2278 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2281 UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
2282 &mask_contains_wcard
,
2284 if (!NT_STATUS_IS_OK(ntstatus
)) {
2285 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2286 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2287 ERRSRV
, ERRbadpath
);
2290 reply_nterror(req
, ntstatus
);
2294 mask
= smb_dname
->original_lcomp
;
2296 directory
= smb_dname
->base_name
;
2298 p
= strrchr_m(directory
,'/');
2300 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2301 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2302 mask
= talloc_strdup(ctx
,"*");
2304 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2307 mask_contains_wcard
= True
;
2309 directory
= talloc_strdup(talloc_tos(), "./");
2311 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2318 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2320 if (info_level
== SMB_FIND_EA_LIST
) {
2323 if (total_data
< 4) {
2324 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2328 ea_size
= IVAL(pdata
,0);
2329 if (ea_size
!= total_data
) {
2330 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2336 if (!lp_ea_support(SNUM(conn
))) {
2337 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2341 /* Pull out the list of names. */
2342 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2344 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2349 *ppdata
= (char *)SMB_REALLOC(
2350 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2351 if(*ppdata
== NULL
) {
2352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2356 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2358 /* Realloc the params space */
2359 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2360 if (*pparams
== NULL
) {
2361 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2366 /* Save the wildcard match and attribs we are using on this directory -
2367 needed as lanman2 assumes these are being saved between calls */
2369 ntstatus
= dptr_create(conn
,
2375 mask_contains_wcard
,
2379 if (!NT_STATUS_IS_OK(ntstatus
)) {
2380 reply_nterror(req
, ntstatus
);
2384 dptr_num
= dptr_dnum(dirptr
);
2385 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2387 /* Initialize per TRANS2_FIND_FIRST operation data */
2388 dptr_init_search_op(dirptr
);
2390 /* We don't need to check for VOL here as this is returned by
2391 a different TRANS2 call. */
2393 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2394 directory
,lp_dontdescend(SNUM(conn
))));
2395 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2396 dont_descend
= True
;
2399 space_remaining
= max_data_bytes
;
2400 out_of_space
= False
;
2402 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2403 bool got_exact_match
= False
;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2408 out_of_space
= True
;
2411 finished
= !get_lanman2_dir_entry(ctx
,
2415 mask
,dirtype
,info_level
,
2416 requires_resume_key
,dont_descend
,
2419 space_remaining
, &out_of_space
,
2421 &last_entry_off
, ea_list
);
2424 if (finished
&& out_of_space
)
2427 if (!finished
&& !out_of_space
)
2431 * As an optimisation if we know we aren't looking
2432 * for a wildcard name (ie. the name matches the wildcard exactly)
2433 * then we can finish on any (first) match.
2434 * This speeds up large directory searches. JRA.
2440 /* Ensure space_remaining never goes -ve. */
2441 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2442 space_remaining
= 0;
2443 out_of_space
= true;
2445 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2449 /* Check if we can close the dirptr */
2450 if(close_after_first
|| (finished
&& close_if_end
)) {
2451 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2452 dptr_close(sconn
, &dptr_num
);
2456 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2457 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2458 * the protocol level is less than NT1. Tested with smbclient. JRA.
2459 * This should fix the OS/2 client bug #2335.
2462 if(numentries
== 0) {
2463 dptr_close(sconn
, &dptr_num
);
2464 if (get_Protocol() < PROTOCOL_NT1
) {
2465 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2468 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2469 ERRDOS
, ERRbadfile
);
2474 /* At this point pdata points to numentries directory entries. */
2476 /* Set up the return parameter block */
2477 SSVAL(params
,0,dptr_num
);
2478 SSVAL(params
,2,numentries
);
2479 SSVAL(params
,4,finished
);
2480 SSVAL(params
,6,0); /* Never an EA error */
2481 SSVAL(params
,8,last_entry_off
);
2483 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2486 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2487 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2489 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2493 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req
->cmd
),
2495 mask
, directory
, dirtype
, numentries
) );
2498 * Force a name mangle here to ensure that the
2499 * mask as an 8.3 name is top of the mangled cache.
2500 * The reasons for this are subtle. Don't remove
2501 * this code unless you know what you are doing
2502 * (see PR#13758). JRA.
2505 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2506 char mangled_name
[13];
2507 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2510 TALLOC_FREE(smb_dname
);
2514 /****************************************************************************
2515 Reply to a TRANS2_FINDNEXT.
2516 ****************************************************************************/
2518 static void call_trans2findnext(connection_struct
*conn
,
2519 struct smb_request
*req
,
2520 char **pparams
, int total_params
,
2521 char **ppdata
, int total_data
,
2522 unsigned int max_data_bytes
)
2524 /* We must be careful here that we don't return more than the
2525 allowed number of data bytes. If this means returning fewer than
2526 maxentries then so be it. We assume that the redirector has
2527 enough room for the fixed number of parameter bytes it has
2529 char *params
= *pparams
;
2530 char *pdata
= *ppdata
;
2536 uint16 findnext_flags
;
2537 bool close_after_request
;
2539 bool requires_resume_key
;
2541 bool mask_contains_wcard
= False
;
2542 char *resume_name
= NULL
;
2543 const char *mask
= NULL
;
2544 const char *directory
= NULL
;
2548 int i
, last_entry_off
=0;
2549 bool finished
= False
;
2550 bool dont_descend
= False
;
2551 bool out_of_space
= False
;
2552 int space_remaining
;
2553 struct ea_list
*ea_list
= NULL
;
2554 NTSTATUS ntstatus
= NT_STATUS_OK
;
2555 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2556 TALLOC_CTX
*ctx
= talloc_tos();
2557 struct dptr_struct
*dirptr
;
2558 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2560 if (total_params
< 13) {
2561 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2565 dptr_num
= SVAL(params
,0);
2566 maxentries
= SVAL(params
,2);
2567 info_level
= SVAL(params
,4);
2568 resume_key
= IVAL(params
,6);
2569 findnext_flags
= SVAL(params
,10);
2570 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2571 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2572 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2573 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2575 if (!continue_bit
) {
2576 /* We only need resume_name if continue_bit is zero. */
2577 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2579 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2580 &mask_contains_wcard
);
2581 if (!NT_STATUS_IS_OK(ntstatus
)) {
2582 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2583 complain (it thinks we're asking for the directory above the shared
2584 path or an invalid name). Catch this as the resume name is only compared, never used in
2585 a file access. JRA. */
2586 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2587 &resume_name
, params
+12,
2591 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2592 reply_nterror(req
, ntstatus
);
2598 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2599 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2600 resume_key = %d resume name = %s continue=%d level = %d\n",
2601 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2602 requires_resume_key
, resume_key
,
2603 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2606 /* W2K3 seems to treat zero as 1. */
2610 switch (info_level
) {
2611 case SMB_FIND_INFO_STANDARD
:
2612 case SMB_FIND_EA_SIZE
:
2613 case SMB_FIND_EA_LIST
:
2614 case SMB_FIND_FILE_DIRECTORY_INFO
:
2615 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2616 case SMB_FIND_FILE_NAMES_INFO
:
2617 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2618 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2619 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2621 case SMB_FIND_FILE_UNIX
:
2622 case SMB_FIND_FILE_UNIX_INFO2
:
2623 /* Always use filesystem for UNIX mtime query. */
2624 ask_sharemode
= false;
2625 if (!lp_unix_extensions()) {
2626 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2631 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2635 if (info_level
== SMB_FIND_EA_LIST
) {
2638 if (total_data
< 4) {
2639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2643 ea_size
= IVAL(pdata
,0);
2644 if (ea_size
!= total_data
) {
2645 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2646 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2647 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2651 if (!lp_ea_support(SNUM(conn
))) {
2652 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2656 /* Pull out the list of names. */
2657 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2664 *ppdata
= (char *)SMB_REALLOC(
2665 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2666 if(*ppdata
== NULL
) {
2667 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2672 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2674 /* Realloc the params space */
2675 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2676 if(*pparams
== NULL
) {
2677 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2683 /* Check that the dptr is valid */
2684 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2685 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2689 directory
= dptr_path(sconn
, dptr_num
);
2691 /* Get the wildcard mask from the dptr */
2692 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2693 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2694 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2700 /* Get the attr mask from the dptr */
2701 dirtype
= dptr_attr(sconn
, dptr_num
);
2703 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2704 dptr_num
, mask
, dirtype
,
2706 dptr_TellDir(dirptr
)));
2708 /* Initialize per TRANS2_FIND_NEXT operation data */
2709 dptr_init_search_op(dirptr
);
2711 /* We don't need to check for VOL here as this is returned by
2712 a different TRANS2 call. */
2714 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2715 directory
,lp_dontdescend(SNUM(conn
))));
2716 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2717 dont_descend
= True
;
2720 space_remaining
= max_data_bytes
;
2721 out_of_space
= False
;
2724 * Seek to the correct position. We no longer use the resume key but
2725 * depend on the last file name instead.
2728 if(!continue_bit
&& resume_name
&& *resume_name
) {
2731 long current_pos
= 0;
2733 * Remember, name_to_8_3 is called by
2734 * get_lanman2_dir_entry(), so the resume name
2735 * could be mangled. Ensure we check the unmangled name.
2738 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2739 char *new_resume_name
= NULL
;
2740 mangle_lookup_name_from_8_3(ctx
,
2744 if (new_resume_name
) {
2745 resume_name
= new_resume_name
;
2750 * Fix for NT redirector problem triggered by resume key indexes
2751 * changing between directory scans. We now return a resume key of 0
2752 * and instead look for the filename to continue from (also given
2753 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2754 * findfirst/findnext (as is usual) then the directory pointer
2755 * should already be at the correct place.
2758 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2759 } /* end if resume_name && !continue_bit */
2761 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2762 bool got_exact_match
= False
;
2764 /* this is a heuristic to avoid seeking the dirptr except when
2765 absolutely necessary. It allows for a filename of about 40 chars */
2766 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2767 out_of_space
= True
;
2770 finished
= !get_lanman2_dir_entry(ctx
,
2774 mask
,dirtype
,info_level
,
2775 requires_resume_key
,dont_descend
,
2778 space_remaining
, &out_of_space
,
2780 &last_entry_off
, ea_list
);
2783 if (finished
&& out_of_space
)
2786 if (!finished
&& !out_of_space
)
2790 * As an optimisation if we know we aren't looking
2791 * for a wildcard name (ie. the name matches the wildcard exactly)
2792 * then we can finish on any (first) match.
2793 * This speeds up large directory searches. JRA.
2799 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2802 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2803 smb_fn_name(req
->cmd
),
2804 mask
, directory
, dirtype
, numentries
) );
2806 /* Check if we can close the dirptr */
2807 if(close_after_request
|| (finished
&& close_if_end
)) {
2808 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2809 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2812 /* Set up the return parameter block */
2813 SSVAL(params
,0,numentries
);
2814 SSVAL(params
,2,finished
);
2815 SSVAL(params
,4,0); /* Never an EA error */
2816 SSVAL(params
,6,last_entry_off
);
2818 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2824 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2826 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2830 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2832 SMB_ASSERT(extended_info
!= NULL
);
2834 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2835 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2836 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2837 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2838 #ifdef SAMBA_VERSION_REVISION
2839 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2841 extended_info
->samba_subversion
= 0;
2842 #ifdef SAMBA_VERSION_RC_RELEASE
2843 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2845 #ifdef SAMBA_VERSION_PRE_RELEASE
2846 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2849 #ifdef SAMBA_VERSION_VENDOR_PATCH
2850 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2852 extended_info
->samba_gitcommitdate
= 0;
2853 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2854 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_GIT_COMMIT_TIME
);
2857 memset(extended_info
->samba_version_string
, 0,
2858 sizeof(extended_info
->samba_version_string
));
2860 snprintf (extended_info
->samba_version_string
,
2861 sizeof(extended_info
->samba_version_string
),
2862 "%s", samba_version_string());
2865 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2866 TALLOC_CTX
*mem_ctx
,
2867 uint16_t info_level
,
2869 unsigned int max_data_bytes
,
2873 char *pdata
, *end_data
;
2874 int data_len
= 0, len
;
2875 const char *vname
= volume_label(SNUM(conn
));
2876 int snum
= SNUM(conn
);
2877 char *fstype
= lp_fstype(SNUM(conn
));
2878 uint32 additional_flags
= 0;
2879 struct smb_filename smb_fname_dot
;
2883 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2884 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2885 "info level (0x%x) on IPC$.\n",
2886 (unsigned int)info_level
));
2887 return NT_STATUS_ACCESS_DENIED
;
2891 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2893 ZERO_STRUCT(smb_fname_dot
);
2894 smb_fname_dot
.base_name
= discard_const_p(char, ".");
2896 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
2897 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2898 return map_nt_error_from_unix(errno
);
2901 st
= smb_fname_dot
.st
;
2903 *ppdata
= (char *)SMB_REALLOC(
2904 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2905 if (*ppdata
== NULL
) {
2906 return NT_STATUS_NO_MEMORY
;
2910 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2911 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2913 switch (info_level
) {
2914 case SMB_INFO_ALLOCATION
:
2916 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2918 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
2919 return map_nt_error_from_unix(errno
);
2922 block_size
= lp_block_size(snum
);
2923 if (bsize
< block_size
) {
2924 uint64_t factor
= block_size
/bsize
;
2929 if (bsize
> block_size
) {
2930 uint64_t factor
= bsize
/block_size
;
2935 bytes_per_sector
= 512;
2936 sectors_per_unit
= bsize
/bytes_per_sector
;
2938 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2939 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2940 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2942 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2943 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2944 SIVAL(pdata
,l1_cUnit
,dsize
);
2945 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2946 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2950 case SMB_INFO_VOLUME
:
2951 /* Return volume name */
2953 * Add volume serial number - hash of a combination of
2954 * the called hostname and the service name.
2956 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2958 * Win2k3 and previous mess this up by sending a name length
2959 * one byte short. I believe only older clients (OS/2 Win9x) use
2960 * this call so try fixing this by adding a terminating null to
2961 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2965 pdata
+l2_vol_szVolLabel
, vname
,
2966 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2967 STR_NOALIGN
|STR_TERMINATE
);
2968 SCVAL(pdata
,l2_vol_cch
,len
);
2969 data_len
= l2_vol_szVolLabel
+ len
;
2970 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2971 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2975 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2976 case SMB_FS_ATTRIBUTE_INFORMATION
:
2978 additional_flags
= 0;
2979 #if defined(HAVE_SYS_QUOTAS)
2980 additional_flags
|= FILE_VOLUME_QUOTAS
;
2983 if(lp_nt_acl_support(SNUM(conn
))) {
2984 additional_flags
|= FILE_PERSISTENT_ACLS
;
2987 /* Capabilities are filled in at connection time through STATVFS call */
2988 additional_flags
|= conn
->fs_capabilities
;
2989 additional_flags
|= lp_parm_int(conn
->params
->service
,
2990 "share", "fake_fscaps",
2993 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2994 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2995 additional_flags
); /* FS ATTRIBUTES */
2997 SIVAL(pdata
,4,255); /* Max filename component length */
2998 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2999 and will think we can't do long filenames */
3000 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3001 PTR_DIFF(end_data
, pdata
+12),
3004 data_len
= 12 + len
;
3007 case SMB_QUERY_FS_LABEL_INFO
:
3008 case SMB_FS_LABEL_INFORMATION
:
3009 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3010 PTR_DIFF(end_data
, pdata
+4), 0);
3015 case SMB_QUERY_FS_VOLUME_INFO
:
3016 case SMB_FS_VOLUME_INFORMATION
:
3019 * Add volume serial number - hash of a combination of
3020 * the called hostname and the service name.
3022 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3023 (str_checksum(get_local_machine_name())<<16));
3025 /* Max label len is 32 characters. */
3026 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3027 PTR_DIFF(end_data
, pdata
+18),
3029 SIVAL(pdata
,12,len
);
3032 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3033 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3036 case SMB_QUERY_FS_SIZE_INFO
:
3037 case SMB_FS_SIZE_INFORMATION
:
3039 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3041 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3042 return map_nt_error_from_unix(errno
);
3044 block_size
= lp_block_size(snum
);
3045 if (bsize
< block_size
) {
3046 uint64_t factor
= block_size
/bsize
;
3051 if (bsize
> block_size
) {
3052 uint64_t factor
= bsize
/block_size
;
3057 bytes_per_sector
= 512;
3058 sectors_per_unit
= bsize
/bytes_per_sector
;
3059 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3060 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3061 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3062 SBIG_UINT(pdata
,0,dsize
);
3063 SBIG_UINT(pdata
,8,dfree
);
3064 SIVAL(pdata
,16,sectors_per_unit
);
3065 SIVAL(pdata
,20,bytes_per_sector
);
3069 case SMB_FS_FULL_SIZE_INFORMATION
:
3071 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3073 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3074 return map_nt_error_from_unix(errno
);
3076 block_size
= lp_block_size(snum
);
3077 if (bsize
< block_size
) {
3078 uint64_t factor
= block_size
/bsize
;
3083 if (bsize
> block_size
) {
3084 uint64_t factor
= bsize
/block_size
;
3089 bytes_per_sector
= 512;
3090 sectors_per_unit
= bsize
/bytes_per_sector
;
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3092 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3093 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3094 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3095 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3096 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3097 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3098 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3102 case SMB_QUERY_FS_DEVICE_INFO
:
3103 case SMB_FS_DEVICE_INFORMATION
:
3105 SIVAL(pdata
,0,0); /* dev type */
3106 SIVAL(pdata
,4,0); /* characteristics */
3109 #ifdef HAVE_SYS_QUOTAS
3110 case SMB_FS_QUOTA_INFORMATION
:
3112 * what we have to send --metze:
3114 * Unknown1: 24 NULL bytes
3115 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3116 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3117 * Quota Flags: 2 byte :
3118 * Unknown3: 6 NULL bytes
3122 * details for Quota Flags:
3124 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3125 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3126 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3127 * 0x0001 Enable Quotas: enable quota for this fs
3131 /* we need to fake up a fsp here,
3132 * because its not send in this call
3135 SMB_NTQUOTA_STRUCT quotas
;
3138 ZERO_STRUCT(quotas
);
3144 if (conn
->server_info
->utok
.uid
!= sec_initial_uid()) {
3145 DEBUG(0,("set_user_quota: access_denied "
3146 "service [%s] user [%s]\n",
3147 lp_servicename(SNUM(conn
)),
3148 conn
->server_info
->unix_name
));
3149 return NT_STATUS_ACCESS_DENIED
;
3152 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3153 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3154 return map_nt_error_from_unix(errno
);
3159 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3160 lp_servicename(SNUM(conn
))));
3162 /* Unknown1 24 NULL bytes*/
3163 SBIG_UINT(pdata
,0,(uint64_t)0);
3164 SBIG_UINT(pdata
,8,(uint64_t)0);
3165 SBIG_UINT(pdata
,16,(uint64_t)0);
3167 /* Default Soft Quota 8 bytes */
3168 SBIG_UINT(pdata
,24,quotas
.softlim
);
3170 /* Default Hard Quota 8 bytes */
3171 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3173 /* Quota flag 2 bytes */
3174 SSVAL(pdata
,40,quotas
.qflags
);
3176 /* Unknown3 6 NULL bytes */
3182 #endif /* HAVE_SYS_QUOTAS */
3183 case SMB_FS_OBJECTID_INFORMATION
:
3185 unsigned char objid
[16];
3186 struct smb_extended_info extended_info
;
3187 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3188 samba_extended_info_version (&extended_info
);
3189 SIVAL(pdata
,16,extended_info
.samba_magic
);
3190 SIVAL(pdata
,20,extended_info
.samba_version
);
3191 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3192 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3193 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3199 * Query the version and capabilities of the CIFS UNIX extensions
3203 case SMB_QUERY_CIFS_UNIX_INFO
:
3205 bool large_write
= lp_min_receive_file_size() &&
3206 !srv_is_signing_active(smbd_server_conn
);
3207 bool large_read
= !srv_is_signing_active(smbd_server_conn
);
3208 int encrypt_caps
= 0;
3210 if (!lp_unix_extensions()) {
3211 return NT_STATUS_INVALID_LEVEL
;
3214 switch (conn
->encrypt_level
) {
3220 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3223 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3224 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3225 large_write
= false;
3231 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3232 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3234 /* We have POSIX ACLs, pathname, encryption,
3235 * large read/write, and locking capability. */
3237 SBIG_UINT(pdata
,4,((uint64_t)(
3238 CIFS_UNIX_POSIX_ACLS_CAP
|
3239 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3240 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3241 CIFS_UNIX_EXTATTR_CAP
|
3242 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3244 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3246 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3250 case SMB_QUERY_POSIX_FS_INFO
:
3253 vfs_statvfs_struct svfs
;
3255 if (!lp_unix_extensions()) {
3256 return NT_STATUS_INVALID_LEVEL
;
3259 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3263 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3264 SIVAL(pdata
,4,svfs
.BlockSize
);
3265 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3266 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3267 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3268 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3269 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3270 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3271 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3273 } else if (rc
== EOPNOTSUPP
) {
3274 return NT_STATUS_INVALID_LEVEL
;
3275 #endif /* EOPNOTSUPP */
3277 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3278 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3283 case SMB_QUERY_POSIX_WHOAMI
:
3289 if (!lp_unix_extensions()) {
3290 return NT_STATUS_INVALID_LEVEL
;
3293 if (max_data_bytes
< 40) {
3294 return NT_STATUS_BUFFER_TOO_SMALL
;
3297 /* We ARE guest if global_sid_Builtin_Guests is
3298 * in our list of SIDs.
3300 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3301 conn
->server_info
->ptok
)) {
3302 flags
|= SMB_WHOAMI_GUEST
;
3305 /* We are NOT guest if global_sid_Authenticated_Users
3306 * is in our list of SIDs.
3308 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3309 conn
->server_info
->ptok
)) {
3310 flags
&= ~SMB_WHOAMI_GUEST
;
3313 /* NOTE: 8 bytes for UID/GID, irrespective of native
3314 * platform size. This matches
3315 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3317 data_len
= 4 /* flags */
3324 + 4 /* pad/reserved */
3325 + (conn
->server_info
->utok
.ngroups
* 8)
3327 + (conn
->server_info
->ptok
->num_sids
*
3331 SIVAL(pdata
, 0, flags
);
3332 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3334 (uint64_t)conn
->server_info
->utok
.uid
);
3335 SBIG_UINT(pdata
, 16,
3336 (uint64_t)conn
->server_info
->utok
.gid
);
3339 if (data_len
>= max_data_bytes
) {
3340 /* Potential overflow, skip the GIDs and SIDs. */
3342 SIVAL(pdata
, 24, 0); /* num_groups */
3343 SIVAL(pdata
, 28, 0); /* num_sids */
3344 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3345 SIVAL(pdata
, 36, 0); /* reserved */
3351 SIVAL(pdata
, 24, conn
->server_info
->utok
.ngroups
);
3352 SIVAL(pdata
, 28, conn
->server_info
->num_sids
);
3354 /* We walk the SID list twice, but this call is fairly
3355 * infrequent, and I don't expect that it's performance
3356 * sensitive -- jpeach
3358 for (i
= 0, sid_bytes
= 0;
3359 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3360 sid_bytes
+= ndr_size_dom_sid(
3361 &conn
->server_info
->ptok
->user_sids
[i
],
3366 /* SID list byte count */
3367 SIVAL(pdata
, 32, sid_bytes
);
3369 /* 4 bytes pad/reserved - must be zero */
3370 SIVAL(pdata
, 36, 0);
3374 for (i
= 0; i
< conn
->server_info
->utok
.ngroups
; ++i
) {
3375 SBIG_UINT(pdata
, data_len
,
3376 (uint64_t)conn
->server_info
->utok
.groups
[i
]);
3382 i
< conn
->server_info
->ptok
->num_sids
; ++i
) {
3383 int sid_len
= ndr_size_dom_sid(
3384 &conn
->server_info
->ptok
->user_sids
[i
],
3388 sid_linearize(pdata
+ data_len
, sid_len
,
3389 &conn
->server_info
->ptok
->user_sids
[i
]);
3390 data_len
+= sid_len
;
3396 case SMB_MAC_QUERY_FS_INFO
:
3398 * Thursby MAC extension... ONLY on NTFS filesystems
3399 * once we do streams then we don't need this
3401 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3403 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3408 return NT_STATUS_INVALID_LEVEL
;
3411 *ret_data_len
= data_len
;
3412 return NT_STATUS_OK
;
3415 /****************************************************************************
3416 Reply to a TRANS2_QFSINFO (query filesystem info).
3417 ****************************************************************************/
3419 static void call_trans2qfsinfo(connection_struct
*conn
,
3420 struct smb_request
*req
,
3421 char **pparams
, int total_params
,
3422 char **ppdata
, int total_data
,
3423 unsigned int max_data_bytes
)
3425 char *params
= *pparams
;
3426 uint16_t info_level
;
3430 if (total_params
< 2) {
3431 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3435 info_level
= SVAL(params
,0);
3437 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3438 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3439 DEBUG(0,("call_trans2qfsinfo: encryption required "
3440 "and info level 0x%x sent.\n",
3441 (unsigned int)info_level
));
3442 exit_server_cleanly("encryption required "
3448 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3450 status
= smbd_do_qfsinfo(conn
, req
,
3455 if (!NT_STATUS_IS_OK(status
)) {
3456 reply_nterror(req
, status
);
3460 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3463 DEBUG( 4, ( "%s info_level = %d\n",
3464 smb_fn_name(req
->cmd
), info_level
) );
3469 /****************************************************************************
3470 Reply to a TRANS2_SETFSINFO (set filesystem info).
3471 ****************************************************************************/
3473 static void call_trans2setfsinfo(connection_struct
*conn
,
3474 struct smb_request
*req
,
3475 char **pparams
, int total_params
,
3476 char **ppdata
, int total_data
,
3477 unsigned int max_data_bytes
)
3479 char *pdata
= *ppdata
;
3480 char *params
= *pparams
;
3483 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3486 if (total_params
< 4) {
3487 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3493 info_level
= SVAL(params
,2);
3496 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3497 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3498 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3499 "info level (0x%x) on IPC$.\n",
3500 (unsigned int)info_level
));
3501 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3506 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3507 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3508 DEBUG(0,("call_trans2setfsinfo: encryption required "
3509 "and info level 0x%x sent.\n",
3510 (unsigned int)info_level
));
3511 exit_server_cleanly("encryption required "
3517 switch(info_level
) {
3518 case SMB_SET_CIFS_UNIX_INFO
:
3520 uint16 client_unix_major
;
3521 uint16 client_unix_minor
;
3522 uint32 client_unix_cap_low
;
3523 uint32 client_unix_cap_high
;
3525 if (!lp_unix_extensions()) {
3527 NT_STATUS_INVALID_LEVEL
);
3531 /* There should be 12 bytes of capabilities set. */
3532 if (total_data
< 8) {
3535 NT_STATUS_INVALID_PARAMETER
);
3538 client_unix_major
= SVAL(pdata
,0);
3539 client_unix_minor
= SVAL(pdata
,2);
3540 client_unix_cap_low
= IVAL(pdata
,4);
3541 client_unix_cap_high
= IVAL(pdata
,8);
3542 /* Just print these values for now. */
3543 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3544 cap_low = 0x%x, cap_high = 0x%x\n",
3545 (unsigned int)client_unix_major
,
3546 (unsigned int)client_unix_minor
,
3547 (unsigned int)client_unix_cap_low
,
3548 (unsigned int)client_unix_cap_high
));
3550 /* Here is where we must switch to posix pathname processing... */
3551 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3552 lp_set_posix_pathnames();
3553 mangle_change_to_posix();
3556 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3557 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3558 /* Client that knows how to do posix locks,
3559 * but not posix open/mkdir operations. Set a
3560 * default type for read/write checks. */
3562 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3568 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3571 size_t param_len
= 0;
3572 size_t data_len
= total_data
;
3574 if (!lp_unix_extensions()) {
3577 NT_STATUS_INVALID_LEVEL
);
3581 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3584 NT_STATUS_NOT_SUPPORTED
);
3588 DEBUG( 4,("call_trans2setfsinfo: "
3589 "request transport encryption.\n"));
3591 status
= srv_request_encryption_setup(conn
,
3592 (unsigned char **)ppdata
,
3594 (unsigned char **)pparams
,
3597 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3598 !NT_STATUS_IS_OK(status
)) {
3599 reply_nterror(req
, status
);
3603 send_trans2_replies(conn
, req
,
3610 if (NT_STATUS_IS_OK(status
)) {
3611 /* Server-side transport
3612 * encryption is now *on*. */
3613 status
= srv_encryption_start(conn
);
3614 if (!NT_STATUS_IS_OK(status
)) {
3615 exit_server_cleanly(
3616 "Failure in setting "
3617 "up encrypted transport");
3623 case SMB_FS_QUOTA_INFORMATION
:
3625 files_struct
*fsp
= NULL
;
3626 SMB_NTQUOTA_STRUCT quotas
;
3628 ZERO_STRUCT(quotas
);
3631 if ((conn
->server_info
->utok
.uid
!= sec_initial_uid())
3632 ||!CAN_WRITE(conn
)) {
3633 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3634 lp_servicename(SNUM(conn
)),
3635 conn
->server_info
->unix_name
));
3636 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3640 /* note: normaly there're 48 bytes,
3641 * but we didn't use the last 6 bytes for now
3644 fsp
= file_fsp(req
, SVAL(params
,0));
3646 if (!check_fsp_ntquota_handle(conn
, req
,
3648 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3650 req
, NT_STATUS_INVALID_HANDLE
);
3654 if (total_data
< 42) {
3655 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3659 NT_STATUS_INVALID_PARAMETER
);
3663 /* unknown_1 24 NULL bytes in pdata*/
3665 /* the soft quotas 8 bytes (uint64_t)*/
3666 quotas
.softlim
= (uint64_t)IVAL(pdata
,24);
3667 #ifdef LARGE_SMB_OFF_T
3668 quotas
.softlim
|= (((uint64_t)IVAL(pdata
,28)) << 32);
3669 #else /* LARGE_SMB_OFF_T */
3670 if ((IVAL(pdata
,28) != 0)&&
3671 ((quotas
.softlim
!= 0xFFFFFFFF)||
3672 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3673 /* more than 32 bits? */
3676 NT_STATUS_INVALID_PARAMETER
);
3679 #endif /* LARGE_SMB_OFF_T */
3681 /* the hard quotas 8 bytes (uint64_t)*/
3682 quotas
.hardlim
= (uint64_t)IVAL(pdata
,32);
3683 #ifdef LARGE_SMB_OFF_T
3684 quotas
.hardlim
|= (((uint64_t)IVAL(pdata
,36)) << 32);
3685 #else /* LARGE_SMB_OFF_T */
3686 if ((IVAL(pdata
,36) != 0)&&
3687 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3688 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3689 /* more than 32 bits? */
3692 NT_STATUS_INVALID_PARAMETER
);
3695 #endif /* LARGE_SMB_OFF_T */
3697 /* quota_flags 2 bytes **/
3698 quotas
.qflags
= SVAL(pdata
,40);
3700 /* unknown_2 6 NULL bytes follow*/
3702 /* now set the quotas */
3703 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3704 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3705 reply_nterror(req
, map_nt_error_from_unix(errno
));
3712 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3714 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3720 * sending this reply works fine,
3721 * but I'm not sure it's the same
3722 * like windows do...
3725 reply_outbuf(req
, 10, 0);
3728 #if defined(HAVE_POSIX_ACLS)
3729 /****************************************************************************
3730 Utility function to count the number of entries in a POSIX acl.
3731 ****************************************************************************/
3733 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3735 unsigned int ace_count
= 0;
3736 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3737 SMB_ACL_ENTRY_T entry
;
3739 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3741 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3742 entry_id
= SMB_ACL_NEXT_ENTRY
;
3749 /****************************************************************************
3750 Utility function to marshall a POSIX acl into wire format.
3751 ****************************************************************************/
3753 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3755 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3756 SMB_ACL_ENTRY_T entry
;
3758 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3759 SMB_ACL_TAG_T tagtype
;
3760 SMB_ACL_PERMSET_T permset
;
3761 unsigned char perms
= 0;
3762 unsigned int own_grp
;
3765 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3766 entry_id
= SMB_ACL_NEXT_ENTRY
;
3769 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3770 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3774 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3775 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3779 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3780 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3781 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3783 SCVAL(pdata
,1,perms
);
3786 case SMB_ACL_USER_OBJ
:
3787 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3788 own_grp
= (unsigned int)pst
->st_ex_uid
;
3789 SIVAL(pdata
,2,own_grp
);
3794 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3796 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3799 own_grp
= (unsigned int)*puid
;
3800 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3801 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3802 SIVAL(pdata
,2,own_grp
);
3806 case SMB_ACL_GROUP_OBJ
:
3807 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3808 own_grp
= (unsigned int)pst
->st_ex_gid
;
3809 SIVAL(pdata
,2,own_grp
);
3814 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3816 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3819 own_grp
= (unsigned int)*pgid
;
3820 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3821 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3822 SIVAL(pdata
,2,own_grp
);
3827 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3828 SIVAL(pdata
,2,0xFFFFFFFF);
3829 SIVAL(pdata
,6,0xFFFFFFFF);
3832 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3833 SIVAL(pdata
,2,0xFFFFFFFF);
3834 SIVAL(pdata
,6,0xFFFFFFFF);
3837 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3840 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3847 /****************************************************************************
3848 Store the FILE_UNIX_BASIC info.
3849 ****************************************************************************/
3851 static char *store_file_unix_basic(connection_struct
*conn
,
3854 const SMB_STRUCT_STAT
*psbuf
)
3856 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3857 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3859 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3862 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3865 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3866 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3867 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3870 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3874 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3878 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3881 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
3885 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
3889 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ex_ino
); /* inode number */
3892 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3896 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3903 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3904 * the chflags(2) (or equivalent) flags.
3906 * XXX: this really should be behind the VFS interface. To do this, we would
3907 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3908 * Each VFS module could then implement its own mapping as appropriate for the
3909 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3911 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3915 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3919 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3923 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3927 { UF_HIDDEN
, EXT_HIDDEN
},
3930 /* Do not remove. We need to guarantee that this array has at least one
3931 * entry to build on HP-UX.
3937 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3938 uint32
*smb_fflags
, uint32
*smb_fmask
)
3942 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3943 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3944 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3945 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3950 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3951 const uint32 smb_fflags
,
3952 const uint32 smb_fmask
,
3955 uint32 max_fmask
= 0;
3958 *stat_fflags
= psbuf
->st_ex_flags
;
3960 /* For each flags requested in smb_fmask, check the state of the
3961 * corresponding flag in smb_fflags and set or clear the matching
3965 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3966 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3967 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3968 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3969 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3971 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3976 /* If smb_fmask is asking to set any bits that are not supported by
3977 * our flag mappings, we should fail.
3979 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3987 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3988 * of file flags and birth (create) time.
3990 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3993 const SMB_STRUCT_STAT
*psbuf
)
3995 uint32 file_flags
= 0;
3996 uint32 flags_mask
= 0;
3998 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4000 /* Create (birth) time 64 bit */
4001 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4004 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4005 SIVAL(pdata
, 0, file_flags
); /* flags */
4006 SIVAL(pdata
, 4, flags_mask
); /* mask */
4012 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4013 const struct stream_struct
*streams
,
4015 unsigned int max_data_bytes
,
4016 unsigned int *data_size
)
4019 unsigned int ofs
= 0;
4021 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4022 unsigned int next_offset
;
4024 smb_ucs2_t
*namebuf
;
4026 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4027 streams
[i
].name
, &namelen
) ||
4030 return NT_STATUS_INVALID_PARAMETER
;
4034 * name_buf is now null-terminated, we need to marshall as not
4040 SIVAL(data
, ofs
+4, namelen
);
4041 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4042 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4043 memcpy(data
+ofs
+24, namebuf
, namelen
);
4044 TALLOC_FREE(namebuf
);
4046 next_offset
= ofs
+ 24 + namelen
;
4048 if (i
== num_streams
-1) {
4049 SIVAL(data
, ofs
, 0);
4052 unsigned int align
= ndr_align_size(next_offset
, 8);
4054 memset(data
+next_offset
, 0, align
);
4055 next_offset
+= align
;
4057 SIVAL(data
, ofs
, next_offset
- ofs
);
4066 return NT_STATUS_OK
;
4069 /****************************************************************************
4070 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4071 ****************************************************************************/
4073 static void call_trans2qpipeinfo(connection_struct
*conn
,
4074 struct smb_request
*req
,
4075 unsigned int tran_call
,
4076 char **pparams
, int total_params
,
4077 char **ppdata
, int total_data
,
4078 unsigned int max_data_bytes
)
4080 char *params
= *pparams
;
4081 char *pdata
= *ppdata
;
4082 unsigned int data_size
= 0;
4083 unsigned int param_size
= 2;
4088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4092 if (total_params
< 4) {
4093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4097 fsp
= file_fsp(req
, SVAL(params
,0));
4098 if (!fsp_is_np(fsp
)) {
4099 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4103 info_level
= SVAL(params
,2);
4105 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4106 if (*pparams
== NULL
) {
4107 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4112 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4113 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4114 if (*ppdata
== NULL
) {
4115 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4120 switch (info_level
) {
4121 case SMB_FILE_STANDARD_INFORMATION
:
4123 SOFF_T(pdata
,0,4096LL);
4130 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4134 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4140 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4141 TALLOC_CTX
*mem_ctx
,
4142 uint16_t info_level
,
4144 struct smb_filename
*smb_fname
,
4145 bool delete_pending
,
4146 struct timespec write_time_ts
,
4148 struct ea_list
*ea_list
,
4149 int lock_data_count
,
4152 unsigned int max_data_bytes
,
4154 unsigned int *pdata_size
)
4156 char *pdata
= *ppdata
;
4157 char *dstart
, *dend
;
4158 unsigned int data_size
;
4159 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4160 time_t create_time
, mtime
, atime
, c_time
;
4161 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4168 uint64_t file_size
= 0;
4170 uint64_t allocation_size
= 0;
4171 uint64_t file_index
= 0;
4172 uint32_t access_mask
= 0;
4174 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4175 return NT_STATUS_INVALID_LEVEL
;
4178 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4179 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4180 info_level
, max_data_bytes
));
4183 mode
= dos_mode_msdfs(conn
, smb_fname
);
4185 mode
= dos_mode(conn
, smb_fname
);
4188 nlink
= psbuf
->st_ex_nlink
;
4190 if (nlink
&& (mode
&aDIR
)) {
4194 if ((nlink
> 0) && delete_pending
) {
4198 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4199 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4200 if (*ppdata
== NULL
) {
4201 return NT_STATUS_NO_MEMORY
;
4205 dend
= dstart
+ data_size
- 1;
4207 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4208 update_stat_ex_mtime(psbuf
, write_time_ts
);
4211 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4212 mtime_ts
= psbuf
->st_ex_mtime
;
4213 atime_ts
= psbuf
->st_ex_atime
;
4214 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4216 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4217 dos_filetime_timespec(&create_time_ts
);
4218 dos_filetime_timespec(&mtime_ts
);
4219 dos_filetime_timespec(&atime_ts
);
4220 dos_filetime_timespec(&ctime_ts
);
4223 create_time
= convert_timespec_to_time_t(create_time_ts
);
4224 mtime
= convert_timespec_to_time_t(mtime_ts
);
4225 atime
= convert_timespec_to_time_t(atime_ts
);
4226 c_time
= convert_timespec_to_time_t(ctime_ts
);
4228 p
= strrchr_m(smb_fname
->base_name
,'/');
4230 base_name
= smb_fname
->base_name
;
4234 /* NT expects the name to be in an exact form of the *full*
4235 filename. See the trans2 torture test */
4236 if (ISDOT(base_name
)) {
4237 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4239 return NT_STATUS_NO_MEMORY
;
4242 dos_fname
= talloc_asprintf(mem_ctx
,
4244 smb_fname
->base_name
);
4246 return NT_STATUS_NO_MEMORY
;
4248 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4249 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4250 smb_fname
->stream_name
);
4252 return NT_STATUS_NO_MEMORY
;
4256 string_replace(dos_fname
, '/', '\\');
4259 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4262 /* Do we have this path open ? */
4264 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4265 fsp1
= file_find_di_first(fileid
);
4266 if (fsp1
&& fsp1
->initial_allocation_size
) {
4267 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4271 if (!(mode
& aDIR
)) {
4272 file_size
= get_file_size_stat(psbuf
);
4276 pos
= fsp
->fh
->position_information
;
4280 access_mask
= fsp
->access_mask
;
4282 /* GENERIC_EXECUTE mapping from Windows */
4283 access_mask
= 0x12019F;
4286 /* This should be an index number - looks like
4289 I think this causes us to fail the IFSKIT
4290 BasicFileInformationTest. -tpot */
4291 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
4292 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
4294 switch (info_level
) {
4295 case SMB_INFO_STANDARD
:
4296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4298 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4299 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4300 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4301 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4302 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4303 SSVAL(pdata
,l1_attrFile
,mode
);
4306 case SMB_INFO_QUERY_EA_SIZE
:
4308 unsigned int ea_size
=
4309 estimate_ea_size(conn
, fsp
,
4310 smb_fname
->base_name
);
4311 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4313 srv_put_dos_date2(pdata
,0,create_time
);
4314 srv_put_dos_date2(pdata
,4,atime
);
4315 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4316 SIVAL(pdata
,12,(uint32
)file_size
);
4317 SIVAL(pdata
,16,(uint32
)allocation_size
);
4318 SSVAL(pdata
,20,mode
);
4319 SIVAL(pdata
,22,ea_size
);
4323 case SMB_INFO_IS_NAME_VALID
:
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4326 /* os/2 needs this ? really ?*/
4327 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4329 /* This is only reached for qpathinfo */
4333 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4335 size_t total_ea_len
= 0;
4336 struct ea_list
*ea_file_list
= NULL
;
4338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4341 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4342 smb_fname
->base_name
,
4344 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4346 if (!ea_list
|| (total_ea_len
> data_size
)) {
4348 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4352 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4356 case SMB_INFO_QUERY_ALL_EAS
:
4358 /* We have data_size bytes to put EA's into. */
4359 size_t total_ea_len
= 0;
4361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4363 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4364 smb_fname
->base_name
,
4366 if (!ea_list
|| (total_ea_len
> data_size
)) {
4368 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4372 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4376 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4378 /* This is FileFullEaInformation - 0xF which maps to
4379 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4381 /* We have data_size bytes to put EA's into. */
4382 size_t total_ea_len
= 0;
4383 struct ea_list
*ea_file_list
= NULL
;
4385 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4387 /*TODO: add filtering and index handling */
4390 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4391 smb_fname
->base_name
,
4393 if (!ea_file_list
) {
4394 return NT_STATUS_NO_EAS_ON_FILE
;
4397 status
= fill_ea_chained_buffer(mem_ctx
,
4401 conn
, ea_file_list
);
4402 if (!NT_STATUS_IS_OK(status
)) {
4408 case SMB_FILE_BASIC_INFORMATION
:
4409 case SMB_QUERY_FILE_BASIC_INFO
:
4411 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4413 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4419 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4420 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4421 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4422 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4423 SIVAL(pdata
,32,mode
);
4425 DEBUG(5,("SMB_QFBI - "));
4426 DEBUG(5,("create: %s ", ctime(&create_time
)));
4427 DEBUG(5,("access: %s ", ctime(&atime
)));
4428 DEBUG(5,("write: %s ", ctime(&mtime
)));
4429 DEBUG(5,("change: %s ", ctime(&c_time
)));
4430 DEBUG(5,("mode: %x\n", mode
));
4433 case SMB_FILE_STANDARD_INFORMATION
:
4434 case SMB_QUERY_FILE_STANDARD_INFO
:
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4438 SOFF_T(pdata
,0,allocation_size
);
4439 SOFF_T(pdata
,8,file_size
);
4440 SIVAL(pdata
,16,nlink
);
4441 SCVAL(pdata
,20,delete_pending
?1:0);
4442 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4443 SSVAL(pdata
,22,0); /* Padding. */
4446 case SMB_FILE_EA_INFORMATION
:
4447 case SMB_QUERY_FILE_EA_INFO
:
4449 unsigned int ea_size
=
4450 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4453 SIVAL(pdata
,0,ea_size
);
4457 /* Get the 8.3 name - used if NT SMB was negotiated. */
4458 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4459 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4462 char mangled_name
[13];
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4464 if (!name_to_8_3(base_name
,mangled_name
,
4465 True
,conn
->params
)) {
4466 return NT_STATUS_NO_MEMORY
;
4468 len
= srvstr_push(dstart
, flags2
,
4469 pdata
+4, mangled_name
,
4470 PTR_DIFF(dend
, pdata
+4),
4472 data_size
= 4 + len
;
4477 case SMB_QUERY_FILE_NAME_INFO
:
4481 this must be *exactly* right for ACLs on mapped drives to work
4483 len
= srvstr_push(dstart
, flags2
,
4485 PTR_DIFF(dend
, pdata
+4),
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4488 data_size
= 4 + len
;
4493 case SMB_FILE_ALLOCATION_INFORMATION
:
4494 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4495 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4497 SOFF_T(pdata
,0,allocation_size
);
4500 case SMB_FILE_END_OF_FILE_INFORMATION
:
4501 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4504 SOFF_T(pdata
,0,file_size
);
4507 case SMB_QUERY_FILE_ALL_INFO
:
4508 case SMB_FILE_ALL_INFORMATION
:
4511 unsigned int ea_size
=
4512 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4514 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4515 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4516 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4517 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4518 SIVAL(pdata
,32,mode
);
4519 SIVAL(pdata
,36,0); /* padding. */
4521 SOFF_T(pdata
,0,allocation_size
);
4522 SOFF_T(pdata
,8,file_size
);
4523 SIVAL(pdata
,16,nlink
);
4524 SCVAL(pdata
,20,delete_pending
);
4525 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4528 SIVAL(pdata
,0,ea_size
);
4529 pdata
+= 4; /* EA info */
4530 len
= srvstr_push(dstart
, flags2
,
4532 PTR_DIFF(dend
, pdata
+4),
4536 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4540 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4543 unsigned int ea_size
=
4544 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4546 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4547 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4548 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4549 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4550 SIVAL(pdata
, 0x20, mode
);
4551 SIVAL(pdata
, 0x24, 0); /* padding. */
4552 SBVAL(pdata
, 0x28, allocation_size
);
4553 SBVAL(pdata
, 0x30, file_size
);
4554 SIVAL(pdata
, 0x38, nlink
);
4555 SCVAL(pdata
, 0x3C, delete_pending
);
4556 SCVAL(pdata
, 0x3D, (mode
&aDIR
)?1:0);
4557 SSVAL(pdata
, 0x3E, 0); /* padding */
4558 SBVAL(pdata
, 0x40, file_index
);
4559 SIVAL(pdata
, 0x48, ea_size
);
4560 SIVAL(pdata
, 0x4C, access_mask
);
4561 SBVAL(pdata
, 0x50, pos
);
4562 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4563 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4567 len
= srvstr_push(dstart
, flags2
,
4569 PTR_DIFF(dend
, pdata
+4),
4573 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4576 case SMB_FILE_INTERNAL_INFORMATION
:
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4579 SBVAL(pdata
, 0, file_index
);
4583 case SMB_FILE_ACCESS_INFORMATION
:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4585 SIVAL(pdata
, 0, access_mask
);
4589 case SMB_FILE_NAME_INFORMATION
:
4590 /* Pathname with leading '\'. */
4593 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4595 SIVAL(pdata
,0,byte_len
);
4596 data_size
= 4 + byte_len
;
4600 case SMB_FILE_DISPOSITION_INFORMATION
:
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4603 SCVAL(pdata
,0,delete_pending
);
4606 case SMB_FILE_POSITION_INFORMATION
:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4609 SOFF_T(pdata
,0,pos
);
4612 case SMB_FILE_MODE_INFORMATION
:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4614 SIVAL(pdata
,0,mode
);
4618 case SMB_FILE_ALIGNMENT_INFORMATION
:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4620 SIVAL(pdata
,0,0); /* No alignment needed. */
4625 * NT4 server just returns "invalid query" to this - if we try
4626 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4629 /* The first statement above is false - verified using Thursby
4630 * client against NT4 -- gcolley.
4632 case SMB_QUERY_FILE_STREAM_INFO
:
4633 case SMB_FILE_STREAM_INFORMATION
: {
4634 unsigned int num_streams
;
4635 struct stream_struct
*streams
;
4637 DEBUG(10,("smbd_do_qfilepathinfo: "
4638 "SMB_FILE_STREAM_INFORMATION\n"));
4640 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4641 return NT_STATUS_INVALID_PARAMETER
;
4644 status
= SMB_VFS_STREAMINFO(
4645 conn
, fsp
, smb_fname
->base_name
, talloc_tos(),
4646 &num_streams
, &streams
);
4648 if (!NT_STATUS_IS_OK(status
)) {
4649 DEBUG(10, ("could not get stream info: %s\n",
4650 nt_errstr(status
)));
4654 status
= marshall_stream_info(num_streams
, streams
,
4655 pdata
, max_data_bytes
,
4658 if (!NT_STATUS_IS_OK(status
)) {
4659 DEBUG(10, ("marshall_stream_info failed: %s\n",
4660 nt_errstr(status
)));
4664 TALLOC_FREE(streams
);
4668 case SMB_QUERY_COMPRESSION_INFO
:
4669 case SMB_FILE_COMPRESSION_INFORMATION
:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4671 SOFF_T(pdata
,0,file_size
);
4672 SIVAL(pdata
,8,0); /* ??? */
4673 SIVAL(pdata
,12,0); /* ??? */
4677 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4679 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4680 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4681 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4682 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4683 SOFF_T(pdata
,32,allocation_size
);
4684 SOFF_T(pdata
,40,file_size
);
4685 SIVAL(pdata
,48,mode
);
4686 SIVAL(pdata
,52,0); /* ??? */
4690 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4692 SIVAL(pdata
,0,mode
);
4698 * CIFS UNIX Extensions.
4701 case SMB_QUERY_FILE_UNIX_BASIC
:
4703 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4704 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4708 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4710 for (i
=0; i
<100; i
++)
4711 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4717 case SMB_QUERY_FILE_UNIX_INFO2
:
4719 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4720 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4724 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4726 for (i
=0; i
<100; i
++)
4727 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4733 case SMB_QUERY_FILE_UNIX_LINK
:
4736 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4739 return NT_STATUS_NO_MEMORY
;
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4744 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4745 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4748 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4750 len
= SMB_VFS_READLINK(conn
,
4751 smb_fname
->base_name
,
4754 return map_nt_error_from_unix(errno
);
4757 len
= srvstr_push(dstart
, flags2
,
4759 PTR_DIFF(dend
, pdata
),
4762 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4767 #if defined(HAVE_POSIX_ACLS)
4768 case SMB_QUERY_POSIX_ACL
:
4770 SMB_ACL_T file_acl
= NULL
;
4771 SMB_ACL_T def_acl
= NULL
;
4772 uint16 num_file_acls
= 0;
4773 uint16 num_def_acls
= 0;
4775 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4776 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4779 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4780 smb_fname
->base_name
,
4781 SMB_ACL_TYPE_ACCESS
);
4784 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4785 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4786 "not implemented on "
4787 "filesystem containing %s\n",
4788 smb_fname
->base_name
));
4789 return NT_STATUS_NOT_IMPLEMENTED
;
4792 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4793 if (fsp
&& fsp
->is_directory
) {
4795 SMB_VFS_SYS_ACL_GET_FILE(
4797 fsp
->fsp_name
->base_name
,
4798 SMB_ACL_TYPE_DEFAULT
);
4801 SMB_VFS_SYS_ACL_GET_FILE(
4803 smb_fname
->base_name
,
4804 SMB_ACL_TYPE_DEFAULT
);
4806 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4809 num_file_acls
= count_acl_entries(conn
, file_acl
);
4810 num_def_acls
= count_acl_entries(conn
, def_acl
);
4812 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4813 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4815 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4816 SMB_POSIX_ACL_HEADER_SIZE
) ));
4818 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4821 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4823 return NT_STATUS_BUFFER_TOO_SMALL
;
4826 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4827 SSVAL(pdata
,2,num_file_acls
);
4828 SSVAL(pdata
,4,num_def_acls
);
4829 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4836 return NT_STATUS_INTERNAL_ERROR
;
4838 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4840 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4843 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4845 return NT_STATUS_INTERNAL_ERROR
;
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4852 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4854 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4860 case SMB_QUERY_POSIX_LOCK
:
4865 enum brl_type lock_type
;
4867 /* We need an open file with a real fd for this. */
4868 if (!fsp
|| fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
4869 return NT_STATUS_INVALID_LEVEL
;
4872 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4873 return NT_STATUS_INVALID_PARAMETER
;
4876 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4877 case POSIX_LOCK_TYPE_READ
:
4878 lock_type
= READ_LOCK
;
4880 case POSIX_LOCK_TYPE_WRITE
:
4881 lock_type
= WRITE_LOCK
;
4883 case POSIX_LOCK_TYPE_UNLOCK
:
4885 /* There's no point in asking for an unlock... */
4886 return NT_STATUS_INVALID_PARAMETER
;
4889 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4890 #if defined(HAVE_LONGLONG)
4891 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4892 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4893 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4894 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4895 #else /* HAVE_LONGLONG */
4896 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4897 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4898 #endif /* HAVE_LONGLONG */
4900 status
= query_lock(fsp
,
4907 if (ERROR_WAS_LOCK_DENIED(status
)) {
4908 /* Here we need to report who has it locked... */
4909 data_size
= POSIX_LOCK_DATA_SIZE
;
4911 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4912 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4913 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4914 #if defined(HAVE_LONGLONG)
4915 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4916 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4917 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4918 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4919 #else /* HAVE_LONGLONG */
4920 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4921 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4922 #endif /* HAVE_LONGLONG */
4924 } else if (NT_STATUS_IS_OK(status
)) {
4925 /* For success we just return a copy of what we sent
4926 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4927 data_size
= POSIX_LOCK_DATA_SIZE
;
4928 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4929 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4937 return NT_STATUS_INVALID_LEVEL
;
4940 *pdata_size
= data_size
;
4941 return NT_STATUS_OK
;
4944 /****************************************************************************
4945 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4946 file name or file id).
4947 ****************************************************************************/
4949 static void call_trans2qfilepathinfo(connection_struct
*conn
,
4950 struct smb_request
*req
,
4951 unsigned int tran_call
,
4952 char **pparams
, int total_params
,
4953 char **ppdata
, int total_data
,
4954 unsigned int max_data_bytes
)
4956 char *params
= *pparams
;
4957 char *pdata
= *ppdata
;
4959 unsigned int data_size
= 0;
4960 unsigned int param_size
= 2;
4961 struct smb_filename
*smb_fname
= NULL
;
4962 bool delete_pending
= False
;
4963 struct timespec write_time_ts
;
4964 files_struct
*fsp
= NULL
;
4965 struct file_id fileid
;
4966 struct ea_list
*ea_list
= NULL
;
4967 int lock_data_count
= 0;
4968 char *lock_data
= NULL
;
4969 bool ms_dfs_link
= false;
4970 NTSTATUS status
= NT_STATUS_OK
;
4973 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4977 ZERO_STRUCT(write_time_ts
);
4979 if (tran_call
== TRANSACT2_QFILEINFO
) {
4980 if (total_params
< 4) {
4981 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4986 call_trans2qpipeinfo(conn
, req
, tran_call
,
4987 pparams
, total_params
,
4993 fsp
= file_fsp(req
, SVAL(params
,0));
4994 info_level
= SVAL(params
,2);
4996 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
4998 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4999 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5003 /* Initial check for valid fsp ptr. */
5004 if (!check_fsp_open(conn
, req
, fsp
)) {
5008 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5010 if (!NT_STATUS_IS_OK(status
)) {
5011 reply_nterror(req
, status
);
5015 if(fsp
->fake_file_handle
) {
5017 * This is actually for the QUOTA_FAKE_FILE --metze
5020 /* We know this name is ok, it's already passed the checks. */
5022 } else if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
5024 * This is actually a QFILEINFO on a directory
5025 * handle (returned from an NT SMB). NT5.0 seems
5026 * to do this call. JRA.
5029 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5030 /* Always do lstat for UNIX calls. */
5031 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5032 DEBUG(3,("call_trans2qfilepathinfo: "
5033 "SMB_VFS_LSTAT of %s failed "
5035 smb_fname_str_dbg(smb_fname
),
5038 map_nt_error_from_unix(errno
));
5041 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5042 DEBUG(3,("call_trans2qfilepathinfo: "
5043 "SMB_VFS_STAT of %s failed (%s)\n",
5044 smb_fname_str_dbg(smb_fname
),
5047 map_nt_error_from_unix(errno
));
5051 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5052 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5055 * Original code - this is an open file.
5057 if (!check_fsp(conn
, req
, fsp
)) {
5061 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5062 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5063 fsp
->fnum
, strerror(errno
)));
5065 map_nt_error_from_unix(errno
));
5068 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5069 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5076 if (total_params
< 7) {
5077 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5081 info_level
= SVAL(params
,0);
5083 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5085 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5086 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5090 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5092 STR_TERMINATE
, &status
);
5093 if (!NT_STATUS_IS_OK(status
)) {
5094 reply_nterror(req
, status
);
5098 status
= filename_convert(req
,
5100 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5105 if (!NT_STATUS_IS_OK(status
)) {
5106 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5107 reply_botherror(req
,
5108 NT_STATUS_PATH_NOT_COVERED
,
5109 ERRSRV
, ERRbadpath
);
5112 reply_nterror(req
, status
);
5116 /* If this is a stream, check if there is a delete_pending. */
5117 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5118 && is_ntfs_stream_smb_fname(smb_fname
)) {
5119 struct smb_filename
*smb_fname_base
= NULL
;
5121 /* Create an smb_filename with stream_name == NULL. */
5123 create_synthetic_smb_fname(talloc_tos(),
5124 smb_fname
->base_name
,
5127 if (!NT_STATUS_IS_OK(status
)) {
5128 reply_nterror(req
, status
);
5132 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5133 /* Always do lstat for UNIX calls. */
5134 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5135 DEBUG(3,("call_trans2qfilepathinfo: "
5136 "SMB_VFS_LSTAT of %s failed "
5138 smb_fname_str_dbg(smb_fname_base
),
5140 TALLOC_FREE(smb_fname_base
);
5142 map_nt_error_from_unix(errno
));
5146 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5147 DEBUG(3,("call_trans2qfilepathinfo: "
5148 "fileinfo of %s failed "
5150 smb_fname_str_dbg(smb_fname_base
),
5152 TALLOC_FREE(smb_fname_base
);
5154 map_nt_error_from_unix(errno
));
5159 fileid
= vfs_file_id_from_sbuf(conn
,
5160 &smb_fname_base
->st
);
5161 TALLOC_FREE(smb_fname_base
);
5162 get_file_infos(fileid
, &delete_pending
, NULL
);
5163 if (delete_pending
) {
5164 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5169 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5170 /* Always do lstat for UNIX calls. */
5171 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5172 DEBUG(3,("call_trans2qfilepathinfo: "
5173 "SMB_VFS_LSTAT of %s failed (%s)\n",
5174 smb_fname_str_dbg(smb_fname
),
5177 map_nt_error_from_unix(errno
));
5181 } else if (!VALID_STAT(smb_fname
->st
) &&
5182 SMB_VFS_STAT(conn
, smb_fname
) &&
5183 (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
5184 ms_dfs_link
= check_msdfs_link(conn
,
5185 smb_fname
->base_name
,
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_STAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname
),
5194 map_nt_error_from_unix(errno
));
5199 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5200 get_file_infos(fileid
, &delete_pending
, &write_time_ts
);
5201 if (delete_pending
) {
5202 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5207 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5208 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5209 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5211 /* Pull out any data sent here before we realloc. */
5212 switch (info_level
) {
5213 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5215 /* Pull any EA list from the data portion. */
5218 if (total_data
< 4) {
5220 req
, NT_STATUS_INVALID_PARAMETER
);
5223 ea_size
= IVAL(pdata
,0);
5225 if (total_data
> 0 && ea_size
!= total_data
) {
5226 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5227 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5229 req
, NT_STATUS_INVALID_PARAMETER
);
5233 if (!lp_ea_support(SNUM(conn
))) {
5234 reply_doserror(req
, ERRDOS
,
5235 ERReasnotsupported
);
5239 /* Pull out the list of names. */
5240 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5243 req
, NT_STATUS_INVALID_PARAMETER
);
5249 case SMB_QUERY_POSIX_LOCK
:
5251 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5252 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5256 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5258 req
, NT_STATUS_INVALID_PARAMETER
);
5262 /* Copy the lock range data. */
5263 lock_data
= (char *)TALLOC_MEMDUP(
5264 req
, pdata
, total_data
);
5266 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5269 lock_data_count
= total_data
;
5275 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5276 if (*pparams
== NULL
) {
5277 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5284 * draft-leach-cifs-v1-spec-02.txt
5285 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5288 * The requested information is placed in the Data portion of the
5289 * transaction response. For the information levels greater than 0x100,
5290 * the transaction response has 1 parameter word which should be
5291 * ignored by the client.
5293 * However Windows only follows this rule for the IS_NAME_VALID call.
5295 switch (info_level
) {
5296 case SMB_INFO_IS_NAME_VALID
:
5301 if ((info_level
& 0xFF00) == 0xFF00) {
5303 * We use levels that start with 0xFF00
5304 * internally to represent SMB2 specific levels
5306 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5310 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5312 delete_pending
, write_time_ts
,
5313 ms_dfs_link
, ea_list
,
5314 lock_data_count
, lock_data
,
5315 req
->flags2
, max_data_bytes
,
5316 ppdata
, &data_size
);
5317 if (!NT_STATUS_IS_OK(status
)) {
5318 reply_nterror(req
, status
);
5322 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5328 /****************************************************************************
5329 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5331 ****************************************************************************/
5333 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5334 connection_struct
*conn
,
5335 const struct smb_filename
*smb_fname_old
,
5336 const struct smb_filename
*smb_fname_new
)
5338 NTSTATUS status
= NT_STATUS_OK
;
5340 /* source must already exist. */
5341 if (!VALID_STAT(smb_fname_old
->st
)) {
5342 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5345 /* Disallow if newname already exists. */
5346 if (VALID_STAT(smb_fname_new
->st
)) {
5347 return NT_STATUS_OBJECT_NAME_COLLISION
;
5350 /* No links from a directory. */
5351 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5352 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5355 /* Setting a hardlink to/from a stream isn't currently supported. */
5356 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5357 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5358 return NT_STATUS_INVALID_PARAMETER
;
5361 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5362 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5364 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5365 smb_fname_new
->base_name
) != 0) {
5366 status
= map_nt_error_from_unix(errno
);
5367 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5368 nt_errstr(status
), smb_fname_old
->base_name
,
5369 smb_fname_new
->base_name
));
5374 /****************************************************************************
5375 Deal with setting the time from any of the setfilepathinfo functions.
5376 ****************************************************************************/
5378 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5380 const struct smb_filename
*smb_fname
,
5381 struct smb_file_time
*ft
,
5382 bool setting_write_time
)
5384 struct smb_filename smb_fname_base
;
5386 FILE_NOTIFY_CHANGE_LAST_ACCESS
5387 |FILE_NOTIFY_CHANGE_LAST_WRITE
5388 |FILE_NOTIFY_CHANGE_CREATION
;
5390 if (!VALID_STAT(smb_fname
->st
)) {
5391 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5394 /* get some defaults (no modifications) if any info is zero or -1. */
5395 if (null_timespec(ft
->create_time
)) {
5396 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5399 if (null_timespec(ft
->atime
)) {
5400 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5403 if (null_timespec(ft
->mtime
)) {
5404 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5407 if (!setting_write_time
) {
5408 /* ft->mtime comes from change time, not write time. */
5409 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5412 /* Ensure the resolution is the correct for
5413 * what we can store on this filesystem. */
5415 round_timespec(conn
->ts_res
, &ft
->create_time
);
5416 round_timespec(conn
->ts_res
, &ft
->ctime
);
5417 round_timespec(conn
->ts_res
, &ft
->atime
);
5418 round_timespec(conn
->ts_res
, &ft
->mtime
);
5420 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5421 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5422 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5423 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5424 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5425 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5426 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5427 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5429 if (setting_write_time
) {
5431 * This was a Windows setfileinfo on an open file.
5432 * NT does this a lot. We also need to
5433 * set the time here, as it can be read by
5434 * FindFirst/FindNext and with the patch for bug #2045
5435 * in smbd/fileio.c it ensures that this timestamp is
5436 * kept sticky even after a write. We save the request
5437 * away and will set it on file close and after a write. JRA.
5440 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5441 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5444 if (fsp
->base_fsp
) {
5445 set_sticky_write_time_fsp(fsp
->base_fsp
,
5448 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5451 set_sticky_write_time_path(
5452 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5457 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5459 /* Always call ntimes on the base, even if a stream was passed in. */
5460 smb_fname_base
= *smb_fname
;
5461 smb_fname_base
.stream_name
= NULL
;
5463 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5464 return map_nt_error_from_unix(errno
);
5467 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5468 smb_fname
->base_name
);
5469 return NT_STATUS_OK
;
5472 /****************************************************************************
5473 Deal with setting the dosmode from any of the setfilepathinfo functions.
5474 ****************************************************************************/
5476 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5477 const struct smb_filename
*smb_fname
,
5480 struct smb_filename
*smb_fname_base
= NULL
;
5483 if (!VALID_STAT(smb_fname
->st
)) {
5484 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5487 /* Always operate on the base_name, even if a stream was passed in. */
5488 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5489 NULL
, &smb_fname
->st
,
5491 if (!NT_STATUS_IS_OK(status
)) {
5496 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5503 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5505 /* check the mode isn't different, before changing it */
5506 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5507 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5508 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5509 (unsigned int)dosmode
));
5511 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5513 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5515 smb_fname_str_dbg(smb_fname_base
),
5517 status
= map_nt_error_from_unix(errno
);
5521 status
= NT_STATUS_OK
;
5523 TALLOC_FREE(smb_fname_base
);
5527 /****************************************************************************
5528 Deal with setting the size from any of the setfilepathinfo functions.
5529 ****************************************************************************/
5531 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5532 struct smb_request
*req
,
5534 const struct smb_filename
*smb_fname
,
5535 const SMB_STRUCT_STAT
*psbuf
,
5537 bool fail_after_createfile
)
5539 NTSTATUS status
= NT_STATUS_OK
;
5540 struct smb_filename
*smb_fname_tmp
= NULL
;
5541 files_struct
*new_fsp
= NULL
;
5543 if (!VALID_STAT(*psbuf
)) {
5544 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5547 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5549 if (size
== get_file_size_stat(psbuf
)) {
5550 return NT_STATUS_OK
;
5553 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5554 smb_fname_str_dbg(smb_fname
), (double)size
));
5556 if (fsp
&& fsp
->fh
->fd
!= -1) {
5557 /* Handle based call. */
5558 if (vfs_set_filelen(fsp
, size
) == -1) {
5559 return map_nt_error_from_unix(errno
);
5561 trigger_write_time_update_immediate(fsp
);
5562 return NT_STATUS_OK
;
5565 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5566 if (!NT_STATUS_IS_OK(status
)) {
5570 smb_fname_tmp
->st
= *psbuf
;
5572 status
= SMB_VFS_CREATE_FILE(
5575 0, /* root_dir_fid */
5576 smb_fname_tmp
, /* fname */
5577 FILE_WRITE_DATA
, /* access_mask */
5578 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5580 FILE_OPEN
, /* create_disposition*/
5581 0, /* create_options */
5582 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5583 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5584 0, /* allocation_size */
5587 &new_fsp
, /* result */
5590 TALLOC_FREE(smb_fname_tmp
);
5592 if (!NT_STATUS_IS_OK(status
)) {
5593 /* NB. We check for open_was_deferred in the caller. */
5597 /* See RAW-SFILEINFO-END-OF-FILE */
5598 if (fail_after_createfile
) {
5599 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5600 return NT_STATUS_INVALID_LEVEL
;
5603 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5604 status
= map_nt_error_from_unix(errno
);
5605 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5609 trigger_write_time_update_immediate(new_fsp
);
5610 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5611 return NT_STATUS_OK
;
5614 /****************************************************************************
5615 Deal with SMB_INFO_SET_EA.
5616 ****************************************************************************/
5618 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5622 const struct smb_filename
*smb_fname
)
5624 struct ea_list
*ea_list
= NULL
;
5625 TALLOC_CTX
*ctx
= NULL
;
5626 NTSTATUS status
= NT_STATUS_OK
;
5628 if (total_data
< 10) {
5630 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5631 length. They seem to have no effect. Bug #3212. JRA */
5633 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5634 /* We're done. We only get EA info in this call. */
5635 return NT_STATUS_OK
;
5638 return NT_STATUS_INVALID_PARAMETER
;
5641 if (IVAL(pdata
,0) > total_data
) {
5642 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5643 IVAL(pdata
,0), (unsigned int)total_data
));
5644 return NT_STATUS_INVALID_PARAMETER
;
5648 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5650 return NT_STATUS_INVALID_PARAMETER
;
5652 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5657 /****************************************************************************
5658 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5659 ****************************************************************************/
5661 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5666 struct ea_list
*ea_list
= NULL
;
5670 return NT_STATUS_INVALID_HANDLE
;
5673 if (!lp_ea_support(SNUM(conn
))) {
5674 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5675 "EA's not supported.\n",
5676 (unsigned int)total_data
));
5677 return NT_STATUS_EAS_NOT_SUPPORTED
;
5680 if (total_data
< 10) {
5681 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5683 (unsigned int)total_data
));
5684 return NT_STATUS_INVALID_PARAMETER
;
5687 ea_list
= read_nttrans_ea_list(talloc_tos(),
5692 return NT_STATUS_INVALID_PARAMETER
;
5694 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5696 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5697 smb_fname_str_dbg(fsp
->fsp_name
),
5698 nt_errstr(status
) ));
5704 /****************************************************************************
5705 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5706 ****************************************************************************/
5708 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5712 struct smb_filename
*smb_fname
)
5714 NTSTATUS status
= NT_STATUS_OK
;
5715 bool delete_on_close
;
5718 if (total_data
< 1) {
5719 return NT_STATUS_INVALID_PARAMETER
;
5723 return NT_STATUS_INVALID_HANDLE
;
5726 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5727 dosmode
= dos_mode(conn
, smb_fname
);
5729 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5730 "delete_on_close = %u\n",
5731 smb_fname_str_dbg(smb_fname
),
5732 (unsigned int)dosmode
,
5733 (unsigned int)delete_on_close
));
5735 if (delete_on_close
) {
5736 status
= can_set_delete_on_close(fsp
, dosmode
);
5737 if (!NT_STATUS_IS_OK(status
)) {
5742 /* The set is across all open files on this dev/inode pair. */
5743 if (!set_delete_on_close(fsp
, delete_on_close
,
5744 &conn
->server_info
->utok
)) {
5745 return NT_STATUS_ACCESS_DENIED
;
5747 return NT_STATUS_OK
;
5750 /****************************************************************************
5751 Deal with SMB_FILE_POSITION_INFORMATION.
5752 ****************************************************************************/
5754 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5759 uint64_t position_information
;
5761 if (total_data
< 8) {
5762 return NT_STATUS_INVALID_PARAMETER
;
5766 /* Ignore on pathname based set. */
5767 return NT_STATUS_OK
;
5770 position_information
= (uint64_t)IVAL(pdata
,0);
5771 #ifdef LARGE_SMB_OFF_T
5772 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5773 #else /* LARGE_SMB_OFF_T */
5774 if (IVAL(pdata
,4) != 0) {
5775 /* more than 32 bits? */
5776 return NT_STATUS_INVALID_PARAMETER
;
5778 #endif /* LARGE_SMB_OFF_T */
5780 DEBUG(10,("smb_file_position_information: Set file position "
5781 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5782 (double)position_information
));
5783 fsp
->fh
->position_information
= position_information
;
5784 return NT_STATUS_OK
;
5787 /****************************************************************************
5788 Deal with SMB_FILE_MODE_INFORMATION.
5789 ****************************************************************************/
5791 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5797 if (total_data
< 4) {
5798 return NT_STATUS_INVALID_PARAMETER
;
5800 mode
= IVAL(pdata
,0);
5801 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5802 return NT_STATUS_INVALID_PARAMETER
;
5804 return NT_STATUS_OK
;
5807 /****************************************************************************
5808 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5809 ****************************************************************************/
5811 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5812 struct smb_request
*req
,
5815 const struct smb_filename
*smb_fname
)
5817 char *link_target
= NULL
;
5818 const char *newname
= smb_fname
->base_name
;
5819 NTSTATUS status
= NT_STATUS_OK
;
5820 TALLOC_CTX
*ctx
= talloc_tos();
5822 /* Set a symbolic link. */
5823 /* Don't allow this if follow links is false. */
5825 if (total_data
== 0) {
5826 return NT_STATUS_INVALID_PARAMETER
;
5829 if (!lp_symlinks(SNUM(conn
))) {
5830 return NT_STATUS_ACCESS_DENIED
;
5833 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
5834 total_data
, STR_TERMINATE
);
5837 return NT_STATUS_INVALID_PARAMETER
;
5840 /* !widelinks forces the target path to be within the share. */
5841 /* This means we can interpret the target as a pathname. */
5842 if (!lp_widelinks(SNUM(conn
))) {
5843 char *rel_name
= NULL
;
5844 char *last_dirp
= NULL
;
5846 if (*link_target
== '/') {
5847 /* No absolute paths allowed. */
5848 return NT_STATUS_ACCESS_DENIED
;
5850 rel_name
= talloc_strdup(ctx
,newname
);
5852 return NT_STATUS_NO_MEMORY
;
5854 last_dirp
= strrchr_m(rel_name
, '/');
5856 last_dirp
[1] = '\0';
5858 rel_name
= talloc_strdup(ctx
,"./");
5860 return NT_STATUS_NO_MEMORY
;
5863 rel_name
= talloc_asprintf_append(rel_name
,
5867 return NT_STATUS_NO_MEMORY
;
5870 status
= check_name(conn
, rel_name
);
5871 if (!NT_STATUS_IS_OK(status
)) {
5876 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5877 newname
, link_target
));
5879 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
5880 return map_nt_error_from_unix(errno
);
5883 return NT_STATUS_OK
;
5886 /****************************************************************************
5887 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5888 ****************************************************************************/
5890 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
5891 struct smb_request
*req
,
5892 const char *pdata
, int total_data
,
5893 const struct smb_filename
*smb_fname_new
)
5895 char *oldname
= NULL
;
5896 struct smb_filename
*smb_fname_old
= NULL
;
5897 TALLOC_CTX
*ctx
= talloc_tos();
5898 NTSTATUS status
= NT_STATUS_OK
;
5900 /* Set a hard link. */
5901 if (total_data
== 0) {
5902 return NT_STATUS_INVALID_PARAMETER
;
5905 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
5906 total_data
, STR_TERMINATE
, &status
);
5907 if (!NT_STATUS_IS_OK(status
)) {
5911 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5912 smb_fname_str_dbg(smb_fname_new
), oldname
));
5914 status
= filename_convert(ctx
,
5916 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5921 if (!NT_STATUS_IS_OK(status
)) {
5925 return hardlink_internals(ctx
, conn
, smb_fname_old
, smb_fname_new
);
5928 /****************************************************************************
5929 Deal with SMB_FILE_RENAME_INFORMATION.
5930 ****************************************************************************/
5932 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5933 struct smb_request
*req
,
5937 struct smb_filename
*smb_fname_src
)
5942 char *newname
= NULL
;
5943 struct smb_filename
*smb_fname_dst
= NULL
;
5944 bool dest_has_wcard
= False
;
5945 NTSTATUS status
= NT_STATUS_OK
;
5947 TALLOC_CTX
*ctx
= talloc_tos();
5949 if (total_data
< 13) {
5950 return NT_STATUS_INVALID_PARAMETER
;
5953 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5954 root_fid
= IVAL(pdata
,4);
5955 len
= IVAL(pdata
,8);
5957 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5958 return NT_STATUS_INVALID_PARAMETER
;
5961 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5964 if (!NT_STATUS_IS_OK(status
)) {
5968 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5971 status
= resolve_dfspath_wcard(ctx
, conn
,
5972 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5976 if (!NT_STATUS_IS_OK(status
)) {
5980 /* Check the new name has no '/' characters. */
5981 if (strchr_m(newname
, '/')) {
5982 return NT_STATUS_NOT_SUPPORTED
;
5985 if (fsp
&& fsp
->base_fsp
) {
5986 /* newname must be a stream name. */
5987 if (newname
[0] != ':') {
5988 return NT_STATUS_NOT_SUPPORTED
;
5991 /* Create an smb_fname to call rename_internals_fsp() with. */
5992 status
= create_synthetic_smb_fname(talloc_tos(),
5993 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
5995 if (!NT_STATUS_IS_OK(status
)) {
6000 * Set the original last component, since
6001 * rename_internals_fsp() requires it.
6003 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6005 if (smb_fname_dst
->original_lcomp
== NULL
) {
6006 status
= NT_STATUS_NO_MEMORY
;
6012 * Build up an smb_fname_dst based on the filename passed in.
6013 * We basically just strip off the last component, and put on
6014 * the newname instead.
6016 char *base_name
= NULL
;
6018 /* newname must *not* be a stream name. */
6019 if (newname
[0] == ':') {
6020 return NT_STATUS_NOT_SUPPORTED
;
6024 * Strip off the last component (filename) of the path passed
6027 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6029 return NT_STATUS_NO_MEMORY
;
6031 p
= strrchr_m(base_name
, '/');
6035 base_name
= talloc_strdup(ctx
, "./");
6037 return NT_STATUS_NO_MEMORY
;
6040 /* Append the new name. */
6041 base_name
= talloc_asprintf_append(base_name
,
6045 return NT_STATUS_NO_MEMORY
;
6048 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6051 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6054 /* If an error we expect this to be
6055 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6057 if (!NT_STATUS_IS_OK(status
)) {
6058 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6062 /* Create an smb_fname to call rename_internals_fsp() */
6063 status
= create_synthetic_smb_fname(ctx
,
6067 if (!NT_STATUS_IS_OK(status
)) {
6074 DEBUG(10,("smb_file_rename_information: "
6075 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6076 fsp
->fnum
, fsp_str_dbg(fsp
),
6077 smb_fname_str_dbg(smb_fname_dst
)));
6078 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6081 DEBUG(10,("smb_file_rename_information: "
6082 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6083 smb_fname_str_dbg(smb_fname_src
),
6084 smb_fname_str_dbg(smb_fname_dst
)));
6085 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6086 smb_fname_dst
, 0, overwrite
, false,
6088 FILE_WRITE_ATTRIBUTES
);
6091 TALLOC_FREE(smb_fname_dst
);
6095 /****************************************************************************
6096 Deal with SMB_SET_POSIX_ACL.
6097 ****************************************************************************/
6099 #if defined(HAVE_POSIX_ACLS)
6100 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6104 const struct smb_filename
*smb_fname
)
6106 uint16 posix_acl_version
;
6107 uint16 num_file_acls
;
6108 uint16 num_def_acls
;
6109 bool valid_file_acls
= True
;
6110 bool valid_def_acls
= True
;
6112 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6113 return NT_STATUS_INVALID_PARAMETER
;
6115 posix_acl_version
= SVAL(pdata
,0);
6116 num_file_acls
= SVAL(pdata
,2);
6117 num_def_acls
= SVAL(pdata
,4);
6119 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6120 valid_file_acls
= False
;
6124 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6125 valid_def_acls
= False
;
6129 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6130 return NT_STATUS_INVALID_PARAMETER
;
6133 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6134 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6135 return NT_STATUS_INVALID_PARAMETER
;
6138 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6139 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6140 (unsigned int)num_file_acls
,
6141 (unsigned int)num_def_acls
));
6143 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6144 smb_fname
->base_name
, num_file_acls
,
6145 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6146 return map_nt_error_from_unix(errno
);
6149 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6150 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6151 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6152 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6153 return map_nt_error_from_unix(errno
);
6155 return NT_STATUS_OK
;
6159 /****************************************************************************
6160 Deal with SMB_SET_POSIX_LOCK.
6161 ****************************************************************************/
6163 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6164 struct smb_request
*req
,
6172 bool blocking_lock
= False
;
6173 enum brl_type lock_type
;
6175 NTSTATUS status
= NT_STATUS_OK
;
6177 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6178 return NT_STATUS_INVALID_HANDLE
;
6181 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6182 return NT_STATUS_INVALID_PARAMETER
;
6185 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6186 case POSIX_LOCK_TYPE_READ
:
6187 lock_type
= READ_LOCK
;
6189 case POSIX_LOCK_TYPE_WRITE
:
6190 /* Return the right POSIX-mappable error code for files opened read-only. */
6191 if (!fsp
->can_write
) {
6192 return NT_STATUS_INVALID_HANDLE
;
6194 lock_type
= WRITE_LOCK
;
6196 case POSIX_LOCK_TYPE_UNLOCK
:
6197 lock_type
= UNLOCK_LOCK
;
6200 return NT_STATUS_INVALID_PARAMETER
;
6203 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6204 blocking_lock
= False
;
6205 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6206 blocking_lock
= True
;
6208 return NT_STATUS_INVALID_PARAMETER
;
6211 if (!lp_blocking_locks(SNUM(conn
))) {
6212 blocking_lock
= False
;
6215 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6216 #if defined(HAVE_LONGLONG)
6217 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6218 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6219 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6220 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6221 #else /* HAVE_LONGLONG */
6222 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6223 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6224 #endif /* HAVE_LONGLONG */
6226 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6227 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6229 (unsigned int)lock_type
,
6230 (unsigned int)lock_pid
,
6234 if (lock_type
== UNLOCK_LOCK
) {
6235 status
= do_unlock(smbd_messaging_context(),
6242 uint32 block_smbpid
;
6244 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
6256 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6258 * A blocking lock was requested. Package up
6259 * this smb into a queued request and push it
6260 * onto the blocking lock queue.
6262 if(push_blocking_lock_request(br_lck
,
6265 -1, /* infinite timeout. */
6273 TALLOC_FREE(br_lck
);
6277 TALLOC_FREE(br_lck
);
6283 /****************************************************************************
6284 Deal with SMB_SET_FILE_BASIC_INFO.
6285 ****************************************************************************/
6287 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6291 const struct smb_filename
*smb_fname
)
6293 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6294 struct smb_file_time ft
;
6296 NTSTATUS status
= NT_STATUS_OK
;
6300 if (total_data
< 36) {
6301 return NT_STATUS_INVALID_PARAMETER
;
6304 /* Set the attributes */
6305 dosmode
= IVAL(pdata
,32);
6306 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6307 if (!NT_STATUS_IS_OK(status
)) {
6312 ft
.create_time
= interpret_long_date(pdata
);
6315 ft
.atime
= interpret_long_date(pdata
+8);
6318 ft
.mtime
= interpret_long_date(pdata
+16);
6321 ft
.ctime
= interpret_long_date(pdata
+24);
6323 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6324 smb_fname_str_dbg(smb_fname
)));
6326 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6330 /****************************************************************************
6331 Deal with SMB_INFO_STANDARD.
6332 ****************************************************************************/
6334 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6338 const struct smb_filename
*smb_fname
)
6340 struct smb_file_time ft
;
6344 if (total_data
< 12) {
6345 return NT_STATUS_INVALID_PARAMETER
;
6349 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6351 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6353 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6355 DEBUG(10,("smb_set_info_standard: file %s\n",
6356 smb_fname_str_dbg(smb_fname
)));
6358 return smb_set_file_time(conn
,
6365 /****************************************************************************
6366 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6367 ****************************************************************************/
6369 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6370 struct smb_request
*req
,
6374 struct smb_filename
*smb_fname
)
6376 uint64_t allocation_size
= 0;
6377 NTSTATUS status
= NT_STATUS_OK
;
6378 files_struct
*new_fsp
= NULL
;
6380 if (!VALID_STAT(smb_fname
->st
)) {
6381 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6384 if (total_data
< 8) {
6385 return NT_STATUS_INVALID_PARAMETER
;
6388 allocation_size
= (uint64_t)IVAL(pdata
,0);
6389 #ifdef LARGE_SMB_OFF_T
6390 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6391 #else /* LARGE_SMB_OFF_T */
6392 if (IVAL(pdata
,4) != 0) {
6393 /* more than 32 bits? */
6394 return NT_STATUS_INVALID_PARAMETER
;
6396 #endif /* LARGE_SMB_OFF_T */
6398 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6399 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6400 (double)allocation_size
));
6402 if (allocation_size
) {
6403 allocation_size
= smb_roundup(conn
, allocation_size
);
6406 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6407 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6408 (double)allocation_size
));
6410 if (fsp
&& fsp
->fh
->fd
!= -1) {
6411 /* Open file handle. */
6412 /* Only change if needed. */
6413 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6414 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6415 return map_nt_error_from_unix(errno
);
6418 /* But always update the time. */
6420 * This is equivalent to a write. Ensure it's seen immediately
6421 * if there are no pending writes.
6423 trigger_write_time_update_immediate(fsp
);
6424 return NT_STATUS_OK
;
6427 /* Pathname or stat or directory file. */
6428 status
= SMB_VFS_CREATE_FILE(
6431 0, /* root_dir_fid */
6432 smb_fname
, /* fname */
6433 FILE_WRITE_DATA
, /* access_mask */
6434 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6436 FILE_OPEN
, /* create_disposition*/
6437 0, /* create_options */
6438 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6439 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6440 0, /* allocation_size */
6443 &new_fsp
, /* result */
6446 if (!NT_STATUS_IS_OK(status
)) {
6447 /* NB. We check for open_was_deferred in the caller. */
6451 /* Only change if needed. */
6452 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6453 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6454 status
= map_nt_error_from_unix(errno
);
6455 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6460 /* Changing the allocation size should set the last mod time. */
6462 * This is equivalent to a write. Ensure it's seen immediately
6463 * if there are no pending writes.
6465 trigger_write_time_update_immediate(new_fsp
);
6467 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6468 return NT_STATUS_OK
;
6471 /****************************************************************************
6472 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6473 ****************************************************************************/
6475 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6476 struct smb_request
*req
,
6480 const struct smb_filename
*smb_fname
,
6481 bool fail_after_createfile
)
6485 if (total_data
< 8) {
6486 return NT_STATUS_INVALID_PARAMETER
;
6489 size
= IVAL(pdata
,0);
6490 #ifdef LARGE_SMB_OFF_T
6491 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6492 #else /* LARGE_SMB_OFF_T */
6493 if (IVAL(pdata
,4) != 0) {
6494 /* more than 32 bits? */
6495 return NT_STATUS_INVALID_PARAMETER
;
6497 #endif /* LARGE_SMB_OFF_T */
6498 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6499 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6502 return smb_set_file_size(conn
, req
,
6507 fail_after_createfile
);
6510 /****************************************************************************
6511 Allow a UNIX info mknod.
6512 ****************************************************************************/
6514 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6517 const struct smb_filename
*smb_fname
)
6519 uint32 file_type
= IVAL(pdata
,56);
6520 #if defined(HAVE_MAKEDEV)
6521 uint32 dev_major
= IVAL(pdata
,60);
6522 uint32 dev_minor
= IVAL(pdata
,68);
6524 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6525 uint32 raw_unixmode
= IVAL(pdata
,84);
6529 if (total_data
< 100) {
6530 return NT_STATUS_INVALID_PARAMETER
;
6533 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6534 PERM_NEW_FILE
, &unixmode
);
6535 if (!NT_STATUS_IS_OK(status
)) {
6539 #if defined(HAVE_MAKEDEV)
6540 dev
= makedev(dev_major
, dev_minor
);
6543 switch (file_type
) {
6544 #if defined(S_IFIFO)
6545 case UNIX_TYPE_FIFO
:
6546 unixmode
|= S_IFIFO
;
6549 #if defined(S_IFSOCK)
6550 case UNIX_TYPE_SOCKET
:
6551 unixmode
|= S_IFSOCK
;
6554 #if defined(S_IFCHR)
6555 case UNIX_TYPE_CHARDEV
:
6556 unixmode
|= S_IFCHR
;
6559 #if defined(S_IFBLK)
6560 case UNIX_TYPE_BLKDEV
:
6561 unixmode
|= S_IFBLK
;
6565 return NT_STATUS_INVALID_PARAMETER
;
6568 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6569 "%.0f mode 0%o for file %s\n", (double)dev
,
6570 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6572 /* Ok - do the mknod. */
6573 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6574 return map_nt_error_from_unix(errno
);
6577 /* If any of the other "set" calls fail we
6578 * don't want to end up with a half-constructed mknod.
6581 if (lp_inherit_perms(SNUM(conn
))) {
6583 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6585 return NT_STATUS_NO_MEMORY
;
6587 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6589 TALLOC_FREE(parent
);
6592 return NT_STATUS_OK
;
6595 /****************************************************************************
6596 Deal with SMB_SET_FILE_UNIX_BASIC.
6597 ****************************************************************************/
6599 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6600 struct smb_request
*req
,
6604 const struct smb_filename
*smb_fname
)
6606 struct smb_file_time ft
;
6607 uint32 raw_unixmode
;
6610 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6611 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6612 NTSTATUS status
= NT_STATUS_OK
;
6613 bool delete_on_fail
= False
;
6614 enum perm_type ptype
;
6615 files_struct
*all_fsps
= NULL
;
6616 bool modify_mtime
= true;
6618 SMB_STRUCT_STAT sbuf
;
6622 if (total_data
< 100) {
6623 return NT_STATUS_INVALID_PARAMETER
;
6626 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6627 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6628 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6629 #ifdef LARGE_SMB_OFF_T
6630 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6631 #else /* LARGE_SMB_OFF_T */
6632 if (IVAL(pdata
,4) != 0) {
6633 /* more than 32 bits? */
6634 return NT_STATUS_INVALID_PARAMETER
;
6636 #endif /* LARGE_SMB_OFF_T */
6639 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6640 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6641 set_owner
= (uid_t
)IVAL(pdata
,40);
6642 set_grp
= (gid_t
)IVAL(pdata
,48);
6643 raw_unixmode
= IVAL(pdata
,84);
6645 if (VALID_STAT(smb_fname
->st
)) {
6646 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6647 ptype
= PERM_EXISTING_DIR
;
6649 ptype
= PERM_EXISTING_FILE
;
6652 ptype
= PERM_NEW_FILE
;
6655 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6657 if (!NT_STATUS_IS_OK(status
)) {
6661 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6662 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6663 smb_fname_str_dbg(smb_fname
), (double)size
,
6664 (unsigned int)set_owner
, (unsigned int)set_grp
,
6665 (int)raw_unixmode
));
6667 sbuf
= smb_fname
->st
;
6669 if (!VALID_STAT(sbuf
)) {
6670 struct smb_filename
*smb_fname_tmp
= NULL
;
6672 * The only valid use of this is to create character and block
6673 * devices, and named pipes. This is deprecated (IMHO) and
6674 * a new info level should be used for mknod. JRA.
6677 status
= smb_unix_mknod(conn
,
6681 if (!NT_STATUS_IS_OK(status
)) {
6685 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6687 if (!NT_STATUS_IS_OK(status
)) {
6691 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6692 status
= map_nt_error_from_unix(errno
);
6693 TALLOC_FREE(smb_fname_tmp
);
6694 SMB_VFS_UNLINK(conn
, smb_fname
);
6698 sbuf
= smb_fname_tmp
->st
;
6699 TALLOC_FREE(smb_fname_tmp
);
6701 /* Ensure we don't try and change anything else. */
6702 raw_unixmode
= SMB_MODE_NO_CHANGE
;
6703 size
= get_file_size_stat(&sbuf
);
6704 ft
.atime
= sbuf
.st_ex_atime
;
6705 ft
.mtime
= sbuf
.st_ex_mtime
;
6707 * We continue here as we might want to change the
6710 delete_on_fail
= True
;
6714 /* Horrible backwards compatibility hack as an old server bug
6715 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6719 size
= get_file_size_stat(&sbuf
);
6724 * Deal with the UNIX specific mode set.
6727 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
6728 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6729 "setting mode 0%o for file %s\n",
6730 (unsigned int)unixmode
,
6731 smb_fname_str_dbg(smb_fname
)));
6732 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
6733 return map_nt_error_from_unix(errno
);
6738 * Deal with the UNIX specific uid set.
6741 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6742 (sbuf
.st_ex_uid
!= set_owner
)) {
6745 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6746 "changing owner %u for path %s\n",
6747 (unsigned int)set_owner
,
6748 smb_fname_str_dbg(smb_fname
)));
6750 if (S_ISLNK(sbuf
.st_ex_mode
)) {
6751 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
6752 set_owner
, (gid_t
)-1);
6754 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
6755 set_owner
, (gid_t
)-1);
6759 status
= map_nt_error_from_unix(errno
);
6760 if (delete_on_fail
) {
6761 SMB_VFS_UNLINK(conn
, smb_fname
);
6768 * Deal with the UNIX specific gid set.
6771 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6772 (sbuf
.st_ex_gid
!= set_grp
)) {
6773 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6774 "changing group %u for file %s\n",
6775 (unsigned int)set_owner
,
6776 smb_fname_str_dbg(smb_fname
)));
6777 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
6779 status
= map_nt_error_from_unix(errno
);
6780 if (delete_on_fail
) {
6781 SMB_VFS_UNLINK(conn
, smb_fname
);
6787 /* Deal with any size changes. */
6789 status
= smb_set_file_size(conn
, req
,
6795 if (!NT_STATUS_IS_OK(status
)) {
6799 /* Deal with any time changes. */
6800 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
6801 /* No change, don't cancel anything. */
6805 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6806 for(all_fsps
= file_find_di_first(id
); all_fsps
;
6807 all_fsps
= file_find_di_next(all_fsps
)) {
6809 * We're setting the time explicitly for UNIX.
6810 * Cancel any pending changes over all handles.
6812 all_fsps
->update_write_time_on_close
= false;
6813 TALLOC_FREE(all_fsps
->update_write_time_event
);
6817 * Override the "setting_write_time"
6818 * parameter here as it almost does what
6819 * we need. Just remember if we modified
6820 * mtime and send the notify ourselves.
6822 if (null_timespec(ft
.mtime
)) {
6823 modify_mtime
= false;
6826 status
= smb_set_file_time(conn
,
6832 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6833 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6838 /****************************************************************************
6839 Deal with SMB_SET_FILE_UNIX_INFO2.
6840 ****************************************************************************/
6842 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6843 struct smb_request
*req
,
6847 const struct smb_filename
*smb_fname
)
6853 if (total_data
< 116) {
6854 return NT_STATUS_INVALID_PARAMETER
;
6857 /* Start by setting all the fields that are common between UNIX_BASIC
6860 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6862 if (!NT_STATUS_IS_OK(status
)) {
6866 smb_fflags
= IVAL(pdata
, 108);
6867 smb_fmask
= IVAL(pdata
, 112);
6869 /* NB: We should only attempt to alter the file flags if the client
6870 * sends a non-zero mask.
6872 if (smb_fmask
!= 0) {
6873 int stat_fflags
= 0;
6875 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6876 smb_fmask
, &stat_fflags
)) {
6877 /* Client asked to alter a flag we don't understand. */
6878 return NT_STATUS_INVALID_PARAMETER
;
6881 if (fsp
&& fsp
->fh
->fd
!= -1) {
6882 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6883 return NT_STATUS_NOT_SUPPORTED
;
6885 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
6886 stat_fflags
) != 0) {
6887 return map_nt_error_from_unix(errno
);
6892 /* XXX: need to add support for changing the create_time here. You
6893 * can do this for paths on Darwin with setattrlist(2). The right way
6894 * to hook this up is probably by extending the VFS utimes interface.
6897 return NT_STATUS_OK
;
6900 /****************************************************************************
6901 Create a directory with POSIX semantics.
6902 ****************************************************************************/
6904 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6905 struct smb_request
*req
,
6908 struct smb_filename
*smb_fname
,
6909 int *pdata_return_size
)
6911 NTSTATUS status
= NT_STATUS_OK
;
6912 uint32 raw_unixmode
= 0;
6913 uint32 mod_unixmode
= 0;
6914 mode_t unixmode
= (mode_t
)0;
6915 files_struct
*fsp
= NULL
;
6916 uint16 info_level_return
= 0;
6918 char *pdata
= *ppdata
;
6920 if (total_data
< 18) {
6921 return NT_STATUS_INVALID_PARAMETER
;
6924 raw_unixmode
= IVAL(pdata
,8);
6925 /* Next 4 bytes are not yet defined. */
6927 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6928 PERM_NEW_DIR
, &unixmode
);
6929 if (!NT_STATUS_IS_OK(status
)) {
6933 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6935 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6936 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6938 status
= SMB_VFS_CREATE_FILE(
6941 0, /* root_dir_fid */
6942 smb_fname
, /* fname */
6943 FILE_READ_ATTRIBUTES
, /* access_mask */
6944 FILE_SHARE_NONE
, /* share_access */
6945 FILE_CREATE
, /* create_disposition*/
6946 FILE_DIRECTORY_FILE
, /* create_options */
6947 mod_unixmode
, /* file_attributes */
6948 0, /* oplock_request */
6949 0, /* allocation_size */
6955 if (NT_STATUS_IS_OK(status
)) {
6956 close_file(req
, fsp
, NORMAL_CLOSE
);
6959 info_level_return
= SVAL(pdata
,16);
6961 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6962 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6963 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6964 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6966 *pdata_return_size
= 12;
6969 /* Realloc the data size */
6970 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6971 if (*ppdata
== NULL
) {
6972 *pdata_return_size
= 0;
6973 return NT_STATUS_NO_MEMORY
;
6977 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6978 SSVAL(pdata
,2,0); /* No fnum. */
6979 SIVAL(pdata
,4,info
); /* Was directory created. */
6981 switch (info_level_return
) {
6982 case SMB_QUERY_FILE_UNIX_BASIC
:
6983 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6984 SSVAL(pdata
,10,0); /* Padding. */
6985 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6988 case SMB_QUERY_FILE_UNIX_INFO2
:
6989 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6990 SSVAL(pdata
,10,0); /* Padding. */
6991 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6995 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6996 SSVAL(pdata
,10,0); /* Padding. */
7003 /****************************************************************************
7004 Open/Create a file with POSIX semantics.
7005 ****************************************************************************/
7007 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7008 struct smb_request
*req
,
7011 struct smb_filename
*smb_fname
,
7012 int *pdata_return_size
)
7014 bool extended_oplock_granted
= False
;
7015 char *pdata
= *ppdata
;
7017 uint32 wire_open_mode
= 0;
7018 uint32 raw_unixmode
= 0;
7019 uint32 mod_unixmode
= 0;
7020 uint32 create_disp
= 0;
7021 uint32 access_mask
= 0;
7022 uint32 create_options
= 0;
7023 NTSTATUS status
= NT_STATUS_OK
;
7024 mode_t unixmode
= (mode_t
)0;
7025 files_struct
*fsp
= NULL
;
7026 int oplock_request
= 0;
7028 uint16 info_level_return
= 0;
7030 if (total_data
< 18) {
7031 return NT_STATUS_INVALID_PARAMETER
;
7034 flags
= IVAL(pdata
,0);
7035 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7036 if (oplock_request
) {
7037 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7040 wire_open_mode
= IVAL(pdata
,4);
7042 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7043 return smb_posix_mkdir(conn
, req
,
7050 switch (wire_open_mode
& SMB_ACCMODE
) {
7052 access_mask
= FILE_READ_DATA
;
7055 access_mask
= FILE_WRITE_DATA
;
7058 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
7061 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7062 (unsigned int)wire_open_mode
));
7063 return NT_STATUS_INVALID_PARAMETER
;
7066 wire_open_mode
&= ~SMB_ACCMODE
;
7068 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
7069 create_disp
= FILE_CREATE
;
7070 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
7071 create_disp
= FILE_OVERWRITE_IF
;
7072 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
7073 create_disp
= FILE_OPEN_IF
;
7074 } else if ((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
| SMB_O_TRUNC
)) == 0) {
7075 create_disp
= FILE_OPEN
;
7077 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7078 (unsigned int)wire_open_mode
));
7079 return NT_STATUS_INVALID_PARAMETER
;
7082 raw_unixmode
= IVAL(pdata
,8);
7083 /* Next 4 bytes are not yet defined. */
7085 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7086 (VALID_STAT(smb_fname
->st
) ?
7087 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7090 if (!NT_STATUS_IS_OK(status
)) {
7094 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7096 if (wire_open_mode
& SMB_O_SYNC
) {
7097 create_options
|= FILE_WRITE_THROUGH
;
7099 if (wire_open_mode
& SMB_O_APPEND
) {
7100 access_mask
|= FILE_APPEND_DATA
;
7102 if (wire_open_mode
& SMB_O_DIRECT
) {
7103 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7106 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7107 smb_fname_str_dbg(smb_fname
),
7108 (unsigned int)wire_open_mode
,
7109 (unsigned int)unixmode
));
7111 status
= SMB_VFS_CREATE_FILE(
7114 0, /* root_dir_fid */
7115 smb_fname
, /* fname */
7116 access_mask
, /* access_mask */
7117 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7119 create_disp
, /* create_disposition*/
7120 FILE_NON_DIRECTORY_FILE
, /* create_options */
7121 mod_unixmode
, /* file_attributes */
7122 oplock_request
, /* oplock_request */
7123 0, /* allocation_size */
7129 if (!NT_STATUS_IS_OK(status
)) {
7133 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7134 extended_oplock_granted
= True
;
7137 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7138 extended_oplock_granted
= True
;
7141 info_level_return
= SVAL(pdata
,16);
7143 /* Allocate the correct return size. */
7145 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7146 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7147 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7148 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7150 *pdata_return_size
= 12;
7153 /* Realloc the data size */
7154 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7155 if (*ppdata
== NULL
) {
7156 close_file(req
, fsp
, ERROR_CLOSE
);
7157 *pdata_return_size
= 0;
7158 return NT_STATUS_NO_MEMORY
;
7162 if (extended_oplock_granted
) {
7163 if (flags
& REQUEST_BATCH_OPLOCK
) {
7164 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7166 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7168 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7169 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7171 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7174 SSVAL(pdata
,2,fsp
->fnum
);
7175 SIVAL(pdata
,4,info
); /* Was file created etc. */
7177 switch (info_level_return
) {
7178 case SMB_QUERY_FILE_UNIX_BASIC
:
7179 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7180 SSVAL(pdata
,10,0); /* padding. */
7181 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7184 case SMB_QUERY_FILE_UNIX_INFO2
:
7185 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7186 SSVAL(pdata
,10,0); /* padding. */
7187 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7191 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7192 SSVAL(pdata
,10,0); /* padding. */
7195 return NT_STATUS_OK
;
7198 /****************************************************************************
7199 Delete a file with POSIX semantics.
7200 ****************************************************************************/
7202 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7203 struct smb_request
*req
,
7206 struct smb_filename
*smb_fname
)
7208 NTSTATUS status
= NT_STATUS_OK
;
7209 files_struct
*fsp
= NULL
;
7213 int create_options
= 0;
7215 struct share_mode_lock
*lck
= NULL
;
7217 if (total_data
< 2) {
7218 return NT_STATUS_INVALID_PARAMETER
;
7221 flags
= SVAL(pdata
,0);
7223 if (!VALID_STAT(smb_fname
->st
)) {
7224 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7227 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7228 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7229 return NT_STATUS_NOT_A_DIRECTORY
;
7232 DEBUG(10,("smb_posix_unlink: %s %s\n",
7233 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7234 smb_fname_str_dbg(smb_fname
)));
7236 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7237 create_options
|= FILE_DIRECTORY_FILE
;
7240 status
= SMB_VFS_CREATE_FILE(
7243 0, /* root_dir_fid */
7244 smb_fname
, /* fname */
7245 DELETE_ACCESS
, /* access_mask */
7246 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7248 FILE_OPEN
, /* create_disposition*/
7249 create_options
, /* create_options */
7250 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7251 0, /* oplock_request */
7252 0, /* allocation_size */
7258 if (!NT_STATUS_IS_OK(status
)) {
7263 * Don't lie to client. If we can't really delete due to
7264 * non-POSIX opens return SHARING_VIOLATION.
7267 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7270 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7271 "lock for file %s\n", fsp_str_dbg(fsp
)));
7272 close_file(req
, fsp
, NORMAL_CLOSE
);
7273 return NT_STATUS_INVALID_PARAMETER
;
7277 * See if others still have the file open. If this is the case, then
7278 * don't delete. If all opens are POSIX delete we can set the delete
7279 * on close disposition.
7281 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7282 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7283 if (is_valid_share_mode_entry(e
)) {
7284 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7287 /* Fail with sharing violation. */
7288 close_file(req
, fsp
, NORMAL_CLOSE
);
7290 return NT_STATUS_SHARING_VIOLATION
;
7295 * Set the delete on close.
7297 status
= smb_set_file_disposition_info(conn
,
7303 if (!NT_STATUS_IS_OK(status
)) {
7304 close_file(req
, fsp
, NORMAL_CLOSE
);
7309 return close_file(req
, fsp
, NORMAL_CLOSE
);
7312 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7313 struct smb_request
*req
,
7314 TALLOC_CTX
*mem_ctx
,
7315 uint16_t info_level
,
7317 struct smb_filename
*smb_fname
,
7318 char **ppdata
, int total_data
,
7321 char *pdata
= *ppdata
;
7322 NTSTATUS status
= NT_STATUS_OK
;
7323 int data_return_size
= 0;
7327 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7328 return NT_STATUS_INVALID_LEVEL
;
7331 if (!CAN_WRITE(conn
)) {
7332 /* Allow POSIX opens. The open path will deny
7333 * any non-readonly opens. */
7334 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7335 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7339 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7340 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7341 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7343 switch (info_level
) {
7345 case SMB_INFO_STANDARD
:
7347 status
= smb_set_info_standard(conn
,
7355 case SMB_INFO_SET_EA
:
7357 status
= smb_info_set_ea(conn
,
7365 case SMB_SET_FILE_BASIC_INFO
:
7366 case SMB_FILE_BASIC_INFORMATION
:
7368 status
= smb_set_file_basic_info(conn
,
7376 case SMB_FILE_ALLOCATION_INFORMATION
:
7377 case SMB_SET_FILE_ALLOCATION_INFO
:
7379 status
= smb_set_file_allocation_info(conn
, req
,
7387 case SMB_FILE_END_OF_FILE_INFORMATION
:
7388 case SMB_SET_FILE_END_OF_FILE_INFO
:
7391 * XP/Win7 both fail after the createfile with
7392 * SMB_SET_FILE_END_OF_FILE_INFO but not
7393 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7394 * The level is known here, so pass it down
7398 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7400 status
= smb_set_file_end_of_file_info(conn
, req
,
7409 case SMB_FILE_DISPOSITION_INFORMATION
:
7410 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7413 /* JRA - We used to just ignore this on a path ?
7414 * Shouldn't this be invalid level on a pathname
7417 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7418 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7421 status
= smb_set_file_disposition_info(conn
,
7429 case SMB_FILE_POSITION_INFORMATION
:
7431 status
= smb_file_position_information(conn
,
7438 case SMB_FILE_FULL_EA_INFORMATION
:
7440 status
= smb_set_file_full_ea_info(conn
,
7447 /* From tridge Samba4 :
7448 * MODE_INFORMATION in setfileinfo (I have no
7449 * idea what "mode information" on a file is - it takes a value of 0,
7450 * 2, 4 or 6. What could it be?).
7453 case SMB_FILE_MODE_INFORMATION
:
7455 status
= smb_file_mode_information(conn
,
7462 * CIFS UNIX extensions.
7465 case SMB_SET_FILE_UNIX_BASIC
:
7467 status
= smb_set_file_unix_basic(conn
, req
,
7475 case SMB_SET_FILE_UNIX_INFO2
:
7477 status
= smb_set_file_unix_info2(conn
, req
,
7485 case SMB_SET_FILE_UNIX_LINK
:
7488 /* We must have a pathname for this. */
7489 return NT_STATUS_INVALID_LEVEL
;
7491 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7492 total_data
, smb_fname
);
7496 case SMB_SET_FILE_UNIX_HLINK
:
7499 /* We must have a pathname for this. */
7500 return NT_STATUS_INVALID_LEVEL
;
7502 status
= smb_set_file_unix_hlink(conn
, req
,
7508 case SMB_FILE_RENAME_INFORMATION
:
7510 status
= smb_file_rename_information(conn
, req
,
7516 #if defined(HAVE_POSIX_ACLS)
7517 case SMB_SET_POSIX_ACL
:
7519 status
= smb_set_posix_acl(conn
,
7528 case SMB_SET_POSIX_LOCK
:
7531 return NT_STATUS_INVALID_LEVEL
;
7533 status
= smb_set_posix_lock(conn
, req
,
7534 pdata
, total_data
, fsp
);
7538 case SMB_POSIX_PATH_OPEN
:
7541 /* We must have a pathname for this. */
7542 return NT_STATUS_INVALID_LEVEL
;
7545 status
= smb_posix_open(conn
, req
,
7553 case SMB_POSIX_PATH_UNLINK
:
7556 /* We must have a pathname for this. */
7557 return NT_STATUS_INVALID_LEVEL
;
7560 status
= smb_posix_unlink(conn
, req
,
7568 return NT_STATUS_INVALID_LEVEL
;
7571 if (!NT_STATUS_IS_OK(status
)) {
7575 *ret_data_size
= data_return_size
;
7576 return NT_STATUS_OK
;
7579 /****************************************************************************
7580 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7581 ****************************************************************************/
7583 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7584 struct smb_request
*req
,
7585 unsigned int tran_call
,
7586 char **pparams
, int total_params
,
7587 char **ppdata
, int total_data
,
7588 unsigned int max_data_bytes
)
7590 char *params
= *pparams
;
7591 char *pdata
= *ppdata
;
7593 struct smb_filename
*smb_fname
= NULL
;
7594 files_struct
*fsp
= NULL
;
7595 NTSTATUS status
= NT_STATUS_OK
;
7596 int data_return_size
= 0;
7599 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7603 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7604 if (total_params
< 4) {
7605 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7609 fsp
= file_fsp(req
, SVAL(params
,0));
7610 /* Basic check for non-null fsp. */
7611 if (!check_fsp_open(conn
, req
, fsp
)) {
7614 info_level
= SVAL(params
,2);
7616 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7618 if (!NT_STATUS_IS_OK(status
)) {
7619 reply_nterror(req
, status
);
7623 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
7625 * This is actually a SETFILEINFO on a directory
7626 * handle (returned from an NT SMB). NT5.0 seems
7627 * to do this call. JRA.
7629 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7630 /* Always do lstat for UNIX calls. */
7631 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
7632 DEBUG(3,("call_trans2setfilepathinfo: "
7633 "SMB_VFS_LSTAT of %s failed "
7635 smb_fname_str_dbg(smb_fname
),
7637 reply_nterror(req
, map_nt_error_from_unix(errno
));
7641 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
7642 DEBUG(3,("call_trans2setfilepathinfo: "
7643 "fileinfo of %s failed (%s)\n",
7644 smb_fname_str_dbg(smb_fname
),
7646 reply_nterror(req
, map_nt_error_from_unix(errno
));
7650 } else if (fsp
->print_file
) {
7652 * Doing a DELETE_ON_CLOSE should cancel a print job.
7654 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
7655 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
7657 DEBUG(3,("call_trans2setfilepathinfo: "
7658 "Cancelling print job (%s)\n",
7662 send_trans2_replies(conn
, req
, params
, 2,
7667 reply_doserror(req
, ERRDOS
, ERRbadpath
);
7672 * Original code - this is an open file.
7674 if (!check_fsp(conn
, req
, fsp
)) {
7678 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
7679 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7680 "of fnum %d failed (%s)\n", fsp
->fnum
,
7682 reply_nterror(req
, map_nt_error_from_unix(errno
));
7690 if (total_params
< 7) {
7691 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7695 info_level
= SVAL(params
,0);
7696 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
7697 total_params
- 6, STR_TERMINATE
,
7699 if (!NT_STATUS_IS_OK(status
)) {
7700 reply_nterror(req
, status
);
7704 status
= filename_convert(req
, conn
,
7705 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7710 if (!NT_STATUS_IS_OK(status
)) {
7711 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7712 reply_botherror(req
,
7713 NT_STATUS_PATH_NOT_COVERED
,
7714 ERRSRV
, ERRbadpath
);
7717 reply_nterror(req
, status
);
7721 if (INFO_LEVEL_IS_UNIX(info_level
)) {
7723 * For CIFS UNIX extensions the target name may not exist.
7726 /* Always do lstat for UNIX calls. */
7727 SMB_VFS_LSTAT(conn
, smb_fname
);
7729 } else if (!VALID_STAT(smb_fname
->st
) &&
7730 SMB_VFS_STAT(conn
, smb_fname
)) {
7731 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7733 smb_fname_str_dbg(smb_fname
),
7735 reply_nterror(req
, map_nt_error_from_unix(errno
));
7740 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7741 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
7742 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
7744 /* Realloc the parameter size */
7745 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7746 if (*pparams
== NULL
) {
7747 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7754 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
7760 if (!NT_STATUS_IS_OK(status
)) {
7761 if (open_was_deferred(req
->mid
)) {
7762 /* We have re-scheduled this call. */
7765 if (blocking_lock_was_deferred(req
->mid
)) {
7766 /* We have re-scheduled this call. */
7769 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7770 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7771 ERRSRV
, ERRbadpath
);
7774 if (info_level
== SMB_POSIX_PATH_OPEN
) {
7775 reply_openerror(req
, status
);
7779 reply_nterror(req
, status
);
7783 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
7789 /****************************************************************************
7790 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7791 ****************************************************************************/
7793 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
7794 char **pparams
, int total_params
,
7795 char **ppdata
, int total_data
,
7796 unsigned int max_data_bytes
)
7798 struct smb_filename
*smb_dname
= NULL
;
7799 char *params
= *pparams
;
7800 char *pdata
= *ppdata
;
7801 char *directory
= NULL
;
7802 NTSTATUS status
= NT_STATUS_OK
;
7803 struct ea_list
*ea_list
= NULL
;
7804 TALLOC_CTX
*ctx
= talloc_tos();
7806 if (!CAN_WRITE(conn
)) {
7807 reply_doserror(req
, ERRSRV
, ERRaccess
);
7811 if (total_params
< 5) {
7812 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7816 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
7817 total_params
- 4, STR_TERMINATE
,
7819 if (!NT_STATUS_IS_OK(status
)) {
7820 reply_nterror(req
, status
);
7824 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
7826 status
= filename_convert(ctx
,
7828 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7834 if (!NT_STATUS_IS_OK(status
)) {
7835 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7836 reply_botherror(req
,
7837 NT_STATUS_PATH_NOT_COVERED
,
7838 ERRSRV
, ERRbadpath
);
7841 reply_nterror(req
, status
);
7845 /* Any data in this call is an EA list. */
7846 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
7847 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
7852 * OS/2 workplace shell seems to send SET_EA requests of "null"
7853 * length (4 bytes containing IVAL 4).
7854 * They seem to have no effect. Bug #3212. JRA.
7857 if (total_data
!= 4) {
7858 if (total_data
< 10) {
7859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7863 if (IVAL(pdata
,0) > total_data
) {
7864 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7865 IVAL(pdata
,0), (unsigned int)total_data
));
7866 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7870 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
7873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7877 /* If total_data == 4 Windows doesn't care what values
7878 * are placed in that field, it just ignores them.
7879 * The System i QNTC IBM SMB client puts bad values here,
7880 * so ignore them. */
7882 status
= create_directory(conn
, req
, smb_dname
);
7884 if (!NT_STATUS_IS_OK(status
)) {
7885 reply_nterror(req
, status
);
7889 /* Try and set any given EA. */
7891 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
7892 if (!NT_STATUS_IS_OK(status
)) {
7893 reply_nterror(req
, status
);
7898 /* Realloc the parameter and data sizes */
7899 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
7900 if(*pparams
== NULL
) {
7901 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7908 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
7911 TALLOC_FREE(smb_dname
);
7915 /****************************************************************************
7916 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7917 We don't actually do this - we just send a null response.
7918 ****************************************************************************/
7920 static void call_trans2findnotifyfirst(connection_struct
*conn
,
7921 struct smb_request
*req
,
7922 char **pparams
, int total_params
,
7923 char **ppdata
, int total_data
,
7924 unsigned int max_data_bytes
)
7926 char *params
= *pparams
;
7929 if (total_params
< 6) {
7930 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7934 info_level
= SVAL(params
,4);
7935 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
7937 switch (info_level
) {
7942 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
7946 /* Realloc the parameter and data sizes */
7947 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
7948 if (*pparams
== NULL
) {
7949 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7954 SSVAL(params
,0,fnf_handle
);
7955 SSVAL(params
,2,0); /* No changes */
7956 SSVAL(params
,4,0); /* No EA errors */
7963 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
7968 /****************************************************************************
7969 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7970 changes). Currently this does nothing.
7971 ****************************************************************************/
7973 static void call_trans2findnotifynext(connection_struct
*conn
,
7974 struct smb_request
*req
,
7975 char **pparams
, int total_params
,
7976 char **ppdata
, int total_data
,
7977 unsigned int max_data_bytes
)
7979 char *params
= *pparams
;
7981 DEBUG(3,("call_trans2findnotifynext\n"));
7983 /* Realloc the parameter and data sizes */
7984 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
7985 if (*pparams
== NULL
) {
7986 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7991 SSVAL(params
,0,0); /* No changes */
7992 SSVAL(params
,2,0); /* No EA errors */
7994 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
7999 /****************************************************************************
8000 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8001 ****************************************************************************/
8003 static void call_trans2getdfsreferral(connection_struct
*conn
,
8004 struct smb_request
*req
,
8005 char **pparams
, int total_params
,
8006 char **ppdata
, int total_data
,
8007 unsigned int max_data_bytes
)
8009 char *params
= *pparams
;
8010 char *pathname
= NULL
;
8012 int max_referral_level
;
8013 NTSTATUS status
= NT_STATUS_OK
;
8014 TALLOC_CTX
*ctx
= talloc_tos();
8016 DEBUG(10,("call_trans2getdfsreferral\n"));
8018 if (total_params
< 3) {
8019 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8023 max_referral_level
= SVAL(params
,0);
8025 if(!lp_host_msdfs()) {
8026 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
8030 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8031 total_params
- 2, STR_TERMINATE
);
8033 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8036 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8037 ppdata
,&status
)) < 0) {
8038 reply_nterror(req
, status
);
8042 SSVAL(req
->inbuf
, smb_flg2
,
8043 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8044 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8049 #define LMCAT_SPL 0x53
8050 #define LMFUNC_GETJOBID 0x60
8052 /****************************************************************************
8053 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8054 ****************************************************************************/
8056 static void call_trans2ioctl(connection_struct
*conn
,
8057 struct smb_request
*req
,
8058 char **pparams
, int total_params
,
8059 char **ppdata
, int total_data
,
8060 unsigned int max_data_bytes
)
8062 char *pdata
= *ppdata
;
8063 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8065 /* check for an invalid fid before proceeding */
8068 reply_doserror(req
, ERRDOS
, ERRbadfid
);
8072 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8073 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8074 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8075 if (*ppdata
== NULL
) {
8076 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8081 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8082 CAN ACCEPT THIS IN UNICODE. JRA. */
8084 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
8085 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8086 global_myname(), 15,
8087 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8088 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8089 lp_servicename(SNUM(conn
)), 13,
8090 STR_ASCII
|STR_TERMINATE
); /* Service name */
8091 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8096 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8097 reply_doserror(req
, ERRSRV
, ERRerror
);
8100 /****************************************************************************
8101 Reply to a SMBfindclose (stop trans2 directory search).
8102 ****************************************************************************/
8104 void reply_findclose(struct smb_request
*req
)
8107 struct smbd_server_connection
*sconn
= smbd_server_conn
;
8109 START_PROFILE(SMBfindclose
);
8112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8113 END_PROFILE(SMBfindclose
);
8117 dptr_num
= SVALS(req
->vwv
+0, 0);
8119 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8121 dptr_close(sconn
, &dptr_num
);
8123 reply_outbuf(req
, 0, 0);
8125 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8127 END_PROFILE(SMBfindclose
);
8131 /****************************************************************************
8132 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8133 ****************************************************************************/
8135 void reply_findnclose(struct smb_request
*req
)
8139 START_PROFILE(SMBfindnclose
);
8142 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8143 END_PROFILE(SMBfindnclose
);
8147 dptr_num
= SVAL(req
->vwv
+0, 0);
8149 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8151 /* We never give out valid handles for a
8152 findnotifyfirst - so any dptr_num is ok here.
8155 reply_outbuf(req
, 0, 0);
8157 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8159 END_PROFILE(SMBfindnclose
);
8163 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8164 struct trans_state
*state
)
8166 if (get_Protocol() >= PROTOCOL_NT1
) {
8167 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8168 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8171 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8172 if (state
->call
!= TRANSACT2_QFSINFO
&&
8173 state
->call
!= TRANSACT2_SETFSINFO
) {
8174 DEBUG(0,("handle_trans2: encryption required "
8176 (unsigned int)state
->call
));
8177 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8182 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8184 /* Now we must call the relevant TRANS2 function */
8185 switch(state
->call
) {
8186 case TRANSACT2_OPEN
:
8188 START_PROFILE(Trans2_open
);
8189 call_trans2open(conn
, req
,
8190 &state
->param
, state
->total_param
,
8191 &state
->data
, state
->total_data
,
8192 state
->max_data_return
);
8193 END_PROFILE(Trans2_open
);
8197 case TRANSACT2_FINDFIRST
:
8199 START_PROFILE(Trans2_findfirst
);
8200 call_trans2findfirst(conn
, req
,
8201 &state
->param
, state
->total_param
,
8202 &state
->data
, state
->total_data
,
8203 state
->max_data_return
);
8204 END_PROFILE(Trans2_findfirst
);
8208 case TRANSACT2_FINDNEXT
:
8210 START_PROFILE(Trans2_findnext
);
8211 call_trans2findnext(conn
, req
,
8212 &state
->param
, state
->total_param
,
8213 &state
->data
, state
->total_data
,
8214 state
->max_data_return
);
8215 END_PROFILE(Trans2_findnext
);
8219 case TRANSACT2_QFSINFO
:
8221 START_PROFILE(Trans2_qfsinfo
);
8222 call_trans2qfsinfo(conn
, req
,
8223 &state
->param
, state
->total_param
,
8224 &state
->data
, state
->total_data
,
8225 state
->max_data_return
);
8226 END_PROFILE(Trans2_qfsinfo
);
8230 case TRANSACT2_SETFSINFO
:
8232 START_PROFILE(Trans2_setfsinfo
);
8233 call_trans2setfsinfo(conn
, req
,
8234 &state
->param
, state
->total_param
,
8235 &state
->data
, state
->total_data
,
8236 state
->max_data_return
);
8237 END_PROFILE(Trans2_setfsinfo
);
8241 case TRANSACT2_QPATHINFO
:
8242 case TRANSACT2_QFILEINFO
:
8244 START_PROFILE(Trans2_qpathinfo
);
8245 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8246 &state
->param
, state
->total_param
,
8247 &state
->data
, state
->total_data
,
8248 state
->max_data_return
);
8249 END_PROFILE(Trans2_qpathinfo
);
8253 case TRANSACT2_SETPATHINFO
:
8254 case TRANSACT2_SETFILEINFO
:
8256 START_PROFILE(Trans2_setpathinfo
);
8257 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8258 &state
->param
, state
->total_param
,
8259 &state
->data
, state
->total_data
,
8260 state
->max_data_return
);
8261 END_PROFILE(Trans2_setpathinfo
);
8265 case TRANSACT2_FINDNOTIFYFIRST
:
8267 START_PROFILE(Trans2_findnotifyfirst
);
8268 call_trans2findnotifyfirst(conn
, req
,
8269 &state
->param
, state
->total_param
,
8270 &state
->data
, state
->total_data
,
8271 state
->max_data_return
);
8272 END_PROFILE(Trans2_findnotifyfirst
);
8276 case TRANSACT2_FINDNOTIFYNEXT
:
8278 START_PROFILE(Trans2_findnotifynext
);
8279 call_trans2findnotifynext(conn
, req
,
8280 &state
->param
, state
->total_param
,
8281 &state
->data
, state
->total_data
,
8282 state
->max_data_return
);
8283 END_PROFILE(Trans2_findnotifynext
);
8287 case TRANSACT2_MKDIR
:
8289 START_PROFILE(Trans2_mkdir
);
8290 call_trans2mkdir(conn
, req
,
8291 &state
->param
, state
->total_param
,
8292 &state
->data
, state
->total_data
,
8293 state
->max_data_return
);
8294 END_PROFILE(Trans2_mkdir
);
8298 case TRANSACT2_GET_DFS_REFERRAL
:
8300 START_PROFILE(Trans2_get_dfs_referral
);
8301 call_trans2getdfsreferral(conn
, req
,
8302 &state
->param
, state
->total_param
,
8303 &state
->data
, state
->total_data
,
8304 state
->max_data_return
);
8305 END_PROFILE(Trans2_get_dfs_referral
);
8309 case TRANSACT2_IOCTL
:
8311 START_PROFILE(Trans2_ioctl
);
8312 call_trans2ioctl(conn
, req
,
8313 &state
->param
, state
->total_param
,
8314 &state
->data
, state
->total_data
,
8315 state
->max_data_return
);
8316 END_PROFILE(Trans2_ioctl
);
8321 /* Error in request */
8322 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8323 reply_doserror(req
, ERRSRV
,ERRerror
);
8327 /****************************************************************************
8328 Reply to a SMBtrans2.
8329 ****************************************************************************/
8331 void reply_trans2(struct smb_request
*req
)
8333 connection_struct
*conn
= req
->conn
;
8338 unsigned int tran_call
;
8339 struct trans_state
*state
;
8342 START_PROFILE(SMBtrans2
);
8344 if (req
->wct
< 14) {
8345 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8346 END_PROFILE(SMBtrans2
);
8350 dsoff
= SVAL(req
->vwv
+12, 0);
8351 dscnt
= SVAL(req
->vwv
+11, 0);
8352 psoff
= SVAL(req
->vwv
+10, 0);
8353 pscnt
= SVAL(req
->vwv
+9, 0);
8354 tran_call
= SVAL(req
->vwv
+14, 0);
8356 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8357 if (!NT_STATUS_IS_OK(result
)) {
8358 DEBUG(2, ("Got invalid trans2 request: %s\n",
8359 nt_errstr(result
)));
8360 reply_nterror(req
, result
);
8361 END_PROFILE(SMBtrans2
);
8366 switch (tran_call
) {
8367 /* List the allowed trans2 calls on IPC$ */
8368 case TRANSACT2_OPEN
:
8369 case TRANSACT2_GET_DFS_REFERRAL
:
8370 case TRANSACT2_QFILEINFO
:
8371 case TRANSACT2_QFSINFO
:
8372 case TRANSACT2_SETFSINFO
:
8375 reply_doserror(req
, ERRSRV
, ERRaccess
);
8376 END_PROFILE(SMBtrans2
);
8381 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8382 DEBUG(0, ("talloc failed\n"));
8383 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8384 END_PROFILE(SMBtrans2
);
8388 state
->cmd
= SMBtrans2
;
8390 state
->mid
= req
->mid
;
8391 state
->vuid
= req
->vuid
;
8392 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8393 state
->setup
= NULL
;
8394 state
->total_param
= SVAL(req
->vwv
+0, 0);
8395 state
->param
= NULL
;
8396 state
->total_data
= SVAL(req
->vwv
+1, 0);
8398 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8399 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8400 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8401 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8402 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8404 state
->call
= tran_call
;
8406 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8407 is so as a sanity check */
8408 if (state
->setup_count
!= 1) {
8410 * Need to have rc=0 for ioctl to get job id for OS/2.
8411 * Network printing will fail if function is not successful.
8412 * Similar function in reply.c will be used if protocol
8413 * is LANMAN1.0 instead of LM1.2X002.
8414 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8415 * outbuf doesn't have to be set(only job id is used).
8417 if ( (state
->setup_count
== 4)
8418 && (tran_call
== TRANSACT2_IOCTL
)
8419 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8420 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8421 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8423 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8424 DEBUG(2,("Transaction is %d\n",tran_call
));
8426 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8427 END_PROFILE(SMBtrans2
);
8432 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8435 if (state
->total_data
) {
8437 if (trans_oob(state
->total_data
, 0, dscnt
)
8438 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8442 /* Can't use talloc here, the core routines do realloc on the
8443 * params and data. */
8444 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8445 if (state
->data
== NULL
) {
8446 DEBUG(0,("reply_trans2: data malloc fail for %u "
8447 "bytes !\n", (unsigned int)state
->total_data
));
8449 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8450 END_PROFILE(SMBtrans2
);
8454 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8457 if (state
->total_param
) {
8459 if (trans_oob(state
->total_param
, 0, pscnt
)
8460 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8464 /* Can't use talloc here, the core routines do realloc on the
8465 * params and data. */
8466 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8467 if (state
->param
== NULL
) {
8468 DEBUG(0,("reply_trans: param malloc fail for %u "
8469 "bytes !\n", (unsigned int)state
->total_param
));
8470 SAFE_FREE(state
->data
);
8472 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8473 END_PROFILE(SMBtrans2
);
8477 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8480 state
->received_data
= dscnt
;
8481 state
->received_param
= pscnt
;
8483 if ((state
->received_param
== state
->total_param
) &&
8484 (state
->received_data
== state
->total_data
)) {
8486 handle_trans2(conn
, req
, state
);
8488 SAFE_FREE(state
->data
);
8489 SAFE_FREE(state
->param
);
8491 END_PROFILE(SMBtrans2
);
8495 DLIST_ADD(conn
->pending_trans
, state
);
8497 /* We need to send an interim response then receive the rest
8498 of the parameter/data bytes */
8499 reply_outbuf(req
, 0, 0);
8500 show_msg((char *)req
->outbuf
);
8501 END_PROFILE(SMBtrans2
);
8506 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8507 SAFE_FREE(state
->data
);
8508 SAFE_FREE(state
->param
);
8510 END_PROFILE(SMBtrans2
);
8511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8515 /****************************************************************************
8516 Reply to a SMBtranss2
8517 ****************************************************************************/
8519 void reply_transs2(struct smb_request
*req
)
8521 connection_struct
*conn
= req
->conn
;
8522 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8523 struct trans_state
*state
;
8525 START_PROFILE(SMBtranss2
);
8527 show_msg((char *)req
->inbuf
);
8530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8531 END_PROFILE(SMBtranss2
);
8535 for (state
= conn
->pending_trans
; state
!= NULL
;
8536 state
= state
->next
) {
8537 if (state
->mid
== req
->mid
) {
8542 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8543 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8544 END_PROFILE(SMBtranss2
);
8548 /* Revise state->total_param and state->total_data in case they have
8549 changed downwards */
8551 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8552 state
->total_param
= SVAL(req
->vwv
+0, 0);
8553 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8554 state
->total_data
= SVAL(req
->vwv
+1, 0);
8556 pcnt
= SVAL(req
->vwv
+2, 0);
8557 poff
= SVAL(req
->vwv
+3, 0);
8558 pdisp
= SVAL(req
->vwv
+4, 0);
8560 dcnt
= SVAL(req
->vwv
+5, 0);
8561 doff
= SVAL(req
->vwv
+6, 0);
8562 ddisp
= SVAL(req
->vwv
+7, 0);
8564 state
->received_param
+= pcnt
;
8565 state
->received_data
+= dcnt
;
8567 if ((state
->received_data
> state
->total_data
) ||
8568 (state
->received_param
> state
->total_param
))
8572 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8573 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8576 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8580 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8581 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8584 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8587 if ((state
->received_param
< state
->total_param
) ||
8588 (state
->received_data
< state
->total_data
)) {
8589 END_PROFILE(SMBtranss2
);
8593 handle_trans2(conn
, req
, state
);
8595 DLIST_REMOVE(conn
->pending_trans
, state
);
8596 SAFE_FREE(state
->data
);
8597 SAFE_FREE(state
->param
);
8600 END_PROFILE(SMBtranss2
);
8605 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8606 DLIST_REMOVE(conn
->pending_trans
, state
);
8607 SAFE_FREE(state
->data
);
8608 SAFE_FREE(state
->param
);
8610 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8611 END_PROFILE(SMBtranss2
);