2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol
;
31 extern int smb_read_error
;
32 extern uint32 global_client_caps
;
33 extern struct current_user current_user
;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct
*conn
,
41 const SMB_STRUCT_STAT
*psbuf
);
43 static char *store_file_unix_basic_info2(connection_struct
*conn
,
46 const SMB_STRUCT_STAT
*psbuf
);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT
smb_roundup(connection_struct
*conn
, SMB_BIG_UINT val
)
55 SMB_BIG_UINT rval
= lp_allocation_roundup_size(SNUM(conn
));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type
= get_remote_arch();
59 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
60 val
= SMB_ROUNDUP(val
,rval
);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT
get_allocation_size(connection_struct
*conn
, files_struct
*fsp
, const SMB_STRUCT_STAT
*sbuf
)
74 if(S_ISDIR(sbuf
->st_mode
)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
81 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
84 if (fsp
&& fsp
->initial_allocation_size
)
85 ret
= MAX(ret
,fsp
->initial_allocation_size
);
87 return smb_roundup(conn
, ret
);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names
[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME
,
96 SAMBA_XATTR_DOS_ATTRIB
,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL
samba_private_attr_name(const char *unix_ea_name
)
108 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
109 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
120 const char *fname
, char *ea_name
, struct ea_struct
*pea
)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size
= 256;
129 val
= TALLOC_REALLOC_ARRAY(mem_ctx
, val
, char, attr_size
);
134 if (fsp
&& fsp
->fh
->fd
!= -1) {
135 sizeret
= SMB_VFS_FGETXATTR(fsp
, fsp
->fh
->fd
, ea_name
, val
, attr_size
);
137 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
140 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name
, (unsigned int)sizeret
));
150 dump_data(10, val
, sizeret
);
153 if (strnequal(ea_name
, "user.", 5)) {
154 pea
->name
= &ea_name
[5];
158 pea
->value
.data
= (unsigned char *)val
;
159 pea
->value
.length
= (size_t)sizeret
;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list
*get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
168 const char *fname
, size_t *pea_total_len
)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size
= 1024;
176 struct ea_list
*ea_list_head
= NULL
;
180 if (!lp_ea_support(SNUM(conn
))) {
184 for (i
= 0, ea_namelist
= TALLOC_ARRAY(mem_ctx
, char, ea_namelist_size
); i
< 6;
185 ea_namelist
= TALLOC_REALLOC_ARRAY(mem_ctx
, ea_namelist
, char, ea_namelist_size
), i
++) {
191 if (fsp
&& fsp
->fh
->fd
!= -1) {
192 sizeret
= SMB_VFS_FLISTXATTR(fsp
, fsp
->fh
->fd
, ea_namelist
, ea_namelist_size
);
194 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
, ea_namelist_size
);
197 if (sizeret
== -1 && errno
== ERANGE
) {
198 ea_namelist_size
*= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret
));
210 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
) + 1) {
211 struct ea_list
*listp
;
213 if (strnequal(p
, "system.", 7) || samba_private_attr_name(p
))
216 listp
= TALLOC_P(mem_ctx
, struct ea_list
);
220 if (!get_ea_value(mem_ctx
, conn
, fsp
, fname
, p
, &listp
->ea
)) {
226 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
227 *pea_total_len
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len
, dos_ea_name
,
230 (unsigned int)listp
->ea
.value
.length
));
232 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
234 /* Add on 4 for total length. */
235 if (*pea_total_len
) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len
));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
250 connection_struct
*conn
, struct ea_list
*ea_list
)
252 unsigned int ret_data_size
= 4;
255 SMB_ASSERT(total_data_size
>= 4);
257 if (!lp_ea_support(SNUM(conn
))) {
262 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
265 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
266 dos_namelen
= strlen(dos_ea_name
);
267 if (dos_namelen
> 255 || dos_namelen
== 0) {
270 if (ea_list
->ea
.value
.length
> 65535) {
273 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
277 /* We know we have room. */
278 SCVAL(p
,0,ea_list
->ea
.flags
);
279 SCVAL(p
,1,dos_namelen
);
280 SSVAL(p
,2,ea_list
->ea
.value
.length
);
281 fstrcpy(p
+4, dos_ea_name
);
282 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
284 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
285 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
288 ret_data_size
= PTR_DIFF(p
, pdata
);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
290 SIVAL(pdata
,0,ret_data_size
);
291 return ret_data_size
;
294 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
296 size_t total_ea_len
= 0;
297 TALLOC_CTX
*mem_ctx
= NULL
;
299 if (!lp_ea_support(SNUM(conn
))) {
302 mem_ctx
= talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
304 talloc_destroy(mem_ctx
);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
315 TALLOC_CTX
*mem_ctx
= talloc_init("canonicalize_ea_name");
316 struct ea_list
*ea_list
= get_ea_list_from_file(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
318 for (; ea_list
; ea_list
= ea_list
->next
) {
319 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name
[5], ea_list
->ea
.name
));
322 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
326 talloc_destroy(mem_ctx
);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, struct ea_list
*ea_list
)
335 if (!lp_ea_support(SNUM(conn
))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED
;
339 for (;ea_list
; ea_list
= ea_list
->next
) {
341 fstring unix_ea_name
;
343 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
346 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
350 if (samba_private_attr_name(unix_ea_name
)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
352 return NT_STATUS_ACCESS_DENIED
;
355 if (ea_list
->ea
.value
.length
== 0) {
356 /* Remove the attribute. */
357 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name
, fsp
->fsp_name
));
360 ret
= SMB_VFS_FREMOVEXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name
, fname
));
364 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret
== -1 && errno
== ENOATTR
) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name
, fsp
->fsp_name
));
378 ret
= SMB_VFS_FSETXATTR(fsp
, fsp
->fh
->fd
, unix_ea_name
,
379 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name
, fname
));
383 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
384 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
390 if (errno
== ENOTSUP
) {
391 return NT_STATUS_EAS_NOT_SUPPORTED
;
394 return map_nt_error_from_unix(errno
);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
406 struct ea_list
*ea_list_head
= NULL
;
409 while (offset
+ 2 < data_size
) {
410 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
411 unsigned int namelen
= CVAL(pdata
,offset
);
413 offset
++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
417 (offset
> data_size
) || (namelen
> data_size
) ||
418 (offset
+ namelen
>= data_size
)) {
421 /* Ensure the name is null terminated. */
422 if (pdata
[offset
+ namelen
] != '\0') {
425 pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
]);
430 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
444 struct ea_list
*eal
= TALLOC_ZERO_P(ctx
, struct ea_list
);
446 unsigned int namelen
;
456 eal
->ea
.flags
= CVAL(pdata
,0);
457 namelen
= CVAL(pdata
,1);
458 val_len
= SVAL(pdata
,2);
460 if (4 + namelen
+ 1 + val_len
> data_size
) {
464 /* Ensure the name is null terminated. */
465 if (pdata
[namelen
+ 4] != '\0') {
468 pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4);
473 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
474 if (!eal
->ea
.value
.data
) {
478 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal
->ea
.value
.data
[val_len
] = '\0';
482 /* But don't count the null. */
483 eal
->ea
.value
.length
--;
486 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
490 dump_data(10, (const char *)eal
->ea
.value
.data
, eal
->ea
.value
.length
);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
501 struct ea_list
*ea_list_head
= NULL
;
503 size_t bytes_used
= 0;
505 while (offset
< data_size
) {
506 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
512 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
513 offset
+= bytes_used
;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list
*ealist
)
526 struct ea_list
*listp
;
529 for (listp
= ealist
; listp
; listp
= listp
->next
) {
530 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
531 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
549 struct ea_list
*nlistp
, *flistp
;
551 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
552 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
553 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
559 /* Copy the data from this entry. */
560 nlistp
->ea
.flags
= flistp
->ea
.flags
;
561 nlistp
->ea
.value
= flistp
->ea
.value
;
564 nlistp
->ea
.flags
= 0;
565 ZERO_STRUCT(nlistp
->ea
.value
);
569 *total_ea_len
= ea_list_size(name_list
);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf
,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send
= datasize
;
595 int params_to_send
= paramsize
;
597 const char *pp
= params
;
598 const char *pd
= pdata
;
599 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
600 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset
= 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf
,10,0,True
);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes
, datasize
));
615 datasize
= data_to_send
= max_data_bytes
;
616 error_packet_set(outbuf
,ERRDOS
,ERRbufferoverflow
,STATUS_BUFFER_OVERFLOW
,__LINE__
,__FILE__
);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send
== 0 && data_to_send
== 0) {
623 if (!send_smb(smbd_server_fd(),outbuf
))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
633 data_alignment_offset
= 4 - (params_to_send
% 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space
= bufsize
- ((smb_buf(outbuf
)+ alignment_offset
+data_alignment_offset
) - outbuf
);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
645 while (params_to_send
|| data_to_send
) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
660 set_message(outbuf
, 10, total_sent_thistime
, True
);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf
,smb_tprcnt
,paramsize
);
664 SSVAL(outbuf
,smb_tdrcnt
,datasize
);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime
= MIN(params_to_send
,useable_space
);
671 data_sent_thistime
= useable_space
- params_sent_thistime
;
672 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
674 SSVAL(outbuf
,smb_prcnt
, params_sent_thistime
);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf
,smb_proff
,((smb_buf(outbuf
)+alignment_offset
) - smb_base(outbuf
)));
683 if(params_sent_thistime
== 0)
684 SSVAL(outbuf
,smb_prdisp
,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf
,smb_prdisp
,pp
- params
);
689 SSVAL(outbuf
,smb_drcnt
, data_sent_thistime
);
690 if(data_sent_thistime
== 0) {
691 SSVAL(outbuf
,smb_droff
,0);
692 SSVAL(outbuf
,smb_drdisp
, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf
,smb_droff
,((smb_buf(outbuf
)+alignment_offset
) -
697 smb_base(outbuf
)) + params_sent_thistime
+ data_alignment_offset
);
698 SSVAL(outbuf
,smb_drdisp
, pd
- pdata
);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime
)
704 memcpy((smb_buf(outbuf
)+alignment_offset
),pp
,params_sent_thistime
);
706 /* Copy in the data bytes */
707 if(data_sent_thistime
)
708 memcpy(smb_buf(outbuf
)+alignment_offset
+params_sent_thistime
+
709 data_alignment_offset
,pd
,data_sent_thistime
);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime
, data_sent_thistime
, useable_space
));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send
, data_to_send
, paramsize
, datasize
));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf
))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp
+= params_sent_thistime
;
722 pd
+= data_sent_thistime
;
724 params_to_send
-= params_sent_thistime
;
725 data_to_send
-= data_sent_thistime
;
728 if(params_to_send
< 0 || data_to_send
< 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send
, data_to_send
));
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
743 char **pparams
, int total_params
, char **ppdata
, int total_data
,
744 unsigned int max_data_bytes
)
746 char *params
= *pparams
;
747 char *pdata
= *ppdata
;
752 BOOL return_additional_info
;
763 SMB_STRUCT_STAT sbuf
;
766 struct ea_list
*ea_list
= NULL
;
771 uint32 create_disposition
;
772 uint32 create_options
= 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params
< 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
782 flags
= SVAL(params
, 0);
783 deny_mode
= SVAL(params
, 2);
784 open_attr
= SVAL(params
,6);
785 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
786 if (oplock_request
) {
787 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
791 return_additional_info
= BITSETW(params
,0);
792 open_sattr
= SVAL(params
, 4);
793 open_time
= make_unix_date3(params
+8);
795 open_ofun
= SVAL(params
,12);
796 open_size
= IVAL(params
,14);
800 return(ERROR_DOS(ERRSRV
,ERRaccess
));
803 srvstr_get_path(inbuf
, fname
, pname
, sizeof(fname
), total_params
- 28, STR_TERMINATE
, &status
);
804 if (!NT_STATUS_IS_OK(status
)) {
805 return ERROR_NT(status
);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
810 (unsigned int)open_ofun
, open_size
));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
815 if (!NT_STATUS_IS_OK(status
)) {
816 return ERROR_NT(status
);
819 status
= check_name(conn
, fname
);
820 if (!NT_STATUS_IS_OK(status
)) {
821 return ERROR_NT(status
);
824 if (open_ofun
== 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION
);
828 if (!map_open_params_to_ntcreate(fname
, deny_mode
, open_ofun
,
833 return ERROR_DOS(ERRDOS
, ERRbadaccess
);
836 /* Any data in this call is an EA list. */
837 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED
);
841 if (total_data
!= 4) {
842 if (total_data
< 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
846 if (IVAL(pdata
,0) > total_data
) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata
,0), (unsigned int)total_data
));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
852 ea_list
= read_ea_list(tmp_talloc_ctx(), pdata
+ 4,
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
857 } else if (IVAL(pdata
,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
861 status
= open_file_ntcreate(conn
,fname
,&sbuf
,
870 if (!NT_STATUS_IS_OK(status
)) {
871 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
872 /* We have re-scheduled this call. */
875 return ERROR_NT(status
);
878 size
= get_file_size(sbuf
);
879 fattr
= dos_mode(conn
,fname
,&sbuf
);
880 mtime
= sbuf
.st_mtime
;
883 close_file(fsp
,ERROR_CLOSE
);
884 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) {
890 SMB_BIG_UINT allocation_size
= (SMB_BIG_UINT
)open_size
;
891 if (allocation_size
&& (allocation_size
> (SMB_BIG_UINT
)size
)) {
892 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
893 if (fsp
->is_directory
) {
894 close_file(fsp
,ERROR_CLOSE
);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
898 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
899 close_file(fsp
,ERROR_CLOSE
);
900 return ERROR_NT(NT_STATUS_DISK_FULL
);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size
= fsp
->initial_allocation_size
;
907 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
,(SMB_BIG_UINT
)size
);
911 if (ea_list
&& smb_action
== FILE_WAS_CREATED
) {
912 status
= set_ea(conn
, fsp
, fname
, ea_list
);
913 if (!NT_STATUS_IS_OK(status
)) {
914 close_file(fsp
,ERROR_CLOSE
);
915 return ERROR_NT(status
);
919 /* Realloc the size of parameters and data we will return */
920 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
921 if(*pparams
== NULL
) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY
);
926 SSVAL(params
,0,fsp
->fnum
);
927 SSVAL(params
,2,fattr
);
928 srv_put_dos_date2(params
,4, mtime
);
929 SIVAL(params
,8, (uint32
)size
);
930 SSVAL(params
,12,deny_mode
);
931 SSVAL(params
,14,0); /* open_type - file or directory. */
932 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
935 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
938 SSVAL(params
,18,smb_action
);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params
,20,inode
);
944 SSVAL(params
,24,0); /* Padding. */
946 uint32 ea_size
= estimate_ea_size(conn
, fsp
, fname
);
947 SIVAL(params
, 26, ea_size
);
949 SIVAL(params
, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf
, bufsize
, params
, 30, *ppdata
, 0, max_data_bytes
);
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL
exact_match(connection_struct
*conn
, char *str
, char *mask
)
967 if (mask
[0] == '.' && mask
[1] == 0)
969 if (conn
->case_sensitive
)
970 return strcmp(str
,mask
)==0;
971 if (StrCaseCmp(str
,mask
) != 0) {
974 if (dptr_has_wild(conn
->dirptr
)) {
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32
unix_filetype(mode_t mode
)
987 return UNIX_TYPE_FILE
;
988 else if(S_ISDIR(mode
))
989 return UNIX_TYPE_DIR
;
991 else if(S_ISLNK(mode
))
992 return UNIX_TYPE_SYMLINK
;
995 else if(S_ISCHR(mode
))
996 return UNIX_TYPE_CHARDEV
;
999 else if(S_ISBLK(mode
))
1000 return UNIX_TYPE_BLKDEV
;
1003 else if(S_ISFIFO(mode
))
1004 return UNIX_TYPE_FIFO
;
1007 else if(S_ISSOCK(mode
))
1008 return UNIX_TYPE_SOCKET
;
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
1012 return UNIX_TYPE_UNKNOWN
;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1021 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1022 SMB_STRUCT_STAT
*psbuf
,
1024 enum perm_type ptype
,
1029 if (perms
== SMB_MODE_NO_CHANGE
) {
1030 if (!VALID_STAT(*psbuf
)) {
1031 return NT_STATUS_INVALID_PARAMETER
;
1033 *ret_perms
= psbuf
->st_mode
;
1034 return NT_STATUS_OK
;
1038 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1039 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1040 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1041 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1042 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1043 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1044 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1045 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1046 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1048 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1051 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1054 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1059 /* Apply mode mask */
1060 ret
&= lp_create_mask(SNUM(conn
));
1061 /* Add in force bits */
1062 ret
|= lp_force_create_mode(SNUM(conn
));
1065 ret
&= lp_dir_mask(SNUM(conn
));
1066 /* Add in force bits */
1067 ret
|= lp_force_dir_mode(SNUM(conn
));
1069 case PERM_EXISTING_FILE
:
1070 /* Apply mode mask */
1071 ret
&= lp_security_mask(SNUM(conn
));
1072 /* Add in force bits */
1073 ret
|= lp_force_security_mode(SNUM(conn
));
1075 case PERM_EXISTING_DIR
:
1076 /* Apply mode mask */
1077 ret
&= lp_dir_security_mask(SNUM(conn
));
1078 /* Add in force bits */
1079 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1084 return NT_STATUS_OK
;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL
get_lanman2_dir_entry(connection_struct
*conn
,
1092 void *inbuf
, char *outbuf
,
1093 char *path_mask
,uint32 dirtype
,int info_level
,
1094 int requires_resume_key
,
1095 BOOL dont_descend
,char **ppdata
,
1096 char *base_data
, int space_remaining
,
1097 BOOL
*out_of_space
, BOOL
*got_exact_match
,
1098 int *last_entry_off
, struct ea_list
*name_list
, TALLOC_CTX
*ea_ctx
)
1102 SMB_STRUCT_STAT sbuf
;
1106 char *p
, *q
, *pdata
= *ppdata
;
1110 SMB_OFF_T file_size
= 0;
1111 SMB_BIG_UINT allocation_size
= 0;
1113 struct timespec mdate_ts
, adate_ts
, create_date_ts
;
1114 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1116 char *last_entry_ptr
;
1118 uint32 nt_extmode
; /* Used for NT connections instead of mode */
1119 BOOL needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
1120 BOOL check_mangled_names
= lp_manglednames(conn
->params
);
1123 *out_of_space
= False
;
1124 *got_exact_match
= False
;
1126 ZERO_STRUCT(mdate_ts
);
1127 ZERO_STRUCT(adate_ts
);
1128 ZERO_STRUCT(create_date_ts
);
1133 p
= strrchr_m(path_mask
,'/');
1136 pstrcpy(mask
,"*.*");
1140 pstrcpy(mask
, path_mask
);
1145 BOOL ms_dfs_link
= False
;
1147 /* Needed if we run out of space */
1148 long curr_dirpos
= prev_dirpos
= dptr_TellDir(conn
->dirptr
);
1149 dname
= dptr_ReadDirName(conn
->dirptr
,&curr_dirpos
,&sbuf
);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn
->dirptr
,curr_dirpos
));
1166 pstrcpy(fname
,dname
);
1168 if(!(got_match
= *got_exact_match
= exact_match(conn
, fname
, mask
)))
1169 got_match
= mask_match(fname
, mask
, conn
->case_sensitive
);
1171 if(!got_match
&& check_mangled_names
&&
1172 !mangle_is_8_3(fname
, False
, conn
->params
)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1182 pstrcpy( newname
, fname
);
1183 mangle_map( newname
, True
, False
, conn
->params
);
1184 if(!(got_match
= *got_exact_match
= exact_match(conn
, newname
, mask
)))
1185 got_match
= mask_match(newname
, mask
, conn
->case_sensitive
);
1189 BOOL isdots
= (strequal(fname
,"..") || strequal(fname
,"."));
1190 if (dont_descend
&& !isdots
)
1193 pstrcpy(pathreal
,conn
->dirpath
);
1195 pstrcat(pathreal
,"/");
1196 pstrcat(pathreal
,dname
);
1198 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1199 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal
,strerror(errno
)));
1204 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
1205 pstring link_target
;
1207 /* Needed to show the msdfs symlinks as
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn
)) &&
1212 ((ms_dfs_link
= is_msdfs_link(conn
, pathreal
, link_target
, &sbuf
)) == True
)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1216 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal
,strerror(errno
)));
1227 mode
= dos_mode_msdfs(conn
,pathreal
,&sbuf
);
1229 mode
= dos_mode(conn
,pathreal
,&sbuf
);
1232 if (!dir_check_ftype(conn
,mode
,dirtype
)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname
,dirtype
));
1238 file_size
= get_file_size(sbuf
);
1239 allocation_size
= get_allocation_size(conn
,NULL
,&sbuf
);
1241 mdate_ts
= get_mtimespec(&sbuf
);
1242 adate_ts
= get_atimespec(&sbuf
);
1243 create_date_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1245 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1246 dos_filetime_timespec(&create_date_ts
);
1247 dos_filetime_timespec(&mdate_ts
);
1248 dos_filetime_timespec(&adate_ts
);
1251 create_date
= convert_timespec_to_time_t(create_date_ts
);
1252 mdate
= convert_timespec_to_time_t(mdate_ts
);
1253 adate
= convert_timespec_to_time_t(adate_ts
);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal
,fname
));
1259 dptr_DirCacheAdd(conn
->dirptr
, dname
, curr_dirpos
);
1263 mangle_map(fname
,False
,True
,conn
->params
);
1268 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
1270 switch (info_level
) {
1271 case SMB_FIND_INFO_STANDARD
:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key
) {
1277 srv_put_dos_date2(p
,0,create_date
);
1278 srv_put_dos_date2(p
,4,adate
);
1279 srv_put_dos_date2(p
,8,mdate
);
1280 SIVAL(p
,12,(uint32
)file_size
);
1281 SIVAL(p
,16,(uint32
)allocation_size
);
1285 p
+= align_string(outbuf
, p
, 0);
1286 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
1287 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1289 SCVAL(nameptr
, -1, len
- 2);
1291 SCVAL(nameptr
, -1, 0);
1295 SCVAL(nameptr
, -1, len
- 1);
1297 SCVAL(nameptr
, -1, 0);
1303 case SMB_FIND_EA_SIZE
:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key
) {
1309 srv_put_dos_date2(p
,0,create_date
);
1310 srv_put_dos_date2(p
,4,adate
);
1311 srv_put_dos_date2(p
,8,mdate
);
1312 SIVAL(p
,12,(uint32
)file_size
);
1313 SIVAL(p
,16,(uint32
)allocation_size
);
1316 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1317 SIVAL(p
,22,ea_size
); /* Extended attributes */
1321 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
1322 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1335 SCVAL(nameptr
,0,len
);
1337 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1340 case SMB_FIND_EA_LIST
:
1342 struct ea_list
*file_list
= NULL
;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1349 if(requires_resume_key
) {
1353 srv_put_dos_date2(p
,0,create_date
);
1354 srv_put_dos_date2(p
,4,adate
);
1355 srv_put_dos_date2(p
,8,mdate
);
1356 SIVAL(p
,12,(uint32
)file_size
);
1357 SIVAL(p
,16,(uint32
)allocation_size
);
1359 p
+= 22; /* p now points to the EA area. */
1361 file_list
= get_ea_list_from_file(ea_ctx
, conn
, NULL
, pathreal
, &ea_len
);
1362 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1369 *out_of_space
= True
;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False
; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p
+= fill_ea_buffer(ea_ctx
, p
, space_remaining
, conn
, name_list
);
1377 len
= srvstr_push(outbuf
, p
+ 1, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
1378 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1391 SCVAL(nameptr
,0,len
);
1393 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1401 SIVAL(p
,0,reskey
); p
+= 4;
1402 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1403 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1404 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1405 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1406 SOFF_T(p
,0,file_size
); p
+= 8;
1407 SOFF_T(p
,0,allocation_size
); p
+= 8;
1408 SIVAL(p
,0,nt_extmode
); p
+= 4;
1409 q
= p
; p
+= 4; /* q is placeholder for name length. */
1411 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1412 SIVAL(p
,0,ea_size
); /* Extended attributes */
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3
&& check_mangled_names
) {
1420 pstring mangled_name
;
1421 pstrcpy(mangled_name
, fname
);
1422 mangle_map(mangled_name
,True
,True
,
1424 mangled_name
[12] = 0;
1425 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1427 memset(p
+ 2 + len
,'\0',24 - len
);
1434 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1437 SIVAL(p
,0,0); /* Ensure any padding is null. */
1438 len
= PTR_DIFF(p
, pdata
);
1439 len
= (len
+ 3) & ~3;
1444 case SMB_FIND_FILE_DIRECTORY_INFO
:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1447 SIVAL(p
,0,reskey
); p
+= 4;
1448 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1449 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1450 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1451 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1452 SOFF_T(p
,0,file_size
); p
+= 8;
1453 SOFF_T(p
,0,allocation_size
); p
+= 8;
1454 SIVAL(p
,0,nt_extmode
); p
+= 4;
1455 len
= srvstr_push(outbuf
, p
+ 4, fname
, -1, STR_TERMINATE_ASCII
);
1458 SIVAL(p
,0,0); /* Ensure any padding is null. */
1459 len
= PTR_DIFF(p
, pdata
);
1460 len
= (len
+ 3) & ~3;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1468 SIVAL(p
,0,reskey
); p
+= 4;
1469 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1470 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1471 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1472 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1473 SOFF_T(p
,0,file_size
); p
+= 8;
1474 SOFF_T(p
,0,allocation_size
); p
+= 8;
1475 SIVAL(p
,0,nt_extmode
); p
+= 4;
1476 q
= p
; p
+= 4; /* q is placeholder for name length. */
1478 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1479 SIVAL(p
,0,ea_size
); /* Extended attributes */
1482 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1486 SIVAL(p
,0,0); /* Ensure any padding is null. */
1487 len
= PTR_DIFF(p
, pdata
);
1488 len
= (len
+ 3) & ~3;
1493 case SMB_FIND_FILE_NAMES_INFO
:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1496 SIVAL(p
,0,reskey
); p
+= 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1503 SIVAL(p
,0,0); /* Ensure any padding is null. */
1504 len
= PTR_DIFF(p
, pdata
);
1505 len
= (len
+ 3) & ~3;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1513 SIVAL(p
,0,reskey
); p
+= 4;
1514 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1515 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1516 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1517 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1518 SOFF_T(p
,0,file_size
); p
+= 8;
1519 SOFF_T(p
,0,allocation_size
); p
+= 8;
1520 SIVAL(p
,0,nt_extmode
); p
+= 4;
1521 q
= p
; p
+= 4; /* q is placeholder for name length. */
1523 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1524 SIVAL(p
,0,ea_size
); /* Extended attributes */
1527 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1528 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1529 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1530 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1533 SIVAL(p
,0,0); /* Ensure any padding is null. */
1534 len
= PTR_DIFF(p
, pdata
);
1535 len
= (len
+ 3) & ~3;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1544 SIVAL(p
,0,reskey
); p
+= 4;
1545 put_long_date_timespec(p
,create_date_ts
); p
+= 8;
1546 put_long_date_timespec(p
,adate_ts
); p
+= 8;
1547 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1548 put_long_date_timespec(p
,mdate_ts
); p
+= 8;
1549 SOFF_T(p
,0,file_size
); p
+= 8;
1550 SOFF_T(p
,0,allocation_size
); p
+= 8;
1551 SIVAL(p
,0,nt_extmode
); p
+= 4;
1552 q
= p
; p
+= 4; /* q is placeholder for name length */
1554 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1555 SIVAL(p
,0,ea_size
); /* Extended attributes */
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3
&& check_mangled_names
) {
1563 pstring mangled_name
;
1564 pstrcpy(mangled_name
, fname
);
1565 mangle_map(mangled_name
,True
,True
,
1567 mangled_name
[12] = 0;
1568 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1571 memset(p
+ 2 + len
,'\0',24 - len
);
1578 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1579 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4; /* FileIndexLow */
1580 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4; /* FileIndexHigh */
1581 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1584 SIVAL(p
,0,0); /* Ensure any padding is null. */
1585 len
= PTR_DIFF(p
, pdata
);
1586 len
= (len
+ 3) & ~3;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX
:
1594 case SMB_FIND_FILE_UNIX_INFO2
:
1596 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level
== SMB_FIND_FILE_UNIX
) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p
= store_file_unix_basic(conn
, p
,
1605 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1606 p
= store_file_unix_basic_info2(conn
, p
,
1610 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
1612 SIVAL(p
,0,0); /* Ensure any padding is null. */
1614 len
= PTR_DIFF(p
, pdata
);
1615 len
= (len
+ 3) & ~3;
1616 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1618 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1627 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1628 /* Move the dirptr back to prev_dirpos */
1629 dptr_SeekDir(conn
->dirptr
, prev_dirpos
);
1630 *out_of_space
= True
;
1631 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1632 return False
; /* Not finished - just out of space */
1635 /* Setup the last entry pointer, as an offset from base_data */
1636 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1637 /* Advance the data pointer to the next slot */
1643 /****************************************************************************
1644 Reply to a TRANS2_FINDFIRST.
1645 ****************************************************************************/
1647 static int call_trans2findfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
1648 char **pparams
, int total_params
, char **ppdata
, int total_data
,
1649 unsigned int max_data_bytes
)
1651 /* We must be careful here that we don't return more than the
1652 allowed number of data bytes. If this means returning fewer than
1653 maxentries then so be it. We assume that the redirector has
1654 enough room for the fixed number of parameter bytes it has
1656 char *params
= *pparams
;
1657 char *pdata
= *ppdata
;
1660 uint16 findfirst_flags
;
1661 BOOL close_after_first
;
1663 BOOL requires_resume_key
;
1668 int last_entry_off
=0;
1672 BOOL finished
= False
;
1673 BOOL dont_descend
= False
;
1674 BOOL out_of_space
= False
;
1675 int space_remaining
;
1676 BOOL mask_contains_wcard
= False
;
1677 SMB_STRUCT_STAT sbuf
;
1678 TALLOC_CTX
*ea_ctx
= NULL
;
1679 struct ea_list
*ea_list
= NULL
;
1680 NTSTATUS ntstatus
= NT_STATUS_OK
;
1682 if (total_params
< 13) {
1683 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1686 dirtype
= SVAL(params
,0);
1687 maxentries
= SVAL(params
,2);
1688 findfirst_flags
= SVAL(params
,4);
1689 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
1690 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1691 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1692 info_level
= SVAL(params
,6);
1694 *directory
= *mask
= 0;
1696 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1697 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1698 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1699 info_level
, max_data_bytes
));
1702 /* W2K3 seems to treat zero as 1. */
1706 switch (info_level
) {
1707 case SMB_FIND_INFO_STANDARD
:
1708 case SMB_FIND_EA_SIZE
:
1709 case SMB_FIND_EA_LIST
:
1710 case SMB_FIND_FILE_DIRECTORY_INFO
:
1711 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1712 case SMB_FIND_FILE_NAMES_INFO
:
1713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1714 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1715 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1717 case SMB_FIND_FILE_UNIX
:
1718 case SMB_FIND_FILE_UNIX_INFO2
:
1719 if (!lp_unix_extensions()) {
1720 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
1727 srvstr_get_path_wcard(inbuf
, directory
, params
+12, sizeof(directory
), total_params
- 12, STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1728 if (!NT_STATUS_IS_OK(ntstatus
)) {
1729 return ERROR_NT(ntstatus
);
1732 ntstatus
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, directory
, &mask_contains_wcard
);
1733 if (!NT_STATUS_IS_OK(ntstatus
)) {
1734 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
1735 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
1737 return ERROR_NT(ntstatus
);
1740 ntstatus
= unix_convert(conn
, directory
, True
, NULL
, &sbuf
);
1741 if (!NT_STATUS_IS_OK(ntstatus
)) {
1742 return ERROR_NT(ntstatus
);
1744 ntstatus
= check_name(conn
, directory
);
1745 if (!NT_STATUS_IS_OK(ntstatus
)) {
1746 return ERROR_NT(ntstatus
);
1749 p
= strrchr_m(directory
,'/');
1751 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1752 if((directory
[0] == '.') && (directory
[1] == '\0')) {
1754 mask_contains_wcard
= True
;
1756 pstrcpy(mask
,directory
);
1758 pstrcpy(directory
,"./");
1764 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
1766 if (info_level
== SMB_FIND_EA_LIST
) {
1769 if (total_data
< 4) {
1770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1773 ea_size
= IVAL(pdata
,0);
1774 if (ea_size
!= total_data
) {
1775 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1776 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
1777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1780 if (!lp_ea_support(SNUM(conn
))) {
1781 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
1784 if ((ea_ctx
= talloc_init("findnext_ea_list")) == NULL
) {
1785 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1788 /* Pull out the list of names. */
1789 ea_list
= read_ea_name_list(ea_ctx
, pdata
+ 4, ea_size
- 4);
1791 talloc_destroy(ea_ctx
);
1792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1796 *ppdata
= (char *)SMB_REALLOC(
1797 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
1798 if(*ppdata
== NULL
) {
1799 talloc_destroy(ea_ctx
);
1800 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1804 /* Realloc the params space */
1805 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
1806 if (*pparams
== NULL
) {
1807 talloc_destroy(ea_ctx
);
1808 return ERROR_NT(NT_STATUS_NO_MEMORY
);
1812 /* Save the wildcard match and attribs we are using on this directory -
1813 needed as lanman2 assumes these are being saved between calls */
1815 ntstatus
= dptr_create(conn
,
1819 SVAL(inbuf
,smb_pid
),
1821 mask_contains_wcard
,
1825 if (!NT_STATUS_IS_OK(ntstatus
)) {
1826 talloc_destroy(ea_ctx
);
1827 return ERROR_NT(ntstatus
);
1830 dptr_num
= dptr_dnum(conn
->dirptr
);
1831 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
1833 /* We don't need to check for VOL here as this is returned by
1834 a different TRANS2 call. */
1836 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1837 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
1838 dont_descend
= True
;
1841 space_remaining
= max_data_bytes
;
1842 out_of_space
= False
;
1844 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1845 BOOL got_exact_match
= False
;
1847 /* this is a heuristic to avoid seeking the dirptr except when
1848 absolutely necessary. It allows for a filename of about 40 chars */
1849 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1850 out_of_space
= True
;
1853 finished
= !get_lanman2_dir_entry(conn
,
1855 mask
,dirtype
,info_level
,
1856 requires_resume_key
,dont_descend
,
1857 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1858 &last_entry_off
, ea_list
, ea_ctx
);
1861 if (finished
&& out_of_space
)
1864 if (!finished
&& !out_of_space
)
1868 * As an optimisation if we know we aren't looking
1869 * for a wildcard name (ie. the name matches the wildcard exactly)
1870 * then we can finish on any (first) match.
1871 * This speeds up large directory searches. JRA.
1877 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1880 talloc_destroy(ea_ctx
);
1882 /* Check if we can close the dirptr */
1883 if(close_after_first
|| (finished
&& close_if_end
)) {
1884 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1885 dptr_close(&dptr_num
);
1889 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1890 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1891 * the protocol level is less than NT1. Tested with smbclient. JRA.
1892 * This should fix the OS/2 client bug #2335.
1895 if(numentries
== 0) {
1896 dptr_close(&dptr_num
);
1897 if (Protocol
< PROTOCOL_NT1
) {
1898 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1900 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE
,ERRDOS
,ERRbadfile
);
1904 /* At this point pdata points to numentries directory entries. */
1906 /* Set up the return parameter block */
1907 SSVAL(params
,0,dptr_num
);
1908 SSVAL(params
,2,numentries
);
1909 SSVAL(params
,4,finished
);
1910 SSVAL(params
,6,0); /* Never an EA error */
1911 SSVAL(params
,8,last_entry_off
);
1913 send_trans2_replies( outbuf
, bufsize
, params
, 10, pdata
, PTR_DIFF(p
,pdata
), max_data_bytes
);
1915 if ((! *directory
) && dptr_path(dptr_num
))
1916 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1918 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1919 smb_fn_name(CVAL(inbuf
,smb_com
)),
1920 mask
, directory
, dirtype
, numentries
) );
1923 * Force a name mangle here to ensure that the
1924 * mask as an 8.3 name is top of the mangled cache.
1925 * The reasons for this are subtle. Don't remove
1926 * this code unless you know what you are doing
1927 * (see PR#13758). JRA.
1930 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
))
1931 mangle_map(mask
, True
, True
, conn
->params
);
1936 /****************************************************************************
1937 Reply to a TRANS2_FINDNEXT.
1938 ****************************************************************************/
1940 static int call_trans2findnext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
1941 char **pparams
, int total_params
, char **ppdata
, int total_data
,
1942 unsigned int max_data_bytes
)
1944 /* We must be careful here that we don't return more than the
1945 allowed number of data bytes. If this means returning fewer than
1946 maxentries then so be it. We assume that the redirector has
1947 enough room for the fixed number of parameter bytes it has
1949 char *params
= *pparams
;
1950 char *pdata
= *ppdata
;
1955 uint16 findnext_flags
;
1956 BOOL close_after_request
;
1958 BOOL requires_resume_key
;
1960 BOOL mask_contains_wcard
= False
;
1961 pstring resume_name
;
1967 int i
, last_entry_off
=0;
1968 BOOL finished
= False
;
1969 BOOL dont_descend
= False
;
1970 BOOL out_of_space
= False
;
1971 int space_remaining
;
1972 TALLOC_CTX
*ea_ctx
= NULL
;
1973 struct ea_list
*ea_list
= NULL
;
1974 NTSTATUS ntstatus
= NT_STATUS_OK
;
1976 if (total_params
< 13) {
1977 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1980 dptr_num
= SVAL(params
,0);
1981 maxentries
= SVAL(params
,2);
1982 info_level
= SVAL(params
,4);
1983 resume_key
= IVAL(params
,6);
1984 findnext_flags
= SVAL(params
,10);
1985 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
1986 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
1987 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
1988 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
1990 *mask
= *directory
= *resume_name
= 0;
1992 srvstr_get_path_wcard(inbuf
, resume_name
, params
+12, sizeof(resume_name
), total_params
- 12, STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
1993 if (!NT_STATUS_IS_OK(ntstatus
)) {
1994 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1995 complain (it thinks we're asking for the directory above the shared
1996 path or an invalid name). Catch this as the resume name is only compared, never used in
1997 a file access. JRA. */
1998 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_OBJECT_PATH_SYNTAX_BAD
)) {
1999 pstrcpy(resume_name
, "..");
2000 } else if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_OBJECT_NAME_INVALID
)) {
2001 pstrcpy(resume_name
, ".");
2003 return ERROR_NT(ntstatus
);
2007 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2008 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2009 resume_key = %d resume name = %s continue=%d level = %d\n",
2010 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2011 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
2014 /* W2K3 seems to treat zero as 1. */
2018 switch (info_level
) {
2019 case SMB_FIND_INFO_STANDARD
:
2020 case SMB_FIND_EA_SIZE
:
2021 case SMB_FIND_EA_LIST
:
2022 case SMB_FIND_FILE_DIRECTORY_INFO
:
2023 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2024 case SMB_FIND_FILE_NAMES_INFO
:
2025 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2026 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2027 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2029 case SMB_FIND_FILE_UNIX
:
2030 case SMB_FIND_FILE_UNIX_INFO2
:
2031 if (!lp_unix_extensions()) {
2032 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2039 if (info_level
== SMB_FIND_EA_LIST
) {
2042 if (total_data
< 4) {
2043 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2046 ea_size
= IVAL(pdata
,0);
2047 if (ea_size
!= total_data
) {
2048 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2049 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2050 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2053 if (!lp_ea_support(SNUM(conn
))) {
2054 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
2057 if ((ea_ctx
= talloc_init("findnext_ea_list")) == NULL
) {
2058 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2061 /* Pull out the list of names. */
2062 ea_list
= read_ea_name_list(ea_ctx
, pdata
+ 4, ea_size
- 4);
2064 talloc_destroy(ea_ctx
);
2065 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2069 *ppdata
= (char *)SMB_REALLOC(
2070 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2071 if(*ppdata
== NULL
) {
2072 talloc_destroy(ea_ctx
);
2073 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2078 /* Realloc the params space */
2079 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2080 if(*pparams
== NULL
) {
2081 talloc_destroy(ea_ctx
);
2082 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2087 /* Check that the dptr is valid */
2088 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
))) {
2089 talloc_destroy(ea_ctx
);
2090 return ERROR_DOS(ERRDOS
,ERRnofiles
);
2093 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
2095 /* Get the wildcard mask from the dptr */
2096 if((p
= dptr_wcard(dptr_num
))== NULL
) {
2097 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2098 talloc_destroy(ea_ctx
);
2099 return ERROR_DOS(ERRDOS
,ERRnofiles
);
2103 pstrcpy(directory
,conn
->dirpath
);
2105 /* Get the attr mask from the dptr */
2106 dirtype
= dptr_attr(dptr_num
);
2108 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2109 dptr_num
, mask
, dirtype
,
2111 dptr_TellDir(conn
->dirptr
)));
2113 /* We don't need to check for VOL here as this is returned by
2114 a different TRANS2 call. */
2116 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
2117 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),conn
->case_sensitive
))
2118 dont_descend
= True
;
2121 space_remaining
= max_data_bytes
;
2122 out_of_space
= False
;
2125 * Seek to the correct position. We no longer use the resume key but
2126 * depend on the last file name instead.
2129 if(*resume_name
&& !continue_bit
) {
2132 long current_pos
= 0;
2134 * Remember, mangle_map is called by
2135 * get_lanman2_dir_entry(), so the resume name
2136 * could be mangled. Ensure we check the unmangled name.
2139 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2140 mangle_check_cache(resume_name
, sizeof(resume_name
)-1,
2145 * Fix for NT redirector problem triggered by resume key indexes
2146 * changing between directory scans. We now return a resume key of 0
2147 * and instead look for the filename to continue from (also given
2148 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2149 * findfirst/findnext (as is usual) then the directory pointer
2150 * should already be at the correct place.
2153 finished
= !dptr_SearchDir(conn
->dirptr
, resume_name
, ¤t_pos
, &st
);
2154 } /* end if resume_name && !continue_bit */
2156 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2157 BOOL got_exact_match
= False
;
2159 /* this is a heuristic to avoid seeking the dirptr except when
2160 absolutely necessary. It allows for a filename of about 40 chars */
2161 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2162 out_of_space
= True
;
2165 finished
= !get_lanman2_dir_entry(conn
,
2167 mask
,dirtype
,info_level
,
2168 requires_resume_key
,dont_descend
,
2169 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
2170 &last_entry_off
, ea_list
, ea_ctx
);
2173 if (finished
&& out_of_space
)
2176 if (!finished
&& !out_of_space
)
2180 * As an optimisation if we know we aren't looking
2181 * for a wildcard name (ie. the name matches the wildcard exactly)
2182 * then we can finish on any (first) match.
2183 * This speeds up large directory searches. JRA.
2189 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2192 talloc_destroy(ea_ctx
);
2194 /* Check if we can close the dirptr */
2195 if(close_after_request
|| (finished
&& close_if_end
)) {
2196 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2197 dptr_close(&dptr_num
); /* This frees up the saved mask */
2200 /* Set up the return parameter block */
2201 SSVAL(params
,0,numentries
);
2202 SSVAL(params
,2,finished
);
2203 SSVAL(params
,4,0); /* Never an EA error */
2204 SSVAL(params
,6,last_entry_off
);
2206 send_trans2_replies( outbuf
, bufsize
, params
, 8, pdata
, PTR_DIFF(p
,pdata
), max_data_bytes
);
2208 if ((! *directory
) && dptr_path(dptr_num
))
2209 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
2211 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2212 smb_fn_name(CVAL(inbuf
,smb_com
)),
2213 mask
, directory
, dirtype
, numentries
) );
2218 /****************************************************************************
2219 Reply to a TRANS2_QFSINFO (query filesystem info).
2220 ****************************************************************************/
2222 static int call_trans2qfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
2223 char **pparams
, int total_params
, char **ppdata
, int total_data
,
2224 unsigned int max_data_bytes
)
2227 char *params
= *pparams
;
2231 char *vname
= volume_label(SNUM(conn
));
2232 int snum
= SNUM(conn
);
2233 char *fstype
= lp_fstype(SNUM(conn
));
2236 if (total_params
< 2) {
2237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2240 info_level
= SVAL(params
,0);
2242 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
2244 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
2245 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
2246 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
2249 *ppdata
= (char *)SMB_REALLOC(
2250 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2251 if (*ppdata
== NULL
) {
2252 return ERROR_NT(NT_STATUS_NO_MEMORY
);
2256 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2258 switch (info_level
) {
2259 case SMB_INFO_ALLOCATION
:
2261 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2263 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2264 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2267 block_size
= lp_block_size(snum
);
2268 if (bsize
< block_size
) {
2269 SMB_BIG_UINT factor
= block_size
/bsize
;
2274 if (bsize
> block_size
) {
2275 SMB_BIG_UINT factor
= bsize
/block_size
;
2280 bytes_per_sector
= 512;
2281 sectors_per_unit
= bsize
/bytes_per_sector
;
2283 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2284 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2285 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2287 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
2288 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2289 SIVAL(pdata
,l1_cUnit
,dsize
);
2290 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2291 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2295 case SMB_INFO_VOLUME
:
2296 /* Return volume name */
2298 * Add volume serial number - hash of a combination of
2299 * the called hostname and the service name.
2301 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2303 * Win2k3 and previous mess this up by sending a name length
2304 * one byte short. I believe only older clients (OS/2 Win9x) use
2305 * this call so try fixing this by adding a terminating null to
2306 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2308 len
= srvstr_push(outbuf
, pdata
+l2_vol_szVolLabel
, vname
, -1, STR_NOALIGN
|STR_TERMINATE
);
2309 SCVAL(pdata
,l2_vol_cch
,len
);
2310 data_len
= l2_vol_szVolLabel
+ len
;
2311 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2312 (unsigned)st
.st_ctime
, len
, vname
));
2315 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2316 case SMB_FS_ATTRIBUTE_INFORMATION
:
2319 #if defined(HAVE_SYS_QUOTAS)
2320 quota_flag
= FILE_VOLUME_QUOTAS
;
2323 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2324 (lp_nt_acl_support(SNUM(conn
)) ? FILE_PERSISTENT_ACLS
: 0)|
2325 quota_flag
); /* FS ATTRIBUTES */
2327 SIVAL(pdata
,4,255); /* Max filename component length */
2328 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2329 and will think we can't do long filenames */
2330 len
= srvstr_push(outbuf
, pdata
+12, fstype
, -1, STR_UNICODE
);
2332 data_len
= 12 + len
;
2335 case SMB_QUERY_FS_LABEL_INFO
:
2336 case SMB_FS_LABEL_INFORMATION
:
2337 len
= srvstr_push(outbuf
, pdata
+4, vname
, -1, 0);
2342 case SMB_QUERY_FS_VOLUME_INFO
:
2343 case SMB_FS_VOLUME_INFORMATION
:
2346 * Add volume serial number - hash of a combination of
2347 * the called hostname and the service name.
2349 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
2350 (str_checksum(get_local_machine_name())<<16));
2352 len
= srvstr_push(outbuf
, pdata
+18, vname
, -1, STR_UNICODE
);
2353 SIVAL(pdata
,12,len
);
2355 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2356 (int)strlen(vname
),vname
, lp_servicename(snum
)));
2359 case SMB_QUERY_FS_SIZE_INFO
:
2360 case SMB_FS_SIZE_INFORMATION
:
2362 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2364 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2365 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2367 block_size
= lp_block_size(snum
);
2368 if (bsize
< block_size
) {
2369 SMB_BIG_UINT factor
= block_size
/bsize
;
2374 if (bsize
> block_size
) {
2375 SMB_BIG_UINT factor
= bsize
/block_size
;
2380 bytes_per_sector
= 512;
2381 sectors_per_unit
= bsize
/bytes_per_sector
;
2382 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2383 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2384 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2385 SBIG_UINT(pdata
,0,dsize
);
2386 SBIG_UINT(pdata
,8,dfree
);
2387 SIVAL(pdata
,16,sectors_per_unit
);
2388 SIVAL(pdata
,20,bytes_per_sector
);
2392 case SMB_FS_FULL_SIZE_INFORMATION
:
2394 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
2396 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
2397 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2399 block_size
= lp_block_size(snum
);
2400 if (bsize
< block_size
) {
2401 SMB_BIG_UINT factor
= block_size
/bsize
;
2406 if (bsize
> block_size
) {
2407 SMB_BIG_UINT factor
= bsize
/block_size
;
2412 bytes_per_sector
= 512;
2413 sectors_per_unit
= bsize
/bytes_per_sector
;
2414 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2415 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2416 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2417 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2418 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2419 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2420 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2421 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2425 case SMB_QUERY_FS_DEVICE_INFO
:
2426 case SMB_FS_DEVICE_INFORMATION
:
2428 SIVAL(pdata
,0,0); /* dev type */
2429 SIVAL(pdata
,4,0); /* characteristics */
2432 #ifdef HAVE_SYS_QUOTAS
2433 case SMB_FS_QUOTA_INFORMATION
:
2435 * what we have to send --metze:
2437 * Unknown1: 24 NULL bytes
2438 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2439 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2440 * Quota Flags: 2 byte :
2441 * Unknown3: 6 NULL bytes
2445 * details for Quota Flags:
2447 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2448 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2449 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2450 * 0x0001 Enable Quotas: enable quota for this fs
2454 /* we need to fake up a fsp here,
2455 * because its not send in this call
2458 SMB_NTQUOTA_STRUCT quotas
;
2461 ZERO_STRUCT(quotas
);
2467 if (current_user
.ut
.uid
!= 0) {
2468 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2469 lp_servicename(SNUM(conn
)),conn
->user
));
2470 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2473 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2474 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2475 return ERROR_DOS(ERRSRV
,ERRerror
);
2480 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2482 /* Unknown1 24 NULL bytes*/
2483 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2484 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2485 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2487 /* Default Soft Quota 8 bytes */
2488 SBIG_UINT(pdata
,24,quotas
.softlim
);
2490 /* Default Hard Quota 8 bytes */
2491 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2493 /* Quota flag 2 bytes */
2494 SSVAL(pdata
,40,quotas
.qflags
);
2496 /* Unknown3 6 NULL bytes */
2502 #endif /* HAVE_SYS_QUOTAS */
2503 case SMB_FS_OBJECTID_INFORMATION
:
2508 * Query the version and capabilities of the CIFS UNIX extensions
2512 case SMB_QUERY_CIFS_UNIX_INFO
:
2513 if (!lp_unix_extensions()) {
2514 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2517 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2518 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2519 /* We have POSIX ACLs, pathname and locking capability. */
2520 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)(
2521 CIFS_UNIX_POSIX_ACLS_CAP
|
2522 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2523 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2524 CIFS_UNIX_EXTATTR_CAP
|
2525 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)));
2528 case SMB_QUERY_POSIX_FS_INFO
:
2531 vfs_statvfs_struct svfs
;
2533 if (!lp_unix_extensions()) {
2534 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2537 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
2541 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2542 SIVAL(pdata
,4,svfs
.BlockSize
);
2543 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2544 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2545 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2546 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2547 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2548 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2549 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2551 } else if (rc
== EOPNOTSUPP
) {
2552 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2553 #endif /* EOPNOTSUPP */
2555 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2556 return ERROR_DOS(ERRSRV
,ERRerror
);
2561 case SMB_QUERY_POSIX_WHOAMI
:
2567 if (!lp_unix_extensions()) {
2568 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2571 if (max_data_bytes
< 40) {
2572 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL
);
2575 /* We ARE guest if global_sid_Builtin_Guests is
2576 * in our list of SIDs.
2578 if (nt_token_check_sid(&global_sid_Builtin_Guests
,
2579 current_user
.nt_user_token
)) {
2580 flags
|= SMB_WHOAMI_GUEST
;
2583 /* We are NOT guest if global_sid_Authenticated_Users
2584 * is in our list of SIDs.
2586 if (nt_token_check_sid(&global_sid_Authenticated_Users
,
2587 current_user
.nt_user_token
)) {
2588 flags
&= ~SMB_WHOAMI_GUEST
;
2591 /* NOTE: 8 bytes for UID/GID, irrespective of native
2592 * platform size. This matches
2593 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2595 data_len
= 4 /* flags */
2602 + 4 /* pad/reserved */
2603 + (current_user
.ut
.ngroups
* 8)
2605 + (current_user
.nt_user_token
->num_sids
*
2609 SIVAL(pdata
, 0, flags
);
2610 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2611 SBIG_UINT(pdata
, 8, (SMB_BIG_UINT
)current_user
.ut
.uid
);
2612 SBIG_UINT(pdata
, 16, (SMB_BIG_UINT
)current_user
.ut
.gid
);
2615 if (data_len
>= max_data_bytes
) {
2616 /* Potential overflow, skip the GIDs and SIDs. */
2618 SIVAL(pdata
, 24, 0); /* num_groups */
2619 SIVAL(pdata
, 28, 0); /* num_sids */
2620 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2621 SIVAL(pdata
, 36, 0); /* reserved */
2627 SIVAL(pdata
, 24, current_user
.ut
.ngroups
);
2629 current_user
.nt_user_token
->num_sids
);
2631 /* We walk the SID list twice, but this call is fairly
2632 * infrequent, and I don't expect that it's performance
2633 * sensitive -- jpeach
2635 for (i
= 0, sid_bytes
= 0;
2636 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
2638 sid_size(¤t_user
.nt_user_token
->user_sids
[i
]);
2641 /* SID list byte count */
2642 SIVAL(pdata
, 32, sid_bytes
);
2644 /* 4 bytes pad/reserved - must be zero */
2645 SIVAL(pdata
, 36, 0);
2649 for (i
= 0; i
< current_user
.ut
.ngroups
; ++i
) {
2650 SBIG_UINT(pdata
, data_len
,
2651 (SMB_BIG_UINT
)current_user
.ut
.groups
[i
]);
2657 i
< current_user
.nt_user_token
->num_sids
; ++i
) {
2659 sid_size(¤t_user
.nt_user_token
->user_sids
[i
]);
2661 sid_linearize(pdata
+ data_len
, sid_len
,
2662 ¤t_user
.nt_user_token
->user_sids
[i
]);
2663 data_len
+= sid_len
;
2669 case SMB_MAC_QUERY_FS_INFO
:
2671 * Thursby MAC extension... ONLY on NTFS filesystems
2672 * once we do streams then we don't need this
2674 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2676 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2681 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2685 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
, max_data_bytes
);
2687 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf
,smb_com
)), info_level
) );
2692 /****************************************************************************
2693 Reply to a TRANS2_SETFSINFO (set filesystem info).
2694 ****************************************************************************/
2696 static int call_trans2setfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
2697 char **pparams
, int total_params
, char **ppdata
, int total_data
,
2698 unsigned int max_data_bytes
)
2700 char *pdata
= *ppdata
;
2701 char *params
= *pparams
;
2705 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn
))));
2708 if (total_params
< 4) {
2709 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2714 info_level
= SVAL(params
,2);
2716 switch(info_level
) {
2717 case SMB_SET_CIFS_UNIX_INFO
:
2719 uint16 client_unix_major
;
2720 uint16 client_unix_minor
;
2721 uint32 client_unix_cap_low
;
2722 uint32 client_unix_cap_high
;
2724 if (!lp_unix_extensions()) {
2725 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2728 /* There should be 12 bytes of capabilities set. */
2729 if (total_data
< 8) {
2730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2732 client_unix_major
= SVAL(pdata
,0);
2733 client_unix_minor
= SVAL(pdata
,2);
2734 client_unix_cap_low
= IVAL(pdata
,4);
2735 client_unix_cap_high
= IVAL(pdata
,8);
2736 /* Just print these values for now. */
2737 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2738 cap_low = 0x%x, cap_high = 0x%x\n",
2739 (unsigned int)client_unix_major
,
2740 (unsigned int)client_unix_minor
,
2741 (unsigned int)client_unix_cap_low
,
2742 (unsigned int)client_unix_cap_high
));
2744 /* Here is where we must switch to posix pathname processing... */
2745 if (client_unix_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
2746 lp_set_posix_pathnames();
2747 mangle_change_to_posix();
2750 if ((client_unix_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
2751 !(client_unix_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
2752 /* Client that knows how to do posix locks,
2753 * but not posix open/mkdir operations. Set a
2754 * default type for read/write checks. */
2756 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
2761 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
2764 size_t data_len
= total_data
;
2766 if (!lp_unix_extensions()) {
2767 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2770 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2772 status
= srv_request_encryption_setup((unsigned char **)&pdata
, &data_len
);
2774 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
2775 error_packet_set(outbuf
, 0, 0, status
, __LINE__
,__FILE__
);
2776 } else if (!NT_STATUS_IS_OK(status
)) {
2777 return ERROR_NT(status
);
2780 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
, max_data_bytes
);
2782 if (NT_STATUS_IS_OK(status
)) {
2783 /* Server-side transport encryption is now *on*. */
2784 srv_encryption_start();
2788 case SMB_FS_QUOTA_INFORMATION
:
2790 files_struct
*fsp
= NULL
;
2791 SMB_NTQUOTA_STRUCT quotas
;
2793 ZERO_STRUCT(quotas
);
2796 if ((current_user
.ut
.uid
!= 0)||!CAN_WRITE(conn
)) {
2797 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2798 lp_servicename(SNUM(conn
)),conn
->user
));
2799 return ERROR_DOS(ERRSRV
,ERRaccess
);
2802 /* note: normaly there're 48 bytes,
2803 * but we didn't use the last 6 bytes for now
2806 fsp
= file_fsp(params
,0);
2807 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
2808 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2809 return ERROR_NT(NT_STATUS_INVALID_HANDLE
);
2812 if (total_data
< 42) {
2813 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2815 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2818 /* unknown_1 24 NULL bytes in pdata*/
2820 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2821 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
2822 #ifdef LARGE_SMB_OFF_T
2823 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
2824 #else /* LARGE_SMB_OFF_T */
2825 if ((IVAL(pdata
,28) != 0)&&
2826 ((quotas
.softlim
!= 0xFFFFFFFF)||
2827 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
2828 /* more than 32 bits? */
2829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2831 #endif /* LARGE_SMB_OFF_T */
2833 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2834 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
2835 #ifdef LARGE_SMB_OFF_T
2836 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
2837 #else /* LARGE_SMB_OFF_T */
2838 if ((IVAL(pdata
,36) != 0)&&
2839 ((quotas
.hardlim
!= 0xFFFFFFFF)||
2840 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
2841 /* more than 32 bits? */
2842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2844 #endif /* LARGE_SMB_OFF_T */
2846 /* quota_flags 2 bytes **/
2847 quotas
.qflags
= SVAL(pdata
,40);
2849 /* unknown_2 6 NULL bytes follow*/
2851 /* now set the quotas */
2852 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2853 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2854 return ERROR_DOS(ERRSRV
,ERRerror
);
2860 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2862 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
2867 * sending this reply works fine,
2868 * but I'm not sure it's the same
2869 * like windows do...
2872 outsize
= set_message(outbuf
,10,0,True
);
2877 #if defined(HAVE_POSIX_ACLS)
2878 /****************************************************************************
2879 Utility function to count the number of entries in a POSIX acl.
2880 ****************************************************************************/
2882 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2884 unsigned int ace_count
= 0;
2885 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2886 SMB_ACL_ENTRY_T entry
;
2888 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
2890 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2891 entry_id
= SMB_ACL_NEXT_ENTRY
;
2898 /****************************************************************************
2899 Utility function to marshall a POSIX acl into wire format.
2900 ****************************************************************************/
2902 static BOOL
marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2904 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2905 SMB_ACL_ENTRY_T entry
;
2907 while ( posix_acl
&& (SMB_VFS_SYS_ACL_GET_ENTRY(conn
, posix_acl
, entry_id
, &entry
) == 1)) {
2908 SMB_ACL_TAG_T tagtype
;
2909 SMB_ACL_PERMSET_T permset
;
2910 unsigned char perms
= 0;
2911 unsigned int own_grp
;
2914 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2915 entry_id
= SMB_ACL_NEXT_ENTRY
;
2918 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn
, entry
, &tagtype
) == -1) {
2919 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2923 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn
, entry
, &permset
) == -1) {
2924 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2928 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2929 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2930 perms
|= (SMB_VFS_SYS_ACL_GET_PERM(conn
, permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2932 SCVAL(pdata
,1,perms
);
2935 case SMB_ACL_USER_OBJ
:
2936 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2937 own_grp
= (unsigned int)pst
->st_uid
;
2938 SIVAL(pdata
,2,own_grp
);
2943 uid_t
*puid
= (uid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
2945 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2947 own_grp
= (unsigned int)*puid
;
2948 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)puid
,tagtype
);
2949 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2950 SIVAL(pdata
,2,own_grp
);
2954 case SMB_ACL_GROUP_OBJ
:
2955 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2956 own_grp
= (unsigned int)pst
->st_gid
;
2957 SIVAL(pdata
,2,own_grp
);
2962 gid_t
*pgid
= (gid_t
*)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn
, entry
);
2964 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2966 own_grp
= (unsigned int)*pgid
;
2967 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn
, (void *)pgid
,tagtype
);
2968 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2969 SIVAL(pdata
,2,own_grp
);
2974 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2975 SIVAL(pdata
,2,0xFFFFFFFF);
2976 SIVAL(pdata
,6,0xFFFFFFFF);
2979 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2980 SIVAL(pdata
,2,0xFFFFFFFF);
2981 SIVAL(pdata
,6,0xFFFFFFFF);
2984 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2987 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2994 /****************************************************************************
2995 Store the FILE_UNIX_BASIC info.
2996 ****************************************************************************/
2998 static char *store_file_unix_basic(connection_struct
*conn
,
3001 const SMB_STRUCT_STAT
*psbuf
)
3003 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3004 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_mode
));
3006 SOFF_T(pdata
,0,get_file_size(*psbuf
)); /* File size 64 Bit */
3009 SOFF_T(pdata
,0,get_allocation_size(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3012 put_long_date_timespec(pdata
,get_ctimespec(psbuf
)); /* Change Time 64 Bit */
3013 put_long_date_timespec(pdata
+8,get_atimespec(psbuf
)); /* Last access time 64 Bit */
3014 put_long_date_timespec(pdata
+16,get_mtimespec(psbuf
)); /* Last modification time 64 Bit */
3017 SIVAL(pdata
,0,psbuf
->st_uid
); /* user id for the owner */
3021 SIVAL(pdata
,0,psbuf
->st_gid
); /* group id of owner */
3025 SIVAL(pdata
,0,unix_filetype(psbuf
->st_mode
));
3028 SIVAL(pdata
,0,unix_dev_major(psbuf
->st_rdev
)); /* Major device number if type is device */
3032 SIVAL(pdata
,0,unix_dev_minor(psbuf
->st_rdev
)); /* Minor device number if type is device */
3036 SINO_T_VAL(pdata
,0,(SMB_INO_T
)psbuf
->st_ino
); /* inode number */
3039 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_mode
)); /* Standard UNIX file permissions */
3043 SIVAL(pdata
,0,psbuf
->st_nlink
); /* number of hard links */
3050 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3051 * the chflags(2) (or equivalent) flags.
3053 * XXX: this really should be behind the VFS interface. To do this, we would
3054 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3055 * Each VFS module could then implement it's own mapping as appropriate for the
3056 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3058 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3062 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3066 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3070 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3074 { UF_HIDDEN
, EXT_HIDDEN
},
3077 /* Do not remove. We need to guarantee that this array has at least one
3078 * entry to build on HP-UX.
3084 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3085 uint32
*smb_fflags
, uint32
*smb_fmask
)
3087 #ifdef HAVE_STAT_ST_FLAGS
3090 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3091 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3092 if (psbuf
->st_flags
& info2_flags_map
[i
].stat_fflag
) {
3093 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3096 #endif /* HAVE_STAT_ST_FLAGS */
3099 static BOOL
map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3100 const uint32 smb_fflags
,
3101 const uint32 smb_fmask
,
3104 #ifdef HAVE_STAT_ST_FLAGS
3105 uint32 max_fmask
= 0;
3108 *stat_fflags
= psbuf
->st_flags
;
3110 /* For each flags requested in smb_fmask, check the state of the
3111 * corresponding flag in smb_fflags and set or clear the matching
3115 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3116 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3117 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3118 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3119 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3121 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3126 /* If smb_fmask is asking to set any bits that are not supported by
3127 * our flag mappings, we should fail.
3129 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3136 #endif /* HAVE_STAT_ST_FLAGS */
3140 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3141 * of file flags and birth (create) time.
3143 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3146 const SMB_STRUCT_STAT
*psbuf
)
3148 uint32 file_flags
= 0;
3149 uint32 flags_mask
= 0;
3151 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3153 /* Create (birth) time 64 bit */
3154 put_long_date_timespec(pdata
, get_create_timespec(psbuf
, False
));
3157 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3158 SIVAL(pdata
, 0, file_flags
); /* flags */
3159 SIVAL(pdata
, 4, flags_mask
); /* mask */
3165 /****************************************************************************
3166 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3167 file name or file id).
3168 ****************************************************************************/
3170 static int call_trans2qfilepathinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
3171 unsigned int tran_call
,
3172 char **pparams
, int total_params
, char **ppdata
, int total_data
,
3173 unsigned int max_data_bytes
)
3175 char *params
= *pparams
;
3176 char *pdata
= *ppdata
;
3180 SMB_OFF_T file_size
=0;
3181 SMB_BIG_UINT allocation_size
=0;
3182 unsigned int data_size
= 0;
3183 unsigned int param_size
= 2;
3184 SMB_STRUCT_STAT sbuf
;
3185 pstring fname
, dos_fname
;
3190 BOOL delete_pending
= False
;
3192 time_t create_time
, mtime
, atime
;
3193 struct timespec create_time_ts
, mtime_ts
, atime_ts
;
3194 files_struct
*fsp
= NULL
;
3195 TALLOC_CTX
*data_ctx
= NULL
;
3196 struct ea_list
*ea_list
= NULL
;
3197 uint32 access_mask
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3198 char *lock_data
= NULL
;
3201 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3205 if (tran_call
== TRANSACT2_QFILEINFO
) {
3206 if (total_params
< 4) {
3207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3210 fsp
= file_fsp(params
,0);
3211 info_level
= SVAL(params
,2);
3213 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
3215 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3216 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
3219 if(fsp
&& (fsp
->fake_file_handle
)) {
3221 * This is actually for the QUOTA_FAKE_FILE --metze
3224 pstrcpy(fname
, fsp
->fsp_name
);
3225 /* We know this name is ok, it's already passed the checks. */
3227 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
3229 * This is actually a QFILEINFO on a directory
3230 * handle (returned from an NT SMB). NT5.0 seems
3231 * to do this call. JRA.
3233 /* We know this name is ok, it's already passed the checks. */
3234 pstrcpy(fname
, fsp
->fsp_name
);
3236 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3237 /* Always do lstat for UNIX calls. */
3238 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3239 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3240 return UNIXERROR(ERRDOS
,ERRbadpath
);
3242 } else if (SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
3243 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3244 return UNIXERROR(ERRDOS
,ERRbadpath
);
3247 delete_pending
= get_delete_on_close_flag(sbuf
.st_dev
, sbuf
.st_ino
);
3250 * Original code - this is an open file.
3252 CHECK_FSP(fsp
,conn
);
3254 pstrcpy(fname
, fsp
->fsp_name
);
3255 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&sbuf
) != 0) {
3256 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
3257 return(UNIXERROR(ERRDOS
,ERRbadfid
));
3259 pos
= fsp
->fh
->position_information
;
3260 delete_pending
= get_delete_on_close_flag(sbuf
.st_dev
, sbuf
.st_ino
);
3261 access_mask
= fsp
->access_mask
;
3264 NTSTATUS status
= NT_STATUS_OK
;
3267 if (total_params
< 7) {
3268 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3271 info_level
= SVAL(params
,0);
3273 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
3275 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3276 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
3279 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), total_params
- 6, STR_TERMINATE
, &status
);
3280 if (!NT_STATUS_IS_OK(status
)) {
3281 return ERROR_NT(status
);
3284 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
3285 if (!NT_STATUS_IS_OK(status
)) {
3286 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3287 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
3289 return ERROR_NT(status
);
3292 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
3293 if (!NT_STATUS_IS_OK(status
)) {
3294 return ERROR_NT(status
);
3296 status
= check_name(conn
, fname
);
3297 if (!NT_STATUS_IS_OK(status
)) {
3298 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,nt_errstr(status
)));
3299 return ERROR_NT(status
);
3302 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3303 /* Always do lstat for UNIX calls. */
3304 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
3305 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
3306 return UNIXERROR(ERRDOS
,ERRbadpath
);
3308 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
3309 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
3310 return UNIXERROR(ERRDOS
,ERRbadpath
);
3313 delete_pending
= get_delete_on_close_flag(sbuf
.st_dev
, sbuf
.st_ino
);
3314 if (delete_pending
) {
3315 return ERROR_NT(NT_STATUS_DELETE_PENDING
);
3319 nlink
= sbuf
.st_nlink
;
3321 if ((nlink
> 0) && S_ISDIR(sbuf
.st_mode
)) {
3322 /* NTFS does not seem to count ".." */
3326 if ((nlink
> 0) && delete_pending
) {
3330 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
3331 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
3334 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3335 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
3337 p
= strrchr_m(fname
,'/');
3343 mode
= dos_mode(conn
,fname
,&sbuf
);
3345 mode
= FILE_ATTRIBUTE_NORMAL
;
3347 fullpathname
= fname
;
3349 file_size
= get_file_size(sbuf
);
3351 /* Pull out any data sent here before we realloc. */
3352 switch (info_level
) {
3353 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3355 /* Pull any EA list from the data portion. */
3358 if (total_data
< 4) {
3359 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3361 ea_size
= IVAL(pdata
,0);
3363 if (total_data
> 0 && ea_size
!= total_data
) {
3364 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3365 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3366 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3369 if (!lp_ea_support(SNUM(conn
))) {
3370 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
3373 if ((data_ctx
= talloc_init("ea_list")) == NULL
) {
3374 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3377 /* Pull out the list of names. */
3378 ea_list
= read_ea_name_list(data_ctx
, pdata
+ 4, ea_size
- 4);
3380 talloc_destroy(data_ctx
);
3381 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3386 case SMB_QUERY_POSIX_LOCK
:
3388 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
3389 return ERROR_NT(NT_STATUS_INVALID_HANDLE
);
3392 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
3393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3396 if ((data_ctx
= talloc_init("lock_request")) == NULL
) {
3397 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3400 /* Copy the lock range data. */
3401 lock_data
= (char *)talloc_memdup(
3402 data_ctx
, pdata
, total_data
);
3404 talloc_destroy(data_ctx
);
3405 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3412 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
3413 if (*pparams
== NULL
) {
3414 talloc_destroy(data_ctx
);
3415 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3419 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3420 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3421 if (*ppdata
== NULL
) {
3422 talloc_destroy(data_ctx
);
3423 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3427 create_time_ts
= get_create_timespec(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
3428 mtime_ts
= get_mtimespec(&sbuf
);
3429 atime_ts
= get_atimespec(&sbuf
);
3431 allocation_size
= get_allocation_size(conn
,fsp
,&sbuf
);
3434 if (!null_timespec(fsp
->pending_modtime
)) {
3435 /* the pending modtime overrides the current modtime */
3436 mtime_ts
= fsp
->pending_modtime
;
3439 /* Do we have this path open ? */
3440 files_struct
*fsp1
= file_find_di_first(sbuf
.st_dev
, sbuf
.st_ino
);
3441 if (fsp1
&& !null_timespec(fsp1
->pending_modtime
)) {
3442 /* the pending modtime overrides the current modtime */
3443 mtime_ts
= fsp1
->pending_modtime
;
3445 if (fsp1
&& fsp1
->initial_allocation_size
) {
3446 allocation_size
= get_allocation_size(conn
, fsp1
, &sbuf
);
3450 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3451 dos_filetime_timespec(&create_time_ts
);
3452 dos_filetime_timespec(&mtime_ts
);
3453 dos_filetime_timespec(&atime_ts
);
3456 create_time
= convert_timespec_to_time_t(create_time_ts
);
3457 mtime
= convert_timespec_to_time_t(mtime_ts
);
3458 atime
= convert_timespec_to_time_t(atime_ts
);
3460 /* NT expects the name to be in an exact form of the *full*
3461 filename. See the trans2 torture test */
3462 if (strequal(base_name
,".")) {
3463 pstrcpy(dos_fname
, "\\");
3465 pstr_sprintf(dos_fname
, "\\%s", fname
);
3466 string_replace(dos_fname
, '/', '\\');
3469 switch (info_level
) {
3470 case SMB_INFO_STANDARD
:
3471 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3473 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3474 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3475 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3476 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
3477 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
3478 SSVAL(pdata
,l1_attrFile
,mode
);
3481 case SMB_INFO_QUERY_EA_SIZE
:
3483 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3484 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3486 srv_put_dos_date2(pdata
,0,create_time
);
3487 srv_put_dos_date2(pdata
,4,atime
);
3488 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3489 SIVAL(pdata
,12,(uint32
)file_size
);
3490 SIVAL(pdata
,16,(uint32
)allocation_size
);
3491 SSVAL(pdata
,20,mode
);
3492 SIVAL(pdata
,22,ea_size
);
3496 case SMB_INFO_IS_NAME_VALID
:
3497 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3498 if (tran_call
== TRANSACT2_QFILEINFO
) {
3499 /* os/2 needs this ? really ?*/
3500 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
3506 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3508 size_t total_ea_len
= 0;
3509 struct ea_list
*ea_file_list
= NULL
;
3511 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3513 ea_file_list
= get_ea_list_from_file(data_ctx
, conn
, fsp
, fname
, &total_ea_len
);
3514 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3516 if (!ea_list
|| (total_ea_len
> data_size
)) {
3517 talloc_destroy(data_ctx
);
3519 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3523 data_size
= fill_ea_buffer(data_ctx
, pdata
, data_size
, conn
, ea_list
);
3524 talloc_destroy(data_ctx
);
3528 case SMB_INFO_QUERY_ALL_EAS
:
3530 /* We have data_size bytes to put EA's into. */
3531 size_t total_ea_len
= 0;
3533 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3535 data_ctx
= talloc_init("ea_ctx");
3537 return ERROR_NT(NT_STATUS_NO_MEMORY
);
3540 ea_list
= get_ea_list_from_file(data_ctx
, conn
, fsp
, fname
, &total_ea_len
);
3541 if (!ea_list
|| (total_ea_len
> data_size
)) {
3542 talloc_destroy(data_ctx
);
3544 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3548 data_size
= fill_ea_buffer(data_ctx
, pdata
, data_size
, conn
, ea_list
);
3549 talloc_destroy(data_ctx
);
3553 case SMB_FILE_BASIC_INFORMATION
:
3554 case SMB_QUERY_FILE_BASIC_INFO
:
3556 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3557 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3558 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3564 put_long_date_timespec(pdata
,create_time_ts
);
3565 put_long_date_timespec(pdata
+8,atime_ts
);
3566 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
3567 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
3568 SIVAL(pdata
,32,mode
);
3570 DEBUG(5,("SMB_QFBI - "));
3571 DEBUG(5,("create: %s ", ctime(&create_time
)));
3572 DEBUG(5,("access: %s ", ctime(&atime
)));
3573 DEBUG(5,("write: %s ", ctime(&mtime
)));
3574 DEBUG(5,("change: %s ", ctime(&mtime
)));
3575 DEBUG(5,("mode: %x\n", mode
));
3578 case SMB_FILE_STANDARD_INFORMATION
:
3579 case SMB_QUERY_FILE_STANDARD_INFO
:
3581 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3583 SOFF_T(pdata
,0,allocation_size
);
3584 SOFF_T(pdata
,8,file_size
);
3585 SIVAL(pdata
,16,nlink
);
3586 SCVAL(pdata
,20,delete_pending
?1:0);
3587 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
3588 SSVAL(pdata
,22,0); /* Padding. */
3591 case SMB_FILE_EA_INFORMATION
:
3592 case SMB_QUERY_FILE_EA_INFO
:
3594 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3595 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3597 SIVAL(pdata
,0,ea_size
);
3601 /* Get the 8.3 name - used if NT SMB was negotiated. */
3602 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3603 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3607 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3608 pstrcpy(short_name
,base_name
);
3609 /* Mangle if not already 8.3 */
3610 if(!mangle_is_8_3(short_name
, True
, conn
->params
)) {
3611 mangle_map(short_name
,True
,True
,conn
->params
);
3613 len
= srvstr_push(outbuf
, pdata
+4, short_name
, -1, STR_UNICODE
);
3614 data_size
= 4 + len
;
3619 case SMB_QUERY_FILE_NAME_INFO
:
3621 this must be *exactly* right for ACLs on mapped drives to work
3623 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
3624 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3625 data_size
= 4 + len
;
3629 case SMB_FILE_ALLOCATION_INFORMATION
:
3630 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3631 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3633 SOFF_T(pdata
,0,allocation_size
);
3636 case SMB_FILE_END_OF_FILE_INFORMATION
:
3637 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3640 SOFF_T(pdata
,0,file_size
);
3643 case SMB_QUERY_FILE_ALL_INFO
:
3644 case SMB_FILE_ALL_INFORMATION
:
3646 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
3647 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3648 put_long_date_timespec(pdata
,create_time_ts
);
3649 put_long_date_timespec(pdata
+8,atime_ts
);
3650 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
3651 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
3652 SIVAL(pdata
,32,mode
);
3653 SIVAL(pdata
,36,0); /* padding. */
3655 SOFF_T(pdata
,0,allocation_size
);
3656 SOFF_T(pdata
,8,file_size
);
3657 SIVAL(pdata
,16,nlink
);
3658 SCVAL(pdata
,20,delete_pending
);
3659 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
3662 SIVAL(pdata
,0,ea_size
);
3663 pdata
+= 4; /* EA info */
3664 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
3667 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3670 case SMB_FILE_INTERNAL_INFORMATION
:
3671 /* This should be an index number - looks like
3674 I think this causes us to fail the IFSKIT
3675 BasicFileInformationTest. -tpot */
3677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3678 SIVAL(pdata
,0,sbuf
.st_ino
); /* FileIndexLow */
3679 SIVAL(pdata
,4,sbuf
.st_dev
); /* FileIndexHigh */
3683 case SMB_FILE_ACCESS_INFORMATION
:
3684 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3685 SIVAL(pdata
,0,access_mask
);
3689 case SMB_FILE_NAME_INFORMATION
:
3690 /* Pathname with leading '\'. */
3693 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3695 SIVAL(pdata
,0,byte_len
);
3696 data_size
= 4 + byte_len
;
3700 case SMB_FILE_DISPOSITION_INFORMATION
:
3701 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3703 SCVAL(pdata
,0,delete_pending
);
3706 case SMB_FILE_POSITION_INFORMATION
:
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3709 SOFF_T(pdata
,0,pos
);
3712 case SMB_FILE_MODE_INFORMATION
:
3713 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3714 SIVAL(pdata
,0,mode
);
3718 case SMB_FILE_ALIGNMENT_INFORMATION
:
3719 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3720 SIVAL(pdata
,0,0); /* No alignment needed. */
3726 * NT4 server just returns "invalid query" to this - if we try to answer
3727 * it then NTws gets a BSOD! (tridge).
3728 * W2K seems to want this. JRA.
3730 case SMB_QUERY_FILE_STREAM_INFO
:
3732 case SMB_FILE_STREAM_INFORMATION
:
3733 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3737 size_t byte_len
= dos_PutUniCode(pdata
+24,"::$DATA", (size_t)0xE, False
);
3738 SIVAL(pdata
,0,0); /* ??? */
3739 SIVAL(pdata
,4,byte_len
); /* Byte length of unicode string ::$DATA */
3740 SOFF_T(pdata
,8,file_size
);
3741 SIVAL(pdata
,16,allocation_size
);
3742 SIVAL(pdata
,20,0); /* ??? */
3743 data_size
= 24 + byte_len
;
3747 case SMB_QUERY_COMPRESSION_INFO
:
3748 case SMB_FILE_COMPRESSION_INFORMATION
:
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3750 SOFF_T(pdata
,0,file_size
);
3751 SIVAL(pdata
,8,0); /* ??? */
3752 SIVAL(pdata
,12,0); /* ??? */
3756 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3757 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3758 put_long_date_timespec(pdata
,create_time_ts
);
3759 put_long_date_timespec(pdata
+8,atime_ts
);
3760 put_long_date_timespec(pdata
+16,mtime_ts
); /* write time */
3761 put_long_date_timespec(pdata
+24,mtime_ts
); /* change time */
3762 SIVAL(pdata
,32,allocation_size
);
3763 SOFF_T(pdata
,40,file_size
);
3764 SIVAL(pdata
,48,mode
);
3765 SIVAL(pdata
,52,0); /* ??? */
3769 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3770 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3771 SIVAL(pdata
,0,mode
);
3777 * CIFS UNIX Extensions.
3780 case SMB_QUERY_FILE_UNIX_BASIC
:
3782 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, &sbuf
);
3783 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3787 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3789 for (i
=0; i
<100; i
++)
3790 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
3796 case SMB_QUERY_FILE_UNIX_INFO2
:
3798 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, &sbuf
);
3799 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3803 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3805 for (i
=0; i
<100; i
++)
3806 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
3812 case SMB_QUERY_FILE_UNIX_LINK
:
3816 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3818 if(!S_ISLNK(sbuf
.st_mode
))
3819 return(UNIXERROR(ERRSRV
,ERRbadlink
));
3821 return(UNIXERROR(ERRDOS
,ERRbadlink
));
3823 len
= SMB_VFS_READLINK(conn
,fullpathname
, buffer
, sizeof(pstring
)-1); /* read link */
3825 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3827 len
= srvstr_push(outbuf
, pdata
, buffer
, -1, STR_TERMINATE
);
3829 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3834 #if defined(HAVE_POSIX_ACLS)
3835 case SMB_QUERY_POSIX_ACL
:
3837 SMB_ACL_T file_acl
= NULL
;
3838 SMB_ACL_T def_acl
= NULL
;
3839 uint16 num_file_acls
= 0;
3840 uint16 num_def_acls
= 0;
3842 if (fsp
&& !fsp
->is_directory
&& (fsp
->fh
->fd
!= -1)) {
3843 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, fsp
->fh
->fd
);
3845 file_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_ACCESS
);
3848 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
3849 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3851 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED
);
3854 if (S_ISDIR(sbuf
.st_mode
)) {
3855 if (fsp
&& fsp
->is_directory
) {
3856 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fsp
->fsp_name
, SMB_ACL_TYPE_DEFAULT
);
3858 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
, fname
, SMB_ACL_TYPE_DEFAULT
);
3860 def_acl
= free_empty_sys_acl(conn
, def_acl
);
3863 num_file_acls
= count_acl_entries(conn
, file_acl
);
3864 num_def_acls
= count_acl_entries(conn
, def_acl
);
3866 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
3867 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3869 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
3870 SMB_POSIX_ACL_HEADER_SIZE
) ));
3872 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3875 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3877 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL
);
3880 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
3881 SSVAL(pdata
,2,num_file_acls
);
3882 SSVAL(pdata
,4,num_def_acls
);
3883 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, &sbuf
, file_acl
)) {
3885 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3888 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3890 return ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
3892 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), &sbuf
, def_acl
)) {
3894 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3897 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3899 return ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
3903 SMB_VFS_SYS_ACL_FREE_ACL(conn
, file_acl
);
3906 SMB_VFS_SYS_ACL_FREE_ACL(conn
, def_acl
);
3908 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
3914 case SMB_QUERY_POSIX_LOCK
:
3916 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
3918 SMB_BIG_UINT offset
;
3920 enum brl_type lock_type
;
3922 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
3923 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3926 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
3927 case POSIX_LOCK_TYPE_READ
:
3928 lock_type
= READ_LOCK
;
3930 case POSIX_LOCK_TYPE_WRITE
:
3931 lock_type
= WRITE_LOCK
;
3933 case POSIX_LOCK_TYPE_UNLOCK
:
3935 /* There's no point in asking for an unlock... */
3936 talloc_destroy(data_ctx
);
3937 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3940 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
3941 #if defined(HAVE_LONGLONG)
3942 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
3943 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
3944 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
3945 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
3946 #else /* HAVE_LONGLONG */
3947 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
3948 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
3949 #endif /* HAVE_LONGLONG */
3951 status
= query_lock(fsp
,
3958 if (ERROR_WAS_LOCK_DENIED(status
)) {
3959 /* Here we need to report who has it locked... */
3960 data_size
= POSIX_LOCK_DATA_SIZE
;
3962 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
3963 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
3964 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, lock_pid
);
3965 #if defined(HAVE_LONGLONG)
3966 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
3967 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
3968 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
3969 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
3970 #else /* HAVE_LONGLONG */
3971 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
3972 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
3973 #endif /* HAVE_LONGLONG */
3975 } else if (NT_STATUS_IS_OK(status
)) {
3976 /* For success we just return a copy of what we sent
3977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3978 data_size
= POSIX_LOCK_DATA_SIZE
;
3979 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
3980 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
3982 return ERROR_NT(status
);
3988 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
3991 send_trans2_replies(outbuf
, bufsize
, params
, param_size
, *ppdata
, data_size
, max_data_bytes
);
3996 /****************************************************************************
3997 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3999 ****************************************************************************/
4001 NTSTATUS
hardlink_internals(connection_struct
*conn
, pstring oldname
, pstring newname
)
4003 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4004 pstring last_component_oldname
;
4005 pstring last_component_newname
;
4006 NTSTATUS status
= NT_STATUS_OK
;
4011 status
= unix_convert(conn
, oldname
, False
, last_component_oldname
, &sbuf1
);
4012 if (!NT_STATUS_IS_OK(status
)) {
4016 status
= check_name(conn
, oldname
);
4017 if (!NT_STATUS_IS_OK(status
)) {
4021 /* source must already exist. */
4022 if (!VALID_STAT(sbuf1
)) {
4023 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4026 status
= unix_convert(conn
, newname
, False
, last_component_newname
, &sbuf2
);
4027 if (!NT_STATUS_IS_OK(status
)) {
4031 status
= check_name(conn
, newname
);
4032 if (!NT_STATUS_IS_OK(status
)) {
4036 /* Disallow if newname already exists. */
4037 if (VALID_STAT(sbuf2
)) {
4038 return NT_STATUS_OBJECT_NAME_COLLISION
;
4041 /* No links from a directory. */
4042 if (S_ISDIR(sbuf1
.st_mode
)) {
4043 return NT_STATUS_FILE_IS_A_DIRECTORY
;
4046 /* Ensure this is within the share. */
4047 status
= reduce_name(conn
, oldname
);
4048 if (!NT_STATUS_IS_OK(status
)) {
4052 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
4054 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
4055 status
= map_nt_error_from_unix(errno
);
4056 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4057 nt_errstr(status
), newname
, oldname
));
4063 /****************************************************************************
4064 Deal with setting the time from any of the setfilepathinfo functions.
4065 ****************************************************************************/
4067 static NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4070 const SMB_STRUCT_STAT
*psbuf
,
4071 struct timespec ts
[2])
4074 FILE_NOTIFY_CHANGE_LAST_ACCESS
4075 |FILE_NOTIFY_CHANGE_LAST_WRITE
;
4078 if (!VALID_STAT(*psbuf
)) {
4079 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4082 /* get some defaults (no modifications) if any info is zero or -1. */
4083 if (null_timespec(ts
[0])) {
4084 ts
[0] = get_atimespec(psbuf
);
4085 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4088 if (null_timespec(ts
[1])) {
4089 ts
[1] = get_mtimespec(psbuf
);
4090 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4093 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts
[0])) ));
4094 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4097 * Try and set the times of this file if
4098 * they are different from the current values.
4102 struct timespec mts
= get_mtimespec(psbuf
);
4103 struct timespec ats
= get_atimespec(psbuf
);
4104 if ((timespec_compare(&ts
[0], &ats
) == 0) && (timespec_compare(&ts
[1], &mts
) == 0)) {
4105 return NT_STATUS_OK
;
4111 * This was a setfileinfo on an open file.
4112 * NT does this a lot. We also need to
4113 * set the time here, as it can be read by
4114 * FindFirst/FindNext and with the patch for bug #2045
4115 * in smbd/fileio.c it ensures that this timestamp is
4116 * kept sticky even after a write. We save the request
4117 * away and will set it on file close and after a write. JRA.
4120 if (!null_timespec(ts
[1])) {
4121 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4122 time_to_asc(convert_timespec_to_time_t(ts
[1])) ));
4123 fsp_set_pending_modtime(fsp
, ts
[1]);
4127 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4129 if(file_ntimes(conn
, fname
, ts
)!=0) {
4130 return map_nt_error_from_unix(errno
);
4133 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
, fname
);
4135 return NT_STATUS_OK
;
4138 /****************************************************************************
4139 Deal with setting the dosmode from any of the setfilepathinfo functions.
4140 ****************************************************************************/
4142 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4144 SMB_STRUCT_STAT
*psbuf
,
4147 if (!VALID_STAT(*psbuf
)) {
4148 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4152 if (S_ISDIR(psbuf
->st_mode
)) {
4159 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
4161 /* check the mode isn't different, before changing it */
4162 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, psbuf
))) {
4164 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4165 fname
, (unsigned int)dosmode
));
4167 if(file_set_dosmode(conn
, fname
, dosmode
, psbuf
, False
)) {
4168 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4169 fname
, strerror(errno
)));
4170 return map_nt_error_from_unix(errno
);
4173 return NT_STATUS_OK
;
4176 /****************************************************************************
4177 Deal with setting the size from any of the setfilepathinfo functions.
4178 ****************************************************************************/
4180 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4183 SMB_STRUCT_STAT
*psbuf
,
4186 NTSTATUS status
= NT_STATUS_OK
;
4187 files_struct
*new_fsp
= NULL
;
4189 if (!VALID_STAT(*psbuf
)) {
4190 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4193 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
4195 if (size
== get_file_size(*psbuf
)) {
4196 return NT_STATUS_OK
;
4199 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4200 fname
, (double)size
));
4202 if (fsp
&& fsp
->fh
->fd
!= -1) {
4203 /* Handle based call. */
4204 if (vfs_set_filelen(fsp
, size
) == -1) {
4205 return map_nt_error_from_unix(errno
);
4207 return NT_STATUS_OK
;
4210 status
= open_file_ntcreate(conn
, fname
, psbuf
,
4212 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
4215 FILE_ATTRIBUTE_NORMAL
,
4216 FORCE_OPLOCK_BREAK_TO_NONE
,
4219 if (!NT_STATUS_IS_OK(status
)) {
4220 /* NB. We check for open_was_deferred in the caller. */
4224 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4225 status
= map_nt_error_from_unix(errno
);
4226 close_file(new_fsp
,NORMAL_CLOSE
);
4230 close_file(new_fsp
,NORMAL_CLOSE
);
4231 return NT_STATUS_OK
;
4234 /****************************************************************************
4235 Deal with SMB_INFO_SET_EA.
4236 ****************************************************************************/
4238 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4244 struct ea_list
*ea_list
= NULL
;
4245 TALLOC_CTX
*ctx
= NULL
;
4246 NTSTATUS status
= NT_STATUS_OK
;
4248 if (total_data
< 10) {
4250 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4251 length. They seem to have no effect. Bug #3212. JRA */
4253 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4254 /* We're done. We only get EA info in this call. */
4255 return NT_STATUS_OK
;
4258 return NT_STATUS_INVALID_PARAMETER
;
4261 if (IVAL(pdata
,0) > total_data
) {
4262 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4263 IVAL(pdata
,0), (unsigned int)total_data
));
4264 return NT_STATUS_INVALID_PARAMETER
;
4267 ctx
= talloc_init("SMB_INFO_SET_EA");
4269 return NT_STATUS_NO_MEMORY
;
4271 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4273 talloc_destroy(ctx
);
4274 return NT_STATUS_INVALID_PARAMETER
;
4276 status
= set_ea(conn
, fsp
, fname
, ea_list
);
4277 talloc_destroy(ctx
);
4282 /****************************************************************************
4283 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4284 ****************************************************************************/
4286 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4291 SMB_STRUCT_STAT
*psbuf
)
4293 NTSTATUS status
= NT_STATUS_OK
;
4294 BOOL delete_on_close
;
4297 if (total_data
< 1) {
4298 return NT_STATUS_INVALID_PARAMETER
;
4302 return NT_STATUS_INVALID_HANDLE
;
4305 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4306 dosmode
= dos_mode(conn
, fname
, psbuf
);
4308 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4309 "delete_on_close = %u\n",
4311 (unsigned int)dosmode
,
4312 (unsigned int)delete_on_close
));
4314 status
= can_set_delete_on_close(fsp
, delete_on_close
, dosmode
);
4316 if (!NT_STATUS_IS_OK(status
)) {
4320 /* The set is across all open files on this dev/inode pair. */
4321 if (!set_delete_on_close(fsp
, delete_on_close
, ¤t_user
.ut
)) {
4322 return NT_STATUS_ACCESS_DENIED
;
4324 return NT_STATUS_OK
;
4327 /****************************************************************************
4328 Deal with SMB_FILE_POSITION_INFORMATION.
4329 ****************************************************************************/
4331 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4336 SMB_BIG_UINT position_information
;
4338 if (total_data
< 8) {
4339 return NT_STATUS_INVALID_PARAMETER
;
4343 /* Ignore on pathname based set. */
4344 return NT_STATUS_OK
;
4347 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
4348 #ifdef LARGE_SMB_OFF_T
4349 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
4350 #else /* LARGE_SMB_OFF_T */
4351 if (IVAL(pdata
,4) != 0) {
4352 /* more than 32 bits? */
4353 return NT_STATUS_INVALID_PARAMETER
;
4355 #endif /* LARGE_SMB_OFF_T */
4357 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4358 fsp
->fsp_name
, (double)position_information
));
4359 fsp
->fh
->position_information
= position_information
;
4360 return NT_STATUS_OK
;
4363 /****************************************************************************
4364 Deal with SMB_FILE_MODE_INFORMATION.
4365 ****************************************************************************/
4367 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4373 if (total_data
< 4) {
4374 return NT_STATUS_INVALID_PARAMETER
;
4376 mode
= IVAL(pdata
,0);
4377 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4378 return NT_STATUS_INVALID_PARAMETER
;
4380 return NT_STATUS_OK
;
4383 /****************************************************************************
4384 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4385 ****************************************************************************/
4387 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
4393 pstring link_target
;
4394 const char *newname
= fname
;
4395 NTSTATUS status
= NT_STATUS_OK
;
4397 /* Set a symbolic link. */
4398 /* Don't allow this if follow links is false. */
4400 if (total_data
== 0) {
4401 return NT_STATUS_INVALID_PARAMETER
;
4404 if (!lp_symlinks(SNUM(conn
))) {
4405 return NT_STATUS_ACCESS_DENIED
;
4408 srvstr_pull(inbuf
, link_target
, pdata
, sizeof(link_target
), total_data
, STR_TERMINATE
);
4410 /* !widelinks forces the target path to be within the share. */
4411 /* This means we can interpret the target as a pathname. */
4412 if (!lp_widelinks(SNUM(conn
))) {
4414 char *last_dirp
= NULL
;
4416 if (*link_target
== '/') {
4417 /* No absolute paths allowed. */
4418 return NT_STATUS_ACCESS_DENIED
;
4420 pstrcpy(rel_name
, newname
);
4421 last_dirp
= strrchr_m(rel_name
, '/');
4423 last_dirp
[1] = '\0';
4425 pstrcpy(rel_name
, "./");
4427 pstrcat(rel_name
, link_target
);
4429 status
= check_name(conn
, rel_name
);
4430 if (!NT_STATUS_IS_OK(status
)) {
4435 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4436 newname
, link_target
));
4438 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
4439 return map_nt_error_from_unix(errno
);
4442 return NT_STATUS_OK
;
4445 /****************************************************************************
4446 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4447 ****************************************************************************/
4449 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
4457 NTSTATUS status
= NT_STATUS_OK
;
4459 /* Set a hard link. */
4460 if (total_data
== 0) {
4461 return NT_STATUS_INVALID_PARAMETER
;
4464 srvstr_get_path(inbuf
, oldname
, pdata
, sizeof(oldname
), total_data
, STR_TERMINATE
, &status
);
4465 if (!NT_STATUS_IS_OK(status
)) {
4469 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, oldname
);
4470 if (!NT_STATUS_IS_OK(status
)) {
4474 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4477 return hardlink_internals(conn
, oldname
, fname
);
4480 /****************************************************************************
4481 Deal with SMB_FILE_RENAME_INFORMATION.
4482 ****************************************************************************/
4484 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4493 /* uint32 root_fid; */ /* Not used */
4497 BOOL dest_has_wcard
= False
;
4498 NTSTATUS status
= NT_STATUS_OK
;
4501 if (total_data
< 13) {
4502 return NT_STATUS_INVALID_PARAMETER
;
4505 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4506 /* root_fid = IVAL(pdata,4); */
4507 len
= IVAL(pdata
,8);
4509 if (len
> (total_data
- 12) || (len
== 0)) {
4510 return NT_STATUS_INVALID_PARAMETER
;
4513 srvstr_get_path_wcard(inbuf
, newname
, &pdata
[12], sizeof(newname
), len
, 0, &status
, &dest_has_wcard
);
4514 if (!NT_STATUS_IS_OK(status
)) {
4518 status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, newname
, &dest_has_wcard
);
4519 if (!NT_STATUS_IS_OK(status
)) {
4523 /* Check the new name has no '/' characters. */
4524 if (strchr_m(newname
, '/')) {
4525 return NT_STATUS_NOT_SUPPORTED
;
4528 /* Create the base directory. */
4529 pstrcpy(base_name
, fname
);
4530 p
= strrchr_m(base_name
, '/');
4534 /* Append the new name. */
4535 pstrcat(base_name
, "/");
4536 pstrcat(base_name
, newname
);
4539 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4540 fsp
->fnum
, fsp
->fsp_name
, base_name
));
4541 status
= rename_internals_fsp(conn
, fsp
, base_name
, 0, overwrite
);
4543 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4545 status
= rename_internals(conn
, fname
, base_name
, 0, overwrite
, False
, dest_has_wcard
);
4551 /****************************************************************************
4552 Deal with SMB_SET_POSIX_ACL.
4553 ****************************************************************************/
4555 #if defined(HAVE_POSIX_ACLS)
4556 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
4561 SMB_STRUCT_STAT
*psbuf
)
4563 uint16 posix_acl_version
;
4564 uint16 num_file_acls
;
4565 uint16 num_def_acls
;
4566 BOOL valid_file_acls
= True
;
4567 BOOL valid_def_acls
= True
;
4569 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
4570 return NT_STATUS_INVALID_PARAMETER
;
4572 posix_acl_version
= SVAL(pdata
,0);
4573 num_file_acls
= SVAL(pdata
,2);
4574 num_def_acls
= SVAL(pdata
,4);
4576 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4577 valid_file_acls
= False
;
4581 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
4582 valid_def_acls
= False
;
4586 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
4587 return NT_STATUS_INVALID_PARAMETER
;
4590 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
4591 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
4592 return NT_STATUS_INVALID_PARAMETER
;
4595 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4596 fname
? fname
: fsp
->fsp_name
,
4597 (unsigned int)num_file_acls
,
4598 (unsigned int)num_def_acls
));
4600 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
, fname
, num_file_acls
,
4601 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
4602 return map_nt_error_from_unix(errno
);
4605 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
, fname
, psbuf
, num_def_acls
,
4606 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
4607 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
4608 return map_nt_error_from_unix(errno
);
4610 return NT_STATUS_OK
;
4614 /****************************************************************************
4615 Deal with SMB_SET_POSIX_LOCK.
4616 ****************************************************************************/
4618 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
4626 SMB_BIG_UINT offset
;
4628 BOOL blocking_lock
= False
;
4629 enum brl_type lock_type
;
4630 NTSTATUS status
= NT_STATUS_OK
;
4632 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
4633 return NT_STATUS_INVALID_HANDLE
;
4636 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
4637 return NT_STATUS_INVALID_PARAMETER
;
4640 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4641 case POSIX_LOCK_TYPE_READ
:
4642 lock_type
= READ_LOCK
;
4644 case POSIX_LOCK_TYPE_WRITE
:
4645 /* Return the right POSIX-mappable error code for files opened read-only. */
4646 if (!fsp
->can_write
) {
4647 return NT_STATUS_INVALID_HANDLE
;
4649 lock_type
= WRITE_LOCK
;
4651 case POSIX_LOCK_TYPE_UNLOCK
:
4652 lock_type
= UNLOCK_LOCK
;
4655 return NT_STATUS_INVALID_PARAMETER
;
4658 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
4659 blocking_lock
= False
;
4660 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
4661 blocking_lock
= True
;
4663 return NT_STATUS_INVALID_PARAMETER
;
4666 if (!lp_blocking_locks(SNUM(conn
))) {
4667 blocking_lock
= False
;
4670 lock_pid
= IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4671 #if defined(HAVE_LONGLONG)
4672 offset
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
4673 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
4674 count
= (((SMB_BIG_UINT
) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
4675 ((SMB_BIG_UINT
) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
4676 #else /* HAVE_LONGLONG */
4677 offset
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4678 count
= (SMB_BIG_UINT
)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4679 #endif /* HAVE_LONGLONG */
4681 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4682 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4684 (unsigned int)lock_type
,
4685 (unsigned int)lock_pid
,
4689 if (lock_type
== UNLOCK_LOCK
) {
4690 status
= do_unlock(fsp
,
4696 struct byte_range_lock
*br_lck
= do_lock(fsp
,
4705 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
4707 * A blocking lock was requested. Package up
4708 * this smb into a queued request and push it
4709 * onto the blocking lock queue.
4711 if(push_blocking_lock_request(br_lck
,
4714 -1, /* infinite timeout. */
4721 TALLOC_FREE(br_lck
);
4725 TALLOC_FREE(br_lck
);
4731 /****************************************************************************
4732 Deal with SMB_INFO_STANDARD.
4733 ****************************************************************************/
4735 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4740 const SMB_STRUCT_STAT
*psbuf
)
4742 struct timespec ts
[2];
4744 if (total_data
< 12) {
4745 return NT_STATUS_INVALID_PARAMETER
;
4749 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastAccess
));
4751 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata
+l1_fdateLastWrite
));
4753 DEBUG(10,("smb_set_info_standard: file %s\n",
4754 fname
? fname
: fsp
->fsp_name
));
4756 return smb_set_file_time(conn
,
4763 /****************************************************************************
4764 Deal with SMB_SET_FILE_BASIC_INFO.
4765 ****************************************************************************/
4767 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4772 SMB_STRUCT_STAT
*psbuf
)
4774 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4775 struct timespec write_time
;
4776 struct timespec changed_time
;
4778 struct timespec ts
[2];
4779 NTSTATUS status
= NT_STATUS_OK
;
4781 if (total_data
< 36) {
4782 return NT_STATUS_INVALID_PARAMETER
;
4785 /* Set the attributes */
4786 dosmode
= IVAL(pdata
,32);
4787 status
= smb_set_file_dosmode(conn
,
4791 if (!NT_STATUS_IS_OK(status
)) {
4795 /* Ignore create time at offset pdata. */
4798 ts
[0] = interpret_long_date(pdata
+8);
4800 write_time
= interpret_long_date(pdata
+16);
4801 changed_time
= interpret_long_date(pdata
+24);
4804 ts
[1] = timespec_min(&write_time
, &changed_time
);
4806 if ((timespec_compare(&write_time
, &ts
[1]) == 1) && !null_timespec(write_time
)) {
4810 /* Prefer a defined time to an undefined one. */
4811 if (null_timespec(ts
[1])) {
4812 ts
[1] = null_timespec(write_time
) ? changed_time
: write_time
;
4815 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4816 fname
? fname
: fsp
->fsp_name
));
4818 return smb_set_file_time(conn
,
4825 /****************************************************************************
4826 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4827 ****************************************************************************/
4829 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4834 SMB_STRUCT_STAT
*psbuf
)
4836 SMB_BIG_UINT allocation_size
= 0;
4837 NTSTATUS status
= NT_STATUS_OK
;
4838 files_struct
*new_fsp
= NULL
;
4840 if (!VALID_STAT(*psbuf
)) {
4841 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4844 if (total_data
< 8) {
4845 return NT_STATUS_INVALID_PARAMETER
;
4848 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
4849 #ifdef LARGE_SMB_OFF_T
4850 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
4851 #else /* LARGE_SMB_OFF_T */
4852 if (IVAL(pdata
,4) != 0) {
4853 /* more than 32 bits? */
4854 return NT_STATUS_INVALID_PARAMETER
;
4856 #endif /* LARGE_SMB_OFF_T */
4858 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4859 fname
, (double)allocation_size
));
4861 if (allocation_size
) {
4862 allocation_size
= smb_roundup(conn
, allocation_size
);
4865 if(allocation_size
== get_file_size(*psbuf
)) {
4866 return NT_STATUS_OK
;
4869 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4870 fname
, (double)allocation_size
));
4872 if (fsp
&& fsp
->fh
->fd
!= -1) {
4873 /* Open file handle. */
4874 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
4875 return map_nt_error_from_unix(errno
);
4877 return NT_STATUS_OK
;
4880 /* Pathname or stat or directory file. */
4882 status
= open_file_ntcreate(conn
, fname
, psbuf
,
4884 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
4887 FILE_ATTRIBUTE_NORMAL
,
4888 FORCE_OPLOCK_BREAK_TO_NONE
,
4891 if (!NT_STATUS_IS_OK(status
)) {
4892 /* NB. We check for open_was_deferred in the caller. */
4895 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
4896 status
= map_nt_error_from_unix(errno
);
4897 close_file(new_fsp
,NORMAL_CLOSE
);
4901 close_file(new_fsp
,NORMAL_CLOSE
);
4902 return NT_STATUS_OK
;
4905 /****************************************************************************
4906 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4907 ****************************************************************************/
4909 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
4914 SMB_STRUCT_STAT
*psbuf
)
4918 if (total_data
< 8) {
4919 return NT_STATUS_INVALID_PARAMETER
;
4922 size
= IVAL(pdata
,0);
4923 #ifdef LARGE_SMB_OFF_T
4924 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
4925 #else /* LARGE_SMB_OFF_T */
4926 if (IVAL(pdata
,4) != 0) {
4927 /* more than 32 bits? */
4928 return NT_STATUS_INVALID_PARAMETER
;
4930 #endif /* LARGE_SMB_OFF_T */
4931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4932 "file %s to %.0f\n", fname
, (double)size
));
4934 return smb_set_file_size(conn
,
4941 /****************************************************************************
4942 Allow a UNIX info mknod.
4943 ****************************************************************************/
4945 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
4949 SMB_STRUCT_STAT
*psbuf
)
4951 uint32 file_type
= IVAL(pdata
,56);
4952 #if defined(HAVE_MAKEDEV)
4953 uint32 dev_major
= IVAL(pdata
,60);
4954 uint32 dev_minor
= IVAL(pdata
,68);
4956 SMB_DEV_T dev
= (SMB_DEV_T
)0;
4957 uint32 raw_unixmode
= IVAL(pdata
,84);
4961 if (total_data
< 100) {
4962 return NT_STATUS_INVALID_PARAMETER
;
4965 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_FILE
, &unixmode
);
4966 if (!NT_STATUS_IS_OK(status
)) {
4970 #if defined(HAVE_MAKEDEV)
4971 dev
= makedev(dev_major
, dev_minor
);
4974 switch (file_type
) {
4975 #if defined(S_IFIFO)
4976 case UNIX_TYPE_FIFO
:
4977 unixmode
|= S_IFIFO
;
4980 #if defined(S_IFSOCK)
4981 case UNIX_TYPE_SOCKET
:
4982 unixmode
|= S_IFSOCK
;
4985 #if defined(S_IFCHR)
4986 case UNIX_TYPE_CHARDEV
:
4987 unixmode
|= S_IFCHR
;
4990 #if defined(S_IFBLK)
4991 case UNIX_TYPE_BLKDEV
:
4992 unixmode
|= S_IFBLK
;
4996 return NT_STATUS_INVALID_PARAMETER
;
4999 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5000 0%o for file %s\n", (double)dev
, (unsigned int)unixmode
, fname
));
5002 /* Ok - do the mknod. */
5003 if (SMB_VFS_MKNOD(conn
, fname
, unixmode
, dev
) != 0) {
5004 return map_nt_error_from_unix(errno
);
5007 /* If any of the other "set" calls fail we
5008 * don't want to end up with a half-constructed mknod.
5011 if (lp_inherit_perms(SNUM(conn
))) {
5013 conn
, parent_dirname(fname
),
5017 if (SMB_VFS_STAT(conn
, fname
, psbuf
) != 0) {
5018 status
= map_nt_error_from_unix(errno
);
5019 SMB_VFS_UNLINK(conn
,fname
);
5022 return NT_STATUS_OK
;
5025 /****************************************************************************
5026 Deal with SMB_SET_FILE_UNIX_BASIC.
5027 ****************************************************************************/
5029 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5034 SMB_STRUCT_STAT
*psbuf
)
5036 struct timespec ts
[2];
5037 uint32 raw_unixmode
;
5040 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5041 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5042 NTSTATUS status
= NT_STATUS_OK
;
5043 BOOL delete_on_fail
= False
;
5044 enum perm_type ptype
;
5046 if (total_data
< 100) {
5047 return NT_STATUS_INVALID_PARAMETER
;
5050 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5051 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5052 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5053 #ifdef LARGE_SMB_OFF_T
5054 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
5055 #else /* LARGE_SMB_OFF_T */
5056 if (IVAL(pdata
,4) != 0) {
5057 /* more than 32 bits? */
5058 return NT_STATUS_INVALID_PARAMETER
;
5060 #endif /* LARGE_SMB_OFF_T */
5063 ts
[0] = interpret_long_date(pdata
+24); /* access_time */
5064 ts
[1] = interpret_long_date(pdata
+32); /* modification_time */
5065 set_owner
= (uid_t
)IVAL(pdata
,40);
5066 set_grp
= (gid_t
)IVAL(pdata
,48);
5067 raw_unixmode
= IVAL(pdata
,84);
5069 if (VALID_STAT(*psbuf
)) {
5070 if (S_ISDIR(psbuf
->st_mode
)) {
5071 ptype
= PERM_EXISTING_DIR
;
5073 ptype
= PERM_EXISTING_FILE
;
5076 ptype
= PERM_NEW_FILE
;
5079 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, ptype
, &unixmode
);
5080 if (!NT_STATUS_IS_OK(status
)) {
5084 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5085 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5086 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
5088 if (!VALID_STAT(*psbuf
)) {
5090 * The only valid use of this is to create character and block
5091 * devices, and named pipes. This is deprecated (IMHO) and
5092 * a new info level should be used for mknod. JRA.
5095 status
= smb_unix_mknod(conn
,
5100 if (!NT_STATUS_IS_OK(status
)) {
5104 /* Ensure we don't try and change anything else. */
5105 raw_unixmode
= SMB_MODE_NO_CHANGE
;
5106 size
= get_file_size(*psbuf
);
5107 ts
[0] = get_atimespec(psbuf
);
5108 ts
[1] = get_mtimespec(psbuf
);
5110 * We continue here as we might want to change the
5113 delete_on_fail
= True
;
5117 /* Horrible backwards compatibility hack as an old server bug
5118 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5122 size
= get_file_size(*psbuf
);
5127 * Deal with the UNIX specific mode set.
5130 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5131 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5132 (unsigned int)unixmode
, fname
));
5133 if (SMB_VFS_CHMOD(conn
, fname
, unixmode
) != 0) {
5134 return map_nt_error_from_unix(errno
);
5139 * Deal with the UNIX specific uid set.
5142 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (psbuf
->st_uid
!= set_owner
)) {
5143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5144 (unsigned int)set_owner
, fname
));
5145 if (SMB_VFS_CHOWN(conn
, fname
, set_owner
, (gid_t
)-1) != 0) {
5146 status
= map_nt_error_from_unix(errno
);
5147 if (delete_on_fail
) {
5148 SMB_VFS_UNLINK(conn
,fname
);
5155 * Deal with the UNIX specific gid set.
5158 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (psbuf
->st_gid
!= set_grp
)) {
5159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5160 (unsigned int)set_owner
, fname
));
5161 if (SMB_VFS_CHOWN(conn
, fname
, (uid_t
)-1, set_grp
) != 0) {
5162 status
= map_nt_error_from_unix(errno
);
5163 if (delete_on_fail
) {
5164 SMB_VFS_UNLINK(conn
,fname
);
5170 /* Deal with any size changes. */
5172 status
= smb_set_file_size(conn
,
5177 if (!NT_STATUS_IS_OK(status
)) {
5181 /* Deal with any time changes. */
5183 return smb_set_file_time(conn
,
5190 /****************************************************************************
5191 Deal with SMB_SET_FILE_UNIX_INFO2.
5192 ****************************************************************************/
5194 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
5199 SMB_STRUCT_STAT
*psbuf
)
5205 if (total_data
< 116) {
5206 return NT_STATUS_INVALID_PARAMETER
;
5209 /* Start by setting all the fields that are common between UNIX_BASIC
5212 status
= smb_set_file_unix_basic(conn
, pdata
, total_data
,
5214 if (!NT_STATUS_IS_OK(status
)) {
5218 smb_fflags
= IVAL(pdata
, 108);
5219 smb_fmask
= IVAL(pdata
, 112);
5221 /* NB: We should only attempt to alter the file flags if the client
5222 * sends a non-zero mask.
5224 if (smb_fmask
!= 0) {
5225 int stat_fflags
= 0;
5227 if (!map_info2_flags_to_sbuf(psbuf
, smb_fflags
, smb_fmask
,
5229 /* Client asked to alter a flag we don't understand. */
5230 return NT_STATUS_INVALID_PARAMETER
;
5233 if (fsp
&& fsp
->fh
->fd
!= -1) {
5234 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5235 return NT_STATUS_NOT_SUPPORTED
;
5237 if (SMB_VFS_CHFLAGS(conn
, fname
, stat_fflags
) != 0) {
5238 return map_nt_error_from_unix(errno
);
5243 /* XXX: need to add support for changing the create_time here. You
5244 * can do this for paths on Darwin with setattrlist(2). The right way
5245 * to hook this up is probably by extending the VFS utimes interface.
5248 return NT_STATUS_OK
;
5251 /****************************************************************************
5252 Create a directory with POSIX semantics.
5253 ****************************************************************************/
5255 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
5259 SMB_STRUCT_STAT
*psbuf
,
5260 int *pdata_return_size
)
5262 NTSTATUS status
= NT_STATUS_OK
;
5263 uint32 raw_unixmode
= 0;
5264 uint32 mod_unixmode
= 0;
5265 mode_t unixmode
= (mode_t
)0;
5266 files_struct
*fsp
= NULL
;
5267 uint16 info_level_return
= 0;
5269 char *pdata
= *ppdata
;
5271 if (total_data
< 18) {
5272 return NT_STATUS_INVALID_PARAMETER
;
5275 raw_unixmode
= IVAL(pdata
,8);
5276 /* Next 4 bytes are not yet defined. */
5278 status
= unix_perms_from_wire(conn
, psbuf
, raw_unixmode
, PERM_NEW_DIR
, &unixmode
);
5279 if (!NT_STATUS_IS_OK(status
)) {
5283 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
5285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5286 fname
, (unsigned int)unixmode
));
5288 status
= open_directory(conn
,
5291 FILE_READ_ATTRIBUTES
, /* Just a stat open */
5292 FILE_SHARE_NONE
, /* Ignored for stat opens */
5299 if (NT_STATUS_IS_OK(status
)) {
5300 close_file(fsp
, NORMAL_CLOSE
);
5303 info_level_return
= SVAL(pdata
,16);
5305 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
5306 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
5307 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
5308 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
5310 *pdata_return_size
= 12;
5313 /* Realloc the data size */
5314 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
5315 if (*ppdata
== NULL
) {
5316 *pdata_return_size
= 0;
5317 return NT_STATUS_NO_MEMORY
;
5320 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
5321 SSVAL(pdata
,2,0); /* No fnum. */
5322 SIVAL(pdata
,4,info
); /* Was directory created. */
5324 switch (info_level_return
) {
5325 case SMB_QUERY_FILE_UNIX_BASIC
:
5326 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
5327 SSVAL(pdata
,10,0); /* Padding. */
5328 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
5329 case SMB_QUERY_FILE_UNIX_INFO2
:
5330 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
5331 SSVAL(pdata
,10,0); /* Padding. */
5332 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
5334 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
5335 SSVAL(pdata
,10,0); /* Padding. */
5341 /****************************************************************************
5342 Open/Create a file with POSIX semantics.
5343 ****************************************************************************/
5345 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
5349 SMB_STRUCT_STAT
*psbuf
,
5350 int *pdata_return_size
)
5352 BOOL extended_oplock_granted
= False
;
5353 char *pdata
= *ppdata
;
5355 uint32 wire_open_mode
= 0;
5356 uint32 raw_unixmode
= 0;
5357 uint32 mod_unixmode
= 0;
5358 uint32 create_disp
= 0;
5359 uint32 access_mask
= 0;
5360 uint32 create_options
= 0;
5361 NTSTATUS status
= NT_STATUS_OK
;
5362 mode_t unixmode
= (mode_t
)0;
5363 files_struct
*fsp
= NULL
;
5364 int oplock_request
= 0;
5366 uint16 info_level_return
= 0;
5368 if (total_data
< 18) {
5369 return NT_STATUS_INVALID_PARAMETER
;
5372 flags
= IVAL(pdata
,0);
5373 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
5374 if (oplock_request
) {
5375 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
5378 wire_open_mode
= IVAL(pdata
,4);
5380 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
5381 return smb_posix_mkdir(conn
,
5389 switch (wire_open_mode
& SMB_ACCMODE
) {
5391 access_mask
= FILE_READ_DATA
;
5394 access_mask
= FILE_WRITE_DATA
;
5397 access_mask
= FILE_READ_DATA
|FILE_WRITE_DATA
;
5400 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5401 (unsigned int)wire_open_mode
));
5402 return NT_STATUS_INVALID_PARAMETER
;
5405 wire_open_mode
&= ~SMB_ACCMODE
;
5407 if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) == (SMB_O_CREAT
| SMB_O_EXCL
)) {
5408 create_disp
= FILE_CREATE
;
5409 } else if((wire_open_mode
& (SMB_O_CREAT
| SMB_O_TRUNC
)) == (SMB_O_CREAT
| SMB_O_TRUNC
)) {
5410 create_disp
= FILE_OVERWRITE_IF
;
5411 } else if((wire_open_mode
& SMB_O_CREAT
) == SMB_O_CREAT
) {
5412 create_disp
= FILE_OPEN_IF
;
5414 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5415 (unsigned int)wire_open_mode
));
5416 return NT_STATUS_INVALID_PARAMETER
;
5419 raw_unixmode
= IVAL(pdata
,8);
5420 /* Next 4 bytes are not yet defined. */
5422 status
= unix_perms_from_wire(conn
,
5425 VALID_STAT(*psbuf
) ? PERM_EXISTING_FILE
: PERM_NEW_FILE
,
5428 if (!NT_STATUS_IS_OK(status
)) {
5432 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
5434 if (wire_open_mode
& SMB_O_SYNC
) {
5435 create_options
|= FILE_WRITE_THROUGH
;
5437 if (wire_open_mode
& SMB_O_APPEND
) {
5438 access_mask
|= FILE_APPEND_DATA
;
5440 if (wire_open_mode
& SMB_O_DIRECT
) {
5441 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
5444 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5446 (unsigned int)wire_open_mode
,
5447 (unsigned int)unixmode
));
5449 status
= open_file_ntcreate(conn
,
5453 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5455 0, /* no create options yet. */
5461 if (!NT_STATUS_IS_OK(status
)) {
5465 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
5466 extended_oplock_granted
= True
;
5469 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
5470 extended_oplock_granted
= True
;
5473 info_level_return
= SVAL(pdata
,16);
5475 /* Allocate the correct return size. */
5477 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
5478 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
5479 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
5480 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
5482 *pdata_return_size
= 12;
5485 /* Realloc the data size */
5486 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
5487 if (*ppdata
== NULL
) {
5488 close_file(fsp
,ERROR_CLOSE
);
5489 *pdata_return_size
= 0;
5490 return NT_STATUS_NO_MEMORY
;
5493 if (extended_oplock_granted
) {
5494 if (flags
& REQUEST_BATCH_OPLOCK
) {
5495 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
5497 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
5499 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
5500 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
5502 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
5505 SSVAL(pdata
,2,fsp
->fnum
);
5506 SIVAL(pdata
,4,info
); /* Was file created etc. */
5508 switch (info_level_return
) {
5509 case SMB_QUERY_FILE_UNIX_BASIC
:
5510 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
5511 SSVAL(pdata
,10,0); /* padding. */
5512 store_file_unix_basic(conn
, pdata
+ 12, fsp
, psbuf
);
5513 case SMB_QUERY_FILE_UNIX_INFO2
:
5514 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
5515 SSVAL(pdata
,10,0); /* padding. */
5516 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
, psbuf
);
5518 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
5519 SSVAL(pdata
,10,0); /* padding. */
5521 return NT_STATUS_OK
;
5524 /****************************************************************************
5525 Delete a file with POSIX semantics.
5526 ****************************************************************************/
5528 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
5532 SMB_STRUCT_STAT
*psbuf
)
5534 NTSTATUS status
= NT_STATUS_OK
;
5535 files_struct
*fsp
= NULL
;
5539 if (total_data
< 2) {
5540 return NT_STATUS_INVALID_PARAMETER
;
5543 flags
= SVAL(pdata
,0);
5545 if (!VALID_STAT(*psbuf
)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5549 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
5550 !VALID_STAT_OF_DIR(*psbuf
)) {
5551 return NT_STATUS_NOT_A_DIRECTORY
;
5554 DEBUG(10,("smb_posix_unlink: %s %s\n",
5555 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
5558 if (VALID_STAT_OF_DIR(*psbuf
)) {
5559 status
= open_directory(conn
,
5563 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5565 FILE_DELETE_ON_CLOSE
,
5566 FILE_FLAG_POSIX_SEMANTICS
|0777,
5572 status
= open_file_ntcreate(conn
,
5576 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5579 FILE_FLAG_POSIX_SEMANTICS
|0777,
5580 0, /* No oplock, but break existing ones. */
5584 * For file opens we must set the delete on close
5588 if (!NT_STATUS_IS_OK(status
)) {
5592 status
= smb_set_file_disposition_info(conn
,
5600 if (!NT_STATUS_IS_OK(status
)) {
5603 return close_file(fsp
, NORMAL_CLOSE
);
5606 /****************************************************************************
5607 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5608 ****************************************************************************/
5610 static int call_trans2setfilepathinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
5611 unsigned int tran_call
,
5612 char **pparams
, int total_params
, char **ppdata
, int total_data
,
5613 unsigned int max_data_bytes
)
5615 char *params
= *pparams
;
5616 char *pdata
= *ppdata
;
5618 SMB_STRUCT_STAT sbuf
;
5620 files_struct
*fsp
= NULL
;
5621 NTSTATUS status
= NT_STATUS_OK
;
5622 int data_return_size
= 0;
5625 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
5630 if (tran_call
== TRANSACT2_SETFILEINFO
) {
5631 if (total_params
< 4) {
5632 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
5635 fsp
= file_fsp(params
,0);
5636 info_level
= SVAL(params
,2);
5638 if(fsp
&& (fsp
->is_directory
|| fsp
->fh
->fd
== -1)) {
5640 * This is actually a SETFILEINFO on a directory
5641 * handle (returned from an NT SMB). NT5.0 seems
5642 * to do this call. JRA.
5644 pstrcpy(fname
, fsp
->fsp_name
);
5645 if (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0) {
5646 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
5647 return UNIXERROR(ERRDOS
,ERRbadpath
);
5649 } else if (fsp
&& fsp
->print_file
) {
5651 * Doing a DELETE_ON_CLOSE should cancel a print job.
5653 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
5654 fsp
->fh
->private_options
|= FILE_DELETE_ON_CLOSE
;
5656 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
5659 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0, max_data_bytes
);
5662 return (UNIXERROR(ERRDOS
,ERRbadpath
));
5665 * Original code - this is an open file.
5667 CHECK_FSP(fsp
,conn
);
5669 pstrcpy(fname
, fsp
->fsp_name
);
5671 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &sbuf
) != 0) {
5672 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
5673 return(UNIXERROR(ERRDOS
,ERRbadfid
));
5678 if (total_params
< 7) {
5679 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
5682 info_level
= SVAL(params
,0);
5683 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), total_params
- 6, STR_TERMINATE
, &status
);
5684 if (!NT_STATUS_IS_OK(status
)) {
5685 return ERROR_NT(status
);
5688 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
5689 if (!NT_STATUS_IS_OK(status
)) {
5690 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5691 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
5693 return ERROR_NT(status
);
5696 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
5697 if (!NT_STATUS_IS_OK(status
)) {
5698 return ERROR_NT(status
);
5701 status
= check_name(conn
, fname
);
5702 if (!NT_STATUS_IS_OK(status
)) {
5703 return ERROR_NT(status
);
5707 * For CIFS UNIX extensions the target name may not exist.
5710 if(!VALID_STAT(sbuf
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
5711 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname
, strerror(errno
)));
5712 return UNIXERROR(ERRDOS
,ERRbadpath
);
5716 if (!CAN_WRITE(conn
)) {
5717 return ERROR_DOS(ERRSRV
,ERRaccess
);
5720 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5721 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5724 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5725 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
5727 /* Realloc the parameter size */
5728 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5729 if (*pparams
== NULL
) {
5730 return ERROR_NT(NT_STATUS_NO_MEMORY
);
5736 if (fsp
&& !null_timespec(fsp
->pending_modtime
)) {
5737 /* the pending modtime overrides the current modtime */
5738 set_mtimespec(&sbuf
, fsp
->pending_modtime
);
5741 switch (info_level
) {
5743 case SMB_INFO_STANDARD
:
5745 status
= smb_set_info_standard(conn
,
5754 case SMB_INFO_SET_EA
:
5756 status
= smb_info_set_ea(conn
,
5764 case SMB_SET_FILE_BASIC_INFO
:
5765 case SMB_FILE_BASIC_INFORMATION
:
5767 status
= smb_set_file_basic_info(conn
,
5776 case SMB_FILE_ALLOCATION_INFORMATION
:
5777 case SMB_SET_FILE_ALLOCATION_INFO
:
5779 status
= smb_set_file_allocation_info(conn
,
5788 case SMB_FILE_END_OF_FILE_INFORMATION
:
5789 case SMB_SET_FILE_END_OF_FILE_INFO
:
5791 status
= smb_set_file_end_of_file_info(conn
,
5800 case SMB_FILE_DISPOSITION_INFORMATION
:
5801 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5804 /* JRA - We used to just ignore this on a path ?
5805 * Shouldn't this be invalid level on a pathname
5808 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5809 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5812 status
= smb_set_file_disposition_info(conn
,
5821 case SMB_FILE_POSITION_INFORMATION
:
5823 status
= smb_file_position_information(conn
,
5830 /* From tridge Samba4 :
5831 * MODE_INFORMATION in setfileinfo (I have no
5832 * idea what "mode information" on a file is - it takes a value of 0,
5833 * 2, 4 or 6. What could it be?).
5836 case SMB_FILE_MODE_INFORMATION
:
5838 status
= smb_file_mode_information(conn
,
5845 * CIFS UNIX extensions.
5848 case SMB_SET_FILE_UNIX_BASIC
:
5850 status
= smb_set_file_unix_basic(conn
,
5859 case SMB_SET_FILE_UNIX_INFO2
:
5861 status
= smb_set_file_unix_info2(conn
,
5870 case SMB_SET_FILE_UNIX_LINK
:
5872 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
5873 /* We must have a pathname for this. */
5874 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5876 status
= smb_set_file_unix_link(conn
,
5884 case SMB_SET_FILE_UNIX_HLINK
:
5886 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
5887 /* We must have a pathname for this. */
5888 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5890 status
= smb_set_file_unix_hlink(conn
,
5899 case SMB_FILE_RENAME_INFORMATION
:
5901 status
= smb_file_rename_information(conn
,
5911 #if defined(HAVE_POSIX_ACLS)
5912 case SMB_SET_POSIX_ACL
:
5914 status
= smb_set_posix_acl(conn
,
5924 case SMB_SET_POSIX_LOCK
:
5926 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5927 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5929 status
= smb_set_posix_lock(conn
,
5938 case SMB_POSIX_PATH_OPEN
:
5940 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
5941 /* We must have a pathname for this. */
5942 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5945 status
= smb_posix_open(conn
,
5954 case SMB_POSIX_PATH_UNLINK
:
5956 if (tran_call
!= TRANSACT2_SETPATHINFO
) {
5957 /* We must have a pathname for this. */
5958 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5961 status
= smb_posix_unlink(conn
,
5970 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5974 if (!NT_STATUS_IS_OK(status
)) {
5975 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
5976 /* We have re-scheduled this call. */
5979 if (blocking_lock_was_deferred(SVAL(inbuf
,smb_mid
))) {
5980 /* We have re-scheduled this call. */
5983 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5984 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
5986 return ERROR_NT(status
);
5990 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, data_return_size
, max_data_bytes
);
5995 /****************************************************************************
5996 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5997 ****************************************************************************/
5999 static int call_trans2mkdir(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
6000 char **pparams
, int total_params
, char **ppdata
, int total_data
,
6001 unsigned int max_data_bytes
)
6003 char *params
= *pparams
;
6004 char *pdata
= *ppdata
;
6006 SMB_STRUCT_STAT sbuf
;
6007 NTSTATUS status
= NT_STATUS_OK
;
6008 struct ea_list
*ea_list
= NULL
;
6010 if (!CAN_WRITE(conn
))
6011 return ERROR_DOS(ERRSRV
,ERRaccess
);
6013 if (total_params
< 5) {
6014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6017 srvstr_get_path(inbuf
, directory
, ¶ms
[4], sizeof(directory
), total_params
- 4, STR_TERMINATE
, &status
);
6018 if (!NT_STATUS_IS_OK(status
)) {
6019 return ERROR_NT(status
);
6022 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
6024 status
= unix_convert(conn
, directory
, False
, NULL
, &sbuf
);
6025 if (!NT_STATUS_IS_OK(status
)) {
6026 return ERROR_NT(status
);
6029 status
= check_name(conn
, directory
);
6030 if (!NT_STATUS_IS_OK(status
)) {
6031 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status
)));
6032 return ERROR_NT(status
);
6035 /* Any data in this call is an EA list. */
6036 if (total_data
&& (total_data
!= 4) && !lp_ea_support(SNUM(conn
))) {
6037 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED
);
6041 * OS/2 workplace shell seems to send SET_EA requests of "null"
6042 * length (4 bytes containing IVAL 4).
6043 * They seem to have no effect. Bug #3212. JRA.
6046 if (total_data
!= 4) {
6047 if (total_data
< 10) {
6048 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6051 if (IVAL(pdata
,0) > total_data
) {
6052 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6053 IVAL(pdata
,0), (unsigned int)total_data
));
6054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6057 ea_list
= read_ea_list(tmp_talloc_ctx(), pdata
+ 4,
6060 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6062 } else if (IVAL(pdata
,0) != 4) {
6063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6066 status
= create_directory(conn
, directory
);
6068 if (!NT_STATUS_IS_OK(status
)) {
6069 return ERROR_NT(status
);
6072 /* Try and set any given EA. */
6074 status
= set_ea(conn
, NULL
, directory
, ea_list
);
6075 if (!NT_STATUS_IS_OK(status
)) {
6076 return ERROR_NT(status
);
6080 /* Realloc the parameter and data sizes */
6081 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6082 if(*pparams
== NULL
) {
6083 return ERROR_NT(NT_STATUS_NO_MEMORY
);
6089 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0, max_data_bytes
);
6094 /****************************************************************************
6095 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6096 We don't actually do this - we just send a null response.
6097 ****************************************************************************/
6099 static int call_trans2findnotifyfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
6100 char **pparams
, int total_params
, char **ppdata
, int total_data
,
6101 unsigned int max_data_bytes
)
6103 static uint16 fnf_handle
= 257;
6104 char *params
= *pparams
;
6107 if (total_params
< 6) {
6108 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6111 info_level
= SVAL(params
,4);
6112 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
6114 switch (info_level
) {
6119 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6122 /* Realloc the parameter and data sizes */
6123 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
6124 if (*pparams
== NULL
) {
6125 return ERROR_NT(NT_STATUS_NO_MEMORY
);
6129 SSVAL(params
,0,fnf_handle
);
6130 SSVAL(params
,2,0); /* No changes */
6131 SSVAL(params
,4,0); /* No EA errors */
6138 send_trans2_replies(outbuf
, bufsize
, params
, 6, *ppdata
, 0, max_data_bytes
);
6143 /****************************************************************************
6144 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6145 changes). Currently this does nothing.
6146 ****************************************************************************/
6148 static int call_trans2findnotifynext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
6149 char **pparams
, int total_params
, char **ppdata
, int total_data
,
6150 unsigned int max_data_bytes
)
6152 char *params
= *pparams
;
6154 DEBUG(3,("call_trans2findnotifynext\n"));
6156 /* Realloc the parameter and data sizes */
6157 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
6158 if (*pparams
== NULL
) {
6159 return ERROR_NT(NT_STATUS_NO_MEMORY
);
6163 SSVAL(params
,0,0); /* No changes */
6164 SSVAL(params
,2,0); /* No EA errors */
6166 send_trans2_replies(outbuf
, bufsize
, params
, 4, *ppdata
, 0, max_data_bytes
);
6171 /****************************************************************************
6172 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6173 ****************************************************************************/
6175 static int call_trans2getdfsreferral(connection_struct
*conn
, char* inbuf
, char* outbuf
, int length
, int bufsize
,
6176 char **pparams
, int total_params
, char **ppdata
, int total_data
,
6177 unsigned int max_data_bytes
)
6179 char *params
= *pparams
;
6182 int max_referral_level
;
6184 DEBUG(10,("call_trans2getdfsreferral\n"));
6186 if (total_params
< 3) {
6187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6190 max_referral_level
= SVAL(params
,0);
6192 if(!lp_host_msdfs())
6193 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
6195 srvstr_pull(inbuf
, pathname
, ¶ms
[2], sizeof(pathname
), total_params
- 2, STR_TERMINATE
);
6196 if((reply_size
= setup_dfs_referral(conn
, pathname
,max_referral_level
,ppdata
)) < 0)
6197 return UNIXERROR(ERRDOS
,ERRbadfile
);
6199 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
6200 send_trans2_replies(outbuf
,bufsize
,0,0,*ppdata
,reply_size
, max_data_bytes
);
6205 #define LMCAT_SPL 0x53
6206 #define LMFUNC_GETJOBID 0x60
6208 /****************************************************************************
6209 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6210 ****************************************************************************/
6212 static int call_trans2ioctl(connection_struct
*conn
, char* inbuf
, char* outbuf
, int length
, int bufsize
,
6213 char **pparams
, int total_params
, char **ppdata
, int total_data
,
6214 unsigned int max_data_bytes
)
6216 char *pdata
= *ppdata
;
6217 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv15
);
6219 /* check for an invalid fid before proceeding */
6222 return(ERROR_DOS(ERRDOS
,ERRbadfid
));
6224 if ((SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
6225 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
6226 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
6227 if (*ppdata
== NULL
) {
6228 return ERROR_NT(NT_STATUS_NO_MEMORY
);
6232 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6233 CAN ACCEPT THIS IN UNICODE. JRA. */
6235 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
6236 srvstr_push( outbuf
, pdata
+ 2, global_myname(), 15, STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
6237 srvstr_push( outbuf
, pdata
+18, lp_servicename(SNUM(conn
)), 13, STR_ASCII
|STR_TERMINATE
); /* Service name */
6238 send_trans2_replies(outbuf
,bufsize
,*pparams
,0,*ppdata
,32, max_data_bytes
);
6241 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6242 return ERROR_DOS(ERRSRV
,ERRerror
);
6246 /****************************************************************************
6247 Reply to a SMBfindclose (stop trans2 directory search).
6248 ****************************************************************************/
6250 int reply_findclose(connection_struct
*conn
,
6251 char *inbuf
,char *outbuf
,int length
,int bufsize
)
6254 int dptr_num
=SVALS(inbuf
,smb_vwv0
);
6255 START_PROFILE(SMBfindclose
);
6257 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
6259 dptr_close(&dptr_num
);
6261 outsize
= set_message(outbuf
,0,0,False
);
6263 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
6265 END_PROFILE(SMBfindclose
);
6269 /****************************************************************************
6270 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6271 ****************************************************************************/
6273 int reply_findnclose(connection_struct
*conn
,
6274 char *inbuf
,char *outbuf
,int length
,int bufsize
)
6278 START_PROFILE(SMBfindnclose
);
6280 dptr_num
= SVAL(inbuf
,smb_vwv0
);
6282 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
6284 /* We never give out valid handles for a
6285 findnotifyfirst - so any dptr_num is ok here.
6288 outsize
= set_message(outbuf
,0,0,False
);
6290 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
6292 END_PROFILE(SMBfindnclose
);
6296 int handle_trans2(connection_struct
*conn
,
6297 struct trans_state
*state
,
6298 char *inbuf
, char *outbuf
, int size
, int bufsize
)
6302 if (Protocol
>= PROTOCOL_NT1
) {
6303 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | 0x40); /* IS_LONG_NAME */
6306 /* Now we must call the relevant TRANS2 function */
6307 switch(state
->call
) {
6308 case TRANSACT2_OPEN
:
6310 START_PROFILE(Trans2_open
);
6311 outsize
= call_trans2open(
6312 conn
, inbuf
, outbuf
, bufsize
,
6313 &state
->param
, state
->total_param
,
6314 &state
->data
, state
->total_data
,
6315 state
->max_data_return
);
6316 END_PROFILE(Trans2_open
);
6320 case TRANSACT2_FINDFIRST
:
6322 START_PROFILE(Trans2_findfirst
);
6323 outsize
= call_trans2findfirst(
6324 conn
, inbuf
, outbuf
, bufsize
,
6325 &state
->param
, state
->total_param
,
6326 &state
->data
, state
->total_data
,
6327 state
->max_data_return
);
6328 END_PROFILE(Trans2_findfirst
);
6332 case TRANSACT2_FINDNEXT
:
6334 START_PROFILE(Trans2_findnext
);
6335 outsize
= call_trans2findnext(
6336 conn
, inbuf
, outbuf
, size
, bufsize
,
6337 &state
->param
, state
->total_param
,
6338 &state
->data
, state
->total_data
,
6339 state
->max_data_return
);
6340 END_PROFILE(Trans2_findnext
);
6344 case TRANSACT2_QFSINFO
:
6346 START_PROFILE(Trans2_qfsinfo
);
6347 outsize
= call_trans2qfsinfo(
6348 conn
, inbuf
, outbuf
, size
, bufsize
,
6349 &state
->param
, state
->total_param
,
6350 &state
->data
, state
->total_data
,
6351 state
->max_data_return
);
6352 END_PROFILE(Trans2_qfsinfo
);
6356 case TRANSACT2_SETFSINFO
:
6358 START_PROFILE(Trans2_setfsinfo
);
6359 outsize
= call_trans2setfsinfo(
6360 conn
, inbuf
, outbuf
, size
, bufsize
,
6361 &state
->param
, state
->total_param
,
6362 &state
->data
, state
->total_data
,
6363 state
->max_data_return
);
6364 END_PROFILE(Trans2_setfsinfo
);
6368 case TRANSACT2_QPATHINFO
:
6369 case TRANSACT2_QFILEINFO
:
6371 START_PROFILE(Trans2_qpathinfo
);
6372 outsize
= call_trans2qfilepathinfo(
6373 conn
, inbuf
, outbuf
, size
, bufsize
, state
->call
,
6374 &state
->param
, state
->total_param
,
6375 &state
->data
, state
->total_data
,
6376 state
->max_data_return
);
6377 END_PROFILE(Trans2_qpathinfo
);
6381 case TRANSACT2_SETPATHINFO
:
6382 case TRANSACT2_SETFILEINFO
:
6384 START_PROFILE(Trans2_setpathinfo
);
6385 outsize
= call_trans2setfilepathinfo(
6386 conn
, inbuf
, outbuf
, size
, bufsize
, state
->call
,
6387 &state
->param
, state
->total_param
,
6388 &state
->data
, state
->total_data
,
6389 state
->max_data_return
);
6390 END_PROFILE(Trans2_setpathinfo
);
6394 case TRANSACT2_FINDNOTIFYFIRST
:
6396 START_PROFILE(Trans2_findnotifyfirst
);
6397 outsize
= call_trans2findnotifyfirst(
6398 conn
, inbuf
, outbuf
, size
, bufsize
,
6399 &state
->param
, state
->total_param
,
6400 &state
->data
, state
->total_data
,
6401 state
->max_data_return
);
6402 END_PROFILE(Trans2_findnotifyfirst
);
6406 case TRANSACT2_FINDNOTIFYNEXT
:
6408 START_PROFILE(Trans2_findnotifynext
);
6409 outsize
= call_trans2findnotifynext(
6410 conn
, inbuf
, outbuf
, size
, bufsize
,
6411 &state
->param
, state
->total_param
,
6412 &state
->data
, state
->total_data
,
6413 state
->max_data_return
);
6414 END_PROFILE(Trans2_findnotifynext
);
6418 case TRANSACT2_MKDIR
:
6420 START_PROFILE(Trans2_mkdir
);
6421 outsize
= call_trans2mkdir(
6422 conn
, inbuf
, outbuf
, size
, bufsize
,
6423 &state
->param
, state
->total_param
,
6424 &state
->data
, state
->total_data
,
6425 state
->max_data_return
);
6426 END_PROFILE(Trans2_mkdir
);
6430 case TRANSACT2_GET_DFS_REFERRAL
:
6432 START_PROFILE(Trans2_get_dfs_referral
);
6433 outsize
= call_trans2getdfsreferral(
6434 conn
, inbuf
, outbuf
, size
, bufsize
,
6435 &state
->param
, state
->total_param
,
6436 &state
->data
, state
->total_data
,
6437 state
->max_data_return
);
6438 END_PROFILE(Trans2_get_dfs_referral
);
6442 case TRANSACT2_IOCTL
:
6444 START_PROFILE(Trans2_ioctl
);
6445 outsize
= call_trans2ioctl(
6446 conn
, inbuf
, outbuf
, size
, bufsize
,
6447 &state
->param
, state
->total_param
,
6448 &state
->data
, state
->total_data
,
6449 state
->max_data_return
);
6450 END_PROFILE(Trans2_ioctl
);
6455 /* Error in request */
6456 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
6457 outsize
= ERROR_DOS(ERRSRV
,ERRerror
);
6463 /****************************************************************************
6464 Reply to a SMBtrans2.
6465 ****************************************************************************/
6467 int reply_trans2(connection_struct
*conn
, char *inbuf
,char *outbuf
,
6468 int size
, int bufsize
)
6471 unsigned int dsoff
= SVAL(inbuf
, smb_dsoff
);
6472 unsigned int dscnt
= SVAL(inbuf
, smb_dscnt
);
6473 unsigned int psoff
= SVAL(inbuf
, smb_psoff
);
6474 unsigned int pscnt
= SVAL(inbuf
, smb_pscnt
);
6475 unsigned int tran_call
= SVAL(inbuf
, smb_setup0
);
6476 struct trans_state
*state
;
6479 START_PROFILE(SMBtrans2
);
6481 result
= allow_new_trans(conn
->pending_trans
, SVAL(inbuf
, smb_mid
));
6482 if (!NT_STATUS_IS_OK(result
)) {
6483 DEBUG(2, ("Got invalid trans2 request: %s\n",
6484 nt_errstr(result
)));
6485 END_PROFILE(SMBtrans2
);
6486 return ERROR_NT(result
);
6489 if (IS_IPC(conn
) && (tran_call
!= TRANSACT2_OPEN
)
6490 && (tran_call
!= TRANSACT2_GET_DFS_REFERRAL
)) {
6491 END_PROFILE(SMBtrans2
);
6492 return ERROR_DOS(ERRSRV
,ERRaccess
);
6495 if ((state
= TALLOC_P(conn
->mem_ctx
, struct trans_state
)) == NULL
) {
6496 DEBUG(0, ("talloc failed\n"));
6497 END_PROFILE(SMBtrans2
);
6498 return ERROR_NT(NT_STATUS_NO_MEMORY
);
6501 state
->cmd
= SMBtrans2
;
6503 state
->mid
= SVAL(inbuf
, smb_mid
);
6504 state
->vuid
= SVAL(inbuf
, smb_uid
);
6505 state
->setup_count
= SVAL(inbuf
, smb_suwcnt
);
6506 state
->setup
= NULL
;
6507 state
->total_param
= SVAL(inbuf
, smb_tpscnt
);
6508 state
->param
= NULL
;
6509 state
->total_data
= SVAL(inbuf
, smb_tdscnt
);
6511 state
->max_param_return
= SVAL(inbuf
, smb_mprcnt
);
6512 state
->max_data_return
= SVAL(inbuf
, smb_mdrcnt
);
6513 state
->max_setup_return
= SVAL(inbuf
, smb_msrcnt
);
6514 state
->close_on_completion
= BITSETW(inbuf
+smb_vwv5
,0);
6515 state
->one_way
= BITSETW(inbuf
+smb_vwv5
,1);
6517 state
->call
= tran_call
;
6519 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6520 is so as a sanity check */
6521 if (state
->setup_count
!= 1) {
6523 * Need to have rc=0 for ioctl to get job id for OS/2.
6524 * Network printing will fail if function is not successful.
6525 * Similar function in reply.c will be used if protocol
6526 * is LANMAN1.0 instead of LM1.2X002.
6527 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6528 * outbuf doesn't have to be set(only job id is used).
6530 if ( (state
->setup_count
== 4) && (tran_call
== TRANSACT2_IOCTL
) &&
6531 (SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
6532 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
6533 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6535 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
6536 DEBUG(2,("Transaction is %d\n",tran_call
));
6538 END_PROFILE(SMBtrans2
);
6539 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6543 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
6546 if (state
->total_data
) {
6547 /* Can't use talloc here, the core routines do realloc on the
6548 * params and data. */
6549 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
6550 if (state
->data
== NULL
) {
6551 DEBUG(0,("reply_trans2: data malloc fail for %u "
6552 "bytes !\n", (unsigned int)state
->total_data
));
6554 END_PROFILE(SMBtrans2
);
6555 return(ERROR_DOS(ERRDOS
,ERRnomem
));
6557 if ((dsoff
+dscnt
< dsoff
) || (dsoff
+dscnt
< dscnt
))
6559 if ((smb_base(inbuf
)+dsoff
+dscnt
> inbuf
+ size
) ||
6560 (smb_base(inbuf
)+dsoff
+dscnt
< smb_base(inbuf
)))
6563 memcpy(state
->data
,smb_base(inbuf
)+dsoff
,dscnt
);
6566 if (state
->total_param
) {
6567 /* Can't use talloc here, the core routines do realloc on the
6568 * params and data. */
6569 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
6570 if (state
->param
== NULL
) {
6571 DEBUG(0,("reply_trans: param malloc fail for %u "
6572 "bytes !\n", (unsigned int)state
->total_param
));
6573 SAFE_FREE(state
->data
);
6575 END_PROFILE(SMBtrans2
);
6576 return(ERROR_DOS(ERRDOS
,ERRnomem
));
6578 if ((psoff
+pscnt
< psoff
) || (psoff
+pscnt
< pscnt
))
6580 if ((smb_base(inbuf
)+psoff
+pscnt
> inbuf
+ size
) ||
6581 (smb_base(inbuf
)+psoff
+pscnt
< smb_base(inbuf
)))
6584 memcpy(state
->param
,smb_base(inbuf
)+psoff
,pscnt
);
6587 state
->received_data
= dscnt
;
6588 state
->received_param
= pscnt
;
6590 if ((state
->received_param
== state
->total_param
) &&
6591 (state
->received_data
== state
->total_data
)) {
6593 outsize
= handle_trans2(conn
, state
, inbuf
, outbuf
,
6595 SAFE_FREE(state
->data
);
6596 SAFE_FREE(state
->param
);
6598 END_PROFILE(SMBtrans2
);
6602 DLIST_ADD(conn
->pending_trans
, state
);
6604 /* We need to send an interim response then receive the rest
6605 of the parameter/data bytes */
6606 outsize
= set_message(outbuf
,0,0,False
);
6608 END_PROFILE(SMBtrans2
);
6613 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6614 SAFE_FREE(state
->data
);
6615 SAFE_FREE(state
->param
);
6617 END_PROFILE(SMBtrans2
);
6618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6622 /****************************************************************************
6623 Reply to a SMBtranss2
6624 ****************************************************************************/
6626 int reply_transs2(connection_struct
*conn
,
6627 char *inbuf
,char *outbuf
,int size
,int bufsize
)
6630 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
6631 struct trans_state
*state
;
6633 START_PROFILE(SMBtranss2
);
6637 for (state
= conn
->pending_trans
; state
!= NULL
;
6638 state
= state
->next
) {
6639 if (state
->mid
== SVAL(inbuf
,smb_mid
)) {
6644 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
6645 END_PROFILE(SMBtranss2
);
6646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
6649 /* Revise state->total_param and state->total_data in case they have
6650 changed downwards */
6652 if (SVAL(inbuf
, smb_tpscnt
) < state
->total_param
)
6653 state
->total_param
= SVAL(inbuf
, smb_tpscnt
);
6654 if (SVAL(inbuf
, smb_tdscnt
) < state
->total_data
)
6655 state
->total_data
= SVAL(inbuf
, smb_tdscnt
);
6657 pcnt
= SVAL(inbuf
, smb_spscnt
);
6658 poff
= SVAL(inbuf
, smb_spsoff
);
6659 pdisp
= SVAL(inbuf
, smb_spsdisp
);
6661 dcnt
= SVAL(inbuf
, smb_sdscnt
);
6662 doff
= SVAL(inbuf
, smb_sdsoff
);
6663 ddisp
= SVAL(inbuf
, smb_sdsdisp
);
6665 state
->received_param
+= pcnt
;
6666 state
->received_data
+= dcnt
;
6668 if ((state
->received_data
> state
->total_data
) ||
6669 (state
->received_param
> state
->total_param
))
6673 if (pdisp
+pcnt
> state
->total_param
)
6675 if ((pdisp
+pcnt
< pdisp
) || (pdisp
+pcnt
< pcnt
))
6677 if (pdisp
> state
->total_param
)
6679 if ((smb_base(inbuf
) + poff
+ pcnt
> inbuf
+ size
) ||
6680 (smb_base(inbuf
) + poff
+ pcnt
< smb_base(inbuf
)))
6682 if (state
->param
+ pdisp
< state
->param
)
6685 memcpy(state
->param
+pdisp
,smb_base(inbuf
)+poff
,
6690 if (ddisp
+dcnt
> state
->total_data
)
6692 if ((ddisp
+dcnt
< ddisp
) || (ddisp
+dcnt
< dcnt
))
6694 if (ddisp
> state
->total_data
)
6696 if ((smb_base(inbuf
) + doff
+ dcnt
> inbuf
+ size
) ||
6697 (smb_base(inbuf
) + doff
+ dcnt
< smb_base(inbuf
)))
6699 if (state
->data
+ ddisp
< state
->data
)
6702 memcpy(state
->data
+ddisp
, smb_base(inbuf
)+doff
,
6706 if ((state
->received_param
< state
->total_param
) ||
6707 (state
->received_data
< state
->total_data
)) {
6708 END_PROFILE(SMBtranss2
);
6712 /* construct_reply_common has done us the favor to pre-fill the
6713 * command field with SMBtranss2 which is wrong :-)
6715 SCVAL(outbuf
,smb_com
,SMBtrans2
);
6717 outsize
= handle_trans2(conn
, state
, inbuf
, outbuf
, size
, bufsize
);
6719 DLIST_REMOVE(conn
->pending_trans
, state
);
6720 SAFE_FREE(state
->data
);
6721 SAFE_FREE(state
->param
);
6725 END_PROFILE(SMBtranss2
);
6726 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
6729 END_PROFILE(SMBtranss2
);
6734 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6735 DLIST_REMOVE(conn
->pending_trans
, state
);
6736 SAFE_FREE(state
->data
);
6737 SAFE_FREE(state
->param
);
6739 END_PROFILE(SMBtranss2
);
6740 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);