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 struct smb_filename
*fname
,
2978 char *pdata
, *end_data
;
2979 int data_len
= 0, len
;
2980 const char *vname
= volume_label(SNUM(conn
));
2981 int snum
= SNUM(conn
);
2982 char *fstype
= lp_fstype(SNUM(conn
));
2983 const char *filename
= NULL
;
2984 uint32 additional_flags
= 0;
2985 struct smb_filename smb_fname
;
2987 NTSTATUS status
= NT_STATUS_OK
;
2989 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2992 filename
= fname
->base_name
;
2996 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2997 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2998 "info level (0x%x) on IPC$.\n",
2999 (unsigned int)info_level
));
3000 return NT_STATUS_ACCESS_DENIED
;
3004 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3006 ZERO_STRUCT(smb_fname
);
3007 smb_fname
.base_name
= discard_const_p(char, filename
);
3009 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3010 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3011 return map_nt_error_from_unix(errno
);
3016 *ppdata
= (char *)SMB_REALLOC(
3017 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3018 if (*ppdata
== NULL
) {
3019 return NT_STATUS_NO_MEMORY
;
3023 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3024 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3026 switch (info_level
) {
3027 case SMB_INFO_ALLOCATION
:
3029 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3031 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3032 return map_nt_error_from_unix(errno
);
3035 block_size
= lp_block_size(snum
);
3036 if (bsize
< block_size
) {
3037 uint64_t factor
= block_size
/bsize
;
3042 if (bsize
> block_size
) {
3043 uint64_t factor
= bsize
/block_size
;
3048 bytes_per_sector
= 512;
3049 sectors_per_unit
= bsize
/bytes_per_sector
;
3051 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3052 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3053 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3055 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3056 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3057 SIVAL(pdata
,l1_cUnit
,dsize
);
3058 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3059 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3063 case SMB_INFO_VOLUME
:
3064 /* Return volume name */
3066 * Add volume serial number - hash of a combination of
3067 * the called hostname and the service name.
3069 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3071 * Win2k3 and previous mess this up by sending a name length
3072 * one byte short. I believe only older clients (OS/2 Win9x) use
3073 * this call so try fixing this by adding a terminating null to
3074 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3078 pdata
+l2_vol_szVolLabel
, vname
,
3079 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3080 STR_NOALIGN
|STR_TERMINATE
);
3081 SCVAL(pdata
,l2_vol_cch
,len
);
3082 data_len
= l2_vol_szVolLabel
+ len
;
3083 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3084 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3088 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3089 case SMB_FS_ATTRIBUTE_INFORMATION
:
3091 additional_flags
= 0;
3092 #if defined(HAVE_SYS_QUOTAS)
3093 additional_flags
|= FILE_VOLUME_QUOTAS
;
3096 if(lp_nt_acl_support(SNUM(conn
))) {
3097 additional_flags
|= FILE_PERSISTENT_ACLS
;
3100 /* Capabilities are filled in at connection time through STATVFS call */
3101 additional_flags
|= conn
->fs_capabilities
;
3102 additional_flags
|= lp_parm_int(conn
->params
->service
,
3103 "share", "fake_fscaps",
3106 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3107 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3108 additional_flags
); /* FS ATTRIBUTES */
3110 SIVAL(pdata
,4,255); /* Max filename component length */
3111 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3112 and will think we can't do long filenames */
3113 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3114 PTR_DIFF(end_data
, pdata
+12),
3117 data_len
= 12 + len
;
3118 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3119 /* the client only requested a portion of the
3121 data_len
= max_data_bytes
;
3122 status
= STATUS_BUFFER_OVERFLOW
;
3126 case SMB_QUERY_FS_LABEL_INFO
:
3127 case SMB_FS_LABEL_INFORMATION
:
3128 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3129 PTR_DIFF(end_data
, pdata
+4), 0);
3134 case SMB_QUERY_FS_VOLUME_INFO
:
3135 case SMB_FS_VOLUME_INFORMATION
:
3138 * Add volume serial number - hash of a combination of
3139 * the called hostname and the service name.
3141 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
3142 (str_checksum(get_local_machine_name())<<16));
3144 /* Max label len is 32 characters. */
3145 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3146 PTR_DIFF(end_data
, pdata
+18),
3148 SIVAL(pdata
,12,len
);
3151 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3152 (int)strlen(vname
),vname
, lp_servicename(snum
)));
3153 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3154 /* the client only requested a portion of the
3156 data_len
= max_data_bytes
;
3157 status
= STATUS_BUFFER_OVERFLOW
;
3162 case SMB_QUERY_FS_SIZE_INFO
:
3163 case SMB_FS_SIZE_INFORMATION
:
3165 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3167 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3168 return map_nt_error_from_unix(errno
);
3170 block_size
= lp_block_size(snum
);
3171 if (bsize
< block_size
) {
3172 uint64_t factor
= block_size
/bsize
;
3177 if (bsize
> block_size
) {
3178 uint64_t factor
= bsize
/block_size
;
3183 bytes_per_sector
= 512;
3184 sectors_per_unit
= bsize
/bytes_per_sector
;
3185 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3186 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3187 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3188 SBIG_UINT(pdata
,0,dsize
);
3189 SBIG_UINT(pdata
,8,dfree
);
3190 SIVAL(pdata
,16,sectors_per_unit
);
3191 SIVAL(pdata
,20,bytes_per_sector
);
3195 case SMB_FS_FULL_SIZE_INFORMATION
:
3197 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3199 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3200 return map_nt_error_from_unix(errno
);
3202 block_size
= lp_block_size(snum
);
3203 if (bsize
< block_size
) {
3204 uint64_t factor
= block_size
/bsize
;
3209 if (bsize
> block_size
) {
3210 uint64_t factor
= bsize
/block_size
;
3215 bytes_per_sector
= 512;
3216 sectors_per_unit
= bsize
/bytes_per_sector
;
3217 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3218 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3219 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3220 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3221 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3222 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3223 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3224 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3228 case SMB_QUERY_FS_DEVICE_INFO
:
3229 case SMB_FS_DEVICE_INFORMATION
:
3231 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3233 if (!CAN_WRITE(conn
)) {
3234 characteristics
|= FILE_READ_ONLY_DEVICE
;
3237 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3238 SIVAL(pdata
,4,characteristics
);
3242 #ifdef HAVE_SYS_QUOTAS
3243 case SMB_FS_QUOTA_INFORMATION
:
3245 * what we have to send --metze:
3247 * Unknown1: 24 NULL bytes
3248 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3249 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3250 * Quota Flags: 2 byte :
3251 * Unknown3: 6 NULL bytes
3255 * details for Quota Flags:
3257 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3258 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3259 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3260 * 0x0001 Enable Quotas: enable quota for this fs
3264 /* we need to fake up a fsp here,
3265 * because its not send in this call
3268 SMB_NTQUOTA_STRUCT quotas
;
3271 ZERO_STRUCT(quotas
);
3277 if (get_current_uid(conn
) != 0) {
3278 DEBUG(0,("set_user_quota: access_denied "
3279 "service [%s] user [%s]\n",
3280 lp_servicename(SNUM(conn
)),
3281 conn
->session_info
->unix_name
));
3282 return NT_STATUS_ACCESS_DENIED
;
3285 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3286 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3287 return map_nt_error_from_unix(errno
);
3292 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3293 lp_servicename(SNUM(conn
))));
3295 /* Unknown1 24 NULL bytes*/
3296 SBIG_UINT(pdata
,0,(uint64_t)0);
3297 SBIG_UINT(pdata
,8,(uint64_t)0);
3298 SBIG_UINT(pdata
,16,(uint64_t)0);
3300 /* Default Soft Quota 8 bytes */
3301 SBIG_UINT(pdata
,24,quotas
.softlim
);
3303 /* Default Hard Quota 8 bytes */
3304 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3306 /* Quota flag 2 bytes */
3307 SSVAL(pdata
,40,quotas
.qflags
);
3309 /* Unknown3 6 NULL bytes */
3315 #endif /* HAVE_SYS_QUOTAS */
3316 case SMB_FS_OBJECTID_INFORMATION
:
3318 unsigned char objid
[16];
3319 struct smb_extended_info extended_info
;
3320 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3321 samba_extended_info_version (&extended_info
);
3322 SIVAL(pdata
,16,extended_info
.samba_magic
);
3323 SIVAL(pdata
,20,extended_info
.samba_version
);
3324 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3325 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3326 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3332 * Query the version and capabilities of the CIFS UNIX extensions
3336 case SMB_QUERY_CIFS_UNIX_INFO
:
3338 bool large_write
= lp_min_receive_file_size() &&
3339 !srv_is_signing_active(conn
->sconn
);
3340 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3341 int encrypt_caps
= 0;
3343 if (!lp_unix_extensions()) {
3344 return NT_STATUS_INVALID_LEVEL
;
3347 switch (conn
->encrypt_level
) {
3353 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3356 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3357 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3358 large_write
= false;
3364 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3365 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3367 /* We have POSIX ACLs, pathname, encryption,
3368 * large read/write, and locking capability. */
3370 SBIG_UINT(pdata
,4,((uint64_t)(
3371 CIFS_UNIX_POSIX_ACLS_CAP
|
3372 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3373 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3374 CIFS_UNIX_EXTATTR_CAP
|
3375 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3377 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3379 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3383 case SMB_QUERY_POSIX_FS_INFO
:
3386 vfs_statvfs_struct svfs
;
3388 if (!lp_unix_extensions()) {
3389 return NT_STATUS_INVALID_LEVEL
;
3392 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3396 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3397 SIVAL(pdata
,4,svfs
.BlockSize
);
3398 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3399 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3400 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3401 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3402 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3403 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3406 } else if (rc
== EOPNOTSUPP
) {
3407 return NT_STATUS_INVALID_LEVEL
;
3408 #endif /* EOPNOTSUPP */
3410 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3411 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3416 case SMB_QUERY_POSIX_WHOAMI
:
3422 if (!lp_unix_extensions()) {
3423 return NT_STATUS_INVALID_LEVEL
;
3426 if (max_data_bytes
< 40) {
3427 return NT_STATUS_BUFFER_TOO_SMALL
;
3430 /* We ARE guest if global_sid_Builtin_Guests is
3431 * in our list of SIDs.
3433 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
3434 conn
->session_info
->security_token
)) {
3435 flags
|= SMB_WHOAMI_GUEST
;
3438 /* We are NOT guest if global_sid_Authenticated_Users
3439 * is in our list of SIDs.
3441 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
3442 conn
->session_info
->security_token
)) {
3443 flags
&= ~SMB_WHOAMI_GUEST
;
3446 /* NOTE: 8 bytes for UID/GID, irrespective of native
3447 * platform size. This matches
3448 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3450 data_len
= 4 /* flags */
3457 + 4 /* pad/reserved */
3458 + (conn
->session_info
->utok
.ngroups
* 8)
3460 + (conn
->session_info
->security_token
->num_sids
*
3464 SIVAL(pdata
, 0, flags
);
3465 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3467 (uint64_t)conn
->session_info
->utok
.uid
);
3468 SBIG_UINT(pdata
, 16,
3469 (uint64_t)conn
->session_info
->utok
.gid
);
3472 if (data_len
>= max_data_bytes
) {
3473 /* Potential overflow, skip the GIDs and SIDs. */
3475 SIVAL(pdata
, 24, 0); /* num_groups */
3476 SIVAL(pdata
, 28, 0); /* num_sids */
3477 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3478 SIVAL(pdata
, 36, 0); /* reserved */
3484 SIVAL(pdata
, 24, conn
->session_info
->utok
.ngroups
);
3485 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3487 /* We walk the SID list twice, but this call is fairly
3488 * infrequent, and I don't expect that it's performance
3489 * sensitive -- jpeach
3491 for (i
= 0, sid_bytes
= 0;
3492 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3493 sid_bytes
+= ndr_size_dom_sid(
3494 &conn
->session_info
->security_token
->sids
[i
],
3498 /* SID list byte count */
3499 SIVAL(pdata
, 32, sid_bytes
);
3501 /* 4 bytes pad/reserved - must be zero */
3502 SIVAL(pdata
, 36, 0);
3506 for (i
= 0; i
< conn
->session_info
->utok
.ngroups
; ++i
) {
3507 SBIG_UINT(pdata
, data_len
,
3508 (uint64_t)conn
->session_info
->utok
.groups
[i
]);
3514 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3515 int sid_len
= ndr_size_dom_sid(
3516 &conn
->session_info
->security_token
->sids
[i
],
3519 sid_linearize(pdata
+ data_len
, sid_len
,
3520 &conn
->session_info
->security_token
->sids
[i
]);
3521 data_len
+= sid_len
;
3527 case SMB_MAC_QUERY_FS_INFO
:
3529 * Thursby MAC extension... ONLY on NTFS filesystems
3530 * once we do streams then we don't need this
3532 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3534 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3539 return NT_STATUS_INVALID_LEVEL
;
3542 *ret_data_len
= data_len
;
3546 /****************************************************************************
3547 Reply to a TRANS2_QFSINFO (query filesystem info).
3548 ****************************************************************************/
3550 static void call_trans2qfsinfo(connection_struct
*conn
,
3551 struct smb_request
*req
,
3552 char **pparams
, int total_params
,
3553 char **ppdata
, int total_data
,
3554 unsigned int max_data_bytes
)
3556 char *params
= *pparams
;
3557 uint16_t info_level
;
3561 if (total_params
< 2) {
3562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3566 info_level
= SVAL(params
,0);
3568 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3569 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3570 DEBUG(0,("call_trans2qfsinfo: encryption required "
3571 "and info level 0x%x sent.\n",
3572 (unsigned int)info_level
));
3573 exit_server_cleanly("encryption required "
3579 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3581 status
= smbd_do_qfsinfo(conn
, req
,
3587 if (!NT_STATUS_IS_OK(status
)) {
3588 reply_nterror(req
, status
);
3592 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3595 DEBUG( 4, ( "%s info_level = %d\n",
3596 smb_fn_name(req
->cmd
), info_level
) );
3601 /****************************************************************************
3602 Reply to a TRANS2_SETFSINFO (set filesystem info).
3603 ****************************************************************************/
3605 static void call_trans2setfsinfo(connection_struct
*conn
,
3606 struct smb_request
*req
,
3607 char **pparams
, int total_params
,
3608 char **ppdata
, int total_data
,
3609 unsigned int max_data_bytes
)
3611 char *pdata
= *ppdata
;
3612 char *params
= *pparams
;
3615 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
3618 if (total_params
< 4) {
3619 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3621 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3625 info_level
= SVAL(params
,2);
3628 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3629 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3630 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3631 "info level (0x%x) on IPC$.\n",
3632 (unsigned int)info_level
));
3633 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3638 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3639 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3640 DEBUG(0,("call_trans2setfsinfo: encryption required "
3641 "and info level 0x%x sent.\n",
3642 (unsigned int)info_level
));
3643 exit_server_cleanly("encryption required "
3649 switch(info_level
) {
3650 case SMB_SET_CIFS_UNIX_INFO
:
3652 uint16 client_unix_major
;
3653 uint16 client_unix_minor
;
3654 uint32 client_unix_cap_low
;
3655 uint32 client_unix_cap_high
;
3657 if (!lp_unix_extensions()) {
3659 NT_STATUS_INVALID_LEVEL
);
3663 /* There should be 12 bytes of capabilities set. */
3664 if (total_data
< 8) {
3667 NT_STATUS_INVALID_PARAMETER
);
3670 client_unix_major
= SVAL(pdata
,0);
3671 client_unix_minor
= SVAL(pdata
,2);
3672 client_unix_cap_low
= IVAL(pdata
,4);
3673 client_unix_cap_high
= IVAL(pdata
,8);
3674 /* Just print these values for now. */
3675 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3676 cap_low = 0x%x, cap_high = 0x%x\n",
3677 (unsigned int)client_unix_major
,
3678 (unsigned int)client_unix_minor
,
3679 (unsigned int)client_unix_cap_low
,
3680 (unsigned int)client_unix_cap_high
));
3682 /* Here is where we must switch to posix pathname processing... */
3683 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3684 lp_set_posix_pathnames();
3685 mangle_change_to_posix();
3688 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3689 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3690 /* Client that knows how to do posix locks,
3691 * but not posix open/mkdir operations. Set a
3692 * default type for read/write checks. */
3694 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3700 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3703 size_t param_len
= 0;
3704 size_t data_len
= total_data
;
3706 if (!lp_unix_extensions()) {
3709 NT_STATUS_INVALID_LEVEL
);
3713 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3716 NT_STATUS_NOT_SUPPORTED
);
3720 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3721 DEBUG( 2,("call_trans2setfsinfo: "
3722 "request transport encryption disabled"
3723 "with 'fork echo handler = yes'\n"));
3726 NT_STATUS_NOT_SUPPORTED
);
3730 DEBUG( 4,("call_trans2setfsinfo: "
3731 "request transport encryption.\n"));
3733 status
= srv_request_encryption_setup(conn
,
3734 (unsigned char **)ppdata
,
3736 (unsigned char **)pparams
,
3739 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3740 !NT_STATUS_IS_OK(status
)) {
3741 reply_nterror(req
, status
);
3745 send_trans2_replies(conn
, req
,
3752 if (NT_STATUS_IS_OK(status
)) {
3753 /* Server-side transport
3754 * encryption is now *on*. */
3755 status
= srv_encryption_start(conn
);
3756 if (!NT_STATUS_IS_OK(status
)) {
3757 exit_server_cleanly(
3758 "Failure in setting "
3759 "up encrypted transport");
3765 case SMB_FS_QUOTA_INFORMATION
:
3767 files_struct
*fsp
= NULL
;
3768 SMB_NTQUOTA_STRUCT quotas
;
3770 ZERO_STRUCT(quotas
);
3773 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3774 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3775 lp_servicename(SNUM(conn
)),
3776 conn
->session_info
->unix_name
));
3777 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3781 /* note: normaly there're 48 bytes,
3782 * but we didn't use the last 6 bytes for now
3785 fsp
= file_fsp(req
, SVAL(params
,0));
3787 if (!check_fsp_ntquota_handle(conn
, req
,
3789 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3791 req
, NT_STATUS_INVALID_HANDLE
);
3795 if (total_data
< 42) {
3796 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3800 NT_STATUS_INVALID_PARAMETER
);
3804 /* unknown_1 24 NULL bytes in pdata*/
3806 /* the soft quotas 8 bytes (uint64_t)*/
3807 quotas
.softlim
= BVAL(pdata
,24);
3809 /* the hard quotas 8 bytes (uint64_t)*/
3810 quotas
.hardlim
= BVAL(pdata
,32);
3812 /* quota_flags 2 bytes **/
3813 quotas
.qflags
= SVAL(pdata
,40);
3815 /* unknown_2 6 NULL bytes follow*/
3817 /* now set the quotas */
3818 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3819 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3820 reply_nterror(req
, map_nt_error_from_unix(errno
));
3827 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3829 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3835 * sending this reply works fine,
3836 * but I'm not sure it's the same
3837 * like windows do...
3840 reply_outbuf(req
, 10, 0);
3843 #if defined(HAVE_POSIX_ACLS)
3844 /****************************************************************************
3845 Utility function to count the number of entries in a POSIX acl.
3846 ****************************************************************************/
3848 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3850 unsigned int ace_count
= 0;
3851 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3852 SMB_ACL_ENTRY_T entry
;
3854 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3856 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3857 entry_id
= SMB_ACL_NEXT_ENTRY
;
3864 /****************************************************************************
3865 Utility function to marshall a POSIX acl into wire format.
3866 ****************************************************************************/
3868 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3870 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3871 SMB_ACL_ENTRY_T entry
;
3873 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3874 SMB_ACL_TAG_T tagtype
;
3875 SMB_ACL_PERMSET_T permset
;
3876 unsigned char perms
= 0;
3877 unsigned int own_grp
;
3880 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3881 entry_id
= SMB_ACL_NEXT_ENTRY
;
3884 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3885 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3889 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3894 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3895 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3896 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3898 SCVAL(pdata
,1,perms
);
3901 case SMB_ACL_USER_OBJ
:
3902 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3903 own_grp
= (unsigned int)pst
->st_ex_uid
;
3904 SIVAL(pdata
,2,own_grp
);
3909 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3911 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3914 own_grp
= (unsigned int)*puid
;
3915 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3916 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3917 SIVAL(pdata
,2,own_grp
);
3921 case SMB_ACL_GROUP_OBJ
:
3922 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3923 own_grp
= (unsigned int)pst
->st_ex_gid
;
3924 SIVAL(pdata
,2,own_grp
);
3929 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3931 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3934 own_grp
= (unsigned int)*pgid
;
3935 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3936 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3937 SIVAL(pdata
,2,own_grp
);
3942 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3943 SIVAL(pdata
,2,0xFFFFFFFF);
3944 SIVAL(pdata
,6,0xFFFFFFFF);
3947 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3948 SIVAL(pdata
,2,0xFFFFFFFF);
3949 SIVAL(pdata
,6,0xFFFFFFFF);
3952 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3955 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3962 /****************************************************************************
3963 Store the FILE_UNIX_BASIC info.
3964 ****************************************************************************/
3966 static char *store_file_unix_basic(connection_struct
*conn
,
3969 const SMB_STRUCT_STAT
*psbuf
)
3971 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3973 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3974 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3976 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3979 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3982 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3983 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3984 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3987 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3991 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3995 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3998 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_ex_rdev
)); /* Major device number if type is device */
4002 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_ex_rdev
)); /* Minor device number if type is device */
4006 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4009 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4013 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4020 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4021 * the chflags(2) (or equivalent) flags.
4023 * XXX: this really should be behind the VFS interface. To do this, we would
4024 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4025 * Each VFS module could then implement its own mapping as appropriate for the
4026 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4028 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4032 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4036 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4040 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4044 { UF_HIDDEN
, EXT_HIDDEN
},
4047 /* Do not remove. We need to guarantee that this array has at least one
4048 * entry to build on HP-UX.
4054 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4055 uint32
*smb_fflags
, uint32
*smb_fmask
)
4059 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4060 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4061 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4062 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4067 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4068 const uint32 smb_fflags
,
4069 const uint32 smb_fmask
,
4072 uint32 max_fmask
= 0;
4075 *stat_fflags
= psbuf
->st_ex_flags
;
4077 /* For each flags requested in smb_fmask, check the state of the
4078 * corresponding flag in smb_fflags and set or clear the matching
4082 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4083 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4084 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4085 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4086 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4088 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4093 /* If smb_fmask is asking to set any bits that are not supported by
4094 * our flag mappings, we should fail.
4096 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4104 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4105 * of file flags and birth (create) time.
4107 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4110 const SMB_STRUCT_STAT
*psbuf
)
4112 uint32 file_flags
= 0;
4113 uint32 flags_mask
= 0;
4115 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4117 /* Create (birth) time 64 bit */
4118 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4121 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4122 SIVAL(pdata
, 0, file_flags
); /* flags */
4123 SIVAL(pdata
, 4, flags_mask
); /* mask */
4129 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4130 const struct stream_struct
*streams
,
4132 unsigned int max_data_bytes
,
4133 unsigned int *data_size
)
4136 unsigned int ofs
= 0;
4138 for (i
= 0; i
< num_streams
; i
++) {
4139 unsigned int next_offset
;
4141 smb_ucs2_t
*namebuf
;
4143 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4144 streams
[i
].name
, &namelen
) ||
4147 return NT_STATUS_INVALID_PARAMETER
;
4151 * name_buf is now null-terminated, we need to marshall as not
4158 * We cannot overflow ...
4160 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4161 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4163 TALLOC_FREE(namebuf
);
4164 return STATUS_BUFFER_OVERFLOW
;
4167 SIVAL(data
, ofs
+4, namelen
);
4168 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4169 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4170 memcpy(data
+ofs
+24, namebuf
, namelen
);
4171 TALLOC_FREE(namebuf
);
4173 next_offset
= ofs
+ 24 + namelen
;
4175 if (i
== num_streams
-1) {
4176 SIVAL(data
, ofs
, 0);
4179 unsigned int align
= ndr_align_size(next_offset
, 8);
4181 if ((next_offset
+ align
) > max_data_bytes
) {
4182 DEBUG(10, ("refusing to overflow align "
4183 "reply at stream %u\n",
4185 TALLOC_FREE(namebuf
);
4186 return STATUS_BUFFER_OVERFLOW
;
4189 memset(data
+next_offset
, 0, align
);
4190 next_offset
+= align
;
4192 SIVAL(data
, ofs
, next_offset
- ofs
);
4199 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4203 return NT_STATUS_OK
;
4206 /****************************************************************************
4207 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4208 ****************************************************************************/
4210 static void call_trans2qpipeinfo(connection_struct
*conn
,
4211 struct smb_request
*req
,
4212 unsigned int tran_call
,
4213 char **pparams
, int total_params
,
4214 char **ppdata
, int total_data
,
4215 unsigned int max_data_bytes
)
4217 char *params
= *pparams
;
4218 char *pdata
= *ppdata
;
4219 unsigned int data_size
= 0;
4220 unsigned int param_size
= 2;
4225 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4229 if (total_params
< 4) {
4230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4234 fsp
= file_fsp(req
, SVAL(params
,0));
4235 if (!fsp_is_np(fsp
)) {
4236 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4240 info_level
= SVAL(params
,2);
4242 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4243 if (*pparams
== NULL
) {
4244 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4249 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4250 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4251 if (*ppdata
== NULL
) {
4252 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4257 switch (info_level
) {
4258 case SMB_FILE_STANDARD_INFORMATION
:
4260 SOFF_T(pdata
,0,4096LL);
4267 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4271 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4277 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4278 TALLOC_CTX
*mem_ctx
,
4279 uint16_t info_level
,
4281 struct smb_filename
*smb_fname
,
4282 bool delete_pending
,
4283 struct timespec write_time_ts
,
4284 struct ea_list
*ea_list
,
4285 int lock_data_count
,
4288 unsigned int max_data_bytes
,
4290 unsigned int *pdata_size
)
4292 char *pdata
= *ppdata
;
4293 char *dstart
, *dend
;
4294 unsigned int data_size
;
4295 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4296 time_t create_time
, mtime
, atime
, c_time
;
4297 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4304 uint64_t file_size
= 0;
4306 uint64_t allocation_size
= 0;
4307 uint64_t file_index
= 0;
4308 uint32_t access_mask
= 0;
4310 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4311 return NT_STATUS_INVALID_LEVEL
;
4314 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4315 smb_fname_str_dbg(smb_fname
), fsp
? fsp
->fnum
: -1,
4316 info_level
, max_data_bytes
));
4318 mode
= dos_mode(conn
, smb_fname
);
4319 nlink
= psbuf
->st_ex_nlink
;
4321 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4325 if ((nlink
> 0) && delete_pending
) {
4329 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4330 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4331 if (*ppdata
== NULL
) {
4332 return NT_STATUS_NO_MEMORY
;
4336 dend
= dstart
+ data_size
- 1;
4338 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4339 update_stat_ex_mtime(psbuf
, write_time_ts
);
4342 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4343 mtime_ts
= psbuf
->st_ex_mtime
;
4344 atime_ts
= psbuf
->st_ex_atime
;
4345 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4347 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4348 dos_filetime_timespec(&create_time_ts
);
4349 dos_filetime_timespec(&mtime_ts
);
4350 dos_filetime_timespec(&atime_ts
);
4351 dos_filetime_timespec(&ctime_ts
);
4354 create_time
= convert_timespec_to_time_t(create_time_ts
);
4355 mtime
= convert_timespec_to_time_t(mtime_ts
);
4356 atime
= convert_timespec_to_time_t(atime_ts
);
4357 c_time
= convert_timespec_to_time_t(ctime_ts
);
4359 p
= strrchr_m(smb_fname
->base_name
,'/');
4361 base_name
= smb_fname
->base_name
;
4365 /* NT expects the name to be in an exact form of the *full*
4366 filename. See the trans2 torture test */
4367 if (ISDOT(base_name
)) {
4368 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4370 return NT_STATUS_NO_MEMORY
;
4373 dos_fname
= talloc_asprintf(mem_ctx
,
4375 smb_fname
->base_name
);
4377 return NT_STATUS_NO_MEMORY
;
4379 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4380 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4381 smb_fname
->stream_name
);
4383 return NT_STATUS_NO_MEMORY
;
4387 string_replace(dos_fname
, '/', '\\');
4390 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4393 /* Do we have this path open ? */
4395 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4396 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4397 if (fsp1
&& fsp1
->initial_allocation_size
) {
4398 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4402 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4403 file_size
= get_file_size_stat(psbuf
);
4407 pos
= fsp
->fh
->position_information
;
4411 access_mask
= fsp
->access_mask
;
4413 /* GENERIC_EXECUTE mapping from Windows */
4414 access_mask
= 0x12019F;
4417 /* This should be an index number - looks like
4420 I think this causes us to fail the IFSKIT
4421 BasicFileInformationTest. -tpot */
4422 file_index
= get_FileIndex(conn
, psbuf
);
4424 switch (info_level
) {
4425 case SMB_INFO_STANDARD
:
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4428 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4429 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4430 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4431 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4432 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4433 SSVAL(pdata
,l1_attrFile
,mode
);
4436 case SMB_INFO_QUERY_EA_SIZE
:
4438 unsigned int ea_size
=
4439 estimate_ea_size(conn
, fsp
,
4440 smb_fname
->base_name
);
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4443 srv_put_dos_date2(pdata
,0,create_time
);
4444 srv_put_dos_date2(pdata
,4,atime
);
4445 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4446 SIVAL(pdata
,12,(uint32
)file_size
);
4447 SIVAL(pdata
,16,(uint32
)allocation_size
);
4448 SSVAL(pdata
,20,mode
);
4449 SIVAL(pdata
,22,ea_size
);
4453 case SMB_INFO_IS_NAME_VALID
:
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4456 /* os/2 needs this ? really ?*/
4457 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4459 /* This is only reached for qpathinfo */
4463 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4465 size_t total_ea_len
= 0;
4466 struct ea_list
*ea_file_list
= NULL
;
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4471 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4472 smb_fname
->base_name
,
4474 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4476 if (!ea_list
|| (total_ea_len
> data_size
)) {
4478 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4482 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4486 case SMB_INFO_QUERY_ALL_EAS
:
4488 /* We have data_size bytes to put EA's into. */
4489 size_t total_ea_len
= 0;
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4493 ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4494 smb_fname
->base_name
,
4496 if (!ea_list
|| (total_ea_len
> data_size
)) {
4498 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4502 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4506 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4508 /* This is FileFullEaInformation - 0xF which maps to
4509 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4511 /* We have data_size bytes to put EA's into. */
4512 size_t total_ea_len
= 0;
4513 struct ea_list
*ea_file_list
= NULL
;
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4517 /*TODO: add filtering and index handling */
4520 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4521 smb_fname
->base_name
,
4523 if (!ea_file_list
) {
4524 return NT_STATUS_NO_EAS_ON_FILE
;
4527 status
= fill_ea_chained_buffer(mem_ctx
,
4531 conn
, ea_file_list
);
4532 if (!NT_STATUS_IS_OK(status
)) {
4538 case SMB_FILE_BASIC_INFORMATION
:
4539 case SMB_QUERY_FILE_BASIC_INFO
:
4541 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4543 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4549 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4550 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4551 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4552 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4553 SIVAL(pdata
,32,mode
);
4555 DEBUG(5,("SMB_QFBI - "));
4556 DEBUG(5,("create: %s ", ctime(&create_time
)));
4557 DEBUG(5,("access: %s ", ctime(&atime
)));
4558 DEBUG(5,("write: %s ", ctime(&mtime
)));
4559 DEBUG(5,("change: %s ", ctime(&c_time
)));
4560 DEBUG(5,("mode: %x\n", mode
));
4563 case SMB_FILE_STANDARD_INFORMATION
:
4564 case SMB_QUERY_FILE_STANDARD_INFO
:
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4568 SOFF_T(pdata
,0,allocation_size
);
4569 SOFF_T(pdata
,8,file_size
);
4570 SIVAL(pdata
,16,nlink
);
4571 SCVAL(pdata
,20,delete_pending
?1:0);
4572 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4573 SSVAL(pdata
,22,0); /* Padding. */
4576 case SMB_FILE_EA_INFORMATION
:
4577 case SMB_QUERY_FILE_EA_INFO
:
4579 unsigned int ea_size
=
4580 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4583 SIVAL(pdata
,0,ea_size
);
4587 /* Get the 8.3 name - used if NT SMB was negotiated. */
4588 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4589 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4592 char mangled_name
[13];
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4594 if (!name_to_8_3(base_name
,mangled_name
,
4595 True
,conn
->params
)) {
4596 return NT_STATUS_NO_MEMORY
;
4598 len
= srvstr_push(dstart
, flags2
,
4599 pdata
+4, mangled_name
,
4600 PTR_DIFF(dend
, pdata
+4),
4602 data_size
= 4 + len
;
4607 case SMB_QUERY_FILE_NAME_INFO
:
4611 this must be *exactly* right for ACLs on mapped drives to work
4613 len
= srvstr_push(dstart
, flags2
,
4615 PTR_DIFF(dend
, pdata
+4),
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4618 data_size
= 4 + len
;
4623 case SMB_FILE_ALLOCATION_INFORMATION
:
4624 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4627 SOFF_T(pdata
,0,allocation_size
);
4630 case SMB_FILE_END_OF_FILE_INFORMATION
:
4631 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4634 SOFF_T(pdata
,0,file_size
);
4637 case SMB_QUERY_FILE_ALL_INFO
:
4638 case SMB_FILE_ALL_INFORMATION
:
4641 unsigned int ea_size
=
4642 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4643 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4644 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4645 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4646 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4647 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4648 SIVAL(pdata
,32,mode
);
4649 SIVAL(pdata
,36,0); /* padding. */
4651 SOFF_T(pdata
,0,allocation_size
);
4652 SOFF_T(pdata
,8,file_size
);
4653 SIVAL(pdata
,16,nlink
);
4654 SCVAL(pdata
,20,delete_pending
);
4655 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4658 SIVAL(pdata
,0,ea_size
);
4659 pdata
+= 4; /* EA info */
4660 len
= srvstr_push(dstart
, flags2
,
4662 PTR_DIFF(dend
, pdata
+4),
4666 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4670 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4673 unsigned int ea_size
=
4674 estimate_ea_size(conn
, fsp
, smb_fname
->base_name
);
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4676 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4677 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4678 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4679 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4680 SIVAL(pdata
, 0x20, mode
);
4681 SIVAL(pdata
, 0x24, 0); /* padding. */
4682 SBVAL(pdata
, 0x28, allocation_size
);
4683 SBVAL(pdata
, 0x30, file_size
);
4684 SIVAL(pdata
, 0x38, nlink
);
4685 SCVAL(pdata
, 0x3C, delete_pending
);
4686 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4687 SSVAL(pdata
, 0x3E, 0); /* padding */
4688 SBVAL(pdata
, 0x40, file_index
);
4689 SIVAL(pdata
, 0x48, ea_size
);
4690 SIVAL(pdata
, 0x4C, access_mask
);
4691 SBVAL(pdata
, 0x50, pos
);
4692 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4693 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4697 len
= srvstr_push(dstart
, flags2
,
4699 PTR_DIFF(dend
, pdata
+4),
4703 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4706 case SMB_FILE_INTERNAL_INFORMATION
:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4709 SBVAL(pdata
, 0, file_index
);
4713 case SMB_FILE_ACCESS_INFORMATION
:
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4715 SIVAL(pdata
, 0, access_mask
);
4719 case SMB_FILE_NAME_INFORMATION
:
4720 /* Pathname with leading '\'. */
4723 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4725 SIVAL(pdata
,0,byte_len
);
4726 data_size
= 4 + byte_len
;
4730 case SMB_FILE_DISPOSITION_INFORMATION
:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4733 SCVAL(pdata
,0,delete_pending
);
4736 case SMB_FILE_POSITION_INFORMATION
:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4739 SOFF_T(pdata
,0,pos
);
4742 case SMB_FILE_MODE_INFORMATION
:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4744 SIVAL(pdata
,0,mode
);
4748 case SMB_FILE_ALIGNMENT_INFORMATION
:
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4750 SIVAL(pdata
,0,0); /* No alignment needed. */
4755 * NT4 server just returns "invalid query" to this - if we try
4756 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4759 /* The first statement above is false - verified using Thursby
4760 * client against NT4 -- gcolley.
4762 case SMB_QUERY_FILE_STREAM_INFO
:
4763 case SMB_FILE_STREAM_INFORMATION
: {
4764 unsigned int num_streams
= 0;
4765 struct stream_struct
*streams
= NULL
;
4767 DEBUG(10,("smbd_do_qfilepathinfo: "
4768 "SMB_FILE_STREAM_INFORMATION\n"));
4770 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4771 return NT_STATUS_INVALID_PARAMETER
;
4774 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4775 talloc_tos(), &num_streams
, &streams
);
4777 if (!NT_STATUS_IS_OK(status
)) {
4778 DEBUG(10, ("could not get stream info: %s\n",
4779 nt_errstr(status
)));
4783 status
= marshall_stream_info(num_streams
, streams
,
4784 pdata
, max_data_bytes
,
4787 if (!NT_STATUS_IS_OK(status
)) {
4788 DEBUG(10, ("marshall_stream_info failed: %s\n",
4789 nt_errstr(status
)));
4790 TALLOC_FREE(streams
);
4794 TALLOC_FREE(streams
);
4798 case SMB_QUERY_COMPRESSION_INFO
:
4799 case SMB_FILE_COMPRESSION_INFORMATION
:
4800 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4801 SOFF_T(pdata
,0,file_size
);
4802 SIVAL(pdata
,8,0); /* ??? */
4803 SIVAL(pdata
,12,0); /* ??? */
4807 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4809 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4810 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4811 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4812 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4813 SOFF_T(pdata
,32,allocation_size
);
4814 SOFF_T(pdata
,40,file_size
);
4815 SIVAL(pdata
,48,mode
);
4816 SIVAL(pdata
,52,0); /* ??? */
4820 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4821 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4822 SIVAL(pdata
,0,mode
);
4828 * CIFS UNIX Extensions.
4831 case SMB_QUERY_FILE_UNIX_BASIC
:
4833 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4834 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4836 DEBUG(4,("smbd_do_qfilepathinfo: "
4837 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4838 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4842 case SMB_QUERY_FILE_UNIX_INFO2
:
4844 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4845 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4849 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4851 for (i
=0; i
<100; i
++)
4852 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4858 case SMB_QUERY_FILE_UNIX_LINK
:
4861 char *buffer
= TALLOC_ARRAY(mem_ctx
, char, PATH_MAX
+1);
4864 return NT_STATUS_NO_MEMORY
;
4867 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4869 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4870 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4873 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4875 len
= SMB_VFS_READLINK(conn
,
4876 smb_fname
->base_name
,
4879 return map_nt_error_from_unix(errno
);
4882 len
= srvstr_push(dstart
, flags2
,
4884 PTR_DIFF(dend
, pdata
),
4887 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4892 #if defined(HAVE_POSIX_ACLS)
4893 case SMB_QUERY_POSIX_ACL
:
4895 SMB_ACL_T file_acl
= NULL
;
4896 SMB_ACL_T def_acl
= NULL
;
4897 uint16 num_file_acls
= 0;
4898 uint16 num_def_acls
= 0;
4900 if (fsp
&& fsp
->fh
->fd
!= -1) {
4901 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4904 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4905 smb_fname
->base_name
,
4906 SMB_ACL_TYPE_ACCESS
);
4909 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4910 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4911 "not implemented on "
4912 "filesystem containing %s\n",
4913 smb_fname
->base_name
));
4914 return NT_STATUS_NOT_IMPLEMENTED
;
4917 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4918 if (fsp
&& fsp
->is_directory
) {
4920 SMB_VFS_SYS_ACL_GET_FILE(
4922 fsp
->fsp_name
->base_name
,
4923 SMB_ACL_TYPE_DEFAULT
);
4926 SMB_VFS_SYS_ACL_GET_FILE(
4928 smb_fname
->base_name
,
4929 SMB_ACL_TYPE_DEFAULT
);
4931 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4934 num_file_acls
= count_acl_entries(conn
, file_acl
);
4935 num_def_acls
= count_acl_entries(conn
, def_acl
);
4937 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4938 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4940 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4941 SMB_POSIX_ACL_HEADER_SIZE
) ));
4943 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4948 return NT_STATUS_BUFFER_TOO_SMALL
;
4951 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4952 SSVAL(pdata
,2,num_file_acls
);
4953 SSVAL(pdata
,4,num_def_acls
);
4954 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4956 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4959 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4961 return NT_STATUS_INTERNAL_ERROR
;
4963 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4965 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4968 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4970 return NT_STATUS_INTERNAL_ERROR
;
4974 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4977 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4979 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4985 case SMB_QUERY_POSIX_LOCK
:
4990 enum brl_type lock_type
;
4992 /* We need an open file with a real fd for this. */
4993 if (!fsp
|| fsp
->fh
->fd
== -1) {
4994 return NT_STATUS_INVALID_LEVEL
;
4997 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4998 return NT_STATUS_INVALID_PARAMETER
;
5001 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5002 case POSIX_LOCK_TYPE_READ
:
5003 lock_type
= READ_LOCK
;
5005 case POSIX_LOCK_TYPE_WRITE
:
5006 lock_type
= WRITE_LOCK
;
5008 case POSIX_LOCK_TYPE_UNLOCK
:
5010 /* There's no point in asking for an unlock... */
5011 return NT_STATUS_INVALID_PARAMETER
;
5014 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5015 #if defined(HAVE_LONGLONG)
5016 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5017 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5018 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5019 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5020 #else /* HAVE_LONGLONG */
5021 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5022 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5023 #endif /* HAVE_LONGLONG */
5025 status
= query_lock(fsp
,
5032 if (ERROR_WAS_LOCK_DENIED(status
)) {
5033 /* Here we need to report who has it locked... */
5034 data_size
= POSIX_LOCK_DATA_SIZE
;
5036 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5037 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5038 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5039 #if defined(HAVE_LONGLONG)
5040 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5041 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5042 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5043 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5044 #else /* HAVE_LONGLONG */
5045 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5046 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5047 #endif /* HAVE_LONGLONG */
5049 } else if (NT_STATUS_IS_OK(status
)) {
5050 /* For success we just return a copy of what we sent
5051 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5052 data_size
= POSIX_LOCK_DATA_SIZE
;
5053 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5054 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5062 return NT_STATUS_INVALID_LEVEL
;
5065 *pdata_size
= data_size
;
5066 return NT_STATUS_OK
;
5069 /****************************************************************************
5070 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5071 file name or file id).
5072 ****************************************************************************/
5074 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5075 struct smb_request
*req
,
5076 unsigned int tran_call
,
5077 char **pparams
, int total_params
,
5078 char **ppdata
, int total_data
,
5079 unsigned int max_data_bytes
)
5081 char *params
= *pparams
;
5082 char *pdata
= *ppdata
;
5084 unsigned int data_size
= 0;
5085 unsigned int param_size
= 2;
5086 struct smb_filename
*smb_fname
= NULL
;
5087 bool delete_pending
= False
;
5088 struct timespec write_time_ts
;
5089 files_struct
*fsp
= NULL
;
5090 struct file_id fileid
;
5091 struct ea_list
*ea_list
= NULL
;
5092 int lock_data_count
= 0;
5093 char *lock_data
= NULL
;
5094 NTSTATUS status
= NT_STATUS_OK
;
5097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5101 ZERO_STRUCT(write_time_ts
);
5103 if (tran_call
== TRANSACT2_QFILEINFO
) {
5104 if (total_params
< 4) {
5105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5110 call_trans2qpipeinfo(conn
, req
, tran_call
,
5111 pparams
, total_params
,
5117 fsp
= file_fsp(req
, SVAL(params
,0));
5118 info_level
= SVAL(params
,2);
5120 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5122 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5123 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5127 /* Initial check for valid fsp ptr. */
5128 if (!check_fsp_open(conn
, req
, fsp
)) {
5132 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5134 if (!NT_STATUS_IS_OK(status
)) {
5135 reply_nterror(req
, status
);
5139 if(fsp
->fake_file_handle
) {
5141 * This is actually for the QUOTA_FAKE_FILE --metze
5144 /* We know this name is ok, it's already passed the checks. */
5146 } else if(fsp
->fh
->fd
== -1) {
5148 * This is actually a QFILEINFO on a directory
5149 * handle (returned from an NT SMB). NT5.0 seems
5150 * to do this call. JRA.
5153 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5154 /* Always do lstat for UNIX calls. */
5155 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5156 DEBUG(3,("call_trans2qfilepathinfo: "
5157 "SMB_VFS_LSTAT of %s failed "
5159 smb_fname_str_dbg(smb_fname
),
5162 map_nt_error_from_unix(errno
));
5165 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5166 DEBUG(3,("call_trans2qfilepathinfo: "
5167 "SMB_VFS_STAT of %s failed (%s)\n",
5168 smb_fname_str_dbg(smb_fname
),
5171 map_nt_error_from_unix(errno
));
5175 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5176 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5179 * Original code - this is an open file.
5181 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5182 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5183 fsp
->fnum
, strerror(errno
)));
5185 map_nt_error_from_unix(errno
));
5188 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5189 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5195 uint32_t ucf_flags
= 0;
5198 if (total_params
< 7) {
5199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5203 info_level
= SVAL(params
,0);
5205 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5207 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5208 if (!lp_unix_extensions()) {
5209 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5212 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5213 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5214 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5215 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5219 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5221 STR_TERMINATE
, &status
);
5222 if (!NT_STATUS_IS_OK(status
)) {
5223 reply_nterror(req
, status
);
5227 status
= filename_convert(req
,
5229 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5234 if (!NT_STATUS_IS_OK(status
)) {
5235 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5236 reply_botherror(req
,
5237 NT_STATUS_PATH_NOT_COVERED
,
5238 ERRSRV
, ERRbadpath
);
5241 reply_nterror(req
, status
);
5245 /* If this is a stream, check if there is a delete_pending. */
5246 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5247 && is_ntfs_stream_smb_fname(smb_fname
)) {
5248 struct smb_filename
*smb_fname_base
= NULL
;
5250 /* Create an smb_filename with stream_name == NULL. */
5252 create_synthetic_smb_fname(talloc_tos(),
5253 smb_fname
->base_name
,
5256 if (!NT_STATUS_IS_OK(status
)) {
5257 reply_nterror(req
, status
);
5261 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5262 /* Always do lstat for UNIX calls. */
5263 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5264 DEBUG(3,("call_trans2qfilepathinfo: "
5265 "SMB_VFS_LSTAT of %s failed "
5267 smb_fname_str_dbg(smb_fname_base
),
5269 TALLOC_FREE(smb_fname_base
);
5271 map_nt_error_from_unix(errno
));
5275 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5276 DEBUG(3,("call_trans2qfilepathinfo: "
5277 "fileinfo of %s failed "
5279 smb_fname_str_dbg(smb_fname_base
),
5281 TALLOC_FREE(smb_fname_base
);
5283 map_nt_error_from_unix(errno
));
5288 status
= file_name_hash(conn
,
5289 smb_fname_str_dbg(smb_fname_base
),
5291 if (!NT_STATUS_IS_OK(status
)) {
5292 TALLOC_FREE(smb_fname_base
);
5293 reply_nterror(req
, status
);
5297 fileid
= vfs_file_id_from_sbuf(conn
,
5298 &smb_fname_base
->st
);
5299 TALLOC_FREE(smb_fname_base
);
5300 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5301 if (delete_pending
) {
5302 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5307 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5308 /* Always do lstat for UNIX calls. */
5309 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5310 DEBUG(3,("call_trans2qfilepathinfo: "
5311 "SMB_VFS_LSTAT of %s failed (%s)\n",
5312 smb_fname_str_dbg(smb_fname
),
5315 map_nt_error_from_unix(errno
));
5320 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5321 DEBUG(3,("call_trans2qfilepathinfo: "
5322 "SMB_VFS_STAT of %s failed (%s)\n",
5323 smb_fname_str_dbg(smb_fname
),
5326 map_nt_error_from_unix(errno
));
5331 status
= file_name_hash(conn
,
5332 smb_fname_str_dbg(smb_fname
),
5334 if (!NT_STATUS_IS_OK(status
)) {
5335 reply_nterror(req
, status
);
5339 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5340 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5341 if (delete_pending
) {
5342 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5347 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5348 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5349 fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
5351 /* Pull out any data sent here before we realloc. */
5352 switch (info_level
) {
5353 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5355 /* Pull any EA list from the data portion. */
5358 if (total_data
< 4) {
5360 req
, NT_STATUS_INVALID_PARAMETER
);
5363 ea_size
= IVAL(pdata
,0);
5365 if (total_data
> 0 && ea_size
!= total_data
) {
5366 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5367 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5369 req
, NT_STATUS_INVALID_PARAMETER
);
5373 if (!lp_ea_support(SNUM(conn
))) {
5374 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5378 /* Pull out the list of names. */
5379 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5382 req
, NT_STATUS_INVALID_PARAMETER
);
5388 case SMB_QUERY_POSIX_LOCK
:
5390 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5391 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5395 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5397 req
, NT_STATUS_INVALID_PARAMETER
);
5401 /* Copy the lock range data. */
5402 lock_data
= (char *)TALLOC_MEMDUP(
5403 req
, pdata
, total_data
);
5405 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5408 lock_data_count
= total_data
;
5414 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5415 if (*pparams
== NULL
) {
5416 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5423 * draft-leach-cifs-v1-spec-02.txt
5424 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5427 * The requested information is placed in the Data portion of the
5428 * transaction response. For the information levels greater than 0x100,
5429 * the transaction response has 1 parameter word which should be
5430 * ignored by the client.
5432 * However Windows only follows this rule for the IS_NAME_VALID call.
5434 switch (info_level
) {
5435 case SMB_INFO_IS_NAME_VALID
:
5440 if ((info_level
& 0xFF00) == 0xFF00) {
5442 * We use levels that start with 0xFF00
5443 * internally to represent SMB2 specific levels
5445 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5449 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5451 delete_pending
, write_time_ts
,
5453 lock_data_count
, lock_data
,
5454 req
->flags2
, max_data_bytes
,
5455 ppdata
, &data_size
);
5456 if (!NT_STATUS_IS_OK(status
)) {
5457 reply_nterror(req
, status
);
5461 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5467 /****************************************************************************
5468 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5470 ****************************************************************************/
5472 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5473 connection_struct
*conn
,
5474 struct smb_request
*req
,
5475 bool overwrite_if_exists
,
5476 const struct smb_filename
*smb_fname_old
,
5477 struct smb_filename
*smb_fname_new
)
5479 NTSTATUS status
= NT_STATUS_OK
;
5481 /* source must already exist. */
5482 if (!VALID_STAT(smb_fname_old
->st
)) {
5483 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5486 if (VALID_STAT(smb_fname_new
->st
)) {
5487 if (overwrite_if_exists
) {
5488 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5489 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5491 status
= unlink_internals(conn
,
5493 FILE_ATTRIBUTE_NORMAL
,
5496 if (!NT_STATUS_IS_OK(status
)) {
5500 /* Disallow if newname already exists. */
5501 return NT_STATUS_OBJECT_NAME_COLLISION
;
5505 /* No links from a directory. */
5506 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5507 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5510 /* Setting a hardlink to/from a stream isn't currently supported. */
5511 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5512 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5513 return NT_STATUS_INVALID_PARAMETER
;
5516 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5517 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5519 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5520 smb_fname_new
->base_name
) != 0) {
5521 status
= map_nt_error_from_unix(errno
);
5522 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5523 nt_errstr(status
), smb_fname_old
->base_name
,
5524 smb_fname_new
->base_name
));
5529 /****************************************************************************
5530 Deal with setting the time from any of the setfilepathinfo functions.
5531 ****************************************************************************/
5533 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5535 const struct smb_filename
*smb_fname
,
5536 struct smb_file_time
*ft
,
5537 bool setting_write_time
)
5539 struct smb_filename smb_fname_base
;
5541 FILE_NOTIFY_CHANGE_LAST_ACCESS
5542 |FILE_NOTIFY_CHANGE_LAST_WRITE
5543 |FILE_NOTIFY_CHANGE_CREATION
;
5545 if (!VALID_STAT(smb_fname
->st
)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5549 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
5550 return NT_STATUS_ACCESS_DENIED
;
5553 /* get some defaults (no modifications) if any info is zero or -1. */
5554 if (null_timespec(ft
->create_time
)) {
5555 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5558 if (null_timespec(ft
->atime
)) {
5559 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5562 if (null_timespec(ft
->mtime
)) {
5563 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5566 if (!setting_write_time
) {
5567 /* ft->mtime comes from change time, not write time. */
5568 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5571 /* Ensure the resolution is the correct for
5572 * what we can store on this filesystem. */
5574 round_timespec(conn
->ts_res
, &ft
->create_time
);
5575 round_timespec(conn
->ts_res
, &ft
->ctime
);
5576 round_timespec(conn
->ts_res
, &ft
->atime
);
5577 round_timespec(conn
->ts_res
, &ft
->mtime
);
5579 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5580 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5581 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5582 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5583 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5584 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5585 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5586 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5588 if (setting_write_time
) {
5590 * This was a Windows setfileinfo on an open file.
5591 * NT does this a lot. We also need to
5592 * set the time here, as it can be read by
5593 * FindFirst/FindNext and with the patch for bug #2045
5594 * in smbd/fileio.c it ensures that this timestamp is
5595 * kept sticky even after a write. We save the request
5596 * away and will set it on file close and after a write. JRA.
5599 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5600 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5603 if (fsp
->base_fsp
) {
5604 set_sticky_write_time_fsp(fsp
->base_fsp
,
5607 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5610 set_sticky_write_time_path(
5611 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5616 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5618 /* Always call ntimes on the base, even if a stream was passed in. */
5619 smb_fname_base
= *smb_fname
;
5620 smb_fname_base
.stream_name
= NULL
;
5622 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5623 return map_nt_error_from_unix(errno
);
5626 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5627 smb_fname
->base_name
);
5628 return NT_STATUS_OK
;
5631 /****************************************************************************
5632 Deal with setting the dosmode from any of the setfilepathinfo functions.
5633 ****************************************************************************/
5635 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5636 const struct smb_filename
*smb_fname
,
5639 struct smb_filename
*smb_fname_base
= NULL
;
5642 if (!VALID_STAT(smb_fname
->st
)) {
5643 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5646 /* Always operate on the base_name, even if a stream was passed in. */
5647 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5648 NULL
, &smb_fname
->st
,
5650 if (!NT_STATUS_IS_OK(status
)) {
5655 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5656 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5658 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5662 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5664 /* check the mode isn't different, before changing it */
5665 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5666 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5667 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5668 (unsigned int)dosmode
));
5670 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5672 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5674 smb_fname_str_dbg(smb_fname_base
),
5676 status
= map_nt_error_from_unix(errno
);
5680 status
= NT_STATUS_OK
;
5682 TALLOC_FREE(smb_fname_base
);
5686 /****************************************************************************
5687 Deal with setting the size from any of the setfilepathinfo functions.
5688 ****************************************************************************/
5690 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5691 struct smb_request
*req
,
5693 const struct smb_filename
*smb_fname
,
5694 const SMB_STRUCT_STAT
*psbuf
,
5696 bool fail_after_createfile
)
5698 NTSTATUS status
= NT_STATUS_OK
;
5699 struct smb_filename
*smb_fname_tmp
= NULL
;
5700 files_struct
*new_fsp
= NULL
;
5702 if (!VALID_STAT(*psbuf
)) {
5703 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5706 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5707 return NT_STATUS_ACCESS_DENIED
;
5710 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5712 if (size
== get_file_size_stat(psbuf
)) {
5713 return NT_STATUS_OK
;
5716 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5717 smb_fname_str_dbg(smb_fname
), (double)size
));
5719 if (fsp
&& fsp
->fh
->fd
!= -1) {
5720 /* Handle based call. */
5721 if (vfs_set_filelen(fsp
, size
) == -1) {
5722 return map_nt_error_from_unix(errno
);
5724 trigger_write_time_update_immediate(fsp
);
5725 return NT_STATUS_OK
;
5728 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5729 if (!NT_STATUS_IS_OK(status
)) {
5733 smb_fname_tmp
->st
= *psbuf
;
5735 status
= SMB_VFS_CREATE_FILE(
5738 0, /* root_dir_fid */
5739 smb_fname_tmp
, /* fname */
5740 FILE_WRITE_DATA
, /* access_mask */
5741 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5743 FILE_OPEN
, /* create_disposition*/
5744 0, /* create_options */
5745 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5746 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5747 0, /* allocation_size */
5748 0, /* private_flags */
5751 &new_fsp
, /* result */
5754 TALLOC_FREE(smb_fname_tmp
);
5756 if (!NT_STATUS_IS_OK(status
)) {
5757 /* NB. We check for open_was_deferred in the caller. */
5761 /* See RAW-SFILEINFO-END-OF-FILE */
5762 if (fail_after_createfile
) {
5763 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5764 return NT_STATUS_INVALID_LEVEL
;
5767 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5768 status
= map_nt_error_from_unix(errno
);
5769 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5773 trigger_write_time_update_immediate(new_fsp
);
5774 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5775 return NT_STATUS_OK
;
5778 /****************************************************************************
5779 Deal with SMB_INFO_SET_EA.
5780 ****************************************************************************/
5782 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5786 const struct smb_filename
*smb_fname
)
5788 struct ea_list
*ea_list
= NULL
;
5789 TALLOC_CTX
*ctx
= NULL
;
5790 NTSTATUS status
= NT_STATUS_OK
;
5792 if (total_data
< 10) {
5794 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5795 length. They seem to have no effect. Bug #3212. JRA */
5797 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5798 /* We're done. We only get EA info in this call. */
5799 return NT_STATUS_OK
;
5802 return NT_STATUS_INVALID_PARAMETER
;
5805 if (IVAL(pdata
,0) > total_data
) {
5806 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5807 IVAL(pdata
,0), (unsigned int)total_data
));
5808 return NT_STATUS_INVALID_PARAMETER
;
5812 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5814 return NT_STATUS_INVALID_PARAMETER
;
5817 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5818 return NT_STATUS_ACCESS_DENIED
;
5821 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5826 /****************************************************************************
5827 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5828 ****************************************************************************/
5830 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5835 struct ea_list
*ea_list
= NULL
;
5839 return NT_STATUS_INVALID_HANDLE
;
5842 if (!lp_ea_support(SNUM(conn
))) {
5843 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5844 "EA's not supported.\n",
5845 (unsigned int)total_data
));
5846 return NT_STATUS_EAS_NOT_SUPPORTED
;
5849 if (total_data
< 10) {
5850 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5852 (unsigned int)total_data
));
5853 return NT_STATUS_INVALID_PARAMETER
;
5856 ea_list
= read_nttrans_ea_list(talloc_tos(),
5861 return NT_STATUS_INVALID_PARAMETER
;
5864 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_EA
)) {
5865 return NT_STATUS_ACCESS_DENIED
;
5868 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5870 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5871 smb_fname_str_dbg(fsp
->fsp_name
),
5872 nt_errstr(status
) ));
5878 /****************************************************************************
5879 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5880 ****************************************************************************/
5882 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5886 struct smb_filename
*smb_fname
)
5888 NTSTATUS status
= NT_STATUS_OK
;
5889 bool delete_on_close
;
5892 if (total_data
< 1) {
5893 return NT_STATUS_INVALID_PARAMETER
;
5897 return NT_STATUS_INVALID_HANDLE
;
5900 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5901 dosmode
= dos_mode(conn
, smb_fname
);
5903 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5904 "delete_on_close = %u\n",
5905 smb_fname_str_dbg(smb_fname
),
5906 (unsigned int)dosmode
,
5907 (unsigned int)delete_on_close
));
5909 if (delete_on_close
) {
5910 status
= can_set_delete_on_close(fsp
, dosmode
);
5911 if (!NT_STATUS_IS_OK(status
)) {
5916 /* The set is across all open files on this dev/inode pair. */
5917 if (!set_delete_on_close(fsp
, delete_on_close
,
5918 conn
->session_info
->security_token
,
5919 &conn
->session_info
->utok
)) {
5920 return NT_STATUS_ACCESS_DENIED
;
5922 return NT_STATUS_OK
;
5925 /****************************************************************************
5926 Deal with SMB_FILE_POSITION_INFORMATION.
5927 ****************************************************************************/
5929 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5934 uint64_t position_information
;
5936 if (total_data
< 8) {
5937 return NT_STATUS_INVALID_PARAMETER
;
5941 /* Ignore on pathname based set. */
5942 return NT_STATUS_OK
;
5945 position_information
= (uint64_t)IVAL(pdata
,0);
5946 #ifdef LARGE_SMB_OFF_T
5947 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5948 #else /* LARGE_SMB_OFF_T */
5949 if (IVAL(pdata
,4) != 0) {
5950 /* more than 32 bits? */
5951 return NT_STATUS_INVALID_PARAMETER
;
5953 #endif /* LARGE_SMB_OFF_T */
5955 DEBUG(10,("smb_file_position_information: Set file position "
5956 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5957 (double)position_information
));
5958 fsp
->fh
->position_information
= position_information
;
5959 return NT_STATUS_OK
;
5962 /****************************************************************************
5963 Deal with SMB_FILE_MODE_INFORMATION.
5964 ****************************************************************************/
5966 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5972 if (total_data
< 4) {
5973 return NT_STATUS_INVALID_PARAMETER
;
5975 mode
= IVAL(pdata
,0);
5976 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5977 return NT_STATUS_INVALID_PARAMETER
;
5979 return NT_STATUS_OK
;
5982 /****************************************************************************
5983 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5984 ****************************************************************************/
5986 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5987 struct smb_request
*req
,
5990 const struct smb_filename
*smb_fname
)
5992 char *link_target
= NULL
;
5993 const char *newname
= smb_fname
->base_name
;
5994 TALLOC_CTX
*ctx
= talloc_tos();
5996 /* Set a symbolic link. */
5997 /* Don't allow this if follow links is false. */
5999 if (total_data
== 0) {
6000 return NT_STATUS_INVALID_PARAMETER
;
6003 if (!lp_symlinks(SNUM(conn
))) {
6004 return NT_STATUS_ACCESS_DENIED
;
6007 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6008 total_data
, STR_TERMINATE
);
6011 return NT_STATUS_INVALID_PARAMETER
;
6014 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6015 newname
, link_target
));
6017 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6018 return map_nt_error_from_unix(errno
);
6021 return NT_STATUS_OK
;
6024 /****************************************************************************
6025 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6026 ****************************************************************************/
6028 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6029 struct smb_request
*req
,
6030 const char *pdata
, int total_data
,
6031 struct smb_filename
*smb_fname_new
)
6033 char *oldname
= NULL
;
6034 struct smb_filename
*smb_fname_old
= NULL
;
6035 TALLOC_CTX
*ctx
= talloc_tos();
6036 NTSTATUS status
= NT_STATUS_OK
;
6038 /* Set a hard link. */
6039 if (total_data
== 0) {
6040 return NT_STATUS_INVALID_PARAMETER
;
6043 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6044 total_data
, STR_TERMINATE
, &status
);
6045 if (!NT_STATUS_IS_OK(status
)) {
6049 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6050 smb_fname_str_dbg(smb_fname_new
), oldname
));
6052 status
= filename_convert(ctx
,
6054 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6059 if (!NT_STATUS_IS_OK(status
)) {
6063 return hardlink_internals(ctx
, conn
, req
, false,
6064 smb_fname_old
, smb_fname_new
);
6067 /****************************************************************************
6068 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6069 ****************************************************************************/
6071 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6072 struct smb_request
*req
,
6076 struct smb_filename
*smb_fname_src
)
6080 char *newname
= NULL
;
6081 struct smb_filename
*smb_fname_dst
= NULL
;
6082 NTSTATUS status
= NT_STATUS_OK
;
6083 TALLOC_CTX
*ctx
= talloc_tos();
6086 return NT_STATUS_INVALID_HANDLE
;
6089 if (total_data
< 20) {
6090 return NT_STATUS_INVALID_PARAMETER
;
6093 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6094 len
= IVAL(pdata
,16);
6096 if (len
> (total_data
- 20) || (len
== 0)) {
6097 return NT_STATUS_INVALID_PARAMETER
;
6100 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6101 &pdata
[20], len
, STR_TERMINATE
,
6103 if (!NT_STATUS_IS_OK(status
)) {
6107 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6110 status
= filename_convert(ctx
,
6112 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6117 if (!NT_STATUS_IS_OK(status
)) {
6121 if (fsp
->base_fsp
) {
6122 /* newname must be a stream name. */
6123 if (newname
[0] != ':') {
6124 return NT_STATUS_NOT_SUPPORTED
;
6127 /* Create an smb_fname to call rename_internals_fsp() with. */
6128 status
= create_synthetic_smb_fname(talloc_tos(),
6129 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6131 if (!NT_STATUS_IS_OK(status
)) {
6136 * Set the original last component, since
6137 * rename_internals_fsp() requires it.
6139 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6141 if (smb_fname_dst
->original_lcomp
== NULL
) {
6142 status
= NT_STATUS_NO_MEMORY
;
6148 DEBUG(10,("smb2_file_rename_information: "
6149 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6150 fsp
->fnum
, fsp_str_dbg(fsp
),
6151 smb_fname_str_dbg(smb_fname_dst
)));
6152 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6153 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6157 TALLOC_FREE(smb_fname_dst
);
6161 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6162 struct smb_request
*req
,
6166 struct smb_filename
*smb_fname_src
)
6170 char *newname
= NULL
;
6171 struct smb_filename
*smb_fname_dst
= NULL
;
6172 NTSTATUS status
= NT_STATUS_OK
;
6173 TALLOC_CTX
*ctx
= talloc_tos();
6176 return NT_STATUS_INVALID_HANDLE
;
6179 if (total_data
< 20) {
6180 return NT_STATUS_INVALID_PARAMETER
;
6183 overwrite
= (CVAL(pdata
,0) ? true : false);
6184 len
= IVAL(pdata
,16);
6186 if (len
> (total_data
- 20) || (len
== 0)) {
6187 return NT_STATUS_INVALID_PARAMETER
;
6190 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6191 &pdata
[20], len
, STR_TERMINATE
,
6193 if (!NT_STATUS_IS_OK(status
)) {
6197 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6200 status
= filename_convert(ctx
,
6202 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6207 if (!NT_STATUS_IS_OK(status
)) {
6211 if (fsp
->base_fsp
) {
6212 /* No stream names. */
6213 return NT_STATUS_NOT_SUPPORTED
;
6216 DEBUG(10,("smb_file_link_information: "
6217 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6218 fsp
->fnum
, fsp_str_dbg(fsp
),
6219 smb_fname_str_dbg(smb_fname_dst
)));
6220 status
= hardlink_internals(ctx
,
6227 TALLOC_FREE(smb_fname_dst
);
6231 /****************************************************************************
6232 Deal with SMB_FILE_RENAME_INFORMATION.
6233 ****************************************************************************/
6235 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6236 struct smb_request
*req
,
6240 struct smb_filename
*smb_fname_src
)
6245 char *newname
= NULL
;
6246 struct smb_filename
*smb_fname_dst
= NULL
;
6247 bool dest_has_wcard
= False
;
6248 NTSTATUS status
= NT_STATUS_OK
;
6250 TALLOC_CTX
*ctx
= talloc_tos();
6252 if (total_data
< 13) {
6253 return NT_STATUS_INVALID_PARAMETER
;
6256 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6257 root_fid
= IVAL(pdata
,4);
6258 len
= IVAL(pdata
,8);
6260 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6261 return NT_STATUS_INVALID_PARAMETER
;
6264 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6267 if (!NT_STATUS_IS_OK(status
)) {
6271 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6274 status
= resolve_dfspath_wcard(ctx
, conn
,
6275 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6280 if (!NT_STATUS_IS_OK(status
)) {
6284 /* Check the new name has no '/' characters. */
6285 if (strchr_m(newname
, '/')) {
6286 return NT_STATUS_NOT_SUPPORTED
;
6289 if (fsp
&& fsp
->base_fsp
) {
6290 /* newname must be a stream name. */
6291 if (newname
[0] != ':') {
6292 return NT_STATUS_NOT_SUPPORTED
;
6295 /* Create an smb_fname to call rename_internals_fsp() with. */
6296 status
= create_synthetic_smb_fname(talloc_tos(),
6297 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6299 if (!NT_STATUS_IS_OK(status
)) {
6304 * Set the original last component, since
6305 * rename_internals_fsp() requires it.
6307 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6309 if (smb_fname_dst
->original_lcomp
== NULL
) {
6310 status
= NT_STATUS_NO_MEMORY
;
6316 * Build up an smb_fname_dst based on the filename passed in.
6317 * We basically just strip off the last component, and put on
6318 * the newname instead.
6320 char *base_name
= NULL
;
6322 /* newname must *not* be a stream name. */
6323 if (newname
[0] == ':') {
6324 return NT_STATUS_NOT_SUPPORTED
;
6328 * Strip off the last component (filename) of the path passed
6331 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6333 return NT_STATUS_NO_MEMORY
;
6335 p
= strrchr_m(base_name
, '/');
6339 base_name
= talloc_strdup(ctx
, "");
6341 return NT_STATUS_NO_MEMORY
;
6344 /* Append the new name. */
6345 base_name
= talloc_asprintf_append(base_name
,
6349 return NT_STATUS_NO_MEMORY
;
6352 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6355 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6358 /* If an error we expect this to be
6359 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6361 if (!NT_STATUS_IS_OK(status
)) {
6362 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6366 /* Create an smb_fname to call rename_internals_fsp() */
6367 status
= create_synthetic_smb_fname(ctx
,
6371 if (!NT_STATUS_IS_OK(status
)) {
6378 DEBUG(10,("smb_file_rename_information: "
6379 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6380 fsp
->fnum
, fsp_str_dbg(fsp
),
6381 smb_fname_str_dbg(smb_fname_dst
)));
6382 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6385 DEBUG(10,("smb_file_rename_information: "
6386 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6387 smb_fname_str_dbg(smb_fname_src
),
6388 smb_fname_str_dbg(smb_fname_dst
)));
6389 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6390 smb_fname_dst
, 0, overwrite
, false,
6392 FILE_WRITE_ATTRIBUTES
);
6395 TALLOC_FREE(smb_fname_dst
);
6399 /****************************************************************************
6400 Deal with SMB_SET_POSIX_ACL.
6401 ****************************************************************************/
6403 #if defined(HAVE_POSIX_ACLS)
6404 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6408 const struct smb_filename
*smb_fname
)
6410 uint16 posix_acl_version
;
6411 uint16 num_file_acls
;
6412 uint16 num_def_acls
;
6413 bool valid_file_acls
= True
;
6414 bool valid_def_acls
= True
;
6416 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6417 return NT_STATUS_INVALID_PARAMETER
;
6419 posix_acl_version
= SVAL(pdata
,0);
6420 num_file_acls
= SVAL(pdata
,2);
6421 num_def_acls
= SVAL(pdata
,4);
6423 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6424 valid_file_acls
= False
;
6428 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6429 valid_def_acls
= False
;
6433 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6434 return NT_STATUS_INVALID_PARAMETER
;
6437 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6438 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6439 return NT_STATUS_INVALID_PARAMETER
;
6442 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6443 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6444 (unsigned int)num_file_acls
,
6445 (unsigned int)num_def_acls
));
6447 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6448 smb_fname
->base_name
, num_file_acls
,
6449 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6450 return map_nt_error_from_unix(errno
);
6453 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6454 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6455 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6456 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6457 return map_nt_error_from_unix(errno
);
6459 return NT_STATUS_OK
;
6463 /****************************************************************************
6464 Deal with SMB_SET_POSIX_LOCK.
6465 ****************************************************************************/
6467 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6468 struct smb_request
*req
,
6476 bool blocking_lock
= False
;
6477 enum brl_type lock_type
;
6479 NTSTATUS status
= NT_STATUS_OK
;
6481 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6482 return NT_STATUS_INVALID_HANDLE
;
6485 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6486 return NT_STATUS_INVALID_PARAMETER
;
6489 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6490 case POSIX_LOCK_TYPE_READ
:
6491 lock_type
= READ_LOCK
;
6493 case POSIX_LOCK_TYPE_WRITE
:
6494 /* Return the right POSIX-mappable error code for files opened read-only. */
6495 if (!fsp
->can_write
) {
6496 return NT_STATUS_INVALID_HANDLE
;
6498 lock_type
= WRITE_LOCK
;
6500 case POSIX_LOCK_TYPE_UNLOCK
:
6501 lock_type
= UNLOCK_LOCK
;
6504 return NT_STATUS_INVALID_PARAMETER
;
6507 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6508 blocking_lock
= False
;
6509 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6510 blocking_lock
= True
;
6512 return NT_STATUS_INVALID_PARAMETER
;
6515 if (!lp_blocking_locks(SNUM(conn
))) {
6516 blocking_lock
= False
;
6519 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6520 #if defined(HAVE_LONGLONG)
6521 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6522 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6523 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6524 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6525 #else /* HAVE_LONGLONG */
6526 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6527 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6528 #endif /* HAVE_LONGLONG */
6530 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6531 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6533 (unsigned int)lock_type
,
6534 (unsigned long long)smblctx
,
6538 if (lock_type
== UNLOCK_LOCK
) {
6539 status
= do_unlock(req
->sconn
->msg_ctx
,
6546 uint64_t block_smblctx
;
6548 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6560 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6562 * A blocking lock was requested. Package up
6563 * this smb into a queued request and push it
6564 * onto the blocking lock queue.
6566 if(push_blocking_lock_request(br_lck
,
6569 -1, /* infinite timeout. */
6577 TALLOC_FREE(br_lck
);
6581 TALLOC_FREE(br_lck
);
6587 /****************************************************************************
6588 Deal with SMB_SET_FILE_BASIC_INFO.
6589 ****************************************************************************/
6591 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6595 const struct smb_filename
*smb_fname
)
6597 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6598 struct smb_file_time ft
;
6600 NTSTATUS status
= NT_STATUS_OK
;
6604 if (total_data
< 36) {
6605 return NT_STATUS_INVALID_PARAMETER
;
6608 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6609 return NT_STATUS_ACCESS_DENIED
;
6612 /* Set the attributes */
6613 dosmode
= IVAL(pdata
,32);
6614 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6615 if (!NT_STATUS_IS_OK(status
)) {
6620 ft
.create_time
= interpret_long_date(pdata
);
6623 ft
.atime
= interpret_long_date(pdata
+8);
6626 ft
.mtime
= interpret_long_date(pdata
+16);
6629 ft
.ctime
= interpret_long_date(pdata
+24);
6631 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6632 smb_fname_str_dbg(smb_fname
)));
6634 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6638 /****************************************************************************
6639 Deal with SMB_INFO_STANDARD.
6640 ****************************************************************************/
6642 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6646 const struct smb_filename
*smb_fname
)
6648 struct smb_file_time ft
;
6652 if (total_data
< 12) {
6653 return NT_STATUS_INVALID_PARAMETER
;
6656 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6657 return NT_STATUS_ACCESS_DENIED
;
6661 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6663 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6665 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6667 DEBUG(10,("smb_set_info_standard: file %s\n",
6668 smb_fname_str_dbg(smb_fname
)));
6670 return smb_set_file_time(conn
,
6677 /****************************************************************************
6678 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6679 ****************************************************************************/
6681 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6682 struct smb_request
*req
,
6686 struct smb_filename
*smb_fname
)
6688 uint64_t allocation_size
= 0;
6689 NTSTATUS status
= NT_STATUS_OK
;
6690 files_struct
*new_fsp
= NULL
;
6692 if (!VALID_STAT(smb_fname
->st
)) {
6693 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6696 if (total_data
< 8) {
6697 return NT_STATUS_INVALID_PARAMETER
;
6700 allocation_size
= (uint64_t)IVAL(pdata
,0);
6701 #ifdef LARGE_SMB_OFF_T
6702 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6703 #else /* LARGE_SMB_OFF_T */
6704 if (IVAL(pdata
,4) != 0) {
6705 /* more than 32 bits? */
6706 return NT_STATUS_INVALID_PARAMETER
;
6708 #endif /* LARGE_SMB_OFF_T */
6710 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6711 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6712 (double)allocation_size
));
6714 if (allocation_size
) {
6715 allocation_size
= smb_roundup(conn
, allocation_size
);
6718 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6719 return NT_STATUS_ACCESS_DENIED
;
6722 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6723 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6724 (double)allocation_size
));
6726 if (fsp
&& fsp
->fh
->fd
!= -1) {
6727 /* Open file handle. */
6728 /* Only change if needed. */
6729 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6730 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6731 return map_nt_error_from_unix(errno
);
6734 /* But always update the time. */
6736 * This is equivalent to a write. Ensure it's seen immediately
6737 * if there are no pending writes.
6739 trigger_write_time_update_immediate(fsp
);
6740 return NT_STATUS_OK
;
6743 /* Pathname or stat or directory file. */
6744 status
= SMB_VFS_CREATE_FILE(
6747 0, /* root_dir_fid */
6748 smb_fname
, /* fname */
6749 FILE_WRITE_DATA
, /* access_mask */
6750 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6752 FILE_OPEN
, /* create_disposition*/
6753 0, /* create_options */
6754 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6755 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6756 0, /* allocation_size */
6757 0, /* private_flags */
6760 &new_fsp
, /* result */
6763 if (!NT_STATUS_IS_OK(status
)) {
6764 /* NB. We check for open_was_deferred in the caller. */
6768 /* Only change if needed. */
6769 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6770 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6771 status
= map_nt_error_from_unix(errno
);
6772 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6777 /* Changing the allocation size should set the last mod time. */
6779 * This is equivalent to a write. Ensure it's seen immediately
6780 * if there are no pending writes.
6782 trigger_write_time_update_immediate(new_fsp
);
6784 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6785 return NT_STATUS_OK
;
6788 /****************************************************************************
6789 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6790 ****************************************************************************/
6792 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6793 struct smb_request
*req
,
6797 const struct smb_filename
*smb_fname
,
6798 bool fail_after_createfile
)
6802 if (total_data
< 8) {
6803 return NT_STATUS_INVALID_PARAMETER
;
6806 size
= IVAL(pdata
,0);
6807 #ifdef LARGE_SMB_OFF_T
6808 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6809 #else /* LARGE_SMB_OFF_T */
6810 if (IVAL(pdata
,4) != 0) {
6811 /* more than 32 bits? */
6812 return NT_STATUS_INVALID_PARAMETER
;
6814 #endif /* LARGE_SMB_OFF_T */
6815 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6816 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6819 if (fsp
&& !(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6820 return NT_STATUS_ACCESS_DENIED
;
6823 return smb_set_file_size(conn
, req
,
6828 fail_after_createfile
);
6831 /****************************************************************************
6832 Allow a UNIX info mknod.
6833 ****************************************************************************/
6835 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6838 const struct smb_filename
*smb_fname
)
6840 uint32 file_type
= IVAL(pdata
,56);
6841 #if defined(HAVE_MAKEDEV)
6842 uint32 dev_major
= IVAL(pdata
,60);
6843 uint32 dev_minor
= IVAL(pdata
,68);
6845 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6846 uint32 raw_unixmode
= IVAL(pdata
,84);
6850 if (total_data
< 100) {
6851 return NT_STATUS_INVALID_PARAMETER
;
6854 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6855 PERM_NEW_FILE
, &unixmode
);
6856 if (!NT_STATUS_IS_OK(status
)) {
6860 #if defined(HAVE_MAKEDEV)
6861 dev
= makedev(dev_major
, dev_minor
);
6864 switch (file_type
) {
6865 #if defined(S_IFIFO)
6866 case UNIX_TYPE_FIFO
:
6867 unixmode
|= S_IFIFO
;
6870 #if defined(S_IFSOCK)
6871 case UNIX_TYPE_SOCKET
:
6872 unixmode
|= S_IFSOCK
;
6875 #if defined(S_IFCHR)
6876 case UNIX_TYPE_CHARDEV
:
6877 unixmode
|= S_IFCHR
;
6880 #if defined(S_IFBLK)
6881 case UNIX_TYPE_BLKDEV
:
6882 unixmode
|= S_IFBLK
;
6886 return NT_STATUS_INVALID_PARAMETER
;
6889 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6890 "%.0f mode 0%o for file %s\n", (double)dev
,
6891 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6893 /* Ok - do the mknod. */
6894 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6895 return map_nt_error_from_unix(errno
);
6898 /* If any of the other "set" calls fail we
6899 * don't want to end up with a half-constructed mknod.
6902 if (lp_inherit_perms(SNUM(conn
))) {
6904 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6906 return NT_STATUS_NO_MEMORY
;
6908 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6910 TALLOC_FREE(parent
);
6913 return NT_STATUS_OK
;
6916 /****************************************************************************
6917 Deal with SMB_SET_FILE_UNIX_BASIC.
6918 ****************************************************************************/
6920 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6921 struct smb_request
*req
,
6925 const struct smb_filename
*smb_fname
)
6927 struct smb_file_time ft
;
6928 uint32 raw_unixmode
;
6931 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6932 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6933 NTSTATUS status
= NT_STATUS_OK
;
6934 bool delete_on_fail
= False
;
6935 enum perm_type ptype
;
6936 files_struct
*all_fsps
= NULL
;
6937 bool modify_mtime
= true;
6939 struct smb_filename
*smb_fname_tmp
= NULL
;
6940 SMB_STRUCT_STAT sbuf
;
6944 if (total_data
< 100) {
6945 return NT_STATUS_INVALID_PARAMETER
;
6948 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6949 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6950 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6951 #ifdef LARGE_SMB_OFF_T
6952 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
6953 #else /* LARGE_SMB_OFF_T */
6954 if (IVAL(pdata
,4) != 0) {
6955 /* more than 32 bits? */
6956 return NT_STATUS_INVALID_PARAMETER
;
6958 #endif /* LARGE_SMB_OFF_T */
6961 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6962 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6963 set_owner
= (uid_t
)IVAL(pdata
,40);
6964 set_grp
= (gid_t
)IVAL(pdata
,48);
6965 raw_unixmode
= IVAL(pdata
,84);
6967 if (VALID_STAT(smb_fname
->st
)) {
6968 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6969 ptype
= PERM_EXISTING_DIR
;
6971 ptype
= PERM_EXISTING_FILE
;
6974 ptype
= PERM_NEW_FILE
;
6977 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6979 if (!NT_STATUS_IS_OK(status
)) {
6983 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6984 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6985 smb_fname_str_dbg(smb_fname
), (double)size
,
6986 (unsigned int)set_owner
, (unsigned int)set_grp
,
6987 (int)raw_unixmode
));
6989 sbuf
= smb_fname
->st
;
6991 if (!VALID_STAT(sbuf
)) {
6993 * The only valid use of this is to create character and block
6994 * devices, and named pipes. This is deprecated (IMHO) and
6995 * a new info level should be used for mknod. JRA.
6998 status
= smb_unix_mknod(conn
,
7002 if (!NT_STATUS_IS_OK(status
)) {
7006 status
= copy_smb_filename(talloc_tos(), smb_fname
,
7008 if (!NT_STATUS_IS_OK(status
)) {
7012 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7013 status
= map_nt_error_from_unix(errno
);
7014 TALLOC_FREE(smb_fname_tmp
);
7015 SMB_VFS_UNLINK(conn
, smb_fname
);
7019 sbuf
= smb_fname_tmp
->st
;
7020 smb_fname
= smb_fname_tmp
;
7022 /* Ensure we don't try and change anything else. */
7023 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7024 size
= get_file_size_stat(&sbuf
);
7025 ft
.atime
= sbuf
.st_ex_atime
;
7026 ft
.mtime
= sbuf
.st_ex_mtime
;
7028 * We continue here as we might want to change the
7031 delete_on_fail
= True
;
7035 /* Horrible backwards compatibility hack as an old server bug
7036 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7040 size
= get_file_size_stat(&sbuf
);
7045 * Deal with the UNIX specific mode set.
7048 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7049 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7050 "setting mode 0%o for file %s\n",
7051 (unsigned int)unixmode
,
7052 smb_fname_str_dbg(smb_fname
)));
7053 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7054 return map_nt_error_from_unix(errno
);
7059 * Deal with the UNIX specific uid set.
7062 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7063 (sbuf
.st_ex_uid
!= set_owner
)) {
7066 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7067 "changing owner %u for path %s\n",
7068 (unsigned int)set_owner
,
7069 smb_fname_str_dbg(smb_fname
)));
7071 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7072 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7073 set_owner
, (gid_t
)-1);
7075 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7076 set_owner
, (gid_t
)-1);
7080 status
= map_nt_error_from_unix(errno
);
7081 if (delete_on_fail
) {
7082 SMB_VFS_UNLINK(conn
, smb_fname
);
7089 * Deal with the UNIX specific gid set.
7092 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7093 (sbuf
.st_ex_gid
!= set_grp
)) {
7094 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7095 "changing group %u for file %s\n",
7096 (unsigned int)set_owner
,
7097 smb_fname_str_dbg(smb_fname
)));
7098 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7100 status
= map_nt_error_from_unix(errno
);
7101 if (delete_on_fail
) {
7102 SMB_VFS_UNLINK(conn
, smb_fname
);
7108 /* Deal with any size changes. */
7110 status
= smb_set_file_size(conn
, req
,
7116 if (!NT_STATUS_IS_OK(status
)) {
7120 /* Deal with any time changes. */
7121 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7122 /* No change, don't cancel anything. */
7126 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7127 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7128 all_fsps
= file_find_di_next(all_fsps
)) {
7130 * We're setting the time explicitly for UNIX.
7131 * Cancel any pending changes over all handles.
7133 all_fsps
->update_write_time_on_close
= false;
7134 TALLOC_FREE(all_fsps
->update_write_time_event
);
7138 * Override the "setting_write_time"
7139 * parameter here as it almost does what
7140 * we need. Just remember if we modified
7141 * mtime and send the notify ourselves.
7143 if (null_timespec(ft
.mtime
)) {
7144 modify_mtime
= false;
7147 status
= smb_set_file_time(conn
,
7153 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7154 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7159 /****************************************************************************
7160 Deal with SMB_SET_FILE_UNIX_INFO2.
7161 ****************************************************************************/
7163 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7164 struct smb_request
*req
,
7168 const struct smb_filename
*smb_fname
)
7174 if (total_data
< 116) {
7175 return NT_STATUS_INVALID_PARAMETER
;
7178 /* Start by setting all the fields that are common between UNIX_BASIC
7181 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7183 if (!NT_STATUS_IS_OK(status
)) {
7187 smb_fflags
= IVAL(pdata
, 108);
7188 smb_fmask
= IVAL(pdata
, 112);
7190 /* NB: We should only attempt to alter the file flags if the client
7191 * sends a non-zero mask.
7193 if (smb_fmask
!= 0) {
7194 int stat_fflags
= 0;
7196 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7197 smb_fmask
, &stat_fflags
)) {
7198 /* Client asked to alter a flag we don't understand. */
7199 return NT_STATUS_INVALID_PARAMETER
;
7202 if (fsp
&& fsp
->fh
->fd
!= -1) {
7203 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7204 return NT_STATUS_NOT_SUPPORTED
;
7206 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7207 stat_fflags
) != 0) {
7208 return map_nt_error_from_unix(errno
);
7213 /* XXX: need to add support for changing the create_time here. You
7214 * can do this for paths on Darwin with setattrlist(2). The right way
7215 * to hook this up is probably by extending the VFS utimes interface.
7218 return NT_STATUS_OK
;
7221 /****************************************************************************
7222 Create a directory with POSIX semantics.
7223 ****************************************************************************/
7225 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7226 struct smb_request
*req
,
7229 struct smb_filename
*smb_fname
,
7230 int *pdata_return_size
)
7232 NTSTATUS status
= NT_STATUS_OK
;
7233 uint32 raw_unixmode
= 0;
7234 uint32 mod_unixmode
= 0;
7235 mode_t unixmode
= (mode_t
)0;
7236 files_struct
*fsp
= NULL
;
7237 uint16 info_level_return
= 0;
7239 char *pdata
= *ppdata
;
7241 if (total_data
< 18) {
7242 return NT_STATUS_INVALID_PARAMETER
;
7245 raw_unixmode
= IVAL(pdata
,8);
7246 /* Next 4 bytes are not yet defined. */
7248 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7249 PERM_NEW_DIR
, &unixmode
);
7250 if (!NT_STATUS_IS_OK(status
)) {
7254 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7256 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7257 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7259 status
= SMB_VFS_CREATE_FILE(
7262 0, /* root_dir_fid */
7263 smb_fname
, /* fname */
7264 FILE_READ_ATTRIBUTES
, /* access_mask */
7265 FILE_SHARE_NONE
, /* share_access */
7266 FILE_CREATE
, /* create_disposition*/
7267 FILE_DIRECTORY_FILE
, /* create_options */
7268 mod_unixmode
, /* file_attributes */
7269 0, /* oplock_request */
7270 0, /* allocation_size */
7271 0, /* private_flags */
7277 if (NT_STATUS_IS_OK(status
)) {
7278 close_file(req
, fsp
, NORMAL_CLOSE
);
7281 info_level_return
= SVAL(pdata
,16);
7283 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7284 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7285 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7286 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7288 *pdata_return_size
= 12;
7291 /* Realloc the data size */
7292 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7293 if (*ppdata
== NULL
) {
7294 *pdata_return_size
= 0;
7295 return NT_STATUS_NO_MEMORY
;
7299 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7300 SSVAL(pdata
,2,0); /* No fnum. */
7301 SIVAL(pdata
,4,info
); /* Was directory created. */
7303 switch (info_level_return
) {
7304 case SMB_QUERY_FILE_UNIX_BASIC
:
7305 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7306 SSVAL(pdata
,10,0); /* Padding. */
7307 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7310 case SMB_QUERY_FILE_UNIX_INFO2
:
7311 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7312 SSVAL(pdata
,10,0); /* Padding. */
7313 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7317 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7318 SSVAL(pdata
,10,0); /* Padding. */
7325 /****************************************************************************
7326 Open/Create a file with POSIX semantics.
7327 ****************************************************************************/
7329 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7330 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7332 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7333 struct smb_request
*req
,
7336 struct smb_filename
*smb_fname
,
7337 int *pdata_return_size
)
7339 bool extended_oplock_granted
= False
;
7340 char *pdata
= *ppdata
;
7342 uint32 wire_open_mode
= 0;
7343 uint32 raw_unixmode
= 0;
7344 uint32 mod_unixmode
= 0;
7345 uint32 create_disp
= 0;
7346 uint32 access_mask
= 0;
7347 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7348 NTSTATUS status
= NT_STATUS_OK
;
7349 mode_t unixmode
= (mode_t
)0;
7350 files_struct
*fsp
= NULL
;
7351 int oplock_request
= 0;
7353 uint16 info_level_return
= 0;
7355 if (total_data
< 18) {
7356 return NT_STATUS_INVALID_PARAMETER
;
7359 flags
= IVAL(pdata
,0);
7360 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7361 if (oplock_request
) {
7362 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7365 wire_open_mode
= IVAL(pdata
,4);
7367 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7368 return smb_posix_mkdir(conn
, req
,
7375 switch (wire_open_mode
& SMB_ACCMODE
) {
7377 access_mask
= SMB_O_RDONLY_MAPPING
;
7380 access_mask
= SMB_O_WRONLY_MAPPING
;
7383 access_mask
= (SMB_O_RDONLY_MAPPING
|
7384 SMB_O_WRONLY_MAPPING
);
7387 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7388 (unsigned int)wire_open_mode
));
7389 return NT_STATUS_INVALID_PARAMETER
;
7392 wire_open_mode
&= ~SMB_ACCMODE
;
7394 /* First take care of O_CREAT|O_EXCL interactions. */
7395 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7396 case (SMB_O_CREAT
| SMB_O_EXCL
):
7397 /* File exists fail. File not exist create. */
7398 create_disp
= FILE_CREATE
;
7401 /* File exists open. File not exist create. */
7402 create_disp
= FILE_OPEN_IF
;
7405 /* O_EXCL on its own without O_CREAT is undefined.
7406 We deliberately ignore it as some versions of
7407 Linux CIFSFS can send a bare O_EXCL on the
7408 wire which other filesystems in the kernel
7409 ignore. See bug 9519 for details. */
7414 /* File exists open. File not exist fail. */
7415 create_disp
= FILE_OPEN
;
7418 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7419 (unsigned int)wire_open_mode
));
7420 return NT_STATUS_INVALID_PARAMETER
;
7423 /* Next factor in the effects of O_TRUNC. */
7424 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7426 if (wire_open_mode
& SMB_O_TRUNC
) {
7427 switch (create_disp
) {
7429 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7430 /* Leave create_disp alone as
7431 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7433 /* File exists fail. File not exist create. */
7436 /* SMB_O_CREAT | SMB_O_TRUNC */
7437 /* File exists overwrite. File not exist create. */
7438 create_disp
= FILE_OVERWRITE_IF
;
7442 /* File exists overwrite. File not exist fail. */
7443 create_disp
= FILE_OVERWRITE
;
7446 /* Cannot get here. */
7447 smb_panic("smb_posix_open: logic error");
7448 return NT_STATUS_INVALID_PARAMETER
;
7452 raw_unixmode
= IVAL(pdata
,8);
7453 /* Next 4 bytes are not yet defined. */
7455 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7456 (VALID_STAT(smb_fname
->st
) ?
7457 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7460 if (!NT_STATUS_IS_OK(status
)) {
7464 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7466 if (wire_open_mode
& SMB_O_SYNC
) {
7467 create_options
|= FILE_WRITE_THROUGH
;
7469 if (wire_open_mode
& SMB_O_APPEND
) {
7470 access_mask
|= FILE_APPEND_DATA
;
7472 if (wire_open_mode
& SMB_O_DIRECT
) {
7473 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7476 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7477 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7478 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7479 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7481 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7482 create_options
|= FILE_DIRECTORY_FILE
;
7485 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7486 smb_fname_str_dbg(smb_fname
),
7487 (unsigned int)wire_open_mode
,
7488 (unsigned int)unixmode
));
7490 status
= SMB_VFS_CREATE_FILE(
7493 0, /* root_dir_fid */
7494 smb_fname
, /* fname */
7495 access_mask
, /* access_mask */
7496 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7498 create_disp
, /* create_disposition*/
7499 create_options
, /* create_options */
7500 mod_unixmode
, /* file_attributes */
7501 oplock_request
, /* oplock_request */
7502 0, /* allocation_size */
7503 0, /* private_flags */
7509 if (!NT_STATUS_IS_OK(status
)) {
7513 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7514 extended_oplock_granted
= True
;
7517 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7518 extended_oplock_granted
= True
;
7521 info_level_return
= SVAL(pdata
,16);
7523 /* Allocate the correct return size. */
7525 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7526 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7527 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7528 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7530 *pdata_return_size
= 12;
7533 /* Realloc the data size */
7534 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7535 if (*ppdata
== NULL
) {
7536 close_file(req
, fsp
, ERROR_CLOSE
);
7537 *pdata_return_size
= 0;
7538 return NT_STATUS_NO_MEMORY
;
7542 if (extended_oplock_granted
) {
7543 if (flags
& REQUEST_BATCH_OPLOCK
) {
7544 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7546 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7548 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7549 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7551 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7554 SSVAL(pdata
,2,fsp
->fnum
);
7555 SIVAL(pdata
,4,info
); /* Was file created etc. */
7557 switch (info_level_return
) {
7558 case SMB_QUERY_FILE_UNIX_BASIC
:
7559 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7560 SSVAL(pdata
,10,0); /* padding. */
7561 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7564 case SMB_QUERY_FILE_UNIX_INFO2
:
7565 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7566 SSVAL(pdata
,10,0); /* padding. */
7567 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7571 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7572 SSVAL(pdata
,10,0); /* padding. */
7575 return NT_STATUS_OK
;
7578 /****************************************************************************
7579 Delete a file with POSIX semantics.
7580 ****************************************************************************/
7582 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7583 struct smb_request
*req
,
7586 struct smb_filename
*smb_fname
)
7588 NTSTATUS status
= NT_STATUS_OK
;
7589 files_struct
*fsp
= NULL
;
7593 int create_options
= 0;
7595 struct share_mode_lock
*lck
= NULL
;
7597 if (total_data
< 2) {
7598 return NT_STATUS_INVALID_PARAMETER
;
7601 flags
= SVAL(pdata
,0);
7603 if (!VALID_STAT(smb_fname
->st
)) {
7604 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7607 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7608 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7609 return NT_STATUS_NOT_A_DIRECTORY
;
7612 DEBUG(10,("smb_posix_unlink: %s %s\n",
7613 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7614 smb_fname_str_dbg(smb_fname
)));
7616 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7617 create_options
|= FILE_DIRECTORY_FILE
;
7620 status
= SMB_VFS_CREATE_FILE(
7623 0, /* root_dir_fid */
7624 smb_fname
, /* fname */
7625 DELETE_ACCESS
, /* access_mask */
7626 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7628 FILE_OPEN
, /* create_disposition*/
7629 create_options
, /* create_options */
7630 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7631 0, /* oplock_request */
7632 0, /* allocation_size */
7633 0, /* private_flags */
7639 if (!NT_STATUS_IS_OK(status
)) {
7644 * Don't lie to client. If we can't really delete due to
7645 * non-POSIX opens return SHARING_VIOLATION.
7648 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
7651 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7652 "lock for file %s\n", fsp_str_dbg(fsp
)));
7653 close_file(req
, fsp
, NORMAL_CLOSE
);
7654 return NT_STATUS_INVALID_PARAMETER
;
7658 * See if others still have the file open. If this is the case, then
7659 * don't delete. If all opens are POSIX delete we can set the delete
7660 * on close disposition.
7662 for (i
=0; i
<lck
->num_share_modes
; i
++) {
7663 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
7664 if (is_valid_share_mode_entry(e
)) {
7665 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7668 /* Fail with sharing violation. */
7670 close_file(req
, fsp
, NORMAL_CLOSE
);
7671 return NT_STATUS_SHARING_VIOLATION
;
7676 * Set the delete on close.
7678 status
= smb_set_file_disposition_info(conn
,
7686 if (!NT_STATUS_IS_OK(status
)) {
7687 close_file(req
, fsp
, NORMAL_CLOSE
);
7690 return close_file(req
, fsp
, NORMAL_CLOSE
);
7693 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7694 struct smb_request
*req
,
7695 TALLOC_CTX
*mem_ctx
,
7696 uint16_t info_level
,
7698 struct smb_filename
*smb_fname
,
7699 char **ppdata
, int total_data
,
7702 char *pdata
= *ppdata
;
7703 NTSTATUS status
= NT_STATUS_OK
;
7704 int data_return_size
= 0;
7708 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7709 return NT_STATUS_INVALID_LEVEL
;
7712 if (!CAN_WRITE(conn
)) {
7713 /* Allow POSIX opens. The open path will deny
7714 * any non-readonly opens. */
7715 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7716 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7720 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7721 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7722 fsp
? fsp
->fnum
: -1, info_level
, total_data
));
7724 switch (info_level
) {
7726 case SMB_INFO_STANDARD
:
7728 status
= smb_set_info_standard(conn
,
7736 case SMB_INFO_SET_EA
:
7738 status
= smb_info_set_ea(conn
,
7746 case SMB_SET_FILE_BASIC_INFO
:
7747 case SMB_FILE_BASIC_INFORMATION
:
7749 status
= smb_set_file_basic_info(conn
,
7757 case SMB_FILE_ALLOCATION_INFORMATION
:
7758 case SMB_SET_FILE_ALLOCATION_INFO
:
7760 status
= smb_set_file_allocation_info(conn
, req
,
7768 case SMB_FILE_END_OF_FILE_INFORMATION
:
7769 case SMB_SET_FILE_END_OF_FILE_INFO
:
7772 * XP/Win7 both fail after the createfile with
7773 * SMB_SET_FILE_END_OF_FILE_INFO but not
7774 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7775 * The level is known here, so pass it down
7779 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7781 status
= smb_set_file_end_of_file_info(conn
, req
,
7790 case SMB_FILE_DISPOSITION_INFORMATION
:
7791 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7794 /* JRA - We used to just ignore this on a path ?
7795 * Shouldn't this be invalid level on a pathname
7798 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7799 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7802 status
= smb_set_file_disposition_info(conn
,
7810 case SMB_FILE_POSITION_INFORMATION
:
7812 status
= smb_file_position_information(conn
,
7819 case SMB_FILE_FULL_EA_INFORMATION
:
7821 status
= smb_set_file_full_ea_info(conn
,
7828 /* From tridge Samba4 :
7829 * MODE_INFORMATION in setfileinfo (I have no
7830 * idea what "mode information" on a file is - it takes a value of 0,
7831 * 2, 4 or 6. What could it be?).
7834 case SMB_FILE_MODE_INFORMATION
:
7836 status
= smb_file_mode_information(conn
,
7843 * CIFS UNIX extensions.
7846 case SMB_SET_FILE_UNIX_BASIC
:
7848 status
= smb_set_file_unix_basic(conn
, req
,
7856 case SMB_SET_FILE_UNIX_INFO2
:
7858 status
= smb_set_file_unix_info2(conn
, req
,
7866 case SMB_SET_FILE_UNIX_LINK
:
7869 /* We must have a pathname for this. */
7870 return NT_STATUS_INVALID_LEVEL
;
7872 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7873 total_data
, smb_fname
);
7877 case SMB_SET_FILE_UNIX_HLINK
:
7880 /* We must have a pathname for this. */
7881 return NT_STATUS_INVALID_LEVEL
;
7883 status
= smb_set_file_unix_hlink(conn
, req
,
7889 case SMB_FILE_RENAME_INFORMATION
:
7891 status
= smb_file_rename_information(conn
, req
,
7897 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7899 /* SMB2 rename information. */
7900 status
= smb2_file_rename_information(conn
, req
,
7906 case SMB_FILE_LINK_INFORMATION
:
7908 status
= smb_file_link_information(conn
, req
,
7914 #if defined(HAVE_POSIX_ACLS)
7915 case SMB_SET_POSIX_ACL
:
7917 status
= smb_set_posix_acl(conn
,
7926 case SMB_SET_POSIX_LOCK
:
7929 return NT_STATUS_INVALID_LEVEL
;
7931 status
= smb_set_posix_lock(conn
, req
,
7932 pdata
, total_data
, fsp
);
7936 case SMB_POSIX_PATH_OPEN
:
7939 /* We must have a pathname for this. */
7940 return NT_STATUS_INVALID_LEVEL
;
7943 status
= smb_posix_open(conn
, req
,
7951 case SMB_POSIX_PATH_UNLINK
:
7954 /* We must have a pathname for this. */
7955 return NT_STATUS_INVALID_LEVEL
;
7958 status
= smb_posix_unlink(conn
, req
,
7966 return NT_STATUS_INVALID_LEVEL
;
7969 if (!NT_STATUS_IS_OK(status
)) {
7973 *ret_data_size
= data_return_size
;
7974 return NT_STATUS_OK
;
7977 /****************************************************************************
7978 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7979 ****************************************************************************/
7981 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7982 struct smb_request
*req
,
7983 unsigned int tran_call
,
7984 char **pparams
, int total_params
,
7985 char **ppdata
, int total_data
,
7986 unsigned int max_data_bytes
)
7988 char *params
= *pparams
;
7989 char *pdata
= *ppdata
;
7991 struct smb_filename
*smb_fname
= NULL
;
7992 files_struct
*fsp
= NULL
;
7993 NTSTATUS status
= NT_STATUS_OK
;
7994 int data_return_size
= 0;
7997 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8001 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8002 if (total_params
< 4) {
8003 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8007 fsp
= file_fsp(req
, SVAL(params
,0));
8008 /* Basic check for non-null fsp. */
8009 if (!check_fsp_open(conn
, req
, fsp
)) {
8012 info_level
= SVAL(params
,2);
8014 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
8016 if (!NT_STATUS_IS_OK(status
)) {
8017 reply_nterror(req
, status
);
8021 if(fsp
->fh
->fd
== -1) {
8023 * This is actually a SETFILEINFO on a directory
8024 * handle (returned from an NT SMB). NT5.0 seems
8025 * to do this call. JRA.
8027 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8028 /* Always do lstat for UNIX calls. */
8029 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8030 DEBUG(3,("call_trans2setfilepathinfo: "
8031 "SMB_VFS_LSTAT of %s failed "
8033 smb_fname_str_dbg(smb_fname
),
8035 reply_nterror(req
, map_nt_error_from_unix(errno
));
8039 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8040 DEBUG(3,("call_trans2setfilepathinfo: "
8041 "fileinfo of %s failed (%s)\n",
8042 smb_fname_str_dbg(smb_fname
),
8044 reply_nterror(req
, map_nt_error_from_unix(errno
));
8048 } else if (fsp
->print_file
) {
8050 * Doing a DELETE_ON_CLOSE should cancel a print job.
8052 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8053 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8055 DEBUG(3,("call_trans2setfilepathinfo: "
8056 "Cancelling print job (%s)\n",
8060 send_trans2_replies(conn
, req
, params
, 2,
8066 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8071 * Original code - this is an open file.
8073 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8074 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8075 "of fnum %d failed (%s)\n", fsp
->fnum
,
8077 reply_nterror(req
, map_nt_error_from_unix(errno
));
8083 uint32_t ucf_flags
= 0;
8086 if (total_params
< 7) {
8087 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8091 info_level
= SVAL(params
,0);
8092 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8093 total_params
- 6, STR_TERMINATE
,
8095 if (!NT_STATUS_IS_OK(status
)) {
8096 reply_nterror(req
, status
);
8100 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8101 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8102 info_level
== SMB_FILE_RENAME_INFORMATION
||
8103 info_level
== SMB_POSIX_PATH_UNLINK
) {
8104 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8107 status
= filename_convert(req
, conn
,
8108 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8113 if (!NT_STATUS_IS_OK(status
)) {
8114 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8115 reply_botherror(req
,
8116 NT_STATUS_PATH_NOT_COVERED
,
8117 ERRSRV
, ERRbadpath
);
8120 reply_nterror(req
, status
);
8124 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8126 * For CIFS UNIX extensions the target name may not exist.
8129 /* Always do lstat for UNIX calls. */
8130 SMB_VFS_LSTAT(conn
, smb_fname
);
8132 } else if (!VALID_STAT(smb_fname
->st
) &&
8133 SMB_VFS_STAT(conn
, smb_fname
)) {
8134 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8136 smb_fname_str_dbg(smb_fname
),
8138 reply_nterror(req
, map_nt_error_from_unix(errno
));
8143 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8144 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8145 fsp
? fsp
->fnum
: -1, info_level
,total_data
));
8147 /* Realloc the parameter size */
8148 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8149 if (*pparams
== NULL
) {
8150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8157 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8163 if (!NT_STATUS_IS_OK(status
)) {
8164 if (open_was_deferred(req
->mid
)) {
8165 /* We have re-scheduled this call. */
8168 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8169 /* We have re-scheduled this call. */
8172 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8173 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8174 ERRSRV
, ERRbadpath
);
8177 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8178 reply_openerror(req
, status
);
8182 reply_nterror(req
, status
);
8186 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8192 /****************************************************************************
8193 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8194 ****************************************************************************/
8196 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8197 char **pparams
, int total_params
,
8198 char **ppdata
, int total_data
,
8199 unsigned int max_data_bytes
)
8201 struct smb_filename
*smb_dname
= NULL
;
8202 char *params
= *pparams
;
8203 char *pdata
= *ppdata
;
8204 char *directory
= NULL
;
8205 NTSTATUS status
= NT_STATUS_OK
;
8206 struct ea_list
*ea_list
= NULL
;
8207 TALLOC_CTX
*ctx
= talloc_tos();
8209 if (!CAN_WRITE(conn
)) {
8210 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8214 if (total_params
< 5) {
8215 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8219 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8220 total_params
- 4, STR_TERMINATE
,
8222 if (!NT_STATUS_IS_OK(status
)) {
8223 reply_nterror(req
, status
);
8227 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8229 status
= filename_convert(ctx
,
8231 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8237 if (!NT_STATUS_IS_OK(status
)) {
8238 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8239 reply_botherror(req
,
8240 NT_STATUS_PATH_NOT_COVERED
,
8241 ERRSRV
, ERRbadpath
);
8244 reply_nterror(req
, status
);
8249 * OS/2 workplace shell seems to send SET_EA requests of "null"
8250 * length (4 bytes containing IVAL 4).
8251 * They seem to have no effect. Bug #3212. JRA.
8254 if (total_data
&& (total_data
!= 4)) {
8255 /* Any data in this call is an EA list. */
8256 if (total_data
< 10) {
8257 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8261 if (IVAL(pdata
,0) > total_data
) {
8262 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8263 IVAL(pdata
,0), (unsigned int)total_data
));
8264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8268 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8275 if (!lp_ea_support(SNUM(conn
))) {
8276 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8280 /* If total_data == 4 Windows doesn't care what values
8281 * are placed in that field, it just ignores them.
8282 * The System i QNTC IBM SMB client puts bad values here,
8283 * so ignore them. */
8285 status
= create_directory(conn
, req
, smb_dname
);
8287 if (!NT_STATUS_IS_OK(status
)) {
8288 reply_nterror(req
, status
);
8292 /* Try and set any given EA. */
8294 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8295 if (!NT_STATUS_IS_OK(status
)) {
8296 reply_nterror(req
, status
);
8301 /* Realloc the parameter and data sizes */
8302 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8303 if(*pparams
== NULL
) {
8304 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8311 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8314 TALLOC_FREE(smb_dname
);
8318 /****************************************************************************
8319 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8320 We don't actually do this - we just send a null response.
8321 ****************************************************************************/
8323 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8324 struct smb_request
*req
,
8325 char **pparams
, int total_params
,
8326 char **ppdata
, int total_data
,
8327 unsigned int max_data_bytes
)
8329 char *params
= *pparams
;
8332 if (total_params
< 6) {
8333 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8337 info_level
= SVAL(params
,4);
8338 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8340 switch (info_level
) {
8345 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8349 /* Realloc the parameter and data sizes */
8350 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8351 if (*pparams
== NULL
) {
8352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8357 SSVAL(params
,0,fnf_handle
);
8358 SSVAL(params
,2,0); /* No changes */
8359 SSVAL(params
,4,0); /* No EA errors */
8366 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8371 /****************************************************************************
8372 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8373 changes). Currently this does nothing.
8374 ****************************************************************************/
8376 static void call_trans2findnotifynext(connection_struct
*conn
,
8377 struct smb_request
*req
,
8378 char **pparams
, int total_params
,
8379 char **ppdata
, int total_data
,
8380 unsigned int max_data_bytes
)
8382 char *params
= *pparams
;
8384 DEBUG(3,("call_trans2findnotifynext\n"));
8386 /* Realloc the parameter and data sizes */
8387 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8388 if (*pparams
== NULL
) {
8389 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8394 SSVAL(params
,0,0); /* No changes */
8395 SSVAL(params
,2,0); /* No EA errors */
8397 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8402 /****************************************************************************
8403 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8404 ****************************************************************************/
8406 static void call_trans2getdfsreferral(connection_struct
*conn
,
8407 struct smb_request
*req
,
8408 char **pparams
, int total_params
,
8409 char **ppdata
, int total_data
,
8410 unsigned int max_data_bytes
)
8412 char *params
= *pparams
;
8413 char *pathname
= NULL
;
8415 int max_referral_level
;
8416 NTSTATUS status
= NT_STATUS_OK
;
8417 TALLOC_CTX
*ctx
= talloc_tos();
8419 DEBUG(10,("call_trans2getdfsreferral\n"));
8421 if (total_params
< 3) {
8422 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8426 max_referral_level
= SVAL(params
,0);
8428 if(!lp_host_msdfs()) {
8429 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8433 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8434 total_params
- 2, STR_TERMINATE
);
8436 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8439 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8440 ppdata
,&status
)) < 0) {
8441 reply_nterror(req
, status
);
8445 SSVAL(req
->inbuf
, smb_flg2
,
8446 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8447 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8452 #define LMCAT_SPL 0x53
8453 #define LMFUNC_GETJOBID 0x60
8455 /****************************************************************************
8456 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8457 ****************************************************************************/
8459 static void call_trans2ioctl(connection_struct
*conn
,
8460 struct smb_request
*req
,
8461 char **pparams
, int total_params
,
8462 char **ppdata
, int total_data
,
8463 unsigned int max_data_bytes
)
8465 char *pdata
= *ppdata
;
8466 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8468 /* check for an invalid fid before proceeding */
8471 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8475 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8476 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8477 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8478 if (*ppdata
== NULL
) {
8479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8484 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8485 CAN ACCEPT THIS IN UNICODE. JRA. */
8488 if (fsp
->print_file
) {
8489 SSVAL(pdata
, 0, fsp
->print_file
->rap_jobid
);
8493 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8494 global_myname(), 15,
8495 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8496 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8497 lp_servicename(SNUM(conn
)), 13,
8498 STR_ASCII
|STR_TERMINATE
); /* Service name */
8499 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8504 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8505 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8508 /****************************************************************************
8509 Reply to a SMBfindclose (stop trans2 directory search).
8510 ****************************************************************************/
8512 void reply_findclose(struct smb_request
*req
)
8515 struct smbd_server_connection
*sconn
= req
->sconn
;
8517 START_PROFILE(SMBfindclose
);
8520 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8521 END_PROFILE(SMBfindclose
);
8525 dptr_num
= SVALS(req
->vwv
+0, 0);
8527 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8529 dptr_close(sconn
, &dptr_num
);
8531 reply_outbuf(req
, 0, 0);
8533 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8535 END_PROFILE(SMBfindclose
);
8539 /****************************************************************************
8540 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8541 ****************************************************************************/
8543 void reply_findnclose(struct smb_request
*req
)
8547 START_PROFILE(SMBfindnclose
);
8550 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8551 END_PROFILE(SMBfindnclose
);
8555 dptr_num
= SVAL(req
->vwv
+0, 0);
8557 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8559 /* We never give out valid handles for a
8560 findnotifyfirst - so any dptr_num is ok here.
8563 reply_outbuf(req
, 0, 0);
8565 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8567 END_PROFILE(SMBfindnclose
);
8571 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8572 struct trans_state
*state
)
8574 if (get_Protocol() >= PROTOCOL_NT1
) {
8575 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8576 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
8579 if (conn
->encrypt_level
== Required
&& !req
->encrypted
) {
8580 if (state
->call
!= TRANSACT2_QFSINFO
&&
8581 state
->call
!= TRANSACT2_SETFSINFO
) {
8582 DEBUG(0,("handle_trans2: encryption required "
8584 (unsigned int)state
->call
));
8585 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8590 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8592 /* Now we must call the relevant TRANS2 function */
8593 switch(state
->call
) {
8594 case TRANSACT2_OPEN
:
8596 START_PROFILE(Trans2_open
);
8597 call_trans2open(conn
, req
,
8598 &state
->param
, state
->total_param
,
8599 &state
->data
, state
->total_data
,
8600 state
->max_data_return
);
8601 END_PROFILE(Trans2_open
);
8605 case TRANSACT2_FINDFIRST
:
8607 START_PROFILE(Trans2_findfirst
);
8608 call_trans2findfirst(conn
, req
,
8609 &state
->param
, state
->total_param
,
8610 &state
->data
, state
->total_data
,
8611 state
->max_data_return
);
8612 END_PROFILE(Trans2_findfirst
);
8616 case TRANSACT2_FINDNEXT
:
8618 START_PROFILE(Trans2_findnext
);
8619 call_trans2findnext(conn
, req
,
8620 &state
->param
, state
->total_param
,
8621 &state
->data
, state
->total_data
,
8622 state
->max_data_return
);
8623 END_PROFILE(Trans2_findnext
);
8627 case TRANSACT2_QFSINFO
:
8629 START_PROFILE(Trans2_qfsinfo
);
8630 call_trans2qfsinfo(conn
, req
,
8631 &state
->param
, state
->total_param
,
8632 &state
->data
, state
->total_data
,
8633 state
->max_data_return
);
8634 END_PROFILE(Trans2_qfsinfo
);
8638 case TRANSACT2_SETFSINFO
:
8640 START_PROFILE(Trans2_setfsinfo
);
8641 call_trans2setfsinfo(conn
, req
,
8642 &state
->param
, state
->total_param
,
8643 &state
->data
, state
->total_data
,
8644 state
->max_data_return
);
8645 END_PROFILE(Trans2_setfsinfo
);
8649 case TRANSACT2_QPATHINFO
:
8650 case TRANSACT2_QFILEINFO
:
8652 START_PROFILE(Trans2_qpathinfo
);
8653 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8654 &state
->param
, state
->total_param
,
8655 &state
->data
, state
->total_data
,
8656 state
->max_data_return
);
8657 END_PROFILE(Trans2_qpathinfo
);
8661 case TRANSACT2_SETPATHINFO
:
8662 case TRANSACT2_SETFILEINFO
:
8664 START_PROFILE(Trans2_setpathinfo
);
8665 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8666 &state
->param
, state
->total_param
,
8667 &state
->data
, state
->total_data
,
8668 state
->max_data_return
);
8669 END_PROFILE(Trans2_setpathinfo
);
8673 case TRANSACT2_FINDNOTIFYFIRST
:
8675 START_PROFILE(Trans2_findnotifyfirst
);
8676 call_trans2findnotifyfirst(conn
, req
,
8677 &state
->param
, state
->total_param
,
8678 &state
->data
, state
->total_data
,
8679 state
->max_data_return
);
8680 END_PROFILE(Trans2_findnotifyfirst
);
8684 case TRANSACT2_FINDNOTIFYNEXT
:
8686 START_PROFILE(Trans2_findnotifynext
);
8687 call_trans2findnotifynext(conn
, req
,
8688 &state
->param
, state
->total_param
,
8689 &state
->data
, state
->total_data
,
8690 state
->max_data_return
);
8691 END_PROFILE(Trans2_findnotifynext
);
8695 case TRANSACT2_MKDIR
:
8697 START_PROFILE(Trans2_mkdir
);
8698 call_trans2mkdir(conn
, req
,
8699 &state
->param
, state
->total_param
,
8700 &state
->data
, state
->total_data
,
8701 state
->max_data_return
);
8702 END_PROFILE(Trans2_mkdir
);
8706 case TRANSACT2_GET_DFS_REFERRAL
:
8708 START_PROFILE(Trans2_get_dfs_referral
);
8709 call_trans2getdfsreferral(conn
, req
,
8710 &state
->param
, state
->total_param
,
8711 &state
->data
, state
->total_data
,
8712 state
->max_data_return
);
8713 END_PROFILE(Trans2_get_dfs_referral
);
8717 case TRANSACT2_IOCTL
:
8719 START_PROFILE(Trans2_ioctl
);
8720 call_trans2ioctl(conn
, req
,
8721 &state
->param
, state
->total_param
,
8722 &state
->data
, state
->total_data
,
8723 state
->max_data_return
);
8724 END_PROFILE(Trans2_ioctl
);
8729 /* Error in request */
8730 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8731 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8735 /****************************************************************************
8736 Reply to a SMBtrans2.
8737 ****************************************************************************/
8739 void reply_trans2(struct smb_request
*req
)
8741 connection_struct
*conn
= req
->conn
;
8746 unsigned int tran_call
;
8747 struct trans_state
*state
;
8750 START_PROFILE(SMBtrans2
);
8752 if (req
->wct
< 14) {
8753 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8754 END_PROFILE(SMBtrans2
);
8758 dsoff
= SVAL(req
->vwv
+12, 0);
8759 dscnt
= SVAL(req
->vwv
+11, 0);
8760 psoff
= SVAL(req
->vwv
+10, 0);
8761 pscnt
= SVAL(req
->vwv
+9, 0);
8762 tran_call
= SVAL(req
->vwv
+14, 0);
8764 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8765 if (!NT_STATUS_IS_OK(result
)) {
8766 DEBUG(2, ("Got invalid trans2 request: %s\n",
8767 nt_errstr(result
)));
8768 reply_nterror(req
, result
);
8769 END_PROFILE(SMBtrans2
);
8774 switch (tran_call
) {
8775 /* List the allowed trans2 calls on IPC$ */
8776 case TRANSACT2_OPEN
:
8777 case TRANSACT2_GET_DFS_REFERRAL
:
8778 case TRANSACT2_QFILEINFO
:
8779 case TRANSACT2_QFSINFO
:
8780 case TRANSACT2_SETFSINFO
:
8783 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8784 END_PROFILE(SMBtrans2
);
8789 if ((state
= TALLOC_P(conn
, struct trans_state
)) == NULL
) {
8790 DEBUG(0, ("talloc failed\n"));
8791 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8792 END_PROFILE(SMBtrans2
);
8796 state
->cmd
= SMBtrans2
;
8798 state
->mid
= req
->mid
;
8799 state
->vuid
= req
->vuid
;
8800 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8801 state
->setup
= NULL
;
8802 state
->total_param
= SVAL(req
->vwv
+0, 0);
8803 state
->param
= NULL
;
8804 state
->total_data
= SVAL(req
->vwv
+1, 0);
8806 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8807 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8808 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8809 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8810 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8812 state
->call
= tran_call
;
8814 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8815 is so as a sanity check */
8816 if (state
->setup_count
!= 1) {
8818 * Need to have rc=0 for ioctl to get job id for OS/2.
8819 * Network printing will fail if function is not successful.
8820 * Similar function in reply.c will be used if protocol
8821 * is LANMAN1.0 instead of LM1.2X002.
8822 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8823 * outbuf doesn't have to be set(only job id is used).
8825 if ( (state
->setup_count
== 4)
8826 && (tran_call
== TRANSACT2_IOCTL
)
8827 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8828 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8829 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8831 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8832 DEBUG(2,("Transaction is %d\n",tran_call
));
8834 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8835 END_PROFILE(SMBtrans2
);
8840 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8843 if (state
->total_data
) {
8845 if (trans_oob(state
->total_data
, 0, dscnt
)
8846 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8850 /* Can't use talloc here, the core routines do realloc on the
8851 * params and data. */
8852 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8853 if (state
->data
== NULL
) {
8854 DEBUG(0,("reply_trans2: data malloc fail for %u "
8855 "bytes !\n", (unsigned int)state
->total_data
));
8857 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8858 END_PROFILE(SMBtrans2
);
8862 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8865 if (state
->total_param
) {
8867 if (trans_oob(state
->total_param
, 0, pscnt
)
8868 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8872 /* Can't use talloc here, the core routines do realloc on the
8873 * params and data. */
8874 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8875 if (state
->param
== NULL
) {
8876 DEBUG(0,("reply_trans: param malloc fail for %u "
8877 "bytes !\n", (unsigned int)state
->total_param
));
8878 SAFE_FREE(state
->data
);
8880 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8881 END_PROFILE(SMBtrans2
);
8885 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8888 state
->received_data
= dscnt
;
8889 state
->received_param
= pscnt
;
8891 if ((state
->received_param
== state
->total_param
) &&
8892 (state
->received_data
== state
->total_data
)) {
8894 handle_trans2(conn
, req
, state
);
8896 SAFE_FREE(state
->data
);
8897 SAFE_FREE(state
->param
);
8899 END_PROFILE(SMBtrans2
);
8903 DLIST_ADD(conn
->pending_trans
, state
);
8905 /* We need to send an interim response then receive the rest
8906 of the parameter/data bytes */
8907 reply_outbuf(req
, 0, 0);
8908 show_msg((char *)req
->outbuf
);
8909 END_PROFILE(SMBtrans2
);
8914 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8915 SAFE_FREE(state
->data
);
8916 SAFE_FREE(state
->param
);
8918 END_PROFILE(SMBtrans2
);
8919 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8923 /****************************************************************************
8924 Reply to a SMBtranss2
8925 ****************************************************************************/
8927 void reply_transs2(struct smb_request
*req
)
8929 connection_struct
*conn
= req
->conn
;
8930 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8931 struct trans_state
*state
;
8933 START_PROFILE(SMBtranss2
);
8935 show_msg((char *)req
->inbuf
);
8937 /* Windows clients expect all replies to
8938 a transact secondary (SMBtranss2 0x33)
8939 to have a command code of transact
8940 (SMBtrans2 0x32). See bug #8989
8941 and also [MS-CIFS] section 2.2.4.47.2
8944 req
->cmd
= SMBtrans2
;
8947 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8948 END_PROFILE(SMBtranss2
);
8952 for (state
= conn
->pending_trans
; state
!= NULL
;
8953 state
= state
->next
) {
8954 if (state
->mid
== req
->mid
) {
8959 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8960 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8961 END_PROFILE(SMBtranss2
);
8965 /* Revise state->total_param and state->total_data in case they have
8966 changed downwards */
8968 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8969 state
->total_param
= SVAL(req
->vwv
+0, 0);
8970 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8971 state
->total_data
= SVAL(req
->vwv
+1, 0);
8973 pcnt
= SVAL(req
->vwv
+2, 0);
8974 poff
= SVAL(req
->vwv
+3, 0);
8975 pdisp
= SVAL(req
->vwv
+4, 0);
8977 dcnt
= SVAL(req
->vwv
+5, 0);
8978 doff
= SVAL(req
->vwv
+6, 0);
8979 ddisp
= SVAL(req
->vwv
+7, 0);
8981 state
->received_param
+= pcnt
;
8982 state
->received_data
+= dcnt
;
8984 if ((state
->received_data
> state
->total_data
) ||
8985 (state
->received_param
> state
->total_param
))
8989 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8990 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8993 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8997 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8998 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9001 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9004 if ((state
->received_param
< state
->total_param
) ||
9005 (state
->received_data
< state
->total_data
)) {
9006 END_PROFILE(SMBtranss2
);
9010 handle_trans2(conn
, req
, state
);
9012 DLIST_REMOVE(conn
->pending_trans
, state
);
9013 SAFE_FREE(state
->data
);
9014 SAFE_FREE(state
->param
);
9017 END_PROFILE(SMBtranss2
);
9022 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9023 DLIST_REMOVE(conn
->pending_trans
, state
);
9024 SAFE_FREE(state
->data
);
9025 SAFE_FREE(state
->param
);
9027 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9028 END_PROFILE(SMBtranss2
);