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 "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "libsmb/libsmb.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 Roundup a value to the nearest allocation roundup size boundary.
56 Only do this for Windows clients.
57 ********************************************************************/
59 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
61 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
63 /* Only roundup for Windows clients. */
64 enum remote_arch_types ra_type
= get_remote_arch();
65 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
66 val
= SMB_ROUNDUP(val
,rval
);
71 /********************************************************************
72 Create a 64 bit FileIndex. If the file is on the same device as
73 the root of the share, just return the 64-bit inode. If it isn't,
74 mangle as we used to do.
75 ********************************************************************/
77 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
80 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
81 return (uint64_t)psbuf
->st_ex_ino
;
83 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
84 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name
)
98 static const char * const prohibited_ea_names
[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME
,
100 SAMBA_XATTR_DOS_ATTRIB
,
108 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
109 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
112 if (StrnCaseCmp(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
113 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
119 /****************************************************************************
120 Get one EA value. Fill in a struct ea_struct.
121 ****************************************************************************/
123 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
124 files_struct
*fsp
, const char *fname
,
125 const char *ea_name
, struct ea_struct
*pea
)
127 /* Get the value of this xattr. Max size is 64k. */
128 size_t attr_size
= 256;
134 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
136 return NT_STATUS_NO_MEMORY
;
139 if (fsp
&& fsp
->fh
->fd
!= -1) {
140 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
142 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
145 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
151 return map_nt_error_from_unix(errno
);
154 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
155 dump_data(10, (uint8
*)val
, sizeret
);
158 if (strnequal(ea_name
, "user.", 5)) {
159 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
161 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
163 if (pea
->name
== NULL
) {
165 return NT_STATUS_NO_MEMORY
;
167 pea
->value
.data
= (unsigned char *)val
;
168 pea
->value
.length
= (size_t)sizeret
;
172 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
173 files_struct
*fsp
, const char *fname
,
174 char ***pnames
, size_t *pnum_names
)
176 /* Get a list of all xattrs. Max namesize is 64k. */
177 size_t ea_namelist_size
= 1024;
178 char *ea_namelist
= NULL
;
183 ssize_t sizeret
= -1;
185 if (!lp_ea_support(SNUM(conn
))) {
194 * TALLOC the result early to get the talloc hierarchy right.
197 names
= TALLOC_ARRAY(mem_ctx
, char *, 1);
199 DEBUG(0, ("talloc failed\n"));
200 return NT_STATUS_NO_MEMORY
;
203 while (ea_namelist_size
<= 65536) {
205 ea_namelist
= TALLOC_REALLOC_ARRAY(
206 names
, ea_namelist
, char, ea_namelist_size
);
207 if (ea_namelist
== NULL
) {
208 DEBUG(0, ("talloc failed\n"));
210 return NT_STATUS_NO_MEMORY
;
213 if (fsp
&& fsp
->fh
->fd
!= -1) {
214 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
217 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
221 if ((sizeret
== -1) && (errno
== ERANGE
)) {
222 ea_namelist_size
*= 2;
231 return map_nt_error_from_unix(errno
);
234 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
235 (unsigned int)sizeret
));
247 * Ensure the result is 0-terminated
250 if (ea_namelist
[sizeret
-1] != '\0') {
252 return NT_STATUS_INTERNAL_ERROR
;
260 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
264 tmp
= TALLOC_REALLOC_ARRAY(mem_ctx
, names
, char *, num_names
);
266 DEBUG(0, ("talloc failed\n"));
268 return NT_STATUS_NO_MEMORY
;
274 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
275 names
[num_names
++] = p
;
283 *pnum_names
= num_names
;
287 /****************************************************************************
288 Return a linked list of the total EA's. Plus the total size
289 ****************************************************************************/
291 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
292 const char *fname
, size_t *pea_total_len
)
294 /* Get a list of all xattrs. Max namesize is 64k. */
297 struct ea_list
*ea_list_head
= NULL
;
302 if (!lp_ea_support(SNUM(conn
))) {
306 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
309 if (!NT_STATUS_IS_OK(status
) || (num_names
== 0)) {
313 for (i
=0; i
<num_names
; i
++) {
314 struct ea_list
*listp
;
317 if (strnequal(names
[i
], "system.", 7)
318 || samba_private_attr_name(names
[i
]))
321 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
326 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx
, conn
, fsp
,
332 if (listp
->ea
.value
.length
== 0) {
334 * We can never return a zero length EA.
335 * Windows reports the EA's as corrupted.
341 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
344 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
346 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
347 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
348 (unsigned int)listp
->ea
.value
.length
));
350 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
354 /* Add on 4 for total length. */
355 if (*pea_total_len
) {
359 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
360 (unsigned int)*pea_total_len
));
365 /****************************************************************************
366 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
368 ****************************************************************************/
370 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
371 connection_struct
*conn
, struct ea_list
*ea_list
)
373 unsigned int ret_data_size
= 4;
376 SMB_ASSERT(total_data_size
>= 4);
378 if (!lp_ea_support(SNUM(conn
))) {
383 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
386 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
387 dos_namelen
= strlen(dos_ea_name
);
388 if (dos_namelen
> 255 || dos_namelen
== 0) {
391 if (ea_list
->ea
.value
.length
> 65535) {
394 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
398 /* We know we have room. */
399 SCVAL(p
,0,ea_list
->ea
.flags
);
400 SCVAL(p
,1,dos_namelen
);
401 SSVAL(p
,2,ea_list
->ea
.value
.length
);
402 fstrcpy(p
+4, dos_ea_name
);
403 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
405 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
406 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
409 ret_data_size
= PTR_DIFF(p
, pdata
);
410 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
411 SIVAL(pdata
,0,ret_data_size
);
412 return ret_data_size
;
415 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
417 unsigned int total_data_size
,
418 unsigned int *ret_data_size
,
419 connection_struct
*conn
,
420 struct ea_list
*ea_list
)
422 uint8_t *p
= (uint8_t *)pdata
;
423 uint8_t *last_start
= NULL
;
424 bool store_data
= (pdata
!= NULL
);
428 if (!lp_ea_support(SNUM(conn
))) {
429 return NT_STATUS_NO_EAS_ON_FILE
;
432 for (; ea_list
; ea_list
= ea_list
->next
) {
438 if (last_start
&& store_data
) {
439 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
443 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
444 dos_namelen
= strlen(dos_ea_name
);
445 if (dos_namelen
> 255 || dos_namelen
== 0) {
446 return NT_STATUS_INTERNAL_ERROR
;
448 if (ea_list
->ea
.value
.length
> 65535) {
449 return NT_STATUS_INTERNAL_ERROR
;
452 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
455 pad
= (4 - (this_size
% 4)) % 4;
459 if (this_size
> total_data_size
) {
460 return NT_STATUS_INFO_LENGTH_MISMATCH
;
463 /* We know we have room. */
465 SIVAL(p
, 0x00, 0); /* next offset */
466 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
467 SCVAL(p
, 0x05, dos_namelen
);
468 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
469 fstrcpy((char *)(p
+0x08), dos_ea_name
);
470 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
472 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
478 total_data_size
-= this_size
;
482 *ret_data_size
= PTR_DIFF(p
, pdata
);
483 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
487 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
489 size_t total_ea_len
= 0;
490 struct ea_list
*ea_list
= NULL
;
491 TALLOC_CTX
*mem_ctx
= NULL
;
493 if (!lp_ea_support(SNUM(conn
))) {
496 mem_ctx
= talloc_tos();
497 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
498 if (ea_list
== NULL
) {
501 if(conn
->sconn
->using_smb2
) {
503 unsigned int ret_data_size
;
505 * We're going to be using fill_ea_chained_buffer() to
506 * marshall EA's - this size is significantly larger
507 * than the SMB1 buffer. Re-calculate the size without
510 status
= fill_ea_chained_buffer(mem_ctx
,
516 if (!NT_STATUS_IS_OK(status
)) {
519 total_ea_len
= ret_data_size
;
525 /****************************************************************************
526 Ensure the EA name is case insensitive by matching any existing EA name.
527 ****************************************************************************/
529 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
532 TALLOC_CTX
*mem_ctx
= talloc_tos();
533 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
535 for (; ea_list
; ea_list
= ea_list
->next
) {
536 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
537 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
538 &unix_ea_name
[5], ea_list
->ea
.name
));
539 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
545 /****************************************************************************
546 Set or delete an extended attribute.
547 ****************************************************************************/
549 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
550 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
554 if (!lp_ea_support(SNUM(conn
))) {
555 return NT_STATUS_EAS_NOT_SUPPORTED
;
558 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
559 return NT_STATUS_ACCESS_DENIED
;
562 /* For now setting EAs on streams isn't supported. */
563 fname
= smb_fname
->base_name
;
565 for (;ea_list
; ea_list
= ea_list
->next
) {
567 fstring unix_ea_name
;
569 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
570 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
572 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
574 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
576 if (samba_private_attr_name(unix_ea_name
)) {
577 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
578 return NT_STATUS_ACCESS_DENIED
;
581 if (ea_list
->ea
.value
.length
== 0) {
582 /* Remove the attribute. */
583 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
584 DEBUG(10,("set_ea: deleting ea name %s on "
585 "file %s by file descriptor.\n",
586 unix_ea_name
, fsp_str_dbg(fsp
)));
587 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
589 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
590 unix_ea_name
, fname
));
591 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
594 /* Removing a non existent attribute always succeeds. */
595 if (ret
== -1 && errno
== ENOATTR
) {
596 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
602 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
603 DEBUG(10,("set_ea: setting ea name %s on file "
604 "%s by file descriptor.\n",
605 unix_ea_name
, fsp_str_dbg(fsp
)));
606 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
607 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
609 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
610 unix_ea_name
, fname
));
611 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
612 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
618 if (errno
== ENOTSUP
) {
619 return NT_STATUS_EAS_NOT_SUPPORTED
;
622 return map_nt_error_from_unix(errno
);
628 /****************************************************************************
629 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
630 ****************************************************************************/
632 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
634 struct ea_list
*ea_list_head
= NULL
;
635 size_t converted_size
, offset
= 0;
637 while (offset
+ 2 < data_size
) {
638 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
639 unsigned int namelen
= CVAL(pdata
,offset
);
641 offset
++; /* Go past the namelen byte. */
643 /* integer wrap paranioa. */
644 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
645 (offset
> data_size
) || (namelen
> data_size
) ||
646 (offset
+ namelen
>= data_size
)) {
649 /* Ensure the name is null terminated. */
650 if (pdata
[offset
+ namelen
] != '\0') {
653 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
655 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
656 "failed: %s", strerror(errno
)));
662 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
663 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
664 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
670 /****************************************************************************
671 Read one EA list entry from the buffer.
672 ****************************************************************************/
674 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
676 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
678 unsigned int namelen
;
679 size_t converted_size
;
689 eal
->ea
.flags
= CVAL(pdata
,0);
690 namelen
= CVAL(pdata
,1);
691 val_len
= SVAL(pdata
,2);
693 if (4 + namelen
+ 1 + val_len
> data_size
) {
697 /* Ensure the name is null terminated. */
698 if (pdata
[namelen
+ 4] != '\0') {
701 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
702 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
709 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
710 if (!eal
->ea
.value
.data
) {
714 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
716 /* Ensure we're null terminated just in case we print the value. */
717 eal
->ea
.value
.data
[val_len
] = '\0';
718 /* But don't count the null. */
719 eal
->ea
.value
.length
--;
722 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
725 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
726 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
731 /****************************************************************************
732 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
733 ****************************************************************************/
735 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
737 struct ea_list
*ea_list_head
= NULL
;
739 size_t bytes_used
= 0;
741 while (offset
< data_size
) {
742 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
748 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
749 offset
+= bytes_used
;
755 /****************************************************************************
756 Count the total EA size needed.
757 ****************************************************************************/
759 static size_t ea_list_size(struct ea_list
*ealist
)
762 struct ea_list
*listp
;
765 for (listp
= ealist
; listp
; listp
= listp
->next
) {
766 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
767 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
769 /* Add on 4 for total length. */
777 /****************************************************************************
778 Return a union of EA's from a file list and a list of names.
779 The TALLOC context for the two lists *MUST* be identical as we steal
780 memory from one list to add to another. JRA.
781 ****************************************************************************/
783 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
785 struct ea_list
*nlistp
, *flistp
;
787 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
788 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
789 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
795 /* Copy the data from this entry. */
796 nlistp
->ea
.flags
= flistp
->ea
.flags
;
797 nlistp
->ea
.value
= flistp
->ea
.value
;
800 nlistp
->ea
.flags
= 0;
801 ZERO_STRUCT(nlistp
->ea
.value
);
805 *total_ea_len
= ea_list_size(name_list
);
809 /****************************************************************************
810 Send the required number of replies back.
811 We assume all fields other than the data fields are
812 set correctly for the type of call.
813 HACK ! Always assumes smb_setup field is zero.
814 ****************************************************************************/
816 void send_trans2_replies(connection_struct
*conn
,
817 struct smb_request
*req
,
824 /* As we are using a protocol > LANMAN1 then the max_send
825 variable must have been set in the sessetupX call.
826 This takes precedence over the max_xmit field in the
827 global struct. These different max_xmit variables should
828 be merged as this is now too confusing */
830 int data_to_send
= datasize
;
831 int params_to_send
= paramsize
;
833 const char *pp
= params
;
834 const char *pd
= pdata
;
835 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
836 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
837 int data_alignment_offset
= 0;
838 bool overflow
= False
;
839 struct smbd_server_connection
*sconn
= req
->sconn
;
840 int max_send
= sconn
->smb1
.sessions
.max_send
;
842 /* Modify the data_to_send and datasize and set the error if
843 we're trying to send more than max_data_bytes. We still send
844 the part of the packet(s) that fit. Strange, but needed
847 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
848 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
849 max_data_bytes
, datasize
));
850 datasize
= data_to_send
= max_data_bytes
;
854 /* If there genuinely are no parameters or data to send just send the empty packet */
856 if(params_to_send
== 0 && data_to_send
== 0) {
857 reply_outbuf(req
, 10, 0);
858 show_msg((char *)req
->outbuf
);
859 if (!srv_send_smb(sconn
,
862 IS_CONN_ENCRYPTED(conn
),
864 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
866 TALLOC_FREE(req
->outbuf
);
870 /* When sending params and data ensure that both are nicely aligned */
871 /* Only do this alignment when there is also data to send - else
872 can cause NT redirector problems. */
874 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
875 data_alignment_offset
= 4 - (params_to_send
% 4);
877 /* Space is bufsize minus Netbios over TCP header minus SMB header */
878 /* The alignment_offset is to align the param bytes on an even byte
879 boundary. NT 4.0 Beta needs this to work correctly. */
881 useable_space
= max_send
- (smb_size
884 + data_alignment_offset
);
886 if (useable_space
< 0) {
887 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
888 "= %d!!!", useable_space
));
889 exit_server_cleanly("send_trans2_replies: Not enough space");
892 while (params_to_send
|| data_to_send
) {
893 /* Calculate whether we will totally or partially fill this packet */
895 total_sent_thistime
= params_to_send
+ data_to_send
;
897 /* We can never send more than useable_space */
899 * Note that 'useable_space' does not include the alignment offsets,
900 * but we must include the alignment offsets in the calculation of
901 * the length of the data we send over the wire, as the alignment offsets
902 * are sent here. Fix from Marc_Jacobsen@hp.com.
905 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
907 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
908 + data_alignment_offset
);
910 /* Set total params and data to be sent */
911 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
912 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
914 /* Calculate how many parameters and data we can fit into
915 * this packet. Parameters get precedence
918 params_sent_thistime
= MIN(params_to_send
,useable_space
);
919 data_sent_thistime
= useable_space
- params_sent_thistime
;
920 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
922 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
924 /* smb_proff is the offset from the start of the SMB header to the
925 parameter bytes, however the first 4 bytes of outbuf are
926 the Netbios over TCP header. Thus use smb_base() to subtract
927 them from the calculation */
929 SSVAL(req
->outbuf
,smb_proff
,
930 ((smb_buf(req
->outbuf
)+alignment_offset
)
931 - smb_base(req
->outbuf
)));
933 if(params_sent_thistime
== 0)
934 SSVAL(req
->outbuf
,smb_prdisp
,0);
936 /* Absolute displacement of param bytes sent in this packet */
937 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
939 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
940 if(data_sent_thistime
== 0) {
941 SSVAL(req
->outbuf
,smb_droff
,0);
942 SSVAL(req
->outbuf
,smb_drdisp
, 0);
944 /* The offset of the data bytes is the offset of the
945 parameter bytes plus the number of parameters being sent this time */
946 SSVAL(req
->outbuf
, smb_droff
,
947 ((smb_buf(req
->outbuf
)+alignment_offset
)
948 - smb_base(req
->outbuf
))
949 + params_sent_thistime
+ data_alignment_offset
);
950 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
953 /* Initialize the padding for alignment */
955 if (alignment_offset
!= 0) {
956 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
959 /* Copy the param bytes into the packet */
961 if(params_sent_thistime
) {
962 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
963 params_sent_thistime
);
966 /* Copy in the data bytes */
967 if(data_sent_thistime
) {
968 if (data_alignment_offset
!= 0) {
969 memset((smb_buf(req
->outbuf
)+alignment_offset
+
970 params_sent_thistime
), 0,
971 data_alignment_offset
);
973 memcpy(smb_buf(req
->outbuf
)+alignment_offset
974 +params_sent_thistime
+data_alignment_offset
,
975 pd
,data_sent_thistime
);
978 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
979 params_sent_thistime
, data_sent_thistime
, useable_space
));
980 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
981 params_to_send
, data_to_send
, paramsize
, datasize
));
984 error_packet_set((char *)req
->outbuf
,
985 ERRDOS
,ERRbufferoverflow
,
986 STATUS_BUFFER_OVERFLOW
,
990 /* Send the packet */
991 show_msg((char *)req
->outbuf
);
992 if (!srv_send_smb(sconn
,
995 IS_CONN_ENCRYPTED(conn
),
997 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
999 TALLOC_FREE(req
->outbuf
);
1001 pp
+= params_sent_thistime
;
1002 pd
+= data_sent_thistime
;
1004 params_to_send
-= params_sent_thistime
;
1005 data_to_send
-= data_sent_thistime
;
1008 if(params_to_send
< 0 || data_to_send
< 0) {
1009 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1010 params_to_send
, data_to_send
));
1018 /****************************************************************************
1019 Reply to a TRANSACT2_OPEN.
1020 ****************************************************************************/
1022 static void call_trans2open(connection_struct
*conn
,
1023 struct smb_request
*req
,
1024 char **pparams
, int total_params
,
1025 char **ppdata
, int total_data
,
1026 unsigned int max_data_bytes
)
1028 struct smb_filename
*smb_fname
= NULL
;
1029 char *params
= *pparams
;
1030 char *pdata
= *ppdata
;
1033 bool oplock_request
;
1035 bool return_additional_info
;
1044 int fattr
=0,mtime
=0;
1045 SMB_INO_T inode
= 0;
1048 struct ea_list
*ea_list
= NULL
;
1053 uint32 create_disposition
;
1054 uint32 create_options
= 0;
1055 uint32_t private_flags
= 0;
1056 TALLOC_CTX
*ctx
= talloc_tos();
1059 * Ensure we have enough parameters to perform the operation.
1062 if (total_params
< 29) {
1063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1067 flags
= SVAL(params
, 0);
1068 deny_mode
= SVAL(params
, 2);
1069 open_attr
= SVAL(params
,6);
1070 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1071 if (oplock_request
) {
1072 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1076 return_additional_info
= BITSETW(params
,0);
1077 open_sattr
= SVAL(params
, 4);
1078 open_time
= make_unix_date3(params
+8);
1080 open_ofun
= SVAL(params
,12);
1081 open_size
= IVAL(params
,14);
1082 pname
= ¶ms
[28];
1085 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1089 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1090 total_params
- 28, STR_TERMINATE
,
1092 if (!NT_STATUS_IS_OK(status
)) {
1093 reply_nterror(req
, status
);
1097 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1098 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1099 (unsigned int)open_ofun
, open_size
));
1101 status
= filename_convert(ctx
,
1103 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1108 if (!NT_STATUS_IS_OK(status
)) {
1109 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1110 reply_botherror(req
,
1111 NT_STATUS_PATH_NOT_COVERED
,
1112 ERRSRV
, ERRbadpath
);
1115 reply_nterror(req
, status
);
1119 if (open_ofun
== 0) {
1120 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1124 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1126 &access_mask
, &share_mode
,
1127 &create_disposition
,
1130 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1134 /* Any data in this call is an EA list. */
1135 if (total_data
&& (total_data
!= 4)) {
1136 if (total_data
< 10) {
1137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1141 if (IVAL(pdata
,0) > total_data
) {
1142 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1143 IVAL(pdata
,0), (unsigned int)total_data
));
1144 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1148 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1155 if (!lp_ea_support(SNUM(conn
))) {
1156 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1161 status
= SMB_VFS_CREATE_FILE(
1164 0, /* root_dir_fid */
1165 smb_fname
, /* fname */
1166 access_mask
, /* access_mask */
1167 share_mode
, /* share_access */
1168 create_disposition
, /* create_disposition*/
1169 create_options
, /* create_options */
1170 open_attr
, /* file_attributes */
1171 oplock_request
, /* oplock_request */
1172 open_size
, /* allocation_size */
1175 ea_list
, /* ea_list */
1177 &smb_action
); /* psbuf */
1179 if (!NT_STATUS_IS_OK(status
)) {
1180 if (open_was_deferred(req
->mid
)) {
1181 /* We have re-scheduled this call. */
1184 reply_openerror(req
, status
);
1188 size
= get_file_size_stat(&smb_fname
->st
);
1189 fattr
= dos_mode(conn
, smb_fname
);
1190 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1191 inode
= smb_fname
->st
.st_ex_ino
;
1192 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1193 close_file(req
, fsp
, ERROR_CLOSE
);
1194 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1198 /* Realloc the size of parameters and data we will return */
1199 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1200 if(*pparams
== NULL
) {
1201 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1206 SSVAL(params
,0,fsp
->fnum
);
1207 SSVAL(params
,2,fattr
);
1208 srv_put_dos_date2(params
,4, mtime
);
1209 SIVAL(params
,8, (uint32
)size
);
1210 SSVAL(params
,12,deny_mode
);
1211 SSVAL(params
,14,0); /* open_type - file or directory. */
1212 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1214 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1215 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1218 SSVAL(params
,18,smb_action
);
1221 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1223 SIVAL(params
,20,inode
);
1224 SSVAL(params
,24,0); /* Padding. */
1226 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1227 fsp
->fsp_name
->base_name
);
1228 SIVAL(params
, 26, ea_size
);
1230 SIVAL(params
, 26, 0);
1233 /* Send the required number of replies */
1234 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1236 TALLOC_FREE(smb_fname
);
1239 /*********************************************************
1240 Routine to check if a given string matches exactly.
1241 as a special case a mask of "." does NOT match. That
1242 is required for correct wildcard semantics
1243 Case can be significant or not.
1244 **********************************************************/
1246 static bool exact_match(bool has_wild
,
1247 bool case_sensitive
,
1251 if (mask
[0] == '.' && mask
[1] == 0) {
1259 if (case_sensitive
) {
1260 return strcmp(str
,mask
)==0;
1262 return StrCaseCmp(str
,mask
) == 0;
1266 /****************************************************************************
1267 Return the filetype for UNIX extensions.
1268 ****************************************************************************/
1270 static uint32
unix_filetype(mode_t mode
)
1273 return UNIX_TYPE_FILE
;
1274 else if(S_ISDIR(mode
))
1275 return UNIX_TYPE_DIR
;
1277 else if(S_ISLNK(mode
))
1278 return UNIX_TYPE_SYMLINK
;
1281 else if(S_ISCHR(mode
))
1282 return UNIX_TYPE_CHARDEV
;
1285 else if(S_ISBLK(mode
))
1286 return UNIX_TYPE_BLKDEV
;
1289 else if(S_ISFIFO(mode
))
1290 return UNIX_TYPE_FIFO
;
1293 else if(S_ISSOCK(mode
))
1294 return UNIX_TYPE_SOCKET
;
1297 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1298 return UNIX_TYPE_UNKNOWN
;
1301 /****************************************************************************
1302 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1303 ****************************************************************************/
1305 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1307 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1308 const SMB_STRUCT_STAT
*psbuf
,
1310 enum perm_type ptype
,
1315 if (perms
== SMB_MODE_NO_CHANGE
) {
1316 if (!VALID_STAT(*psbuf
)) {
1317 return NT_STATUS_INVALID_PARAMETER
;
1319 *ret_perms
= psbuf
->st_ex_mode
;
1320 return NT_STATUS_OK
;
1324 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1325 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1326 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1327 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1328 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1329 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1330 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1331 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1332 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1334 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1337 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1340 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1345 /* Apply mode mask */
1346 ret
&= lp_create_mask(SNUM(conn
));
1347 /* Add in force bits */
1348 ret
|= lp_force_create_mode(SNUM(conn
));
1351 ret
&= lp_dir_mask(SNUM(conn
));
1352 /* Add in force bits */
1353 ret
|= lp_force_dir_mode(SNUM(conn
));
1355 case PERM_EXISTING_FILE
:
1356 /* Apply mode mask */
1357 ret
&= lp_security_mask(SNUM(conn
));
1358 /* Add in force bits */
1359 ret
|= lp_force_security_mode(SNUM(conn
));
1361 case PERM_EXISTING_DIR
:
1362 /* Apply mode mask */
1363 ret
&= lp_dir_security_mask(SNUM(conn
));
1364 /* Add in force bits */
1365 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1370 return NT_STATUS_OK
;
1373 /****************************************************************************
1374 Needed to show the msdfs symlinks as directories. Modifies psbuf
1375 to be a directory if it's a msdfs link.
1376 ****************************************************************************/
1378 static bool check_msdfs_link(connection_struct
*conn
,
1379 const char *pathname
,
1380 SMB_STRUCT_STAT
*psbuf
)
1382 int saved_errno
= errno
;
1383 if(lp_host_msdfs() &&
1384 lp_msdfs_root(SNUM(conn
)) &&
1385 is_msdfs_link(conn
, pathname
, psbuf
)) {
1387 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1390 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1391 errno
= saved_errno
;
1394 errno
= saved_errno
;
1399 /****************************************************************************
1400 Get a level dependent lanman2 dir entry.
1401 ****************************************************************************/
1403 struct smbd_dirptr_lanman2_state
{
1404 connection_struct
*conn
;
1405 uint32_t info_level
;
1406 bool check_mangled_names
;
1408 bool got_exact_match
;
1411 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1417 struct smbd_dirptr_lanman2_state
*state
=
1418 (struct smbd_dirptr_lanman2_state
*)private_data
;
1420 char mangled_name
[13]; /* mangled 8.3 name. */
1424 /* Mangle fname if it's an illegal name. */
1425 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1426 ok
= name_to_8_3(dname
, mangled_name
,
1427 true, state
->conn
->params
);
1431 fname
= mangled_name
;
1436 got_match
= exact_match(state
->has_wild
,
1437 state
->conn
->case_sensitive
,
1439 state
->got_exact_match
= got_match
;
1441 got_match
= mask_match(fname
, mask
,
1442 state
->conn
->case_sensitive
);
1445 if(!got_match
&& state
->check_mangled_names
&&
1446 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1448 * It turns out that NT matches wildcards against
1449 * both long *and* short names. This may explain some
1450 * of the wildcard wierdness from old DOS clients
1451 * that some people have been seeing.... JRA.
1453 /* Force the mangling into 8.3. */
1454 ok
= name_to_8_3(fname
, mangled_name
,
1455 false, state
->conn
->params
);
1460 got_match
= exact_match(state
->has_wild
,
1461 state
->conn
->case_sensitive
,
1462 mangled_name
, mask
);
1463 state
->got_exact_match
= got_match
;
1465 got_match
= mask_match(mangled_name
, mask
,
1466 state
->conn
->case_sensitive
);
1474 *_fname
= talloc_strdup(ctx
, fname
);
1475 if (*_fname
== NULL
) {
1482 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1484 struct smb_filename
*smb_fname
,
1487 struct smbd_dirptr_lanman2_state
*state
=
1488 (struct smbd_dirptr_lanman2_state
*)private_data
;
1489 bool ms_dfs_link
= false;
1492 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1493 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1494 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1495 "Couldn't lstat [%s] (%s)\n",
1496 smb_fname_str_dbg(smb_fname
),
1500 } else if (!VALID_STAT(smb_fname
->st
) &&
1501 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1502 /* Needed to show the msdfs symlinks as
1505 ms_dfs_link
= check_msdfs_link(state
->conn
,
1506 smb_fname
->base_name
,
1509 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1510 "Couldn't stat [%s] (%s)\n",
1511 smb_fname_str_dbg(smb_fname
),
1518 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1520 mode
= dos_mode(state
->conn
, smb_fname
);
1527 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1528 connection_struct
*conn
,
1530 uint32_t info_level
,
1531 struct ea_list
*name_list
,
1532 bool check_mangled_names
,
1533 bool requires_resume_key
,
1536 const struct smb_filename
*smb_fname
,
1537 int space_remaining
,
1544 uint64_t *last_entry_off
)
1546 char *p
, *q
, *pdata
= *ppdata
;
1548 uint64_t file_size
= 0;
1549 uint64_t allocation_size
= 0;
1550 uint64_t file_index
= 0;
1552 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1553 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1554 time_t c_date
= (time_t)0;
1556 char *last_entry_ptr
;
1561 *out_of_space
= false;
1563 ZERO_STRUCT(mdate_ts
);
1564 ZERO_STRUCT(adate_ts
);
1565 ZERO_STRUCT(create_date_ts
);
1566 ZERO_STRUCT(cdate_ts
);
1568 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1569 file_size
= get_file_size_stat(&smb_fname
->st
);
1571 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1573 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1575 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1576 adate_ts
= smb_fname
->st
.st_ex_atime
;
1577 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1578 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1580 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1581 dos_filetime_timespec(&create_date_ts
);
1582 dos_filetime_timespec(&mdate_ts
);
1583 dos_filetime_timespec(&adate_ts
);
1584 dos_filetime_timespec(&cdate_ts
);
1587 create_date
= convert_timespec_to_time_t(create_date_ts
);
1588 mdate
= convert_timespec_to_time_t(mdate_ts
);
1589 adate
= convert_timespec_to_time_t(adate_ts
);
1590 c_date
= convert_timespec_to_time_t(cdate_ts
);
1592 /* align the record */
1593 SMB_ASSERT(align
>= 1);
1595 off
= (int)PTR_DIFF(pdata
, base_data
);
1596 pad
= (off
+ (align
-1)) & ~(align
-1);
1599 if (pad
&& pad
> space_remaining
) {
1600 *out_of_space
= true;
1601 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1602 "for padding (wanted %u, had %d)\n",
1605 return false; /* Not finished - just out of space */
1609 /* initialize padding to 0 */
1611 memset(pdata
, 0, pad
);
1613 space_remaining
-= pad
;
1615 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1625 switch (info_level
) {
1626 case SMB_FIND_INFO_STANDARD
:
1627 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1628 if(requires_resume_key
) {
1632 srv_put_dos_date2(p
,0,create_date
);
1633 srv_put_dos_date2(p
,4,adate
);
1634 srv_put_dos_date2(p
,8,mdate
);
1635 SIVAL(p
,12,(uint32
)file_size
);
1636 SIVAL(p
,16,(uint32
)allocation_size
);
1640 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1641 p
+= ucs2_align(base_data
, p
, 0);
1643 len
= srvstr_push(base_data
, flags2
, p
,
1644 fname
, PTR_DIFF(end_data
, p
),
1646 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1648 SCVAL(nameptr
, -1, len
- 2);
1650 SCVAL(nameptr
, -1, 0);
1654 SCVAL(nameptr
, -1, len
- 1);
1656 SCVAL(nameptr
, -1, 0);
1662 case SMB_FIND_EA_SIZE
:
1663 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1664 if (requires_resume_key
) {
1668 srv_put_dos_date2(p
,0,create_date
);
1669 srv_put_dos_date2(p
,4,adate
);
1670 srv_put_dos_date2(p
,8,mdate
);
1671 SIVAL(p
,12,(uint32
)file_size
);
1672 SIVAL(p
,16,(uint32
)allocation_size
);
1675 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1676 smb_fname
->base_name
);
1677 SIVAL(p
,22,ea_size
); /* Extended attributes */
1681 len
= srvstr_push(base_data
, flags2
,
1682 p
, fname
, PTR_DIFF(end_data
, p
),
1683 STR_TERMINATE
| STR_NOALIGN
);
1684 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1697 SCVAL(nameptr
,0,len
);
1699 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1702 case SMB_FIND_EA_LIST
:
1704 struct ea_list
*file_list
= NULL
;
1707 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1711 if (requires_resume_key
) {
1715 srv_put_dos_date2(p
,0,create_date
);
1716 srv_put_dos_date2(p
,4,adate
);
1717 srv_put_dos_date2(p
,8,mdate
);
1718 SIVAL(p
,12,(uint32
)file_size
);
1719 SIVAL(p
,16,(uint32
)allocation_size
);
1721 p
+= 22; /* p now points to the EA area. */
1723 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
,
1724 smb_fname
->base_name
,
1726 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1728 /* We need to determine if this entry will fit in the space available. */
1729 /* Max string size is 255 bytes. */
1730 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1731 *out_of_space
= true;
1732 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1733 "(wanted %u, had %d)\n",
1734 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1736 return False
; /* Not finished - just out of space */
1739 /* Push the ea_data followed by the name. */
1740 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1742 len
= srvstr_push(base_data
, flags2
,
1743 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1744 STR_TERMINATE
| STR_NOALIGN
);
1745 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1758 SCVAL(nameptr
,0,len
);
1760 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1764 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1765 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1766 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1768 SIVAL(p
,0,reskey
); p
+= 4;
1769 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1770 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1771 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1772 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1773 SOFF_T(p
,0,file_size
); p
+= 8;
1774 SOFF_T(p
,0,allocation_size
); p
+= 8;
1775 SIVAL(p
,0,mode
); p
+= 4;
1776 q
= p
; p
+= 4; /* q is placeholder for name length. */
1777 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1778 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1780 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1781 smb_fname
->base_name
);
1782 SIVAL(p
,0,ea_size
); /* Extended attributes */
1785 /* Clear the short name buffer. This is
1786 * IMPORTANT as not doing so will trigger
1787 * a Win2k client bug. JRA.
1789 if (!was_8_3
&& check_mangled_names
) {
1790 char mangled_name
[13]; /* mangled 8.3 name. */
1791 if (!name_to_8_3(fname
,mangled_name
,True
,
1793 /* Error - mangle failed ! */
1794 memset(mangled_name
,'\0',12);
1796 mangled_name
[12] = 0;
1797 len
= srvstr_push(base_data
, flags2
,
1798 p
+2, mangled_name
, 24,
1799 STR_UPPER
|STR_UNICODE
);
1801 memset(p
+ 2 + len
,'\0',24 - len
);
1808 len
= srvstr_push(base_data
, flags2
, p
,
1809 fname
, PTR_DIFF(end_data
, p
),
1810 STR_TERMINATE_ASCII
);
1814 len
= PTR_DIFF(p
, pdata
);
1815 pad
= (len
+ (align
-1)) & ~(align
-1);
1817 * offset to the next entry, the caller
1818 * will overwrite it for the last entry
1819 * that's why we always include the padding
1823 * set padding to zero
1826 memset(p
, 0, pad
- len
);
1833 case SMB_FIND_FILE_DIRECTORY_INFO
:
1834 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1836 SIVAL(p
,0,reskey
); p
+= 4;
1837 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1838 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1839 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1840 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1841 SOFF_T(p
,0,file_size
); p
+= 8;
1842 SOFF_T(p
,0,allocation_size
); p
+= 8;
1843 SIVAL(p
,0,mode
); p
+= 4;
1844 len
= srvstr_push(base_data
, flags2
,
1845 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1846 STR_TERMINATE_ASCII
);
1850 len
= PTR_DIFF(p
, pdata
);
1851 pad
= (len
+ (align
-1)) & ~(align
-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1859 * set padding to zero
1862 memset(p
, 0, pad
- len
);
1869 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1872 SIVAL(p
,0,reskey
); p
+= 4;
1873 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1874 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1876 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1877 SOFF_T(p
,0,file_size
); p
+= 8;
1878 SOFF_T(p
,0,allocation_size
); p
+= 8;
1879 SIVAL(p
,0,mode
); p
+= 4;
1880 q
= p
; p
+= 4; /* q is placeholder for name length. */
1882 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1883 smb_fname
->base_name
);
1884 SIVAL(p
,0,ea_size
); /* Extended attributes */
1887 len
= srvstr_push(base_data
, flags2
, p
,
1888 fname
, PTR_DIFF(end_data
, p
),
1889 STR_TERMINATE_ASCII
);
1893 len
= PTR_DIFF(p
, pdata
);
1894 pad
= (len
+ (align
-1)) & ~(align
-1);
1896 * offset to the next entry, the caller
1897 * will overwrite it for the last entry
1898 * that's why we always include the padding
1902 * set padding to zero
1905 memset(p
, 0, pad
- len
);
1912 case SMB_FIND_FILE_NAMES_INFO
:
1913 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1915 SIVAL(p
,0,reskey
); p
+= 4;
1917 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1918 acl on a dir (tridge) */
1919 len
= srvstr_push(base_data
, flags2
, p
,
1920 fname
, PTR_DIFF(end_data
, p
),
1921 STR_TERMINATE_ASCII
);
1925 len
= PTR_DIFF(p
, pdata
);
1926 pad
= (len
+ (align
-1)) & ~(align
-1);
1928 * offset to the next entry, the caller
1929 * will overwrite it for the last entry
1930 * that's why we always include the padding
1934 * set padding to zero
1937 memset(p
, 0, pad
- len
);
1944 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1945 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1947 SIVAL(p
,0,reskey
); p
+= 4;
1948 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1949 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1950 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1951 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1952 SOFF_T(p
,0,file_size
); p
+= 8;
1953 SOFF_T(p
,0,allocation_size
); p
+= 8;
1954 SIVAL(p
,0,mode
); p
+= 4;
1955 q
= p
; p
+= 4; /* q is placeholder for name length. */
1956 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1957 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1959 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1960 smb_fname
->base_name
);
1961 SIVAL(p
,0,ea_size
); /* Extended attributes */
1964 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1965 SBVAL(p
,0,file_index
); p
+= 8;
1966 len
= srvstr_push(base_data
, flags2
, p
,
1967 fname
, PTR_DIFF(end_data
, p
),
1968 STR_TERMINATE_ASCII
);
1972 len
= PTR_DIFF(p
, pdata
);
1973 pad
= (len
+ (align
-1)) & ~(align
-1);
1975 * offset to the next entry, the caller
1976 * will overwrite it for the last entry
1977 * that's why we always include the padding
1981 * set padding to zero
1984 memset(p
, 0, pad
- len
);
1991 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1992 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1993 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1995 SIVAL(p
,0,reskey
); p
+= 4;
1996 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1997 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1998 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1999 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2000 SOFF_T(p
,0,file_size
); p
+= 8;
2001 SOFF_T(p
,0,allocation_size
); p
+= 8;
2002 SIVAL(p
,0,mode
); p
+= 4;
2003 q
= p
; p
+= 4; /* q is placeholder for name length */
2004 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2005 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2007 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2008 smb_fname
->base_name
);
2009 SIVAL(p
,0,ea_size
); /* Extended attributes */
2012 /* Clear the short name buffer. This is
2013 * IMPORTANT as not doing so will trigger
2014 * a Win2k client bug. JRA.
2016 if (!was_8_3
&& check_mangled_names
) {
2017 char mangled_name
[13]; /* mangled 8.3 name. */
2018 if (!name_to_8_3(fname
,mangled_name
,True
,
2020 /* Error - mangle failed ! */
2021 memset(mangled_name
,'\0',12);
2023 mangled_name
[12] = 0;
2024 len
= srvstr_push(base_data
, flags2
,
2025 p
+2, mangled_name
, 24,
2026 STR_UPPER
|STR_UNICODE
);
2029 memset(p
+ 2 + len
,'\0',24 - len
);
2036 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2037 SBVAL(p
,0,file_index
); p
+= 8;
2038 len
= srvstr_push(base_data
, flags2
, p
,
2039 fname
, PTR_DIFF(end_data
, p
),
2040 STR_TERMINATE_ASCII
);
2044 len
= PTR_DIFF(p
, pdata
);
2045 pad
= (len
+ (align
-1)) & ~(align
-1);
2047 * offset to the next entry, the caller
2048 * will overwrite it for the last entry
2049 * that's why we always include the padding
2053 * set padding to zero
2056 memset(p
, 0, pad
- len
);
2063 /* CIFS UNIX Extension. */
2065 case SMB_FIND_FILE_UNIX
:
2066 case SMB_FIND_FILE_UNIX_INFO2
:
2068 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2070 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (info_level
== SMB_FIND_FILE_UNIX
) {
2073 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2074 p
= store_file_unix_basic(conn
, p
,
2075 NULL
, &smb_fname
->st
);
2076 len
= srvstr_push(base_data
, flags2
, p
,
2077 fname
, PTR_DIFF(end_data
, p
),
2080 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2081 p
= store_file_unix_basic_info2(conn
, p
,
2082 NULL
, &smb_fname
->st
);
2085 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2086 PTR_DIFF(end_data
, p
), 0);
2087 SIVAL(nameptr
, 0, len
);
2092 len
= PTR_DIFF(p
, pdata
);
2093 pad
= (len
+ (align
-1)) & ~(align
-1);
2095 * offset to the next entry, the caller
2096 * will overwrite it for the last entry
2097 * that's why we always include the padding
2101 * set padding to zero
2104 memset(p
, 0, pad
- len
);
2109 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2117 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2118 *out_of_space
= true;
2119 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2120 "(wanted %u, had %d)\n",
2121 (unsigned int)PTR_DIFF(p
,pdata
),
2123 return false; /* Not finished - just out of space */
2126 /* Setup the last entry pointer, as an offset from base_data */
2127 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2128 /* Advance the data pointer to the next slot */
2134 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2135 connection_struct
*conn
,
2136 struct dptr_struct
*dirptr
,
2138 const char *path_mask
,
2141 int requires_resume_key
,
2149 int space_remaining
,
2151 bool *got_exact_match
,
2152 int *_last_entry_off
,
2153 struct ea_list
*name_list
)
2156 const char *mask
= NULL
;
2157 long prev_dirpos
= 0;
2160 struct smb_filename
*smb_fname
= NULL
;
2161 struct smbd_dirptr_lanman2_state state
;
2163 uint64_t last_entry_off
= 0;
2167 state
.info_level
= info_level
;
2168 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2169 state
.has_wild
= dptr_has_wild(dirptr
);
2170 state
.got_exact_match
= false;
2172 *out_of_space
= false;
2173 *got_exact_match
= false;
2175 p
= strrchr_m(path_mask
,'/');
2186 ok
= smbd_dirptr_get_entry(ctx
,
2192 smbd_dirptr_lanman2_match_fn
,
2193 smbd_dirptr_lanman2_mode_fn
,
2203 *got_exact_match
= state
.got_exact_match
;
2205 ok
= smbd_marshall_dir_entry(ctx
,
2210 state
.check_mangled_names
,
2211 requires_resume_key
,
2224 TALLOC_FREE(smb_fname
);
2225 if (*out_of_space
) {
2226 dptr_SeekDir(dirptr
, prev_dirpos
);
2233 *_last_entry_off
= last_entry_off
;
2237 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2238 connection_struct
*conn
,
2239 struct dptr_struct
*dirptr
,
2241 const char *path_mask
,
2244 bool requires_resume_key
,
2250 int space_remaining
,
2252 bool *got_exact_match
,
2253 int *last_entry_off
,
2254 struct ea_list
*name_list
)
2257 const bool do_pad
= true;
2259 if (info_level
>= 1 && info_level
<= 3) {
2260 /* No alignment on earlier info levels. */
2264 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2265 path_mask
, dirtype
, info_level
,
2266 requires_resume_key
, dont_descend
, ask_sharemode
,
2268 ppdata
, base_data
, end_data
,
2270 out_of_space
, got_exact_match
,
2271 last_entry_off
, name_list
);
2274 /****************************************************************************
2275 Reply to a TRANS2_FINDFIRST.
2276 ****************************************************************************/
2278 static void call_trans2findfirst(connection_struct
*conn
,
2279 struct smb_request
*req
,
2280 char **pparams
, int total_params
,
2281 char **ppdata
, int total_data
,
2282 unsigned int max_data_bytes
)
2284 /* We must be careful here that we don't return more than the
2285 allowed number of data bytes. If this means returning fewer than
2286 maxentries then so be it. We assume that the redirector has
2287 enough room for the fixed number of parameter bytes it has
2289 struct smb_filename
*smb_dname
= NULL
;
2290 char *params
= *pparams
;
2291 char *pdata
= *ppdata
;
2295 uint16 findfirst_flags
;
2296 bool close_after_first
;
2298 bool requires_resume_key
;
2300 char *directory
= NULL
;
2303 int last_entry_off
=0;
2307 bool finished
= False
;
2308 bool dont_descend
= False
;
2309 bool out_of_space
= False
;
2310 int space_remaining
;
2311 bool mask_contains_wcard
= False
;
2312 struct ea_list
*ea_list
= NULL
;
2313 NTSTATUS ntstatus
= NT_STATUS_OK
;
2314 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2315 TALLOC_CTX
*ctx
= talloc_tos();
2316 struct dptr_struct
*dirptr
= NULL
;
2317 struct smbd_server_connection
*sconn
= req
->sconn
;
2318 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2320 if (total_params
< 13) {
2321 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2325 dirtype
= SVAL(params
,0);
2326 maxentries
= SVAL(params
,2);
2327 findfirst_flags
= SVAL(params
,4);
2328 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2329 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2330 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2331 info_level
= SVAL(params
,6);
2333 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2334 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2335 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2336 info_level
, max_data_bytes
));
2339 /* W2K3 seems to treat zero as 1. */
2343 switch (info_level
) {
2344 case SMB_FIND_INFO_STANDARD
:
2345 case SMB_FIND_EA_SIZE
:
2346 case SMB_FIND_EA_LIST
:
2347 case SMB_FIND_FILE_DIRECTORY_INFO
:
2348 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2349 case SMB_FIND_FILE_NAMES_INFO
:
2350 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2351 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2352 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2354 case SMB_FIND_FILE_UNIX
:
2355 case SMB_FIND_FILE_UNIX_INFO2
:
2356 /* Always use filesystem for UNIX mtime query. */
2357 ask_sharemode
= false;
2358 if (!lp_unix_extensions()) {
2359 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2362 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2365 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2369 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2370 params
+12, total_params
- 12,
2371 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2372 if (!NT_STATUS_IS_OK(ntstatus
)) {
2373 reply_nterror(req
, ntstatus
);
2377 ntstatus
= filename_convert(ctx
, conn
,
2378 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2381 &mask_contains_wcard
,
2383 if (!NT_STATUS_IS_OK(ntstatus
)) {
2384 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2385 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2386 ERRSRV
, ERRbadpath
);
2389 reply_nterror(req
, ntstatus
);
2393 mask
= smb_dname
->original_lcomp
;
2395 directory
= smb_dname
->base_name
;
2397 p
= strrchr_m(directory
,'/');
2399 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2400 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2401 mask
= talloc_strdup(ctx
,"*");
2403 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2406 mask_contains_wcard
= True
;
2412 if (p
== NULL
|| p
== directory
) {
2413 /* Ensure we don't have a directory name of "". */
2414 directory
= talloc_strdup(talloc_tos(), ".");
2416 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2421 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2423 if (info_level
== SMB_FIND_EA_LIST
) {
2426 if (total_data
< 4) {
2427 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2431 ea_size
= IVAL(pdata
,0);
2432 if (ea_size
!= total_data
) {
2433 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2434 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2435 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2439 if (!lp_ea_support(SNUM(conn
))) {
2440 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2444 /* Pull out the list of names. */
2445 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2452 *ppdata
= (char *)SMB_REALLOC(
2453 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2454 if(*ppdata
== NULL
) {
2455 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2459 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2461 /* Realloc the params space */
2462 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2463 if (*pparams
== NULL
) {
2464 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2469 /* Save the wildcard match and attribs we are using on this directory -
2470 needed as lanman2 assumes these are being saved between calls */
2472 ntstatus
= dptr_create(conn
,
2479 mask_contains_wcard
,
2483 if (!NT_STATUS_IS_OK(ntstatus
)) {
2484 reply_nterror(req
, ntstatus
);
2488 dptr_num
= dptr_dnum(dirptr
);
2489 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2491 /* Initialize per TRANS2_FIND_FIRST operation data */
2492 dptr_init_search_op(dirptr
);
2494 /* We don't need to check for VOL here as this is returned by
2495 a different TRANS2 call. */
2497 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2498 directory
,lp_dontdescend(SNUM(conn
))));
2499 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2500 dont_descend
= True
;
2503 space_remaining
= max_data_bytes
;
2504 out_of_space
= False
;
2506 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2507 bool got_exact_match
= False
;
2509 /* this is a heuristic to avoid seeking the dirptr except when
2510 absolutely necessary. It allows for a filename of about 40 chars */
2511 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2512 out_of_space
= True
;
2515 finished
= !get_lanman2_dir_entry(ctx
,
2519 mask
,dirtype
,info_level
,
2520 requires_resume_key
,dont_descend
,
2523 space_remaining
, &out_of_space
,
2525 &last_entry_off
, ea_list
);
2528 if (finished
&& out_of_space
)
2531 if (!finished
&& !out_of_space
)
2535 * As an optimisation if we know we aren't looking
2536 * for a wildcard name (ie. the name matches the wildcard exactly)
2537 * then we can finish on any (first) match.
2538 * This speeds up large directory searches. JRA.
2544 /* Ensure space_remaining never goes -ve. */
2545 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2546 space_remaining
= 0;
2547 out_of_space
= true;
2549 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2553 /* Check if we can close the dirptr */
2554 if(close_after_first
|| (finished
&& close_if_end
)) {
2555 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2556 dptr_close(sconn
, &dptr_num
);
2560 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2561 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2562 * the protocol level is less than NT1. Tested with smbclient. JRA.
2563 * This should fix the OS/2 client bug #2335.
2566 if(numentries
== 0) {
2567 dptr_close(sconn
, &dptr_num
);
2568 if (get_Protocol() < PROTOCOL_NT1
) {
2569 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2572 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2573 ERRDOS
, ERRbadfile
);
2578 /* At this point pdata points to numentries directory entries. */
2580 /* Set up the return parameter block */
2581 SSVAL(params
,0,dptr_num
);
2582 SSVAL(params
,2,numentries
);
2583 SSVAL(params
,4,finished
);
2584 SSVAL(params
,6,0); /* Never an EA error */
2585 SSVAL(params
,8,last_entry_off
);
2587 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2590 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2591 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2593 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2597 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2598 smb_fn_name(req
->cmd
),
2599 mask
, directory
, dirtype
, numentries
) );
2602 * Force a name mangle here to ensure that the
2603 * mask as an 8.3 name is top of the mangled cache.
2604 * The reasons for this are subtle. Don't remove
2605 * this code unless you know what you are doing
2606 * (see PR#13758). JRA.
2609 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2610 char mangled_name
[13];
2611 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2614 TALLOC_FREE(smb_dname
);
2618 /****************************************************************************
2619 Reply to a TRANS2_FINDNEXT.
2620 ****************************************************************************/
2622 static void call_trans2findnext(connection_struct
*conn
,
2623 struct smb_request
*req
,
2624 char **pparams
, int total_params
,
2625 char **ppdata
, int total_data
,
2626 unsigned int max_data_bytes
)
2628 /* We must be careful here that we don't return more than the
2629 allowed number of data bytes. If this means returning fewer than
2630 maxentries then so be it. We assume that the redirector has
2631 enough room for the fixed number of parameter bytes it has
2633 char *params
= *pparams
;
2634 char *pdata
= *ppdata
;
2640 uint16 findnext_flags
;
2641 bool close_after_request
;
2643 bool requires_resume_key
;
2645 bool mask_contains_wcard
= False
;
2646 char *resume_name
= NULL
;
2647 const char *mask
= NULL
;
2648 const char *directory
= NULL
;
2652 int i
, last_entry_off
=0;
2653 bool finished
= False
;
2654 bool dont_descend
= False
;
2655 bool out_of_space
= False
;
2656 int space_remaining
;
2657 struct ea_list
*ea_list
= NULL
;
2658 NTSTATUS ntstatus
= NT_STATUS_OK
;
2659 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2660 TALLOC_CTX
*ctx
= talloc_tos();
2661 struct dptr_struct
*dirptr
;
2662 struct smbd_server_connection
*sconn
= req
->sconn
;
2664 if (total_params
< 13) {
2665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2669 dptr_num
= SVAL(params
,0);
2670 maxentries
= SVAL(params
,2);
2671 info_level
= SVAL(params
,4);
2672 resume_key
= IVAL(params
,6);
2673 findnext_flags
= SVAL(params
,10);
2674 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2675 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2676 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2677 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2679 if (!continue_bit
) {
2680 /* We only need resume_name if continue_bit is zero. */
2681 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2683 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2684 &mask_contains_wcard
);
2685 if (!NT_STATUS_IS_OK(ntstatus
)) {
2686 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2687 complain (it thinks we're asking for the directory above the shared
2688 path or an invalid name). Catch this as the resume name is only compared, never used in
2689 a file access. JRA. */
2690 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2691 &resume_name
, params
+12,
2695 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2696 reply_nterror(req
, ntstatus
);
2702 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2703 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2704 resume_key = %d resume name = %s continue=%d level = %d\n",
2705 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2706 requires_resume_key
, resume_key
,
2707 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2710 /* W2K3 seems to treat zero as 1. */
2714 switch (info_level
) {
2715 case SMB_FIND_INFO_STANDARD
:
2716 case SMB_FIND_EA_SIZE
:
2717 case SMB_FIND_EA_LIST
:
2718 case SMB_FIND_FILE_DIRECTORY_INFO
:
2719 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2720 case SMB_FIND_FILE_NAMES_INFO
:
2721 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2722 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2723 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2725 case SMB_FIND_FILE_UNIX
:
2726 case SMB_FIND_FILE_UNIX_INFO2
:
2727 /* Always use filesystem for UNIX mtime query. */
2728 ask_sharemode
= false;
2729 if (!lp_unix_extensions()) {
2730 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2735 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2739 if (info_level
== SMB_FIND_EA_LIST
) {
2742 if (total_data
< 4) {
2743 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2747 ea_size
= IVAL(pdata
,0);
2748 if (ea_size
!= total_data
) {
2749 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2750 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2751 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2755 if (!lp_ea_support(SNUM(conn
))) {
2756 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2760 /* Pull out the list of names. */
2761 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2763 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2768 *ppdata
= (char *)SMB_REALLOC(
2769 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2770 if(*ppdata
== NULL
) {
2771 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2776 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2778 /* Realloc the params space */
2779 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2780 if(*pparams
== NULL
) {
2781 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2787 /* Check that the dptr is valid */
2788 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2789 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2793 directory
= dptr_path(sconn
, dptr_num
);
2795 /* Get the wildcard mask from the dptr */
2796 if((p
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2797 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2798 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2804 /* Get the attr mask from the dptr */
2805 dirtype
= dptr_attr(sconn
, dptr_num
);
2807 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2808 dptr_num
, mask
, dirtype
,
2810 dptr_TellDir(dirptr
)));
2812 /* Initialize per TRANS2_FIND_NEXT operation data */
2813 dptr_init_search_op(dirptr
);
2815 /* We don't need to check for VOL here as this is returned by
2816 a different TRANS2 call. */
2818 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2819 directory
,lp_dontdescend(SNUM(conn
))));
2820 if (in_list(directory
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2821 dont_descend
= True
;
2824 space_remaining
= max_data_bytes
;
2825 out_of_space
= False
;
2828 * Seek to the correct position. We no longer use the resume key but
2829 * depend on the last file name instead.
2832 if(!continue_bit
&& resume_name
&& *resume_name
) {
2835 long current_pos
= 0;
2837 * Remember, name_to_8_3 is called by
2838 * get_lanman2_dir_entry(), so the resume name
2839 * could be mangled. Ensure we check the unmangled name.
2842 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2843 char *new_resume_name
= NULL
;
2844 mangle_lookup_name_from_8_3(ctx
,
2848 if (new_resume_name
) {
2849 resume_name
= new_resume_name
;
2854 * Fix for NT redirector problem triggered by resume key indexes
2855 * changing between directory scans. We now return a resume key of 0
2856 * and instead look for the filename to continue from (also given
2857 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2858 * findfirst/findnext (as is usual) then the directory pointer
2859 * should already be at the correct place.
2862 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2863 } /* end if resume_name && !continue_bit */
2865 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2866 bool got_exact_match
= False
;
2868 /* this is a heuristic to avoid seeking the dirptr except when
2869 absolutely necessary. It allows for a filename of about 40 chars */
2870 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2871 out_of_space
= True
;
2874 finished
= !get_lanman2_dir_entry(ctx
,
2878 mask
,dirtype
,info_level
,
2879 requires_resume_key
,dont_descend
,
2882 space_remaining
, &out_of_space
,
2884 &last_entry_off
, ea_list
);
2887 if (finished
&& out_of_space
)
2890 if (!finished
&& !out_of_space
)
2894 * As an optimisation if we know we aren't looking
2895 * for a wildcard name (ie. the name matches the wildcard exactly)
2896 * then we can finish on any (first) match.
2897 * This speeds up large directory searches. JRA.
2903 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2906 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2907 smb_fn_name(req
->cmd
),
2908 mask
, directory
, dirtype
, numentries
) );
2910 /* Check if we can close the dirptr */
2911 if(close_after_request
|| (finished
&& close_if_end
)) {
2912 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2913 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2916 /* Set up the return parameter block */
2917 SSVAL(params
,0,numentries
);
2918 SSVAL(params
,2,finished
);
2919 SSVAL(params
,4,0); /* Never an EA error */
2920 SSVAL(params
,6,last_entry_off
);
2922 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2928 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2930 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2934 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2936 SMB_ASSERT(extended_info
!= NULL
);
2938 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2939 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2940 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2941 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2942 #ifdef SAMBA_VERSION_REVISION
2943 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2945 extended_info
->samba_subversion
= 0;
2946 #ifdef SAMBA_VERSION_RC_RELEASE
2947 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2949 #ifdef SAMBA_VERSION_PRE_RELEASE
2950 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2953 #ifdef SAMBA_VERSION_VENDOR_PATCH
2954 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2956 extended_info
->samba_gitcommitdate
= 0;
2957 #ifdef SAMBA_VERSION_COMMIT_TIME
2958 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2961 memset(extended_info
->samba_version_string
, 0,
2962 sizeof(extended_info
->samba_version_string
));
2964 snprintf (extended_info
->samba_version_string
,
2965 sizeof(extended_info
->samba_version_string
),
2966 "%s", samba_version_string());
2969 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
2970 TALLOC_CTX
*mem_ctx
,
2971 uint16_t info_level
,
2973 unsigned int max_data_bytes
,
2974 size_t *fixed_portion
,
2975 struct smb_filename
*fname
,
2979 char *pdata
, *end_data
;
2980 int data_len
= 0, len
;
2981 const char *vname
= volume_label(SNUM(conn
));
2982 int snum
= SNUM(conn
);
2983 char *fstype
= lp_fstype(SNUM(conn
));
2984 const char *filename
= NULL
;
2985 uint32 additional_flags
= 0;
2986 struct smb_filename smb_fname
;
2988 NTSTATUS status
= NT_STATUS_OK
;
2990 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2993 filename
= fname
->base_name
;
2997 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2998 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2999 "info level (0x%x) on IPC$.\n",
3000 (unsigned int)info_level
));
3001 return NT_STATUS_ACCESS_DENIED
;
3005 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3007 ZERO_STRUCT(smb_fname
);
3008 smb_fname
.base_name
= discard_const_p(char, filename
);
3010 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3011 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3012 return map_nt_error_from_unix(errno
);
3017 *ppdata
= (char *)SMB_REALLOC(
3018 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3019 if (*ppdata
== NULL
) {
3020 return NT_STATUS_NO_MEMORY
;
3024 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3025 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3029 switch (info_level
) {
3030 case SMB_INFO_ALLOCATION
:
3032 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3034 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3035 return map_nt_error_from_unix(errno
);
3038 block_size
= lp_block_size(snum
);
3039 if (bsize
< block_size
) {
3040 uint64_t factor
= block_size
/bsize
;
3045 if (bsize
> block_size
) {
3046 uint64_t factor
= bsize
/block_size
;
3051 bytes_per_sector
= 512;
3052 sectors_per_unit
= bsize
/bytes_per_sector
;
3054 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3055 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3056 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3058 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3059 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3060 SIVAL(pdata
,l1_cUnit
,dsize
);
3061 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3062 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3066 case SMB_INFO_VOLUME
:
3067 /* Return volume name */
3069 * Add volume serial number - hash of a combination of
3070 * the called hostname and the service name.
3072 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3074 * Win2k3 and previous mess this up by sending a name length
3075 * one byte short. I believe only older clients (OS/2 Win9x) use
3076 * this call so try fixing this by adding a terminating null to
3077 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3081 pdata
+l2_vol_szVolLabel
, vname
,
3082 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3083 STR_NOALIGN
|STR_TERMINATE
);
3084 SCVAL(pdata
,l2_vol_cch
,len
);
3085 data_len
= l2_vol_szVolLabel
+ len
;
3086 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3087 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3091 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3092 case SMB_FS_ATTRIBUTE_INFORMATION
:
3094 additional_flags
= 0;
3095 #if defined(HAVE_SYS_QUOTAS)
3096 additional_flags
|= FILE_VOLUME_QUOTAS
;
3099 if(lp_nt_acl_support(SNUM(conn
))) {
3100 additional_flags
|= FILE_PERSISTENT_ACLS
;
3103 /* Capabilities are filled in at connection time through STATVFS call */
3104 additional_flags
|= conn
->fs_capabilities
;
3105 additional_flags
|= lp_parm_int(conn
->params
->service
,
3106 "share", "fake_fscaps",
3109 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3110 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3111 additional_flags
); /* FS ATTRIBUTES */
3113 SIVAL(pdata
,4,255); /* Max filename component length */
3114 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3115 and will think we can't do long filenames */
3116 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3117 PTR_DIFF(end_data
, pdata
+12),
3120 data_len
= 12 + len
;
3121 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3122 /* the client only requested a portion of the
3124 data_len
= max_data_bytes
;
3125 status
= STATUS_BUFFER_OVERFLOW
;
3127 *fixed_portion
= 16;
3130 case SMB_QUERY_FS_LABEL_INFO
:
3131 case SMB_FS_LABEL_INFORMATION
:
3132 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3133 PTR_DIFF(end_data
, pdata
+4), 0);
3138 case SMB_QUERY_FS_VOLUME_INFO
:
3139 case SMB_FS_VOLUME_INFORMATION
:
3142 * Add volume serial number - hash of a combination of
3143 * the called hostname and the service name.
3145 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3146 (str_checksum(get_local_machine_name())<<16));
3148 /* Max label len is 32 characters. */
3149 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3150 PTR_DIFF(end_data
, pdata
+18),
3152 SIVAL(pdata
,12,len
);
3155 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3156 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3157 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3158 /* the client only requested a portion of the
3160 data_len
= max_data_bytes
;
3161 status
= STATUS_BUFFER_OVERFLOW
;
3166 case SMB_QUERY_FS_SIZE_INFO
:
3167 case SMB_FS_SIZE_INFORMATION
:
3169 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3171 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3172 return map_nt_error_from_unix(errno
);
3174 block_size
= lp_block_size(snum
);
3175 if (bsize
< block_size
) {
3176 uint64_t factor
= block_size
/bsize
;
3181 if (bsize
> block_size
) {
3182 uint64_t factor
= bsize
/block_size
;
3187 bytes_per_sector
= 512;
3188 sectors_per_unit
= bsize
/bytes_per_sector
;
3189 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3190 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3191 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3192 SBIG_UINT(pdata
,0,dsize
);
3193 SBIG_UINT(pdata
,8,dfree
);
3194 SIVAL(pdata
,16,sectors_per_unit
);
3195 SIVAL(pdata
,20,bytes_per_sector
);
3196 *fixed_portion
= 24;
3200 case SMB_FS_FULL_SIZE_INFORMATION
:
3202 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3204 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3205 return map_nt_error_from_unix(errno
);
3207 block_size
= lp_block_size(snum
);
3208 if (bsize
< block_size
) {
3209 uint64_t factor
= block_size
/bsize
;
3214 if (bsize
> block_size
) {
3215 uint64_t factor
= bsize
/block_size
;
3220 bytes_per_sector
= 512;
3221 sectors_per_unit
= bsize
/bytes_per_sector
;
3222 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3224 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3225 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3226 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3227 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3228 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3229 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3230 *fixed_portion
= 32;
3234 case SMB_QUERY_FS_DEVICE_INFO
:
3235 case SMB_FS_DEVICE_INFORMATION
:
3237 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3239 if (!CAN_WRITE(conn
)) {
3240 characteristics
|= FILE_READ_ONLY_DEVICE
;
3243 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3244 SIVAL(pdata
,4,characteristics
);
3249 #ifdef HAVE_SYS_QUOTAS
3250 case SMB_FS_QUOTA_INFORMATION
:
3252 * what we have to send --metze:
3254 * Unknown1: 24 NULL bytes
3255 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3256 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3257 * Quota Flags: 2 byte :
3258 * Unknown3: 6 NULL bytes
3262 * details for Quota Flags:
3264 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3265 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3266 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3267 * 0x0001 Enable Quotas: enable quota for this fs
3271 /* we need to fake up a fsp here,
3272 * because its not send in this call
3275 SMB_NTQUOTA_STRUCT quotas
;
3278 ZERO_STRUCT(quotas
);
3284 if (get_current_uid(conn
) != 0) {
3285 DEBUG(0,("set_user_quota: access_denied "
3286 "service [%s] user [%s]\n",
3287 lp_servicename(SNUM(conn
)),
3288 conn
->session_info
->unix_name
));
3289 return NT_STATUS_ACCESS_DENIED
;
3292 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3293 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3294 return map_nt_error_from_unix(errno
);
3299 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3300 lp_servicename(SNUM(conn
))));
3302 /* Unknown1 24 NULL bytes*/
3303 SBIG_UINT(pdata
,0,(uint64_t)0);
3304 SBIG_UINT(pdata
,8,(uint64_t)0);
3305 SBIG_UINT(pdata
,16,(uint64_t)0);
3307 /* Default Soft Quota 8 bytes */
3308 SBIG_UINT(pdata
,24,quotas
.softlim
);
3310 /* Default Hard Quota 8 bytes */
3311 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3313 /* Quota flag 2 bytes */
3314 SSVAL(pdata
,40,quotas
.qflags
);
3316 /* Unknown3 6 NULL bytes */
3322 #endif /* HAVE_SYS_QUOTAS */
3323 case SMB_FS_OBJECTID_INFORMATION
:
3325 unsigned char objid
[16];
3326 struct smb_extended_info extended_info
;
3327 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3328 samba_extended_info_version (&extended_info
);
3329 SIVAL(pdata
,16,extended_info
.samba_magic
);
3330 SIVAL(pdata
,20,extended_info
.samba_version
);
3331 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3332 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3333 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3339 * Query the version and capabilities of the CIFS UNIX extensions
3343 case SMB_QUERY_CIFS_UNIX_INFO
:
3345 bool large_write
= lp_min_receive_file_size() &&
3346 !srv_is_signing_active(conn
->sconn
);
3347 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3348 int encrypt_caps
= 0;
3350 if (!lp_unix_extensions()) {
3351 return NT_STATUS_INVALID_LEVEL
;
3354 switch (conn
->encrypt_level
) {
3360 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3363 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3364 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3365 large_write
= false;
3371 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3372 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3374 /* We have POSIX ACLs, pathname, encryption,
3375 * large read/write, and locking capability. */
3377 SBIG_UINT(pdata
,4,((uint64_t)(
3378 CIFS_UNIX_POSIX_ACLS_CAP
|
3379 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3380 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3381 CIFS_UNIX_EXTATTR_CAP
|
3382 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3384 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3386 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3390 case SMB_QUERY_POSIX_FS_INFO
:
3393 vfs_statvfs_struct svfs
;
3395 if (!lp_unix_extensions()) {
3396 return NT_STATUS_INVALID_LEVEL
;
3399 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3403 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3404 SIVAL(pdata
,4,svfs
.BlockSize
);
3405 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3406 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3407 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3408 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3409 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3410 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3411 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3413 } else if (rc
== EOPNOTSUPP
) {
3414 return NT_STATUS_INVALID_LEVEL
;
3415 #endif /* EOPNOTSUPP */
3417 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3418 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3420 *fixed_portion
= 24;
3424 case SMB_QUERY_POSIX_WHOAMI
:
3430 if (!lp_unix_extensions()) {
3431 return NT_STATUS_INVALID_LEVEL
;
3434 if (max_data_bytes
< 40) {
3435 return NT_STATUS_BUFFER_TOO_SMALL
;
3438 /* We ARE guest if global_sid_Builtin_Guests is
3439 * in our list of SIDs.
3441 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3442 conn
->session_info
->security_token
)) {
3443 flags
|= SMB_WHOAMI_GUEST
;
3446 /* We are NOT guest if global_sid_Authenticated_Users
3447 * is in our list of SIDs.
3449 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3450 conn
->session_info
->security_token
)) {
3451 flags
&= ~SMB_WHOAMI_GUEST
;
3454 /* NOTE: 8 bytes for UID/GID, irrespective of native
3455 * platform size. This matches
3456 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3458 data_len
= 4 /* flags */
3465 + 4 /* pad/reserved */
3466 + (conn
->session_info
->utok
.ngroups
* 8)
3468 + (conn
->session_info
->security_token
->num_sids
*
3472 SIVAL(pdata
, 0, flags
);
3473 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3475 (uint64_t)conn
->session_info
->utok
.uid
);
3476 SBIG_UINT(pdata
, 16,
3477 (uint64_t)conn
->session_info
->utok
.gid
);
3480 if (data_len
>= max_data_bytes
) {
3481 /* Potential overflow, skip the GIDs and SIDs. */
3483 SIVAL(pdata
, 24, 0); /* num_groups */
3484 SIVAL(pdata
, 28, 0); /* num_sids */
3485 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3486 SIVAL(pdata
, 36, 0); /* reserved */
3492 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3493 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3495 /* We walk the SID list twice, but this call is fairly
3496 * infrequent, and I don't expect that it's performance
3497 * sensitive -- jpeach
3499 for (i
= 0, sid_bytes
= 0;
3500 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3501 sid_bytes
+= ndr_size_dom_sid(
3502 &conn
->session_info
->security_token
->sids
[i
],
3506 /* SID list byte count */
3507 SIVAL(pdata
, 32, sid_bytes
);
3509 /* 4 bytes pad/reserved - must be zero */
3510 SIVAL(pdata
, 36, 0);
3514 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3515 SBIG_UINT(pdata
, data_len
,
3516 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3522 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3523 int sid_len
= ndr_size_dom_sid(
3524 &conn
->session_info
->security_token
->sids
[i
],
3527 sid_linearize(pdata
+ data_len
, sid_len
,
3528 &conn
->session_info
->security_token
->sids
[i
]);
3529 data_len
+= sid_len
;
3535 case SMB_MAC_QUERY_FS_INFO
:
3537 * Thursby MAC extension... ONLY on NTFS filesystems
3538 * once we do streams then we don't need this
3540 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3542 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3547 return NT_STATUS_INVALID_LEVEL
;
3550 *ret_data_len
= data_len
;
3554 /****************************************************************************
3555 Reply to a TRANS2_QFSINFO (query filesystem info).
3556 ****************************************************************************/
3558 static void call_trans2qfsinfo(connection_struct
*conn
,
3559 struct smb_request
*req
,
3560 char **pparams
, int total_params
,
3561 char **ppdata
, int total_data
,
3562 unsigned int max_data_bytes
)
3564 char *params
= *pparams
;
3565 uint16_t info_level
;
3567 size_t fixed_portion
;
3570 if (total_params
< 2) {
3571 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3575 info_level
= SVAL(params
,0);
3577 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3578 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3579 DEBUG(0,("call_trans2qfsinfo: encryption required "
3580 "and info level 0x%x sent.\n",
3581 (unsigned int)info_level
));
3582 exit_server_cleanly("encryption required "
3588 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3590 status
= smbd_do_qfsinfo(conn
, req
,
3597 if (!NT_STATUS_IS_OK(status
)) {
3598 reply_nterror(req
, status
);
3602 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3605 DEBUG( 4, ( "%s info_level = %d\n",
3606 smb_fn_name(req
->cmd
), info_level
) );
3611 /****************************************************************************
3612 Reply to a TRANS2_SETFSINFO (set filesystem info).
3613 ****************************************************************************/
3615 static void call_trans2setfsinfo(connection_struct
*conn
,
3616 struct smb_request
*req
,
3617 char **pparams
, int total_params
,
3618 char **ppdata
, int total_data
,
3619 unsigned int max_data_bytes
)
3621 char *pdata
= *ppdata
;
3622 char *params
= *pparams
;
3625 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3628 if (total_params
< 4) {
3629 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3631 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3635 info_level
= SVAL(params
,2);
3638 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3639 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3640 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3641 "info level (0x%x) on IPC$.\n",
3642 (unsigned int)info_level
));
3643 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3648 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3649 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3650 DEBUG(0,("call_trans2setfsinfo: encryption required "
3651 "and info level 0x%x sent.\n",
3652 (unsigned int)info_level
));
3653 exit_server_cleanly("encryption required "
3659 switch(info_level
) {
3660 case SMB_SET_CIFS_UNIX_INFO
:
3662 uint16 client_unix_major
;
3663 uint16 client_unix_minor
;
3664 uint32 client_unix_cap_low
;
3665 uint32 client_unix_cap_high
;
3667 if (!lp_unix_extensions()) {
3669 NT_STATUS_INVALID_LEVEL
);
3673 /* There should be 12 bytes of capabilities set. */
3674 if (total_data
< 8) {
3677 NT_STATUS_INVALID_PARAMETER
);
3680 client_unix_major
= SVAL(pdata
,0);
3681 client_unix_minor
= SVAL(pdata
,2);
3682 client_unix_cap_low
= IVAL(pdata
,4);
3683 client_unix_cap_high
= IVAL(pdata
,8);
3684 /* Just print these values for now. */
3685 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3686 cap_low = 0x%x, cap_high = 0x%x\n",
3687 (unsigned int)client_unix_major
,
3688 (unsigned int)client_unix_minor
,
3689 (unsigned int)client_unix_cap_low
,
3690 (unsigned int)client_unix_cap_high
));
3692 /* Here is where we must switch to posix pathname processing... */
3693 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3694 lp_set_posix_pathnames();
3695 mangle_change_to_posix();
3698 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3699 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3700 /* Client that knows how to do posix locks,
3701 * but not posix open/mkdir operations. Set a
3702 * default type for read/write checks. */
3704 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3710 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3713 size_t param_len
= 0;
3714 size_t data_len
= total_data
;
3716 if (!lp_unix_extensions()) {
3719 NT_STATUS_INVALID_LEVEL
);
3723 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3726 NT_STATUS_NOT_SUPPORTED
);
3730 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3731 DEBUG( 2,("call_trans2setfsinfo: "
3732 "request transport encryption disabled"
3733 "with 'fork echo handler = yes'\n"));
3736 NT_STATUS_NOT_SUPPORTED
);
3740 DEBUG( 4,("call_trans2setfsinfo: "
3741 "request transport encryption.\n"));
3743 status
= srv_request_encryption_setup(conn
,
3744 (unsigned char **)ppdata
,
3746 (unsigned char **)pparams
,
3749 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3750 !NT_STATUS_IS_OK(status
)) {
3751 reply_nterror(req
, status
);
3755 send_trans2_replies(conn
, req
,
3762 if (NT_STATUS_IS_OK(status
)) {
3763 /* Server-side transport
3764 * encryption is now *on*. */
3765 status
= srv_encryption_start(conn
);
3766 if (!NT_STATUS_IS_OK(status
)) {
3767 exit_server_cleanly(
3768 "Failure in setting "
3769 "up encrypted transport");
3775 case SMB_FS_QUOTA_INFORMATION
:
3777 files_struct
*fsp
= NULL
;
3778 SMB_NTQUOTA_STRUCT quotas
;
3780 ZERO_STRUCT(quotas
);
3783 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3784 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3785 lp_servicename(SNUM(conn
)),
3786 conn
->session_info
->unix_name
));
3787 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3791 /* note: normaly there're 48 bytes,
3792 * but we didn't use the last 6 bytes for now
3795 fsp
= file_fsp(req
, SVAL(params
,0));
3797 if (!check_fsp_ntquota_handle(conn
, req
,
3799 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3801 req
, NT_STATUS_INVALID_HANDLE
);
3805 if (total_data
< 42) {
3806 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3810 NT_STATUS_INVALID_PARAMETER
);
3814 /* unknown_1 24 NULL bytes in pdata*/
3816 /* the soft quotas 8 bytes (uint64_t)*/
3817 quotas
.softlim
= BVAL(pdata
,24);
3819 /* the hard quotas 8 bytes (uint64_t)*/
3820 quotas
.hardlim
= BVAL(pdata
,32);
3822 /* quota_flags 2 bytes **/
3823 quotas
.qflags
= SVAL(pdata
,40);
3825 /* unknown_2 6 NULL bytes follow*/
3827 /* now set the quotas */
3828 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3829 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3830 reply_nterror(req
, map_nt_error_from_unix(errno
));
3837 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3839 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3845 * sending this reply works fine,
3846 * but I'm not sure it's the same
3847 * like windows do...
3850 reply_outbuf(req
, 10, 0);
3853 #if defined(HAVE_POSIX_ACLS)
3854 /****************************************************************************
3855 Utility function to count the number of entries in a POSIX acl.
3856 ****************************************************************************/
3858 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3860 unsigned int ace_count
= 0;
3861 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3862 SMB_ACL_ENTRY_T entry
;
3864 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3866 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3867 entry_id
= SMB_ACL_NEXT_ENTRY
;
3874 /****************************************************************************
3875 Utility function to marshall a POSIX acl into wire format.
3876 ****************************************************************************/
3878 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3880 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3881 SMB_ACL_ENTRY_T entry
;
3883 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3884 SMB_ACL_TAG_T tagtype
;
3885 SMB_ACL_PERMSET_T permset
;
3886 unsigned char perms
= 0;
3887 unsigned int own_grp
;
3890 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3891 entry_id
= SMB_ACL_NEXT_ENTRY
;
3894 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3895 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3899 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3900 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3904 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3905 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3906 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3908 SCVAL(pdata
,1,perms
);
3911 case SMB_ACL_USER_OBJ
:
3912 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3913 own_grp
= (unsigned int)pst
->st_ex_uid
;
3914 SIVAL(pdata
,2,own_grp
);
3919 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3924 own_grp
= (unsigned int)*puid
;
3925 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3926 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3927 SIVAL(pdata
,2,own_grp
);
3931 case SMB_ACL_GROUP_OBJ
:
3932 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3933 own_grp
= (unsigned int)pst
->st_ex_gid
;
3934 SIVAL(pdata
,2,own_grp
);
3939 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3941 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3944 own_grp
= (unsigned int)*pgid
;
3945 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3946 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3947 SIVAL(pdata
,2,own_grp
);
3952 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3953 SIVAL(pdata
,2,0xFFFFFFFF);
3954 SIVAL(pdata
,6,0xFFFFFFFF);
3957 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3958 SIVAL(pdata
,2,0xFFFFFFFF);
3959 SIVAL(pdata
,6,0xFFFFFFFF);
3962 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3965 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3972 /****************************************************************************
3973 Store the FILE_UNIX_BASIC info.
3974 ****************************************************************************/
3976 static char *store_file_unix_basic(connection_struct
*conn
,
3979 const SMB_STRUCT_STAT
*psbuf
)
3981 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3983 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3984 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3986 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3989 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3992 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3993 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3994 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3997 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4001 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4005 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4008 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
4012 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
4016 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4019 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4023 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4030 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4031 * the chflags(2) (or equivalent) flags.
4033 * XXX: this really should be behind the VFS interface. To do this, we would
4034 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4035 * Each VFS module could then implement its own mapping as appropriate for the
4036 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4038 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4042 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4046 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4050 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4054 { UF_HIDDEN
, EXT_HIDDEN
},
4057 /* Do not remove. We need to guarantee that this array has at least one
4058 * entry to build on HP-UX.
4064 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4065 uint32
*smb_fflags
, uint32
*smb_fmask
)
4069 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4070 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4071 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4072 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4077 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4078 const uint32 smb_fflags
,
4079 const uint32 smb_fmask
,
4082 uint32 max_fmask
= 0;
4085 *stat_fflags
= psbuf
->st_ex_flags
;
4087 /* For each flags requested in smb_fmask, check the state of the
4088 * corresponding flag in smb_fflags and set or clear the matching
4092 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4093 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4094 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4095 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4096 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4098 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4103 /* If smb_fmask is asking to set any bits that are not supported by
4104 * our flag mappings, we should fail.
4106 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4114 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4115 * of file flags and birth (create) time.
4117 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4120 const SMB_STRUCT_STAT
*psbuf
)
4122 uint32 file_flags
= 0;
4123 uint32 flags_mask
= 0;
4125 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4127 /* Create (birth) time 64 bit */
4128 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4131 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4132 SIVAL(pdata
, 0, file_flags
); /* flags */
4133 SIVAL(pdata
, 4, flags_mask
); /* mask */
4139 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4140 const struct stream_struct
*streams
,
4142 unsigned int max_data_bytes
,
4143 unsigned int *data_size
)
4146 unsigned int ofs
= 0;
4148 if (max_data_bytes
< 32) {
4149 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4152 for (i
= 0; i
< num_streams
; i
++) {
4153 unsigned int next_offset
;
4155 smb_ucs2_t
*namebuf
;
4157 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4158 streams
[i
].name
, &namelen
) ||
4161 return NT_STATUS_INVALID_PARAMETER
;
4165 * name_buf is now null-terminated, we need to marshall as not
4172 * We cannot overflow ...
4174 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4175 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4177 TALLOC_FREE(namebuf
);
4178 return STATUS_BUFFER_OVERFLOW
;
4181 SIVAL(data
, ofs
+4, namelen
);
4182 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4183 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4184 memcpy(data
+ofs
+24, namebuf
, namelen
);
4185 TALLOC_FREE(namebuf
);
4187 next_offset
= ofs
+ 24 + namelen
;
4189 if (i
== num_streams
-1) {
4190 SIVAL(data
, ofs
, 0);
4193 unsigned int align
= ndr_align_size(next_offset
, 8);
4195 if ((next_offset
+ align
) > max_data_bytes
) {
4196 DEBUG(10, ("refusing to overflow align "
4197 "reply at stream %u\n",
4199 TALLOC_FREE(namebuf
);
4200 return STATUS_BUFFER_OVERFLOW
;
4203 memset(data
+next_offset
, 0, align
);
4204 next_offset
+= align
;
4206 SIVAL(data
, ofs
, next_offset
- ofs
);
4213 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4217 return NT_STATUS_OK
;
4220 /****************************************************************************
4221 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4222 ****************************************************************************/
4224 static void call_trans2qpipeinfo(connection_struct
*conn
,
4225 struct smb_request
*req
,
4226 unsigned int tran_call
,
4227 char **pparams
, int total_params
,
4228 char **ppdata
, int total_data
,
4229 unsigned int max_data_bytes
)
4231 char *params
= *pparams
;
4232 char *pdata
= *ppdata
;
4233 unsigned int data_size
= 0;
4234 unsigned int param_size
= 2;
4239 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4243 if (total_params
< 4) {
4244 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4248 fsp
= file_fsp(req
, SVAL(params
,0));
4249 if (!fsp_is_np(fsp
)) {
4250 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4254 info_level
= SVAL(params
,2);
4256 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4257 if (*pparams
== NULL
) {
4258 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4263 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4264 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4265 if (*ppdata
== NULL
) {
4266 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4271 switch (info_level
) {
4272 case SMB_FILE_STANDARD_INFORMATION
:
4274 SOFF_T(pdata
,0,4096LL);
4281 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4285 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4291 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4292 TALLOC_CTX
*mem_ctx
,
4293 uint16_t info_level
,
4295 struct smb_filename
*smb_fname
,
4296 bool delete_pending
,
4297 struct timespec write_time_ts
,
4298 struct ea_list
*ea_list
,
4299 int lock_data_count
,
4302 unsigned int max_data_bytes
,
4303 size_t *fixed_portion
,
4305 unsigned int *pdata_size
)
4307 char *pdata
= *ppdata
;
4308 char *dstart
, *dend
;
4309 unsigned int data_size
;
4310 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4311 time_t create_time
, mtime
, atime
, c_time
;
4312 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4319 uint64_t file_size
= 0;
4321 uint64_t allocation_size
= 0;
4322 uint64_t file_index
= 0;
4323 uint32_t access_mask
= 0;
4325 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4326 return NT_STATUS_INVALID_LEVEL
;
4329 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4330 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4331 info_level
, max_data_bytes
));
4333 mode
= dos_mode(conn
, smb_fname
);
4334 nlink
= psbuf
->st_ex_nlink
;
4336 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4340 if ((nlink
> 0) && delete_pending
) {
4344 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4345 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4346 if (*ppdata
== NULL
) {
4347 return NT_STATUS_NO_MEMORY
;
4351 dend
= dstart
+ data_size
- 1;
4353 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4354 update_stat_ex_mtime(psbuf
, write_time_ts
);
4357 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4358 mtime_ts
= psbuf
->st_ex_mtime
;
4359 atime_ts
= psbuf
->st_ex_atime
;
4360 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4362 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4363 dos_filetime_timespec(&create_time_ts
);
4364 dos_filetime_timespec(&mtime_ts
);
4365 dos_filetime_timespec(&atime_ts
);
4366 dos_filetime_timespec(&ctime_ts
);
4369 create_time
= convert_timespec_to_time_t(create_time_ts
);
4370 mtime
= convert_timespec_to_time_t(mtime_ts
);
4371 atime
= convert_timespec_to_time_t(atime_ts
);
4372 c_time
= convert_timespec_to_time_t(ctime_ts
);
4374 p
= strrchr_m(smb_fname
->base_name
,'/');
4376 base_name
= smb_fname
->base_name
;
4380 /* NT expects the name to be in an exact form of the *full*
4381 filename. See the trans2 torture test */
4382 if (ISDOT(base_name
)) {
4383 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4385 return NT_STATUS_NO_MEMORY
;
4388 dos_fname
= talloc_asprintf(mem_ctx
,
4390 smb_fname
->base_name
);
4392 return NT_STATUS_NO_MEMORY
;
4394 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4395 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4396 smb_fname
->stream_name
);
4398 return NT_STATUS_NO_MEMORY
;
4402 string_replace(dos_fname
, '/', '\\');
4405 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4408 /* Do we have this path open ? */
4410 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4411 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4412 if (fsp1
&& fsp1
->initial_allocation_size
) {
4413 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4417 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4418 file_size
= get_file_size_stat(psbuf
);
4422 pos
= fsp
->fh
->position_information
;
4426 access_mask
= fsp
->access_mask
;
4428 /* GENERIC_EXECUTE mapping from Windows */
4429 access_mask
= 0x12019F;
4432 /* This should be an index number - looks like
4435 I think this causes us to fail the IFSKIT
4436 BasicFileInformationTest. -tpot */
4437 file_index
= get_FileIndex(conn
, psbuf
);
4441 switch (info_level
) {
4442 case SMB_INFO_STANDARD
:
4443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4445 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4446 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4447 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4448 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4449 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4450 SSVAL(pdata
,l1_attrFile
,mode
);
4453 case SMB_INFO_QUERY_EA_SIZE
:
4455 unsigned int ea_size
=
4456 estimate_ea_size(conn
, fsp
,
4457 smb_fname
->base_name
);
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4460 srv_put_dos_date2(pdata
,0,create_time
);
4461 srv_put_dos_date2(pdata
,4,atime
);
4462 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4463 SIVAL(pdata
,12,(uint32
)file_size
);
4464 SIVAL(pdata
,16,(uint32
)allocation_size
);
4465 SSVAL(pdata
,20,mode
);
4466 SIVAL(pdata
,22,ea_size
);
4470 case SMB_INFO_IS_NAME_VALID
:
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4473 /* os/2 needs this ? really ?*/
4474 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4476 /* This is only reached for qpathinfo */
4480 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4482 size_t total_ea_len
= 0;
4483 struct ea_list
*ea_file_list
= NULL
;
4485 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4488 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4489 smb_fname
->base_name
,
4491 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4493 if (!ea_list
|| (total_ea_len
> data_size
)) {
4495 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4499 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4503 case SMB_INFO_QUERY_ALL_EAS
:
4505 /* We have data_size bytes to put EA's into. */
4506 size_t total_ea_len
= 0;
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4510 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4511 smb_fname
->base_name
,
4513 if (!ea_list
|| (total_ea_len
> data_size
)) {
4515 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4519 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4523 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4525 /* This is FileFullEaInformation - 0xF which maps to
4526 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4528 /* We have data_size bytes to put EA's into. */
4529 size_t total_ea_len
= 0;
4530 struct ea_list
*ea_file_list
= NULL
;
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4534 /*TODO: add filtering and index handling */
4537 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4538 smb_fname
->base_name
,
4540 if (!ea_file_list
) {
4541 return NT_STATUS_NO_EAS_ON_FILE
;
4544 status
= fill_ea_chained_buffer(mem_ctx
,
4548 conn
, ea_file_list
);
4549 if (!NT_STATUS_IS_OK(status
)) {
4555 case SMB_FILE_BASIC_INFORMATION
:
4556 case SMB_QUERY_FILE_BASIC_INFO
:
4558 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4560 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4562 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4566 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4567 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4568 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4569 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4570 SIVAL(pdata
,32,mode
);
4572 DEBUG(5,("SMB_QFBI - "));
4573 DEBUG(5,("create: %s ", ctime(&create_time
)));
4574 DEBUG(5,("access: %s ", ctime(&atime
)));
4575 DEBUG(5,("write: %s ", ctime(&mtime
)));
4576 DEBUG(5,("change: %s ", ctime(&c_time
)));
4577 DEBUG(5,("mode: %x\n", mode
));
4578 *fixed_portion
= data_size
;
4581 case SMB_FILE_STANDARD_INFORMATION
:
4582 case SMB_QUERY_FILE_STANDARD_INFO
:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4586 SOFF_T(pdata
,0,allocation_size
);
4587 SOFF_T(pdata
,8,file_size
);
4588 SIVAL(pdata
,16,nlink
);
4589 SCVAL(pdata
,20,delete_pending
?1:0);
4590 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4591 SSVAL(pdata
,22,0); /* Padding. */
4592 *fixed_portion
= 24;
4595 case SMB_FILE_EA_INFORMATION
:
4596 case SMB_QUERY_FILE_EA_INFO
:
4598 unsigned int ea_size
=
4599 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4603 SIVAL(pdata
,0,ea_size
);
4607 /* Get the 8.3 name - used if NT SMB was negotiated. */
4608 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4609 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4612 char mangled_name
[13];
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4614 if (!name_to_8_3(base_name
,mangled_name
,
4615 True
,conn
->params
)) {
4616 return NT_STATUS_NO_MEMORY
;
4618 len
= srvstr_push(dstart
, flags2
,
4619 pdata
+4, mangled_name
,
4620 PTR_DIFF(dend
, pdata
+4),
4622 data_size
= 4 + len
;
4628 case SMB_QUERY_FILE_NAME_INFO
:
4632 this must be *exactly* right for ACLs on mapped drives to work
4634 len
= srvstr_push(dstart
, flags2
,
4636 PTR_DIFF(dend
, pdata
+4),
4638 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4639 data_size
= 4 + len
;
4644 case SMB_FILE_ALLOCATION_INFORMATION
:
4645 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4648 SOFF_T(pdata
,0,allocation_size
);
4651 case SMB_FILE_END_OF_FILE_INFORMATION
:
4652 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4655 SOFF_T(pdata
,0,file_size
);
4658 case SMB_QUERY_FILE_ALL_INFO
:
4659 case SMB_FILE_ALL_INFORMATION
:
4662 unsigned int ea_size
=
4663 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4665 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4666 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4667 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4668 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4669 SIVAL(pdata
,32,mode
);
4670 SIVAL(pdata
,36,0); /* padding. */
4672 SOFF_T(pdata
,0,allocation_size
);
4673 SOFF_T(pdata
,8,file_size
);
4674 SIVAL(pdata
,16,nlink
);
4675 SCVAL(pdata
,20,delete_pending
);
4676 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4679 SIVAL(pdata
,0,ea_size
);
4680 pdata
+= 4; /* EA info */
4681 len
= srvstr_push(dstart
, flags2
,
4683 PTR_DIFF(dend
, pdata
+4),
4687 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4688 *fixed_portion
= 10;
4692 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4695 unsigned int ea_size
=
4696 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4698 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4699 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4700 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4701 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4702 SIVAL(pdata
, 0x20, mode
);
4703 SIVAL(pdata
, 0x24, 0); /* padding. */
4704 SBVAL(pdata
, 0x28, allocation_size
);
4705 SBVAL(pdata
, 0x30, file_size
);
4706 SIVAL(pdata
, 0x38, nlink
);
4707 SCVAL(pdata
, 0x3C, delete_pending
);
4708 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4709 SSVAL(pdata
, 0x3E, 0); /* padding */
4710 SBVAL(pdata
, 0x40, file_index
);
4711 SIVAL(pdata
, 0x48, ea_size
);
4712 SIVAL(pdata
, 0x4C, access_mask
);
4713 SBVAL(pdata
, 0x50, pos
);
4714 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4715 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4719 len
= srvstr_push(dstart
, flags2
,
4721 PTR_DIFF(dend
, pdata
+4),
4725 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4726 *fixed_portion
= 104;
4729 case SMB_FILE_INTERNAL_INFORMATION
:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4732 SBVAL(pdata
, 0, file_index
);
4737 case SMB_FILE_ACCESS_INFORMATION
:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4739 SIVAL(pdata
, 0, access_mask
);
4744 case SMB_FILE_NAME_INFORMATION
:
4745 /* Pathname with leading '\'. */
4748 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4750 SIVAL(pdata
,0,byte_len
);
4751 data_size
= 4 + byte_len
;
4755 case SMB_FILE_DISPOSITION_INFORMATION
:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4758 SCVAL(pdata
,0,delete_pending
);
4762 case SMB_FILE_POSITION_INFORMATION
:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4765 SOFF_T(pdata
,0,pos
);
4769 case SMB_FILE_MODE_INFORMATION
:
4770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4771 SIVAL(pdata
,0,mode
);
4776 case SMB_FILE_ALIGNMENT_INFORMATION
:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4778 SIVAL(pdata
,0,0); /* No alignment needed. */
4784 * NT4 server just returns "invalid query" to this - if we try
4785 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4788 /* The first statement above is false - verified using Thursby
4789 * client against NT4 -- gcolley.
4791 case SMB_QUERY_FILE_STREAM_INFO
:
4792 case SMB_FILE_STREAM_INFORMATION
: {
4793 unsigned int num_streams
= 0;
4794 struct stream_struct
*streams
= NULL
;
4796 DEBUG(10,("smbd_do_qfilepathinfo: "
4797 "SMB_FILE_STREAM_INFORMATION\n"));
4799 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4800 return NT_STATUS_INVALID_PARAMETER
;
4803 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4804 talloc_tos(), &num_streams
, &streams
);
4806 if (!NT_STATUS_IS_OK(status
)) {
4807 DEBUG(10, ("could not get stream info: %s\n",
4808 nt_errstr(status
)));
4812 status
= marshall_stream_info(num_streams
, streams
,
4813 pdata
, max_data_bytes
,
4816 if (!NT_STATUS_IS_OK(status
)) {
4817 DEBUG(10, ("marshall_stream_info failed: %s\n",
4818 nt_errstr(status
)));
4819 TALLOC_FREE(streams
);
4823 TALLOC_FREE(streams
);
4825 *fixed_portion
= 32;
4829 case SMB_QUERY_COMPRESSION_INFO
:
4830 case SMB_FILE_COMPRESSION_INFORMATION
:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4832 SOFF_T(pdata
,0,file_size
);
4833 SIVAL(pdata
,8,0); /* ??? */
4834 SIVAL(pdata
,12,0); /* ??? */
4836 *fixed_portion
= 16;
4839 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4841 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4842 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4843 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4844 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4845 SOFF_T(pdata
,32,allocation_size
);
4846 SOFF_T(pdata
,40,file_size
);
4847 SIVAL(pdata
,48,mode
);
4848 SIVAL(pdata
,52,0); /* ??? */
4850 *fixed_portion
= 56;
4853 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4855 SIVAL(pdata
,0,mode
);
4862 * CIFS UNIX Extensions.
4865 case SMB_QUERY_FILE_UNIX_BASIC
:
4867 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4868 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4870 DEBUG(4,("smbd_do_qfilepathinfo: "
4871 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4872 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4876 case SMB_QUERY_FILE_UNIX_INFO2
:
4878 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4879 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4883 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4885 for (i
=0; i
<100; i
++)
4886 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4892 case SMB_QUERY_FILE_UNIX_LINK
:
4895 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4898 return NT_STATUS_NO_MEMORY
;
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4903 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4904 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4907 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4909 len
= SMB_VFS_READLINK(conn
,
4910 smb_fname
->base_name
,
4913 return map_nt_error_from_unix(errno
);
4916 len
= srvstr_push(dstart
, flags2
,
4918 PTR_DIFF(dend
, pdata
),
4921 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4926 #if defined(HAVE_POSIX_ACLS)
4927 case SMB_QUERY_POSIX_ACL
:
4929 SMB_ACL_T file_acl
= NULL
;
4930 SMB_ACL_T def_acl
= NULL
;
4931 uint16 num_file_acls
= 0;
4932 uint16 num_def_acls
= 0;
4934 if (fsp
&& fsp
->fh
->fd
!= -1) {
4935 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4938 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4939 smb_fname
->base_name
,
4940 SMB_ACL_TYPE_ACCESS
);
4943 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4944 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4945 "not implemented on "
4946 "filesystem containing %s\n",
4947 smb_fname
->base_name
));
4948 return NT_STATUS_NOT_IMPLEMENTED
;
4951 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4952 if (fsp
&& fsp
->is_directory
) {
4954 SMB_VFS_SYS_ACL_GET_FILE(
4956 fsp
->fsp_name
->base_name
,
4957 SMB_ACL_TYPE_DEFAULT
);
4960 SMB_VFS_SYS_ACL_GET_FILE(
4962 smb_fname
->base_name
,
4963 SMB_ACL_TYPE_DEFAULT
);
4965 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4968 num_file_acls
= count_acl_entries(conn
, file_acl
);
4969 num_def_acls
= count_acl_entries(conn
, def_acl
);
4971 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4972 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4974 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4975 SMB_POSIX_ACL_HEADER_SIZE
) ));
4977 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4980 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4982 return NT_STATUS_BUFFER_TOO_SMALL
;
4985 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4986 SSVAL(pdata
,2,num_file_acls
);
4987 SSVAL(pdata
,4,num_def_acls
);
4988 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4990 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4993 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4995 return NT_STATUS_INTERNAL_ERROR
;
4997 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4999 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
5002 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
5004 return NT_STATUS_INTERNAL_ERROR
;
5008 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
5011 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
5013 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5019 case SMB_QUERY_POSIX_LOCK
:
5024 enum brl_type lock_type
;
5026 /* We need an open file with a real fd for this. */
5027 if (!fsp
|| fsp
->fh
->fd
== -1) {
5028 return NT_STATUS_INVALID_LEVEL
;
5031 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5032 return NT_STATUS_INVALID_PARAMETER
;
5035 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5036 case POSIX_LOCK_TYPE_READ
:
5037 lock_type
= READ_LOCK
;
5039 case POSIX_LOCK_TYPE_WRITE
:
5040 lock_type
= WRITE_LOCK
;
5042 case POSIX_LOCK_TYPE_UNLOCK
:
5044 /* There's no point in asking for an unlock... */
5045 return NT_STATUS_INVALID_PARAMETER
;
5048 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5049 #if defined(HAVE_LONGLONG)
5050 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5051 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5052 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5053 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5054 #else /* HAVE_LONGLONG */
5055 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5056 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5057 #endif /* HAVE_LONGLONG */
5059 status
= query_lock(fsp
,
5066 if (ERROR_WAS_LOCK_DENIED(status
)) {
5067 /* Here we need to report who has it locked... */
5068 data_size
= POSIX_LOCK_DATA_SIZE
;
5070 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5071 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5072 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5073 #if defined(HAVE_LONGLONG)
5074 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5075 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5076 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5077 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5078 #else /* HAVE_LONGLONG */
5079 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5080 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5081 #endif /* HAVE_LONGLONG */
5083 } else if (NT_STATUS_IS_OK(status
)) {
5084 /* For success we just return a copy of what we sent
5085 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5086 data_size
= POSIX_LOCK_DATA_SIZE
;
5087 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5088 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5096 return NT_STATUS_INVALID_LEVEL
;
5099 *pdata_size
= data_size
;
5100 return NT_STATUS_OK
;
5103 /****************************************************************************
5104 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5105 file name or file id).
5106 ****************************************************************************/
5108 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5109 struct smb_request
*req
,
5110 unsigned int tran_call
,
5111 char **pparams
, int total_params
,
5112 char **ppdata
, int total_data
,
5113 unsigned int max_data_bytes
)
5115 char *params
= *pparams
;
5116 char *pdata
= *ppdata
;
5118 unsigned int data_size
= 0;
5119 unsigned int param_size
= 2;
5120 struct smb_filename
*smb_fname
= NULL
;
5121 bool delete_pending
= False
;
5122 struct timespec write_time_ts
;
5123 files_struct
*fsp
= NULL
;
5124 struct file_id fileid
;
5125 struct ea_list
*ea_list
= NULL
;
5126 int lock_data_count
= 0;
5127 char *lock_data
= NULL
;
5128 size_t fixed_portion
;
5129 NTSTATUS status
= NT_STATUS_OK
;
5132 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5136 ZERO_STRUCT(write_time_ts
);
5138 if (tran_call
== TRANSACT2_QFILEINFO
) {
5139 if (total_params
< 4) {
5140 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5145 call_trans2qpipeinfo(conn
, req
, tran_call
,
5146 pparams
, total_params
,
5152 fsp
= file_fsp(req
, SVAL(params
,0));
5153 info_level
= SVAL(params
,2);
5155 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5157 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5158 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5162 /* Initial check for valid fsp ptr. */
5163 if (!check_fsp_open(conn
, req
, fsp
)) {
5167 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5169 if (!NT_STATUS_IS_OK(status
)) {
5170 reply_nterror(req
, status
);
5174 if(fsp
->fake_file_handle
) {
5176 * This is actually for the QUOTA_FAKE_FILE --metze
5179 /* We know this name is ok, it's already passed the checks. */
5181 } else if(fsp
->fh
->fd
== -1) {
5183 * This is actually a QFILEINFO on a directory
5184 * handle (returned from an NT SMB). NT5.0 seems
5185 * to do this call. JRA.
5188 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5189 /* Always do lstat for UNIX calls. */
5190 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5191 DEBUG(3,("call_trans2qfilepathinfo: "
5192 "SMB_VFS_LSTAT of %s failed "
5194 smb_fname_str_dbg(smb_fname
),
5197 map_nt_error_from_unix(errno
));
5200 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5201 DEBUG(3,("call_trans2qfilepathinfo: "
5202 "SMB_VFS_STAT of %s failed (%s)\n",
5203 smb_fname_str_dbg(smb_fname
),
5206 map_nt_error_from_unix(errno
));
5210 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5211 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5214 * Original code - this is an open file.
5216 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5217 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5218 fsp
->fnum
, strerror(errno
)));
5220 map_nt_error_from_unix(errno
));
5223 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5224 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5230 uint32_t ucf_flags
= 0;
5233 if (total_params
< 7) {
5234 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5238 info_level
= SVAL(params
,0);
5240 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5242 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5243 if (!lp_unix_extensions()) {
5244 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5247 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5248 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5249 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5250 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5254 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5256 STR_TERMINATE
, &status
);
5257 if (!NT_STATUS_IS_OK(status
)) {
5258 reply_nterror(req
, status
);
5262 status
= filename_convert(req
,
5264 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5269 if (!NT_STATUS_IS_OK(status
)) {
5270 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5271 reply_botherror(req
,
5272 NT_STATUS_PATH_NOT_COVERED
,
5273 ERRSRV
, ERRbadpath
);
5276 reply_nterror(req
, status
);
5280 /* If this is a stream, check if there is a delete_pending. */
5281 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5282 && is_ntfs_stream_smb_fname(smb_fname
)) {
5283 struct smb_filename
*smb_fname_base
= NULL
;
5285 /* Create an smb_filename with stream_name == NULL. */
5287 create_synthetic_smb_fname(talloc_tos(),
5288 smb_fname
->base_name
,
5291 if (!NT_STATUS_IS_OK(status
)) {
5292 reply_nterror(req
, status
);
5296 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5297 /* Always do lstat for UNIX calls. */
5298 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_LSTAT of %s failed "
5302 smb_fname_str_dbg(smb_fname_base
),
5304 TALLOC_FREE(smb_fname_base
);
5306 map_nt_error_from_unix(errno
));
5310 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "fileinfo of %s failed "
5314 smb_fname_str_dbg(smb_fname_base
),
5316 TALLOC_FREE(smb_fname_base
);
5318 map_nt_error_from_unix(errno
));
5323 status
= file_name_hash(conn
,
5324 smb_fname_str_dbg(smb_fname_base
),
5326 if (!NT_STATUS_IS_OK(status
)) {
5327 TALLOC_FREE(smb_fname_base
);
5328 reply_nterror(req
, status
);
5332 fileid
= vfs_file_id_from_sbuf(conn
,
5333 &smb_fname_base
->st
);
5334 TALLOC_FREE(smb_fname_base
);
5335 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5336 if (delete_pending
) {
5337 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5342 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5343 /* Always do lstat for UNIX calls. */
5344 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5345 DEBUG(3,("call_trans2qfilepathinfo: "
5346 "SMB_VFS_LSTAT of %s failed (%s)\n",
5347 smb_fname_str_dbg(smb_fname
),
5350 map_nt_error_from_unix(errno
));
5355 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5356 DEBUG(3,("call_trans2qfilepathinfo: "
5357 "SMB_VFS_STAT of %s failed (%s)\n",
5358 smb_fname_str_dbg(smb_fname
),
5361 map_nt_error_from_unix(errno
));
5366 status
= file_name_hash(conn
,
5367 smb_fname_str_dbg(smb_fname
),
5369 if (!NT_STATUS_IS_OK(status
)) {
5370 reply_nterror(req
, status
);
5374 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5375 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5376 if (delete_pending
) {
5377 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5382 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5383 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5384 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5386 /* Pull out any data sent here before we realloc. */
5387 switch (info_level
) {
5388 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5390 /* Pull any EA list from the data portion. */
5393 if (total_data
< 4) {
5395 req
, NT_STATUS_INVALID_PARAMETER
);
5398 ea_size
= IVAL(pdata
,0);
5400 if (total_data
> 0 && ea_size
!= total_data
) {
5401 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5402 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5404 req
, NT_STATUS_INVALID_PARAMETER
);
5408 if (!lp_ea_support(SNUM(conn
))) {
5409 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5413 /* Pull out the list of names. */
5414 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5417 req
, NT_STATUS_INVALID_PARAMETER
);
5423 case SMB_QUERY_POSIX_LOCK
:
5425 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5426 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5430 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5432 req
, NT_STATUS_INVALID_PARAMETER
);
5436 /* Copy the lock range data. */
5437 lock_data
= (char *)TALLOC_MEMDUP(
5438 req
, pdata
, total_data
);
5440 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5443 lock_data_count
= total_data
;
5449 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5450 if (*pparams
== NULL
) {
5451 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5458 * draft-leach-cifs-v1-spec-02.txt
5459 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5462 * The requested information is placed in the Data portion of the
5463 * transaction response. For the information levels greater than 0x100,
5464 * the transaction response has 1 parameter word which should be
5465 * ignored by the client.
5467 * However Windows only follows this rule for the IS_NAME_VALID call.
5469 switch (info_level
) {
5470 case SMB_INFO_IS_NAME_VALID
:
5475 if ((info_level
& 0xFF00) == 0xFF00) {
5477 * We use levels that start with 0xFF00
5478 * internally to represent SMB2 specific levels
5480 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5484 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5486 delete_pending
, write_time_ts
,
5488 lock_data_count
, lock_data
,
5489 req
->flags2
, max_data_bytes
,
5491 ppdata
, &data_size
);
5492 if (!NT_STATUS_IS_OK(status
)) {
5493 reply_nterror(req
, status
);
5497 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5503 /****************************************************************************
5504 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5506 ****************************************************************************/
5508 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5509 connection_struct
*conn
,
5510 struct smb_request
*req
,
5511 bool overwrite_if_exists
,
5512 const struct smb_filename
*smb_fname_old
,
5513 struct smb_filename
*smb_fname_new
)
5515 NTSTATUS status
= NT_STATUS_OK
;
5517 /* source must already exist. */
5518 if (!VALID_STAT(smb_fname_old
->st
)) {
5519 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5522 if (VALID_STAT(smb_fname_new
->st
)) {
5523 if (overwrite_if_exists
) {
5524 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5525 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5527 status
= unlink_internals(conn
,
5529 FILE_ATTRIBUTE_NORMAL
,
5532 if (!NT_STATUS_IS_OK(status
)) {
5536 /* Disallow if newname already exists. */
5537 return NT_STATUS_OBJECT_NAME_COLLISION
;
5541 /* No links from a directory. */
5542 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5543 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5546 /* Setting a hardlink to/from a stream isn't currently supported. */
5547 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5548 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5549 return NT_STATUS_INVALID_PARAMETER
;
5552 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5553 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5555 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5556 smb_fname_new
->base_name
) != 0) {
5557 status
= map_nt_error_from_unix(errno
);
5558 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5559 nt_errstr(status
), smb_fname_old
->base_name
,
5560 smb_fname_new
->base_name
));
5565 /****************************************************************************
5566 Deal with setting the time from any of the setfilepathinfo functions.
5567 ****************************************************************************/
5569 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5571 const struct smb_filename
*smb_fname
,
5572 struct smb_file_time
*ft
,
5573 bool setting_write_time
)
5575 struct smb_filename smb_fname_base
;
5577 FILE_NOTIFY_CHANGE_LAST_ACCESS
5578 |FILE_NOTIFY_CHANGE_LAST_WRITE
5579 |FILE_NOTIFY_CHANGE_CREATION
;
5581 if (!VALID_STAT(smb_fname
->st
)) {
5582 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5585 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5586 return NT_STATUS_ACCESS_DENIED
;
5589 /* get some defaults (no modifications) if any info is zero or -1. */
5590 if (null_timespec(ft
->create_time
)) {
5591 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5594 if (null_timespec(ft
->atime
)) {
5595 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5598 if (null_timespec(ft
->mtime
)) {
5599 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5602 if (!setting_write_time
) {
5603 /* ft->mtime comes from change time, not write time. */
5604 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5607 /* Ensure the resolution is the correct for
5608 * what we can store on this filesystem. */
5610 round_timespec(conn
->ts_res
, &ft
->create_time
);
5611 round_timespec(conn
->ts_res
, &ft
->ctime
);
5612 round_timespec(conn
->ts_res
, &ft
->atime
);
5613 round_timespec(conn
->ts_res
, &ft
->mtime
);
5615 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5616 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5617 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5618 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5619 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5620 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5621 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5622 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5624 if (setting_write_time
) {
5626 * This was a Windows setfileinfo on an open file.
5627 * NT does this a lot. We also need to
5628 * set the time here, as it can be read by
5629 * FindFirst/FindNext and with the patch for bug #2045
5630 * in smbd/fileio.c it ensures that this timestamp is
5631 * kept sticky even after a write. We save the request
5632 * away and will set it on file close and after a write. JRA.
5635 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5636 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5639 if (fsp
->base_fsp
) {
5640 set_sticky_write_time_fsp(fsp
->base_fsp
,
5643 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5646 set_sticky_write_time_path(
5647 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5652 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5654 /* Always call ntimes on the base, even if a stream was passed in. */
5655 smb_fname_base
= *smb_fname
;
5656 smb_fname_base
.stream_name
= NULL
;
5658 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5659 return map_nt_error_from_unix(errno
);
5662 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5663 smb_fname
->base_name
);
5664 return NT_STATUS_OK
;
5667 /****************************************************************************
5668 Deal with setting the dosmode from any of the setfilepathinfo functions.
5669 ****************************************************************************/
5671 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5672 const struct smb_filename
*smb_fname
,
5675 struct smb_filename
*smb_fname_base
= NULL
;
5678 if (!VALID_STAT(smb_fname
->st
)) {
5679 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5682 /* Always operate on the base_name, even if a stream was passed in. */
5683 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5684 NULL
, &smb_fname
->st
,
5686 if (!NT_STATUS_IS_OK(status
)) {
5691 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5692 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5694 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5698 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5700 /* check the mode isn't different, before changing it */
5701 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5702 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5703 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5704 (unsigned int)dosmode
));
5706 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5708 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5710 smb_fname_str_dbg(smb_fname_base
),
5712 status
= map_nt_error_from_unix(errno
);
5716 status
= NT_STATUS_OK
;
5718 TALLOC_FREE(smb_fname_base
);
5722 /****************************************************************************
5723 Deal with setting the size from any of the setfilepathinfo functions.
5724 ****************************************************************************/
5726 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5727 struct smb_request
*req
,
5729 const struct smb_filename
*smb_fname
,
5730 const SMB_STRUCT_STAT
*psbuf
,
5732 bool fail_after_createfile
)
5734 NTSTATUS status
= NT_STATUS_OK
;
5735 struct smb_filename
*smb_fname_tmp
= NULL
;
5736 files_struct
*new_fsp
= NULL
;
5738 if (!VALID_STAT(*psbuf
)) {
5739 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5742 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5743 return NT_STATUS_ACCESS_DENIED
;
5746 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5748 if (size
== get_file_size_stat(psbuf
)) {
5749 return NT_STATUS_OK
;
5752 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5753 smb_fname_str_dbg(smb_fname
), (double)size
));
5755 if (fsp
&& fsp
->fh
->fd
!= -1) {
5756 /* Handle based call. */
5757 if (vfs_set_filelen(fsp
, size
) == -1) {
5758 return map_nt_error_from_unix(errno
);
5760 trigger_write_time_update_immediate(fsp
);
5761 return NT_STATUS_OK
;
5764 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5765 if (!NT_STATUS_IS_OK(status
)) {
5769 smb_fname_tmp
->st
= *psbuf
;
5771 status
= SMB_VFS_CREATE_FILE(
5774 0, /* root_dir_fid */
5775 smb_fname_tmp
, /* fname */
5776 FILE_WRITE_DATA
, /* access_mask */
5777 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5779 FILE_OPEN
, /* create_disposition*/
5780 0, /* create_options */
5781 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5782 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5783 0, /* allocation_size */
5784 0, /* private_flags */
5787 &new_fsp
, /* result */
5790 TALLOC_FREE(smb_fname_tmp
);
5792 if (!NT_STATUS_IS_OK(status
)) {
5793 /* NB. We check for open_was_deferred in the caller. */
5797 /* See RAW-SFILEINFO-END-OF-FILE */
5798 if (fail_after_createfile
) {
5799 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5800 return NT_STATUS_INVALID_LEVEL
;
5803 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5804 status
= map_nt_error_from_unix(errno
);
5805 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5809 trigger_write_time_update_immediate(new_fsp
);
5810 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5811 return NT_STATUS_OK
;
5814 /****************************************************************************
5815 Deal with SMB_INFO_SET_EA.
5816 ****************************************************************************/
5818 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5822 const struct smb_filename
*smb_fname
)
5824 struct ea_list
*ea_list
= NULL
;
5825 TALLOC_CTX
*ctx
= NULL
;
5826 NTSTATUS status
= NT_STATUS_OK
;
5828 if (total_data
< 10) {
5830 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5831 length. They seem to have no effect. Bug #3212. JRA */
5833 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5834 /* We're done. We only get EA info in this call. */
5835 return NT_STATUS_OK
;
5838 return NT_STATUS_INVALID_PARAMETER
;
5841 if (IVAL(pdata
,0) > total_data
) {
5842 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5843 IVAL(pdata
,0), (unsigned int)total_data
));
5844 return NT_STATUS_INVALID_PARAMETER
;
5848 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5850 return NT_STATUS_INVALID_PARAMETER
;
5853 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5854 return NT_STATUS_ACCESS_DENIED
;
5857 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5862 /****************************************************************************
5863 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5864 ****************************************************************************/
5866 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5871 struct ea_list
*ea_list
= NULL
;
5875 return NT_STATUS_INVALID_HANDLE
;
5878 if (!lp_ea_support(SNUM(conn
))) {
5879 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5880 "EA's not supported.\n",
5881 (unsigned int)total_data
));
5882 return NT_STATUS_EAS_NOT_SUPPORTED
;
5885 if (total_data
< 10) {
5886 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5888 (unsigned int)total_data
));
5889 return NT_STATUS_INVALID_PARAMETER
;
5892 ea_list
= read_nttrans_ea_list(talloc_tos(),
5897 return NT_STATUS_INVALID_PARAMETER
;
5900 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5901 return NT_STATUS_ACCESS_DENIED
;
5904 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5906 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5907 smb_fname_str_dbg(fsp
->fsp_name
),
5908 nt_errstr(status
) ));
5914 /****************************************************************************
5915 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5916 ****************************************************************************/
5918 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5922 struct smb_filename
*smb_fname
)
5924 NTSTATUS status
= NT_STATUS_OK
;
5925 bool delete_on_close
;
5928 if (total_data
< 1) {
5929 return NT_STATUS_INVALID_PARAMETER
;
5933 return NT_STATUS_INVALID_HANDLE
;
5936 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5937 dosmode
= dos_mode(conn
, smb_fname
);
5939 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5940 "delete_on_close = %u\n",
5941 smb_fname_str_dbg(smb_fname
),
5942 (unsigned int)dosmode
,
5943 (unsigned int)delete_on_close
));
5945 if (delete_on_close
) {
5946 status
= can_set_delete_on_close(fsp
, dosmode
);
5947 if (!NT_STATUS_IS_OK(status
)) {
5952 /* The set is across all open files on this dev/inode pair. */
5953 if (!set_delete_on_close(fsp
, delete_on_close
,
5954 conn
->session_info
->security_token
,
5955 &conn
->session_info
->utok
)) {
5956 return NT_STATUS_ACCESS_DENIED
;
5958 return NT_STATUS_OK
;
5961 /****************************************************************************
5962 Deal with SMB_FILE_POSITION_INFORMATION.
5963 ****************************************************************************/
5965 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5970 uint64_t position_information
;
5972 if (total_data
< 8) {
5973 return NT_STATUS_INVALID_PARAMETER
;
5977 /* Ignore on pathname based set. */
5978 return NT_STATUS_OK
;
5981 position_information
= (uint64_t)IVAL(pdata
,0);
5982 #ifdef LARGE_SMB_OFF_T
5983 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5984 #else /* LARGE_SMB_OFF_T */
5985 if (IVAL(pdata
,4) != 0) {
5986 /* more than 32 bits? */
5987 return NT_STATUS_INVALID_PARAMETER
;
5989 #endif /* LARGE_SMB_OFF_T */
5991 DEBUG(10,("smb_file_position_information: Set file position "
5992 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5993 (double)position_information
));
5994 fsp
->fh
->position_information
= position_information
;
5995 return NT_STATUS_OK
;
5998 /****************************************************************************
5999 Deal with SMB_FILE_MODE_INFORMATION.
6000 ****************************************************************************/
6002 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6008 if (total_data
< 4) {
6009 return NT_STATUS_INVALID_PARAMETER
;
6011 mode
= IVAL(pdata
,0);
6012 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6013 return NT_STATUS_INVALID_PARAMETER
;
6015 return NT_STATUS_OK
;
6018 /****************************************************************************
6019 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6020 ****************************************************************************/
6022 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6023 struct smb_request
*req
,
6026 const struct smb_filename
*smb_fname
)
6028 char *link_target
= NULL
;
6029 const char *newname
= smb_fname
->base_name
;
6030 TALLOC_CTX
*ctx
= talloc_tos();
6032 /* Set a symbolic link. */
6033 /* Don't allow this if follow links is false. */
6035 if (total_data
== 0) {
6036 return NT_STATUS_INVALID_PARAMETER
;
6039 if (!lp_symlinks(SNUM(conn
))) {
6040 return NT_STATUS_ACCESS_DENIED
;
6043 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6044 total_data
, STR_TERMINATE
);
6047 return NT_STATUS_INVALID_PARAMETER
;
6050 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6051 newname
, link_target
));
6053 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6054 return map_nt_error_from_unix(errno
);
6057 return NT_STATUS_OK
;
6060 /****************************************************************************
6061 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6062 ****************************************************************************/
6064 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6065 struct smb_request
*req
,
6066 const char *pdata
, int total_data
,
6067 struct smb_filename
*smb_fname_new
)
6069 char *oldname
= NULL
;
6070 struct smb_filename
*smb_fname_old
= NULL
;
6071 TALLOC_CTX
*ctx
= talloc_tos();
6072 NTSTATUS status
= NT_STATUS_OK
;
6074 /* Set a hard link. */
6075 if (total_data
== 0) {
6076 return NT_STATUS_INVALID_PARAMETER
;
6079 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6080 total_data
, STR_TERMINATE
, &status
);
6081 if (!NT_STATUS_IS_OK(status
)) {
6085 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6086 smb_fname_str_dbg(smb_fname_new
), oldname
));
6088 status
= filename_convert(ctx
,
6090 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6095 if (!NT_STATUS_IS_OK(status
)) {
6099 return hardlink_internals(ctx
, conn
, req
, false,
6100 smb_fname_old
, smb_fname_new
);
6103 /****************************************************************************
6104 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6105 ****************************************************************************/
6107 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6108 struct smb_request
*req
,
6112 struct smb_filename
*smb_fname_src
)
6116 char *newname
= NULL
;
6117 struct smb_filename
*smb_fname_dst
= NULL
;
6118 NTSTATUS status
= NT_STATUS_OK
;
6119 TALLOC_CTX
*ctx
= talloc_tos();
6122 return NT_STATUS_INVALID_HANDLE
;
6125 if (total_data
< 20) {
6126 return NT_STATUS_INVALID_PARAMETER
;
6129 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6130 len
= IVAL(pdata
,16);
6132 if (len
> (total_data
- 20) || (len
== 0)) {
6133 return NT_STATUS_INVALID_PARAMETER
;
6136 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6137 &pdata
[20], len
, STR_TERMINATE
,
6139 if (!NT_STATUS_IS_OK(status
)) {
6143 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6146 status
= filename_convert(ctx
,
6148 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6153 if (!NT_STATUS_IS_OK(status
)) {
6157 if (fsp
->base_fsp
) {
6158 /* newname must be a stream name. */
6159 if (newname
[0] != ':') {
6160 return NT_STATUS_NOT_SUPPORTED
;
6163 /* Create an smb_fname to call rename_internals_fsp() with. */
6164 status
= create_synthetic_smb_fname(talloc_tos(),
6165 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6167 if (!NT_STATUS_IS_OK(status
)) {
6172 * Set the original last component, since
6173 * rename_internals_fsp() requires it.
6175 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6177 if (smb_fname_dst
->original_lcomp
== NULL
) {
6178 status
= NT_STATUS_NO_MEMORY
;
6184 DEBUG(10,("smb2_file_rename_information: "
6185 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6186 fsp
->fnum
, fsp_str_dbg(fsp
),
6187 smb_fname_str_dbg(smb_fname_dst
)));
6188 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6189 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6193 TALLOC_FREE(smb_fname_dst
);
6197 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6198 struct smb_request
*req
,
6202 struct smb_filename
*smb_fname_src
)
6206 char *newname
= NULL
;
6207 struct smb_filename
*smb_fname_dst
= NULL
;
6208 NTSTATUS status
= NT_STATUS_OK
;
6209 TALLOC_CTX
*ctx
= talloc_tos();
6212 return NT_STATUS_INVALID_HANDLE
;
6215 if (total_data
< 20) {
6216 return NT_STATUS_INVALID_PARAMETER
;
6219 overwrite
= (CVAL(pdata
,0) ? true : false);
6220 len
= IVAL(pdata
,16);
6222 if (len
> (total_data
- 20) || (len
== 0)) {
6223 return NT_STATUS_INVALID_PARAMETER
;
6226 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6227 &pdata
[20], len
, STR_TERMINATE
,
6229 if (!NT_STATUS_IS_OK(status
)) {
6233 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6236 status
= filename_convert(ctx
,
6238 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6243 if (!NT_STATUS_IS_OK(status
)) {
6247 if (fsp
->base_fsp
) {
6248 /* No stream names. */
6249 return NT_STATUS_NOT_SUPPORTED
;
6252 DEBUG(10,("smb_file_link_information: "
6253 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6254 fsp
->fnum
, fsp_str_dbg(fsp
),
6255 smb_fname_str_dbg(smb_fname_dst
)));
6256 status
= hardlink_internals(ctx
,
6263 TALLOC_FREE(smb_fname_dst
);
6267 /****************************************************************************
6268 Deal with SMB_FILE_RENAME_INFORMATION.
6269 ****************************************************************************/
6271 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6272 struct smb_request
*req
,
6276 struct smb_filename
*smb_fname_src
)
6281 char *newname
= NULL
;
6282 struct smb_filename
*smb_fname_dst
= NULL
;
6283 bool dest_has_wcard
= False
;
6284 NTSTATUS status
= NT_STATUS_OK
;
6286 TALLOC_CTX
*ctx
= talloc_tos();
6288 if (total_data
< 13) {
6289 return NT_STATUS_INVALID_PARAMETER
;
6292 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6293 root_fid
= IVAL(pdata
,4);
6294 len
= IVAL(pdata
,8);
6296 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6297 return NT_STATUS_INVALID_PARAMETER
;
6300 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6303 if (!NT_STATUS_IS_OK(status
)) {
6307 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6310 status
= resolve_dfspath_wcard(ctx
, conn
,
6311 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6316 if (!NT_STATUS_IS_OK(status
)) {
6320 /* Check the new name has no '/' characters. */
6321 if (strchr_m(newname
, '/')) {
6322 return NT_STATUS_NOT_SUPPORTED
;
6325 if (fsp
&& fsp
->base_fsp
) {
6326 /* newname must be a stream name. */
6327 if (newname
[0] != ':') {
6328 return NT_STATUS_NOT_SUPPORTED
;
6331 /* Create an smb_fname to call rename_internals_fsp() with. */
6332 status
= create_synthetic_smb_fname(talloc_tos(),
6333 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6335 if (!NT_STATUS_IS_OK(status
)) {
6340 * Set the original last component, since
6341 * rename_internals_fsp() requires it.
6343 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6345 if (smb_fname_dst
->original_lcomp
== NULL
) {
6346 status
= NT_STATUS_NO_MEMORY
;
6352 * Build up an smb_fname_dst based on the filename passed in.
6353 * We basically just strip off the last component, and put on
6354 * the newname instead.
6356 char *base_name
= NULL
;
6358 /* newname must *not* be a stream name. */
6359 if (newname
[0] == ':') {
6360 return NT_STATUS_NOT_SUPPORTED
;
6364 * Strip off the last component (filename) of the path passed
6367 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6369 return NT_STATUS_NO_MEMORY
;
6371 p
= strrchr_m(base_name
, '/');
6375 base_name
= talloc_strdup(ctx
, "");
6377 return NT_STATUS_NO_MEMORY
;
6380 /* Append the new name. */
6381 base_name
= talloc_asprintf_append(base_name
,
6385 return NT_STATUS_NO_MEMORY
;
6388 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6391 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6394 /* If an error we expect this to be
6395 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6397 if (!NT_STATUS_IS_OK(status
)) {
6398 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6402 /* Create an smb_fname to call rename_internals_fsp() */
6403 status
= create_synthetic_smb_fname(ctx
,
6407 if (!NT_STATUS_IS_OK(status
)) {
6414 DEBUG(10,("smb_file_rename_information: "
6415 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6416 fsp
->fnum
, fsp_str_dbg(fsp
),
6417 smb_fname_str_dbg(smb_fname_dst
)));
6418 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6421 DEBUG(10,("smb_file_rename_information: "
6422 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6423 smb_fname_str_dbg(smb_fname_src
),
6424 smb_fname_str_dbg(smb_fname_dst
)));
6425 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6426 smb_fname_dst
, 0, overwrite
, false,
6428 FILE_WRITE_ATTRIBUTES
);
6431 TALLOC_FREE(smb_fname_dst
);
6435 /****************************************************************************
6436 Deal with SMB_SET_POSIX_ACL.
6437 ****************************************************************************/
6439 #if defined(HAVE_POSIX_ACLS)
6440 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6444 const struct smb_filename
*smb_fname
)
6446 uint16 posix_acl_version
;
6447 uint16 num_file_acls
;
6448 uint16 num_def_acls
;
6449 bool valid_file_acls
= True
;
6450 bool valid_def_acls
= True
;
6452 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6453 return NT_STATUS_INVALID_PARAMETER
;
6455 posix_acl_version
= SVAL(pdata
,0);
6456 num_file_acls
= SVAL(pdata
,2);
6457 num_def_acls
= SVAL(pdata
,4);
6459 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6460 valid_file_acls
= False
;
6464 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6465 valid_def_acls
= False
;
6469 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6470 return NT_STATUS_INVALID_PARAMETER
;
6473 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6474 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6475 return NT_STATUS_INVALID_PARAMETER
;
6478 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6479 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6480 (unsigned int)num_file_acls
,
6481 (unsigned int)num_def_acls
));
6483 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6484 smb_fname
->base_name
, num_file_acls
,
6485 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6486 return map_nt_error_from_unix(errno
);
6489 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6490 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6491 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6492 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6493 return map_nt_error_from_unix(errno
);
6495 return NT_STATUS_OK
;
6499 /****************************************************************************
6500 Deal with SMB_SET_POSIX_LOCK.
6501 ****************************************************************************/
6503 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6504 struct smb_request
*req
,
6512 bool blocking_lock
= False
;
6513 enum brl_type lock_type
;
6515 NTSTATUS status
= NT_STATUS_OK
;
6517 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6518 return NT_STATUS_INVALID_HANDLE
;
6521 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6522 return NT_STATUS_INVALID_PARAMETER
;
6525 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6526 case POSIX_LOCK_TYPE_READ
:
6527 lock_type
= READ_LOCK
;
6529 case POSIX_LOCK_TYPE_WRITE
:
6530 /* Return the right POSIX-mappable error code for files opened read-only. */
6531 if (!fsp
->can_write
) {
6532 return NT_STATUS_INVALID_HANDLE
;
6534 lock_type
= WRITE_LOCK
;
6536 case POSIX_LOCK_TYPE_UNLOCK
:
6537 lock_type
= UNLOCK_LOCK
;
6540 return NT_STATUS_INVALID_PARAMETER
;
6543 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6544 blocking_lock
= False
;
6545 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6546 blocking_lock
= True
;
6548 return NT_STATUS_INVALID_PARAMETER
;
6551 if (!lp_blocking_locks(SNUM(conn
))) {
6552 blocking_lock
= False
;
6555 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6556 #if defined(HAVE_LONGLONG)
6557 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6558 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6559 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6560 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6561 #else /* HAVE_LONGLONG */
6562 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6563 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6564 #endif /* HAVE_LONGLONG */
6566 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6567 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6569 (unsigned int)lock_type
,
6570 (unsigned long long)smblctx
,
6574 if (lock_type
== UNLOCK_LOCK
) {
6575 status
= do_unlock(req
->sconn
->msg_ctx
,
6582 uint64_t block_smblctx
;
6584 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6596 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6598 * A blocking lock was requested. Package up
6599 * this smb into a queued request and push it
6600 * onto the blocking lock queue.
6602 if(push_blocking_lock_request(br_lck
,
6605 -1, /* infinite timeout. */
6613 TALLOC_FREE(br_lck
);
6617 TALLOC_FREE(br_lck
);
6623 /****************************************************************************
6624 Deal with SMB_SET_FILE_BASIC_INFO.
6625 ****************************************************************************/
6627 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6631 const struct smb_filename
*smb_fname
)
6633 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6634 struct smb_file_time ft
;
6636 NTSTATUS status
= NT_STATUS_OK
;
6640 if (total_data
< 36) {
6641 return NT_STATUS_INVALID_PARAMETER
;
6644 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6645 return NT_STATUS_ACCESS_DENIED
;
6648 /* Set the attributes */
6649 dosmode
= IVAL(pdata
,32);
6650 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6651 if (!NT_STATUS_IS_OK(status
)) {
6656 ft
.create_time
= interpret_long_date(pdata
);
6659 ft
.atime
= interpret_long_date(pdata
+8);
6662 ft
.mtime
= interpret_long_date(pdata
+16);
6665 ft
.ctime
= interpret_long_date(pdata
+24);
6667 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6668 smb_fname_str_dbg(smb_fname
)));
6670 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6674 /****************************************************************************
6675 Deal with SMB_INFO_STANDARD.
6676 ****************************************************************************/
6678 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6682 const struct smb_filename
*smb_fname
)
6684 struct smb_file_time ft
;
6688 if (total_data
< 12) {
6689 return NT_STATUS_INVALID_PARAMETER
;
6692 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6693 return NT_STATUS_ACCESS_DENIED
;
6697 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6699 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6701 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6703 DEBUG(10,("smb_set_info_standard: file %s\n",
6704 smb_fname_str_dbg(smb_fname
)));
6706 return smb_set_file_time(conn
,
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6718 struct smb_request
*req
,
6722 struct smb_filename
*smb_fname
)
6724 uint64_t allocation_size
= 0;
6725 NTSTATUS status
= NT_STATUS_OK
;
6726 files_struct
*new_fsp
= NULL
;
6728 if (!VALID_STAT(smb_fname
->st
)) {
6729 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6732 if (total_data
< 8) {
6733 return NT_STATUS_INVALID_PARAMETER
;
6736 allocation_size
= (uint64_t)IVAL(pdata
,0);
6737 #ifdef LARGE_SMB_OFF_T
6738 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6739 #else /* LARGE_SMB_OFF_T */
6740 if (IVAL(pdata
,4) != 0) {
6741 /* more than 32 bits? */
6742 return NT_STATUS_INVALID_PARAMETER
;
6744 #endif /* LARGE_SMB_OFF_T */
6746 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6747 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6748 (double)allocation_size
));
6750 if (allocation_size
) {
6751 allocation_size
= smb_roundup(conn
, allocation_size
);
6754 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6755 return NT_STATUS_ACCESS_DENIED
;
6758 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6759 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6760 (double)allocation_size
));
6762 if (fsp
&& fsp
->fh
->fd
!= -1) {
6763 /* Open file handle. */
6764 /* Only change if needed. */
6765 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6766 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6767 return map_nt_error_from_unix(errno
);
6770 /* But always update the time. */
6772 * This is equivalent to a write. Ensure it's seen immediately
6773 * if there are no pending writes.
6775 trigger_write_time_update_immediate(fsp
);
6776 return NT_STATUS_OK
;
6779 /* Pathname or stat or directory file. */
6780 status
= SMB_VFS_CREATE_FILE(
6783 0, /* root_dir_fid */
6784 smb_fname
, /* fname */
6785 FILE_WRITE_DATA
, /* access_mask */
6786 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6788 FILE_OPEN
, /* create_disposition*/
6789 0, /* create_options */
6790 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6791 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6792 0, /* allocation_size */
6793 0, /* private_flags */
6796 &new_fsp
, /* result */
6799 if (!NT_STATUS_IS_OK(status
)) {
6800 /* NB. We check for open_was_deferred in the caller. */
6804 /* Only change if needed. */
6805 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6806 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6807 status
= map_nt_error_from_unix(errno
);
6808 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6813 /* Changing the allocation size should set the last mod time. */
6815 * This is equivalent to a write. Ensure it's seen immediately
6816 * if there are no pending writes.
6818 trigger_write_time_update_immediate(new_fsp
);
6820 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6821 return NT_STATUS_OK
;
6824 /****************************************************************************
6825 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6826 ****************************************************************************/
6828 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6829 struct smb_request
*req
,
6833 const struct smb_filename
*smb_fname
,
6834 bool fail_after_createfile
)
6838 if (total_data
< 8) {
6839 return NT_STATUS_INVALID_PARAMETER
;
6842 size
= IVAL(pdata
,0);
6843 #ifdef LARGE_SMB_OFF_T
6844 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6845 #else /* LARGE_SMB_OFF_T */
6846 if (IVAL(pdata
,4) != 0) {
6847 /* more than 32 bits? */
6848 return NT_STATUS_INVALID_PARAMETER
;
6850 #endif /* LARGE_SMB_OFF_T */
6851 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6852 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6855 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6856 return NT_STATUS_ACCESS_DENIED
;
6859 return smb_set_file_size(conn
, req
,
6864 fail_after_createfile
);
6867 /****************************************************************************
6868 Allow a UNIX info mknod.
6869 ****************************************************************************/
6871 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6874 const struct smb_filename
*smb_fname
)
6876 uint32 file_type
= IVAL(pdata
,56);
6877 #if defined(HAVE_MAKEDEV)
6878 uint32 dev_major
= IVAL(pdata
,60);
6879 uint32 dev_minor
= IVAL(pdata
,68);
6881 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6882 uint32 raw_unixmode
= IVAL(pdata
,84);
6886 if (total_data
< 100) {
6887 return NT_STATUS_INVALID_PARAMETER
;
6890 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6891 PERM_NEW_FILE
, &unixmode
);
6892 if (!NT_STATUS_IS_OK(status
)) {
6896 #if defined(HAVE_MAKEDEV)
6897 dev
= makedev(dev_major
, dev_minor
);
6900 switch (file_type
) {
6901 #if defined(S_IFIFO)
6902 case UNIX_TYPE_FIFO
:
6903 unixmode
|= S_IFIFO
;
6906 #if defined(S_IFSOCK)
6907 case UNIX_TYPE_SOCKET
:
6908 unixmode
|= S_IFSOCK
;
6911 #if defined(S_IFCHR)
6912 case UNIX_TYPE_CHARDEV
:
6913 unixmode
|= S_IFCHR
;
6916 #if defined(S_IFBLK)
6917 case UNIX_TYPE_BLKDEV
:
6918 unixmode
|= S_IFBLK
;
6922 return NT_STATUS_INVALID_PARAMETER
;
6925 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6926 "%.0f mode 0%o for file %s\n", (double)dev
,
6927 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6929 /* Ok - do the mknod. */
6930 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6931 return map_nt_error_from_unix(errno
);
6934 /* If any of the other "set" calls fail we
6935 * don't want to end up with a half-constructed mknod.
6938 if (lp_inherit_perms(SNUM(conn
))) {
6940 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6942 return NT_STATUS_NO_MEMORY
;
6944 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6946 TALLOC_FREE(parent
);
6949 return NT_STATUS_OK
;
6952 /****************************************************************************
6953 Deal with SMB_SET_FILE_UNIX_BASIC.
6954 ****************************************************************************/
6956 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6957 struct smb_request
*req
,
6961 const struct smb_filename
*smb_fname
)
6963 struct smb_file_time ft
;
6964 uint32 raw_unixmode
;
6967 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6968 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6969 NTSTATUS status
= NT_STATUS_OK
;
6970 bool delete_on_fail
= False
;
6971 enum perm_type ptype
;
6972 files_struct
*all_fsps
= NULL
;
6973 bool modify_mtime
= true;
6975 struct smb_filename
*smb_fname_tmp
= NULL
;
6976 SMB_STRUCT_STAT sbuf
;
6980 if (total_data
< 100) {
6981 return NT_STATUS_INVALID_PARAMETER
;
6984 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6985 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6986 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6987 #ifdef LARGE_SMB_OFF_T
6988 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6989 #else /* LARGE_SMB_OFF_T */
6990 if (IVAL(pdata
,4) != 0) {
6991 /* more than 32 bits? */
6992 return NT_STATUS_INVALID_PARAMETER
;
6994 #endif /* LARGE_SMB_OFF_T */
6997 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6998 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6999 set_owner
= (uid_t
)IVAL(pdata
,40);
7000 set_grp
= (gid_t
)IVAL(pdata
,48);
7001 raw_unixmode
= IVAL(pdata
,84);
7003 if (VALID_STAT(smb_fname
->st
)) {
7004 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7005 ptype
= PERM_EXISTING_DIR
;
7007 ptype
= PERM_EXISTING_FILE
;
7010 ptype
= PERM_NEW_FILE
;
7013 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7015 if (!NT_STATUS_IS_OK(status
)) {
7019 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7020 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7021 smb_fname_str_dbg(smb_fname
), (double)size
,
7022 (unsigned int)set_owner
, (unsigned int)set_grp
,
7023 (int)raw_unixmode
));
7025 sbuf
= smb_fname
->st
;
7027 if (!VALID_STAT(sbuf
)) {
7029 * The only valid use of this is to create character and block
7030 * devices, and named pipes. This is deprecated (IMHO) and
7031 * a new info level should be used for mknod. JRA.
7034 status
= smb_unix_mknod(conn
,
7038 if (!NT_STATUS_IS_OK(status
)) {
7042 status
= copy_smb_filename(talloc_tos(), smb_fname
,
7044 if (!NT_STATUS_IS_OK(status
)) {
7048 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7049 status
= map_nt_error_from_unix(errno
);
7050 TALLOC_FREE(smb_fname_tmp
);
7051 SMB_VFS_UNLINK(conn
, smb_fname
);
7055 sbuf
= smb_fname_tmp
->st
;
7056 smb_fname
= smb_fname_tmp
;
7058 /* Ensure we don't try and change anything else. */
7059 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7060 size
= get_file_size_stat(&sbuf
);
7061 ft
.atime
= sbuf
.st_ex_atime
;
7062 ft
.mtime
= sbuf
.st_ex_mtime
;
7064 * We continue here as we might want to change the
7067 delete_on_fail
= True
;
7071 /* Horrible backwards compatibility hack as an old server bug
7072 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7076 size
= get_file_size_stat(&sbuf
);
7081 * Deal with the UNIX specific mode set.
7084 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7085 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7086 "setting mode 0%o for file %s\n",
7087 (unsigned int)unixmode
,
7088 smb_fname_str_dbg(smb_fname
)));
7089 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7090 return map_nt_error_from_unix(errno
);
7095 * Deal with the UNIX specific uid set.
7098 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7099 (sbuf
.st_ex_uid
!= set_owner
)) {
7102 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7103 "changing owner %u for path %s\n",
7104 (unsigned int)set_owner
,
7105 smb_fname_str_dbg(smb_fname
)));
7107 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7108 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7109 set_owner
, (gid_t
)-1);
7111 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7112 set_owner
, (gid_t
)-1);
7116 status
= map_nt_error_from_unix(errno
);
7117 if (delete_on_fail
) {
7118 SMB_VFS_UNLINK(conn
, smb_fname
);
7125 * Deal with the UNIX specific gid set.
7128 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7129 (sbuf
.st_ex_gid
!= set_grp
)) {
7130 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7131 "changing group %u for file %s\n",
7132 (unsigned int)set_owner
,
7133 smb_fname_str_dbg(smb_fname
)));
7134 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7136 status
= map_nt_error_from_unix(errno
);
7137 if (delete_on_fail
) {
7138 SMB_VFS_UNLINK(conn
, smb_fname
);
7144 /* Deal with any size changes. */
7146 status
= smb_set_file_size(conn
, req
,
7152 if (!NT_STATUS_IS_OK(status
)) {
7156 /* Deal with any time changes. */
7157 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7158 /* No change, don't cancel anything. */
7162 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7163 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7164 all_fsps
= file_find_di_next(all_fsps
)) {
7166 * We're setting the time explicitly for UNIX.
7167 * Cancel any pending changes over all handles.
7169 all_fsps
->update_write_time_on_close
= false;
7170 TALLOC_FREE(all_fsps
->update_write_time_event
);
7174 * Override the "setting_write_time"
7175 * parameter here as it almost does what
7176 * we need. Just remember if we modified
7177 * mtime and send the notify ourselves.
7179 if (null_timespec(ft
.mtime
)) {
7180 modify_mtime
= false;
7183 status
= smb_set_file_time(conn
,
7189 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7190 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7195 /****************************************************************************
7196 Deal with SMB_SET_FILE_UNIX_INFO2.
7197 ****************************************************************************/
7199 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7200 struct smb_request
*req
,
7204 const struct smb_filename
*smb_fname
)
7210 if (total_data
< 116) {
7211 return NT_STATUS_INVALID_PARAMETER
;
7214 /* Start by setting all the fields that are common between UNIX_BASIC
7217 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7219 if (!NT_STATUS_IS_OK(status
)) {
7223 smb_fflags
= IVAL(pdata
, 108);
7224 smb_fmask
= IVAL(pdata
, 112);
7226 /* NB: We should only attempt to alter the file flags if the client
7227 * sends a non-zero mask.
7229 if (smb_fmask
!= 0) {
7230 int stat_fflags
= 0;
7232 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7233 smb_fmask
, &stat_fflags
)) {
7234 /* Client asked to alter a flag we don't understand. */
7235 return NT_STATUS_INVALID_PARAMETER
;
7238 if (fsp
&& fsp
->fh
->fd
!= -1) {
7239 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7240 return NT_STATUS_NOT_SUPPORTED
;
7242 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7243 stat_fflags
) != 0) {
7244 return map_nt_error_from_unix(errno
);
7249 /* XXX: need to add support for changing the create_time here. You
7250 * can do this for paths on Darwin with setattrlist(2). The right way
7251 * to hook this up is probably by extending the VFS utimes interface.
7254 return NT_STATUS_OK
;
7257 /****************************************************************************
7258 Create a directory with POSIX semantics.
7259 ****************************************************************************/
7261 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7262 struct smb_request
*req
,
7265 struct smb_filename
*smb_fname
,
7266 int *pdata_return_size
)
7268 NTSTATUS status
= NT_STATUS_OK
;
7269 uint32 raw_unixmode
= 0;
7270 uint32 mod_unixmode
= 0;
7271 mode_t unixmode
= (mode_t
)0;
7272 files_struct
*fsp
= NULL
;
7273 uint16 info_level_return
= 0;
7275 char *pdata
= *ppdata
;
7277 if (total_data
< 18) {
7278 return NT_STATUS_INVALID_PARAMETER
;
7281 raw_unixmode
= IVAL(pdata
,8);
7282 /* Next 4 bytes are not yet defined. */
7284 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7285 PERM_NEW_DIR
, &unixmode
);
7286 if (!NT_STATUS_IS_OK(status
)) {
7290 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7292 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7293 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7295 status
= SMB_VFS_CREATE_FILE(
7298 0, /* root_dir_fid */
7299 smb_fname
, /* fname */
7300 FILE_READ_ATTRIBUTES
, /* access_mask */
7301 FILE_SHARE_NONE
, /* share_access */
7302 FILE_CREATE
, /* create_disposition*/
7303 FILE_DIRECTORY_FILE
, /* create_options */
7304 mod_unixmode
, /* file_attributes */
7305 0, /* oplock_request */
7306 0, /* allocation_size */
7307 0, /* private_flags */
7313 if (NT_STATUS_IS_OK(status
)) {
7314 close_file(req
, fsp
, NORMAL_CLOSE
);
7317 info_level_return
= SVAL(pdata
,16);
7319 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7320 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7321 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7322 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7324 *pdata_return_size
= 12;
7327 /* Realloc the data size */
7328 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7329 if (*ppdata
== NULL
) {
7330 *pdata_return_size
= 0;
7331 return NT_STATUS_NO_MEMORY
;
7335 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7336 SSVAL(pdata
,2,0); /* No fnum. */
7337 SIVAL(pdata
,4,info
); /* Was directory created. */
7339 switch (info_level_return
) {
7340 case SMB_QUERY_FILE_UNIX_BASIC
:
7341 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7342 SSVAL(pdata
,10,0); /* Padding. */
7343 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7346 case SMB_QUERY_FILE_UNIX_INFO2
:
7347 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7348 SSVAL(pdata
,10,0); /* Padding. */
7349 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7353 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7354 SSVAL(pdata
,10,0); /* Padding. */
7361 /****************************************************************************
7362 Open/Create a file with POSIX semantics.
7363 ****************************************************************************/
7365 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7366 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7368 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7369 struct smb_request
*req
,
7372 struct smb_filename
*smb_fname
,
7373 int *pdata_return_size
)
7375 bool extended_oplock_granted
= False
;
7376 char *pdata
= *ppdata
;
7378 uint32 wire_open_mode
= 0;
7379 uint32 raw_unixmode
= 0;
7380 uint32 mod_unixmode
= 0;
7381 uint32 create_disp
= 0;
7382 uint32 access_mask
= 0;
7383 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7384 NTSTATUS status
= NT_STATUS_OK
;
7385 mode_t unixmode
= (mode_t
)0;
7386 files_struct
*fsp
= NULL
;
7387 int oplock_request
= 0;
7389 uint16 info_level_return
= 0;
7391 if (total_data
< 18) {
7392 return NT_STATUS_INVALID_PARAMETER
;
7395 flags
= IVAL(pdata
,0);
7396 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7397 if (oplock_request
) {
7398 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7401 wire_open_mode
= IVAL(pdata
,4);
7403 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7404 return smb_posix_mkdir(conn
, req
,
7411 switch (wire_open_mode
& SMB_ACCMODE
) {
7413 access_mask
= SMB_O_RDONLY_MAPPING
;
7416 access_mask
= SMB_O_WRONLY_MAPPING
;
7419 access_mask
= (SMB_O_RDONLY_MAPPING
|
7420 SMB_O_WRONLY_MAPPING
);
7423 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7424 (unsigned int)wire_open_mode
));
7425 return NT_STATUS_INVALID_PARAMETER
;
7428 wire_open_mode
&= ~SMB_ACCMODE
;
7430 /* First take care of O_CREAT|O_EXCL interactions. */
7431 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7432 case (SMB_O_CREAT
| SMB_O_EXCL
):
7433 /* File exists fail. File not exist create. */
7434 create_disp
= FILE_CREATE
;
7437 /* File exists open. File not exist create. */
7438 create_disp
= FILE_OPEN_IF
;
7441 /* O_EXCL on its own without O_CREAT is undefined.
7442 We deliberately ignore it as some versions of
7443 Linux CIFSFS can send a bare O_EXCL on the
7444 wire which other filesystems in the kernel
7445 ignore. See bug 9519 for details. */
7450 /* File exists open. File not exist fail. */
7451 create_disp
= FILE_OPEN
;
7454 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7455 (unsigned int)wire_open_mode
));
7456 return NT_STATUS_INVALID_PARAMETER
;
7459 /* Next factor in the effects of O_TRUNC. */
7460 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7462 if (wire_open_mode
& SMB_O_TRUNC
) {
7463 switch (create_disp
) {
7465 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7466 /* Leave create_disp alone as
7467 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7469 /* File exists fail. File not exist create. */
7472 /* SMB_O_CREAT | SMB_O_TRUNC */
7473 /* File exists overwrite. File not exist create. */
7474 create_disp
= FILE_OVERWRITE_IF
;
7478 /* File exists overwrite. File not exist fail. */
7479 create_disp
= FILE_OVERWRITE
;
7482 /* Cannot get here. */
7483 smb_panic("smb_posix_open: logic error");
7484 return NT_STATUS_INVALID_PARAMETER
;
7488 raw_unixmode
= IVAL(pdata
,8);
7489 /* Next 4 bytes are not yet defined. */
7491 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7492 (VALID_STAT(smb_fname
->st
) ?
7493 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7496 if (!NT_STATUS_IS_OK(status
)) {
7500 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7502 if (wire_open_mode
& SMB_O_SYNC
) {
7503 create_options
|= FILE_WRITE_THROUGH
;
7505 if (wire_open_mode
& SMB_O_APPEND
) {
7506 access_mask
|= FILE_APPEND_DATA
;
7508 if (wire_open_mode
& SMB_O_DIRECT
) {
7509 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7512 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7513 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7514 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7515 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7517 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7518 create_options
|= FILE_DIRECTORY_FILE
;
7521 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7522 smb_fname_str_dbg(smb_fname
),
7523 (unsigned int)wire_open_mode
,
7524 (unsigned int)unixmode
));
7526 status
= SMB_VFS_CREATE_FILE(
7529 0, /* root_dir_fid */
7530 smb_fname
, /* fname */
7531 access_mask
, /* access_mask */
7532 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7534 create_disp
, /* create_disposition*/
7535 create_options
, /* create_options */
7536 mod_unixmode
, /* file_attributes */
7537 oplock_request
, /* oplock_request */
7538 0, /* allocation_size */
7539 0, /* private_flags */
7545 if (!NT_STATUS_IS_OK(status
)) {
7549 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7550 extended_oplock_granted
= True
;
7553 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7554 extended_oplock_granted
= True
;
7557 info_level_return
= SVAL(pdata
,16);
7559 /* Allocate the correct return size. */
7561 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7562 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7563 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7564 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7566 *pdata_return_size
= 12;
7569 /* Realloc the data size */
7570 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7571 if (*ppdata
== NULL
) {
7572 close_file(req
, fsp
, ERROR_CLOSE
);
7573 *pdata_return_size
= 0;
7574 return NT_STATUS_NO_MEMORY
;
7578 if (extended_oplock_granted
) {
7579 if (flags
& REQUEST_BATCH_OPLOCK
) {
7580 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7582 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7584 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7585 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7587 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7590 SSVAL(pdata
,2,fsp
->fnum
);
7591 SIVAL(pdata
,4,info
); /* Was file created etc. */
7593 switch (info_level_return
) {
7594 case SMB_QUERY_FILE_UNIX_BASIC
:
7595 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7596 SSVAL(pdata
,10,0); /* padding. */
7597 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7600 case SMB_QUERY_FILE_UNIX_INFO2
:
7601 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7602 SSVAL(pdata
,10,0); /* padding. */
7603 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7607 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7608 SSVAL(pdata
,10,0); /* padding. */
7611 return NT_STATUS_OK
;
7614 /****************************************************************************
7615 Delete a file with POSIX semantics.
7616 ****************************************************************************/
7618 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7619 struct smb_request
*req
,
7622 struct smb_filename
*smb_fname
)
7624 NTSTATUS status
= NT_STATUS_OK
;
7625 files_struct
*fsp
= NULL
;
7629 int create_options
= 0;
7631 struct share_mode_lock
*lck
= NULL
;
7633 if (total_data
< 2) {
7634 return NT_STATUS_INVALID_PARAMETER
;
7637 flags
= SVAL(pdata
,0);
7639 if (!VALID_STAT(smb_fname
->st
)) {
7640 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7643 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7644 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7645 return NT_STATUS_NOT_A_DIRECTORY
;
7648 DEBUG(10,("smb_posix_unlink: %s %s\n",
7649 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7650 smb_fname_str_dbg(smb_fname
)));
7652 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7653 create_options
|= FILE_DIRECTORY_FILE
;
7656 status
= SMB_VFS_CREATE_FILE(
7659 0, /* root_dir_fid */
7660 smb_fname
, /* fname */
7661 DELETE_ACCESS
, /* access_mask */
7662 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7664 FILE_OPEN
, /* create_disposition*/
7665 create_options
, /* create_options */
7666 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7667 0, /* oplock_request */
7668 0, /* allocation_size */
7669 0, /* private_flags */
7675 if (!NT_STATUS_IS_OK(status
)) {
7680 * Don't lie to client. If we can't really delete due to
7681 * non-POSIX opens return SHARING_VIOLATION.
7684 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7687 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7688 "lock for file %s\n", fsp_str_dbg(fsp
)));
7689 close_file(req
, fsp
, NORMAL_CLOSE
);
7690 return NT_STATUS_INVALID_PARAMETER
;
7694 * See if others still have the file open. If this is the case, then
7695 * don't delete. If all opens are POSIX delete we can set the delete
7696 * on close disposition.
7698 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7699 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7700 if (is_valid_share_mode_entry(e
)) {
7701 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7704 /* Fail with sharing violation. */
7706 close_file(req
, fsp
, NORMAL_CLOSE
);
7707 return NT_STATUS_SHARING_VIOLATION
;
7712 * Set the delete on close.
7714 status
= smb_set_file_disposition_info(conn
,
7722 if (!NT_STATUS_IS_OK(status
)) {
7723 close_file(req
, fsp
, NORMAL_CLOSE
);
7726 return close_file(req
, fsp
, NORMAL_CLOSE
);
7729 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7730 struct smb_request
*req
,
7731 TALLOC_CTX
*mem_ctx
,
7732 uint16_t info_level
,
7734 struct smb_filename
*smb_fname
,
7735 char **ppdata
, int total_data
,
7738 char *pdata
= *ppdata
;
7739 NTSTATUS status
= NT_STATUS_OK
;
7740 int data_return_size
= 0;
7744 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7745 return NT_STATUS_INVALID_LEVEL
;
7748 if (!CAN_WRITE(conn
)) {
7749 /* Allow POSIX opens. The open path will deny
7750 * any non-readonly opens. */
7751 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7752 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7756 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7757 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7758 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7760 switch (info_level
) {
7762 case SMB_INFO_STANDARD
:
7764 status
= smb_set_info_standard(conn
,
7772 case SMB_INFO_SET_EA
:
7774 status
= smb_info_set_ea(conn
,
7782 case SMB_SET_FILE_BASIC_INFO
:
7783 case SMB_FILE_BASIC_INFORMATION
:
7785 status
= smb_set_file_basic_info(conn
,
7793 case SMB_FILE_ALLOCATION_INFORMATION
:
7794 case SMB_SET_FILE_ALLOCATION_INFO
:
7796 status
= smb_set_file_allocation_info(conn
, req
,
7804 case SMB_FILE_END_OF_FILE_INFORMATION
:
7805 case SMB_SET_FILE_END_OF_FILE_INFO
:
7808 * XP/Win7 both fail after the createfile with
7809 * SMB_SET_FILE_END_OF_FILE_INFO but not
7810 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7811 * The level is known here, so pass it down
7815 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7817 status
= smb_set_file_end_of_file_info(conn
, req
,
7826 case SMB_FILE_DISPOSITION_INFORMATION
:
7827 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7830 /* JRA - We used to just ignore this on a path ?
7831 * Shouldn't this be invalid level on a pathname
7834 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7835 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7838 status
= smb_set_file_disposition_info(conn
,
7846 case SMB_FILE_POSITION_INFORMATION
:
7848 status
= smb_file_position_information(conn
,
7855 case SMB_FILE_FULL_EA_INFORMATION
:
7857 status
= smb_set_file_full_ea_info(conn
,
7864 /* From tridge Samba4 :
7865 * MODE_INFORMATION in setfileinfo (I have no
7866 * idea what "mode information" on a file is - it takes a value of 0,
7867 * 2, 4 or 6. What could it be?).
7870 case SMB_FILE_MODE_INFORMATION
:
7872 status
= smb_file_mode_information(conn
,
7879 * CIFS UNIX extensions.
7882 case SMB_SET_FILE_UNIX_BASIC
:
7884 status
= smb_set_file_unix_basic(conn
, req
,
7892 case SMB_SET_FILE_UNIX_INFO2
:
7894 status
= smb_set_file_unix_info2(conn
, req
,
7902 case SMB_SET_FILE_UNIX_LINK
:
7905 /* We must have a pathname for this. */
7906 return NT_STATUS_INVALID_LEVEL
;
7908 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7909 total_data
, smb_fname
);
7913 case SMB_SET_FILE_UNIX_HLINK
:
7916 /* We must have a pathname for this. */
7917 return NT_STATUS_INVALID_LEVEL
;
7919 status
= smb_set_file_unix_hlink(conn
, req
,
7925 case SMB_FILE_RENAME_INFORMATION
:
7927 status
= smb_file_rename_information(conn
, req
,
7933 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7935 /* SMB2 rename information. */
7936 status
= smb2_file_rename_information(conn
, req
,
7942 case SMB_FILE_LINK_INFORMATION
:
7944 status
= smb_file_link_information(conn
, req
,
7950 #if defined(HAVE_POSIX_ACLS)
7951 case SMB_SET_POSIX_ACL
:
7953 status
= smb_set_posix_acl(conn
,
7962 case SMB_SET_POSIX_LOCK
:
7965 return NT_STATUS_INVALID_LEVEL
;
7967 status
= smb_set_posix_lock(conn
, req
,
7968 pdata
, total_data
, fsp
);
7972 case SMB_POSIX_PATH_OPEN
:
7975 /* We must have a pathname for this. */
7976 return NT_STATUS_INVALID_LEVEL
;
7979 status
= smb_posix_open(conn
, req
,
7987 case SMB_POSIX_PATH_UNLINK
:
7990 /* We must have a pathname for this. */
7991 return NT_STATUS_INVALID_LEVEL
;
7994 status
= smb_posix_unlink(conn
, req
,
8002 return NT_STATUS_INVALID_LEVEL
;
8005 if (!NT_STATUS_IS_OK(status
)) {
8009 *ret_data_size
= data_return_size
;
8010 return NT_STATUS_OK
;
8013 /****************************************************************************
8014 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8015 ****************************************************************************/
8017 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8018 struct smb_request
*req
,
8019 unsigned int tran_call
,
8020 char **pparams
, int total_params
,
8021 char **ppdata
, int total_data
,
8022 unsigned int max_data_bytes
)
8024 char *params
= *pparams
;
8025 char *pdata
= *ppdata
;
8027 struct smb_filename
*smb_fname
= NULL
;
8028 files_struct
*fsp
= NULL
;
8029 NTSTATUS status
= NT_STATUS_OK
;
8030 int data_return_size
= 0;
8033 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8037 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8038 if (total_params
< 4) {
8039 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8043 fsp
= file_fsp(req
, SVAL(params
,0));
8044 /* Basic check for non-null fsp. */
8045 if (!check_fsp_open(conn
, req
, fsp
)) {
8048 info_level
= SVAL(params
,2);
8050 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
8052 if (!NT_STATUS_IS_OK(status
)) {
8053 reply_nterror(req
, status
);
8057 if(fsp
->fh
->fd
== -1) {
8059 * This is actually a SETFILEINFO on a directory
8060 * handle (returned from an NT SMB). NT5.0 seems
8061 * to do this call. JRA.
8063 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8064 /* Always do lstat for UNIX calls. */
8065 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8066 DEBUG(3,("call_trans2setfilepathinfo: "
8067 "SMB_VFS_LSTAT of %s failed "
8069 smb_fname_str_dbg(smb_fname
),
8071 reply_nterror(req
, map_nt_error_from_unix(errno
));
8075 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8076 DEBUG(3,("call_trans2setfilepathinfo: "
8077 "fileinfo of %s failed (%s)\n",
8078 smb_fname_str_dbg(smb_fname
),
8080 reply_nterror(req
, map_nt_error_from_unix(errno
));
8084 } else if (fsp
->print_file
) {
8086 * Doing a DELETE_ON_CLOSE should cancel a print job.
8088 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8089 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8091 DEBUG(3,("call_trans2setfilepathinfo: "
8092 "Cancelling print job (%s)\n",
8096 send_trans2_replies(conn
, req
, params
, 2,
8102 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8107 * Original code - this is an open file.
8109 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8110 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8111 "of fnum %d failed (%s)\n", fsp
->fnum
,
8113 reply_nterror(req
, map_nt_error_from_unix(errno
));
8119 uint32_t ucf_flags
= 0;
8122 if (total_params
< 7) {
8123 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8127 info_level
= SVAL(params
,0);
8128 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8129 total_params
- 6, STR_TERMINATE
,
8131 if (!NT_STATUS_IS_OK(status
)) {
8132 reply_nterror(req
, status
);
8136 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8137 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8138 info_level
== SMB_FILE_RENAME_INFORMATION
||
8139 info_level
== SMB_POSIX_PATH_UNLINK
) {
8140 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8143 status
= filename_convert(req
, conn
,
8144 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8149 if (!NT_STATUS_IS_OK(status
)) {
8150 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8151 reply_botherror(req
,
8152 NT_STATUS_PATH_NOT_COVERED
,
8153 ERRSRV
, ERRbadpath
);
8156 reply_nterror(req
, status
);
8160 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8162 * For CIFS UNIX extensions the target name may not exist.
8165 /* Always do lstat for UNIX calls. */
8166 SMB_VFS_LSTAT(conn
, smb_fname
);
8168 } else if (!VALID_STAT(smb_fname
->st
) &&
8169 SMB_VFS_STAT(conn
, smb_fname
)) {
8170 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8172 smb_fname_str_dbg(smb_fname
),
8174 reply_nterror(req
, map_nt_error_from_unix(errno
));
8179 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8180 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8181 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8183 /* Realloc the parameter size */
8184 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8185 if (*pparams
== NULL
) {
8186 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8193 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8199 if (!NT_STATUS_IS_OK(status
)) {
8200 if (open_was_deferred(req
->mid
)) {
8201 /* We have re-scheduled this call. */
8204 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8205 /* We have re-scheduled this call. */
8208 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8209 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8210 ERRSRV
, ERRbadpath
);
8213 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8214 reply_openerror(req
, status
);
8218 reply_nterror(req
, status
);
8222 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8228 /****************************************************************************
8229 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8230 ****************************************************************************/
8232 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8233 char **pparams
, int total_params
,
8234 char **ppdata
, int total_data
,
8235 unsigned int max_data_bytes
)
8237 struct smb_filename
*smb_dname
= NULL
;
8238 char *params
= *pparams
;
8239 char *pdata
= *ppdata
;
8240 char *directory
= NULL
;
8241 NTSTATUS status
= NT_STATUS_OK
;
8242 struct ea_list
*ea_list
= NULL
;
8243 TALLOC_CTX
*ctx
= talloc_tos();
8245 if (!CAN_WRITE(conn
)) {
8246 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8250 if (total_params
< 5) {
8251 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8255 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8256 total_params
- 4, STR_TERMINATE
,
8258 if (!NT_STATUS_IS_OK(status
)) {
8259 reply_nterror(req
, status
);
8263 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8265 status
= filename_convert(ctx
,
8267 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8273 if (!NT_STATUS_IS_OK(status
)) {
8274 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8275 reply_botherror(req
,
8276 NT_STATUS_PATH_NOT_COVERED
,
8277 ERRSRV
, ERRbadpath
);
8280 reply_nterror(req
, status
);
8285 * OS/2 workplace shell seems to send SET_EA requests of "null"
8286 * length (4 bytes containing IVAL 4).
8287 * They seem to have no effect. Bug #3212. JRA.
8290 if (total_data
&& (total_data
!= 4)) {
8291 /* Any data in this call is an EA list. */
8292 if (total_data
< 10) {
8293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8297 if (IVAL(pdata
,0) > total_data
) {
8298 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8299 IVAL(pdata
,0), (unsigned int)total_data
));
8300 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8304 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8307 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8311 if (!lp_ea_support(SNUM(conn
))) {
8312 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8316 /* If total_data == 4 Windows doesn't care what values
8317 * are placed in that field, it just ignores them.
8318 * The System i QNTC IBM SMB client puts bad values here,
8319 * so ignore them. */
8321 status
= create_directory(conn
, req
, smb_dname
);
8323 if (!NT_STATUS_IS_OK(status
)) {
8324 reply_nterror(req
, status
);
8328 /* Try and set any given EA. */
8330 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8331 if (!NT_STATUS_IS_OK(status
)) {
8332 reply_nterror(req
, status
);
8337 /* Realloc the parameter and data sizes */
8338 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8339 if(*pparams
== NULL
) {
8340 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8347 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8350 TALLOC_FREE(smb_dname
);
8354 /****************************************************************************
8355 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8356 We don't actually do this - we just send a null response.
8357 ****************************************************************************/
8359 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8360 struct smb_request
*req
,
8361 char **pparams
, int total_params
,
8362 char **ppdata
, int total_data
,
8363 unsigned int max_data_bytes
)
8365 char *params
= *pparams
;
8368 if (total_params
< 6) {
8369 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8373 info_level
= SVAL(params
,4);
8374 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8376 switch (info_level
) {
8381 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8385 /* Realloc the parameter and data sizes */
8386 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8387 if (*pparams
== NULL
) {
8388 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8393 SSVAL(params
,0,fnf_handle
);
8394 SSVAL(params
,2,0); /* No changes */
8395 SSVAL(params
,4,0); /* No EA errors */
8402 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8407 /****************************************************************************
8408 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8409 changes). Currently this does nothing.
8410 ****************************************************************************/
8412 static void call_trans2findnotifynext(connection_struct
*conn
,
8413 struct smb_request
*req
,
8414 char **pparams
, int total_params
,
8415 char **ppdata
, int total_data
,
8416 unsigned int max_data_bytes
)
8418 char *params
= *pparams
;
8420 DEBUG(3,("call_trans2findnotifynext\n"));
8422 /* Realloc the parameter and data sizes */
8423 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8424 if (*pparams
== NULL
) {
8425 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8430 SSVAL(params
,0,0); /* No changes */
8431 SSVAL(params
,2,0); /* No EA errors */
8433 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8438 /****************************************************************************
8439 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8440 ****************************************************************************/
8442 static void call_trans2getdfsreferral(connection_struct
*conn
,
8443 struct smb_request
*req
,
8444 char **pparams
, int total_params
,
8445 char **ppdata
, int total_data
,
8446 unsigned int max_data_bytes
)
8448 char *params
= *pparams
;
8449 char *pathname
= NULL
;
8451 int max_referral_level
;
8452 NTSTATUS status
= NT_STATUS_OK
;
8453 TALLOC_CTX
*ctx
= talloc_tos();
8455 DEBUG(10,("call_trans2getdfsreferral\n"));
8457 if (total_params
< 3) {
8458 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8462 max_referral_level
= SVAL(params
,0);
8464 if(!lp_host_msdfs()) {
8465 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8469 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8470 total_params
- 2, STR_TERMINATE
);
8472 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8475 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8476 ppdata
,&status
)) < 0) {
8477 reply_nterror(req
, status
);
8481 SSVAL(req
->inbuf
, smb_flg2
,
8482 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8483 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8488 #define LMCAT_SPL 0x53
8489 #define LMFUNC_GETJOBID 0x60
8491 /****************************************************************************
8492 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8493 ****************************************************************************/
8495 static void call_trans2ioctl(connection_struct
*conn
,
8496 struct smb_request
*req
,
8497 char **pparams
, int total_params
,
8498 char **ppdata
, int total_data
,
8499 unsigned int max_data_bytes
)
8501 char *pdata
= *ppdata
;
8502 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8504 /* check for an invalid fid before proceeding */
8507 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8511 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8512 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8513 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8514 if (*ppdata
== NULL
) {
8515 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8520 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8521 CAN ACCEPT THIS IN UNICODE. JRA. */
8524 if (fsp
->print_file
) {
8525 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8529 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8530 global_myname(), 15,
8531 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8532 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8533 lp_servicename(SNUM(conn
)), 13,
8534 STR_ASCII
|STR_TERMINATE
); /* Service name */
8535 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8540 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8541 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8544 /****************************************************************************
8545 Reply to a SMBfindclose (stop trans2 directory search).
8546 ****************************************************************************/
8548 void reply_findclose(struct smb_request
*req
)
8551 struct smbd_server_connection
*sconn
= req
->sconn
;
8553 START_PROFILE(SMBfindclose
);
8556 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8557 END_PROFILE(SMBfindclose
);
8561 dptr_num
= SVALS(req
->vwv
+0, 0);
8563 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8565 dptr_close(sconn
, &dptr_num
);
8567 reply_outbuf(req
, 0, 0);
8569 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8571 END_PROFILE(SMBfindclose
);
8575 /****************************************************************************
8576 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8577 ****************************************************************************/
8579 void reply_findnclose(struct smb_request
*req
)
8583 START_PROFILE(SMBfindnclose
);
8586 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8587 END_PROFILE(SMBfindnclose
);
8591 dptr_num
= SVAL(req
->vwv
+0, 0);
8593 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8595 /* We never give out valid handles for a
8596 findnotifyfirst - so any dptr_num is ok here.
8599 reply_outbuf(req
, 0, 0);
8601 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8603 END_PROFILE(SMBfindnclose
);
8607 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8608 struct trans_state
*state
)
8610 if (get_Protocol() >= PROTOCOL_NT1
) {
8611 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8612 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8615 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8616 if (state
->call
!= TRANSACT2_QFSINFO
&&
8617 state
->call
!= TRANSACT2_SETFSINFO
) {
8618 DEBUG(0,("handle_trans2: encryption required "
8620 (unsigned int)state
->call
));
8621 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8626 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8628 /* Now we must call the relevant TRANS2 function */
8629 switch(state
->call
) {
8630 case TRANSACT2_OPEN
:
8632 START_PROFILE(Trans2_open
);
8633 call_trans2open(conn
, req
,
8634 &state
->param
, state
->total_param
,
8635 &state
->data
, state
->total_data
,
8636 state
->max_data_return
);
8637 END_PROFILE(Trans2_open
);
8641 case TRANSACT2_FINDFIRST
:
8643 START_PROFILE(Trans2_findfirst
);
8644 call_trans2findfirst(conn
, req
,
8645 &state
->param
, state
->total_param
,
8646 &state
->data
, state
->total_data
,
8647 state
->max_data_return
);
8648 END_PROFILE(Trans2_findfirst
);
8652 case TRANSACT2_FINDNEXT
:
8654 START_PROFILE(Trans2_findnext
);
8655 call_trans2findnext(conn
, req
,
8656 &state
->param
, state
->total_param
,
8657 &state
->data
, state
->total_data
,
8658 state
->max_data_return
);
8659 END_PROFILE(Trans2_findnext
);
8663 case TRANSACT2_QFSINFO
:
8665 START_PROFILE(Trans2_qfsinfo
);
8666 call_trans2qfsinfo(conn
, req
,
8667 &state
->param
, state
->total_param
,
8668 &state
->data
, state
->total_data
,
8669 state
->max_data_return
);
8670 END_PROFILE(Trans2_qfsinfo
);
8674 case TRANSACT2_SETFSINFO
:
8676 START_PROFILE(Trans2_setfsinfo
);
8677 call_trans2setfsinfo(conn
, req
,
8678 &state
->param
, state
->total_param
,
8679 &state
->data
, state
->total_data
,
8680 state
->max_data_return
);
8681 END_PROFILE(Trans2_setfsinfo
);
8685 case TRANSACT2_QPATHINFO
:
8686 case TRANSACT2_QFILEINFO
:
8688 START_PROFILE(Trans2_qpathinfo
);
8689 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8690 &state
->param
, state
->total_param
,
8691 &state
->data
, state
->total_data
,
8692 state
->max_data_return
);
8693 END_PROFILE(Trans2_qpathinfo
);
8697 case TRANSACT2_SETPATHINFO
:
8698 case TRANSACT2_SETFILEINFO
:
8700 START_PROFILE(Trans2_setpathinfo
);
8701 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8702 &state
->param
, state
->total_param
,
8703 &state
->data
, state
->total_data
,
8704 state
->max_data_return
);
8705 END_PROFILE(Trans2_setpathinfo
);
8709 case TRANSACT2_FINDNOTIFYFIRST
:
8711 START_PROFILE(Trans2_findnotifyfirst
);
8712 call_trans2findnotifyfirst(conn
, req
,
8713 &state
->param
, state
->total_param
,
8714 &state
->data
, state
->total_data
,
8715 state
->max_data_return
);
8716 END_PROFILE(Trans2_findnotifyfirst
);
8720 case TRANSACT2_FINDNOTIFYNEXT
:
8722 START_PROFILE(Trans2_findnotifynext
);
8723 call_trans2findnotifynext(conn
, req
,
8724 &state
->param
, state
->total_param
,
8725 &state
->data
, state
->total_data
,
8726 state
->max_data_return
);
8727 END_PROFILE(Trans2_findnotifynext
);
8731 case TRANSACT2_MKDIR
:
8733 START_PROFILE(Trans2_mkdir
);
8734 call_trans2mkdir(conn
, req
,
8735 &state
->param
, state
->total_param
,
8736 &state
->data
, state
->total_data
,
8737 state
->max_data_return
);
8738 END_PROFILE(Trans2_mkdir
);
8742 case TRANSACT2_GET_DFS_REFERRAL
:
8744 START_PROFILE(Trans2_get_dfs_referral
);
8745 call_trans2getdfsreferral(conn
, req
,
8746 &state
->param
, state
->total_param
,
8747 &state
->data
, state
->total_data
,
8748 state
->max_data_return
);
8749 END_PROFILE(Trans2_get_dfs_referral
);
8753 case TRANSACT2_IOCTL
:
8755 START_PROFILE(Trans2_ioctl
);
8756 call_trans2ioctl(conn
, req
,
8757 &state
->param
, state
->total_param
,
8758 &state
->data
, state
->total_data
,
8759 state
->max_data_return
);
8760 END_PROFILE(Trans2_ioctl
);
8765 /* Error in request */
8766 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8767 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8771 /****************************************************************************
8772 Reply to a SMBtrans2.
8773 ****************************************************************************/
8775 void reply_trans2(struct smb_request
*req
)
8777 connection_struct
*conn
= req
->conn
;
8782 unsigned int tran_call
;
8783 struct trans_state
*state
;
8786 START_PROFILE(SMBtrans2
);
8788 if (req
->wct
< 14) {
8789 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8790 END_PROFILE(SMBtrans2
);
8794 dsoff
= SVAL(req
->vwv
+12, 0);
8795 dscnt
= SVAL(req
->vwv
+11, 0);
8796 psoff
= SVAL(req
->vwv
+10, 0);
8797 pscnt
= SVAL(req
->vwv
+9, 0);
8798 tran_call
= SVAL(req
->vwv
+14, 0);
8800 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8801 if (!NT_STATUS_IS_OK(result
)) {
8802 DEBUG(2, ("Got invalid trans2 request: %s\n",
8803 nt_errstr(result
)));
8804 reply_nterror(req
, result
);
8805 END_PROFILE(SMBtrans2
);
8810 switch (tran_call
) {
8811 /* List the allowed trans2 calls on IPC$ */
8812 case TRANSACT2_OPEN
:
8813 case TRANSACT2_GET_DFS_REFERRAL
:
8814 case TRANSACT2_QFILEINFO
:
8815 case TRANSACT2_QFSINFO
:
8816 case TRANSACT2_SETFSINFO
:
8819 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8820 END_PROFILE(SMBtrans2
);
8825 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8826 DEBUG(0, ("talloc failed\n"));
8827 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8828 END_PROFILE(SMBtrans2
);
8832 state
->cmd
= SMBtrans2
;
8834 state
->mid
= req
->mid
;
8835 state
->vuid
= req
->vuid
;
8836 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8837 state
->setup
= NULL
;
8838 state
->total_param
= SVAL(req
->vwv
+0, 0);
8839 state
->param
= NULL
;
8840 state
->total_data
= SVAL(req
->vwv
+1, 0);
8842 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8843 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8844 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8845 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8846 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8848 state
->call
= tran_call
;
8850 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8851 is so as a sanity check */
8852 if (state
->setup_count
!= 1) {
8854 * Need to have rc=0 for ioctl to get job id for OS/2.
8855 * Network printing will fail if function is not successful.
8856 * Similar function in reply.c will be used if protocol
8857 * is LANMAN1.0 instead of LM1.2X002.
8858 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8859 * outbuf doesn't have to be set(only job id is used).
8861 if ( (state
->setup_count
== 4)
8862 && (tran_call
== TRANSACT2_IOCTL
)
8863 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8864 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8865 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8867 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8868 DEBUG(2,("Transaction is %d\n",tran_call
));
8870 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8871 END_PROFILE(SMBtrans2
);
8876 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8879 if (state
->total_data
) {
8881 if (trans_oob(state
->total_data
, 0, dscnt
)
8882 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8886 /* Can't use talloc here, the core routines do realloc on the
8887 * params and data. */
8888 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8889 if (state
->data
== NULL
) {
8890 DEBUG(0,("reply_trans2: data malloc fail for %u "
8891 "bytes !\n", (unsigned int)state
->total_data
));
8893 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8894 END_PROFILE(SMBtrans2
);
8898 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8901 if (state
->total_param
) {
8903 if (trans_oob(state
->total_param
, 0, pscnt
)
8904 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8908 /* Can't use talloc here, the core routines do realloc on the
8909 * params and data. */
8910 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8911 if (state
->param
== NULL
) {
8912 DEBUG(0,("reply_trans: param malloc fail for %u "
8913 "bytes !\n", (unsigned int)state
->total_param
));
8914 SAFE_FREE(state
->data
);
8916 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8917 END_PROFILE(SMBtrans2
);
8921 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8924 state
->received_data
= dscnt
;
8925 state
->received_param
= pscnt
;
8927 if ((state
->received_param
== state
->total_param
) &&
8928 (state
->received_data
== state
->total_data
)) {
8930 handle_trans2(conn
, req
, state
);
8932 SAFE_FREE(state
->data
);
8933 SAFE_FREE(state
->param
);
8935 END_PROFILE(SMBtrans2
);
8939 DLIST_ADD(conn
->pending_trans
, state
);
8941 /* We need to send an interim response then receive the rest
8942 of the parameter/data bytes */
8943 reply_outbuf(req
, 0, 0);
8944 show_msg((char *)req
->outbuf
);
8945 END_PROFILE(SMBtrans2
);
8950 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8951 SAFE_FREE(state
->data
);
8952 SAFE_FREE(state
->param
);
8954 END_PROFILE(SMBtrans2
);
8955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8959 /****************************************************************************
8960 Reply to a SMBtranss2
8961 ****************************************************************************/
8963 void reply_transs2(struct smb_request
*req
)
8965 connection_struct
*conn
= req
->conn
;
8966 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8967 struct trans_state
*state
;
8969 START_PROFILE(SMBtranss2
);
8971 show_msg((char *)req
->inbuf
);
8973 /* Windows clients expect all replies to
8974 a transact secondary (SMBtranss2 0x33)
8975 to have a command code of transact
8976 (SMBtrans2 0x32). See bug #8989
8977 and also [MS-CIFS] section 2.2.4.47.2
8980 req
->cmd
= SMBtrans2
;
8983 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8984 END_PROFILE(SMBtranss2
);
8988 for (state
= conn
->pending_trans
; state
!= NULL
;
8989 state
= state
->next
) {
8990 if (state
->mid
== req
->mid
) {
8995 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8996 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8997 END_PROFILE(SMBtranss2
);
9001 /* Revise state->total_param and state->total_data in case they have
9002 changed downwards */
9004 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9005 state
->total_param
= SVAL(req
->vwv
+0, 0);
9006 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9007 state
->total_data
= SVAL(req
->vwv
+1, 0);
9009 pcnt
= SVAL(req
->vwv
+2, 0);
9010 poff
= SVAL(req
->vwv
+3, 0);
9011 pdisp
= SVAL(req
->vwv
+4, 0);
9013 dcnt
= SVAL(req
->vwv
+5, 0);
9014 doff
= SVAL(req
->vwv
+6, 0);
9015 ddisp
= SVAL(req
->vwv
+7, 0);
9017 state
->received_param
+= pcnt
;
9018 state
->received_data
+= dcnt
;
9020 if ((state
->received_data
> state
->total_data
) ||
9021 (state
->received_param
> state
->total_param
))
9025 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9026 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9029 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9033 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9034 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9037 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9040 if ((state
->received_param
< state
->total_param
) ||
9041 (state
->received_data
< state
->total_data
)) {
9042 END_PROFILE(SMBtranss2
);
9046 handle_trans2(conn
, req
, state
);
9048 DLIST_REMOVE(conn
->pending_trans
, state
);
9049 SAFE_FREE(state
->data
);
9050 SAFE_FREE(state
->param
);
9053 END_PROFILE(SMBtranss2
);
9058 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9059 DLIST_REMOVE(conn
->pending_trans
, state
);
9060 SAFE_FREE(state
->data
);
9061 SAFE_FREE(state
->param
);
9063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9064 END_PROFILE(SMBtranss2
);