2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
8 Extensively modified by Andrew Tridgell, 1995
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 extern enum protocol_types Protocol
;
29 extern int smb_read_error
;
30 extern int global_oplock_break
;
31 extern uint32 global_client_caps
;
32 extern struct current_user current_user
;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
44 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type
= get_remote_arch();
48 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
49 val
= SMB_ROUNDUP(val
,rval
);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
63 if(S_ISDIR(sbuf
->st_mode
)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
70 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
73 if (fsp
&& fsp
->initial_allocation_size
)
74 ret
= MAX(ret
,fsp
->initial_allocation_size
);
76 return smb_roundup(conn
, ret
);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names
[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME
,
85 SAMBA_XATTR_DOS_ATTRIB
,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL
samba_private_attr_name(const char *unix_ea_name
)
97 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
98 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
109 const char *fname
, char *ea_name
, struct ea_struct
*pea
)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size
= 256;
118 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
123 if (fsp
&& fsp
->fh
->fd
!= -1) {
124 sizeret
= SMB_VFS_FGETXATTR(fsp
, fsp
->fh
->fd
, ea_name
, val
, attr_size
);
126 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
129 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name
, (unsigned int)sizeret
));
139 dump_data(10, val
, sizeret
);
142 if (strnequal(ea_name
, "user.", 5)) {
143 pea
->name
= &ea_name
[5];
147 pea
->value
.data
= (unsigned char *)val
;
148 pea
->value
.length
= (size_t)sizeret
;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
157 const char *fname
, size_t *pea_total_len
)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size
= 1024;
165 struct ea_list
*ea_list_head
= NULL
;
169 if (!lp_ea_support(SNUM(conn
))) {
173 for (i
= 0, ea_namelist
= TALLOC(mem_ctx
, ea_namelist_size
); i
< 6;
174 ea_namelist
= TALLOC_REALLOC_ARRAY(mem_ctx
, ea_namelist
, char, ea_namelist_size
), i
++) {
175 if (fsp
&& fsp
->fh
->fd
!= -1) {
176 sizeret
= SMB_VFS_FLISTXATTR(fsp
, fsp
->fh
->fd
, ea_namelist
, ea_namelist_size
);
178 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
, ea_namelist_size
);
181 if (sizeret
== -1 && errno
== ERANGE
) {
182 ea_namelist_size
*= 2;
191 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret
));
194 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
) + 1) {
195 struct ea_list
*listp
, *tmp
;
197 if (strnequal(p
, "system.", 7) || samba_private_attr_name(p
))
200 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
204 if (!get_ea_value(mem_ctx
, conn
, fsp
, fname
, p
, &listp
->ea
)) {
210 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
211 *pea_total_len
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
212 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213 (unsigned int)*pea_total_len
, dos_ea_name
,
214 (unsigned int)listp
->ea
.value
.length
));
216 DLIST_ADD_END(ea_list_head
, listp
, tmp
);
218 /* Add on 4 for total length. */
219 if (*pea_total_len
) {
224 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len
));
228 /****************************************************************************
229 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
231 ****************************************************************************/
233 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
234 connection_struct
*conn
, struct ea_list
*ea_list
)
236 unsigned int ret_data_size
= 4;
239 SMB_ASSERT(total_data_size
>= 4);
241 if (!lp_ea_support(SNUM(conn
))) {
246 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
249 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
250 dos_namelen
= strlen(dos_ea_name
);
251 if (dos_namelen
> 255 || dos_namelen
== 0) {
254 if (ea_list
->ea
.value
.length
> 65535) {
257 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
261 /* We know we have room. */
262 SCVAL(p
,0,ea_list
->ea
.flags
);
263 SCVAL(p
,1,dos_namelen
);
264 SSVAL(p
,2,ea_list
->ea
.value
.length
);
265 fstrcpy(p
+4, dos_ea_name
);
266 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
268 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
269 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
272 ret_data_size
= PTR_DIFF(p
, pdata
);
273 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
274 SIVAL(pdata
,0,ret_data_size
);
275 return ret_data_size
;
278 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
280 size_t total_ea_len
= 0;
281 TALLOC_CTX
*mem_ctx
= NULL
;
283 if (!lp_ea_support(SNUM(conn
))) {
286 mem_ctx
= talloc_init("estimate_ea_size");
287 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
288 talloc_destroy(mem_ctx
);
292 /****************************************************************************
293 Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
296 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
299 TALLOC_CTX
*mem_ctx
= talloc_init("canonicalize_ea_name");
300 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
302 for (; ea_list
; ea_list
= ea_list
->next
) {
303 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
304 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305 &unix_ea_name
[5], ea_list
->ea
.name
));
306 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
310 talloc_destroy(mem_ctx
);
313 /****************************************************************************
314 Set or delete an extended attribute.
315 ****************************************************************************/
317 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
319 if (!lp_ea_support(SNUM(conn
))) {
320 return NT_STATUS_EAS_NOT_SUPPORTED
;
323 for (;ea_list
; ea_list
= ea_list
->next
) {
325 fstring unix_ea_name
;
327 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
328 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
330 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
332 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
334 if (samba_private_attr_name(unix_ea_name
)) {
335 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
336 return NT_STATUS_ACCESS_DENIED
;
339 if (ea_list
->ea
.value
.length
== 0) {
340 /* Remove the attribute. */
341 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
342 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343 unix_ea_name
, fsp
->fsp_name
));
344 ret
= SMB_VFS_FREMOVEXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
);
346 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347 unix_ea_name
, fname
));
348 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
351 /* Removing a non existent attribute always succeeds. */
352 if (ret
== -1 && errno
== ENOATTR
) {
353 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
360 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361 unix_ea_name
, fsp
->fsp_name
));
362 ret
= SMB_VFS_FSETXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
,
363 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
365 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366 unix_ea_name
, fname
));
367 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
368 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
374 if (errno
== ENOTSUP
) {
375 return NT_STATUS_EAS_NOT_SUPPORTED
;
378 return map_nt_error_from_unix(errno
);
384 /****************************************************************************
385 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
388 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
390 struct ea_list
*ea_list_head
= NULL
;
393 while (offset
+ 2 < data_size
) {
395 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
396 unsigned int namelen
= CVAL(pdata
,offset
);
398 offset
++; /* Go past the namelen byte. */
400 /* integer wrap paranioa. */
401 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
402 (offset
> data_size
) || (namelen
> data_size
) ||
403 (offset
+ namelen
>= data_size
)) {
406 /* Ensure the name is null terminated. */
407 if (pdata
[offset
+ namelen
] != '\0') {
410 pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
]);
415 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
416 DLIST_ADD_END(ea_list_head
, eal
, tmp
);
417 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
423 /****************************************************************************
424 Read one EA list entry from the buffer.
425 ****************************************************************************/
427 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
429 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
431 unsigned int namelen
;
441 eal
->ea
.flags
= CVAL(pdata
,0);
442 namelen
= CVAL(pdata
,1);
443 val_len
= SVAL(pdata
,2);
445 if (4 + namelen
+ 1 + val_len
> data_size
) {
449 /* Ensure the name is null terminated. */
450 if (pdata
[namelen
+ 4] != '\0') {
453 pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4);
458 eal
->ea
.value
= data_blob(NULL
, (size_t)val_len
+ 1);
459 if (!eal
->ea
.value
.data
) {
463 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
465 /* Ensure we're null terminated just in case we print the value. */
466 eal
->ea
.value
.data
[val_len
] = '\0';
467 /* But don't count the null. */
468 eal
->ea
.value
.length
--;
471 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
474 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
475 dump_data(10, (const char *)eal
->ea
.value
.data
, eal
->ea
.value
.length
);
480 /****************************************************************************
481 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
484 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
486 struct ea_list
*ea_list_head
= NULL
;
488 size_t bytes_used
= 0;
490 while (offset
< data_size
) {
492 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
498 DLIST_ADD_END(ea_list_head
, eal
, tmp
);
499 offset
+= bytes_used
;
505 /****************************************************************************
506 Count the total EA size needed.
507 ****************************************************************************/
509 static size_t ea_list_size(struct ea_list
*ealist
)
512 struct ea_list
*listp
;
515 for (listp
= ealist
; listp
; listp
= listp
->next
) {
516 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
517 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
519 /* Add on 4 for total length. */
527 /****************************************************************************
528 Return a union of EA's from a file list and a list of names.
529 The TALLOC context for the two lists *MUST* be identical as we steal
530 memory from one list to add to another. JRA.
531 ****************************************************************************/
533 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
535 struct ea_list
*nlistp
, *flistp
;
537 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
538 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
539 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
545 /* Copy the data from this entry. */
546 nlistp
->ea
.flags
= flistp
->ea
.flags
;
547 nlistp
->ea
.value
= flistp
->ea
.value
;
550 nlistp
->ea
.flags
= 0;
551 ZERO_STRUCT(nlistp
->ea
.value
);
555 *total_ea_len
= ea_list_size(name_list
);
559 /****************************************************************************
560 Send the required number of replies back.
561 We assume all fields other than the data fields are
562 set correctly for the type of call.
563 HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
566 static int send_trans2_replies(char *outbuf
,
573 /* As we are using a protocol > LANMAN1 then the max_send
574 variable must have been set in the sessetupX call.
575 This takes precedence over the max_xmit field in the
576 global struct. These different max_xmit variables should
577 be merged as this is now too confusing */
579 int data_to_send
= datasize
;
580 int params_to_send
= paramsize
;
584 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
585 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586 int data_alignment_offset
= 0;
588 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
590 set_message(outbuf
,10,0,True
);
592 /* If there genuinely are no parameters or data to send just send the empty packet */
594 if(params_to_send
== 0 && data_to_send
== 0) {
596 if (!send_smb(smbd_server_fd(),outbuf
))
597 exit_server("send_trans2_replies: send_smb failed.");
601 /* When sending params and data ensure that both are nicely aligned */
602 /* Only do this alignment when there is also data to send - else
603 can cause NT redirector problems. */
605 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
606 data_alignment_offset
= 4 - (params_to_send
% 4);
608 /* Space is bufsize minus Netbios over TCP header minus SMB header */
609 /* The alignment_offset is to align the param bytes on an even byte
610 boundary. NT 4.0 Beta needs this to work correctly. */
612 useable_space
= bufsize
- ((smb_buf(outbuf
)+ alignment_offset
+data_alignment_offset
) - outbuf
);
614 /* useable_space can never be more than max_send minus the alignment offset. */
616 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
618 while (params_to_send
|| data_to_send
) {
619 /* Calculate whether we will totally or partially fill this packet */
621 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
623 /* We can never send more than useable_space */
625 * Note that 'useable_space' does not include the alignment offsets,
626 * but we must include the alignment offsets in the calculation of
627 * the length of the data we send over the wire, as the alignment offsets
628 * are sent here. Fix from Marc_Jacobsen@hp.com.
631 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
633 set_message(outbuf
, 10, total_sent_thistime
, True
);
635 /* Set total params and data to be sent */
636 SSVAL(outbuf
,smb_tprcnt
,paramsize
);
637 SSVAL(outbuf
,smb_tdrcnt
,datasize
);
639 /* Calculate how many parameters and data we can fit into
640 * this packet. Parameters get precedence
643 params_sent_thistime
= MIN(params_to_send
,useable_space
);
644 data_sent_thistime
= useable_space
- params_sent_thistime
;
645 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
647 SSVAL(outbuf
,smb_prcnt
, params_sent_thistime
);
649 /* smb_proff is the offset from the start of the SMB header to the
650 parameter bytes, however the first 4 bytes of outbuf are
651 the Netbios over TCP header. Thus use smb_base() to subtract
652 them from the calculation */
654 SSVAL(outbuf
,smb_proff
,((smb_buf(outbuf
)+alignment_offset
) - smb_base(outbuf
)));
656 if(params_sent_thistime
== 0)
657 SSVAL(outbuf
,smb_prdisp
,0);
659 /* Absolute displacement of param bytes sent in this packet */
660 SSVAL(outbuf
,smb_prdisp
,pp
- params
);
662 SSVAL(outbuf
,smb_drcnt
, data_sent_thistime
);
663 if(data_sent_thistime
== 0) {
664 SSVAL(outbuf
,smb_droff
,0);
665 SSVAL(outbuf
,smb_drdisp
, 0);
667 /* The offset of the data bytes is the offset of the
668 parameter bytes plus the number of parameters being sent this time */
669 SSVAL(outbuf
,smb_droff
,((smb_buf(outbuf
)+alignment_offset
) -
670 smb_base(outbuf
)) + params_sent_thistime
+ data_alignment_offset
);
671 SSVAL(outbuf
,smb_drdisp
, pd
- pdata
);
674 /* Copy the param bytes into the packet */
676 if(params_sent_thistime
)
677 memcpy((smb_buf(outbuf
)+alignment_offset
),pp
,params_sent_thistime
);
679 /* Copy in the data bytes */
680 if(data_sent_thistime
)
681 memcpy(smb_buf(outbuf
)+alignment_offset
+params_sent_thistime
+
682 data_alignment_offset
,pd
,data_sent_thistime
);
684 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685 params_sent_thistime
, data_sent_thistime
, useable_space
));
686 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687 params_to_send
, data_to_send
, paramsize
, datasize
));
689 /* Send the packet */
691 if (!send_smb(smbd_server_fd(),outbuf
))
692 exit_server("send_trans2_replies: send_smb failed.");
694 pp
+= params_sent_thistime
;
695 pd
+= data_sent_thistime
;
697 params_to_send
-= params_sent_thistime
;
698 data_to_send
-= data_sent_thistime
;
701 if(params_to_send
< 0 || data_to_send
< 0) {
702 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703 params_to_send
, data_to_send
));
711 /****************************************************************************
712 Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
715 static int call_trans2open(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
716 char **pparams
, int total_params
, char **ppdata
, int total_data
,
717 unsigned int max_data_bytes
)
719 char *params
= *pparams
;
720 char *pdata
= *ppdata
;
725 BOOL return_additional_info
;
736 SMB_STRUCT_STAT sbuf
;
738 BOOL bad_path
= False
;
740 TALLOC_CTX
*ctx
= NULL
;
741 struct ea_list
*ea_list
= NULL
;
746 uint32 create_disposition
;
747 uint32 create_options
= 0;
750 * Ensure we have enough parameters to perform the operation.
753 if (total_params
< 29) {
754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
757 flags
= SVAL(params
, 0);
758 deny_mode
= SVAL(params
, 2);
759 open_attr
= SVAL(params
,6);
760 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
761 if (oplock_request
) {
762 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
766 return_additional_info
= BITSETW(params
,0);
767 open_sattr
= SVAL(params
, 4);
768 open_time
= make_unix_date3(params
+8);
770 open_ofun
= SVAL(params
,12);
771 open_size
= IVAL(params
,14);
775 return(ERROR_DOS(ERRSRV
,ERRaccess
));
778 srvstr_get_path(inbuf
, fname
, pname
, sizeof(fname
), -1, STR_TERMINATE
, &status
, False
);
779 if (!NT_STATUS_IS_OK(status
)) {
780 return ERROR_NT(status
);
783 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
785 (unsigned int)open_ofun
, open_size
));
787 /* XXXX we need to handle passed times, sattr and flags */
789 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
791 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
794 if (!check_name(fname
,conn
)) {
795 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
798 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
803 return ERROR_DOS(ERRDOS
, ERRbadaccess
);
806 /* Any data in this call is an EA list. */
807 if (total_data
&& !lp_ea_support(SNUM(conn
))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED
);
812 if (total_data
< 10) {
813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
816 if (IVAL(pdata
,0) > total_data
) {
817 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818 IVAL(pdata
,0), (unsigned int)total_data
));
819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
822 ctx
= talloc_init("TRANS2_OPEN_SET_EA");
824 return ERROR_NT(NT_STATUS_NO_MEMORY
);
826 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
833 fsp
= open_file_ntcreate(conn
,fname
,&sbuf
,
844 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
845 /* We have re-scheduled this call. */
848 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
851 size
= get_file_size(sbuf
);
852 fattr
= dos_mode(conn
,fname
,&sbuf
);
853 mtime
= sbuf
.st_mtime
;
857 close_file(fsp
,False
);
858 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
861 if (total_data
&& smb_action
== FILE_WAS_CREATED
) {
862 status
= set_ea(conn
, fsp
, fname
, ea_list
);
864 if (!NT_STATUS_IS_OK(status
)) {
865 close_file(fsp
,False
);
866 return ERROR_NT(status
);
870 /* Realloc the size of parameters and data we will return */
871 params
= SMB_REALLOC(*pparams
, 30);
872 if( params
== NULL
) {
873 return ERROR_NT(NT_STATUS_NO_MEMORY
);
877 SSVAL(params
,0,fsp
->fnum
);
878 SSVAL(params
,2,open_attr
);
879 put_dos_date2(params
,4, mtime
);
880 SIVAL(params
,8, (uint32
)size
);
881 SSVAL(params
,12,deny_mode
);
882 SSVAL(params
,14,0); /* open_type - file or directory. */
883 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
885 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
886 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
889 SSVAL(params
,18,smb_action
);
892 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
894 SIVAL(params
,20,inode
);
895 SSVAL(params
,24,0); /* Padding. */
897 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fname
);
898 SIVAL(params
, 26, ea_size
);
900 SIVAL(params
, 26, 0);
903 /* Send the required number of replies */
904 send_trans2_replies(outbuf
, bufsize
, params
, 30, *ppdata
, 0);
909 /*********************************************************
910 Routine to check if a given string matches exactly.
911 as a special case a mask of "." does NOT match. That
912 is required for correct wildcard semantics
913 Case can be significant or not.
914 **********************************************************/
916 static BOOL
exact_match(char *str
,char *mask
, BOOL case_sig
)
918 if (mask
[0] == '.' && mask
[1] == 0)
921 return strcmp(str
,mask
)==0;
922 if (StrCaseCmp(str
,mask
) != 0) {
925 if (ms_has_wild(str
)) {
931 /****************************************************************************
932 Return the filetype for UNIX extensions.
933 ****************************************************************************/
935 static uint32
unix_filetype(mode_t mode
)
938 return UNIX_TYPE_FILE
;
939 else if(S_ISDIR(mode
))
940 return UNIX_TYPE_DIR
;
942 else if(S_ISLNK(mode
))
943 return UNIX_TYPE_SYMLINK
;
946 else if(S_ISCHR(mode
))
947 return UNIX_TYPE_CHARDEV
;
950 else if(S_ISBLK(mode
))
951 return UNIX_TYPE_BLKDEV
;
954 else if(S_ISFIFO(mode
))
955 return UNIX_TYPE_FIFO
;
958 else if(S_ISSOCK(mode
))
959 return UNIX_TYPE_SOCKET
;
962 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
963 return UNIX_TYPE_UNKNOWN
;
966 /****************************************************************************
967 Map wire perms onto standard UNIX permissions. Obey share restrictions.
968 ****************************************************************************/
970 static mode_t
unix_perms_from_wire( connection_struct
*conn
, SMB_STRUCT_STAT
*pst
, uint32 perms
)
974 if (perms
== SMB_MODE_NO_CHANGE
)
977 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
978 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
979 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
980 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
981 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
982 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
983 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
984 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
985 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
987 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
990 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
993 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
996 if (VALID_STAT(*pst
) && S_ISDIR(pst
->st_mode
)) {
997 ret
&= lp_dir_mask(SNUM(conn
));
998 /* Add in force bits */
999 ret
|= lp_force_dir_mode(SNUM(conn
));
1001 /* Apply mode mask */
1002 ret
&= lp_create_mask(SNUM(conn
));
1003 /* Add in force bits */
1004 ret
|= lp_force_create_mode(SNUM(conn
));
1010 /****************************************************************************
1011 Get a level dependent lanman2 dir entry.
1012 ****************************************************************************/
1014 static BOOL
get_lanman2_dir_entry(connection_struct
*conn
,
1015 void *inbuf
, void *outbuf
,
1016 char *path_mask
,uint32 dirtype
,int info_level
,
1017 int requires_resume_key
,
1018 BOOL dont_descend
,char **ppdata
,
1019 char *base_data
, int space_remaining
,
1020 BOOL
*out_of_space
, BOOL
*got_exact_match
,
1021 int *last_entry_off
, struct ea_list
*name_list
, TALLOC_CTX
*ea_ctx
)
1025 SMB_STRUCT_STAT sbuf
;
1029 char *p
, *q
, *pdata
= *ppdata
;
1033 SMB_OFF_T file_size
= 0;
1034 SMB_BIG_UINT allocation_size
= 0;
1036 time_t mdate
=0, adate
=0, cdate
=0;
1038 char *last_entry_ptr
;
1040 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1041 BOOL needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1042 BOOL check_mangled_names
= lp_manglednames(SNUM(conn
));
1045 *out_of_space
= False
;
1046 *got_exact_match
= False
;
1051 p
= strrchr_m(path_mask
,'/');
1054 pstrcpy(mask
,"*.*");
1058 pstrcpy(mask
, path_mask
);
1063 /* Needed if we run out of space */
1064 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1065 dname
= dptr_ReadDirName(conn
->dirptr
,&curr_dirpos
,&sbuf
);
1068 * Due to bugs in NT client redirectors we are not using
1069 * resume keys any more - set them to zero.
1070 * Check out the related comments in findfirst/findnext.
1076 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1077 (long)conn
->dirptr
,curr_dirpos
));
1082 pstrcpy(fname
,dname
);
1084 if(!(got_match
= *got_exact_match
= exact_match(fname
, mask
, conn
->case_sensitive
)))
1085 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1087 if(!got_match
&& check_mangled_names
&& !mangle_is_8_3(fname
, False
, SNUM(conn
))) {
1090 * It turns out that NT matches wildcards against
1091 * both long *and* short names. This may explain some
1092 * of the wildcard wierdness from old DOS clients
1093 * that some people have been seeing.... JRA.
1097 pstrcpy( newname
, fname
);
1098 mangle_map( newname
, True
, False
, SNUM(conn
));
1099 if(!(got_match
= *got_exact_match
= exact_match(newname
, mask
, conn
->case_sensitive
)))
1100 got_match
= mask_match(newname
, mask
, conn
->case_sensitive
);
1104 BOOL isdots
= (strequal(fname
,"..") || strequal(fname
,"."));
1105 if (dont_descend
&& !isdots
)
1108 pstrcpy(pathreal
,conn
->dirpath
);
1110 pstrcat(pathreal
,"/");
1111 pstrcat(pathreal
,dname
);
1113 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1114 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1115 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1116 pathreal
,strerror(errno
)));
1119 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1121 /* Needed to show the msdfs symlinks as
1124 if(lp_host_msdfs() &&
1125 lp_msdfs_root(SNUM(conn
)) &&
1126 is_msdfs_link(NULL
,conn
, pathreal
, NULL
, NULL
,
1129 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal
));
1130 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
1134 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1135 pathreal
,strerror(errno
)));
1140 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1142 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1143 DEBUG(5,("[%s] attribs didn't match %x\n",fname
,dirtype
));
1147 file_size
= get_file_size(sbuf
);
1148 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1149 mdate
= sbuf
.st_mtime
;
1150 adate
= sbuf
.st_atime
;
1151 cdate
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1153 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1160 /* This is necessary, as otherwise the
1161 * desktop.ini file in this folder is
1163 mode
|= (lp_profile_acls(SNUM(conn
)) ? aRONLY
: 0);
1167 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal
,fname
));
1173 mangle_map(fname
,False
,True
,SNUM(conn
));
1178 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1180 switch (info_level
) {
1181 case SMB_FIND_INFO_STANDARD
:
1182 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1183 if(requires_resume_key
) {
1187 put_dos_date2(p
,0,cdate
);
1188 put_dos_date2(p
,4,adate
);
1189 put_dos_date2(p
,8,mdate
);
1190 SIVAL(p
,12,(uint32
)file_size
);
1191 SIVAL(p
,16,(uint32
)allocation_size
);
1195 p
+= align_string(outbuf
, p
, 0);
1196 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
1197 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1199 SCVAL(nameptr
, -1, len
- 2);
1201 SCVAL(nameptr
, -1, 0);
1205 SCVAL(nameptr
, -1, len
- 1);
1207 SCVAL(nameptr
, -1, 0);
1213 case SMB_FIND_EA_SIZE
:
1214 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1215 if(requires_resume_key
) {
1219 put_dos_date2(p
,0,cdate
);
1220 put_dos_date2(p
,4,adate
);
1221 put_dos_date2(p
,8,mdate
);
1222 SIVAL(p
,12,(uint32
)file_size
);
1223 SIVAL(p
,16,(uint32
)allocation_size
);
1226 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1227 SIVAL(p
,22,ea_size
); /* Extended attributes */
1231 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
1232 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1245 SCVAL(nameptr
,0,len
);
1247 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1250 case SMB_FIND_EA_LIST
:
1252 struct ea_list
*file_list
= NULL
;
1255 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1259 if(requires_resume_key
) {
1263 put_dos_date2(p
,0,cdate
);
1264 put_dos_date2(p
,4,adate
);
1265 put_dos_date2(p
,8,mdate
);
1266 SIVAL(p
,12,(uint32
)file_size
);
1267 SIVAL(p
,16,(uint32
)allocation_size
);
1269 p
+= 22; /* p now points to the EA area. */
1271 file_list
= get_ea_list_from_file(ea_ctx
, conn
, NULL
, pathreal
, &ea_len
);
1272 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1274 /* We need to determine if this entry will fit in the space available. */
1275 /* Max string size is 255 bytes. */
1276 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1277 /* Move the dirptr back to prev_dirpos */
1278 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1279 *out_of_space
= True
;
1280 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1281 return False
; /* Not finished - just out of space */
1284 /* Push the ea_data followed by the name. */
1285 p
+= fill_ea_buffer(ea_ctx
, p
, space_remaining
, conn
, name_list
);
1287 len
= srvstr_push(outbuf
, p
+ 1, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
1288 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1301 SCVAL(nameptr
,0,len
);
1303 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1307 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1308 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1309 was_8_3
= mangle_is_8_3(fname
, True
, SNUM(conn
));
1311 SIVAL(p
,0,reskey
); p
+= 4;
1312 put_long_date(p
,cdate
); p
+= 8;
1313 put_long_date(p
,adate
); p
+= 8;
1314 put_long_date(p
,mdate
); p
+= 8;
1315 put_long_date(p
,mdate
); p
+= 8;
1316 SOFF_T(p
,0,file_size
); p
+= 8;
1317 SOFF_T(p
,0,allocation_size
); p
+= 8;
1318 SIVAL(p
,0,nt_extmode
); p
+= 4;
1319 q
= p
; p
+= 4; /* q is placeholder for name length. */
1321 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1322 SIVAL(p
,0,ea_size
); /* Extended attributes */
1325 /* Clear the short name buffer. This is
1326 * IMPORTANT as not doing so will trigger
1327 * a Win2k client bug. JRA.
1329 if (!was_8_3
&& check_mangled_names
) {
1330 pstring mangled_name
;
1331 pstrcpy(mangled_name
, fname
);
1332 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
1333 mangled_name
[12] = 0;
1334 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1336 memset(p
+ 2 + len
,'\0',24 - len
);
1343 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1346 SIVAL(p
,0,0); /* Ensure any padding is null. */
1347 len
= PTR_DIFF(p
, pdata
);
1348 len
= (len
+ 3) & ~3;
1353 case SMB_FIND_FILE_DIRECTORY_INFO
:
1354 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1356 SIVAL(p
,0,reskey
); p
+= 4;
1357 put_long_date(p
,cdate
); p
+= 8;
1358 put_long_date(p
,adate
); p
+= 8;
1359 put_long_date(p
,mdate
); p
+= 8;
1360 put_long_date(p
,mdate
); p
+= 8;
1361 SOFF_T(p
,0,file_size
); p
+= 8;
1362 SOFF_T(p
,0,allocation_size
); p
+= 8;
1363 SIVAL(p
,0,nt_extmode
); p
+= 4;
1364 len
= srvstr_push(outbuf
, p
+ 4, fname
, -1, STR_TERMINATE_ASCII
);
1367 SIVAL(p
,0,0); /* Ensure any padding is null. */
1368 len
= PTR_DIFF(p
, pdata
);
1369 len
= (len
+ 3) & ~3;
1374 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1375 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1377 SIVAL(p
,0,reskey
); p
+= 4;
1378 put_long_date(p
,cdate
); p
+= 8;
1379 put_long_date(p
,adate
); p
+= 8;
1380 put_long_date(p
,mdate
); p
+= 8;
1381 put_long_date(p
,mdate
); p
+= 8;
1382 SOFF_T(p
,0,file_size
); p
+= 8;
1383 SOFF_T(p
,0,allocation_size
); p
+= 8;
1384 SIVAL(p
,0,nt_extmode
); p
+= 4;
1385 q
= p
; p
+= 4; /* q is placeholder for name length. */
1387 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1388 SIVAL(p
,0,ea_size
); /* Extended attributes */
1391 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1395 SIVAL(p
,0,0); /* Ensure any padding is null. */
1396 len
= PTR_DIFF(p
, pdata
);
1397 len
= (len
+ 3) & ~3;
1402 case SMB_FIND_FILE_NAMES_INFO
:
1403 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1405 SIVAL(p
,0,reskey
); p
+= 4;
1407 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1408 acl on a dir (tridge) */
1409 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1412 SIVAL(p
,0,0); /* Ensure any padding is null. */
1413 len
= PTR_DIFF(p
, pdata
);
1414 len
= (len
+ 3) & ~3;
1419 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1420 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1422 SIVAL(p
,0,reskey
); p
+= 4;
1423 put_long_date(p
,cdate
); p
+= 8;
1424 put_long_date(p
,adate
); p
+= 8;
1425 put_long_date(p
,mdate
); p
+= 8;
1426 put_long_date(p
,mdate
); p
+= 8;
1427 SOFF_T(p
,0,file_size
); p
+= 8;
1428 SOFF_T(p
,0,allocation_size
); p
+= 8;
1429 SIVAL(p
,0,nt_extmode
); p
+= 4;
1430 q
= p
; p
+= 4; /* q is placeholder for name length. */
1432 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1433 SIVAL(p
,0,ea_size
); /* Extended attributes */
1436 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1437 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4;
1438 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4;
1439 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1442 SIVAL(p
,0,0); /* Ensure any padding is null. */
1443 len
= PTR_DIFF(p
, pdata
);
1444 len
= (len
+ 3) & ~3;
1449 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1450 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1451 was_8_3
= mangle_is_8_3(fname
, True
, SNUM(conn
));
1453 SIVAL(p
,0,reskey
); p
+= 4;
1454 put_long_date(p
,cdate
); p
+= 8;
1455 put_long_date(p
,adate
); p
+= 8;
1456 put_long_date(p
,mdate
); p
+= 8;
1457 put_long_date(p
,mdate
); p
+= 8;
1458 SOFF_T(p
,0,file_size
); p
+= 8;
1459 SOFF_T(p
,0,allocation_size
); p
+= 8;
1460 SIVAL(p
,0,nt_extmode
); p
+= 4;
1461 q
= p
; p
+= 4; /* q is placeholder for name length */
1463 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1464 SIVAL(p
,0,ea_size
); /* Extended attributes */
1467 /* Clear the short name buffer. This is
1468 * IMPORTANT as not doing so will trigger
1469 * a Win2k client bug. JRA.
1471 if (!was_8_3
&& check_mangled_names
) {
1472 pstring mangled_name
;
1473 pstrcpy(mangled_name
, fname
);
1474 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
1475 mangled_name
[12] = 0;
1476 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1479 memset(p
+ 2 + len
,'\0',24 - len
);
1486 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1487 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4;
1488 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4;
1489 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1492 SIVAL(p
,0,0); /* Ensure any padding is null. */
1493 len
= PTR_DIFF(p
, pdata
);
1494 len
= (len
+ 3) & ~3;
1499 /* CIFS UNIX Extension. */
1501 case SMB_FIND_FILE_UNIX
:
1502 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1504 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1506 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1507 SOFF_T(p
,0,get_file_size(sbuf
)); /* File size 64 Bit */
1510 SOFF_T(p
,0,get_allocation_size(conn
,NULL
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
1513 put_long_date(p
,sbuf
.st_ctime
); /* Inode change Time 64 Bit */
1514 put_long_date(p
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
1515 put_long_date(p
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
1518 SIVAL(p
,0,sbuf
.st_uid
); /* user id for the owner */
1522 SIVAL(p
,0,sbuf
.st_gid
); /* group id of owner */
1526 SIVAL(p
,0,unix_filetype(sbuf
.st_mode
));
1529 SIVAL(p
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
1533 SIVAL(p
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
1537 SINO_T(p
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
1540 SIVAL(p
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
1544 SIVAL(p
,0,sbuf
.st_nlink
); /* number of hard links */
1548 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
1550 SIVAL(p
,0,0); /* Ensure any padding is null. */
1552 len
= PTR_DIFF(p
, pdata
);
1553 len
= (len
+ 3) & ~3;
1554 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1556 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1565 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1568 *out_of_space
= True
;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False
; /* Not finished - just out of space */
1573 /* Setup the last entry pointer, as an offset from base_data */
1574 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1575 /* Advance the data pointer to the next slot */
1581 /****************************************************************************
1582 Reply to a TRANS2_FINDFIRST.
1583 ****************************************************************************/
1585 static int call_trans2findfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
1586 char **pparams
, int total_params
, char **ppdata
, int total_data
,
1587 unsigned int max_data_bytes
)
1589 /* We must be careful here that we don't return more than the
1590 allowed number of data bytes. If this means returning fewer than
1591 maxentries then so be it. We assume that the redirector has
1592 enough room for the fixed number of parameter bytes it has
1594 char *params
= *pparams
;
1595 char *pdata
= *ppdata
;
1596 uint32 dirtype
= SVAL(params
,0);
1597 int maxentries
= SVAL(params
,2);
1598 uint16 findfirst_flags
= SVAL(params
,4);
1599 BOOL close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1600 BOOL close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1601 BOOL requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1602 int info_level
= SVAL(params
,6);
1606 int last_entry_off
=0;
1610 BOOL finished
= False
;
1611 BOOL dont_descend
= False
;
1612 BOOL out_of_space
= False
;
1613 int space_remaining
;
1614 BOOL bad_path
= False
;
1615 SMB_STRUCT_STAT sbuf
;
1616 TALLOC_CTX
*ea_ctx
= NULL
;
1617 struct ea_list
*ea_list
= NULL
;
1618 NTSTATUS ntstatus
= NT_STATUS_OK
;
1620 if (total_params
< 12) {
1621 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1624 *directory
= *mask
= 0;
1626 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1627 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1628 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1629 info_level
, max_data_bytes
));
1632 /* W2K3 seems to treat zero as 1. */
1636 switch (info_level
) {
1637 case SMB_FIND_INFO_STANDARD
:
1638 case SMB_FIND_EA_SIZE
:
1639 case SMB_FIND_EA_LIST
:
1640 case SMB_FIND_FILE_DIRECTORY_INFO
:
1641 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1642 case SMB_FIND_FILE_NAMES_INFO
:
1643 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1644 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1645 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1647 case SMB_FIND_FILE_UNIX
:
1648 if (!lp_unix_extensions())
1649 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1652 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1655 srvstr_get_path(inbuf
, directory
, params
+12, sizeof(directory
), -1, STR_TERMINATE
, &ntstatus
, True
);
1656 if (!NT_STATUS_IS_OK(ntstatus
)) {
1657 return ERROR_NT(ntstatus
);
1660 RESOLVE_DFSPATH_WCARD(directory
, conn
, inbuf
, outbuf
);
1662 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
1664 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
1666 if(!check_name(directory
,conn
)) {
1667 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1670 p
= strrchr_m(directory
,'/');
1672 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1673 if((directory
[0] == '.') && (directory
[1] == '\0'))
1676 pstrcpy(mask
,directory
);
1677 pstrcpy(directory
,"./");
1683 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
1685 if (info_level
== SMB_FIND_EA_LIST
) {
1688 if (total_data
< 4) {
1689 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1692 ea_size
= IVAL(pdata
,0);
1693 if (ea_size
!= total_data
) {
1694 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1695 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
1696 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1699 if (!lp_ea_support(SNUM(conn
))) {
1700 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
1703 if ((ea_ctx
= talloc_init("findnext_ea_list")) == NULL
) {
1704 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1707 /* Pull out the list of names. */
1708 ea_list
= read_ea_name_list(ea_ctx
, pdata
+ 4, ea_size
- 4);
1710 talloc_destroy(ea_ctx
);
1711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1715 pdata
= SMB_REALLOC(*ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1716 if( pdata
== NULL
) {
1717 talloc_destroy(ea_ctx
);
1718 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1723 /* Realloc the params space */
1724 params
= SMB_REALLOC(*pparams
, 10);
1725 if (params
== NULL
) {
1726 talloc_destroy(ea_ctx
);
1727 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1731 /* Save the wildcard match and attribs we are using on this directory -
1732 needed as lanman2 assumes these are being saved between calls */
1734 dptr_num
= dptr_create(conn
,directory
, False
, True
,SVAL(inbuf
,smb_pid
), mask
, dirtype
);
1736 talloc_destroy(ea_ctx
);
1737 return(UNIXERROR(ERRDOS
,ERRbadfile
));
1740 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num
, mask
, dirtype
));
1742 /* We don't need to check for VOL here as this is returned by
1743 a different TRANS2 call. */
1745 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1746 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
1747 dont_descend
= True
;
1750 space_remaining
= max_data_bytes
;
1751 out_of_space
= False
;
1753 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1754 BOOL got_exact_match
= False
;
1756 /* this is a heuristic to avoid seeking the dirptr except when
1757 absolutely necessary. It allows for a filename of about 40 chars */
1758 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1759 out_of_space
= True
;
1762 finished
= !get_lanman2_dir_entry(conn
,
1764 mask
,dirtype
,info_level
,
1765 requires_resume_key
,dont_descend
,
1766 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1767 &last_entry_off
, ea_list
, ea_ctx
);
1770 if (finished
&& out_of_space
)
1773 if (!finished
&& !out_of_space
)
1777 * As an optimisation if we know we aren't looking
1778 * for a wildcard name (ie. the name matches the wildcard exactly)
1779 * then we can finish on any (first) match.
1780 * This speeds up large directory searches. JRA.
1786 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1789 talloc_destroy(ea_ctx
);
1791 /* Check if we can close the dirptr */
1792 if(close_after_first
|| (finished
&& close_if_end
)) {
1793 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1794 dptr_close(&dptr_num
);
1798 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1799 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800 * the protocol level is less than NT1. Tested with smbclient. JRA.
1801 * This should fix the OS/2 client bug #2335.
1804 if(numentries
== 0) {
1805 dptr_close(&dptr_num
);
1806 if (Protocol
< PROTOCOL_NT1
) {
1807 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1809 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE
,ERRDOS
,ERRbadfile
);
1813 /* At this point pdata points to numentries directory entries. */
1815 /* Set up the return parameter block */
1816 SSVAL(params
,0,dptr_num
);
1817 SSVAL(params
,2,numentries
);
1818 SSVAL(params
,4,finished
);
1819 SSVAL(params
,6,0); /* Never an EA error */
1820 SSVAL(params
,8,last_entry_off
);
1822 send_trans2_replies( outbuf
, bufsize
, params
, 10, pdata
, PTR_DIFF(p
,pdata
));
1824 if ((! *directory
) && dptr_path(dptr_num
))
1825 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1827 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828 smb_fn_name(CVAL(inbuf
,smb_com
)),
1829 mask
, directory
, dirtype
, numentries
) );
1832 * Force a name mangle here to ensure that the
1833 * mask as an 8.3 name is top of the mangled cache.
1834 * The reasons for this are subtle. Don't remove
1835 * this code unless you know what you are doing
1836 * (see PR#13758). JRA.
1839 if(!mangle_is_8_3_wildcards( mask
, False
, SNUM(conn
)))
1840 mangle_map(mask
, True
, True
, SNUM(conn
));
1845 /****************************************************************************
1846 Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1849 static int call_trans2findnext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
1850 char **pparams
, int total_params
, char **ppdata
, int total_data
,
1851 unsigned int max_data_bytes
)
1853 /* We must be careful here that we don't return more than the
1854 allowed number of data bytes. If this means returning fewer than
1855 maxentries then so be it. We assume that the redirector has
1856 enough room for the fixed number of parameter bytes it has
1858 char *params
= *pparams
;
1859 char *pdata
= *ppdata
;
1860 int dptr_num
= SVAL(params
,0);
1861 int maxentries
= SVAL(params
,2);
1862 uint16 info_level
= SVAL(params
,4);
1863 uint32 resume_key
= IVAL(params
,6);
1864 uint16 findnext_flags
= SVAL(params
,10);
1865 BOOL close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
1866 BOOL close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1867 BOOL requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1868 BOOL continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
1869 pstring resume_name
;
1875 int i
, last_entry_off
=0;
1876 BOOL finished
= False
;
1877 BOOL dont_descend
= False
;
1878 BOOL out_of_space
= False
;
1879 int space_remaining
;
1880 TALLOC_CTX
*ea_ctx
= NULL
;
1881 struct ea_list
*ea_list
= NULL
;
1882 NTSTATUS ntstatus
= NT_STATUS_OK
;
1884 if (total_params
< 12) {
1885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1888 *mask
= *directory
= *resume_name
= 0;
1890 srvstr_get_path(inbuf
, resume_name
, params
+12, sizeof(resume_name
), -1, STR_TERMINATE
, &ntstatus
, True
);
1891 if (!NT_STATUS_IS_OK(ntstatus
)) {
1892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1893 complain (it thinks we're asking for the directory above the shared
1894 path or an invalid name). Catch this as the resume name is only compared, never used in
1895 a file access. JRA. */
1896 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_OBJECT_PATH_SYNTAX_BAD
)) {
1897 pstrcpy(resume_name
, "..");
1898 } else if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_OBJECT_NAME_INVALID
)) {
1899 pstrcpy(resume_name
, ".");
1901 return ERROR_NT(ntstatus
);
1905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1907 resume_key = %d resume name = %s continue=%d level = %d\n",
1908 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
1909 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
1912 /* W2K3 seems to treat zero as 1. */
1916 switch (info_level
) {
1917 case SMB_FIND_INFO_STANDARD
:
1918 case SMB_FIND_EA_SIZE
:
1919 case SMB_FIND_EA_LIST
:
1920 case SMB_FIND_FILE_DIRECTORY_INFO
:
1921 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1922 case SMB_FIND_FILE_NAMES_INFO
:
1923 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1925 case SMB_FIND_FILE_UNIX
:
1926 if (!lp_unix_extensions())
1927 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1930 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1933 if (info_level
== SMB_FIND_EA_LIST
) {
1936 if (total_data
< 4) {
1937 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1940 ea_size
= IVAL(pdata
,0);
1941 if (ea_size
!= total_data
) {
1942 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1943 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
1944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1947 if (!lp_ea_support(SNUM(conn
))) {
1948 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
1951 if ((ea_ctx
= talloc_init("findnext_ea_list")) == NULL
) {
1952 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1955 /* Pull out the list of names. */
1956 ea_list
= read_ea_name_list(ea_ctx
, pdata
+ 4, ea_size
- 4);
1958 talloc_destroy(ea_ctx
);
1959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1963 pdata
= SMB_REALLOC( *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1965 talloc_destroy(ea_ctx
);
1966 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1971 /* Realloc the params space */
1972 params
= SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
1973 if( params
== NULL
) {
1974 talloc_destroy(ea_ctx
);
1975 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1980 /* Check that the dptr is valid */
1981 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
1982 talloc_destroy(ea_ctx
);
1983 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1986 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1988 /* Get the wildcard mask from the dptr */
1989 if((p
= dptr_wcard(dptr_num
))== NULL
) {
1990 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
1991 talloc_destroy(ea_ctx
);
1992 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1996 pstrcpy(directory
,conn
->dirpath
);
1998 /* Get the attr mask from the dptr */
1999 dirtype
= dptr_attr(dptr_num
);
2001 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2002 dptr_num
, mask
, dirtype
,
2004 dptr_TellDir(conn
->dirptr
)));
2006 /* We don't need to check for VOL here as this is returned by
2007 a different TRANS2 call. */
2009 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2010 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2011 dont_descend
= True
;
2014 space_remaining
= max_data_bytes
;
2015 out_of_space
= False
;
2018 * Seek to the correct position. We no longer use the resume key but
2019 * depend on the last file name instead.
2022 if(*resume_name
&& !continue_bit
) {
2025 long current_pos
= 0;
2027 * Remember, mangle_map is called by
2028 * get_lanman2_dir_entry(), so the resume name
2029 * could be mangled. Ensure we check the unmangled name.
2032 if (mangle_is_mangled(resume_name
, SNUM(conn
))) {
2033 mangle_check_cache(resume_name
, sizeof(resume_name
)-1, SNUM(conn
));
2037 * Fix for NT redirector problem triggered by resume key indexes
2038 * changing between directory scans. We now return a resume key of 0
2039 * and instead look for the filename to continue from (also given
2040 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2041 * findfirst/findnext (as is usual) then the directory pointer
2042 * should already be at the correct place.
2045 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2046 } /* end if resume_name && !continue_bit */
2048 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2049 BOOL got_exact_match
= False
;
2051 /* this is a heuristic to avoid seeking the dirptr except when
2052 absolutely necessary. It allows for a filename of about 40 chars */
2053 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2054 out_of_space
= True
;
2057 finished
= !get_lanman2_dir_entry(conn
,
2059 mask
,dirtype
,info_level
,
2060 requires_resume_key
,dont_descend
,
2061 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
2062 &last_entry_off
, ea_list
, ea_ctx
);
2065 if (finished
&& out_of_space
)
2068 if (!finished
&& !out_of_space
)
2072 * As an optimisation if we know we aren't looking
2073 * for a wildcard name (ie. the name matches the wildcard exactly)
2074 * then we can finish on any (first) match.
2075 * This speeds up large directory searches. JRA.
2081 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2084 talloc_destroy(ea_ctx
);
2086 /* Check if we can close the dirptr */
2087 if(close_after_request
|| (finished
&& close_if_end
)) {
2088 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2089 dptr_close(&dptr_num
); /* This frees up the saved mask */
2092 /* Set up the return parameter block */
2093 SSVAL(params
,0,numentries
);
2094 SSVAL(params
,2,finished
);
2095 SSVAL(params
,4,0); /* Never an EA error */
2096 SSVAL(params
,6,last_entry_off
);
2098 send_trans2_replies( outbuf
, bufsize
, params
, 8, pdata
, PTR_DIFF(p
,pdata
));
2100 if ((! *directory
) && dptr_path(dptr_num
))
2101 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
2103 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2104 smb_fn_name(CVAL(inbuf
,smb_com
)),
2105 mask
, directory
, dirtype
, numentries
) );
2110 /****************************************************************************
2111 Reply to a TRANS2_QFSINFO (query filesystem info).
2112 ****************************************************************************/
2114 static int call_trans2qfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
2115 char **pparams
, int total_params
, char **ppdata
, int total_data
,
2116 unsigned int max_data_bytes
)
2118 char *pdata
= *ppdata
;
2119 char *params
= *pparams
;
2120 uint16 info_level
= SVAL(params
,0);
2123 char *vname
= volume_label(SNUM(conn
));
2124 int snum
= SNUM(conn
);
2125 char *fstype
= lp_fstype(SNUM(conn
));
2128 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2130 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2131 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2132 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
2135 pdata
= SMB_REALLOC(*ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2136 if ( pdata
== NULL
) {
2137 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2141 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2143 switch (info_level
) {
2144 case SMB_INFO_ALLOCATION
:
2146 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2148 if (SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2149 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2152 block_size
= lp_block_size(snum
);
2153 if (bsize
< block_size
) {
2154 SMB_BIG_UINT factor
= block_size
/bsize
;
2159 if (bsize
> block_size
) {
2160 SMB_BIG_UINT factor
= bsize
/block_size
;
2165 bytes_per_sector
= 512;
2166 sectors_per_unit
= bsize
/bytes_per_sector
;
2168 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2169 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2170 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2172 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2173 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2174 SIVAL(pdata
,l1_cUnit
,dsize
);
2175 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2176 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2180 case SMB_INFO_VOLUME
:
2181 /* Return volume name */
2183 * Add volume serial number - hash of a combination of
2184 * the called hostname and the service name.
2186 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2188 * Win2k3 and previous mess this up by sending a name length
2189 * one byte short. I believe only older clients (OS/2 Win9x) use
2190 * this call so try fixing this by adding a terminating null to
2191 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2193 len
= srvstr_push(outbuf
, pdata
+l2_vol_szVolLabel
, vname
, -1, STR_NOALIGN
|STR_TERMINATE
);
2194 SCVAL(pdata
,l2_vol_cch
,len
);
2195 data_len
= l2_vol_szVolLabel
+ len
;
2196 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2197 (unsigned)st
.st_ctime
, len
, vname
));
2200 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2201 case SMB_FS_ATTRIBUTE_INFORMATION
:
2204 #if defined(HAVE_SYS_QUOTAS)
2205 quota_flag
= FILE_VOLUME_QUOTAS
;
2208 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2209 (lp_nt_acl_support(SNUM(conn
)) ? FILE_PERSISTENT_ACLS
: 0)|
2210 quota_flag
); /* FS ATTRIBUTES */
2212 SIVAL(pdata
,4,255); /* Max filename component length */
2213 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2214 and will think we can't do long filenames */
2215 len
= srvstr_push(outbuf
, pdata
+12, fstype
, -1, STR_UNICODE
);
2217 data_len
= 12 + len
;
2220 case SMB_QUERY_FS_LABEL_INFO
:
2221 case SMB_FS_LABEL_INFORMATION
:
2222 len
= srvstr_push(outbuf
, pdata
+4, vname
, -1, 0);
2227 case SMB_QUERY_FS_VOLUME_INFO
:
2228 case SMB_FS_VOLUME_INFORMATION
:
2231 * Add volume serial number - hash of a combination of
2232 * the called hostname and the service name.
2234 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2235 (str_checksum(get_local_machine_name())<<16));
2237 len
= srvstr_push(outbuf
, pdata
+18, vname
, -1, STR_UNICODE
);
2238 SIVAL(pdata
,12,len
);
2240 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2241 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2244 case SMB_QUERY_FS_SIZE_INFO
:
2245 case SMB_FS_SIZE_INFORMATION
:
2247 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2249 if (SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2250 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2252 block_size
= lp_block_size(snum
);
2253 if (bsize
< block_size
) {
2254 SMB_BIG_UINT factor
= block_size
/bsize
;
2259 if (bsize
> block_size
) {
2260 SMB_BIG_UINT factor
= bsize
/block_size
;
2265 bytes_per_sector
= 512;
2266 sectors_per_unit
= bsize
/bytes_per_sector
;
2267 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2268 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2269 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2270 SBIG_UINT(pdata
,0,dsize
);
2271 SBIG_UINT(pdata
,8,dfree
);
2272 SIVAL(pdata
,16,sectors_per_unit
);
2273 SIVAL(pdata
,20,bytes_per_sector
);
2277 case SMB_FS_FULL_SIZE_INFORMATION
:
2279 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2281 if (SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2282 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2284 block_size
= lp_block_size(snum
);
2285 if (bsize
< block_size
) {
2286 SMB_BIG_UINT factor
= block_size
/bsize
;
2291 if (bsize
> block_size
) {
2292 SMB_BIG_UINT factor
= bsize
/block_size
;
2297 bytes_per_sector
= 512;
2298 sectors_per_unit
= bsize
/bytes_per_sector
;
2299 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2300 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2301 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2302 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2303 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2304 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2305 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2306 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2310 case SMB_QUERY_FS_DEVICE_INFO
:
2311 case SMB_FS_DEVICE_INFORMATION
:
2313 SIVAL(pdata
,0,0); /* dev type */
2314 SIVAL(pdata
,4,0); /* characteristics */
2317 #ifdef HAVE_SYS_QUOTAS
2318 case SMB_FS_QUOTA_INFORMATION
:
2320 * what we have to send --metze:
2322 * Unknown1: 24 NULL bytes
2323 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2324 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2325 * Quota Flags: 2 byte :
2326 * Unknown3: 6 NULL bytes
2330 * details for Quota Flags:
2332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2335 * 0x0001 Enable Quotas: enable quota for this fs
2339 /* we need to fake up a fsp here,
2340 * because its not send in this call
2343 SMB_NTQUOTA_STRUCT quotas
;
2346 ZERO_STRUCT(quotas
);
2353 if (current_user
.uid
!= 0) {
2354 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2355 lp_servicename(SNUM(conn
)),conn
->user
));
2356 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2359 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2360 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2361 return ERROR_DOS(ERRSRV
,ERRerror
);
2366 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2368 /* Unknown1 24 NULL bytes*/
2369 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2370 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2371 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2373 /* Default Soft Quota 8 bytes */
2374 SBIG_UINT(pdata
,24,quotas
.softlim
);
2376 /* Default Hard Quota 8 bytes */
2377 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2379 /* Quota flag 2 bytes */
2380 SSVAL(pdata
,40,quotas
.qflags
);
2382 /* Unknown3 6 NULL bytes */
2388 #endif /* HAVE_SYS_QUOTAS */
2389 case SMB_FS_OBJECTID_INFORMATION
:
2394 * Query the version and capabilities of the CIFS UNIX extensions
2398 case SMB_QUERY_CIFS_UNIX_INFO
:
2399 if (!lp_unix_extensions())
2400 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2402 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2403 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2404 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(CIFS_UNIX_POSIX_ACLS_CAP
|
2405 CIFS_UNIX_POSIX_PATHNAMES_CAP
))); /* We have POSIX ACLs and pathname capability. */
2408 case SMB_MAC_QUERY_FS_INFO
:
2410 * Thursby MAC extension... ONLY on NTFS filesystems
2411 * once we do streams then we don't need this
2413 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2415 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2420 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2424 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
);
2426 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf
,smb_com
)), info_level
) );
2431 /****************************************************************************
2432 Reply to a TRANS2_SETFSINFO (set filesystem info).
2433 ****************************************************************************/
2435 static int call_trans2setfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
2436 char **pparams
, int total_params
, char **ppdata
, int total_data
,
2437 unsigned int max_data_bytes
)
2439 char *pdata
= *ppdata
;
2440 char *params
= *pparams
;
2444 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
2447 if (total_params
< 4) {
2448 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2450 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2453 info_level
= SVAL(params
,2);
2455 switch(info_level
) {
2456 case SMB_SET_CIFS_UNIX_INFO
:
2458 uint16 client_unix_major
;
2459 uint16 client_unix_minor
;
2460 uint32 client_unix_cap_low
;
2461 uint32 client_unix_cap_high
;
2463 if (!lp_unix_extensions()) {
2464 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2467 /* There should be 12 bytes of capabilities set. */
2468 if (total_data
< 8) {
2469 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2471 client_unix_major
= SVAL(pdata
,0);
2472 client_unix_minor
= SVAL(pdata
,2);
2473 client_unix_cap_low
= IVAL(pdata
,4);
2474 client_unix_cap_high
= IVAL(pdata
,8);
2475 /* Just print these values for now. */
2476 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2477 cap_low = 0x%x, cap_high = 0x%x\n",
2478 (unsigned int)client_unix_major
,
2479 (unsigned int)client_unix_minor
,
2480 (unsigned int)client_unix_cap_low
,
2481 (unsigned int)client_unix_cap_high
));
2483 /* Here is where we must switch to posix pathname processing... */
2484 lp_set_posix_pathnames();
2485 mangle_change_to_posix();
2488 case SMB_FS_QUOTA_INFORMATION
:
2490 files_struct
*fsp
= NULL
;
2491 SMB_NTQUOTA_STRUCT quotas
;
2493 ZERO_STRUCT(quotas
);
2496 if ((current_user
.uid
!= 0)||!CAN_WRITE(conn
)) {
2497 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2498 lp_servicename(SNUM(conn
)),conn
->user
));
2499 return ERROR_DOS(ERRSRV
,ERRaccess
);
2502 /* note: normaly there're 48 bytes,
2503 * but we didn't use the last 6 bytes for now
2506 fsp
= file_fsp(params
,0);
2507 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
2508 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2509 return ERROR_NT(NT_STATUS_INVALID_HANDLE
);
2512 if (total_data
< 42) {
2513 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2518 /* unknown_1 24 NULL bytes in pdata*/
2520 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2521 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
2522 #ifdef LARGE_SMB_OFF_T
2523 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
2524 #else /* LARGE_SMB_OFF_T */
2525 if ((IVAL(pdata
,28) != 0)&&
2526 ((quotas
.softlim
!= 0xFFFFFFFF)||
2527 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
2528 /* more than 32 bits? */
2529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2531 #endif /* LARGE_SMB_OFF_T */
2533 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2534 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
2535 #ifdef LARGE_SMB_OFF_T
2536 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
2537 #else /* LARGE_SMB_OFF_T */
2538 if ((IVAL(pdata
,36) != 0)&&
2539 ((quotas
.hardlim
!= 0xFFFFFFFF)||
2540 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
2541 /* more than 32 bits? */
2542 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2544 #endif /* LARGE_SMB_OFF_T */
2546 /* quota_flags 2 bytes **/
2547 quotas
.qflags
= SVAL(pdata
,40);
2549 /* unknown_2 6 NULL bytes follow*/
2551 /* now set the quotas */
2552 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2553 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2554 return ERROR_DOS(ERRSRV
,ERRerror
);
2560 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2562 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2567 * sending this reply works fine,
2568 * but I'm not sure it's the same
2569 * like windows do...
2572 outsize
= set_message(outbuf
,10,0,True
);
2577 /****************************************************************************
2578 Utility function to set bad path error.
2579 ****************************************************************************/
2581 int set_bad_path_error(int err
, BOOL bad_path
, char *outbuf
, int def_class
, uint32 def_code
)
2583 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2584 err
, (int)bad_path
));
2588 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
2590 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2593 return UNIXERROR(def_class
,def_code
);
2596 #if defined(HAVE_POSIX_ACLS)
2597 /****************************************************************************
2598 Utility function to count the number of entries in a POSIX acl.
2599 ****************************************************************************/
2601 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2603 unsigned int ace_count
= 0;
2604 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2605 SMB_ACL_ENTRY_T entry
;
2607 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
2609 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2610 entry_id
= SMB_ACL_NEXT_ENTRY
;
2617 /****************************************************************************
2618 Utility function to marshall a POSIX acl into wire format.
2619 ****************************************************************************/
2621 static BOOL
marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2623 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2624 SMB_ACL_ENTRY_T entry
;
2626 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
2627 SMB_ACL_TAG_T tagtype
;
2628 SMB_ACL_PERMSET_T permset
;
2629 unsigned char perms
= 0;
2630 unsigned int own_grp
;
2633 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2634 entry_id
= SMB_ACL_NEXT_ENTRY
;
2637 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
2638 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2642 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
2643 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2647 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2648 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2649 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2651 SCVAL(pdata
,1,perms
);
2654 case SMB_ACL_USER_OBJ
:
2655 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2656 own_grp
= (unsigned int)pst
->st_uid
;
2657 SIVAL(pdata
,2,own_grp
);
2662 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
2664 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2666 own_grp
= (unsigned int)*puid
;
2667 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
2668 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2669 SIVAL(pdata
,2,own_grp
);
2673 case SMB_ACL_GROUP_OBJ
:
2674 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2675 own_grp
= (unsigned int)pst
->st_gid
;
2676 SIVAL(pdata
,2,own_grp
);
2681 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
2683 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2685 own_grp
= (unsigned int)*pgid
;
2686 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
2687 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2688 SIVAL(pdata
,2,own_grp
);
2693 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2694 SIVAL(pdata
,2,0xFFFFFFFF);
2695 SIVAL(pdata
,6,0xFFFFFFFF);
2698 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2699 SIVAL(pdata
,2,0xFFFFFFFF);
2700 SIVAL(pdata
,6,0xFFFFFFFF);
2703 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2706 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2713 /****************************************************************************
2714 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2715 file name or file id).
2716 ****************************************************************************/
2718 static int call_trans2qfilepathinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
2719 unsigned int tran_call
,
2720 char **pparams
, int total_params
, char **ppdata
, int total_data
,
2721 unsigned int max_data_bytes
)
2723 char *params
= *pparams
;
2724 char *pdata
= *ppdata
;
2728 SMB_OFF_T file_size
=0;
2729 SMB_BIG_UINT allocation_size
=0;
2730 unsigned int data_size
= 0;
2731 unsigned int param_size
= 2;
2732 SMB_STRUCT_STAT sbuf
;
2733 pstring fname
, dos_fname
;
2738 BOOL bad_path
= False
;
2739 BOOL delete_pending
= False
;
2742 files_struct
*fsp
= NULL
;
2743 TALLOC_CTX
*ea_ctx
= NULL
;
2744 struct ea_list
*ea_list
= NULL
;
2745 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2752 if (tran_call
== TRANSACT2_QFILEINFO
) {
2753 if (total_params
< 4) {
2754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2757 fsp
= file_fsp(params
,0);
2758 info_level
= SVAL(params
,2);
2760 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
2762 if(fsp
&& (fsp
->fake_file_handle
)) {
2764 * This is actually for the QUOTA_FAKE_FILE --metze
2767 pstrcpy(fname
, fsp
->fsp_name
);
2768 /* We know this name is ok, it's already passed the checks. */
2770 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
2772 * This is actually a QFILEINFO on a directory
2773 * handle (returned from an NT SMB). NT5.0 seems
2774 * to do this call. JRA.
2776 /* We know this name is ok, it's already passed the checks. */
2777 pstrcpy(fname
, fsp
->fsp_name
);
2779 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2780 /* Always do lstat for UNIX calls. */
2781 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
2782 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
2783 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2785 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
2786 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
2787 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2791 get_delete_on_close_flag(sbuf
.st_dev
,
2795 * Original code - this is an open file.
2797 CHECK_FSP(fsp
,conn
);
2799 pstrcpy(fname
, fsp
->fsp_name
);
2800 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&sbuf
) != 0) {
2801 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
2802 return(UNIXERROR(ERRDOS
,ERRbadfid
));
2804 pos
= fsp
->fh
->position_information
;
2806 get_delete_on_close_flag(sbuf
.st_dev
,
2808 access_mask
= fsp
->access_mask
;
2811 NTSTATUS status
= NT_STATUS_OK
;
2814 if (total_params
< 6) {
2815 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2818 info_level
= SVAL(params
,0);
2820 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
2822 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
, &status
, False
);
2823 if (!NT_STATUS_IS_OK(status
)) {
2824 return ERROR_NT(status
);
2827 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
2829 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2831 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
2833 if (!check_name(fname
,conn
)) {
2834 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
2835 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2838 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2839 /* Always do lstat for UNIX calls. */
2840 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
2841 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
2842 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2844 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
2845 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
2846 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2849 delete_pending
= get_delete_on_close_flag(sbuf
.st_dev
,
2851 if (delete_pending
) {
2852 return ERROR_NT(NT_STATUS_DELETE_PENDING
);
2856 nlink
= sbuf
.st_nlink
;
2858 if ((nlink
> 0) && S_ISDIR(sbuf
.st_mode
)) {
2859 /* NTFS does not seem to count ".." */
2863 if ((nlink
> 0) && delete_pending
) {
2867 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
2868 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2870 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2871 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
2873 p
= strrchr_m(fname
,'/');
2879 mode
= dos_mode(conn
,fname
,&sbuf
);
2881 mode
= FILE_ATTRIBUTE_NORMAL
;
2883 fullpathname
= fname
;
2884 file_size
= get_file_size(sbuf
);
2886 /* This is necessary, as otherwise the desktop.ini file in
2887 * this folder is ignored */
2888 mode
|= (lp_profile_acls(SNUM(conn
)) ? aRONLY
: 0);
2892 /* Pull any EA list from the data portion. */
2893 if (info_level
== SMB_INFO_QUERY_EAS_FROM_LIST
) {
2896 if (total_data
< 4) {
2897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2899 ea_size
= IVAL(pdata
,0);
2901 if (total_data
> 0 && ea_size
!= total_data
) {
2902 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2903 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2904 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2907 if (!lp_ea_support(SNUM(conn
))) {
2908 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
2911 if ((ea_ctx
= talloc_init("ea_list")) == NULL
) {
2912 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2915 /* Pull out the list of names. */
2916 ea_list
= read_ea_name_list(ea_ctx
, pdata
+ 4, ea_size
- 4);
2918 talloc_destroy(ea_ctx
);
2919 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2923 params
= SMB_REALLOC(*pparams
,2);
2924 if (params
== NULL
) {
2925 talloc_destroy(ea_ctx
);
2926 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2930 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
2931 pdata
= SMB_REALLOC(*ppdata
, data_size
);
2932 if ( pdata
== NULL
) {
2933 talloc_destroy(ea_ctx
);
2934 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2938 c_time
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
2940 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
2943 if (fsp
->pending_modtime
) {
2944 /* the pending modtime overrides the current modtime */
2945 sbuf
.st_mtime
= fsp
->pending_modtime
;
2948 /* Do we have this path open ? */
2949 files_struct
*fsp1
= file_find_di_first(sbuf
.st_dev
, sbuf
.st_ino
);
2950 if (fsp1
&& fsp1
->pending_modtime
) {
2951 /* the pending modtime overrides the current modtime */
2952 sbuf
.st_mtime
= fsp1
->pending_modtime
;
2954 if (fsp1
&& fsp1
->initial_allocation_size
) {
2955 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
2959 if (lp_dos_filetime_resolution(SNUM(conn
))) {
2961 sbuf
.st_atime
&= ~1;
2962 sbuf
.st_ctime
&= ~1;
2963 sbuf
.st_mtime
&= ~1;
2966 /* NT expects the name to be in an exact form of the *full*
2967 filename. See the trans2 torture test */
2968 if (strequal(base_name
,".")) {
2969 pstrcpy(dos_fname
, "\\");
2971 pstr_sprintf(dos_fname
, "\\%s", fname
);
2972 string_replace(dos_fname
, '/', '\\');
2975 switch (info_level
) {
2976 case SMB_INFO_STANDARD
:
2977 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2979 put_dos_date2(pdata
,l1_fdateCreation
,c_time
);
2980 put_dos_date2(pdata
,l1_fdateLastAccess
,sbuf
.st_atime
);
2981 put_dos_date2(pdata
,l1_fdateLastWrite
,sbuf
.st_mtime
); /* write time */
2982 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
2983 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
2984 SSVAL(pdata
,l1_attrFile
,mode
);
2987 case SMB_INFO_QUERY_EA_SIZE
:
2989 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
2990 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2992 put_dos_date2(pdata
,0,c_time
);
2993 put_dos_date2(pdata
,4,sbuf
.st_atime
);
2994 put_dos_date2(pdata
,8,sbuf
.st_mtime
); /* write time */
2995 SIVAL(pdata
,12,(uint32
)file_size
);
2996 SIVAL(pdata
,16,(uint32
)allocation_size
);
2997 SSVAL(pdata
,20,mode
);
2998 SIVAL(pdata
,22,ea_size
);
3002 case SMB_INFO_IS_NAME_VALID
:
3003 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3004 if (tran_call
== TRANSACT2_QFILEINFO
) {
3005 /* os/2 needs this ? really ?*/
3006 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
3012 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3014 size_t total_ea_len
= 0;
3015 struct ea_list
*ea_file_list
= NULL
;
3017 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3019 ea_file_list
= get_ea_list_from_file(ea_ctx
, conn
, fsp
, fname
, &total_ea_len
);
3020 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3022 if (!ea_list
|| (total_ea_len
> data_size
)) {
3023 talloc_destroy(ea_ctx
);
3025 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3029 data_size
= fill_ea_buffer(ea_ctx
, pdata
, data_size
, conn
, ea_list
);
3030 talloc_destroy(ea_ctx
);
3034 case SMB_INFO_QUERY_ALL_EAS
:
3036 /* We have data_size bytes to put EA's into. */
3037 size_t total_ea_len
= 0;
3039 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3041 ea_ctx
= talloc_init("ea_ctx");
3043 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3046 ea_list
= get_ea_list_from_file(ea_ctx
, conn
, fsp
, fname
, &total_ea_len
);
3047 if (!ea_list
|| (total_ea_len
> data_size
)) {
3048 talloc_destroy(ea_ctx
);
3050 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3054 data_size
= fill_ea_buffer(ea_ctx
, pdata
, data_size
, conn
, ea_list
);
3055 talloc_destroy(ea_ctx
);
3059 case SMB_FILE_BASIC_INFORMATION
:
3060 case SMB_QUERY_FILE_BASIC_INFO
:
3062 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3063 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3064 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3066 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3070 put_long_date(pdata
,c_time
);
3071 put_long_date(pdata
+8,sbuf
.st_atime
);
3072 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
3073 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
3074 SIVAL(pdata
,32,mode
);
3076 DEBUG(5,("SMB_QFBI - "));
3078 time_t create_time
= c_time
;
3079 DEBUG(5,("create: %s ", ctime(&create_time
)));
3081 DEBUG(5,("access: %s ", ctime(&sbuf
.st_atime
)));
3082 DEBUG(5,("write: %s ", ctime(&sbuf
.st_mtime
)));
3083 DEBUG(5,("change: %s ", ctime(&sbuf
.st_mtime
)));
3084 DEBUG(5,("mode: %x\n", mode
));
3087 case SMB_FILE_STANDARD_INFORMATION
:
3088 case SMB_QUERY_FILE_STANDARD_INFO
:
3090 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3092 SOFF_T(pdata
,0,allocation_size
);
3093 SOFF_T(pdata
,8,file_size
);
3094 SIVAL(pdata
,16,nlink
);
3095 SCVAL(pdata
,20,delete_pending
?1:0);
3096 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
3097 SSVAL(pdata
,22,0); /* Padding. */
3100 case SMB_FILE_EA_INFORMATION
:
3101 case SMB_QUERY_FILE_EA_INFO
:
3103 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3104 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3106 SIVAL(pdata
,0,ea_size
);
3110 /* Get the 8.3 name - used if NT SMB was negotiated. */
3111 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3112 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3116 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3117 pstrcpy(short_name
,base_name
);
3118 /* Mangle if not already 8.3 */
3119 if(!mangle_is_8_3(short_name
, True
, SNUM(conn
))) {
3120 mangle_map(short_name
,True
,True
,SNUM(conn
));
3122 len
= srvstr_push(outbuf
, pdata
+4, short_name
, -1, STR_UNICODE
);
3123 data_size
= 4 + len
;
3128 case SMB_QUERY_FILE_NAME_INFO
:
3130 this must be *exactly* right for ACLs on mapped drives to work
3132 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
3133 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3134 data_size
= 4 + len
;
3138 case SMB_FILE_ALLOCATION_INFORMATION
:
3139 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3140 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3142 SOFF_T(pdata
,0,allocation_size
);
3145 case SMB_FILE_END_OF_FILE_INFORMATION
:
3146 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3147 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3149 SOFF_T(pdata
,0,file_size
);
3152 case SMB_QUERY_FILE_ALL_INFO
:
3153 case SMB_FILE_ALL_INFORMATION
:
3155 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3156 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3157 put_long_date(pdata
,c_time
);
3158 put_long_date(pdata
+8,sbuf
.st_atime
);
3159 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
3160 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
3161 SIVAL(pdata
,32,mode
);
3162 SIVAL(pdata
,36,0); /* padding. */
3164 SOFF_T(pdata
,0,allocation_size
);
3165 SOFF_T(pdata
,8,file_size
);
3166 SIVAL(pdata
,16,nlink
);
3167 SCVAL(pdata
,20,delete_pending
);
3168 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
3171 SIVAL(pdata
,0,ea_size
);
3172 pdata
+= 4; /* EA info */
3173 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
3176 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3179 case SMB_FILE_INTERNAL_INFORMATION
:
3180 /* This should be an index number - looks like
3183 I think this causes us to fail the IFSKIT
3184 BasicFileInformationTest. -tpot */
3186 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3187 SIVAL(pdata
,0,sbuf
.st_dev
);
3188 SIVAL(pdata
,4,sbuf
.st_ino
);
3192 case SMB_FILE_ACCESS_INFORMATION
:
3193 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3194 SIVAL(pdata
,0,access_mask
);
3198 case SMB_FILE_NAME_INFORMATION
:
3199 /* Pathname with leading '\'. */
3202 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,max_data_bytes
,False
);
3203 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3204 SIVAL(pdata
,0,byte_len
);
3205 data_size
= 4 + byte_len
;
3209 case SMB_FILE_DISPOSITION_INFORMATION
:
3210 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3212 SCVAL(pdata
,0,delete_pending
);
3215 case SMB_FILE_POSITION_INFORMATION
:
3216 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3218 SOFF_T(pdata
,0,pos
);
3221 case SMB_FILE_MODE_INFORMATION
:
3222 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3223 SIVAL(pdata
,0,mode
);
3227 case SMB_FILE_ALIGNMENT_INFORMATION
:
3228 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3229 SIVAL(pdata
,0,0); /* No alignment needed. */
3235 * NT4 server just returns "invalid query" to this - if we try to answer
3236 * it then NTws gets a BSOD! (tridge).
3237 * W2K seems to want this. JRA.
3239 case SMB_QUERY_FILE_STREAM_INFO
:
3241 case SMB_FILE_STREAM_INFORMATION
:
3242 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3246 size_t byte_len
= dos_PutUniCode(pdata
+24,"::$DATA", 0xE, False
);
3247 SIVAL(pdata
,0,0); /* ??? */
3248 SIVAL(pdata
,4,byte_len
); /* Byte length of unicode string ::$DATA */
3249 SOFF_T(pdata
,8,file_size
);
3250 SIVAL(pdata
,16,allocation_size
);
3251 SIVAL(pdata
,20,0); /* ??? */
3252 data_size
= 24 + byte_len
;
3256 case SMB_QUERY_COMPRESSION_INFO
:
3257 case SMB_FILE_COMPRESSION_INFORMATION
:
3258 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3259 SOFF_T(pdata
,0,file_size
);
3260 SIVAL(pdata
,8,0); /* ??? */
3261 SIVAL(pdata
,12,0); /* ??? */
3265 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3267 put_long_date(pdata
,c_time
);
3268 put_long_date(pdata
+8,sbuf
.st_atime
);
3269 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
3270 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
3271 SIVAL(pdata
,32,allocation_size
);
3272 SOFF_T(pdata
,40,file_size
);
3273 SIVAL(pdata
,48,mode
);
3274 SIVAL(pdata
,52,0); /* ??? */
3278 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3279 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3280 SIVAL(pdata
,0,mode
);
3286 * CIFS UNIX Extensions.
3289 case SMB_QUERY_FILE_UNIX_BASIC
:
3291 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3292 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf
.st_mode
));
3294 SOFF_T(pdata
,0,get_file_size(sbuf
)); /* File size 64 Bit */
3297 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
3300 put_long_date(pdata
,sbuf
.st_ctime
); /* Creation Time 64 Bit */
3301 put_long_date(pdata
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
3302 put_long_date(pdata
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
3305 SIVAL(pdata
,0,sbuf
.st_uid
); /* user id for the owner */
3309 SIVAL(pdata
,0,sbuf
.st_gid
); /* group id of owner */
3313 SIVAL(pdata
,0,unix_filetype(sbuf
.st_mode
));
3316 SIVAL(pdata
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
3320 SIVAL(pdata
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
3324 SINO_T(pdata
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
3327 SIVAL(pdata
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
3331 SIVAL(pdata
,0,sbuf
.st_nlink
); /* number of hard links */
3334 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3338 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3340 for (i
=0; i
<100; i
++)
3341 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
3347 case SMB_QUERY_FILE_UNIX_LINK
:
3351 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3353 if(!S_ISLNK(sbuf
.st_mode
))
3354 return(UNIXERROR(ERRSRV
,ERRbadlink
));
3356 return(UNIXERROR(ERRDOS
,ERRbadlink
));
3358 len
= SMB_VFS_READLINK(conn
,fullpathname
, buffer
, sizeof(pstring
)-1); /* read link */
3360 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3362 len
= srvstr_push(outbuf
, pdata
, buffer
, -1, STR_TERMINATE
);
3364 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3369 #if defined(HAVE_POSIX_ACLS)
3370 case SMB_QUERY_POSIX_ACL
:
3372 SMB_ACL_T file_acl
= NULL
;
3373 SMB_ACL_T def_acl
= NULL
;
3374 uint16 num_file_acls
= 0;
3375 uint16 num_def_acls
= 0;
3377 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
3378 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, fsp
->fh
->fd
);
3380 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
3383 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
3384 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3386 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED
);
3389 if (S_ISDIR(sbuf
.st_mode
)) {
3390 if (fsp
&& fsp
->is_directory
) {
3391 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
3393 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
3395 def_acl
= free_empty_sys_acl(conn
, def_acl
);
3398 num_file_acls
= count_acl_entries(conn
, file_acl
);
3399 num_def_acls
= count_acl_entries(conn
, def_acl
);
3401 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
3402 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3404 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
3405 SMB_POSIX_ACL_HEADER_SIZE
) ));
3407 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3410 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3412 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL
);
3415 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
3416 SSVAL(pdata
,2,num_file_acls
);
3417 SSVAL(pdata
,4,num_def_acls
);
3418 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
3420 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3423 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3425 return ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
3427 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
3429 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3432 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3434 return ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
3438 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3441 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3443 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
3449 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3452 send_trans2_replies(outbuf
, bufsize
, params
, param_size
, *ppdata
, data_size
);
3457 /****************************************************************************
3458 Deal with the internal needs of setting the delete on close flag. Note that
3459 as the tdb locking is recursive, it is safe to call this from within
3460 open_file_shared. JRA.
3461 ****************************************************************************/
3463 NTSTATUS
can_set_delete_on_close(files_struct
*fsp
, BOOL delete_on_close
,
3466 if (!delete_on_close
) {
3467 return NT_STATUS_OK
;
3471 * Only allow delete on close for writable files.
3474 if ((dosmode
& aRONLY
) &&
3475 !lp_delete_readonly(SNUM(fsp
->conn
))) {
3476 DEBUG(10,("can_set_delete_on_close: file %s delete on close "
3477 "flag set but file attribute is readonly.\n",
3479 return NT_STATUS_CANNOT_DELETE
;
3483 * Only allow delete on close for writable shares.
3486 if (!CAN_WRITE(fsp
->conn
)) {
3487 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3488 "close flag set but write access denied on share.\n",
3490 return NT_STATUS_ACCESS_DENIED
;
3494 * Only allow delete on close for files/directories opened with delete
3498 if (!(fsp
->access_mask
& DELETE_ACCESS
)) {
3499 DEBUG(10,("can_set_delete_on_close: file %s delete on "
3500 "close flag set but delete access denied.\n",
3502 return NT_STATUS_ACCESS_DENIED
;
3505 return NT_STATUS_OK
;
3508 /****************************************************************************
3509 Sets the delete on close flag over all share modes on this file.
3510 Modify the share mode entry for all files open
3511 on this device and inode to tell other smbds we have
3512 changed the delete on close flag. This will be noticed
3513 in the close code, the last closer will delete the file
3515 ****************************************************************************/
3517 NTSTATUS
set_delete_on_close(files_struct
*fsp
, BOOL delete_on_close
)
3519 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
3520 "fnum = %d, file %s\n",
3521 delete_on_close
? "Adding" : "Removing", fsp
->fnum
,
3524 if (fsp
->is_directory
|| fsp
->is_stat
)
3525 return NT_STATUS_OK
;
3527 if (lock_share_entry_fsp(fsp
) == False
)
3528 return NT_STATUS_ACCESS_DENIED
;
3530 if (!modify_delete_flag(fsp
->dev
, fsp
->inode
, delete_on_close
)) {
3531 DEBUG(0,("set_delete_on_close: failed to change delete "
3532 "on close flag for file %s\n",
3534 unlock_share_entry_fsp(fsp
);
3535 return NT_STATUS_ACCESS_DENIED
;
3538 unlock_share_entry_fsp(fsp
);
3539 return NT_STATUS_OK
;
3542 /****************************************************************************
3543 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3545 ****************************************************************************/
3547 NTSTATUS
hardlink_internals(connection_struct
*conn
, char *oldname
, char *newname
)
3549 BOOL bad_path_oldname
= False
;
3550 BOOL bad_path_newname
= False
;
3551 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3552 pstring last_component_oldname
;
3553 pstring last_component_newname
;
3554 NTSTATUS status
= NT_STATUS_OK
;
3560 if (ms_has_wild(newname
) || ms_has_wild(oldname
)) {
3561 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
3564 unix_convert(oldname
,conn
,last_component_oldname
,&bad_path_oldname
,&sbuf1
);
3565 if (bad_path_oldname
) {
3566 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3569 /* Quick check for "." and ".." */
3570 if (last_component_oldname
[0] == '.') {
3571 if (!last_component_oldname
[1] || (last_component_oldname
[1] == '.' && !last_component_oldname
[2])) {
3572 return NT_STATUS_OBJECT_NAME_INVALID
;
3576 /* source must already exist. */
3577 if (!VALID_STAT(sbuf1
)) {
3578 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3581 if (!check_name(oldname
,conn
)) {
3582 return NT_STATUS_ACCESS_DENIED
;
3585 unix_convert(newname
,conn
,last_component_newname
,&bad_path_newname
,&sbuf2
);
3586 if (bad_path_newname
) {
3587 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3590 /* Quick check for "." and ".." */
3591 if (last_component_newname
[0] == '.') {
3592 if (!last_component_newname
[1] || (last_component_newname
[1] == '.' && !last_component_newname
[2])) {
3593 return NT_STATUS_OBJECT_NAME_INVALID
;
3597 /* Disallow if newname already exists. */
3598 if (VALID_STAT(sbuf2
)) {
3599 return NT_STATUS_OBJECT_NAME_COLLISION
;
3602 if (!check_name(newname
,conn
)) {
3603 return NT_STATUS_ACCESS_DENIED
;
3606 /* No links from a directory. */
3607 if (S_ISDIR(sbuf1
.st_mode
)) {
3608 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3611 /* Ensure this is within the share. */
3612 if (!reduce_name(conn
, oldname
) != 0)
3613 return NT_STATUS_ACCESS_DENIED
;
3615 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
3617 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
3618 status
= map_nt_error_from_unix(errno
);
3619 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3620 nt_errstr(status
), newname
, oldname
));
3626 /****************************************************************************
3627 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3628 ****************************************************************************/
3630 static int call_trans2setfilepathinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
3631 unsigned int tran_call
,
3632 char **pparams
, int total_params
, char **ppdata
, int total_data
,
3633 unsigned int max_data_bytes
)
3635 char *params
= *pparams
;
3636 char *pdata
= *ppdata
;
3641 SMB_STRUCT_STAT sbuf
;
3644 BOOL bad_path
= False
;
3645 files_struct
*fsp
= NULL
;
3646 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
3647 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
3648 mode_t unixmode
= 0;
3649 NTSTATUS status
= NT_STATUS_OK
;
3652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3657 if (tran_call
== TRANSACT2_SETFILEINFO
) {
3658 if (total_params
< 4) {
3659 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3662 fsp
= file_fsp(params
,0);
3663 info_level
= SVAL(params
,2);
3665 if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3667 * This is actually a SETFILEINFO on a directory
3668 * handle (returned from an NT SMB). NT5.0 seems
3669 * to do this call. JRA.
3671 pstrcpy(fname
, fsp
->fsp_name
);
3672 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
3673 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
3674 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3676 } else if (fsp
&& fsp
->print_file
) {
3678 * Doing a DELETE_ON_CLOSE should cancel a print job.
3680 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
3681 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
3683 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
3686 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3689 return (UNIXERROR(ERRDOS
,ERRbadpath
));
3692 * Original code - this is an open file.
3694 CHECK_FSP(fsp
,conn
);
3696 pstrcpy(fname
, fsp
->fsp_name
);
3699 if (SMB_VFS_FSTAT(fsp
,fd
,&sbuf
) != 0) {
3700 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
3701 return(UNIXERROR(ERRDOS
,ERRbadfid
));
3706 if (total_params
< 6) {
3707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3710 info_level
= SVAL(params
,0);
3711 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
, &status
, False
);
3712 if (!NT_STATUS_IS_OK(status
)) {
3713 return ERROR_NT(status
);
3715 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
3717 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
3721 * For CIFS UNIX extensions the target name may not exist.
3724 if(!VALID_STAT(sbuf
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
3725 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname
, strerror(errno
)));
3726 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3729 if(!check_name(fname
, conn
)) {
3730 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3735 if (!CAN_WRITE(conn
))
3736 return ERROR_DOS(ERRSRV
,ERRaccess
);
3738 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
3739 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3741 if (VALID_STAT(sbuf
))
3742 unixmode
= sbuf
.st_mode
;
3744 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3745 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
3747 /* Realloc the parameter size */
3748 params
= SMB_REALLOC(*pparams
,2);
3749 if(params
== NULL
) {
3750 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3756 if (fsp
&& fsp
->pending_modtime
) {
3757 /* the pending modtime overrides the current modtime */
3758 sbuf
.st_mtime
= fsp
->pending_modtime
;
3761 size
= get_file_size(sbuf
);
3762 tvs
.modtime
= sbuf
.st_mtime
;
3763 tvs
.actime
= sbuf
.st_atime
;
3764 dosmode
= dos_mode(conn
,fname
,&sbuf
);
3765 unixmode
= sbuf
.st_mode
;
3767 set_owner
= VALID_STAT(sbuf
) ? sbuf
.st_uid
: (uid_t
)SMB_UID_NO_CHANGE
;
3768 set_grp
= VALID_STAT(sbuf
) ? sbuf
.st_gid
: (gid_t
)SMB_GID_NO_CHANGE
;
3770 switch (info_level
) {
3771 case SMB_INFO_STANDARD
:
3773 if (total_data
< 12) {
3774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3778 tvs
.actime
= make_unix_date2(pdata
+l1_fdateLastAccess
);
3780 tvs
.modtime
= make_unix_date2(pdata
+l1_fdateLastWrite
);
3784 case SMB_INFO_SET_EA
:
3786 struct ea_list
*ea_list
= NULL
;
3787 TALLOC_CTX
*ctx
= NULL
;
3789 if (total_data
< 10) {
3790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3793 if (IVAL(pdata
,0) > total_data
) {
3794 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3795 IVAL(pdata
,0), (unsigned int)total_data
));
3796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3799 ctx
= talloc_init("SMB_INFO_SET_EA");
3801 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3803 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
3805 talloc_destroy(ctx
);
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3808 status
= set_ea(conn
, fsp
, fname
, ea_list
);
3809 talloc_destroy(ctx
);
3811 if (!NT_STATUS_IS_OK(status
)) {
3812 return ERROR_NT(status
);
3815 /* We're done. We only get EA info in this call. */
3817 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3822 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3823 /* XXXX um, i don't think this is right.
3824 it's also not in the cifs6.txt spec.
3826 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3827 if (total_data
< 28)
3828 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3830 tvs
.actime
= make_unix_date2(pdata
+8);
3831 tvs
.modtime
= make_unix_date2(pdata
+12);
3832 size
= IVAL(pdata
,16);
3833 dosmode
= IVAL(pdata
,24);
3836 /* XXXX nor this. not in cifs6.txt, either. */
3837 case SMB_INFO_QUERY_ALL_EAS
:
3838 if (total_data
< 28)
3839 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3841 tvs
.actime
= make_unix_date2(pdata
+8);
3842 tvs
.modtime
= make_unix_date2(pdata
+12);
3843 size
= IVAL(pdata
,16);
3844 dosmode
= IVAL(pdata
,24);
3848 case SMB_SET_FILE_BASIC_INFO
:
3849 case SMB_FILE_BASIC_INFORMATION
:
3851 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3853 time_t changed_time
;
3855 if (total_data
< 36) {
3856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3859 /* Ignore create time at offset pdata. */
3862 tvs
.actime
= interpret_long_date(pdata
+8);
3864 write_time
= interpret_long_date(pdata
+16);
3865 changed_time
= interpret_long_date(pdata
+24);
3867 tvs
.modtime
= MIN(write_time
, changed_time
);
3869 if (write_time
> tvs
.modtime
&& write_time
!= (time_t)-1) {
3870 tvs
.modtime
= write_time
;
3872 /* Prefer a defined time to an undefined one. */
3873 if (null_mtime(tvs
.modtime
)) {
3874 tvs
.modtime
= null_mtime(write_time
) ? changed_time
: write_time
;
3878 dosmode
= IVAL(pdata
,32);
3882 case SMB_FILE_ALLOCATION_INFORMATION
:
3883 case SMB_SET_FILE_ALLOCATION_INFO
:
3886 SMB_BIG_UINT allocation_size
;
3888 if (total_data
< 8) {
3889 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3892 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
3893 #ifdef LARGE_SMB_OFF_T
3894 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
3895 #else /* LARGE_SMB_OFF_T */
3896 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3897 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3898 #endif /* LARGE_SMB_OFF_T */
3899 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3900 fname
, (double)allocation_size
));
3902 if (allocation_size
) {
3903 allocation_size
= smb_roundup(conn
, allocation_size
);
3906 if(allocation_size
!= get_file_size(sbuf
)) {
3907 SMB_STRUCT_STAT new_sbuf
;
3909 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3910 fname
, (double)allocation_size
));
3913 files_struct
*new_fsp
= NULL
;
3915 if(global_oplock_break
) {
3916 /* Queue this file modify as we are the process of an oplock break. */
3918 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3919 DEBUGADD(2,( "in oplock break state.\n"));
3921 push_oplock_pending_smb_message(inbuf
, length
);
3925 new_fsp
= open_file_ntcreate(conn
, fname
, &sbuf
,
3927 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
3930 FILE_ATTRIBUTE_NORMAL
,
3934 if (new_fsp
== NULL
) {
3935 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3937 ret
= vfs_allocate_file_space(new_fsp
, allocation_size
);
3938 if (SMB_VFS_FSTAT(new_fsp
,new_fsp
->fh
->fd
,&new_sbuf
) != 0) {
3939 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3940 new_fsp
->fnum
, strerror(errno
)));
3943 close_file(new_fsp
,True
);
3945 ret
= vfs_allocate_file_space(fsp
, allocation_size
);
3946 if (SMB_VFS_FSTAT(fsp
,fd
,&new_sbuf
) != 0) {
3947 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3948 fsp
->fnum
, strerror(errno
)));
3953 return ERROR_NT(NT_STATUS_DISK_FULL
);
3955 /* Allocate can truncate size... */
3956 size
= get_file_size(new_sbuf
);
3962 case SMB_FILE_END_OF_FILE_INFORMATION
:
3963 case SMB_SET_FILE_END_OF_FILE_INFO
:
3965 if (total_data
< 8) {
3966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3969 size
= IVAL(pdata
,0);
3970 #ifdef LARGE_SMB_OFF_T
3971 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
3972 #else /* LARGE_SMB_OFF_T */
3973 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3974 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3975 #endif /* LARGE_SMB_OFF_T */
3976 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname
, (double)size
));
3980 case SMB_FILE_DISPOSITION_INFORMATION
:
3981 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
3983 BOOL delete_on_close
;
3985 if (total_data
< 1) {
3986 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3989 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
3991 /* Just ignore this set on a path. */
3992 if (tran_call
!= TRANSACT2_SETFILEINFO
)
3996 return(UNIXERROR(ERRDOS
,ERRbadfid
));
3998 status
= can_set_delete_on_close(fsp
, delete_on_close
,
4001 if (!NT_STATUS_IS_OK(status
)) {
4002 return ERROR_NT(status
);
4005 /* The set is across all open files on this dev/inode pair. */
4006 status
=set_delete_on_close(fsp
, delete_on_close
);
4007 if (!NT_STATUS_IS_OK(status
)) {
4008 return ERROR_NT(status
);
4012 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4016 case SMB_FILE_POSITION_INFORMATION
:
4018 SMB_BIG_UINT position_information
;
4020 if (total_data
< 8) {
4021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4024 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
4025 #ifdef LARGE_SMB_OFF_T
4026 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
4027 #else /* LARGE_SMB_OFF_T */
4028 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
4029 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
4030 #endif /* LARGE_SMB_OFF_T */
4031 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4032 fname
, (double)position_information
));
4034 fsp
->fh
->position_information
= position_information
;
4037 /* We're done. We only get position info in this call. */
4039 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4043 /* From tridge Samba4 :
4044 * MODE_INFORMATION in setfileinfo (I have no
4045 * idea what "mode information" on a file is - it takes a value of 0,
4046 * 2, 4 or 6. What could it be?).
4049 case SMB_FILE_MODE_INFORMATION
:
4053 if (total_data
< 4) {
4054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4056 mode
= IVAL(pdata
,0);
4057 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4058 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4061 /* We're done. We only get mode info in this call. */
4063 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4068 * CIFS UNIX extensions.
4071 case SMB_SET_FILE_UNIX_BASIC
:
4073 uint32 raw_unixmode
;
4075 if (total_data
< 100) {
4076 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4079 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
4080 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
4081 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
4082 #ifdef LARGE_SMB_OFF_T
4083 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
4084 #else /* LARGE_SMB_OFF_T */
4085 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
4086 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
4087 #endif /* LARGE_SMB_OFF_T */
4089 pdata
+=24; /* ctime & st_blocks are not changed */
4090 tvs
.actime
= interpret_long_date(pdata
); /* access_time */
4091 tvs
.modtime
= interpret_long_date(pdata
+8); /* modification_time */
4093 set_owner
= (uid_t
)IVAL(pdata
,0);
4095 set_grp
= (gid_t
)IVAL(pdata
,0);
4097 raw_unixmode
= IVAL(pdata
,28);
4098 unixmode
= unix_perms_from_wire(conn
, &sbuf
, raw_unixmode
);
4099 dosmode
= 0; /* Ensure dos mode change doesn't override this. */
4101 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4102 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4103 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
4105 if (!VALID_STAT(sbuf
)) {
4108 * The only valid use of this is to create character and block
4109 * devices, and named pipes. This is deprecated (IMHO) and
4110 * a new info level should be used for mknod. JRA.
4113 uint32 file_type
= IVAL(pdata
,0);
4114 #if defined(HAVE_MAKEDEV)
4115 uint32 dev_major
= IVAL(pdata
,4);
4116 uint32 dev_minor
= IVAL(pdata
,12);
4119 uid_t myuid
= geteuid();
4120 gid_t mygid
= getegid();
4121 SMB_DEV_T dev
= (SMB_DEV_T
)0;
4123 if (tran_call
== TRANSACT2_SETFILEINFO
)
4124 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
4126 if (raw_unixmode
== SMB_MODE_NO_CHANGE
) {
4127 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4130 #if defined(HAVE_MAKEDEV)
4131 dev
= makedev(dev_major
, dev_minor
);
4134 /* We can only create as the owner/group we are. */
4136 if ((set_owner
!= myuid
) && (set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
))
4137 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
4138 if ((set_grp
!= mygid
) && (set_grp
!= (gid_t
)SMB_GID_NO_CHANGE
))
4139 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
4141 switch (file_type
) {
4142 #if defined(S_IFIFO)
4143 case UNIX_TYPE_FIFO
:
4144 unixmode
|= S_IFIFO
;
4147 #if defined(S_IFSOCK)
4148 case UNIX_TYPE_SOCKET
:
4149 unixmode
|= S_IFSOCK
;
4152 #if defined(S_IFCHR)
4153 case UNIX_TYPE_CHARDEV
:
4154 unixmode
|= S_IFCHR
;
4157 #if defined(S_IFBLK)
4158 case UNIX_TYPE_BLKDEV
:
4159 unixmode
|= S_IFBLK
;
4163 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
4166 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4167 0%o for file %s\n", (double)dev
, unixmode
, fname
));
4169 /* Ok - do the mknod. */
4170 if (SMB_VFS_MKNOD(conn
,fname
, unixmode
, dev
) != 0)
4171 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4173 inherit_access_acl(conn
, fname
, unixmode
);
4176 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4181 * Deal with the UNIX specific mode set.
4184 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
4185 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4186 (unsigned int)unixmode
, fname
));
4187 if (SMB_VFS_CHMOD(conn
,fname
,unixmode
) != 0)
4188 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4192 * Deal with the UNIX specific uid set.
4195 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (sbuf
.st_uid
!= set_owner
)) {
4196 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4197 (unsigned int)set_owner
, fname
));
4198 if (SMB_VFS_CHOWN(conn
,fname
,set_owner
, (gid_t
)-1) != 0)
4199 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4203 * Deal with the UNIX specific gid set.
4206 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (sbuf
.st_gid
!= set_grp
)) {
4207 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4208 (unsigned int)set_owner
, fname
));
4209 if (SMB_VFS_CHOWN(conn
,fname
,(uid_t
)-1, set_grp
) != 0)
4210 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4215 case SMB_SET_FILE_UNIX_LINK
:
4217 pstring link_target
;
4218 char *newname
= fname
;
4220 /* Set a symbolic link. */
4221 /* Don't allow this if follow links is false. */
4223 if (!lp_symlinks(SNUM(conn
)))
4224 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
4226 srvstr_pull(inbuf
, link_target
, pdata
, sizeof(link_target
), -1, STR_TERMINATE
);
4228 /* !widelinks forces the target path to be within the share. */
4229 /* This means we can interpret the target as a pathname. */
4230 if (!lp_widelinks(SNUM(conn
))) {
4232 char *last_dirp
= NULL
;
4234 unix_format(link_target
);
4235 if (*link_target
== '/') {
4236 /* No absolute paths allowed. */
4237 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4239 pstrcpy(rel_name
, newname
);
4240 last_dirp
= strrchr_m(rel_name
, '/');
4242 last_dirp
[1] = '\0';
4244 pstrcpy(rel_name
, "./");
4246 pstrcat(rel_name
, link_target
);
4248 if (!check_name(rel_name
, conn
)) {
4249 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4253 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4254 fname
, link_target
));
4256 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0)
4257 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4259 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4263 case SMB_SET_FILE_UNIX_HLINK
:
4266 char *newname
= fname
;
4268 /* Set a hard link. */
4269 srvstr_get_path(inbuf
, oldname
, pdata
, sizeof(oldname
), -1, STR_TERMINATE
, &status
, False
);
4270 if (!NT_STATUS_IS_OK(status
)) {
4271 return ERROR_NT(status
);
4274 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4277 status
= hardlink_internals(conn
, oldname
, newname
);
4278 if (!NT_STATUS_IS_OK(status
)) {
4279 return ERROR_NT(status
);
4283 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4287 case SMB_FILE_RENAME_INFORMATION
:
4296 if (total_data
< 12) {
4297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4300 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4301 root_fid
= IVAL(pdata
,4);
4302 len
= IVAL(pdata
,8);
4303 srvstr_get_path(inbuf
, newname
, &pdata
[12], sizeof(newname
), len
, 0, &status
, False
);
4304 if (!NT_STATUS_IS_OK(status
)) {
4305 return ERROR_NT(status
);
4308 /* Check the new name has no '/' characters. */
4309 if (strchr_m(newname
, '/'))
4310 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4312 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4314 /* Create the base directory. */
4315 pstrcpy(base_name
, fname
);
4316 p
= strrchr_m(base_name
, '/');
4319 /* Append the new name. */
4320 pstrcat(base_name
, "/");
4321 pstrcat(base_name
, newname
);
4324 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4325 fsp
->fnum
, fsp
->fsp_name
, base_name
));
4326 status
= rename_internals_fsp(conn
, fsp
, base_name
, 0, overwrite
);
4328 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4330 status
= rename_internals(conn
, fname
, base_name
, 0, overwrite
);
4332 if (!NT_STATUS_IS_OK(status
)) {
4333 return ERROR_NT(status
);
4335 process_pending_change_notify_queue((time_t)0);
4337 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4341 #if defined(HAVE_POSIX_ACLS)
4342 case SMB_SET_POSIX_ACL
:
4344 uint16 posix_acl_version
;
4345 uint16 num_file_acls
;
4346 uint16 num_def_acls
;
4347 BOOL valid_file_acls
= True
;
4348 BOOL valid_def_acls
= True
;
4350 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4351 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4353 posix_acl_version
= SVAL(pdata
,0);
4354 num_file_acls
= SVAL(pdata
,2);
4355 num_def_acls
= SVAL(pdata
,4);
4357 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4358 valid_file_acls
= False
;
4362 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4363 valid_def_acls
= False
;
4367 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4368 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4371 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
4372 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
4373 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4376 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
4377 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
4378 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4381 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, &sbuf
, num_def_acls
,
4382 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
4383 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
4384 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4388 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4394 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
4397 /* get some defaults (no modifications) if any info is zero or -1. */
4398 if (null_mtime(tvs
.actime
)) {
4399 tvs
.actime
= sbuf
.st_atime
;
4402 if (null_mtime(tvs
.modtime
)) {
4403 tvs
.modtime
= sbuf
.st_mtime
;
4406 DEBUG(6,("actime: %s " , ctime(&tvs
.actime
)));
4407 DEBUG(6,("modtime: %s ", ctime(&tvs
.modtime
)));
4408 DEBUG(6,("size: %.0f ", (double)size
));
4411 if (S_ISDIR(sbuf
.st_mode
))
4417 DEBUG(6,("dosmode: %x\n" , dosmode
));
4419 if(!((info_level
== SMB_SET_FILE_END_OF_FILE_INFO
) ||
4420 (info_level
== SMB_SET_FILE_ALLOCATION_INFO
) ||
4421 (info_level
== SMB_FILE_ALLOCATION_INFORMATION
) ||
4422 (info_level
== SMB_FILE_END_OF_FILE_INFORMATION
))) {
4425 * Only do this test if we are not explicitly
4426 * changing the size of a file.
4429 size
= get_file_size(sbuf
);
4433 * Try and set the times, size and mode of this file -
4434 * if they are different from the current values
4437 /* check the mode isn't different, before changing it */
4438 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, &sbuf
))) {
4440 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname
, dosmode
));
4442 if(file_set_dosmode(conn
, fname
, dosmode
, &sbuf
, False
)) {
4443 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname
, strerror(errno
)));
4444 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4449 if (size
!= get_file_size(sbuf
)) {
4453 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4454 fname
, (double)size
));
4457 files_struct
*new_fsp
= NULL
;
4459 if(global_oplock_break
) {
4460 /* Queue this file modify as we are the process of an oplock break. */
4462 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4463 DEBUGADD(2,( "in oplock break state.\n"));
4465 push_oplock_pending_smb_message(inbuf
, length
);
4469 new_fsp
= open_file_ntcreate(conn
, fname
, &sbuf
,
4471 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4474 FILE_ATTRIBUTE_NORMAL
,
4478 if (new_fsp
== NULL
) {
4479 return(UNIXERROR(ERRDOS
,ERRbadpath
));
4481 ret
= vfs_set_filelen(new_fsp
, size
);
4482 close_file(new_fsp
,True
);
4484 ret
= vfs_set_filelen(fsp
, size
);
4488 return (UNIXERROR(ERRHRD
,ERRdiskfull
));
4493 * Finally the times.
4495 if (sbuf
.st_mtime
!= tvs
.modtime
|| sbuf
.st_atime
!= tvs
.actime
) {
4498 * This was a setfileinfo on an open file.
4499 * NT does this a lot. We also need to
4500 * set the time here, as it can be read by
4501 * FindFirst/FindNext and with the patch for bug #2045
4502 * in smbd/fileio.c it ensures that this timestamp is
4503 * kept sticky even after a write. We save the request
4504 * away and will set it on file close and after a write. JRA.
4507 if (tvs
.modtime
!= (time_t)0 && tvs
.modtime
!= (time_t)-1) {
4508 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs
.modtime
) ));
4509 fsp_set_pending_modtime(fsp
, tvs
.modtime
);
4513 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4515 if(file_utime(conn
, fname
, &tvs
)!=0) {
4516 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4521 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4526 /****************************************************************************
4527 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4528 ****************************************************************************/
4530 static int call_trans2mkdir(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
4531 char **pparams
, int total_params
, char **ppdata
, int total_data
,
4532 unsigned int max_data_bytes
)
4534 char *params
= *pparams
;
4535 char *pdata
= *ppdata
;
4538 SMB_STRUCT_STAT sbuf
;
4539 BOOL bad_path
= False
;
4540 NTSTATUS status
= NT_STATUS_OK
;
4541 TALLOC_CTX
*ctx
= NULL
;
4542 struct ea_list
*ea_list
= NULL
;
4544 if (!CAN_WRITE(conn
))
4545 return ERROR_DOS(ERRSRV
,ERRaccess
);
4547 if (total_params
< 4) {
4548 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4551 srvstr_get_path(inbuf
, directory
, ¶ms
[4], sizeof(directory
), -1, STR_TERMINATE
, &status
, False
);
4552 if (!NT_STATUS_IS_OK(status
)) {
4553 return ERROR_NT(status
);
4556 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
4558 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
4560 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
4563 /* Any data in this call is an EA list. */
4564 if (total_data
&& !lp_ea_support(SNUM(conn
))) {
4565 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED
);
4569 if (total_data
< 10) {
4570 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4573 if (IVAL(pdata
,0) > total_data
) {
4574 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4575 IVAL(pdata
,0), (unsigned int)total_data
));
4576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4579 ctx
= talloc_init("TRANS2_MKDIR_SET_EA");
4581 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4583 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4585 talloc_destroy(ctx
);
4586 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4590 if (check_name(directory
,conn
)) {
4591 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
,True
));
4595 talloc_destroy(ctx
);
4596 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno
)));
4597 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
4600 /* Try and set any given EA. */
4602 status
= set_ea(conn
, NULL
, directory
, ea_list
);
4603 talloc_destroy(ctx
);
4604 if (!NT_STATUS_IS_OK(status
)) {
4605 return ERROR_NT(status
);
4609 /* Realloc the parameter and data sizes */
4610 params
= SMB_REALLOC(*pparams
,2);
4611 if(params
== NULL
) {
4612 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4618 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
4623 /****************************************************************************
4624 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4625 We don't actually do this - we just send a null response.
4626 ****************************************************************************/
4628 static int call_trans2findnotifyfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
4629 char **pparams
, int total_params
, char **ppdata
, int total_data
,
4630 unsigned int max_data_bytes
)
4632 static uint16 fnf_handle
= 257;
4633 char *params
= *pparams
;
4636 if (total_params
< 6) {
4637 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4640 info_level
= SVAL(params
,4);
4641 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
4643 switch (info_level
) {
4648 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
4651 /* Realloc the parameter and data sizes */
4652 params
= SMB_REALLOC(*pparams
,6);
4653 if(params
== NULL
) {
4654 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4658 SSVAL(params
,0,fnf_handle
);
4659 SSVAL(params
,2,0); /* No changes */
4660 SSVAL(params
,4,0); /* No EA errors */
4667 send_trans2_replies(outbuf
, bufsize
, params
, 6, *ppdata
, 0);
4672 /****************************************************************************
4673 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4674 changes). Currently this does nothing.
4675 ****************************************************************************/
4677 static int call_trans2findnotifynext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
4678 char **pparams
, int total_params
, char **ppdata
, int total_data
,
4679 unsigned int max_data_bytes
)
4681 char *params
= *pparams
;
4683 DEBUG(3,("call_trans2findnotifynext\n"));
4685 /* Realloc the parameter and data sizes */
4686 params
= SMB_REALLOC(*pparams
,4);
4687 if(params
== NULL
) {
4688 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4692 SSVAL(params
,0,0); /* No changes */
4693 SSVAL(params
,2,0); /* No EA errors */
4695 send_trans2_replies(outbuf
, bufsize
, params
, 4, *ppdata
, 0);
4700 /****************************************************************************
4701 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4702 ****************************************************************************/
4704 static int call_trans2getdfsreferral(connection_struct
*conn
, char* inbuf
, char* outbuf
, int length
, int bufsize
,
4705 char **pparams
, int total_params
, char **ppdata
, int total_data
,
4706 unsigned int max_data_bytes
)
4708 char *params
= *pparams
;
4711 int max_referral_level
;
4713 DEBUG(10,("call_trans2getdfsreferral\n"));
4715 if (total_params
< 2) {
4716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4719 max_referral_level
= SVAL(params
,0);
4721 if(!lp_host_msdfs())
4722 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
4724 srvstr_pull(inbuf
, pathname
, ¶ms
[2], sizeof(pathname
), -1, STR_TERMINATE
);
4725 if((reply_size
= setup_dfs_referral(conn
, pathname
,max_referral_level
,ppdata
)) < 0)
4726 return UNIXERROR(ERRDOS
,ERRbadfile
);
4728 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
4729 send_trans2_replies(outbuf
,bufsize
,0,0,*ppdata
,reply_size
);
4734 #define LMCAT_SPL 0x53
4735 #define LMFUNC_GETJOBID 0x60
4737 /****************************************************************************
4738 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4739 ****************************************************************************/
4741 static int call_trans2ioctl(connection_struct
*conn
, char* inbuf
, char* outbuf
, int length
, int bufsize
,
4742 char **pparams
, int total_params
, char **ppdata
, int total_data
,
4743 unsigned int max_data_bytes
)
4745 char *pdata
= *ppdata
;
4746 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv15
);
4748 /* check for an invalid fid before proceeding */
4751 return(ERROR_DOS(ERRDOS
,ERRbadfid
));
4753 if ((SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
4754 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
4755 pdata
= SMB_REALLOC(*ppdata
, 32);
4757 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4761 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4762 CAN ACCEPT THIS IN UNICODE. JRA. */
4764 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
4765 srvstr_push( outbuf
, pdata
+ 2, global_myname(), 15, STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
4766 srvstr_push( outbuf
, pdata
+18, lp_servicename(SNUM(conn
)), 13, STR_ASCII
|STR_TERMINATE
); /* Service name */
4767 send_trans2_replies(outbuf
,bufsize
,*pparams
,0,*ppdata
,32);
4770 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4771 return ERROR_DOS(ERRSRV
,ERRerror
);
4775 /****************************************************************************
4776 Reply to a SMBfindclose (stop trans2 directory search).
4777 ****************************************************************************/
4779 int reply_findclose(connection_struct
*conn
,
4780 char *inbuf
,char *outbuf
,int length
,int bufsize
)
4783 int dptr_num
=SVALS(inbuf
,smb_vwv0
);
4784 START_PROFILE(SMBfindclose
);
4786 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
4788 dptr_close(&dptr_num
);
4790 outsize
= set_message(outbuf
,0,0,True
);
4792 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
4794 END_PROFILE(SMBfindclose
);
4798 /****************************************************************************
4799 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4800 ****************************************************************************/
4802 int reply_findnclose(connection_struct
*conn
,
4803 char *inbuf
,char *outbuf
,int length
,int bufsize
)
4807 START_PROFILE(SMBfindnclose
);
4809 dptr_num
= SVAL(inbuf
,smb_vwv0
);
4811 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
4813 /* We never give out valid handles for a
4814 findnotifyfirst - so any dptr_num is ok here.
4817 outsize
= set_message(outbuf
,0,0,True
);
4819 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
4821 END_PROFILE(SMBfindnclose
);
4825 /****************************************************************************
4826 Reply to a SMBtranss2 - just ignore it!
4827 ****************************************************************************/
4829 int reply_transs2(connection_struct
*conn
,
4830 char *inbuf
,char *outbuf
,int length
,int bufsize
)
4832 START_PROFILE(SMBtranss2
);
4833 DEBUG(4,("Ignoring transs2 of length %d\n",length
));
4834 END_PROFILE(SMBtranss2
);
4838 /****************************************************************************
4839 Reply to a SMBtrans2.
4840 ****************************************************************************/
4842 int reply_trans2(connection_struct
*conn
,
4843 char *inbuf
,char *outbuf
,int length
,int bufsize
)
4846 unsigned int total_params
= SVAL(inbuf
, smb_tpscnt
);
4847 unsigned int total_data
=SVAL(inbuf
, smb_tdscnt
);
4848 unsigned int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
4850 unsigned int max_param_reply
= SVAL(inbuf
, smb_mprcnt
);
4851 unsigned int max_setup_fields
= SVAL(inbuf
, smb_msrcnt
);
4852 BOOL close_tid
= BITSETW(inbuf
+smb_flags
,0);
4853 BOOL no_final_response
= BITSETW(inbuf
+smb_flags
,1);
4854 int32 timeout
= IVALS(inbuf
,smb_timeout
);
4856 unsigned int suwcnt
= SVAL(inbuf
, smb_suwcnt
);
4857 unsigned int tran_call
= SVAL(inbuf
, smb_setup0
);
4858 char *params
= NULL
, *data
= NULL
;
4859 unsigned int num_params
, num_params_sofar
, num_data
, num_data_sofar
;
4860 START_PROFILE(SMBtrans2
);
4862 if(global_oplock_break
&& (tran_call
== TRANSACT2_OPEN
)) {
4863 /* Queue this open message as we are the process of an
4866 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4867 DEBUGADD(2,( "in oplock break state.\n"));
4869 push_oplock_pending_smb_message(inbuf
, length
);
4870 END_PROFILE(SMBtrans2
);
4874 if (IS_IPC(conn
) && (tran_call
!= TRANSACT2_OPEN
)
4875 && (tran_call
!= TRANSACT2_GET_DFS_REFERRAL
)) {
4876 END_PROFILE(SMBtrans2
);
4877 return ERROR_DOS(ERRSRV
,ERRaccess
);
4880 outsize
= set_message(outbuf
,0,0,True
);
4882 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4883 is so as a sanity check */
4886 * Need to have rc=0 for ioctl to get job id for OS/2.
4887 * Network printing will fail if function is not successful.
4888 * Similar function in reply.c will be used if protocol
4889 * is LANMAN1.0 instead of LM1.2X002.
4890 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4891 * outbuf doesn't have to be set(only job id is used).
4893 if ( (suwcnt
== 4) && (tran_call
== TRANSACT2_IOCTL
) &&
4894 (SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
4895 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
4896 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4898 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt
));
4899 DEBUG(2,("Transaction is %d\n",tran_call
));
4900 END_PROFILE(SMBtrans2
);
4901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
4905 /* Allocate the space for the maximum needed parameters and data */
4906 if (total_params
> 0)
4907 params
= (char *)SMB_MALLOC(total_params
);
4909 data
= (char *)SMB_MALLOC(total_data
);
4911 if ((total_params
&& !params
) || (total_data
&& !data
)) {
4912 DEBUG(2,("Out of memory in reply_trans2\n"));
4915 END_PROFILE(SMBtrans2
);
4916 return ERROR_NT(NT_STATUS_NO_MEMORY
);
4919 /* Copy the param and data bytes sent with this request into
4920 the params buffer */
4921 num_params
= num_params_sofar
= SVAL(inbuf
,smb_pscnt
);
4922 num_data
= num_data_sofar
= SVAL(inbuf
, smb_dscnt
);
4924 if (num_params
> total_params
|| num_data
> total_data
)
4925 exit_server("invalid params in reply_trans2");
4928 unsigned int psoff
= SVAL(inbuf
, smb_psoff
);
4929 if ((psoff
+ num_params
< psoff
) || (psoff
+ num_params
< num_params
))
4931 if ((smb_base(inbuf
) + psoff
+ num_params
> inbuf
+ length
) ||
4932 (smb_base(inbuf
) + psoff
+ num_params
< smb_base(inbuf
)))
4934 memcpy( params
, smb_base(inbuf
) + psoff
, num_params
);
4937 unsigned int dsoff
= SVAL(inbuf
, smb_dsoff
);
4938 if ((dsoff
+ num_data
< dsoff
) || (dsoff
+ num_data
< num_data
))
4940 if ((smb_base(inbuf
) + dsoff
+ num_data
> inbuf
+ length
) ||
4941 (smb_base(inbuf
) + dsoff
+ num_data
< smb_base(inbuf
)))
4943 memcpy( data
, smb_base(inbuf
) + dsoff
, num_data
);
4946 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
4948 if(num_data_sofar
< total_data
|| num_params_sofar
< total_params
) {
4949 /* We need to send an interim response then receive the rest
4950 of the parameter/data bytes */
4951 outsize
= set_message(outbuf
,0,0,True
);
4952 srv_signing_trans_stop();
4954 if (!send_smb(smbd_server_fd(),outbuf
))
4955 exit_server("reply_trans2: send_smb failed.");
4957 while (num_data_sofar
< total_data
||
4958 num_params_sofar
< total_params
) {
4960 unsigned int param_disp
;
4961 unsigned int param_off
;
4962 unsigned int data_disp
;
4963 unsigned int data_off
;
4965 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
4967 /* We need to re-calcuate the new length after we've read the secondary packet. */
4968 length
= smb_len(inbuf
) + 4;
4971 * The sequence number for the trans reply is always
4972 * based on the last secondary received.
4975 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
4978 (CVAL(inbuf
, smb_com
) != SMBtranss2
)) || !ret
) {
4979 outsize
= set_message(outbuf
,0,0,True
);
4981 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4983 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4984 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
4988 /* Revise total_params and total_data in case
4989 they have changed downwards */
4990 if (SVAL(inbuf
, smb_tpscnt
) < total_params
)
4991 total_params
= SVAL(inbuf
, smb_tpscnt
);
4992 if (SVAL(inbuf
, smb_tdscnt
) < total_data
)
4993 total_data
= SVAL(inbuf
, smb_tdscnt
);
4995 num_params
= SVAL(inbuf
,smb_spscnt
);
4996 param_off
= SVAL(inbuf
, smb_spsoff
);
4997 param_disp
= SVAL(inbuf
, smb_spsdisp
);
4998 num_params_sofar
+= num_params
;
5000 num_data
= SVAL(inbuf
, smb_sdscnt
);
5001 data_off
= SVAL(inbuf
, smb_sdsoff
);
5002 data_disp
= SVAL(inbuf
, smb_sdsdisp
);
5003 num_data_sofar
+= num_data
;
5005 if (num_params_sofar
> total_params
|| num_data_sofar
> total_data
)
5009 if (param_disp
+ num_params
> total_params
)
5011 if ((param_disp
+ num_params
< param_disp
) ||
5012 (param_disp
+ num_params
< num_params
))
5014 if (param_disp
> total_params
)
5016 if ((smb_base(inbuf
) + param_off
+ num_params
> inbuf
+ length
) ||
5017 (smb_base(inbuf
) + param_off
+ num_params
< smb_base(inbuf
)))
5019 if (params
+ param_disp
< params
)
5022 memcpy( ¶ms
[param_disp
], smb_base(inbuf
) + param_off
, num_params
);
5025 if (data_disp
+ num_data
> total_data
)
5027 if ((data_disp
+ num_data
< data_disp
) ||
5028 (data_disp
+ num_data
< num_data
))
5030 if (data_disp
> total_data
)
5032 if ((smb_base(inbuf
) + data_off
+ num_data
> inbuf
+ length
) ||
5033 (smb_base(inbuf
) + data_off
+ num_data
< smb_base(inbuf
)))
5035 if (data
+ data_disp
< data
)
5038 memcpy( &data
[data_disp
], smb_base(inbuf
) + data_off
, num_data
);
5043 if (Protocol
>= PROTOCOL_NT1
) {
5044 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | 0x40); /* IS_LONG_NAME */
5047 /* Now we must call the relevant TRANS2 function */
5049 case TRANSACT2_OPEN
:
5050 START_PROFILE_NESTED(Trans2_open
);
5051 outsize
= call_trans2open(conn
, inbuf
, outbuf
, bufsize
,
5052 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5053 END_PROFILE_NESTED(Trans2_open
);
5056 case TRANSACT2_FINDFIRST
:
5057 START_PROFILE_NESTED(Trans2_findfirst
);
5058 outsize
= call_trans2findfirst(conn
, inbuf
, outbuf
, bufsize
,
5059 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5060 END_PROFILE_NESTED(Trans2_findfirst
);
5063 case TRANSACT2_FINDNEXT
:
5064 START_PROFILE_NESTED(Trans2_findnext
);
5065 outsize
= call_trans2findnext(conn
, inbuf
, outbuf
, length
, bufsize
,
5066 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5067 END_PROFILE_NESTED(Trans2_findnext
);
5070 case TRANSACT2_QFSINFO
:
5071 START_PROFILE_NESTED(Trans2_qfsinfo
);
5072 outsize
= call_trans2qfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
5073 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5074 END_PROFILE_NESTED(Trans2_qfsinfo
);
5077 case TRANSACT2_SETFSINFO
:
5078 START_PROFILE_NESTED(Trans2_setfsinfo
);
5079 outsize
= call_trans2setfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
5080 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5081 END_PROFILE_NESTED(Trans2_setfsinfo
);
5084 case TRANSACT2_QPATHINFO
:
5085 case TRANSACT2_QFILEINFO
:
5086 START_PROFILE_NESTED(Trans2_qpathinfo
);
5087 outsize
= call_trans2qfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
, tran_call
,
5088 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5089 END_PROFILE_NESTED(Trans2_qpathinfo
);
5091 case TRANSACT2_SETPATHINFO
:
5092 case TRANSACT2_SETFILEINFO
:
5093 START_PROFILE_NESTED(Trans2_setpathinfo
);
5094 outsize
= call_trans2setfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
, tran_call
,
5095 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5096 END_PROFILE_NESTED(Trans2_setpathinfo
);
5099 case TRANSACT2_FINDNOTIFYFIRST
:
5100 START_PROFILE_NESTED(Trans2_findnotifyfirst
);
5101 outsize
= call_trans2findnotifyfirst(conn
, inbuf
, outbuf
, length
, bufsize
,
5102 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5103 END_PROFILE_NESTED(Trans2_findnotifyfirst
);
5106 case TRANSACT2_FINDNOTIFYNEXT
:
5107 START_PROFILE_NESTED(Trans2_findnotifynext
);
5108 outsize
= call_trans2findnotifynext(conn
, inbuf
, outbuf
, length
, bufsize
,
5109 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5110 END_PROFILE_NESTED(Trans2_findnotifynext
);
5112 case TRANSACT2_MKDIR
:
5113 START_PROFILE_NESTED(Trans2_mkdir
);
5114 outsize
= call_trans2mkdir(conn
, inbuf
, outbuf
, length
, bufsize
,
5115 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5116 END_PROFILE_NESTED(Trans2_mkdir
);
5119 case TRANSACT2_GET_DFS_REFERRAL
:
5120 START_PROFILE_NESTED(Trans2_get_dfs_referral
);
5121 outsize
= call_trans2getdfsreferral(conn
,inbuf
,outbuf
,length
, bufsize
,
5122 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5123 END_PROFILE_NESTED(Trans2_get_dfs_referral
);
5125 case TRANSACT2_IOCTL
:
5126 START_PROFILE_NESTED(Trans2_ioctl
);
5127 outsize
= call_trans2ioctl(conn
,inbuf
,outbuf
,length
, bufsize
,
5128 ¶ms
, total_params
, &data
, total_data
, max_data_bytes
);
5129 END_PROFILE_NESTED(Trans2_ioctl
);
5132 /* Error in request */
5133 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call
));
5136 END_PROFILE(SMBtrans2
);
5137 srv_signing_trans_stop();
5138 return ERROR_DOS(ERRSRV
,ERRerror
);
5141 /* As we do not know how many data packets will need to be
5142 returned here the various call_trans2xxxx calls
5143 must send their own. Thus a call_trans2xxx routine only
5144 returns a value other than -1 when it wants to send
5148 srv_signing_trans_stop();
5152 END_PROFILE(SMBtrans2
);
5153 return outsize
; /* If a correct response was needed the
5154 call_trans2xxx calls have already sent
5155 it. If outsize != -1 then it is returning */
5159 srv_signing_trans_stop();
5162 END_PROFILE(SMBtrans2
);
5163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);