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 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/>.
29 extern enum protocol_types Protocol
;
30 extern uint32 global_client_caps
;
31 extern struct current_user current_user
;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct
*conn
,
39 const SMB_STRUCT_STAT
*psbuf
);
41 static char *store_file_unix_basic_info2(connection_struct
*conn
,
44 const SMB_STRUCT_STAT
*psbuf
);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
53 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type
= get_remote_arch();
57 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
58 val
= SMB_ROUNDUP(val
,rval
);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, const SMB_STRUCT_STAT
*sbuf
)
72 if(S_ISDIR(sbuf
->st_mode
)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
79 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
82 if (fsp
&& fsp
->initial_allocation_size
)
83 ret
= MAX(ret
,fsp
->initial_allocation_size
);
85 return smb_roundup(conn
, ret
);
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 *prohibited_ea_names
[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME
,
100 SAMBA_XATTR_DOS_ATTRIB
,
106 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
107 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
113 /****************************************************************************
114 Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
117 static bool get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
118 const char *fname
, char *ea_name
, struct ea_struct
*pea
)
120 /* Get the value of this xattr. Max size is 64k. */
121 size_t attr_size
= 256;
127 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
132 if (fsp
&& fsp
->fh
->fd
!= -1) {
133 sizeret
= SMB_VFS_FGETXATTR(fsp
, fsp
->fh
->fd
, ea_name
, val
, attr_size
);
135 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
138 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
147 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
148 dump_data(10, (uint8
*)val
, sizeret
);
151 if (strnequal(ea_name
, "user.", 5)) {
152 pea
->name
= &ea_name
[5];
156 pea
->value
.data
= (unsigned char *)val
;
157 pea
->value
.length
= (size_t)sizeret
;
161 /****************************************************************************
162 Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
165 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
166 const char *fname
, size_t *pea_total_len
)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size
= 1024;
174 struct ea_list
*ea_list_head
= NULL
;
178 if (!lp_ea_support(SNUM(conn
))) {
182 for (i
= 0, ea_namelist
= TALLOC_ARRAY(mem_ctx
, char, ea_namelist_size
); i
< 6;
183 ea_namelist
= TALLOC_REALLOC_ARRAY(mem_ctx
, ea_namelist
, char, ea_namelist_size
), i
++) {
189 if (fsp
&& fsp
->fh
->fd
!= -1) {
190 sizeret
= SMB_VFS_FLISTXATTR(fsp
, fsp
->fh
->fd
, ea_namelist
, ea_namelist_size
);
192 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
, ea_namelist_size
);
195 if (sizeret
== -1 && errno
== ERANGE
) {
196 ea_namelist_size
*= 2;
205 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret
));
208 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
) + 1) {
209 struct ea_list
*listp
;
211 if (strnequal(p
, "system.", 7) || samba_private_attr_name(p
))
214 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
218 if (!get_ea_value(mem_ctx
, conn
, fsp
, fname
, p
, &listp
->ea
)) {
224 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
225 *pea_total_len
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
226 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227 (unsigned int)*pea_total_len
, dos_ea_name
,
228 (unsigned int)listp
->ea
.value
.length
));
230 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
232 /* Add on 4 for total length. */
233 if (*pea_total_len
) {
238 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len
));
242 /****************************************************************************
243 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 ****************************************************************************/
247 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
248 connection_struct
*conn
, struct ea_list
*ea_list
)
250 unsigned int ret_data_size
= 4;
253 SMB_ASSERT(total_data_size
>= 4);
255 if (!lp_ea_support(SNUM(conn
))) {
260 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
263 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
264 dos_namelen
= strlen(dos_ea_name
);
265 if (dos_namelen
> 255 || dos_namelen
== 0) {
268 if (ea_list
->ea
.value
.length
> 65535) {
271 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
275 /* We know we have room. */
276 SCVAL(p
,0,ea_list
->ea
.flags
);
277 SCVAL(p
,1,dos_namelen
);
278 SSVAL(p
,2,ea_list
->ea
.value
.length
);
279 fstrcpy(p
+4, dos_ea_name
);
280 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
282 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
283 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
286 ret_data_size
= PTR_DIFF(p
, pdata
);
287 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
288 SIVAL(pdata
,0,ret_data_size
);
289 return ret_data_size
;
292 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
294 size_t total_ea_len
= 0;
295 TALLOC_CTX
*mem_ctx
= NULL
;
297 if (!lp_ea_support(SNUM(conn
))) {
300 mem_ctx
= talloc_init("estimate_ea_size");
301 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
302 talloc_destroy(mem_ctx
);
306 /****************************************************************************
307 Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
310 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
313 TALLOC_CTX
*mem_ctx
= talloc_init("canonicalize_ea_name");
314 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
316 for (; ea_list
; ea_list
= ea_list
->next
) {
317 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
318 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319 &unix_ea_name
[5], ea_list
->ea
.name
));
320 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
324 talloc_destroy(mem_ctx
);
327 /****************************************************************************
328 Set or delete an extended attribute.
329 ****************************************************************************/
331 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
333 if (!lp_ea_support(SNUM(conn
))) {
334 return NT_STATUS_EAS_NOT_SUPPORTED
;
337 for (;ea_list
; ea_list
= ea_list
->next
) {
339 fstring unix_ea_name
;
341 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
342 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
344 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
346 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
348 if (samba_private_attr_name(unix_ea_name
)) {
349 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
350 return NT_STATUS_ACCESS_DENIED
;
353 if (ea_list
->ea
.value
.length
== 0) {
354 /* Remove the attribute. */
355 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
356 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357 unix_ea_name
, fsp
->fsp_name
));
358 ret
= SMB_VFS_FREMOVEXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
);
360 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361 unix_ea_name
, fname
));
362 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
365 /* Removing a non existent attribute always succeeds. */
366 if (ret
== -1 && errno
== ENOATTR
) {
367 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
373 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name
, fsp
->fsp_name
));
376 ret
= SMB_VFS_FSETXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
,
377 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
379 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380 unix_ea_name
, fname
));
381 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
382 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
388 if (errno
== ENOTSUP
) {
389 return NT_STATUS_EAS_NOT_SUPPORTED
;
392 return map_nt_error_from_unix(errno
);
398 /****************************************************************************
399 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
402 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
404 struct ea_list
*ea_list_head
= NULL
;
407 while (offset
+ 2 < data_size
) {
408 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
409 unsigned int namelen
= CVAL(pdata
,offset
);
411 offset
++; /* Go past the namelen byte. */
413 /* integer wrap paranioa. */
414 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
415 (offset
> data_size
) || (namelen
> data_size
) ||
416 (offset
+ namelen
>= data_size
)) {
419 /* Ensure the name is null terminated. */
420 if (pdata
[offset
+ namelen
] != '\0') {
423 pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
]);
428 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
429 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
430 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
436 /****************************************************************************
437 Read one EA list entry from the buffer.
438 ****************************************************************************/
440 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
442 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
444 unsigned int namelen
;
454 eal
->ea
.flags
= CVAL(pdata
,0);
455 namelen
= CVAL(pdata
,1);
456 val_len
= SVAL(pdata
,2);
458 if (4 + namelen
+ 1 + val_len
> data_size
) {
462 /* Ensure the name is null terminated. */
463 if (pdata
[namelen
+ 4] != '\0') {
466 pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4);
471 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
472 if (!eal
->ea
.value
.data
) {
476 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
478 /* Ensure we're null terminated just in case we print the value. */
479 eal
->ea
.value
.data
[val_len
] = '\0';
480 /* But don't count the null. */
481 eal
->ea
.value
.length
--;
484 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
487 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
488 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
493 /****************************************************************************
494 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
497 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
499 struct ea_list
*ea_list_head
= NULL
;
501 size_t bytes_used
= 0;
503 while (offset
< data_size
) {
504 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
510 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
511 offset
+= bytes_used
;
517 /****************************************************************************
518 Count the total EA size needed.
519 ****************************************************************************/
521 static size_t ea_list_size(struct ea_list
*ealist
)
524 struct ea_list
*listp
;
527 for (listp
= ealist
; listp
; listp
= listp
->next
) {
528 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
529 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
531 /* Add on 4 for total length. */
539 /****************************************************************************
540 Return a union of EA's from a file list and a list of names.
541 The TALLOC context for the two lists *MUST* be identical as we steal
542 memory from one list to add to another. JRA.
543 ****************************************************************************/
545 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
547 struct ea_list
*nlistp
, *flistp
;
549 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
550 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
551 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
557 /* Copy the data from this entry. */
558 nlistp
->ea
.flags
= flistp
->ea
.flags
;
559 nlistp
->ea
.value
= flistp
->ea
.value
;
562 nlistp
->ea
.flags
= 0;
563 ZERO_STRUCT(nlistp
->ea
.value
);
567 *total_ea_len
= ea_list_size(name_list
);
571 /****************************************************************************
572 Send the required number of replies back.
573 We assume all fields other than the data fields are
574 set correctly for the type of call.
575 HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
578 void send_trans2_replies(struct smb_request
*req
,
585 /* As we are using a protocol > LANMAN1 then the max_send
586 variable must have been set in the sessetupX call.
587 This takes precedence over the max_xmit field in the
588 global struct. These different max_xmit variables should
589 be merged as this is now too confusing */
591 int data_to_send
= datasize
;
592 int params_to_send
= paramsize
;
594 const char *pp
= params
;
595 const char *pd
= pdata
;
596 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
597 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
598 int data_alignment_offset
= 0;
599 bool overflow
= False
;
601 /* Modify the data_to_send and datasize and set the error if
602 we're trying to send more than max_data_bytes. We still send
603 the part of the packet(s) that fit. Strange, but needed
606 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
607 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
608 max_data_bytes
, datasize
));
609 datasize
= data_to_send
= max_data_bytes
;
613 /* If there genuinely are no parameters or data to send just send the empty packet */
615 if(params_to_send
== 0 && data_to_send
== 0) {
616 reply_outbuf(req
, 10, 0);
617 show_msg((char *)req
->outbuf
);
621 /* When sending params and data ensure that both are nicely aligned */
622 /* Only do this alignment when there is also data to send - else
623 can cause NT redirector problems. */
625 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
626 data_alignment_offset
= 4 - (params_to_send
% 4);
628 /* Space is bufsize minus Netbios over TCP header minus SMB header */
629 /* The alignment_offset is to align the param bytes on an even byte
630 boundary. NT 4.0 Beta needs this to work correctly. */
632 useable_space
= max_send
- (smb_size
635 + data_alignment_offset
);
637 /* useable_space can never be more than max_send minus the alignment offset. */
639 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
641 while (params_to_send
|| data_to_send
) {
642 /* Calculate whether we will totally or partially fill this packet */
644 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
646 /* We can never send more than useable_space */
648 * Note that 'useable_space' does not include the alignment offsets,
649 * but we must include the alignment offsets in the calculation of
650 * the length of the data we send over the wire, as the alignment offsets
651 * are sent here. Fix from Marc_Jacobsen@hp.com.
654 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
656 reply_outbuf(req
, 10, total_sent_thistime
);
658 /* Set total params and data to be sent */
659 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
660 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
662 /* Calculate how many parameters and data we can fit into
663 * this packet. Parameters get precedence
666 params_sent_thistime
= MIN(params_to_send
,useable_space
);
667 data_sent_thistime
= useable_space
- params_sent_thistime
;
668 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
670 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
672 /* smb_proff is the offset from the start of the SMB header to the
673 parameter bytes, however the first 4 bytes of outbuf are
674 the Netbios over TCP header. Thus use smb_base() to subtract
675 them from the calculation */
677 SSVAL(req
->outbuf
,smb_proff
,
678 ((smb_buf(req
->outbuf
)+alignment_offset
)
679 - smb_base(req
->outbuf
)));
681 if(params_sent_thistime
== 0)
682 SSVAL(req
->outbuf
,smb_prdisp
,0);
684 /* Absolute displacement of param bytes sent in this packet */
685 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
687 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
688 if(data_sent_thistime
== 0) {
689 SSVAL(req
->outbuf
,smb_droff
,0);
690 SSVAL(req
->outbuf
,smb_drdisp
, 0);
692 /* The offset of the data bytes is the offset of the
693 parameter bytes plus the number of parameters being sent this time */
694 SSVAL(req
->outbuf
, smb_droff
,
695 ((smb_buf(req
->outbuf
)+alignment_offset
)
696 - smb_base(req
->outbuf
))
697 + params_sent_thistime
+ data_alignment_offset
);
698 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
701 /* Initialize the padding for alignment */
703 if (alignment_offset
!= 0) {
704 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
707 /* Copy the param bytes into the packet */
709 if(params_sent_thistime
) {
710 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
711 params_sent_thistime
);
714 /* Copy in the data bytes */
715 if(data_sent_thistime
) {
716 if (data_alignment_offset
!= 0) {
717 memset((smb_buf(req
->outbuf
)+alignment_offset
+
718 params_sent_thistime
), 0,
719 data_alignment_offset
);
721 memcpy(smb_buf(req
->outbuf
)+alignment_offset
722 +params_sent_thistime
+data_alignment_offset
,
723 pd
,data_sent_thistime
);
726 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
727 params_sent_thistime
, data_sent_thistime
, useable_space
));
728 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
729 params_to_send
, data_to_send
, paramsize
, datasize
));
732 error_packet_set((char *)req
->outbuf
,
733 ERRDOS
,ERRbufferoverflow
,
734 STATUS_BUFFER_OVERFLOW
,
738 /* Send the packet */
739 show_msg((char *)req
->outbuf
);
740 if (!send_smb(smbd_server_fd(),(char *)req
->outbuf
))
741 exit_server_cleanly("send_trans2_replies: send_smb failed.");
743 TALLOC_FREE(req
->outbuf
);
745 pp
+= params_sent_thistime
;
746 pd
+= data_sent_thistime
;
748 params_to_send
-= params_sent_thistime
;
749 data_to_send
-= data_sent_thistime
;
752 if(params_to_send
< 0 || data_to_send
< 0) {
753 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
754 params_to_send
, data_to_send
));
762 /****************************************************************************
763 Reply to a TRANSACT2_OPEN.
764 ****************************************************************************/
766 static void call_trans2open(connection_struct
*conn
,
767 struct smb_request
*req
,
768 char **pparams
, int total_params
,
769 char **ppdata
, int total_data
,
770 unsigned int max_data_bytes
)
772 char *params
= *pparams
;
773 char *pdata
= *ppdata
;
778 bool return_additional_info
;
789 SMB_STRUCT_STAT sbuf
;
792 struct ea_list
*ea_list
= NULL
;
797 uint32 create_disposition
;
798 uint32 create_options
= 0;
799 TALLOC_CTX
*ctx
= talloc_tos();
802 * Ensure we have enough parameters to perform the operation.
805 if (total_params
< 29) {
806 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
810 flags
= SVAL(params
, 0);
811 deny_mode
= SVAL(params
, 2);
812 open_attr
= SVAL(params
,6);
813 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
814 if (oplock_request
) {
815 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
819 return_additional_info
= BITSETW(params
,0);
820 open_sattr
= SVAL(params
, 4);
821 open_time
= make_unix_date3(params
+8);
823 open_ofun
= SVAL(params
,12);
824 open_size
= IVAL(params
,14);
828 reply_doserror(req
, ERRSRV
, ERRaccess
);
832 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
833 total_params
- 28, STR_TERMINATE
,
835 if (!NT_STATUS_IS_OK(status
)) {
836 reply_nterror(req
, status
);
840 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
842 (unsigned int)open_ofun
, open_size
));
844 if (open_ofun
== 0) {
845 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
849 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
854 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
858 /* Any data in this call is an EA list. */
859 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
860 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
864 if (total_data
!= 4) {
865 if (total_data
< 10) {
866 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
870 if (IVAL(pdata
,0) > total_data
) {
871 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
872 IVAL(pdata
,0), (unsigned int)total_data
));
873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
877 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
880 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
883 } else if (IVAL(pdata
,0) != 4) {
884 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
888 status
= create_file(conn
, /* conn */
890 0, /* root_dir_fid */
892 access_mask
, /* access_mask */
893 share_mode
, /* share_access */
894 create_disposition
, /* create_disposition*/
895 create_options
, /* create_options */
896 open_attr
, /* file_attributes */
897 oplock_request
, /* oplock_request */
898 open_size
, /* allocation_size */
900 ea_list
, /* ea_list */
902 &smb_action
, /* pinfo */
905 if (!NT_STATUS_IS_OK(status
)) {
906 if (open_was_deferred(req
->mid
)) {
907 /* We have re-scheduled this call. */
910 reply_openerror(req
, status
);
914 size
= get_file_size(sbuf
);
915 fattr
= dos_mode(conn
,fname
,&sbuf
);
916 mtime
= sbuf
.st_mtime
;
919 close_file(fsp
,ERROR_CLOSE
);
920 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
924 /* Realloc the size of parameters and data we will return */
925 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
926 if(*pparams
== NULL
) {
927 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
932 SSVAL(params
,0,fsp
->fnum
);
933 SSVAL(params
,2,fattr
);
934 srv_put_dos_date2(params
,4, mtime
);
935 SIVAL(params
,8, (uint32
)size
);
936 SSVAL(params
,12,deny_mode
);
937 SSVAL(params
,14,0); /* open_type - file or directory. */
938 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
940 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
941 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
944 SSVAL(params
,18,smb_action
);
947 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
949 SIVAL(params
,20,inode
);
950 SSVAL(params
,24,0); /* Padding. */
952 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fname
);
953 SIVAL(params
, 26, ea_size
);
955 SIVAL(params
, 26, 0);
958 /* Send the required number of replies */
959 send_trans2_replies(req
, params
, 30, *ppdata
, 0, max_data_bytes
);
962 /*********************************************************
963 Routine to check if a given string matches exactly.
964 as a special case a mask of "." does NOT match. That
965 is required for correct wildcard semantics
966 Case can be significant or not.
967 **********************************************************/
969 static bool exact_match(connection_struct
*conn
,
973 if (mask
[0] == '.' && mask
[1] == 0)
975 if (conn
->case_sensitive
)
976 return strcmp(str
,mask
)==0;
977 if (StrCaseCmp(str
,mask
) != 0) {
980 if (dptr_has_wild(conn
->dirptr
)) {
986 /****************************************************************************
987 Return the filetype for UNIX extensions.
988 ****************************************************************************/
990 static uint32
unix_filetype(mode_t mode
)
993 return UNIX_TYPE_FILE
;
994 else if(S_ISDIR(mode
))
995 return UNIX_TYPE_DIR
;
997 else if(S_ISLNK(mode
))
998 return UNIX_TYPE_SYMLINK
;
1001 else if(S_ISCHR(mode
))
1002 return UNIX_TYPE_CHARDEV
;
1005 else if(S_ISBLK(mode
))
1006 return UNIX_TYPE_BLKDEV
;
1009 else if(S_ISFIFO(mode
))
1010 return UNIX_TYPE_FIFO
;
1013 else if(S_ISSOCK(mode
))
1014 return UNIX_TYPE_SOCKET
;
1017 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
1018 return UNIX_TYPE_UNKNOWN
;
1021 /****************************************************************************
1022 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1023 ****************************************************************************/
1025 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1027 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1028 SMB_STRUCT_STAT
*psbuf
,
1030 enum perm_type ptype
,
1035 if (perms
== SMB_MODE_NO_CHANGE
) {
1036 if (!VALID_STAT(*psbuf
)) {
1037 return NT_STATUS_INVALID_PARAMETER
;
1039 *ret_perms
= psbuf
->st_mode
;
1040 return NT_STATUS_OK
;
1044 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1045 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1046 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1047 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1048 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1049 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1050 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1051 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1052 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1054 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1057 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1060 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1065 /* Apply mode mask */
1066 ret
&= lp_create_mask(SNUM(conn
));
1067 /* Add in force bits */
1068 ret
|= lp_force_create_mode(SNUM(conn
));
1071 ret
&= lp_dir_mask(SNUM(conn
));
1072 /* Add in force bits */
1073 ret
|= lp_force_dir_mode(SNUM(conn
));
1075 case PERM_EXISTING_FILE
:
1076 /* Apply mode mask */
1077 ret
&= lp_security_mask(SNUM(conn
));
1078 /* Add in force bits */
1079 ret
|= lp_force_security_mode(SNUM(conn
));
1081 case PERM_EXISTING_DIR
:
1082 /* Apply mode mask */
1083 ret
&= lp_dir_security_mask(SNUM(conn
));
1084 /* Add in force bits */
1085 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1090 return NT_STATUS_OK
;
1093 /****************************************************************************
1094 Get a level dependent lanman2 dir entry.
1095 ****************************************************************************/
1097 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
1098 connection_struct
*conn
,
1100 const char *path_mask
,
1103 int requires_resume_key
,
1108 int space_remaining
,
1110 bool *got_exact_match
,
1111 int *last_entry_off
,
1112 struct ea_list
*name_list
)
1116 SMB_STRUCT_STAT sbuf
;
1117 const char *mask
= NULL
;
1118 char *pathreal
= NULL
;
1119 const char *fname
= NULL
;
1120 char *p
, *q
, *pdata
= *ppdata
;
1124 SMB_OFF_T file_size
= 0;
1125 SMB_BIG_UINT allocation_size
= 0;
1127 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1128 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1130 char *last_entry_ptr
;
1132 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1133 bool needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1134 bool check_mangled_names
= lp_manglednames(conn
->params
);
1135 char mangled_name
[13]; /* mangled 8.3 name. */
1137 *out_of_space
= False
;
1138 *got_exact_match
= False
;
1140 ZERO_STRUCT(mdate_ts
);
1141 ZERO_STRUCT(adate_ts
);
1142 ZERO_STRUCT(create_date_ts
);
1144 if (!conn
->dirptr
) {
1148 p
= strrchr_m(path_mask
,'/');
1151 mask
= talloc_strdup(ctx
,"*.*");
1161 bool ms_dfs_link
= False
;
1163 /* Needed if we run out of space */
1164 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1165 dname
= dptr_ReadDirName(ctx
,conn
->dirptr
,&curr_dirpos
,&sbuf
);
1168 * Due to bugs in NT client redirectors we are not using
1169 * resume keys any more - set them to zero.
1170 * Check out the related comments in findfirst/findnext.
1176 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1177 (long)conn
->dirptr
,curr_dirpos
));
1184 * fname may get mangled, dname is never mangled.
1185 * Whenever we're accessing the filesystem we use
1186 * pathreal which is composed from dname.
1192 /* Mangle fname if it's an illegal name. */
1193 if (mangle_must_mangle(dname
,conn
->params
)) {
1194 if (!name_to_8_3(dname
,mangled_name
,True
,conn
->params
)) {
1195 continue; /* Error - couldn't mangle. */
1197 fname
= mangled_name
;
1200 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
))) {
1201 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1204 if(!got_match
&& check_mangled_names
&&
1205 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1207 * It turns out that NT matches wildcards against
1208 * both long *and* short names. This may explain some
1209 * of the wildcard wierdness from old DOS clients
1210 * that some people have been seeing.... JRA.
1212 /* Force the mangling into 8.3. */
1213 if (!name_to_8_3( fname
, mangled_name
, False
, conn
->params
)) {
1214 continue; /* Error - couldn't mangle. */
1217 if(!(got_match
= *got_exact_match
= exact_match(conn
, mangled_name
, mask
))) {
1218 got_match
= mask_match(mangled_name
, mask
, conn
->case_sensitive
);
1223 bool isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1225 if (dont_descend
&& !isdots
) {
1231 pathreal
= talloc_asprintf(ctx
,
1236 pathreal
= talloc_asprintf(ctx
,
1246 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1247 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1248 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1249 pathreal
,strerror(errno
)));
1250 TALLOC_FREE(pathreal
);
1253 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1254 /* Needed to show the msdfs symlinks as
1257 if(lp_host_msdfs() &&
1258 lp_msdfs_root(SNUM(conn
)) &&
1259 ((ms_dfs_link
= is_msdfs_link(conn
, pathreal
, &sbuf
)) == True
)) {
1260 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1263 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
1267 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1268 pathreal
,strerror(errno
)));
1269 TALLOC_FREE(pathreal
);
1275 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1277 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1280 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1281 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname
,dirtype
));
1282 TALLOC_FREE(pathreal
);
1286 if (!(mode
& aDIR
)) {
1287 file_size
= get_file_size(sbuf
);
1289 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1291 mdate_ts
= get_mtimespec(&sbuf
);
1292 adate_ts
= get_atimespec(&sbuf
);
1293 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1295 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1296 dos_filetime_timespec(&create_date_ts
);
1297 dos_filetime_timespec(&mdate_ts
);
1298 dos_filetime_timespec(&adate_ts
);
1301 create_date
= convert_timespec_to_time_t(create_date_ts
);
1302 mdate
= convert_timespec_to_time_t(mdate_ts
);
1303 adate
= convert_timespec_to_time_t(adate_ts
);
1305 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal
,fname
));
1309 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1316 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1318 switch (info_level
) {
1319 case SMB_FIND_INFO_STANDARD
:
1320 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1321 if(requires_resume_key
) {
1325 srv_put_dos_date2(p
,0,create_date
);
1326 srv_put_dos_date2(p
,4,adate
);
1327 srv_put_dos_date2(p
,8,mdate
);
1328 SIVAL(p
,12,(uint32
)file_size
);
1329 SIVAL(p
,16,(uint32
)allocation_size
);
1333 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1334 p
+= ucs2_align(base_data
, p
, 0);
1336 len
= srvstr_push(base_data
, flags2
, p
,
1337 fname
, PTR_DIFF(end_data
, p
),
1339 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1341 SCVAL(nameptr
, -1, len
- 2);
1343 SCVAL(nameptr
, -1, 0);
1347 SCVAL(nameptr
, -1, len
- 1);
1349 SCVAL(nameptr
, -1, 0);
1355 case SMB_FIND_EA_SIZE
:
1356 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1357 if(requires_resume_key
) {
1361 srv_put_dos_date2(p
,0,create_date
);
1362 srv_put_dos_date2(p
,4,adate
);
1363 srv_put_dos_date2(p
,8,mdate
);
1364 SIVAL(p
,12,(uint32
)file_size
);
1365 SIVAL(p
,16,(uint32
)allocation_size
);
1368 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1369 SIVAL(p
,22,ea_size
); /* Extended attributes */
1373 len
= srvstr_push(base_data
, flags2
,
1374 p
, fname
, PTR_DIFF(end_data
, p
),
1375 STR_TERMINATE
| STR_NOALIGN
);
1376 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1389 SCVAL(nameptr
,0,len
);
1391 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1394 case SMB_FIND_EA_LIST
:
1396 struct ea_list
*file_list
= NULL
;
1399 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1403 if(requires_resume_key
) {
1407 srv_put_dos_date2(p
,0,create_date
);
1408 srv_put_dos_date2(p
,4,adate
);
1409 srv_put_dos_date2(p
,8,mdate
);
1410 SIVAL(p
,12,(uint32
)file_size
);
1411 SIVAL(p
,16,(uint32
)allocation_size
);
1413 p
+= 22; /* p now points to the EA area. */
1415 file_list
= get_ea_list_from_file(ctx
, conn
, NULL
, pathreal
, &ea_len
);
1416 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1418 /* We need to determine if this entry will fit in the space available. */
1419 /* Max string size is 255 bytes. */
1420 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1421 /* Move the dirptr back to prev_dirpos */
1422 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1423 *out_of_space
= True
;
1424 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1425 return False
; /* Not finished - just out of space */
1428 /* Push the ea_data followed by the name. */
1429 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1431 len
= srvstr_push(base_data
, flags2
,
1432 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1433 STR_TERMINATE
| STR_NOALIGN
);
1434 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1447 SCVAL(nameptr
,0,len
);
1449 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1454 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1455 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1457 SIVAL(p
,0,reskey
); p
+= 4;
1458 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1459 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1460 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1461 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1462 SOFF_T(p
,0,file_size
); p
+= 8;
1463 SOFF_T(p
,0,allocation_size
); p
+= 8;
1464 SIVAL(p
,0,nt_extmode
); p
+= 4;
1465 q
= p
; p
+= 4; /* q is placeholder for name length. */
1467 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1468 SIVAL(p
,0,ea_size
); /* Extended attributes */
1471 /* Clear the short name buffer. This is
1472 * IMPORTANT as not doing so will trigger
1473 * a Win2k client bug. JRA.
1475 if (!was_8_3
&& check_mangled_names
) {
1476 if (!name_to_8_3(fname
,mangled_name
,True
,
1478 /* Error - mangle failed ! */
1479 memset(mangled_name
,'\0',12);
1481 mangled_name
[12] = 0;
1482 len
= srvstr_push(base_data
, flags2
,
1483 p
+2, mangled_name
, 24,
1484 STR_UPPER
|STR_UNICODE
);
1486 memset(p
+ 2 + len
,'\0',24 - len
);
1493 len
= srvstr_push(base_data
, flags2
, p
,
1494 fname
, PTR_DIFF(end_data
, p
),
1495 STR_TERMINATE_ASCII
);
1498 SIVAL(p
,0,0); /* Ensure any padding is null. */
1499 len
= PTR_DIFF(p
, pdata
);
1500 len
= (len
+ 3) & ~3;
1505 case SMB_FIND_FILE_DIRECTORY_INFO
:
1506 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1508 SIVAL(p
,0,reskey
); p
+= 4;
1509 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1510 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1511 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1512 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1513 SOFF_T(p
,0,file_size
); p
+= 8;
1514 SOFF_T(p
,0,allocation_size
); p
+= 8;
1515 SIVAL(p
,0,nt_extmode
); p
+= 4;
1516 len
= srvstr_push(base_data
, flags2
,
1517 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1518 STR_TERMINATE_ASCII
);
1521 SIVAL(p
,0,0); /* Ensure any padding is null. */
1522 len
= PTR_DIFF(p
, pdata
);
1523 len
= (len
+ 3) & ~3;
1528 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1529 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1531 SIVAL(p
,0,reskey
); p
+= 4;
1532 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1533 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1534 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1535 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1536 SOFF_T(p
,0,file_size
); p
+= 8;
1537 SOFF_T(p
,0,allocation_size
); p
+= 8;
1538 SIVAL(p
,0,nt_extmode
); p
+= 4;
1539 q
= p
; p
+= 4; /* q is placeholder for name length. */
1541 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1542 SIVAL(p
,0,ea_size
); /* Extended attributes */
1545 len
= srvstr_push(base_data
, flags2
, p
,
1546 fname
, PTR_DIFF(end_data
, p
),
1547 STR_TERMINATE_ASCII
);
1551 SIVAL(p
,0,0); /* Ensure any padding is null. */
1552 len
= PTR_DIFF(p
, pdata
);
1553 len
= (len
+ 3) & ~3;
1558 case SMB_FIND_FILE_NAMES_INFO
:
1559 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1561 SIVAL(p
,0,reskey
); p
+= 4;
1563 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1564 acl on a dir (tridge) */
1565 len
= srvstr_push(base_data
, flags2
, p
,
1566 fname
, PTR_DIFF(end_data
, p
),
1567 STR_TERMINATE_ASCII
);
1570 SIVAL(p
,0,0); /* Ensure any padding is null. */
1571 len
= PTR_DIFF(p
, pdata
);
1572 len
= (len
+ 3) & ~3;
1577 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1578 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1580 SIVAL(p
,0,reskey
); p
+= 4;
1581 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1582 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1583 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1584 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1585 SOFF_T(p
,0,file_size
); p
+= 8;
1586 SOFF_T(p
,0,allocation_size
); p
+= 8;
1587 SIVAL(p
,0,nt_extmode
); p
+= 4;
1588 q
= p
; p
+= 4; /* q is placeholder for name length. */
1590 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1591 SIVAL(p
,0,ea_size
); /* Extended attributes */
1594 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1595 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1596 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1597 len
= srvstr_push(base_data
, flags2
, p
,
1598 fname
, PTR_DIFF(end_data
, p
),
1599 STR_TERMINATE_ASCII
);
1602 SIVAL(p
,0,0); /* Ensure any padding is null. */
1603 len
= PTR_DIFF(p
, pdata
);
1604 len
= (len
+ 3) & ~3;
1609 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1610 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1611 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1613 SIVAL(p
,0,reskey
); p
+= 4;
1614 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1615 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1616 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1617 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1618 SOFF_T(p
,0,file_size
); p
+= 8;
1619 SOFF_T(p
,0,allocation_size
); p
+= 8;
1620 SIVAL(p
,0,nt_extmode
); p
+= 4;
1621 q
= p
; p
+= 4; /* q is placeholder for name length */
1623 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1624 SIVAL(p
,0,ea_size
); /* Extended attributes */
1627 /* Clear the short name buffer. This is
1628 * IMPORTANT as not doing so will trigger
1629 * a Win2k client bug. JRA.
1631 if (!was_8_3
&& check_mangled_names
) {
1632 if (!name_to_8_3(fname
,mangled_name
,True
,
1634 /* Error - mangle failed ! */
1635 memset(mangled_name
,'\0',12);
1637 mangled_name
[12] = 0;
1638 len
= srvstr_push(base_data
, flags2
,
1639 p
+2, mangled_name
, 24,
1640 STR_UPPER
|STR_UNICODE
);
1643 memset(p
+ 2 + len
,'\0',24 - len
);
1650 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1651 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1652 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1653 len
= srvstr_push(base_data
, flags2
, p
,
1654 fname
, PTR_DIFF(end_data
, p
),
1655 STR_TERMINATE_ASCII
);
1658 SIVAL(p
,0,0); /* Ensure any padding is null. */
1659 len
= PTR_DIFF(p
, pdata
);
1660 len
= (len
+ 3) & ~3;
1665 /* CIFS UNIX Extension. */
1667 case SMB_FIND_FILE_UNIX
:
1668 case SMB_FIND_FILE_UNIX_INFO2
:
1670 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1672 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1674 if (info_level
== SMB_FIND_FILE_UNIX
) {
1675 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1676 p
= store_file_unix_basic(conn
, p
,
1678 len
= srvstr_push(base_data
, flags2
, p
,
1679 fname
, PTR_DIFF(end_data
, p
),
1682 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1683 p
= store_file_unix_basic_info2(conn
, p
,
1687 len
= srvstr_push(base_data
, flags2
, p
, fname
,
1688 PTR_DIFF(end_data
, p
), 0);
1689 SIVAL(nameptr
, 0, len
);
1693 SIVAL(p
,0,0); /* Ensure any padding is null. */
1695 len
= PTR_DIFF(p
, pdata
);
1696 len
= (len
+ 3) & ~3;
1697 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1699 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1708 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1709 /* Move the dirptr back to prev_dirpos */
1710 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1711 *out_of_space
= True
;
1712 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1713 return False
; /* Not finished - just out of space */
1716 /* Setup the last entry pointer, as an offset from base_data */
1717 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1718 /* Advance the data pointer to the next slot */
1724 /****************************************************************************
1725 Reply to a TRANS2_FINDFIRST.
1726 ****************************************************************************/
1728 static void call_trans2findfirst(connection_struct
*conn
,
1729 struct smb_request
*req
,
1730 char **pparams
, int total_params
,
1731 char **ppdata
, int total_data
,
1732 unsigned int max_data_bytes
)
1734 /* We must be careful here that we don't return more than the
1735 allowed number of data bytes. If this means returning fewer than
1736 maxentries then so be it. We assume that the redirector has
1737 enough room for the fixed number of parameter bytes it has
1739 char *params
= *pparams
;
1740 char *pdata
= *ppdata
;
1744 uint16 findfirst_flags
;
1745 bool close_after_first
;
1747 bool requires_resume_key
;
1749 char *directory
= NULL
;
1750 const char *mask
= NULL
;
1752 int last_entry_off
=0;
1756 bool finished
= False
;
1757 bool dont_descend
= False
;
1758 bool out_of_space
= False
;
1759 int space_remaining
;
1760 bool mask_contains_wcard
= False
;
1761 SMB_STRUCT_STAT sbuf
;
1762 struct ea_list
*ea_list
= NULL
;
1763 NTSTATUS ntstatus
= NT_STATUS_OK
;
1764 TALLOC_CTX
*ctx
= talloc_tos();
1766 if (total_params
< 13) {
1767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1771 dirtype
= SVAL(params
,0);
1772 maxentries
= SVAL(params
,2);
1773 findfirst_flags
= SVAL(params
,4);
1774 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1775 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1776 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1777 info_level
= SVAL(params
,6);
1779 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1780 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1781 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1782 info_level
, max_data_bytes
));
1785 /* W2K3 seems to treat zero as 1. */
1789 switch (info_level
) {
1790 case SMB_FIND_INFO_STANDARD
:
1791 case SMB_FIND_EA_SIZE
:
1792 case SMB_FIND_EA_LIST
:
1793 case SMB_FIND_FILE_DIRECTORY_INFO
:
1794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1795 case SMB_FIND_FILE_NAMES_INFO
:
1796 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1797 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1798 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1800 case SMB_FIND_FILE_UNIX
:
1801 case SMB_FIND_FILE_UNIX_INFO2
:
1802 if (!lp_unix_extensions()) {
1803 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1808 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
1812 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
1813 params
+12, total_params
- 12,
1814 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1815 if (!NT_STATUS_IS_OK(ntstatus
)) {
1816 reply_nterror(req
, ntstatus
);
1820 ntstatus
= resolve_dfspath_wcard(ctx
, conn
,
1821 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1824 &mask_contains_wcard
);
1825 if (!NT_STATUS_IS_OK(ntstatus
)) {
1826 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1827 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1828 ERRSRV
, ERRbadpath
);
1831 reply_nterror(req
, ntstatus
);
1835 ntstatus
= unix_convert(ctx
, conn
, directory
, True
, &directory
, NULL
, &sbuf
);
1836 if (!NT_STATUS_IS_OK(ntstatus
)) {
1837 reply_nterror(req
, ntstatus
);
1841 ntstatus
= check_name(conn
, directory
);
1842 if (!NT_STATUS_IS_OK(ntstatus
)) {
1843 reply_nterror(req
, ntstatus
);
1847 p
= strrchr_m(directory
,'/');
1849 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1850 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1852 mask_contains_wcard
= True
;
1856 directory
= talloc_strdup(talloc_tos(), "./");
1858 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1866 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
1868 if (info_level
== SMB_FIND_EA_LIST
) {
1871 if (total_data
< 4) {
1872 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1876 ea_size
= IVAL(pdata
,0);
1877 if (ea_size
!= total_data
) {
1878 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1879 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
1880 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1884 if (!lp_ea_support(SNUM(conn
))) {
1885 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
1889 /* Pull out the list of names. */
1890 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
1892 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1897 *ppdata
= (char *)SMB_REALLOC(
1898 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1899 if(*ppdata
== NULL
) {
1900 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1904 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
1906 /* Realloc the params space */
1907 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
1908 if (*pparams
== NULL
) {
1909 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1914 /* Save the wildcard match and attribs we are using on this directory -
1915 needed as lanman2 assumes these are being saved between calls */
1917 ntstatus
= dptr_create(conn
,
1923 mask_contains_wcard
,
1927 if (!NT_STATUS_IS_OK(ntstatus
)) {
1928 reply_nterror(req
, ntstatus
);
1932 dptr_num
= dptr_dnum(conn
->dirptr
);
1933 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
1935 /* We don't need to check for VOL here as this is returned by
1936 a different TRANS2 call. */
1938 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1939 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
1940 dont_descend
= True
;
1943 space_remaining
= max_data_bytes
;
1944 out_of_space
= False
;
1946 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1947 bool got_exact_match
= False
;
1949 /* this is a heuristic to avoid seeking the dirptr except when
1950 absolutely necessary. It allows for a filename of about 40 chars */
1951 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1952 out_of_space
= True
;
1955 TALLOC_CTX
*sub_ctx
= talloc_stackframe();
1957 finished
= !get_lanman2_dir_entry(sub_ctx
,
1960 mask
,dirtype
,info_level
,
1961 requires_resume_key
,dont_descend
,
1963 space_remaining
, &out_of_space
,
1965 &last_entry_off
, ea_list
);
1967 TALLOC_FREE(sub_ctx
);
1970 if (finished
&& out_of_space
)
1973 if (!finished
&& !out_of_space
)
1977 * As an optimisation if we know we aren't looking
1978 * for a wildcard name (ie. the name matches the wildcard exactly)
1979 * then we can finish on any (first) match.
1980 * This speeds up large directory searches. JRA.
1986 /* Ensure space_remaining never goes -ve. */
1987 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
1988 space_remaining
= 0;
1989 out_of_space
= true;
1991 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1995 /* Check if we can close the dirptr */
1996 if(close_after_first
|| (finished
&& close_if_end
)) {
1997 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1998 dptr_close(&dptr_num
);
2002 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2003 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2004 * the protocol level is less than NT1. Tested with smbclient. JRA.
2005 * This should fix the OS/2 client bug #2335.
2008 if(numentries
== 0) {
2009 dptr_close(&dptr_num
);
2010 if (Protocol
< PROTOCOL_NT1
) {
2011 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2014 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2015 ERRDOS
, ERRbadfile
);
2020 /* At this point pdata points to numentries directory entries. */
2022 /* Set up the return parameter block */
2023 SSVAL(params
,0,dptr_num
);
2024 SSVAL(params
,2,numentries
);
2025 SSVAL(params
,4,finished
);
2026 SSVAL(params
,6,0); /* Never an EA error */
2027 SSVAL(params
,8,last_entry_off
);
2029 send_trans2_replies(req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2032 if ((! *directory
) && dptr_path(dptr_num
)) {
2033 directory
= talloc_strdup(talloc_tos(),dptr_path(dptr_num
));
2035 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2039 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2040 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2041 mask
, directory
, dirtype
, numentries
) );
2044 * Force a name mangle here to ensure that the
2045 * mask as an 8.3 name is top of the mangled cache.
2046 * The reasons for this are subtle. Don't remove
2047 * this code unless you know what you are doing
2048 * (see PR#13758). JRA.
2051 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2052 char mangled_name
[13];
2053 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2059 /****************************************************************************
2060 Reply to a TRANS2_FINDNEXT.
2061 ****************************************************************************/
2063 static void call_trans2findnext(connection_struct
*conn
,
2064 struct smb_request
*req
,
2065 char **pparams
, int total_params
,
2066 char **ppdata
, int total_data
,
2067 unsigned int max_data_bytes
)
2069 /* We must be careful here that we don't return more than the
2070 allowed number of data bytes. If this means returning fewer than
2071 maxentries then so be it. We assume that the redirector has
2072 enough room for the fixed number of parameter bytes it has
2074 char *params
= *pparams
;
2075 char *pdata
= *ppdata
;
2081 uint16 findnext_flags
;
2082 bool close_after_request
;
2084 bool requires_resume_key
;
2086 bool mask_contains_wcard
= False
;
2087 char *resume_name
= NULL
;
2088 const char *mask
= NULL
;
2089 const char *directory
= NULL
;
2093 int i
, last_entry_off
=0;
2094 bool finished
= False
;
2095 bool dont_descend
= False
;
2096 bool out_of_space
= False
;
2097 int space_remaining
;
2098 struct ea_list
*ea_list
= NULL
;
2099 NTSTATUS ntstatus
= NT_STATUS_OK
;
2100 TALLOC_CTX
*ctx
= talloc_tos();
2102 if (total_params
< 13) {
2103 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2107 dptr_num
= SVAL(params
,0);
2108 maxentries
= SVAL(params
,2);
2109 info_level
= SVAL(params
,4);
2110 resume_key
= IVAL(params
,6);
2111 findnext_flags
= SVAL(params
,10);
2112 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2113 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2114 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2115 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2117 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2119 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2120 &mask_contains_wcard
);
2121 if (!NT_STATUS_IS_OK(ntstatus
)) {
2122 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2123 complain (it thinks we're asking for the directory above the shared
2124 path or an invalid name). Catch this as the resume name is only compared, never used in
2125 a file access. JRA. */
2126 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2127 &resume_name
, params
+12,
2131 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2132 reply_nterror(req
, ntstatus
);
2137 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2138 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2139 resume_key = %d resume name = %s continue=%d level = %d\n",
2140 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2141 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2144 /* W2K3 seems to treat zero as 1. */
2148 switch (info_level
) {
2149 case SMB_FIND_INFO_STANDARD
:
2150 case SMB_FIND_EA_SIZE
:
2151 case SMB_FIND_EA_LIST
:
2152 case SMB_FIND_FILE_DIRECTORY_INFO
:
2153 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2154 case SMB_FIND_FILE_NAMES_INFO
:
2155 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2156 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2157 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2159 case SMB_FIND_FILE_UNIX
:
2160 case SMB_FIND_FILE_UNIX_INFO2
:
2161 if (!lp_unix_extensions()) {
2162 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2167 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2171 if (info_level
== SMB_FIND_EA_LIST
) {
2174 if (total_data
< 4) {
2175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2179 ea_size
= IVAL(pdata
,0);
2180 if (ea_size
!= total_data
) {
2181 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2182 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2187 if (!lp_ea_support(SNUM(conn
))) {
2188 reply_doserror(req
, ERRDOS
, ERReasnotsupported
);
2192 /* Pull out the list of names. */
2193 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2195 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2200 *ppdata
= (char *)SMB_REALLOC(
2201 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2202 if(*ppdata
== NULL
) {
2203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2208 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2210 /* Realloc the params space */
2211 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2212 if(*pparams
== NULL
) {
2213 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2219 /* Check that the dptr is valid */
2220 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2221 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2225 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2227 /* Get the wildcard mask from the dptr */
2228 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2229 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2230 reply_doserror(req
, ERRDOS
, ERRnofiles
);
2235 directory
= conn
->dirpath
;
2237 /* Get the attr mask from the dptr */
2238 dirtype
= dptr_attr(dptr_num
);
2240 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2241 dptr_num
, mask
, dirtype
,
2243 dptr_TellDir(conn
->dirptr
)));
2245 /* We don't need to check for VOL here as this is returned by
2246 a different TRANS2 call. */
2248 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2249 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2250 dont_descend
= True
;
2253 space_remaining
= max_data_bytes
;
2254 out_of_space
= False
;
2257 * Seek to the correct position. We no longer use the resume key but
2258 * depend on the last file name instead.
2261 if(*resume_name
&& !continue_bit
) {
2264 long current_pos
= 0;
2266 * Remember, name_to_8_3 is called by
2267 * get_lanman2_dir_entry(), so the resume name
2268 * could be mangled. Ensure we check the unmangled name.
2271 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2272 char *new_resume_name
= NULL
;
2273 mangle_lookup_name_from_8_3(ctx
,
2277 if (new_resume_name
) {
2278 resume_name
= new_resume_name
;
2283 * Fix for NT redirector problem triggered by resume key indexes
2284 * changing between directory scans. We now return a resume key of 0
2285 * and instead look for the filename to continue from (also given
2286 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2287 * findfirst/findnext (as is usual) then the directory pointer
2288 * should already be at the correct place.
2291 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2292 } /* end if resume_name && !continue_bit */
2294 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2295 bool got_exact_match
= False
;
2297 /* this is a heuristic to avoid seeking the dirptr except when
2298 absolutely necessary. It allows for a filename of about 40 chars */
2299 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2300 out_of_space
= True
;
2303 TALLOC_CTX
*sub_ctx
= talloc_stackframe();
2305 finished
= !get_lanman2_dir_entry(sub_ctx
,
2308 mask
,dirtype
,info_level
,
2309 requires_resume_key
,dont_descend
,
2311 space_remaining
, &out_of_space
,
2313 &last_entry_off
, ea_list
);
2315 TALLOC_FREE(sub_ctx
);
2318 if (finished
&& out_of_space
)
2321 if (!finished
&& !out_of_space
)
2325 * As an optimisation if we know we aren't looking
2326 * for a wildcard name (ie. the name matches the wildcard exactly)
2327 * then we can finish on any (first) match.
2328 * This speeds up large directory searches. JRA.
2334 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2337 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2338 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
2339 mask
, directory
, dirtype
, numentries
) );
2341 /* Check if we can close the dirptr */
2342 if(close_after_request
|| (finished
&& close_if_end
)) {
2343 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2344 dptr_close(&dptr_num
); /* This frees up the saved mask */
2347 /* Set up the return parameter block */
2348 SSVAL(params
,0,numentries
);
2349 SSVAL(params
,2,finished
);
2350 SSVAL(params
,4,0); /* Never an EA error */
2351 SSVAL(params
,6,last_entry_off
);
2353 send_trans2_replies(req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2359 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2361 E_md4hash(lp_servicename(SNUM(conn
)),objid
);
2365 /****************************************************************************
2366 Reply to a TRANS2_QFSINFO (query filesystem info).
2367 ****************************************************************************/
2369 static void call_trans2qfsinfo(connection_struct
*conn
,
2370 struct smb_request
*req
,
2371 char **pparams
, int total_params
,
2372 char **ppdata
, int total_data
,
2373 unsigned int max_data_bytes
)
2375 char *pdata
, *end_data
;
2376 char *params
= *pparams
;
2380 const char *vname
= volume_label(SNUM(conn
));
2381 int snum
= SNUM(conn
);
2382 char *fstype
= lp_fstype(SNUM(conn
));
2385 if (total_params
< 2) {
2386 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2390 info_level
= SVAL(params
,0);
2393 (conn
->encrypt_level
== Required
&& SVAL(req
->inbuf
,4) != 0x45FF )) {
2394 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2395 DEBUG(0,("call_trans2qfsinfo: encryption required "
2396 "and info level 0x%x sent.\n",
2397 (unsigned int)info_level
));
2398 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2403 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2405 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2406 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2407 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
2411 *ppdata
= (char *)SMB_REALLOC(
2412 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2413 if (*ppdata
== NULL
) {
2414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2419 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2420 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2422 switch (info_level
) {
2423 case SMB_INFO_ALLOCATION
:
2425 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2427 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2428 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2432 block_size
= lp_block_size(snum
);
2433 if (bsize
< block_size
) {
2434 SMB_BIG_UINT factor
= block_size
/bsize
;
2439 if (bsize
> block_size
) {
2440 SMB_BIG_UINT factor
= bsize
/block_size
;
2445 bytes_per_sector
= 512;
2446 sectors_per_unit
= bsize
/bytes_per_sector
;
2448 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2449 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2450 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2452 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2453 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2454 SIVAL(pdata
,l1_cUnit
,dsize
);
2455 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2456 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2460 case SMB_INFO_VOLUME
:
2461 /* Return volume name */
2463 * Add volume serial number - hash of a combination of
2464 * the called hostname and the service name.
2466 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2468 * Win2k3 and previous mess this up by sending a name length
2469 * one byte short. I believe only older clients (OS/2 Win9x) use
2470 * this call so try fixing this by adding a terminating null to
2471 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2475 pdata
+l2_vol_szVolLabel
, vname
,
2476 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2477 STR_NOALIGN
|STR_TERMINATE
);
2478 SCVAL(pdata
,l2_vol_cch
,len
);
2479 data_len
= l2_vol_szVolLabel
+ len
;
2480 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2481 (unsigned)st
.st_ctime
, len
, vname
));
2484 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2485 case SMB_FS_ATTRIBUTE_INFORMATION
:
2488 #if defined(HAVE_SYS_QUOTAS)
2489 quota_flag
= FILE_VOLUME_QUOTAS
;
2492 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2493 (lp_nt_acl_support(SNUM(conn
)) ? FILE_PERSISTENT_ACLS
: 0)|
2494 FILE_SUPPORTS_OBJECT_IDS
|
2495 FILE_UNICODE_ON_DISK
|
2496 quota_flag
); /* FS ATTRIBUTES */
2498 SIVAL(pdata
,4,255); /* Max filename component length */
2499 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2500 and will think we can't do long filenames */
2501 len
= srvstr_push(pdata
, req
->flags2
, pdata
+12, fstype
,
2502 PTR_DIFF(end_data
, pdata
+12),
2505 data_len
= 12 + len
;
2508 case SMB_QUERY_FS_LABEL_INFO
:
2509 case SMB_FS_LABEL_INFORMATION
:
2510 len
= srvstr_push(pdata
, req
->flags2
, pdata
+4, vname
,
2511 PTR_DIFF(end_data
, pdata
+4), 0);
2516 case SMB_QUERY_FS_VOLUME_INFO
:
2517 case SMB_FS_VOLUME_INFORMATION
:
2520 * Add volume serial number - hash of a combination of
2521 * the called hostname and the service name.
2523 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2524 (str_checksum(get_local_machine_name())<<16));
2526 /* Max label len is 32 characters. */
2527 len
= srvstr_push(pdata
, req
->flags2
, pdata
+18, vname
,
2528 PTR_DIFF(end_data
, pdata
+18),
2530 SIVAL(pdata
,12,len
);
2533 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2534 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2537 case SMB_QUERY_FS_SIZE_INFO
:
2538 case SMB_FS_SIZE_INFORMATION
:
2540 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2542 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2543 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2546 block_size
= lp_block_size(snum
);
2547 if (bsize
< block_size
) {
2548 SMB_BIG_UINT factor
= block_size
/bsize
;
2553 if (bsize
> block_size
) {
2554 SMB_BIG_UINT factor
= bsize
/block_size
;
2559 bytes_per_sector
= 512;
2560 sectors_per_unit
= bsize
/bytes_per_sector
;
2561 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2562 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2563 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2564 SBIG_UINT(pdata
,0,dsize
);
2565 SBIG_UINT(pdata
,8,dfree
);
2566 SIVAL(pdata
,16,sectors_per_unit
);
2567 SIVAL(pdata
,20,bytes_per_sector
);
2571 case SMB_FS_FULL_SIZE_INFORMATION
:
2573 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2575 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2576 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
2579 block_size
= lp_block_size(snum
);
2580 if (bsize
< block_size
) {
2581 SMB_BIG_UINT factor
= block_size
/bsize
;
2586 if (bsize
> block_size
) {
2587 SMB_BIG_UINT factor
= bsize
/block_size
;
2592 bytes_per_sector
= 512;
2593 sectors_per_unit
= bsize
/bytes_per_sector
;
2594 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2595 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2596 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2597 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2598 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2599 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2600 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2601 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2605 case SMB_QUERY_FS_DEVICE_INFO
:
2606 case SMB_FS_DEVICE_INFORMATION
:
2608 SIVAL(pdata
,0,0); /* dev type */
2609 SIVAL(pdata
,4,0); /* characteristics */
2612 #ifdef HAVE_SYS_QUOTAS
2613 case SMB_FS_QUOTA_INFORMATION
:
2615 * what we have to send --metze:
2617 * Unknown1: 24 NULL bytes
2618 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2619 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2620 * Quota Flags: 2 byte :
2621 * Unknown3: 6 NULL bytes
2625 * details for Quota Flags:
2627 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2628 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2629 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2630 * 0x0001 Enable Quotas: enable quota for this fs
2634 /* we need to fake up a fsp here,
2635 * because its not send in this call
2638 SMB_NTQUOTA_STRUCT quotas
;
2641 ZERO_STRUCT(quotas
);
2647 if (current_user
.ut
.uid
!= 0) {
2648 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2649 lp_servicename(SNUM(conn
)),conn
->user
));
2650 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
2654 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2655 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2656 reply_doserror(req
, ERRSRV
, ERRerror
);
2662 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2664 /* Unknown1 24 NULL bytes*/
2665 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2666 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2667 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2669 /* Default Soft Quota 8 bytes */
2670 SBIG_UINT(pdata
,24,quotas
.softlim
);
2672 /* Default Hard Quota 8 bytes */
2673 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2675 /* Quota flag 2 bytes */
2676 SSVAL(pdata
,40,quotas
.qflags
);
2678 /* Unknown3 6 NULL bytes */
2684 #endif /* HAVE_SYS_QUOTAS */
2685 case SMB_FS_OBJECTID_INFORMATION
:
2687 unsigned char objid
[16];
2688 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2694 * Query the version and capabilities of the CIFS UNIX extensions
2698 case SMB_QUERY_CIFS_UNIX_INFO
:
2700 bool large_write
= lp_min_receive_file_size() &&
2701 !srv_is_signing_active();
2702 bool large_read
= !srv_is_signing_active();
2703 int encrypt_caps
= 0;
2705 if (!lp_unix_extensions()) {
2706 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2710 switch (conn
->encrypt_level
) {
2716 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2719 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2720 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2721 large_write
= false;
2727 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2728 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2730 /* We have POSIX ACLs, pathname, encryption,
2731 * large read/write, and locking capability. */
2733 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2734 CIFS_UNIX_POSIX_ACLS_CAP
|
2735 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2736 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2737 CIFS_UNIX_EXTATTR_CAP
|
2738 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2740 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2742 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2746 case SMB_QUERY_POSIX_FS_INFO
:
2749 vfs_statvfs_struct svfs
;
2751 if (!lp_unix_extensions()) {
2752 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2756 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2760 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2761 SIVAL(pdata
,4,svfs
.BlockSize
);
2762 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2763 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2764 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2765 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2766 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2767 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2768 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2770 } else if (rc
== EOPNOTSUPP
) {
2771 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2773 #endif /* EOPNOTSUPP */
2775 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2776 reply_doserror(req
, ERRSRV
, ERRerror
);
2782 case SMB_QUERY_POSIX_WHOAMI
:
2788 if (!lp_unix_extensions()) {
2789 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2793 if (max_data_bytes
< 40) {
2794 reply_nterror(req
, NT_STATUS_BUFFER_TOO_SMALL
);
2798 /* We ARE guest if global_sid_Builtin_Guests is
2799 * in our list of SIDs.
2801 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
2802 current_user
.nt_user_token
)) {
2803 flags
|= SMB_WHOAMI_GUEST
;
2806 /* We are NOT guest if global_sid_Authenticated_Users
2807 * is in our list of SIDs.
2809 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
2810 current_user
.nt_user_token
)) {
2811 flags
&= ~SMB_WHOAMI_GUEST
;
2814 /* NOTE: 8 bytes for UID/GID, irrespective of native
2815 * platform size. This matches
2816 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2818 data_len
= 4 /* flags */
2825 + 4 /* pad/reserved */
2826 + (current_user
.ut
.ngroups
* 8)
2828 + (current_user
.nt_user_token
->num_sids
*
2832 SIVAL(pdata
, 0, flags
);
2833 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2834 SBIG_UINT(pdata
, 8, (SMB_BIG_UINT
)current_user
.ut
.uid
);
2835 SBIG_UINT(pdata
, 16, (SMB_BIG_UINT
)current_user
.ut
.gid
);
2838 if (data_len
>= max_data_bytes
) {
2839 /* Potential overflow, skip the GIDs and SIDs. */
2841 SIVAL(pdata
, 24, 0); /* num_groups */
2842 SIVAL(pdata
, 28, 0); /* num_sids */
2843 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2844 SIVAL(pdata
, 36, 0); /* reserved */
2850 SIVAL(pdata
, 24, current_user
.ut
.ngroups
);
2852 current_user
.nt_user_token
->num_sids
);
2854 /* We walk the SID list twice, but this call is fairly
2855 * infrequent, and I don't expect that it's performance
2856 * sensitive -- jpeach
2858 for (i
= 0, sid_bytes
= 0;
2859 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
2860 sid_bytes
+= ndr_size_dom_sid(
2861 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
2864 /* SID list byte count */
2865 SIVAL(pdata
, 32, sid_bytes
);
2867 /* 4 bytes pad/reserved - must be zero */
2868 SIVAL(pdata
, 36, 0);
2872 for (i
= 0; i
< current_user
.ut
.ngroups
; ++i
) {
2873 SBIG_UINT(pdata
, data_len
,
2874 (SMB_BIG_UINT
)current_user
.ut
.groups
[i
]);
2880 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
2881 int sid_len
= ndr_size_dom_sid(
2882 ¤t_user
.nt_user_token
->user_sids
[i
], 0);
2884 sid_linearize(pdata
+ data_len
, sid_len
,
2885 ¤t_user
.nt_user_token
->user_sids
[i
]);
2886 data_len
+= sid_len
;
2892 case SMB_MAC_QUERY_FS_INFO
:
2894 * Thursby MAC extension... ONLY on NTFS filesystems
2895 * once we do streams then we don't need this
2897 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2899 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2904 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2909 send_trans2_replies(req
, params
, 0, pdata
, data_len
,
2912 DEBUG( 4, ( "%s info_level = %d\n",
2913 smb_fn_name(CVAL(req
->inbuf
,smb_com
)), info_level
) );
2918 /****************************************************************************
2919 Reply to a TRANS2_SETFSINFO (set filesystem info).
2920 ****************************************************************************/
2922 static void call_trans2setfsinfo(connection_struct
*conn
,
2923 struct smb_request
*req
,
2924 char **pparams
, int total_params
,
2925 char **ppdata
, int total_data
,
2926 unsigned int max_data_bytes
)
2928 char *pdata
= *ppdata
;
2929 char *params
= *pparams
;
2932 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
2935 if (total_params
< 4) {
2936 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2938 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2942 info_level
= SVAL(params
,2);
2945 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
2946 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
2947 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2948 "info level (0x%x) on IPC$.\n",
2949 (unsigned int)info_level
));
2950 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2955 if (conn
->encrypt_level
== Required
&& SVAL(req
->inbuf
,4) != 0x45FF ) {
2956 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
2957 DEBUG(0,("call_trans2setfsinfo: encryption required "
2958 "and info level 0x%x sent.\n",
2959 (unsigned int)info_level
));
2960 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2965 switch(info_level
) {
2966 case SMB_SET_CIFS_UNIX_INFO
:
2968 uint16 client_unix_major
;
2969 uint16 client_unix_minor
;
2970 uint32 client_unix_cap_low
;
2971 uint32 client_unix_cap_high
;
2973 if (!lp_unix_extensions()) {
2975 NT_STATUS_INVALID_LEVEL
);
2979 /* There should be 12 bytes of capabilities set. */
2980 if (total_data
< 8) {
2983 NT_STATUS_INVALID_PARAMETER
);
2986 client_unix_major
= SVAL(pdata
,0);
2987 client_unix_minor
= SVAL(pdata
,2);
2988 client_unix_cap_low
= IVAL(pdata
,4);
2989 client_unix_cap_high
= IVAL(pdata
,8);
2990 /* Just print these values for now. */
2991 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2992 cap_low = 0x%x, cap_high = 0x%x\n",
2993 (unsigned int)client_unix_major
,
2994 (unsigned int)client_unix_minor
,
2995 (unsigned int)client_unix_cap_low
,
2996 (unsigned int)client_unix_cap_high
));
2998 /* Here is where we must switch to posix pathname processing... */
2999 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3000 lp_set_posix_pathnames();
3001 mangle_change_to_posix();
3004 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3005 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3006 /* Client that knows how to do posix locks,
3007 * but not posix open/mkdir operations. Set a
3008 * default type for read/write checks. */
3010 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3016 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3019 size_t param_len
= 0;
3020 size_t data_len
= total_data
;
3022 if (!lp_unix_extensions()) {
3025 NT_STATUS_INVALID_LEVEL
);
3029 if (lp_smb_encrypt(SNUM(conn
)) == false) {
3032 NT_STATUS_NOT_SUPPORTED
);
3036 DEBUG( 4,("call_trans2setfsinfo: "
3037 "request transport encrption.\n"));
3039 status
= srv_request_encryption_setup(conn
,
3040 (unsigned char **)ppdata
,
3042 (unsigned char **)pparams
,
3045 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3046 !NT_STATUS_IS_OK(status
)) {
3047 reply_nterror(req
, status
);
3051 send_trans2_replies(req
,
3058 if (NT_STATUS_IS_OK(status
)) {
3059 /* Server-side transport
3060 * encryption is now *on*. */
3061 status
= srv_encryption_start(conn
);
3062 if (!NT_STATUS_IS_OK(status
)) {
3063 exit_server_cleanly(
3064 "Failure in setting "
3065 "up encrypted transport");
3071 case SMB_FS_QUOTA_INFORMATION
:
3073 files_struct
*fsp
= NULL
;
3074 SMB_NTQUOTA_STRUCT quotas
;
3076 ZERO_STRUCT(quotas
);
3079 if ((current_user
.ut
.uid
!= 0)||!CAN_WRITE(conn
)) {
3080 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3081 lp_servicename(SNUM(conn
)),conn
->user
));
3082 reply_doserror(req
, ERRSRV
, ERRaccess
);
3086 /* note: normaly there're 48 bytes,
3087 * but we didn't use the last 6 bytes for now
3090 fsp
= file_fsp(SVAL(params
,0));
3091 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
3092 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3094 req
, NT_STATUS_INVALID_HANDLE
);
3098 if (total_data
< 42) {
3099 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3103 NT_STATUS_INVALID_PARAMETER
);
3107 /* unknown_1 24 NULL bytes in pdata*/
3109 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3110 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
3111 #ifdef LARGE_SMB_OFF_T
3112 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
3113 #else /* LARGE_SMB_OFF_T */
3114 if ((IVAL(pdata
,28) != 0)&&
3115 ((quotas
.softlim
!= 0xFFFFFFFF)||
3116 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
3117 /* more than 32 bits? */
3120 NT_STATUS_INVALID_PARAMETER
);
3123 #endif /* LARGE_SMB_OFF_T */
3125 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3126 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
3127 #ifdef LARGE_SMB_OFF_T
3128 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
3129 #else /* LARGE_SMB_OFF_T */
3130 if ((IVAL(pdata
,36) != 0)&&
3131 ((quotas
.hardlim
!= 0xFFFFFFFF)||
3132 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
3133 /* more than 32 bits? */
3136 NT_STATUS_INVALID_PARAMETER
);
3139 #endif /* LARGE_SMB_OFF_T */
3141 /* quota_flags 2 bytes **/
3142 quotas
.qflags
= SVAL(pdata
,40);
3144 /* unknown_2 6 NULL bytes follow*/
3146 /* now set the quotas */
3147 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3148 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
3149 reply_doserror(req
, ERRSRV
, ERRerror
);
3156 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3158 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3164 * sending this reply works fine,
3165 * but I'm not sure it's the same
3166 * like windows do...
3169 reply_outbuf(req
, 10, 0);
3172 #if defined(HAVE_POSIX_ACLS)
3173 /****************************************************************************
3174 Utility function to count the number of entries in a POSIX acl.
3175 ****************************************************************************/
3177 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3179 unsigned int ace_count
= 0;
3180 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3181 SMB_ACL_ENTRY_T entry
;
3183 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3185 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3186 entry_id
= SMB_ACL_NEXT_ENTRY
;
3193 /****************************************************************************
3194 Utility function to marshall a POSIX acl into wire format.
3195 ****************************************************************************/
3197 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3199 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3200 SMB_ACL_ENTRY_T entry
;
3202 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
3203 SMB_ACL_TAG_T tagtype
;
3204 SMB_ACL_PERMSET_T permset
;
3205 unsigned char perms
= 0;
3206 unsigned int own_grp
;
3209 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3210 entry_id
= SMB_ACL_NEXT_ENTRY
;
3213 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
3214 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3218 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
3219 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3223 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3224 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3225 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3227 SCVAL(pdata
,1,perms
);
3230 case SMB_ACL_USER_OBJ
:
3231 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3232 own_grp
= (unsigned int)pst
->st_uid
;
3233 SIVAL(pdata
,2,own_grp
);
3238 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3240 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3243 own_grp
= (unsigned int)*puid
;
3244 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
3245 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3246 SIVAL(pdata
,2,own_grp
);
3250 case SMB_ACL_GROUP_OBJ
:
3251 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3252 own_grp
= (unsigned int)pst
->st_gid
;
3253 SIVAL(pdata
,2,own_grp
);
3258 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
3260 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3263 own_grp
= (unsigned int)*pgid
;
3264 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
3265 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3266 SIVAL(pdata
,2,own_grp
);
3271 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3272 SIVAL(pdata
,2,0xFFFFFFFF);
3273 SIVAL(pdata
,6,0xFFFFFFFF);
3276 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3277 SIVAL(pdata
,2,0xFFFFFFFF);
3278 SIVAL(pdata
,6,0xFFFFFFFF);
3281 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3284 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3291 /****************************************************************************
3292 Store the FILE_UNIX_BASIC info.
3293 ****************************************************************************/
3295 static char *store_file_unix_basic(connection_struct
*conn
,
3298 const SMB_STRUCT_STAT
*psbuf
)
3300 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3301 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3303 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3306 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3309 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3310 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3311 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3314 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3318 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3322 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3325 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3329 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3333 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3336 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3340 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3347 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3348 * the chflags(2) (or equivalent) flags.
3350 * XXX: this really should be behind the VFS interface. To do this, we would
3351 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3352 * Each VFS module could then implement its own mapping as appropriate for the
3353 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3355 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3359 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3363 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3367 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3371 { UF_HIDDEN
, EXT_HIDDEN
},
3374 /* Do not remove. We need to guarantee that this array has at least one
3375 * entry to build on HP-UX.
3381 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3382 uint32
*smb_fflags
, uint32
*smb_fmask
)
3384 #ifdef HAVE_STAT_ST_FLAGS
3387 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3388 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3389 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3390 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3393 #endif /* HAVE_STAT_ST_FLAGS */
3396 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3397 const uint32 smb_fflags
,
3398 const uint32 smb_fmask
,
3401 #ifdef HAVE_STAT_ST_FLAGS
3402 uint32 max_fmask
= 0;
3405 *stat_fflags
= psbuf
->st_flags
;
3407 /* For each flags requested in smb_fmask, check the state of the
3408 * corresponding flag in smb_fflags and set or clear the matching
3412 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3413 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3414 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3415 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3416 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3418 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3423 /* If smb_fmask is asking to set any bits that are not supported by
3424 * our flag mappings, we should fail.
3426 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3433 #endif /* HAVE_STAT_ST_FLAGS */
3437 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3438 * of file flags and birth (create) time.
3440 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3443 const SMB_STRUCT_STAT
*psbuf
)
3445 uint32 file_flags
= 0;
3446 uint32 flags_mask
= 0;
3448 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3450 /* Create (birth) time 64 bit */
3451 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3454 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3455 SIVAL(pdata
, 0, file_flags
); /* flags */
3456 SIVAL(pdata
, 4, flags_mask
); /* mask */
3462 /****************************************************************************
3463 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3464 ****************************************************************************/
3466 static void call_trans2qpipeinfo(connection_struct
*conn
,
3467 struct smb_request
*req
,
3468 unsigned int tran_call
,
3469 char **pparams
, int total_params
,
3470 char **ppdata
, int total_data
,
3471 unsigned int max_data_bytes
)
3473 char *params
= *pparams
;
3474 char *pdata
= *ppdata
;
3475 unsigned int data_size
= 0;
3476 unsigned int param_size
= 2;
3478 smb_np_struct
*p_pipe
= NULL
;
3481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3485 if (total_params
< 4) {
3486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3490 p_pipe
= get_rpc_pipe_p(SVAL(params
,0));
3491 if (p_pipe
== NULL
) {
3492 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3496 info_level
= SVAL(params
,2);
3498 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3499 if (*pparams
== NULL
) {
3500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3505 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3506 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3507 if (*ppdata
== NULL
) {
3508 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3513 switch (info_level
) {
3514 case SMB_FILE_STANDARD_INFORMATION
:
3516 SOFF_T(pdata
,0,4096LL);
3523 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3527 send_trans2_replies(req
, params
, param_size
, *ppdata
, data_size
,
3533 /****************************************************************************
3534 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3535 file name or file id).
3536 ****************************************************************************/
3538 static void call_trans2qfilepathinfo(connection_struct
*conn
,
3539 struct smb_request
*req
,
3540 unsigned int tran_call
,
3541 char **pparams
, int total_params
,
3542 char **ppdata
, int total_data
,
3543 unsigned int max_data_bytes
)
3545 char *params
= *pparams
;
3546 char *pdata
= *ppdata
;
3547 char *dstart
, *dend
;
3551 SMB_OFF_T file_size
=0;
3552 SMB_BIG_UINT allocation_size
=0;
3553 unsigned int data_size
= 0;
3554 unsigned int param_size
= 2;
3555 SMB_STRUCT_STAT sbuf
;
3556 char *dos_fname
= NULL
;
3562 bool delete_pending
= False
;
3564 time_t create_time
, mtime
, atime
;
3565 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3566 files_struct
*fsp
= NULL
;
3567 struct file_id fileid
;
3568 struct ea_list
*ea_list
= NULL
;
3569 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3570 char *lock_data
= NULL
;
3571 TALLOC_CTX
*ctx
= talloc_tos();
3574 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3580 if (tran_call
== TRANSACT2_QFILEINFO
) {
3581 if (total_params
< 4) {
3582 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3587 call_trans2qpipeinfo(conn
, req
, tran_call
,
3588 pparams
, total_params
,
3594 fsp
= file_fsp(SVAL(params
,0));
3595 info_level
= SVAL(params
,2);
3597 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3599 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3600 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3604 /* Initial check for valid fsp ptr. */
3605 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
3609 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
3611 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3615 if(fsp
->fake_file_handle
) {
3617 * This is actually for the QUOTA_FAKE_FILE --metze
3620 /* We know this name is ok, it's already passed the checks. */
3622 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3624 * This is actually a QFILEINFO on a directory
3625 * handle (returned from an NT SMB). NT5.0 seems
3626 * to do this call. JRA.
3629 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3630 /* Always do lstat for UNIX calls. */
3631 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3632 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3633 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
3636 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3637 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3638 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3642 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3643 delete_pending
= get_delete_on_close_flag(fileid
);
3646 * Original code - this is an open file.
3648 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3652 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&sbuf
) != 0) {
3653 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3654 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
3657 pos
= fsp
->fh
->position_information
;
3658 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3659 delete_pending
= get_delete_on_close_flag(fileid
);
3660 access_mask
= fsp
->access_mask
;
3664 NTSTATUS status
= NT_STATUS_OK
;
3667 if (total_params
< 7) {
3668 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3672 info_level
= SVAL(params
,0);
3674 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3676 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3677 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3681 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
3683 STR_TERMINATE
, &status
);
3684 if (!NT_STATUS_IS_OK(status
)) {
3685 reply_nterror(req
, status
);
3689 status
= resolve_dfspath(ctx
,
3691 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3694 if (!NT_STATUS_IS_OK(status
)) {
3695 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3696 reply_botherror(req
,
3697 NT_STATUS_PATH_NOT_COVERED
,
3698 ERRSRV
, ERRbadpath
);
3700 reply_nterror(req
, status
);
3704 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
3705 if (!NT_STATUS_IS_OK(status
)) {
3706 reply_nterror(req
, status
);
3709 status
= check_name(conn
, fname
);
3710 if (!NT_STATUS_IS_OK(status
)) {
3711 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3712 reply_nterror(req
, status
);
3716 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3717 /* Always do lstat for UNIX calls. */
3718 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3719 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3720 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3723 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
3724 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3725 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
3729 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3730 delete_pending
= get_delete_on_close_flag(fileid
);
3731 if (delete_pending
) {
3732 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
3737 nlink
= sbuf
.st_nlink
;
3739 if ((nlink
> 0) && S_ISDIR(sbuf
.st_mode
)) {
3740 /* NTFS does not seem to count ".." */
3744 if ((nlink
> 0) && delete_pending
) {
3748 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3749 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3753 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3754 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
3756 p
= strrchr_m(fname
,'/');
3762 mode
= dos_mode(conn
,fname
,&sbuf
);
3764 mode
= FILE_ATTRIBUTE_NORMAL
;
3766 fullpathname
= fname
;
3768 file_size
= get_file_size(sbuf
);
3770 /* Pull out any data sent here before we realloc. */
3771 switch (info_level
) {
3772 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3774 /* Pull any EA list from the data portion. */
3777 if (total_data
< 4) {
3779 req
, NT_STATUS_INVALID_PARAMETER
);
3782 ea_size
= IVAL(pdata
,0);
3784 if (total_data
> 0 && ea_size
!= total_data
) {
3785 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3786 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3788 req
, NT_STATUS_INVALID_PARAMETER
);
3792 if (!lp_ea_support(SNUM(conn
))) {
3793 reply_doserror(req
, ERRDOS
,
3794 ERReasnotsupported
);
3798 /* Pull out the list of names. */
3799 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3802 req
, NT_STATUS_INVALID_PARAMETER
);
3808 case SMB_QUERY_POSIX_LOCK
:
3810 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
3811 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
3815 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
3817 req
, NT_STATUS_INVALID_PARAMETER
);
3821 /* Copy the lock range data. */
3822 lock_data
= (char *)TALLOC_MEMDUP(
3823 ctx
, pdata
, total_data
);
3825 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3833 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3834 if (*pparams
== NULL
) {
3835 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3840 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3841 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3842 if (*ppdata
== NULL
) {
3843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3848 dend
= dstart
+ data_size
- 1;
3850 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
3851 mtime_ts
= get_mtimespec(&sbuf
);
3852 atime_ts
= get_atimespec(&sbuf
);
3854 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
3857 if (!null_timespec(fsp
->pending_modtime
)) {
3858 /* the pending modtime overrides the current modtime */
3859 mtime_ts
= fsp
->pending_modtime
;
3863 /* Do we have this path open ? */
3864 fileid
= vfs_file_id_from_sbuf(conn
, &sbuf
);
3865 fsp1
= file_find_di_first(fileid
);
3866 if (fsp1
&& !null_timespec(fsp1
->pending_modtime
)) {
3867 /* the pending modtime overrides the current modtime */
3868 mtime_ts
= fsp1
->pending_modtime
;
3870 if (fsp1
&& fsp1
->initial_allocation_size
) {
3871 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
3875 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3876 dos_filetime_timespec(&create_time_ts
);
3877 dos_filetime_timespec(&mtime_ts
);
3878 dos_filetime_timespec(&atime_ts
);
3881 create_time
= convert_timespec_to_time_t(create_time_ts
);
3882 mtime
= convert_timespec_to_time_t(mtime_ts
);
3883 atime
= convert_timespec_to_time_t(atime_ts
);
3885 /* NT expects the name to be in an exact form of the *full*
3886 filename. See the trans2 torture test */
3887 if (ISDOT(base_name
)) {
3888 dos_fname
= talloc_strdup(ctx
, "\\");
3890 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3894 dos_fname
= talloc_asprintf(ctx
,
3898 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3901 string_replace(dos_fname
, '/', '\\');
3904 switch (info_level
) {
3905 case SMB_INFO_STANDARD
:
3906 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3908 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3909 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3910 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3911 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
3912 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
3913 SSVAL(pdata
,l1_attrFile
,mode
);
3916 case SMB_INFO_QUERY_EA_SIZE
:
3918 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3919 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3921 srv_put_dos_date2(pdata
,0,create_time
);
3922 srv_put_dos_date2(pdata
,4,atime
);
3923 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3924 SIVAL(pdata
,12,(uint32
)file_size
);
3925 SIVAL(pdata
,16,(uint32
)allocation_size
);
3926 SSVAL(pdata
,20,mode
);
3927 SIVAL(pdata
,22,ea_size
);
3931 case SMB_INFO_IS_NAME_VALID
:
3932 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3933 if (tran_call
== TRANSACT2_QFILEINFO
) {
3934 /* os/2 needs this ? really ?*/
3935 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
3942 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3944 size_t total_ea_len
= 0;
3945 struct ea_list
*ea_file_list
= NULL
;
3947 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3949 ea_file_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
3950 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3952 if (!ea_list
|| (total_ea_len
> data_size
)) {
3954 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3958 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
3962 case SMB_INFO_QUERY_ALL_EAS
:
3964 /* We have data_size bytes to put EA's into. */
3965 size_t total_ea_len
= 0;
3967 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3969 ea_list
= get_ea_list_from_file(ctx
, conn
, fsp
, fname
, &total_ea_len
);
3970 if (!ea_list
|| (total_ea_len
> data_size
)) {
3972 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3976 data_size
= fill_ea_buffer(ctx
, pdata
, data_size
, conn
, ea_list
);
3980 case SMB_FILE_BASIC_INFORMATION
:
3981 case SMB_QUERY_FILE_BASIC_INFO
:
3983 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3984 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3985 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3991 put_long_date_timespec(pdata
,create_time_ts
);
3992 put_long_date_timespec(pdata
+8,atime_ts
);
3993 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
3994 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
3995 SIVAL(pdata
,32,mode
);
3997 DEBUG(5,("SMB_QFBI - "));
3998 DEBUG(5,("create: %s ", ctime(&create_time
)));
3999 DEBUG(5,("access: %s ", ctime(&atime
)));
4000 DEBUG(5,("write: %s ", ctime(&mtime
)));
4001 DEBUG(5,("change: %s ", ctime(&mtime
)));
4002 DEBUG(5,("mode: %x\n", mode
));
4005 case SMB_FILE_STANDARD_INFORMATION
:
4006 case SMB_QUERY_FILE_STANDARD_INFO
:
4008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4010 SOFF_T(pdata
,0,allocation_size
);
4011 SOFF_T(pdata
,8,file_size
);
4012 SIVAL(pdata
,16,nlink
);
4013 SCVAL(pdata
,20,delete_pending
?1:0);
4014 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4015 SSVAL(pdata
,22,0); /* Padding. */
4018 case SMB_FILE_EA_INFORMATION
:
4019 case SMB_QUERY_FILE_EA_INFO
:
4021 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4022 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4024 SIVAL(pdata
,0,ea_size
);
4028 /* Get the 8.3 name - used if NT SMB was negotiated. */
4029 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4030 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4032 char mangled_name
[13];
4033 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4034 if (!name_to_8_3(base_name
,mangled_name
,
4035 True
,conn
->params
)) {
4038 NT_STATUS_NO_MEMORY
);
4040 len
= srvstr_push(dstart
, req
->flags2
,
4041 pdata
+4, mangled_name
,
4042 PTR_DIFF(dend
, pdata
+4),
4044 data_size
= 4 + len
;
4049 case SMB_QUERY_FILE_NAME_INFO
:
4051 this must be *exactly* right for ACLs on mapped drives to work
4053 len
= srvstr_push(dstart
, req
->flags2
,
4055 PTR_DIFF(dend
, pdata
+4),
4057 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4058 data_size
= 4 + len
;
4062 case SMB_FILE_ALLOCATION_INFORMATION
:
4063 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4064 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4066 SOFF_T(pdata
,0,allocation_size
);
4069 case SMB_FILE_END_OF_FILE_INFORMATION
:
4070 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4073 SOFF_T(pdata
,0,file_size
);
4076 case SMB_QUERY_FILE_ALL_INFO
:
4077 case SMB_FILE_ALL_INFORMATION
:
4079 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
4080 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4081 put_long_date_timespec(pdata
,create_time_ts
);
4082 put_long_date_timespec(pdata
+8,atime_ts
);
4083 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4084 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4085 SIVAL(pdata
,32,mode
);
4086 SIVAL(pdata
,36,0); /* padding. */
4088 SOFF_T(pdata
,0,allocation_size
);
4089 SOFF_T(pdata
,8,file_size
);
4090 SIVAL(pdata
,16,nlink
);
4091 SCVAL(pdata
,20,delete_pending
);
4092 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
4095 SIVAL(pdata
,0,ea_size
);
4096 pdata
+= 4; /* EA info */
4097 len
= srvstr_push(dstart
, req
->flags2
,
4099 PTR_DIFF(dend
, pdata
+4),
4103 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4106 case SMB_FILE_INTERNAL_INFORMATION
:
4107 /* This should be an index number - looks like
4110 I think this causes us to fail the IFSKIT
4111 BasicFileInformationTest. -tpot */
4113 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4114 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
4115 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
4119 case SMB_FILE_ACCESS_INFORMATION
:
4120 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4121 SIVAL(pdata
,0,access_mask
);
4125 case SMB_FILE_NAME_INFORMATION
:
4126 /* Pathname with leading '\'. */
4129 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4130 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4131 SIVAL(pdata
,0,byte_len
);
4132 data_size
= 4 + byte_len
;
4136 case SMB_FILE_DISPOSITION_INFORMATION
:
4137 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4139 SCVAL(pdata
,0,delete_pending
);
4142 case SMB_FILE_POSITION_INFORMATION
:
4143 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4145 SOFF_T(pdata
,0,pos
);
4148 case SMB_FILE_MODE_INFORMATION
:
4149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4150 SIVAL(pdata
,0,mode
);
4154 case SMB_FILE_ALIGNMENT_INFORMATION
:
4155 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4156 SIVAL(pdata
,0,0); /* No alignment needed. */
4162 * NT4 server just returns "invalid query" to this - if we try to answer
4163 * it then NTws gets a BSOD! (tridge).
4164 * W2K seems to want this. JRA.
4166 case SMB_QUERY_FILE_STREAM_INFO
:
4168 case SMB_FILE_STREAM_INFORMATION
:
4169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4173 size_t byte_len
= dos_PutUniCode(pdata
+24,"::$DATA", (size_t)0xE, False
);
4174 SIVAL(pdata
,0,0); /* ??? */
4175 SIVAL(pdata
,4,byte_len
); /* Byte length of unicode string ::$DATA */
4176 SOFF_T(pdata
,8,file_size
);
4177 SOFF_T(pdata
,16,allocation_size
);
4178 data_size
= 24 + byte_len
;
4182 case SMB_QUERY_COMPRESSION_INFO
:
4183 case SMB_FILE_COMPRESSION_INFORMATION
:
4184 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4185 SOFF_T(pdata
,0,file_size
);
4186 SIVAL(pdata
,8,0); /* ??? */
4187 SIVAL(pdata
,12,0); /* ??? */
4191 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4192 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4193 put_long_date_timespec(pdata
,create_time_ts
);
4194 put_long_date_timespec(pdata
+8,atime_ts
);
4195 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
4196 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
4197 SOFF_T(pdata
,32,allocation_size
);
4198 SOFF_T(pdata
,40,file_size
);
4199 SIVAL(pdata
,48,mode
);
4200 SIVAL(pdata
,52,0); /* ??? */
4204 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4205 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4206 SIVAL(pdata
,0,mode
);
4212 * CIFS UNIX Extensions.
4215 case SMB_QUERY_FILE_UNIX_BASIC
:
4217 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
4218 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4222 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4224 for (i
=0; i
<100; i
++)
4225 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4231 case SMB_QUERY_FILE_UNIX_INFO2
:
4233 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
4234 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4238 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4240 for (i
=0; i
<100; i
++)
4241 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4247 case SMB_QUERY_FILE_UNIX_LINK
:
4249 char *buffer
= TALLOC_ARRAY(ctx
, char, PATH_MAX
+1);
4252 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4258 if(!S_ISLNK(sbuf
.st_mode
)) {
4259 reply_unixerror(req
, ERRSRV
,
4264 reply_unixerror(req
, ERRDOS
, ERRbadlink
);
4267 len
= SMB_VFS_READLINK(conn
,fullpathname
,
4270 reply_unixerror(req
, ERRDOS
,
4275 len
= srvstr_push(dstart
, req
->flags2
,
4277 PTR_DIFF(dend
, pdata
),
4280 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4285 #if defined(HAVE_POSIX_ACLS)
4286 case SMB_QUERY_POSIX_ACL
:
4288 SMB_ACL_T file_acl
= NULL
;
4289 SMB_ACL_T def_acl
= NULL
;
4290 uint16 num_file_acls
= 0;
4291 uint16 num_def_acls
= 0;
4293 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
4294 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, fsp
->fh
->fd
);
4296 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
4299 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4300 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4304 NT_STATUS_NOT_IMPLEMENTED
);
4308 if (S_ISDIR(sbuf
.st_mode
)) {
4309 if (fsp
&& fsp
->is_directory
) {
4310 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
4312 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
4314 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4317 num_file_acls
= count_acl_entries(conn
, file_acl
);
4318 num_def_acls
= count_acl_entries(conn
, def_acl
);
4320 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4321 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4323 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4324 SMB_POSIX_ACL_HEADER_SIZE
) ));
4326 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4329 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4333 NT_STATUS_BUFFER_TOO_SMALL
);
4337 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4338 SSVAL(pdata
,2,num_file_acls
);
4339 SSVAL(pdata
,4,num_def_acls
);
4340 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
4342 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4345 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4348 req
, NT_STATUS_INTERNAL_ERROR
);
4351 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
4353 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4356 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4360 NT_STATUS_INTERNAL_ERROR
);
4365 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
4368 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
4370 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
4376 case SMB_QUERY_POSIX_LOCK
:
4378 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
4380 SMB_BIG_UINT offset
;
4382 enum brl_type lock_type
;
4384 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4386 req
, NT_STATUS_INVALID_PARAMETER
);
4390 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4391 case POSIX_LOCK_TYPE_READ
:
4392 lock_type
= READ_LOCK
;
4394 case POSIX_LOCK_TYPE_WRITE
:
4395 lock_type
= WRITE_LOCK
;
4397 case POSIX_LOCK_TYPE_UNLOCK
:
4399 /* There's no point in asking for an unlock... */
4402 NT_STATUS_INVALID_PARAMETER
);
4406 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4407 #if defined(HAVE_LONGLONG)
4408 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4409 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4410 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4411 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4412 #else /* HAVE_LONGLONG */
4413 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4414 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4415 #endif /* HAVE_LONGLONG */
4417 status
= query_lock(fsp
,
4424 if (ERROR_WAS_LOCK_DENIED(status
)) {
4425 /* Here we need to report who has it locked... */
4426 data_size
= POSIX_LOCK_DATA_SIZE
;
4428 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4429 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4430 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
4431 #if defined(HAVE_LONGLONG)
4432 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
4433 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
4434 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
4435 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
4436 #else /* HAVE_LONGLONG */
4437 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4438 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4439 #endif /* HAVE_LONGLONG */
4441 } else if (NT_STATUS_IS_OK(status
)) {
4442 /* For success we just return a copy of what we sent
4443 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4444 data_size
= POSIX_LOCK_DATA_SIZE
;
4445 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4446 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4448 reply_nterror(req
, status
);
4455 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4459 send_trans2_replies(req
, params
, param_size
, *ppdata
, data_size
,
4465 /****************************************************************************
4466 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4468 ****************************************************************************/
4470 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4471 connection_struct
*conn
,
4472 const char *oldname_in
,
4473 const char *newname_in
)
4475 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4476 char *last_component_oldname
= NULL
;
4477 char *last_component_newname
= NULL
;
4478 char *oldname
= NULL
;
4479 char *newname
= NULL
;
4480 NTSTATUS status
= NT_STATUS_OK
;
4485 status
= unix_convert(ctx
, conn
, oldname_in
, False
, &oldname
,
4486 &last_component_oldname
, &sbuf1
);
4487 if (!NT_STATUS_IS_OK(status
)) {
4491 status
= check_name(conn
, oldname
);
4492 if (!NT_STATUS_IS_OK(status
)) {
4496 /* source must already exist. */
4497 if (!VALID_STAT(sbuf1
)) {
4498 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4501 status
= unix_convert(ctx
, conn
, newname_in
, False
, &newname
,
4502 &last_component_newname
, &sbuf2
);
4503 if (!NT_STATUS_IS_OK(status
)) {
4507 status
= check_name(conn
, newname
);
4508 if (!NT_STATUS_IS_OK(status
)) {
4512 /* Disallow if newname already exists. */
4513 if (VALID_STAT(sbuf2
)) {
4514 return NT_STATUS_OBJECT_NAME_COLLISION
;
4517 /* No links from a directory. */
4518 if (S_ISDIR(sbuf1
.st_mode
)) {
4519 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4522 /* Ensure this is within the share. */
4523 status
= check_reduced_name(conn
, oldname
);
4524 if (!NT_STATUS_IS_OK(status
)) {
4528 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4530 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4531 status
= map_nt_error_from_unix(errno
);
4532 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4533 nt_errstr(status
), newname
, oldname
));
4539 /****************************************************************************
4540 Deal with setting the time from any of the setfilepathinfo functions.
4541 ****************************************************************************/
4543 static NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4546 const SMB_STRUCT_STAT
*psbuf
,
4547 struct timespec ts
[2],
4548 bool setting_write_time
)
4551 FILE_NOTIFY_CHANGE_LAST_ACCESS
4552 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4554 if (!VALID_STAT(*psbuf
)) {
4555 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4558 /* get some defaults (no modifications) if any info is zero or -1. */
4559 if (null_timespec(ts
[0])) {
4560 ts
[0] = get_atimespec(psbuf
);
4561 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4564 if (null_timespec(ts
[1])) {
4565 ts
[1] = get_mtimespec(psbuf
);
4566 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4569 if (!setting_write_time
) {
4570 /* ts[1] comes from change time, not write time. */
4571 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4574 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4575 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4578 * Try and set the times of this file if
4579 * they are different from the current values.
4583 struct timespec mts
= get_mtimespec(psbuf
);
4584 struct timespec ats
= get_atimespec(psbuf
);
4585 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4586 return NT_STATUS_OK
;
4592 * This was a setfileinfo on an open file.
4593 * NT does this a lot. We also need to
4594 * set the time here, as it can be read by
4595 * FindFirst/FindNext and with the patch for bug #2045
4596 * in smbd/fileio.c it ensures that this timestamp is
4597 * kept sticky even after a write. We save the request
4598 * away and will set it on file close and after a write. JRA.
4601 if (!null_timespec(ts
[1])) {
4602 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4603 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4604 fsp_set_pending_modtime(fsp
, ts
[1]);
4608 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4610 if(file_ntimes(conn
, fname
, ts
)!=0) {
4611 return map_nt_error_from_unix(errno
);
4613 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4615 return NT_STATUS_OK
;
4618 /****************************************************************************
4619 Deal with setting the dosmode from any of the setfilepathinfo functions.
4620 ****************************************************************************/
4622 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4624 SMB_STRUCT_STAT
*psbuf
,
4627 if (!VALID_STAT(*psbuf
)) {
4628 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4632 if (S_ISDIR(psbuf
->st_mode
)) {
4639 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
4641 /* check the mode isn't different, before changing it */
4642 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
4644 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4645 fname
, (unsigned int)dosmode
));
4647 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, NULL
, false)) {
4648 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4649 fname
, strerror(errno
)));
4650 return map_nt_error_from_unix(errno
);
4653 return NT_STATUS_OK
;
4656 /****************************************************************************
4657 Deal with setting the size from any of the setfilepathinfo functions.
4658 ****************************************************************************/
4660 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4661 struct smb_request
*req
,
4664 SMB_STRUCT_STAT
*psbuf
,
4667 NTSTATUS status
= NT_STATUS_OK
;
4668 files_struct
*new_fsp
= NULL
;
4670 if (!VALID_STAT(*psbuf
)) {
4671 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4674 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
4676 if (size
== get_file_size(*psbuf
)) {
4677 return NT_STATUS_OK
;
4680 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4681 fname
, (double)size
));
4683 if (fsp
&& fsp
->fh
->fd
!= -1) {
4684 /* Handle based call. */
4685 if (vfs_set_filelen(fsp
, size
) == -1) {
4686 return map_nt_error_from_unix(errno
);
4688 return NT_STATUS_OK
;
4691 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
4693 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
4696 FILE_ATTRIBUTE_NORMAL
,
4697 FORCE_OPLOCK_BREAK_TO_NONE
,
4700 if (!NT_STATUS_IS_OK(status
)) {
4701 /* NB. We check for open_was_deferred in the caller. */
4705 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4706 status
= map_nt_error_from_unix(errno
);
4707 close_file(new_fsp
,NORMAL_CLOSE
);
4711 close_file(new_fsp
,NORMAL_CLOSE
);
4712 return NT_STATUS_OK
;
4715 /****************************************************************************
4716 Deal with SMB_INFO_SET_EA.
4717 ****************************************************************************/
4719 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4725 struct ea_list
*ea_list
= NULL
;
4726 TALLOC_CTX
*ctx
= NULL
;
4727 NTSTATUS status
= NT_STATUS_OK
;
4729 if (total_data
< 10) {
4731 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4732 length. They seem to have no effect. Bug #3212. JRA */
4734 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4735 /* We're done. We only get EA info in this call. */
4736 return NT_STATUS_OK
;
4739 return NT_STATUS_INVALID_PARAMETER
;
4742 if (IVAL(pdata
,0) > total_data
) {
4743 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4744 IVAL(pdata
,0), (unsigned int)total_data
));
4745 return NT_STATUS_INVALID_PARAMETER
;
4748 ctx
= talloc_init("SMB_INFO_SET_EA");
4750 return NT_STATUS_NO_MEMORY
;
4752 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4754 talloc_destroy(ctx
);
4755 return NT_STATUS_INVALID_PARAMETER
;
4757 status
= set_ea(conn
, fsp
, fname
, ea_list
);
4758 talloc_destroy(ctx
);
4763 /****************************************************************************
4764 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4765 ****************************************************************************/
4767 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4772 SMB_STRUCT_STAT
*psbuf
)
4774 NTSTATUS status
= NT_STATUS_OK
;
4775 bool delete_on_close
;
4778 if (total_data
< 1) {
4779 return NT_STATUS_INVALID_PARAMETER
;
4783 return NT_STATUS_INVALID_HANDLE
;
4786 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4787 dosmode
= dos_mode(conn
, fname
, psbuf
);
4789 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4790 "delete_on_close = %u\n",
4792 (unsigned int)dosmode
,
4793 (unsigned int)delete_on_close
));
4795 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
4797 if (!NT_STATUS_IS_OK(status
)) {
4801 /* The set is across all open files on this dev/inode pair. */
4802 if (!set_delete_on_close(fsp
, delete_on_close
, ¤t_user
.ut
)) {
4803 return NT_STATUS_ACCESS_DENIED
;
4805 return NT_STATUS_OK
;
4808 /****************************************************************************
4809 Deal with SMB_FILE_POSITION_INFORMATION.
4810 ****************************************************************************/
4812 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4817 SMB_BIG_UINT position_information
;
4819 if (total_data
< 8) {
4820 return NT_STATUS_INVALID_PARAMETER
;
4824 /* Ignore on pathname based set. */
4825 return NT_STATUS_OK
;
4828 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
4829 #ifdef LARGE_SMB_OFF_T
4830 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
4831 #else /* LARGE_SMB_OFF_T */
4832 if (IVAL(pdata
,4) != 0) {
4833 /* more than 32 bits? */
4834 return NT_STATUS_INVALID_PARAMETER
;
4836 #endif /* LARGE_SMB_OFF_T */
4838 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4839 fsp
->fsp_name
, (double)position_information
));
4840 fsp
->fh
->position_information
= position_information
;
4841 return NT_STATUS_OK
;
4844 /****************************************************************************
4845 Deal with SMB_FILE_MODE_INFORMATION.
4846 ****************************************************************************/
4848 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4854 if (total_data
< 4) {
4855 return NT_STATUS_INVALID_PARAMETER
;
4857 mode
= IVAL(pdata
,0);
4858 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4859 return NT_STATUS_INVALID_PARAMETER
;
4861 return NT_STATUS_OK
;
4864 /****************************************************************************
4865 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4866 ****************************************************************************/
4868 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
4869 struct smb_request
*req
,
4874 char *link_target
= NULL
;
4875 const char *newname
= fname
;
4876 NTSTATUS status
= NT_STATUS_OK
;
4877 TALLOC_CTX
*ctx
= talloc_tos();
4879 /* Set a symbolic link. */
4880 /* Don't allow this if follow links is false. */
4882 if (total_data
== 0) {
4883 return NT_STATUS_INVALID_PARAMETER
;
4886 if (!lp_symlinks(SNUM(conn
))) {
4887 return NT_STATUS_ACCESS_DENIED
;
4890 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
4891 total_data
, STR_TERMINATE
);
4894 return NT_STATUS_INVALID_PARAMETER
;
4897 /* !widelinks forces the target path to be within the share. */
4898 /* This means we can interpret the target as a pathname. */
4899 if (!lp_widelinks(SNUM(conn
))) {
4900 char *rel_name
= NULL
;
4901 char *last_dirp
= NULL
;
4903 if (*link_target
== '/') {
4904 /* No absolute paths allowed. */
4905 return NT_STATUS_ACCESS_DENIED
;
4907 rel_name
= talloc_strdup(ctx
,newname
);
4909 return NT_STATUS_NO_MEMORY
;
4911 last_dirp
= strrchr_m(rel_name
, '/');
4913 last_dirp
[1] = '\0';
4915 rel_name
= talloc_strdup(ctx
,"./");
4917 return NT_STATUS_NO_MEMORY
;
4920 rel_name
= talloc_asprintf_append(rel_name
,
4924 return NT_STATUS_NO_MEMORY
;
4927 status
= check_name(conn
, rel_name
);
4928 if (!NT_STATUS_IS_OK(status
)) {
4933 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4934 newname
, link_target
));
4936 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
4937 return map_nt_error_from_unix(errno
);
4940 return NT_STATUS_OK
;
4943 /****************************************************************************
4944 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4945 ****************************************************************************/
4947 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
4948 struct smb_request
*req
,
4949 const char *pdata
, int total_data
,
4952 char *oldname
= NULL
;
4953 TALLOC_CTX
*ctx
= talloc_tos();
4954 NTSTATUS status
= NT_STATUS_OK
;
4956 /* Set a hard link. */
4957 if (total_data
== 0) {
4958 return NT_STATUS_INVALID_PARAMETER
;
4961 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
4962 total_data
, STR_TERMINATE
, &status
);
4963 if (!NT_STATUS_IS_OK(status
)) {
4967 status
= resolve_dfspath(ctx
, conn
,
4968 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4971 if (!NT_STATUS_IS_OK(status
)) {
4975 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4978 return hardlink_internals(ctx
, conn
, oldname
, fname
);
4981 /****************************************************************************
4982 Deal with SMB_FILE_RENAME_INFORMATION.
4983 ****************************************************************************/
4985 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4986 struct smb_request
*req
,
4995 char *newname
= NULL
;
4996 char *base_name
= NULL
;
4997 bool dest_has_wcard
= False
;
4998 NTSTATUS status
= NT_STATUS_OK
;
5000 TALLOC_CTX
*ctx
= talloc_tos();
5002 if (total_data
< 13) {
5003 return NT_STATUS_INVALID_PARAMETER
;
5006 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5007 root_fid
= IVAL(pdata
,4);
5008 len
= IVAL(pdata
,8);
5010 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5011 return NT_STATUS_INVALID_PARAMETER
;
5014 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
5017 if (!NT_STATUS_IS_OK(status
)) {
5021 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5024 status
= resolve_dfspath_wcard(ctx
, conn
,
5025 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5029 if (!NT_STATUS_IS_OK(status
)) {
5033 /* Check the new name has no '/' characters. */
5034 if (strchr_m(newname
, '/')) {
5035 return NT_STATUS_NOT_SUPPORTED
;
5038 /* Create the base directory. */
5039 base_name
= talloc_strdup(ctx
, fname
);
5041 return NT_STATUS_NO_MEMORY
;
5043 p
= strrchr_m(base_name
, '/');
5047 base_name
= talloc_strdup(ctx
, "./");
5049 return NT_STATUS_NO_MEMORY
;
5052 /* Append the new name. */
5053 base_name
= talloc_asprintf_append(base_name
,
5057 return NT_STATUS_NO_MEMORY
;
5061 SMB_STRUCT_STAT sbuf
;
5062 char *newname_last_component
= NULL
;
5066 status
= unix_convert(ctx
, conn
, newname
, False
,
5068 &newname_last_component
,
5071 /* If an error we expect this to be
5072 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5074 if (!NT_STATUS_IS_OK(status
)
5075 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
5080 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5081 fsp
->fnum
, fsp
->fsp_name
, base_name
));
5082 status
= rename_internals_fsp(conn
, fsp
, base_name
,
5083 newname_last_component
, 0,
5086 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5087 fname
, base_name
));
5088 status
= rename_internals(ctx
, conn
, req
, fname
, base_name
, 0,
5089 overwrite
, False
, dest_has_wcard
);
5095 /****************************************************************************
5096 Deal with SMB_SET_POSIX_ACL.
5097 ****************************************************************************/
5099 #if defined(HAVE_POSIX_ACLS)
5100 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5105 SMB_STRUCT_STAT
*psbuf
)
5107 uint16 posix_acl_version
;
5108 uint16 num_file_acls
;
5109 uint16 num_def_acls
;
5110 bool valid_file_acls
= True
;
5111 bool valid_def_acls
= True
;
5113 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5114 return NT_STATUS_INVALID_PARAMETER
;
5116 posix_acl_version
= SVAL(pdata
,0);
5117 num_file_acls
= SVAL(pdata
,2);
5118 num_def_acls
= SVAL(pdata
,4);
5120 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5121 valid_file_acls
= False
;
5125 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5126 valid_def_acls
= False
;
5130 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5131 return NT_STATUS_INVALID_PARAMETER
;
5134 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
5135 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
5136 return NT_STATUS_INVALID_PARAMETER
;
5139 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5140 fname
? fname
: fsp
->fsp_name
,
5141 (unsigned int)num_file_acls
,
5142 (unsigned int)num_def_acls
));
5144 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
5145 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
5146 return map_nt_error_from_unix(errno
);
5149 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
5150 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
5151 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
5152 return map_nt_error_from_unix(errno
);
5154 return NT_STATUS_OK
;
5158 /****************************************************************************
5159 Deal with SMB_SET_POSIX_LOCK.
5160 ****************************************************************************/
5162 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
5170 SMB_BIG_UINT offset
;
5172 bool blocking_lock
= False
;
5173 enum brl_type lock_type
;
5174 NTSTATUS status
= NT_STATUS_OK
;
5176 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5177 return NT_STATUS_INVALID_HANDLE
;
5180 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5181 return NT_STATUS_INVALID_PARAMETER
;
5184 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5185 case POSIX_LOCK_TYPE_READ
:
5186 lock_type
= READ_LOCK
;
5188 case POSIX_LOCK_TYPE_WRITE
:
5189 /* Return the right POSIX-mappable error code for files opened read-only. */
5190 if (!fsp
->can_write
) {
5191 return NT_STATUS_INVALID_HANDLE
;
5193 lock_type
= WRITE_LOCK
;
5195 case POSIX_LOCK_TYPE_UNLOCK
:
5196 lock_type
= UNLOCK_LOCK
;
5199 return NT_STATUS_INVALID_PARAMETER
;
5202 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
5203 blocking_lock
= False
;
5204 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
5205 blocking_lock
= True
;
5207 return NT_STATUS_INVALID_PARAMETER
;
5210 if (!lp_blocking_locks(SNUM(conn
))) {
5211 blocking_lock
= False
;
5214 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5215 #if defined(HAVE_LONGLONG)
5216 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5217 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5218 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5219 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5220 #else /* HAVE_LONGLONG */
5221 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5222 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5223 #endif /* HAVE_LONGLONG */
5225 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5226 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5228 (unsigned int)lock_type
,
5229 (unsigned int)lock_pid
,
5233 if (lock_type
== UNLOCK_LOCK
) {
5234 status
= do_unlock(smbd_messaging_context(),
5241 uint32 block_smbpid
;
5243 struct byte_range_lock
*br_lck
= do_lock(smbd_messaging_context(),
5254 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5256 * A blocking lock was requested. Package up
5257 * this smb into a queued request and push it
5258 * onto the blocking lock queue.
5260 if(push_blocking_lock_request(br_lck
,
5261 (char *)inbuf
, length
,
5263 -1, /* infinite timeout. */
5271 TALLOC_FREE(br_lck
);
5275 TALLOC_FREE(br_lck
);
5281 /****************************************************************************
5282 Deal with SMB_INFO_STANDARD.
5283 ****************************************************************************/
5285 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5290 const SMB_STRUCT_STAT
*psbuf
)
5292 struct timespec ts
[2];
5294 if (total_data
< 12) {
5295 return NT_STATUS_INVALID_PARAMETER
;
5299 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
5301 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
5303 DEBUG(10,("smb_set_info_standard: file %s\n",
5304 fname
? fname
: fsp
->fsp_name
));
5306 return smb_set_file_time(conn
,
5314 /****************************************************************************
5315 Deal with SMB_SET_FILE_BASIC_INFO.
5316 ****************************************************************************/
5318 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5323 SMB_STRUCT_STAT
*psbuf
)
5325 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5326 struct timespec write_time
;
5327 struct timespec changed_time
;
5329 struct timespec ts
[2];
5330 NTSTATUS status
= NT_STATUS_OK
;
5331 bool setting_write_time
= true;
5333 if (total_data
< 36) {
5334 return NT_STATUS_INVALID_PARAMETER
;
5337 /* Set the attributes */
5338 dosmode
= IVAL(pdata
,32);
5339 status
= smb_set_file_dosmode(conn
,
5343 if (!NT_STATUS_IS_OK(status
)) {
5347 /* Ignore create time at offset pdata. */
5350 ts
[0] = interpret_long_date(pdata
+8);
5352 write_time
= interpret_long_date(pdata
+16);
5353 changed_time
= interpret_long_date(pdata
+24);
5356 ts
[1] = timespec_min(&write_time
, &changed_time
);
5358 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
5362 /* Prefer a defined time to an undefined one. */
5363 if (null_timespec(ts
[1])) {
5364 if (null_timespec(write_time
)) {
5365 ts
[1] = changed_time
;
5366 setting_write_time
= false;
5372 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5373 fname
? fname
: fsp
->fsp_name
));
5375 return smb_set_file_time(conn
,
5380 setting_write_time
);
5383 /****************************************************************************
5384 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5385 ****************************************************************************/
5387 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5388 struct smb_request
*req
,
5393 SMB_STRUCT_STAT
*psbuf
)
5395 SMB_BIG_UINT allocation_size
= 0;
5396 NTSTATUS status
= NT_STATUS_OK
;
5397 files_struct
*new_fsp
= NULL
;
5399 if (!VALID_STAT(*psbuf
)) {
5400 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5403 if (total_data
< 8) {
5404 return NT_STATUS_INVALID_PARAMETER
;
5407 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
5408 #ifdef LARGE_SMB_OFF_T
5409 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
5410 #else /* LARGE_SMB_OFF_T */
5411 if (IVAL(pdata
,4) != 0) {
5412 /* more than 32 bits? */
5413 return NT_STATUS_INVALID_PARAMETER
;
5415 #endif /* LARGE_SMB_OFF_T */
5417 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5418 fname
, (double)allocation_size
));
5420 if (allocation_size
) {
5421 allocation_size
= smb_roundup(conn
, allocation_size
);
5424 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5425 fname
, (double)allocation_size
));
5427 if (fsp
&& fsp
->fh
->fd
!= -1) {
5428 /* Open file handle. */
5429 /* Only change if needed. */
5430 if (allocation_size
!= get_file_size(*psbuf
)) {
5431 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5432 return map_nt_error_from_unix(errno
);
5435 /* But always update the time. */
5436 if (null_timespec(fsp
->pending_modtime
)) {
5438 * This is equivalent to a write. Ensure it's seen immediately
5439 * if there are no pending writes.
5441 set_filetime(fsp
->conn
, fsp
->fsp_name
,
5442 timespec_current());
5444 return NT_STATUS_OK
;
5447 /* Pathname or stat or directory file. */
5449 status
= open_file_ntcreate(conn
, req
, fname
, psbuf
,
5451 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5454 FILE_ATTRIBUTE_NORMAL
,
5455 FORCE_OPLOCK_BREAK_TO_NONE
,
5458 if (!NT_STATUS_IS_OK(status
)) {
5459 /* NB. We check for open_was_deferred in the caller. */
5463 /* Only change if needed. */
5464 if (allocation_size
!= get_file_size(*psbuf
)) {
5465 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5466 status
= map_nt_error_from_unix(errno
);
5467 close_file(new_fsp
,NORMAL_CLOSE
);
5472 /* Changing the allocation size should set the last mod time. */
5473 /* Don't need to call set_filetime as this will be flushed on
5476 fsp_set_pending_modtime(new_fsp
, timespec_current());
5478 close_file(new_fsp
,NORMAL_CLOSE
);
5479 return NT_STATUS_OK
;
5482 /****************************************************************************
5483 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5484 ****************************************************************************/
5486 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5487 struct smb_request
*req
,
5492 SMB_STRUCT_STAT
*psbuf
)
5496 if (total_data
< 8) {
5497 return NT_STATUS_INVALID_PARAMETER
;
5500 size
= IVAL(pdata
,0);
5501 #ifdef LARGE_SMB_OFF_T
5502 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5503 #else /* LARGE_SMB_OFF_T */
5504 if (IVAL(pdata
,4) != 0) {
5505 /* more than 32 bits? */
5506 return NT_STATUS_INVALID_PARAMETER
;
5508 #endif /* LARGE_SMB_OFF_T */
5509 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5510 "file %s to %.0f\n", fname
, (double)size
));
5512 return smb_set_file_size(conn
, req
,
5519 /****************************************************************************
5520 Allow a UNIX info mknod.
5521 ****************************************************************************/
5523 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5527 SMB_STRUCT_STAT
*psbuf
)
5529 uint32 file_type
= IVAL(pdata
,56);
5530 #if defined(HAVE_MAKEDEV)
5531 uint32 dev_major
= IVAL(pdata
,60);
5532 uint32 dev_minor
= IVAL(pdata
,68);
5534 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5535 uint32 raw_unixmode
= IVAL(pdata
,84);
5539 if (total_data
< 100) {
5540 return NT_STATUS_INVALID_PARAMETER
;
5543 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
5544 if (!NT_STATUS_IS_OK(status
)) {
5548 #if defined(HAVE_MAKEDEV)
5549 dev
= makedev(dev_major
, dev_minor
);
5552 switch (file_type
) {
5553 #if defined(S_IFIFO)
5554 case UNIX_TYPE_FIFO
:
5555 unixmode
|= S_IFIFO
;
5558 #if defined(S_IFSOCK)
5559 case UNIX_TYPE_SOCKET
:
5560 unixmode
|= S_IFSOCK
;
5563 #if defined(S_IFCHR)
5564 case UNIX_TYPE_CHARDEV
:
5565 unixmode
|= S_IFCHR
;
5568 #if defined(S_IFBLK)
5569 case UNIX_TYPE_BLKDEV
:
5570 unixmode
|= S_IFBLK
;
5574 return NT_STATUS_INVALID_PARAMETER
;
5577 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5578 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5580 /* Ok - do the mknod. */
5581 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5582 return map_nt_error_from_unix(errno
);
5585 /* If any of the other "set" calls fail we
5586 * don't want to end up with a half-constructed mknod.
5589 if (lp_inherit_perms(SNUM(conn
))) {
5591 conn
, parent_dirname(fname
),
5595 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5596 status
= map_nt_error_from_unix(errno
);
5597 SMB_VFS_UNLINK(conn
,fname
);
5600 return NT_STATUS_OK
;
5603 /****************************************************************************
5604 Deal with SMB_SET_FILE_UNIX_BASIC.
5605 ****************************************************************************/
5607 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5608 struct smb_request
*req
,
5613 SMB_STRUCT_STAT
*psbuf
)
5615 struct timespec ts
[2];
5616 uint32 raw_unixmode
;
5619 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5620 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5621 NTSTATUS status
= NT_STATUS_OK
;
5622 bool delete_on_fail
= False
;
5623 enum perm_type ptype
;
5625 if (total_data
< 100) {
5626 return NT_STATUS_INVALID_PARAMETER
;
5629 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5630 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5631 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5632 #ifdef LARGE_SMB_OFF_T
5633 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5634 #else /* LARGE_SMB_OFF_T */
5635 if (IVAL(pdata
,4) != 0) {
5636 /* more than 32 bits? */
5637 return NT_STATUS_INVALID_PARAMETER
;
5639 #endif /* LARGE_SMB_OFF_T */
5642 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
5643 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
5644 set_owner
= (uid_t
)IVAL(pdata
,40);
5645 set_grp
= (gid_t
)IVAL(pdata
,48);
5646 raw_unixmode
= IVAL(pdata
,84);
5648 if (VALID_STAT(*psbuf
)) {
5649 if (S_ISDIR(psbuf
->st_mode
)) {
5650 ptype
= PERM_EXISTING_DIR
;
5652 ptype
= PERM_EXISTING_FILE
;
5655 ptype
= PERM_NEW_FILE
;
5658 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
5659 if (!NT_STATUS_IS_OK(status
)) {
5663 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5664 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5665 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
5667 if (!VALID_STAT(*psbuf
)) {
5669 * The only valid use of this is to create character and block
5670 * devices, and named pipes. This is deprecated (IMHO) and
5671 * a new info level should be used for mknod. JRA.
5674 status
= smb_unix_mknod(conn
,
5679 if (!NT_STATUS_IS_OK(status
)) {
5683 /* Ensure we don't try and change anything else. */
5684 raw_unixmode
= SMB_MODE_NO_CHANGE
;
5685 size
= get_file_size(*psbuf
);
5686 ts
[0] = get_atimespec(psbuf
);
5687 ts
[1] = get_mtimespec(psbuf
);
5689 * We continue here as we might want to change the
5692 delete_on_fail
= True
;
5696 /* Horrible backwards compatibility hack as an old server bug
5697 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5701 size
= get_file_size(*psbuf
);
5706 * Deal with the UNIX specific mode set.
5709 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5710 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5711 (unsigned int)unixmode
, fname
));
5712 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
5713 return map_nt_error_from_unix(errno
);
5718 * Deal with the UNIX specific uid set.
5721 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
5724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5725 (unsigned int)set_owner
, fname
));
5727 if (S_ISLNK(psbuf
->st_mode
)) {
5728 ret
= SMB_VFS_LCHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
5730 ret
= SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1);
5734 status
= map_nt_error_from_unix(errno
);
5735 if (delete_on_fail
) {
5736 SMB_VFS_UNLINK(conn
,fname
);
5743 * Deal with the UNIX specific gid set.
5746 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
5747 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5748 (unsigned int)set_owner
, fname
));
5749 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
5750 status
= map_nt_error_from_unix(errno
);
5751 if (delete_on_fail
) {
5752 SMB_VFS_UNLINK(conn
,fname
);
5758 /* Deal with any size changes. */
5760 status
= smb_set_file_size(conn
, req
,
5765 if (!NT_STATUS_IS_OK(status
)) {
5769 /* Deal with any time changes. */
5771 return smb_set_file_time(conn
,
5779 /****************************************************************************
5780 Deal with SMB_SET_FILE_UNIX_INFO2.
5781 ****************************************************************************/
5783 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
5784 struct smb_request
*req
,
5789 SMB_STRUCT_STAT
*psbuf
)
5795 if (total_data
< 116) {
5796 return NT_STATUS_INVALID_PARAMETER
;
5799 /* Start by setting all the fields that are common between UNIX_BASIC
5802 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
5804 if (!NT_STATUS_IS_OK(status
)) {
5808 smb_fflags
= IVAL(pdata
, 108);
5809 smb_fmask
= IVAL(pdata
, 112);
5811 /* NB: We should only attempt to alter the file flags if the client
5812 * sends a non-zero mask.
5814 if (smb_fmask
!= 0) {
5815 int stat_fflags
= 0;
5817 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
5819 /* Client asked to alter a flag we don't understand. */
5820 return NT_STATUS_INVALID_PARAMETER
;
5823 if (fsp
&& fsp
->fh
->fd
!= -1) {
5824 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5825 return NT_STATUS_NOT_SUPPORTED
;
5827 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
5828 return map_nt_error_from_unix(errno
);
5833 /* XXX: need to add support for changing the create_time here. You
5834 * can do this for paths on Darwin with setattrlist(2). The right way
5835 * to hook this up is probably by extending the VFS utimes interface.
5838 return NT_STATUS_OK
;
5841 /****************************************************************************
5842 Create a directory with POSIX semantics.
5843 ****************************************************************************/
5845 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
5846 struct smb_request
*req
,
5850 SMB_STRUCT_STAT
*psbuf
,
5851 int *pdata_return_size
)
5853 NTSTATUS status
= NT_STATUS_OK
;
5854 uint32 raw_unixmode
= 0;
5855 uint32 mod_unixmode
= 0;
5856 mode_t unixmode
= (mode_t
)0;
5857 files_struct
*fsp
= NULL
;
5858 uint16 info_level_return
= 0;
5860 char *pdata
= *ppdata
;
5862 if (total_data
< 18) {
5863 return NT_STATUS_INVALID_PARAMETER
;
5866 raw_unixmode
= IVAL(pdata
,8);
5867 /* Next 4 bytes are not yet defined. */
5869 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
5870 if (!NT_STATUS_IS_OK(status
)) {
5874 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
5876 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5877 fname
, (unsigned int)unixmode
));
5879 status
= open_directory(conn
, req
,
5882 FILE_READ_ATTRIBUTES
, /* Just a stat open */
5883 FILE_SHARE_NONE
, /* Ignored for stat opens */
5890 if (NT_STATUS_IS_OK(status
)) {
5891 close_file(fsp
, NORMAL_CLOSE
);
5894 info_level_return
= SVAL(pdata
,16);
5896 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
5897 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
5898 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
5899 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
5901 *pdata_return_size
= 12;
5904 /* Realloc the data size */
5905 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
5906 if (*ppdata
== NULL
) {
5907 *pdata_return_size
= 0;
5908 return NT_STATUS_NO_MEMORY
;
5912 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
5913 SSVAL(pdata
,2,0); /* No fnum. */
5914 SIVAL(pdata
,4,info
); /* Was directory created. */
5916 switch (info_level_return
) {
5917 case SMB_QUERY_FILE_UNIX_BASIC
:
5918 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
5919 SSVAL(pdata
,10,0); /* Padding. */
5920 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
5922 case SMB_QUERY_FILE_UNIX_INFO2
:
5923 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
5924 SSVAL(pdata
,10,0); /* Padding. */
5925 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
5928 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
5929 SSVAL(pdata
,10,0); /* Padding. */
5936 /****************************************************************************
5937 Open/Create a file with POSIX semantics.
5938 ****************************************************************************/
5940 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
5941 struct smb_request
*req
,
5945 SMB_STRUCT_STAT
*psbuf
,
5946 int *pdata_return_size
)
5948 bool extended_oplock_granted
= False
;
5949 char *pdata
= *ppdata
;
5951 uint32 wire_open_mode
= 0;
5952 uint32 raw_unixmode
= 0;
5953 uint32 mod_unixmode
= 0;
5954 uint32 create_disp
= 0;
5955 uint32 access_mask
= 0;
5956 uint32 create_options
= 0;
5957 NTSTATUS status
= NT_STATUS_OK
;
5958 mode_t unixmode
= (mode_t
)0;
5959 files_struct
*fsp
= NULL
;
5960 int oplock_request
= 0;
5962 uint16 info_level_return
= 0;
5964 if (total_data
< 18) {
5965 return NT_STATUS_INVALID_PARAMETER
;
5968 flags
= IVAL(pdata
,0);
5969 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
5970 if (oplock_request
) {
5971 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
5974 wire_open_mode
= IVAL(pdata
,4);
5976 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
5977 return smb_posix_mkdir(conn
, req
,
5985 switch (wire_open_mode
& SMB_ACCMODE
) {
5987 access_mask
= FILE_READ_DATA
;
5990 access_mask
= FILE_WRITE_DATA
;
5993 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
5996 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5997 (unsigned int)wire_open_mode
));
5998 return NT_STATUS_INVALID_PARAMETER
;
6001 wire_open_mode
&= ~SMB_ACCMODE
;
6003 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
6004 create_disp
= FILE_CREATE
;
6005 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
6006 create_disp
= FILE_OVERWRITE_IF
;
6007 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
6008 create_disp
= FILE_OPEN_IF
;
6010 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6011 (unsigned int)wire_open_mode
));
6012 return NT_STATUS_INVALID_PARAMETER
;
6015 raw_unixmode
= IVAL(pdata
,8);
6016 /* Next 4 bytes are not yet defined. */
6018 status
= unix_perms_from_wire(conn
,
6021 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
6024 if (!NT_STATUS_IS_OK(status
)) {
6028 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
6030 if (wire_open_mode
& SMB_O_SYNC
) {
6031 create_options
|= FILE_WRITE_THROUGH
;
6033 if (wire_open_mode
& SMB_O_APPEND
) {
6034 access_mask
|= FILE_APPEND_DATA
;
6036 if (wire_open_mode
& SMB_O_DIRECT
) {
6037 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
6040 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6042 (unsigned int)wire_open_mode
,
6043 (unsigned int)unixmode
));
6045 status
= open_file_ntcreate(conn
, req
,
6049 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6051 0, /* no create options yet. */
6057 if (!NT_STATUS_IS_OK(status
)) {
6061 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6062 extended_oplock_granted
= True
;
6065 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6066 extended_oplock_granted
= True
;
6069 info_level_return
= SVAL(pdata
,16);
6071 /* Allocate the correct return size. */
6073 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6074 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6075 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6076 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6078 *pdata_return_size
= 12;
6081 /* Realloc the data size */
6082 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6083 if (*ppdata
== NULL
) {
6084 close_file(fsp
,ERROR_CLOSE
);
6085 *pdata_return_size
= 0;
6086 return NT_STATUS_NO_MEMORY
;
6090 if (extended_oplock_granted
) {
6091 if (flags
& REQUEST_BATCH_OPLOCK
) {
6092 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6094 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6096 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6097 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6099 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6102 SSVAL(pdata
,2,fsp
->fnum
);
6103 SIVAL(pdata
,4,info
); /* Was file created etc. */
6105 switch (info_level_return
) {
6106 case SMB_QUERY_FILE_UNIX_BASIC
:
6107 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6108 SSVAL(pdata
,10,0); /* padding. */
6109 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
6111 case SMB_QUERY_FILE_UNIX_INFO2
:
6112 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6113 SSVAL(pdata
,10,0); /* padding. */
6114 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
6117 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6118 SSVAL(pdata
,10,0); /* padding. */
6121 return NT_STATUS_OK
;
6124 /****************************************************************************
6125 Delete a file with POSIX semantics.
6126 ****************************************************************************/
6128 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6129 struct smb_request
*req
,
6133 SMB_STRUCT_STAT
*psbuf
)
6135 NTSTATUS status
= NT_STATUS_OK
;
6136 files_struct
*fsp
= NULL
;
6141 struct share_mode_lock
*lck
= NULL
;
6143 if (total_data
< 2) {
6144 return NT_STATUS_INVALID_PARAMETER
;
6147 flags
= SVAL(pdata
,0);
6149 if (!VALID_STAT(*psbuf
)) {
6150 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6153 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6154 !VALID_STAT_OF_DIR(*psbuf
)) {
6155 return NT_STATUS_NOT_A_DIRECTORY
;
6158 DEBUG(10,("smb_posix_unlink: %s %s\n",
6159 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6162 if (VALID_STAT_OF_DIR(*psbuf
)) {
6163 status
= open_directory(conn
, req
,
6167 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6170 FILE_FLAG_POSIX_SEMANTICS
|0777,
6175 status
= open_file_ntcreate(conn
, req
,
6179 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6182 FILE_FLAG_POSIX_SEMANTICS
|0777,
6183 0, /* No oplock, but break existing ones. */
6188 if (!NT_STATUS_IS_OK(status
)) {
6193 * Don't lie to client. If we can't really delete due to
6194 * non-POSIX opens return SHARING_VIOLATION.
6197 lck
= get_share_mode_lock(NULL
, fsp
->file_id
, NULL
, NULL
);
6199 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6200 "lock for file %s\n", fsp
->fsp_name
));
6201 close_file(fsp
, NORMAL_CLOSE
);
6202 return NT_STATUS_INVALID_PARAMETER
;
6206 * See if others still have the file open. If this is the case, then
6207 * don't delete. If all opens are POSIX delete we can set the delete
6208 * on close disposition.
6210 for (i
=0; i
<lck
->num_share_modes
; i
++) {
6211 struct share_mode_entry
*e
= &lck
->share_modes
[i
];
6212 if (is_valid_share_mode_entry(e
)) {
6213 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
6216 /* Fail with sharing violation. */
6217 close_file(fsp
, NORMAL_CLOSE
);
6219 return NT_STATUS_SHARING_VIOLATION
;
6224 * Set the delete on close.
6226 status
= smb_set_file_disposition_info(conn
,
6233 if (!NT_STATUS_IS_OK(status
)) {
6234 close_file(fsp
, NORMAL_CLOSE
);
6239 return close_file(fsp
, NORMAL_CLOSE
);
6242 /****************************************************************************
6243 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6244 ****************************************************************************/
6246 static void call_trans2setfilepathinfo(connection_struct
*conn
,
6247 struct smb_request
*req
,
6248 unsigned int tran_call
,
6249 char **pparams
, int total_params
,
6250 char **ppdata
, int total_data
,
6251 unsigned int max_data_bytes
)
6253 char *params
= *pparams
;
6254 char *pdata
= *ppdata
;
6256 SMB_STRUCT_STAT sbuf
;
6258 files_struct
*fsp
= NULL
;
6259 NTSTATUS status
= NT_STATUS_OK
;
6260 int data_return_size
= 0;
6261 TALLOC_CTX
*ctx
= talloc_tos();
6264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6270 if (tran_call
== TRANSACT2_SETFILEINFO
) {
6271 if (total_params
< 4) {
6272 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6276 fsp
= file_fsp(SVAL(params
,0));
6277 /* Basic check for non-null fsp. */
6278 if (!check_fsp_open(conn
, req
, fsp
, ¤t_user
)) {
6281 info_level
= SVAL(params
,2);
6283 fname
= talloc_strdup(talloc_tos(),fsp
->fsp_name
);
6285 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6289 if(fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
6291 * This is actually a SETFILEINFO on a directory
6292 * handle (returned from an NT SMB). NT5.0 seems
6293 * to do this call. JRA.
6295 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6296 /* Always do lstat for UNIX calls. */
6297 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
6298 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
6299 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6303 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
6304 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
6305 reply_unixerror(req
,ERRDOS
,ERRbadpath
);
6309 } else if (fsp
->print_file
) {
6311 * Doing a DELETE_ON_CLOSE should cancel a print job.
6313 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
6314 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
6316 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
6319 send_trans2_replies(req
, params
, 2,
6324 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6329 * Original code - this is an open file.
6331 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
6335 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &sbuf
) != 0) {
6336 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
6337 reply_unixerror(req
, ERRDOS
, ERRbadfid
);
6343 if (total_params
< 7) {
6344 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6348 info_level
= SVAL(params
,0);
6349 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, ¶ms
[6],
6350 total_params
- 6, STR_TERMINATE
,
6352 if (!NT_STATUS_IS_OK(status
)) {
6353 reply_nterror(req
, status
);
6357 status
= resolve_dfspath(ctx
, conn
,
6358 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6361 if (!NT_STATUS_IS_OK(status
)) {
6362 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6363 reply_botherror(req
,
6364 NT_STATUS_PATH_NOT_COVERED
,
6365 ERRSRV
, ERRbadpath
);
6368 reply_nterror(req
, status
);
6372 status
= unix_convert(ctx
, conn
, fname
, False
,
6373 &fname
, NULL
, &sbuf
);
6374 if (!NT_STATUS_IS_OK(status
)) {
6375 reply_nterror(req
, status
);
6379 status
= check_name(conn
, fname
);
6380 if (!NT_STATUS_IS_OK(status
)) {
6381 reply_nterror(req
, status
);
6385 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6387 * For CIFS UNIX extensions the target name may not exist.
6390 /* Always do lstat for UNIX calls. */
6391 SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
6393 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
6394 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
6395 reply_unixerror(req
, ERRDOS
, ERRbadpath
);
6400 if (!CAN_WRITE(conn
)) {
6401 reply_doserror(req
, ERRSRV
, ERRaccess
);
6405 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6406 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6410 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6411 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
6413 /* Realloc the parameter size */
6414 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6415 if (*pparams
== NULL
) {
6416 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6423 if (fsp
&& !null_timespec(fsp
->pending_modtime
)) {
6424 /* the pending modtime overrides the current modtime */
6425 set_mtimespec(&sbuf
, fsp
->pending_modtime
);
6428 switch (info_level
) {
6430 case SMB_INFO_STANDARD
:
6432 status
= smb_set_info_standard(conn
,
6441 case SMB_INFO_SET_EA
:
6443 status
= smb_info_set_ea(conn
,
6451 case SMB_SET_FILE_BASIC_INFO
:
6452 case SMB_FILE_BASIC_INFORMATION
:
6454 status
= smb_set_file_basic_info(conn
,
6463 case SMB_FILE_ALLOCATION_INFORMATION
:
6464 case SMB_SET_FILE_ALLOCATION_INFO
:
6466 status
= smb_set_file_allocation_info(conn
, req
,
6475 case SMB_FILE_END_OF_FILE_INFORMATION
:
6476 case SMB_SET_FILE_END_OF_FILE_INFO
:
6478 status
= smb_set_file_end_of_file_info(conn
, req
,
6487 case SMB_FILE_DISPOSITION_INFORMATION
:
6488 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6491 /* JRA - We used to just ignore this on a path ?
6492 * Shouldn't this be invalid level on a pathname
6495 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6496 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6499 status
= smb_set_file_disposition_info(conn
,
6508 case SMB_FILE_POSITION_INFORMATION
:
6510 status
= smb_file_position_information(conn
,
6517 /* From tridge Samba4 :
6518 * MODE_INFORMATION in setfileinfo (I have no
6519 * idea what "mode information" on a file is - it takes a value of 0,
6520 * 2, 4 or 6. What could it be?).
6523 case SMB_FILE_MODE_INFORMATION
:
6525 status
= smb_file_mode_information(conn
,
6532 * CIFS UNIX extensions.
6535 case SMB_SET_FILE_UNIX_BASIC
:
6537 status
= smb_set_file_unix_basic(conn
, req
,
6546 case SMB_SET_FILE_UNIX_INFO2
:
6548 status
= smb_set_file_unix_info2(conn
, req
,
6557 case SMB_SET_FILE_UNIX_LINK
:
6559 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6560 /* We must have a pathname for this. */
6561 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6564 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6569 case SMB_SET_FILE_UNIX_HLINK
:
6571 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6572 /* We must have a pathname for this. */
6573 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6576 status
= smb_set_file_unix_hlink(conn
, req
,
6582 case SMB_FILE_RENAME_INFORMATION
:
6584 status
= smb_file_rename_information(conn
, req
,
6590 #if defined(HAVE_POSIX_ACLS)
6591 case SMB_SET_POSIX_ACL
:
6593 status
= smb_set_posix_acl(conn
,
6603 case SMB_SET_POSIX_LOCK
:
6605 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6606 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6609 status
= smb_set_posix_lock(conn
, req
->inbuf
,
6610 smb_len(req
->inbuf
) + 4,
6611 pdata
, total_data
, fsp
);
6615 case SMB_POSIX_PATH_OPEN
:
6617 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6618 /* We must have a pathname for this. */
6619 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6623 status
= smb_posix_open(conn
, req
,
6632 case SMB_POSIX_PATH_UNLINK
:
6634 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
6635 /* We must have a pathname for this. */
6636 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6640 status
= smb_posix_unlink(conn
, req
,
6649 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6654 if (!NT_STATUS_IS_OK(status
)) {
6655 if (open_was_deferred(req
->mid
)) {
6656 /* We have re-scheduled this call. */
6659 if (blocking_lock_was_deferred(req
->mid
)) {
6660 /* We have re-scheduled this call. */
6663 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6664 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6665 ERRSRV
, ERRbadpath
);
6668 if (info_level
== SMB_POSIX_PATH_OPEN
) {
6669 reply_openerror(req
, status
);
6673 reply_nterror(req
, status
);
6678 send_trans2_replies(req
, params
, 2, *ppdata
, data_return_size
,
6684 /****************************************************************************
6685 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6686 ****************************************************************************/
6688 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
6689 char **pparams
, int total_params
,
6690 char **ppdata
, int total_data
,
6691 unsigned int max_data_bytes
)
6693 char *params
= *pparams
;
6694 char *pdata
= *ppdata
;
6695 char *directory
= NULL
;
6696 SMB_STRUCT_STAT sbuf
;
6697 NTSTATUS status
= NT_STATUS_OK
;
6698 struct ea_list
*ea_list
= NULL
;
6699 TALLOC_CTX
*ctx
= talloc_tos();
6701 if (!CAN_WRITE(conn
)) {
6702 reply_doserror(req
, ERRSRV
, ERRaccess
);
6706 if (total_params
< 5) {
6707 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6711 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
6712 total_params
- 4, STR_TERMINATE
,
6714 if (!NT_STATUS_IS_OK(status
)) {
6715 reply_nterror(req
, status
);
6719 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
6721 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
6722 if (!NT_STATUS_IS_OK(status
)) {
6723 reply_nterror(req
, status
);
6727 status
= check_name(conn
, directory
);
6728 if (!NT_STATUS_IS_OK(status
)) {
6729 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
6730 reply_nterror(req
, status
);
6734 /* Any data in this call is an EA list. */
6735 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
6736 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
6741 * OS/2 workplace shell seems to send SET_EA requests of "null"
6742 * length (4 bytes containing IVAL 4).
6743 * They seem to have no effect. Bug #3212. JRA.
6746 if (total_data
!= 4) {
6747 if (total_data
< 10) {
6748 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6752 if (IVAL(pdata
,0) > total_data
) {
6753 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6754 IVAL(pdata
,0), (unsigned int)total_data
));
6755 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6759 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
6762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6765 } else if (IVAL(pdata
,0) != 4) {
6766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6770 status
= create_directory(conn
, directory
);
6772 if (!NT_STATUS_IS_OK(status
)) {
6773 reply_nterror(req
, status
);
6777 /* Try and set any given EA. */
6779 status
= set_ea(conn
, NULL
, directory
, ea_list
);
6780 if (!NT_STATUS_IS_OK(status
)) {
6781 reply_nterror(req
, status
);
6786 /* Realloc the parameter and data sizes */
6787 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6788 if(*pparams
== NULL
) {
6789 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6796 send_trans2_replies(req
, params
, 2, *ppdata
, 0, max_data_bytes
);
6801 /****************************************************************************
6802 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6803 We don't actually do this - we just send a null response.
6804 ****************************************************************************/
6806 static void call_trans2findnotifyfirst(connection_struct
*conn
,
6807 struct smb_request
*req
,
6808 char **pparams
, int total_params
,
6809 char **ppdata
, int total_data
,
6810 unsigned int max_data_bytes
)
6812 static uint16 fnf_handle
= 257;
6813 char *params
= *pparams
;
6816 if (total_params
< 6) {
6817 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6821 info_level
= SVAL(params
,4);
6822 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
6824 switch (info_level
) {
6829 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6833 /* Realloc the parameter and data sizes */
6834 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
6835 if (*pparams
== NULL
) {
6836 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6841 SSVAL(params
,0,fnf_handle
);
6842 SSVAL(params
,2,0); /* No changes */
6843 SSVAL(params
,4,0); /* No EA errors */
6850 send_trans2_replies(req
, params
, 6, *ppdata
, 0, max_data_bytes
);
6855 /****************************************************************************
6856 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6857 changes). Currently this does nothing.
6858 ****************************************************************************/
6860 static void call_trans2findnotifynext(connection_struct
*conn
,
6861 struct smb_request
*req
,
6862 char **pparams
, int total_params
,
6863 char **ppdata
, int total_data
,
6864 unsigned int max_data_bytes
)
6866 char *params
= *pparams
;
6868 DEBUG(3,("call_trans2findnotifynext\n"));
6870 /* Realloc the parameter and data sizes */
6871 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
6872 if (*pparams
== NULL
) {
6873 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6878 SSVAL(params
,0,0); /* No changes */
6879 SSVAL(params
,2,0); /* No EA errors */
6881 send_trans2_replies(req
, params
, 4, *ppdata
, 0, max_data_bytes
);
6886 /****************************************************************************
6887 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6888 ****************************************************************************/
6890 static void call_trans2getdfsreferral(connection_struct
*conn
,
6891 struct smb_request
*req
,
6892 char **pparams
, int total_params
,
6893 char **ppdata
, int total_data
,
6894 unsigned int max_data_bytes
)
6896 char *params
= *pparams
;
6897 char *pathname
= NULL
;
6899 int max_referral_level
;
6900 NTSTATUS status
= NT_STATUS_OK
;
6901 TALLOC_CTX
*ctx
= talloc_tos();
6903 DEBUG(10,("call_trans2getdfsreferral\n"));
6905 if (total_params
< 3) {
6906 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6910 max_referral_level
= SVAL(params
,0);
6912 if(!lp_host_msdfs()) {
6913 reply_doserror(req
, ERRDOS
, ERRbadfunc
);
6917 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
6918 total_params
- 2, STR_TERMINATE
);
6920 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
6923 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
6924 ppdata
,&status
)) < 0) {
6925 reply_nterror(req
, status
);
6929 SSVAL(req
->inbuf
, smb_flg2
,
6930 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
6931 send_trans2_replies(req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
6936 #define LMCAT_SPL 0x53
6937 #define LMFUNC_GETJOBID 0x60
6939 /****************************************************************************
6940 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6941 ****************************************************************************/
6943 static void call_trans2ioctl(connection_struct
*conn
,
6944 struct smb_request
*req
,
6945 char **pparams
, int total_params
,
6946 char **ppdata
, int total_data
,
6947 unsigned int max_data_bytes
)
6949 char *pdata
= *ppdata
;
6950 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv15
));
6952 /* check for an invalid fid before proceeding */
6955 reply_doserror(req
, ERRDOS
, ERRbadfid
);
6959 if ((SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
6960 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
6961 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
6962 if (*ppdata
== NULL
) {
6963 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6968 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6969 CAN ACCEPT THIS IN UNICODE. JRA. */
6971 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
6972 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
6973 global_myname(), 15,
6974 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
6975 srvstr_push(pdata
, req
->flags2
, pdata
+18,
6976 lp_servicename(SNUM(conn
)), 13,
6977 STR_ASCII
|STR_TERMINATE
); /* Service name */
6978 send_trans2_replies(req
, *pparams
, 0, *ppdata
, 32,
6983 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6984 reply_doserror(req
, ERRSRV
, ERRerror
);
6987 /****************************************************************************
6988 Reply to a SMBfindclose (stop trans2 directory search).
6989 ****************************************************************************/
6991 void reply_findclose(connection_struct
*conn
, struct smb_request
*req
)
6995 START_PROFILE(SMBfindclose
);
6998 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6999 END_PROFILE(SMBfindclose
);
7003 dptr_num
= SVALS(req
->inbuf
,smb_vwv0
);
7005 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7007 dptr_close(&dptr_num
);
7009 reply_outbuf(req
, 0, 0);
7011 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7013 END_PROFILE(SMBfindclose
);
7017 /****************************************************************************
7018 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7019 ****************************************************************************/
7021 void reply_findnclose(connection_struct
*conn
, struct smb_request
*req
)
7025 START_PROFILE(SMBfindnclose
);
7028 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7029 END_PROFILE(SMBfindnclose
);
7033 dptr_num
= SVAL(req
->inbuf
,smb_vwv0
);
7035 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7037 /* We never give out valid handles for a
7038 findnotifyfirst - so any dptr_num is ok here.
7041 reply_outbuf(req
, 0, 0);
7043 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7045 END_PROFILE(SMBfindnclose
);
7049 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
7050 struct trans_state
*state
)
7052 if (Protocol
>= PROTOCOL_NT1
) {
7053 req
->flags2
|= 0x40; /* IS_LONG_NAME */
7054 SSVAL(req
->inbuf
,smb_flg2
,req
->flags2
);
7057 if (conn
->encrypt_level
== Required
&& SVAL(req
->inbuf
,4) != 0x45FF ) {
7058 if (state
->call
!= TRANSACT2_QFSINFO
&&
7059 state
->call
!= TRANSACT2_SETFSINFO
) {
7060 DEBUG(0,("handle_trans2: encryption required "
7062 (unsigned int)state
->call
));
7063 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7068 /* Now we must call the relevant TRANS2 function */
7069 switch(state
->call
) {
7070 case TRANSACT2_OPEN
:
7072 START_PROFILE(Trans2_open
);
7073 call_trans2open(conn
, req
,
7074 &state
->param
, state
->total_param
,
7075 &state
->data
, state
->total_data
,
7076 state
->max_data_return
);
7077 END_PROFILE(Trans2_open
);
7081 case TRANSACT2_FINDFIRST
:
7083 START_PROFILE(Trans2_findfirst
);
7084 call_trans2findfirst(conn
, req
,
7085 &state
->param
, state
->total_param
,
7086 &state
->data
, state
->total_data
,
7087 state
->max_data_return
);
7088 END_PROFILE(Trans2_findfirst
);
7092 case TRANSACT2_FINDNEXT
:
7094 START_PROFILE(Trans2_findnext
);
7095 call_trans2findnext(conn
, req
,
7096 &state
->param
, state
->total_param
,
7097 &state
->data
, state
->total_data
,
7098 state
->max_data_return
);
7099 END_PROFILE(Trans2_findnext
);
7103 case TRANSACT2_QFSINFO
:
7105 START_PROFILE(Trans2_qfsinfo
);
7106 call_trans2qfsinfo(conn
, req
,
7107 &state
->param
, state
->total_param
,
7108 &state
->data
, state
->total_data
,
7109 state
->max_data_return
);
7110 END_PROFILE(Trans2_qfsinfo
);
7114 case TRANSACT2_SETFSINFO
:
7116 START_PROFILE(Trans2_setfsinfo
);
7117 call_trans2setfsinfo(conn
, req
,
7118 &state
->param
, state
->total_param
,
7119 &state
->data
, state
->total_data
,
7120 state
->max_data_return
);
7121 END_PROFILE(Trans2_setfsinfo
);
7125 case TRANSACT2_QPATHINFO
:
7126 case TRANSACT2_QFILEINFO
:
7128 START_PROFILE(Trans2_qpathinfo
);
7129 call_trans2qfilepathinfo(conn
, req
, state
->call
,
7130 &state
->param
, state
->total_param
,
7131 &state
->data
, state
->total_data
,
7132 state
->max_data_return
);
7133 END_PROFILE(Trans2_qpathinfo
);
7137 case TRANSACT2_SETPATHINFO
:
7138 case TRANSACT2_SETFILEINFO
:
7140 START_PROFILE(Trans2_setpathinfo
);
7141 call_trans2setfilepathinfo(conn
, req
, state
->call
,
7142 &state
->param
, state
->total_param
,
7143 &state
->data
, state
->total_data
,
7144 state
->max_data_return
);
7145 END_PROFILE(Trans2_setpathinfo
);
7149 case TRANSACT2_FINDNOTIFYFIRST
:
7151 START_PROFILE(Trans2_findnotifyfirst
);
7152 call_trans2findnotifyfirst(conn
, req
,
7153 &state
->param
, state
->total_param
,
7154 &state
->data
, state
->total_data
,
7155 state
->max_data_return
);
7156 END_PROFILE(Trans2_findnotifyfirst
);
7160 case TRANSACT2_FINDNOTIFYNEXT
:
7162 START_PROFILE(Trans2_findnotifynext
);
7163 call_trans2findnotifynext(conn
, req
,
7164 &state
->param
, state
->total_param
,
7165 &state
->data
, state
->total_data
,
7166 state
->max_data_return
);
7167 END_PROFILE(Trans2_findnotifynext
);
7171 case TRANSACT2_MKDIR
:
7173 START_PROFILE(Trans2_mkdir
);
7174 call_trans2mkdir(conn
, req
,
7175 &state
->param
, state
->total_param
,
7176 &state
->data
, state
->total_data
,
7177 state
->max_data_return
);
7178 END_PROFILE(Trans2_mkdir
);
7182 case TRANSACT2_GET_DFS_REFERRAL
:
7184 START_PROFILE(Trans2_get_dfs_referral
);
7185 call_trans2getdfsreferral(conn
, req
,
7186 &state
->param
, state
->total_param
,
7187 &state
->data
, state
->total_data
,
7188 state
->max_data_return
);
7189 END_PROFILE(Trans2_get_dfs_referral
);
7193 case TRANSACT2_IOCTL
:
7195 START_PROFILE(Trans2_ioctl
);
7196 call_trans2ioctl(conn
, req
,
7197 &state
->param
, state
->total_param
,
7198 &state
->data
, state
->total_data
,
7199 state
->max_data_return
);
7200 END_PROFILE(Trans2_ioctl
);
7205 /* Error in request */
7206 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
7207 reply_doserror(req
, ERRSRV
,ERRerror
);
7211 /****************************************************************************
7212 Reply to a SMBtrans2.
7213 ****************************************************************************/
7215 void reply_trans2(connection_struct
*conn
, struct smb_request
*req
)
7221 unsigned int tran_call
;
7223 struct trans_state
*state
;
7226 START_PROFILE(SMBtrans2
);
7228 if (req
->wct
< 14) {
7229 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7230 END_PROFILE(SMBtrans2
);
7234 dsoff
= SVAL(req
->inbuf
, smb_dsoff
);
7235 dscnt
= SVAL(req
->inbuf
, smb_dscnt
);
7236 psoff
= SVAL(req
->inbuf
, smb_psoff
);
7237 pscnt
= SVAL(req
->inbuf
, smb_pscnt
);
7238 tran_call
= SVAL(req
->inbuf
, smb_setup0
);
7239 size
= smb_len(req
->inbuf
) + 4;
7241 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
7242 if (!NT_STATUS_IS_OK(result
)) {
7243 DEBUG(2, ("Got invalid trans2 request: %s\n",
7244 nt_errstr(result
)));
7245 reply_nterror(req
, result
);
7246 END_PROFILE(SMBtrans2
);
7251 switch (tran_call
) {
7252 /* List the allowed trans2 calls on IPC$ */
7253 case TRANSACT2_OPEN
:
7254 case TRANSACT2_GET_DFS_REFERRAL
:
7255 case TRANSACT2_QFILEINFO
:
7256 case TRANSACT2_QFSINFO
:
7257 case TRANSACT2_SETFSINFO
:
7260 reply_doserror(req
, ERRSRV
, ERRaccess
);
7261 END_PROFILE(SMBtrans2
);
7266 if ((state
= TALLOC_P(conn
->mem_ctx
, struct trans_state
)) == NULL
) {
7267 DEBUG(0, ("talloc failed\n"));
7268 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7269 END_PROFILE(SMBtrans2
);
7273 state
->cmd
= SMBtrans2
;
7275 state
->mid
= req
->mid
;
7276 state
->vuid
= req
->vuid
;
7277 state
->setup_count
= SVAL(req
->inbuf
, smb_suwcnt
);
7278 state
->setup
= NULL
;
7279 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7280 state
->param
= NULL
;
7281 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7283 state
->max_param_return
= SVAL(req
->inbuf
, smb_mprcnt
);
7284 state
->max_data_return
= SVAL(req
->inbuf
, smb_mdrcnt
);
7285 state
->max_setup_return
= SVAL(req
->inbuf
, smb_msrcnt
);
7286 state
->close_on_completion
= BITSETW(req
->inbuf
+smb_vwv5
,0);
7287 state
->one_way
= BITSETW(req
->inbuf
+smb_vwv5
,1);
7289 state
->call
= tran_call
;
7291 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7292 is so as a sanity check */
7293 if (state
->setup_count
!= 1) {
7295 * Need to have rc=0 for ioctl to get job id for OS/2.
7296 * Network printing will fail if function is not successful.
7297 * Similar function in reply.c will be used if protocol
7298 * is LANMAN1.0 instead of LM1.2X002.
7299 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7300 * outbuf doesn't have to be set(only job id is used).
7302 if ( (state
->setup_count
== 4)
7303 && (tran_call
== TRANSACT2_IOCTL
)
7304 && (SVAL(req
->inbuf
,(smb_setup
+4)) == LMCAT_SPL
)
7305 && (SVAL(req
->inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
7306 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7308 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
7309 DEBUG(2,("Transaction is %d\n",tran_call
));
7311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7312 END_PROFILE(SMBtrans2
);
7317 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
7320 if (state
->total_data
) {
7321 /* Can't use talloc here, the core routines do realloc on the
7322 * params and data. */
7323 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
7324 if (state
->data
== NULL
) {
7325 DEBUG(0,("reply_trans2: data malloc fail for %u "
7326 "bytes !\n", (unsigned int)state
->total_data
));
7328 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7329 END_PROFILE(SMBtrans2
);
7332 if ((dsoff
+dscnt
< dsoff
) || (dsoff
+dscnt
< dscnt
))
7334 if ((smb_base(req
->inbuf
)+dsoff
+dscnt
7335 > (char *)req
->inbuf
+ size
) ||
7336 (smb_base(req
->inbuf
)+dsoff
+dscnt
< smb_base(req
->inbuf
)))
7339 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
7342 if (state
->total_param
) {
7343 /* Can't use talloc here, the core routines do realloc on the
7344 * params and data. */
7345 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
7346 if (state
->param
== NULL
) {
7347 DEBUG(0,("reply_trans: param malloc fail for %u "
7348 "bytes !\n", (unsigned int)state
->total_param
));
7349 SAFE_FREE(state
->data
);
7351 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7352 END_PROFILE(SMBtrans2
);
7355 if ((psoff
+pscnt
< psoff
) || (psoff
+pscnt
< pscnt
))
7357 if ((smb_base(req
->inbuf
)+psoff
+pscnt
7358 > (char *)req
->inbuf
+ size
) ||
7359 (smb_base(req
->inbuf
)+psoff
+pscnt
< smb_base(req
->inbuf
)))
7362 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
7365 state
->received_data
= dscnt
;
7366 state
->received_param
= pscnt
;
7368 if ((state
->received_param
== state
->total_param
) &&
7369 (state
->received_data
== state
->total_data
)) {
7371 handle_trans2(conn
, req
, state
);
7373 SAFE_FREE(state
->data
);
7374 SAFE_FREE(state
->param
);
7376 END_PROFILE(SMBtrans2
);
7380 DLIST_ADD(conn
->pending_trans
, state
);
7382 /* We need to send an interim response then receive the rest
7383 of the parameter/data bytes */
7384 reply_outbuf(req
, 0, 0);
7385 show_msg((char *)req
->outbuf
);
7386 END_PROFILE(SMBtrans2
);
7391 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7392 SAFE_FREE(state
->data
);
7393 SAFE_FREE(state
->param
);
7395 END_PROFILE(SMBtrans2
);
7396 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7400 /****************************************************************************
7401 Reply to a SMBtranss2
7402 ****************************************************************************/
7404 void reply_transs2(connection_struct
*conn
, struct smb_request
*req
)
7406 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
7407 struct trans_state
*state
;
7410 START_PROFILE(SMBtranss2
);
7412 show_msg((char *)req
->inbuf
);
7415 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7416 END_PROFILE(SMBtranss2
);
7420 size
= smb_len(req
->inbuf
)+4;
7422 for (state
= conn
->pending_trans
; state
!= NULL
;
7423 state
= state
->next
) {
7424 if (state
->mid
== req
->mid
) {
7429 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
7430 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7431 END_PROFILE(SMBtranss2
);
7435 /* Revise state->total_param and state->total_data in case they have
7436 changed downwards */
7438 if (SVAL(req
->inbuf
, smb_tpscnt
) < state
->total_param
)
7439 state
->total_param
= SVAL(req
->inbuf
, smb_tpscnt
);
7440 if (SVAL(req
->inbuf
, smb_tdscnt
) < state
->total_data
)
7441 state
->total_data
= SVAL(req
->inbuf
, smb_tdscnt
);
7443 pcnt
= SVAL(req
->inbuf
, smb_spscnt
);
7444 poff
= SVAL(req
->inbuf
, smb_spsoff
);
7445 pdisp
= SVAL(req
->inbuf
, smb_spsdisp
);
7447 dcnt
= SVAL(req
->inbuf
, smb_sdscnt
);
7448 doff
= SVAL(req
->inbuf
, smb_sdsoff
);
7449 ddisp
= SVAL(req
->inbuf
, smb_sdsdisp
);
7451 state
->received_param
+= pcnt
;
7452 state
->received_data
+= dcnt
;
7454 if ((state
->received_data
> state
->total_data
) ||
7455 (state
->received_param
> state
->total_param
))
7459 if (pdisp
+pcnt
> state
->total_param
)
7461 if ((pdisp
+pcnt
< pdisp
) || (pdisp
+pcnt
< pcnt
))
7463 if (pdisp
> state
->total_param
)
7465 if ((smb_base(req
->inbuf
) + poff
+ pcnt
7466 > (char *)req
->inbuf
+ size
) ||
7467 (smb_base(req
->inbuf
) + poff
+ pcnt
< smb_base(req
->inbuf
)))
7469 if (state
->param
+ pdisp
< state
->param
)
7472 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,
7477 if (ddisp
+dcnt
> state
->total_data
)
7479 if ((ddisp
+dcnt
< ddisp
) || (ddisp
+dcnt
< dcnt
))
7481 if (ddisp
> state
->total_data
)
7483 if ((smb_base(req
->inbuf
) + doff
+ dcnt
7484 > (char *)req
->inbuf
+ size
) ||
7485 (smb_base(req
->inbuf
) + doff
+ dcnt
< smb_base(req
->inbuf
)))
7487 if (state
->data
+ ddisp
< state
->data
)
7490 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,
7494 if ((state
->received_param
< state
->total_param
) ||
7495 (state
->received_data
< state
->total_data
)) {
7496 END_PROFILE(SMBtranss2
);
7501 * construct_reply_common will copy smb_com from inbuf to
7502 * outbuf. SMBtranss2 is wrong here.
7504 SCVAL(req
->inbuf
,smb_com
,SMBtrans2
);
7506 handle_trans2(conn
, req
, state
);
7508 DLIST_REMOVE(conn
->pending_trans
, state
);
7509 SAFE_FREE(state
->data
);
7510 SAFE_FREE(state
->param
);
7513 END_PROFILE(SMBtranss2
);
7518 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7519 DLIST_REMOVE(conn
->pending_trans
, state
);
7520 SAFE_FREE(state
->data
);
7521 SAFE_FREE(state
->param
);
7523 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7524 END_PROFILE(SMBtranss2
);