2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern BOOL case_sensitive
;
28 extern int smb_read_error
;
29 extern fstring local_machine
;
30 extern int global_oplock_break
;
31 extern uint32 global_client_caps
;
32 extern struct current_user current_user
;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 account sparse files */
38 SMB_BIG_UINT
get_allocation_size(files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret
= (SMB_BIG_UINT
)STAT_ST_BLOCKSIZE
* (SMB_BIG_UINT
)sbuf
->st_blocks
;
44 ret
= (SMB_BIG_UINT
)get_file_size(*sbuf
);
46 if (!ret
&& fsp
&& fsp
->initial_allocation_size
)
47 ret
= fsp
->initial_allocation_size
;
48 ret
= SMB_ROUNDUP(ret
,SMB_ROUNDUP_ALLOCATION_SIZE
);
52 /****************************************************************************
53 Utility functions for dealing with extended attributes.
54 ****************************************************************************/
56 static const char *prohibited_ea_names
[] = {
57 SAMBA_POSIX_INHERITANCE_EA_NAME
,
58 SAMBA_XATTR_DOS_ATTRIB
,
62 /****************************************************************************
63 Refuse to allow clients to overwrite our private xattrs.
64 ****************************************************************************/
66 static BOOL
samba_private_attr_name(const char *unix_ea_name
)
70 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
71 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
78 struct ea_list
*next
, *prev
;
82 /****************************************************************************
83 Get one EA value. Fill in a struct ea_struct.
84 ****************************************************************************/
86 static BOOL
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
87 const char *fname
, char *ea_name
, struct ea_struct
*pea
)
89 /* Get the value of this xattr. Max size is 64k. */
90 size_t attr_size
= 256;
96 val
= talloc_realloc(mem_ctx
, val
, attr_size
);
101 if (fsp
&& fsp
->fd
!= -1) {
102 sizeret
= SMB_VFS_FGETXATTR(fsp
, fsp
->fd
, ea_name
, val
, attr_size
);
104 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
107 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
116 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name
, sizeret
));
117 dump_data(10, val
, sizeret
);
120 if (strnequal(ea_name
, "user.", 5)) {
121 pea
->name
= &ea_name
[5];
125 pea
->value
.data
= val
;
126 pea
->value
.length
= (size_t)sizeret
;
130 /****************************************************************************
131 Return a linked list of the total EA's. Plus the total size
132 ****************************************************************************/
134 static struct ea_list
*get_ea_list(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
, const char *fname
, size_t *pea_total_len
)
136 /* Get a list of all xattrs. Max namesize is 64k. */
137 size_t ea_namelist_size
= 1024;
142 struct ea_list
*ea_list_head
= NULL
;
146 if (!lp_ea_support(SNUM(conn
))) {
150 for (i
= 0, ea_namelist
= talloc(mem_ctx
, ea_namelist_size
); i
< 6;
151 ea_namelist
= talloc_realloc(mem_ctx
, ea_namelist
, ea_namelist_size
), i
++) {
152 if (fsp
&& fsp
->fd
!= -1) {
153 sizeret
= SMB_VFS_FLISTXATTR(fsp
, fsp
->fd
, ea_namelist
, ea_namelist_size
);
155 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
, ea_namelist_size
);
158 if (sizeret
== -1 && errno
== ERANGE
) {
159 ea_namelist_size
*= 2;
168 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret
));
171 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
) + 1) {
172 struct ea_list
*listp
, *tmp
;
174 if (strnequal(p
, "system.", 7) || samba_private_attr_name(p
))
177 listp
= talloc(mem_ctx
, sizeof(struct ea_list
));
181 if (!get_ea_value(mem_ctx
, conn
, fsp
, fname
, p
, &listp
->ea
)) {
187 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
188 *pea_total_len
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
189 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
190 *pea_total_len
, dos_ea_name
,
191 (unsigned int)listp
->ea
.value
.length
));
193 DLIST_ADD_END(ea_list_head
, listp
, tmp
);
195 /* Add on 4 for total length. */
196 if (*pea_total_len
) {
201 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len
));
205 /****************************************************************************
206 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
208 ****************************************************************************/
210 static unsigned int fill_ea_buffer(char *pdata
, unsigned int total_data_size
,
211 connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
213 unsigned int ret_data_size
= 4;
217 struct ea_list
*ea_list
;
219 SMB_ASSERT(total_data_size
>= 4);
222 if (!lp_ea_support(SNUM(conn
))) {
225 mem_ctx
= talloc_init("fill_ea_buffer");
230 ea_list
= get_ea_list(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
232 talloc_destroy(mem_ctx
);
236 if (total_ea_len
> total_data_size
) {
237 talloc_destroy(mem_ctx
);
241 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
244 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
245 dos_namelen
= strlen(dos_ea_name
);
246 if (dos_namelen
> 255 || dos_namelen
== 0) {
249 if (ea_list
->ea
.value
.length
> 65535) {
252 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
256 /* We know we have room. */
257 SCVAL(p
,0,ea_list
->ea
.flags
);
258 SCVAL(p
,1,dos_namelen
);
259 SSVAL(p
,2,ea_list
->ea
.value
.length
);
260 fstrcpy(p
+4, dos_ea_name
);
261 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
263 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
264 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
267 ret_data_size
= PTR_DIFF(p
, pdata
);
268 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
269 ret_data_size
, total_ea_len
));
270 talloc_destroy(mem_ctx
);
271 SIVAL(pdata
,0,ret_data_size
);
272 return ret_data_size
;
275 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const char *fname
)
277 size_t total_ea_len
= 0;
278 TALLOC_CTX
*mem_ctx
= NULL
;
280 if (!lp_ea_support(SNUM(conn
))) {
283 mem_ctx
= talloc_init("estimate_ea_size");
284 (void)get_ea_list(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
285 talloc_destroy(mem_ctx
);
289 /****************************************************************************
290 Ensure the EA name is case insensitive by matching any existing EA name.
291 ****************************************************************************/
293 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
296 TALLOC_CTX
*mem_ctx
= talloc_init("canonicalize_ea_name");
297 struct ea_list
*ea_list
= get_ea_list(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
);
299 for (; ea_list
; ea_list
= ea_list
->next
) {
300 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
301 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
302 &unix_ea_name
[5], ea_list
->ea
.name
));
303 safe_strcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-6);
307 talloc_destroy(mem_ctx
);
310 /****************************************************************************
311 Set or delete an extended attribute.
312 ****************************************************************************/
314 static NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
, const char *fname
,
315 char *pdata
, int total_data
)
317 unsigned int namelen
;
320 fstring unix_ea_name
;
322 if (!lp_ea_support(SNUM(conn
))) {
323 return NT_STATUS_EAS_NOT_SUPPORTED
;
326 if (total_data
< 8) {
327 return NT_STATUS_INVALID_PARAMETER
;
330 if (IVAL(pdata
,0) > total_data
) {
331 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata
,0), (unsigned int)total_data
));
332 return NT_STATUS_INVALID_PARAMETER
;
336 namelen
= CVAL(pdata
,1);
337 ealen
= SVAL(pdata
,2);
339 if (total_data
< 8 + namelen
+ 1 + ealen
) {
340 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
341 (unsigned int)total_data
, namelen
, ealen
));
342 return NT_STATUS_INVALID_PARAMETER
;
345 if (pdata
[namelen
] != '\0') {
346 DEBUG(10,("set_ea: ea name not null terminated\n"));
347 return NT_STATUS_INVALID_PARAMETER
;
350 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
351 pull_ascii(&unix_ea_name
[5], pdata
, sizeof(fstring
) - 5, -1, STR_TERMINATE
);
352 pdata
+= (namelen
+ 1);
354 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
356 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, ealen
));
358 DEBUG(10,("set_ea: data :\n"));
359 dump_data(10, pdata
, ealen
);
362 if (samba_private_attr_name(unix_ea_name
)) {
363 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
364 return NT_STATUS_ACCESS_DENIED
;
368 /* Remove the attribute. */
369 if (fsp
&& (fsp
->fd
!= -1)) {
370 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
371 unix_ea_name
, fsp
->fsp_name
));
372 ret
= SMB_VFS_FREMOVEXATTR(fsp
, fsp
->fd
, unix_ea_name
);
374 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
375 unix_ea_name
, fname
));
376 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
379 /* Removing a non existent attribute always succeeds. */
380 if (ret
== -1 && errno
== ENOATTR
) {
381 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name
));
386 if (fsp
&& (fsp
->fd
!= -1)) {
387 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
388 unix_ea_name
, fsp
->fsp_name
));
389 ret
= SMB_VFS_FSETXATTR(fsp
, fsp
->fd
, unix_ea_name
, pdata
, ealen
, 0);
391 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
392 unix_ea_name
, fname
));
393 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
, pdata
, ealen
, 0);
399 if (errno
== ENOTSUP
) {
400 return NT_STATUS_EAS_NOT_SUPPORTED
;
403 return map_nt_error_from_unix(errno
);
409 /****************************************************************************
410 Send the required number of replies back.
411 We assume all fields other than the data fields are
412 set correctly for the type of call.
413 HACK ! Always assumes smb_setup field is zero.
414 ****************************************************************************/
416 static int send_trans2_replies(char *outbuf
,
423 /* As we are using a protocol > LANMAN1 then the max_send
424 variable must have been set in the sessetupX call.
425 This takes precedence over the max_xmit field in the
426 global struct. These different max_xmit variables should
427 be merged as this is now too confusing */
430 int data_to_send
= datasize
;
431 int params_to_send
= paramsize
;
435 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
436 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
437 int data_alignment_offset
= 0;
439 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
441 set_message(outbuf
,10,0,True
);
443 /* If there genuinely are no parameters or data to send just send the empty packet */
445 if(params_to_send
== 0 && data_to_send
== 0) {
446 if (!send_smb(smbd_server_fd(),outbuf
))
447 exit_server("send_trans2_replies: send_smb failed.");
451 /* When sending params and data ensure that both are nicely aligned */
452 /* Only do this alignment when there is also data to send - else
453 can cause NT redirector problems. */
455 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
456 data_alignment_offset
= 4 - (params_to_send
% 4);
458 /* Space is bufsize minus Netbios over TCP header minus SMB header */
459 /* The alignment_offset is to align the param bytes on an even byte
460 boundary. NT 4.0 Beta needs this to work correctly. */
462 useable_space
= bufsize
- ((smb_buf(outbuf
)+ alignment_offset
+data_alignment_offset
) - outbuf
);
464 /* useable_space can never be more than max_send minus the alignment offset. */
466 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
468 while (params_to_send
|| data_to_send
) {
469 /* Calculate whether we will totally or partially fill this packet */
471 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
473 /* We can never send more than useable_space */
475 * Note that 'useable_space' does not include the alignment offsets,
476 * but we must include the alignment offsets in the calculation of
477 * the length of the data we send over the wire, as the alignment offsets
478 * are sent here. Fix from Marc_Jacobsen@hp.com.
481 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
483 set_message(outbuf
, 10, total_sent_thistime
, True
);
485 /* Set total params and data to be sent */
486 SSVAL(outbuf
,smb_tprcnt
,paramsize
);
487 SSVAL(outbuf
,smb_tdrcnt
,datasize
);
489 /* Calculate how many parameters and data we can fit into
490 * this packet. Parameters get precedence
493 params_sent_thistime
= MIN(params_to_send
,useable_space
);
494 data_sent_thistime
= useable_space
- params_sent_thistime
;
495 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
497 SSVAL(outbuf
,smb_prcnt
, params_sent_thistime
);
499 /* smb_proff is the offset from the start of the SMB header to the
500 parameter bytes, however the first 4 bytes of outbuf are
501 the Netbios over TCP header. Thus use smb_base() to subtract
502 them from the calculation */
504 SSVAL(outbuf
,smb_proff
,((smb_buf(outbuf
)+alignment_offset
) - smb_base(outbuf
)));
506 if(params_sent_thistime
== 0)
507 SSVAL(outbuf
,smb_prdisp
,0);
509 /* Absolute displacement of param bytes sent in this packet */
510 SSVAL(outbuf
,smb_prdisp
,pp
- params
);
512 SSVAL(outbuf
,smb_drcnt
, data_sent_thistime
);
513 if(data_sent_thistime
== 0) {
514 SSVAL(outbuf
,smb_droff
,0);
515 SSVAL(outbuf
,smb_drdisp
, 0);
517 /* The offset of the data bytes is the offset of the
518 parameter bytes plus the number of parameters being sent this time */
519 SSVAL(outbuf
,smb_droff
,((smb_buf(outbuf
)+alignment_offset
) -
520 smb_base(outbuf
)) + params_sent_thistime
+ data_alignment_offset
);
521 SSVAL(outbuf
,smb_drdisp
, pd
- pdata
);
524 /* Copy the param bytes into the packet */
526 if(params_sent_thistime
)
527 memcpy((smb_buf(outbuf
)+alignment_offset
),pp
,params_sent_thistime
);
529 /* Copy in the data bytes */
530 if(data_sent_thistime
)
531 memcpy(smb_buf(outbuf
)+alignment_offset
+params_sent_thistime
+
532 data_alignment_offset
,pd
,data_sent_thistime
);
534 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
535 params_sent_thistime
, data_sent_thistime
, useable_space
));
536 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
537 params_to_send
, data_to_send
, paramsize
, datasize
));
539 /* Send the packet */
540 if (!send_smb(smbd_server_fd(),outbuf
))
541 exit_server("send_trans2_replies: send_smb failed.");
543 pp
+= params_sent_thistime
;
544 pd
+= data_sent_thistime
;
546 params_to_send
-= params_sent_thistime
;
547 data_to_send
-= data_sent_thistime
;
550 if(params_to_send
< 0 || data_to_send
< 0) {
551 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
552 params_to_send
, data_to_send
));
560 /****************************************************************************
561 Reply to a TRANSACT2_OPEN.
562 ****************************************************************************/
564 static int call_trans2open(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
565 char **pparams
, int total_params
, char **ppdata
, int total_data
)
567 char *params
= *pparams
;
572 BOOL return_additional_info
;
581 int fmode
=0,mtime
=0,rmode
;
583 SMB_STRUCT_STAT sbuf
;
585 BOOL bad_path
= False
;
590 * Ensure we have enough parameters to perform the operation.
593 if (total_params
< 29)
594 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
596 open_mode
= SVAL(params
, 2);
597 open_attr
= SVAL(params
,6);
598 oplock_request
= (((SVAL(params
,0)|(1<<1))>>1) | ((SVAL(params
,0)|(1<<2))>>1));
600 return_additional_info
= BITSETW(params
,0);
601 open_sattr
= SVAL(params
, 4);
602 open_time
= make_unix_date3(params
+8);
604 open_ofun
= SVAL(params
,12);
605 open_size
= IVAL(params
,14);
609 return(ERROR_DOS(ERRSRV
,ERRaccess
));
611 srvstr_get_path(inbuf
, fname
, pname
, sizeof(fname
), -1, STR_TERMINATE
, &status
);
612 if (!NT_STATUS_IS_OK(status
)) {
613 return ERROR_NT(status
);
616 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
617 fname
,open_mode
, open_attr
, open_ofun
, open_size
));
619 /* XXXX we need to handle passed times, sattr and flags */
621 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
623 if (!check_name(fname
,conn
)) {
624 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
627 fsp
= open_file_shared(conn
,fname
,&sbuf
,open_mode
,open_ofun
,(uint32
)open_attr
,
628 oplock_request
, &rmode
,&smb_action
);
631 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
634 size
= get_file_size(sbuf
);
635 fmode
= dos_mode(conn
,fname
,&sbuf
);
636 mtime
= sbuf
.st_mtime
;
639 close_file(fsp
,False
);
640 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
643 /* Realloc the size of parameters and data we will return */
644 params
= Realloc(*pparams
, 28);
646 return(ERROR_DOS(ERRDOS
,ERRnomem
));
649 memset((char *)params
,'\0',28);
650 SSVAL(params
,0,fsp
->fnum
);
651 SSVAL(params
,2,fmode
);
652 put_dos_date2(params
,4, mtime
);
653 SIVAL(params
,8, (uint32
)size
);
654 SSVAL(params
,12,rmode
);
656 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
657 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
659 SSVAL(params
,18,smb_action
);
662 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
664 SIVAL(params
,20,inode
);
666 /* Send the required number of replies */
667 send_trans2_replies(outbuf
, bufsize
, params
, 28, *ppdata
, 0);
672 /*********************************************************
673 Routine to check if a given string matches exactly.
674 as a special case a mask of "." does NOT match. That
675 is required for correct wildcard semantics
676 Case can be significant or not.
677 **********************************************************/
679 static BOOL
exact_match(char *str
,char *mask
, BOOL case_sig
)
681 if (mask
[0] == '.' && mask
[1] == 0)
684 return strcmp(str
,mask
)==0;
685 if (StrCaseCmp(str
,mask
) != 0) {
688 if (ms_has_wild(str
)) {
694 /****************************************************************************
695 Return the filetype for UNIX extensions.
696 ****************************************************************************/
698 static uint32
unix_filetype(mode_t mode
)
701 return UNIX_TYPE_FILE
;
702 else if(S_ISDIR(mode
))
703 return UNIX_TYPE_DIR
;
705 else if(S_ISLNK(mode
))
706 return UNIX_TYPE_SYMLINK
;
709 else if(S_ISCHR(mode
))
710 return UNIX_TYPE_CHARDEV
;
713 else if(S_ISBLK(mode
))
714 return UNIX_TYPE_BLKDEV
;
717 else if(S_ISFIFO(mode
))
718 return UNIX_TYPE_FIFO
;
721 else if(S_ISSOCK(mode
))
722 return UNIX_TYPE_SOCKET
;
725 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
726 return UNIX_TYPE_UNKNOWN
;
729 /****************************************************************************
730 Return the major devicenumber for UNIX extensions.
731 ****************************************************************************/
733 static uint32
unix_dev_major(SMB_DEV_T dev
)
735 #if defined(HAVE_DEVICE_MAJOR_FN)
736 return (uint32
)major(dev
);
738 return (uint32
)(dev
>> 8);
742 /****************************************************************************
743 Return the minor devicenumber for UNIX extensions.
744 ****************************************************************************/
746 static uint32
unix_dev_minor(SMB_DEV_T dev
)
748 #if defined(HAVE_DEVICE_MINOR_FN)
749 return (uint32
)minor(dev
);
751 return (uint32
)(dev
& 0xff);
755 /****************************************************************************
756 Map wire perms onto standard UNIX permissions. Obey share restrictions.
757 ****************************************************************************/
759 static mode_t
unix_perms_from_wire( connection_struct
*conn
, SMB_STRUCT_STAT
*pst
, uint32 perms
)
763 if (perms
== SMB_MODE_NO_CHANGE
)
766 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
767 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
768 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
769 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
770 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
771 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
772 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
773 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
774 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
776 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
779 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
782 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
785 if (VALID_STAT(*pst
) && S_ISDIR(pst
->st_mode
)) {
786 ret
&= lp_dir_mask(SNUM(conn
));
787 /* Add in force bits */
788 ret
|= lp_force_dir_mode(SNUM(conn
));
790 /* Apply mode mask */
791 ret
&= lp_create_mask(SNUM(conn
));
792 /* Add in force bits */
793 ret
|= lp_force_create_mode(SNUM(conn
));
799 /****************************************************************************
800 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
801 ****************************************************************************/
803 time_t interpret_long_unix_date(char *p
)
805 DEBUG(10,("interpret_long_unix_date\n"));
806 if(IVAL(p
,0) == SMB_TIME_NO_CHANGE_LO
&&
807 IVAL(p
,4) == SMB_TIME_NO_CHANGE_HI
) {
810 return interpret_long_date(p
);
814 /****************************************************************************
815 Get a level dependent lanman2 dir entry.
816 ****************************************************************************/
818 static BOOL
get_lanman2_dir_entry(connection_struct
*conn
,
819 void *inbuf
, void *outbuf
,
820 char *path_mask
,int dirtype
,int info_level
,
821 int requires_resume_key
,
822 BOOL dont_descend
,char **ppdata
,
823 char *base_data
, int space_remaining
,
824 BOOL
*out_of_space
, BOOL
*got_exact_match
,
829 SMB_STRUCT_STAT sbuf
;
833 char *p
, *q
, *pdata
= *ppdata
;
837 SMB_OFF_T file_size
= 0;
838 SMB_BIG_UINT allocation_size
= 0;
840 time_t mdate
=0, adate
=0, cdate
=0;
843 int nt_extmode
; /* Used for NT connections instead of mode */
844 BOOL needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
847 *out_of_space
= False
;
848 *got_exact_match
= False
;
853 p
= strrchr_m(path_mask
,'/');
860 pstrcpy(mask
, path_mask
);
865 /* Needed if we run out of space */
866 prev_dirpos
= TellDir(conn
->dirptr
);
867 dname
= ReadDirName(conn
->dirptr
);
870 * Due to bugs in NT client redirectors we are not using
871 * resume keys any more - set them to zero.
872 * Check out the related comments in findfirst/findnext.
878 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
879 (long)conn
->dirptr
,TellDir(conn
->dirptr
)));
884 pstrcpy(fname
,dname
);
886 if(!(got_match
= *got_exact_match
= exact_match(fname
, mask
, case_sensitive
)))
887 got_match
= mask_match(fname
, mask
, case_sensitive
);
889 if(!got_match
&& !mangle_is_8_3(fname
, False
)) {
892 * It turns out that NT matches wildcards against
893 * both long *and* short names. This may explain some
894 * of the wildcard wierdness from old DOS clients
895 * that some people have been seeing.... JRA.
899 pstrcpy( newname
, fname
);
900 mangle_map( newname
, True
, False
, SNUM(conn
));
901 if(!(got_match
= *got_exact_match
= exact_match(newname
, mask
, case_sensitive
)))
902 got_match
= mask_match(newname
, mask
, case_sensitive
);
906 BOOL isdots
= (strequal(fname
,"..") || strequal(fname
,"."));
907 if (dont_descend
&& !isdots
)
910 pstrcpy(pathreal
,conn
->dirpath
);
912 pstrcat(pathreal
,"/");
913 pstrcat(pathreal
,dname
);
915 if (INFO_LEVEL_IS_UNIX(info_level
)) {
916 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
917 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
918 pathreal
,strerror(errno
)));
921 } else if (SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
923 /* Needed to show the msdfs symlinks as
926 if(lp_host_msdfs() &&
927 lp_msdfs_root(SNUM(conn
)) &&
928 is_msdfs_link(conn
, pathreal
, NULL
, NULL
,
931 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal
));
932 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
936 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
937 pathreal
,strerror(errno
)));
942 mode
= dos_mode(conn
,pathreal
,&sbuf
);
944 if (!dir_check_ftype(conn
,mode
,&sbuf
,dirtype
)) {
945 DEBUG(5,("[%s] attribs didn't match %x\n",fname
,dirtype
));
949 file_size
= get_file_size(sbuf
);
950 allocation_size
= get_allocation_size(NULL
,&sbuf
);
951 mdate
= sbuf
.st_mtime
;
952 adate
= sbuf
.st_atime
;
953 cdate
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
955 if (lp_dos_filetime_resolution(SNUM(conn
))) {
964 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal
,fname
));
970 mangle_map(fname
,False
,True
,SNUM(conn
));
975 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
977 switch (info_level
) {
978 case SMB_INFO_STANDARD
:
979 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
980 if(requires_resume_key
) {
984 put_dos_date2(p
,l1_fdateCreation
,cdate
);
985 put_dos_date2(p
,l1_fdateLastAccess
,adate
);
986 put_dos_date2(p
,l1_fdateLastWrite
,mdate
);
987 SIVAL(p
,l1_cbFile
,(uint32
)file_size
);
988 SIVAL(p
,l1_cbFileAlloc
,(uint32
)allocation_size
);
989 SSVAL(p
,l1_attrFile
,mode
);
992 p
+= align_string(outbuf
, p
, 0);
993 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
994 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
996 SCVAL(nameptr
, -1, len
- 2);
998 SCVAL(nameptr
, -1, 0);
1002 SCVAL(nameptr
, -1, len
- 1);
1004 SCVAL(nameptr
, -1, 0);
1010 case SMB_INFO_QUERY_EA_SIZE
:
1011 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1012 if(requires_resume_key
) {
1016 put_dos_date2(p
,l2_fdateCreation
,cdate
);
1017 put_dos_date2(p
,l2_fdateLastAccess
,adate
);
1018 put_dos_date2(p
,l2_fdateLastWrite
,mdate
);
1019 SIVAL(p
,l2_cbFile
,(uint32
)file_size
);
1020 SIVAL(p
,l2_cbFileAlloc
,(uint32
)allocation_size
);
1021 SSVAL(p
,l2_attrFile
,mode
);
1023 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1024 SIVAL(p
,l2_cbList
,ea_size
); /* Extended attributes */
1028 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
1029 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
) {
1042 SCVAL(nameptr
,0,len
);
1044 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1047 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1048 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1049 was_8_3
= mangle_is_8_3(fname
, True
);
1051 SIVAL(p
,0,reskey
); p
+= 4;
1052 put_long_date(p
,cdate
); p
+= 8;
1053 put_long_date(p
,adate
); p
+= 8;
1054 put_long_date(p
,mdate
); p
+= 8;
1055 put_long_date(p
,mdate
); p
+= 8;
1056 SOFF_T(p
,0,file_size
); p
+= 8;
1057 SOFF_T(p
,0,allocation_size
); p
+= 8;
1058 SIVAL(p
,0,nt_extmode
); p
+= 4;
1059 q
= p
; p
+= 4; /* q is placeholder for name length. */
1061 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1062 SIVAL(p
,0,ea_size
); /* Extended attributes */
1065 /* Clear the short name buffer. This is
1066 * IMPORTANT as not doing so will trigger
1067 * a Win2k client bug. JRA.
1070 if (!was_8_3
&& lp_manglednames(SNUM(conn
))) {
1071 pstring mangled_name
;
1072 pstrcpy(mangled_name
, fname
);
1073 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
1074 mangled_name
[12] = 0;
1075 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1082 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1085 len
= PTR_DIFF(p
, pdata
);
1086 len
= (len
+ 3) & ~3;
1091 case SMB_FIND_FILE_DIRECTORY_INFO
:
1092 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1094 SIVAL(p
,0,reskey
); p
+= 4;
1095 put_long_date(p
,cdate
); p
+= 8;
1096 put_long_date(p
,adate
); p
+= 8;
1097 put_long_date(p
,mdate
); p
+= 8;
1098 put_long_date(p
,mdate
); p
+= 8;
1099 SOFF_T(p
,0,file_size
); p
+= 8;
1100 SOFF_T(p
,0,allocation_size
); p
+= 8;
1101 SIVAL(p
,0,nt_extmode
); p
+= 4;
1102 len
= srvstr_push(outbuf
, p
+ 4, fname
, -1, STR_TERMINATE_ASCII
);
1105 len
= PTR_DIFF(p
, pdata
);
1106 len
= (len
+ 3) & ~3;
1111 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1112 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1114 SIVAL(p
,0,reskey
); p
+= 4;
1115 put_long_date(p
,cdate
); p
+= 8;
1116 put_long_date(p
,adate
); p
+= 8;
1117 put_long_date(p
,mdate
); p
+= 8;
1118 put_long_date(p
,mdate
); p
+= 8;
1119 SOFF_T(p
,0,file_size
); p
+= 8;
1120 SOFF_T(p
,0,allocation_size
); p
+= 8;
1121 SIVAL(p
,0,nt_extmode
); p
+= 4;
1122 q
= p
; p
+= 4; /* q is placeholder for name length. */
1124 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1125 SIVAL(p
,0,ea_size
); /* Extended attributes */
1128 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1132 len
= PTR_DIFF(p
, pdata
);
1133 len
= (len
+ 3) & ~3;
1138 case SMB_FIND_FILE_NAMES_INFO
:
1139 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1141 SIVAL(p
,0,reskey
); p
+= 4;
1143 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1144 acl on a dir (tridge) */
1145 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1148 len
= PTR_DIFF(p
, pdata
);
1149 len
= (len
+ 3) & ~3;
1154 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1155 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1157 SIVAL(p
,0,reskey
); p
+= 4;
1158 put_long_date(p
,cdate
); p
+= 8;
1159 put_long_date(p
,adate
); p
+= 8;
1160 put_long_date(p
,mdate
); p
+= 8;
1161 put_long_date(p
,mdate
); p
+= 8;
1162 SOFF_T(p
,0,file_size
); p
+= 8;
1163 SOFF_T(p
,0,allocation_size
); p
+= 8;
1164 SIVAL(p
,0,nt_extmode
); p
+= 4;
1165 q
= p
; p
+= 4; /* q is placeholder for name length. */
1167 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1168 SIVAL(p
,0,ea_size
); /* Extended attributes */
1171 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1172 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4;
1173 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4;
1174 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1177 len
= PTR_DIFF(p
, pdata
);
1178 len
= (len
+ 3) & ~3;
1183 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1184 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1185 was_8_3
= mangle_is_8_3(fname
, True
);
1187 SIVAL(p
,0,reskey
); p
+= 4;
1188 put_long_date(p
,cdate
); p
+= 8;
1189 put_long_date(p
,adate
); p
+= 8;
1190 put_long_date(p
,mdate
); p
+= 8;
1191 put_long_date(p
,mdate
); p
+= 8;
1192 SOFF_T(p
,0,file_size
); p
+= 8;
1193 SOFF_T(p
,0,allocation_size
); p
+= 8;
1194 SIVAL(p
,0,nt_extmode
); p
+= 4;
1195 q
= p
; p
+= 4; /* q is placeholder for name length */
1197 unsigned int ea_size
= estimate_ea_size(conn
, NULL
, pathreal
);
1198 SIVAL(p
,0,ea_size
); /* Extended attributes */
1201 /* Clear the short name buffer. This is
1202 * IMPORTANT as not doing so will trigger
1203 * a Win2k client bug. JRA.
1206 if (!was_8_3
&& lp_manglednames(SNUM(conn
))) {
1207 pstring mangled_name
;
1208 pstrcpy(mangled_name
, fname
);
1209 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
1210 mangled_name
[12] = 0;
1211 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
1218 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
1219 SIVAL(p
,0,sbuf
.st_dev
); p
+= 4;
1220 SIVAL(p
,0,sbuf
.st_ino
); p
+= 4;
1221 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
1224 len
= PTR_DIFF(p
, pdata
);
1225 len
= (len
+ 3) & ~3;
1230 /* CIFS UNIX Extension. */
1232 case SMB_FIND_FILE_UNIX
:
1233 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1235 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1237 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1238 SOFF_T(p
,0,get_file_size(sbuf
)); /* File size 64 Bit */
1241 SOFF_T(p
,0,get_allocation_size(NULL
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
1244 put_long_date(p
,sbuf
.st_ctime
); /* Inode change Time 64 Bit */
1245 put_long_date(p
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
1246 put_long_date(p
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
1249 SIVAL(p
,0,sbuf
.st_uid
); /* user id for the owner */
1253 SIVAL(p
,0,sbuf
.st_gid
); /* group id of owner */
1257 SIVAL(p
,0,unix_filetype(sbuf
.st_mode
));
1260 SIVAL(p
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
1264 SIVAL(p
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
1268 SINO_T(p
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
1271 SIVAL(p
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
1275 SIVAL(p
,0,sbuf
.st_nlink
); /* number of hard links */
1279 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
1282 len
= PTR_DIFF(p
, pdata
);
1283 len
= (len
+ 3) & ~3;
1284 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
1286 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1295 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1296 /* Move the dirptr back to prev_dirpos */
1297 SeekDir(conn
->dirptr
, prev_dirpos
);
1298 *out_of_space
= True
;
1299 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1300 return False
; /* Not finished - just out of space */
1303 /* Setup the last_filename pointer, as an offset from base_data */
1304 *last_name_off
= PTR_DIFF(nameptr
,base_data
);
1305 /* Advance the data pointer to the next slot */
1311 /****************************************************************************
1312 Reply to a TRANS2_FINDFIRST.
1313 ****************************************************************************/
1315 static int call_trans2findfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
1316 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1318 /* We must be careful here that we don't return more than the
1319 allowed number of data bytes. If this means returning fewer than
1320 maxentries then so be it. We assume that the redirector has
1321 enough room for the fixed number of parameter bytes it has
1323 uint32 max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1324 char *params
= *pparams
;
1325 char *pdata
= *ppdata
;
1326 int dirtype
= SVAL(params
,0);
1327 int maxentries
= SVAL(params
,2);
1328 BOOL close_after_first
= BITSETW(params
+4,0);
1329 BOOL close_if_end
= BITSETW(params
+4,1);
1330 BOOL requires_resume_key
= BITSETW(params
+4,2);
1331 int info_level
= SVAL(params
,6);
1335 int last_name_off
=0;
1339 BOOL finished
= False
;
1340 BOOL dont_descend
= False
;
1341 BOOL out_of_space
= False
;
1342 int space_remaining
;
1343 BOOL bad_path
= False
;
1344 SMB_STRUCT_STAT sbuf
;
1345 NTSTATUS ntstatus
= NT_STATUS_OK
;
1347 if (total_params
< 12)
1348 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
1350 *directory
= *mask
= 0;
1352 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1353 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1354 dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
1355 info_level
, max_data_bytes
));
1357 switch (info_level
) {
1358 case SMB_INFO_STANDARD
:
1359 case SMB_INFO_QUERY_EA_SIZE
:
1360 case SMB_FIND_FILE_DIRECTORY_INFO
:
1361 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1362 case SMB_FIND_FILE_NAMES_INFO
:
1363 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1364 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1365 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1367 case SMB_FIND_FILE_UNIX
:
1368 if (!lp_unix_extensions())
1369 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1372 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1375 srvstr_get_path(inbuf
, directory
, params
+12, sizeof(directory
), -1, STR_TERMINATE
, &ntstatus
);
1376 if (!NT_STATUS_IS_OK(ntstatus
)) {
1377 return ERROR_NT(ntstatus
);
1380 RESOLVE_FINDFIRST_DFSPATH(directory
, conn
, inbuf
, outbuf
);
1382 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
1383 if(!check_name(directory
,conn
)) {
1384 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1387 p
= strrchr_m(directory
,'/');
1389 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1390 if((directory
[0] == '.') && (directory
[1] == '\0'))
1393 pstrcpy(mask
,directory
);
1394 pstrcpy(directory
,"./");
1400 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
1402 pdata
= Realloc(*ppdata
, max_data_bytes
+ 1024);
1404 return(ERROR_DOS(ERRDOS
,ERRnomem
));
1407 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1409 /* Realloc the params space */
1410 params
= Realloc(*pparams
, 10);
1412 return ERROR_DOS(ERRDOS
,ERRnomem
);
1415 dptr_num
= dptr_create(conn
,directory
, False
, True
,SVAL(inbuf
,smb_pid
));
1417 return(UNIXERROR(ERRDOS
,ERRbadfile
));
1419 /* Save the wildcard match and attribs we are using on this directory -
1420 needed as lanman2 assumes these are being saved between calls */
1422 if(!(wcard
= strdup(mask
))) {
1423 dptr_close(&dptr_num
);
1424 return ERROR_DOS(ERRDOS
,ERRnomem
);
1427 dptr_set_wcard(dptr_num
, wcard
);
1428 dptr_set_attr(dptr_num
, dirtype
);
1430 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num
, wcard
, dirtype
));
1432 /* We don't need to check for VOL here as this is returned by
1433 a different TRANS2 call. */
1435 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1436 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),case_sensitive
))
1437 dont_descend
= True
;
1440 space_remaining
= max_data_bytes
;
1441 out_of_space
= False
;
1443 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1444 BOOL got_exact_match
= False
;
1446 /* this is a heuristic to avoid seeking the dirptr except when
1447 absolutely necessary. It allows for a filename of about 40 chars */
1448 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1449 out_of_space
= True
;
1452 finished
= !get_lanman2_dir_entry(conn
,
1454 mask
,dirtype
,info_level
,
1455 requires_resume_key
,dont_descend
,
1456 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1460 if (finished
&& out_of_space
)
1463 if (!finished
&& !out_of_space
)
1467 * As an optimisation if we know we aren't looking
1468 * for a wildcard name (ie. the name matches the wildcard exactly)
1469 * then we can finish on any (first) match.
1470 * This speeds up large directory searches. JRA.
1476 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1479 /* Check if we can close the dirptr */
1480 if(close_after_first
|| (finished
&& close_if_end
)) {
1481 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1482 dptr_close(&dptr_num
);
1486 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1487 * from observation of NT.
1490 if(numentries
== 0) {
1491 dptr_close(&dptr_num
);
1492 return ERROR_DOS(ERRDOS
,ERRbadfile
);
1495 /* At this point pdata points to numentries directory entries. */
1497 /* Set up the return parameter block */
1498 SSVAL(params
,0,dptr_num
);
1499 SSVAL(params
,2,numentries
);
1500 SSVAL(params
,4,finished
);
1501 SSVAL(params
,6,0); /* Never an EA error */
1502 SSVAL(params
,8,last_name_off
);
1504 send_trans2_replies( outbuf
, bufsize
, params
, 10, pdata
, PTR_DIFF(p
,pdata
));
1506 if ((! *directory
) && dptr_path(dptr_num
))
1507 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1509 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1510 smb_fn_name(CVAL(inbuf
,smb_com
)),
1511 mask
, directory
, dirtype
, numentries
) );
1514 * Force a name mangle here to ensure that the
1515 * mask as an 8.3 name is top of the mangled cache.
1516 * The reasons for this are subtle. Don't remove
1517 * this code unless you know what you are doing
1518 * (see PR#13758). JRA.
1521 if(!mangle_is_8_3_wildcards( mask
, False
))
1522 mangle_map(mask
, True
, True
, SNUM(conn
));
1527 /****************************************************************************
1528 Reply to a TRANS2_FINDNEXT.
1529 ****************************************************************************/
1531 static int call_trans2findnext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
1532 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1534 /* We must be careful here that we don't return more than the
1535 allowed number of data bytes. If this means returning fewer than
1536 maxentries then so be it. We assume that the redirector has
1537 enough room for the fixed number of parameter bytes it has
1539 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1540 char *params
= *pparams
;
1541 char *pdata
= *ppdata
;
1542 int dptr_num
= SVAL(params
,0);
1543 int maxentries
= SVAL(params
,2);
1544 uint16 info_level
= SVAL(params
,4);
1545 uint32 resume_key
= IVAL(params
,6);
1546 BOOL close_after_request
= BITSETW(params
+10,0);
1547 BOOL close_if_end
= BITSETW(params
+10,1);
1548 BOOL requires_resume_key
= BITSETW(params
+10,2);
1549 BOOL continue_bit
= BITSETW(params
+10,3);
1550 pstring resume_name
;
1556 int i
, last_name_off
=0;
1557 BOOL finished
= False
;
1558 BOOL dont_descend
= False
;
1559 BOOL out_of_space
= False
;
1560 int space_remaining
;
1561 NTSTATUS ntstatus
= NT_STATUS_OK
;
1563 if (total_params
< 12)
1564 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
1566 *mask
= *directory
= *resume_name
= 0;
1568 srvstr_get_path(inbuf
, resume_name
, params
+12, sizeof(resume_name
), -1, STR_TERMINATE
, &ntstatus
);
1569 if (!NT_STATUS_IS_OK(ntstatus
)) {
1570 return ERROR_NT(ntstatus
);
1573 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1574 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1575 resume_key = %d resume name = %s continue=%d level = %d\n",
1576 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
1577 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
1579 switch (info_level
) {
1580 case SMB_INFO_STANDARD
:
1581 case SMB_INFO_QUERY_EA_SIZE
:
1582 case SMB_FIND_FILE_DIRECTORY_INFO
:
1583 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1584 case SMB_FIND_FILE_NAMES_INFO
:
1585 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1587 case SMB_FIND_FILE_UNIX
:
1588 if (!lp_unix_extensions())
1589 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1592 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1595 pdata
= Realloc( *ppdata
, max_data_bytes
+ 1024);
1597 return ERROR_DOS(ERRDOS
,ERRnomem
);
1600 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1602 /* Realloc the params space */
1603 params
= Realloc(*pparams
, 6*SIZEOFWORD
);
1604 if( params
== NULL
)
1605 return ERROR_DOS(ERRDOS
,ERRnomem
);
1609 /* Check that the dptr is valid */
1610 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
)))
1611 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1613 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1615 /* Get the wildcard mask from the dptr */
1616 if((p
= dptr_wcard(dptr_num
))== NULL
) {
1617 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
1618 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1622 pstrcpy(directory
,conn
->dirpath
);
1624 /* Get the attr mask from the dptr */
1625 dirtype
= dptr_attr(dptr_num
);
1627 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1628 dptr_num
, mask
, dirtype
,
1630 TellDir(conn
->dirptr
)));
1632 /* We don't need to check for VOL here as this is returned by
1633 a different TRANS2 call. */
1635 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1636 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),case_sensitive
))
1637 dont_descend
= True
;
1640 space_remaining
= max_data_bytes
;
1641 out_of_space
= False
;
1644 * Seek to the correct position. We no longer use the resume key but
1645 * depend on the last file name instead.
1648 if(requires_resume_key
&& *resume_name
&& !continue_bit
) {
1651 * Fix for NT redirector problem triggered by resume key indexes
1652 * changing between directory scans. We now return a resume key of 0
1653 * and instead look for the filename to continue from (also given
1654 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1655 * findfirst/findnext (as is usual) then the directory pointer
1656 * should already be at the correct place. Check this by scanning
1657 * backwards looking for an exact (ie. case sensitive) filename match.
1658 * If we get to the beginning of the directory and haven't found it then scan
1659 * forwards again looking for a match. JRA.
1662 int current_pos
, start_pos
;
1663 const char *dname
= NULL
;
1664 pstring dname_pstring
;
1665 void *dirptr
= conn
->dirptr
;
1666 start_pos
= TellDir(dirptr
);
1667 for(current_pos
= start_pos
; current_pos
>= 0; current_pos
--) {
1668 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos
));
1670 SeekDir(dirptr
, current_pos
);
1671 dname
= ReadDirName(dirptr
);
1674 * Remember, mangle_map is called by
1675 * get_lanman2_dir_entry(), so the resume name
1676 * could be mangled. Ensure we do the same
1680 /* make sure we get a copy that mangle_map can modify */
1682 pstrcpy(dname_pstring
, dname
);
1683 mangle_map( dname_pstring
, False
, True
, SNUM(conn
));
1685 if(strcsequal( resume_name
, dname_pstring
)) {
1686 SeekDir(dirptr
, current_pos
+1);
1687 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos
+1 ));
1694 * Scan forward from start if not found going backwards.
1697 if(current_pos
< 0) {
1698 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos
));
1699 SeekDir(dirptr
, start_pos
);
1700 for(current_pos
= start_pos
; (dname
= ReadDirName(dirptr
)) != NULL
; SeekDir(dirptr
,++current_pos
)) {
1703 * Remember, mangle_map is called by
1704 * get_lanman2_dir_entry(), so the resume name
1705 * could be mangled. Ensure we do the same
1710 /* make sure we get a copy that mangle_map can modify */
1712 pstrcpy(dname_pstring
, dname
);
1713 mangle_map(dname_pstring
, False
, True
, SNUM(conn
));
1715 if(strcsequal( resume_name
, dname_pstring
)) {
1716 SeekDir(dirptr
, current_pos
+1);
1717 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos
+1 ));
1722 } /* end if current_pos */
1723 } /* end if requires_resume_key && !continue_bit */
1725 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
1726 BOOL got_exact_match
= False
;
1728 /* this is a heuristic to avoid seeking the dirptr except when
1729 absolutely necessary. It allows for a filename of about 40 chars */
1730 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1731 out_of_space
= True
;
1734 finished
= !get_lanman2_dir_entry(conn
,
1736 mask
,dirtype
,info_level
,
1737 requires_resume_key
,dont_descend
,
1738 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1742 if (finished
&& out_of_space
)
1745 if (!finished
&& !out_of_space
)
1749 * As an optimisation if we know we aren't looking
1750 * for a wildcard name (ie. the name matches the wildcard exactly)
1751 * then we can finish on any (first) match.
1752 * This speeds up large directory searches. JRA.
1758 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1761 /* Check if we can close the dirptr */
1762 if(close_after_request
|| (finished
&& close_if_end
)) {
1763 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
1764 dptr_close(&dptr_num
); /* This frees up the saved mask */
1767 /* Set up the return parameter block */
1768 SSVAL(params
,0,numentries
);
1769 SSVAL(params
,2,finished
);
1770 SSVAL(params
,4,0); /* Never an EA error */
1771 SSVAL(params
,6,last_name_off
);
1773 send_trans2_replies( outbuf
, bufsize
, params
, 8, pdata
, PTR_DIFF(p
,pdata
));
1775 if ((! *directory
) && dptr_path(dptr_num
))
1776 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1778 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1779 smb_fn_name(CVAL(inbuf
,smb_com
)),
1780 mask
, directory
, dirtype
, numentries
) );
1785 /****************************************************************************
1786 Reply to a TRANS2_QFSINFO (query filesystem info).
1787 ****************************************************************************/
1789 static int call_trans2qfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
,
1790 int length
, int bufsize
,
1791 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1793 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1794 char *pdata
= *ppdata
;
1795 char *params
= *pparams
;
1796 uint16 info_level
= SVAL(params
,0);
1799 char *vname
= volume_label(SNUM(conn
));
1800 int snum
= SNUM(conn
);
1801 char *fstype
= lp_fstype(SNUM(conn
));
1804 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
1806 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
1807 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
1808 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
1811 pdata
= Realloc(*ppdata
, max_data_bytes
+ 1024);
1812 if ( pdata
== NULL
)
1813 return ERROR_DOS(ERRDOS
,ERRnomem
);
1816 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1818 switch (info_level
) {
1819 case SMB_INFO_ALLOCATION
:
1821 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1823 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1824 block_size
= lp_block_size(snum
);
1825 if (bsize
< block_size
) {
1826 SMB_BIG_UINT factor
= block_size
/bsize
;
1831 if (bsize
> block_size
) {
1832 SMB_BIG_UINT factor
= bsize
/block_size
;
1837 bytes_per_sector
= 512;
1838 sectors_per_unit
= bsize
/bytes_per_sector
;
1840 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1841 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1842 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1844 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
1845 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
1846 SIVAL(pdata
,l1_cUnit
,dsize
);
1847 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
1848 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
1852 case SMB_INFO_VOLUME
:
1853 /* Return volume name */
1855 * Add volume serial number - hash of a combination of
1856 * the called hostname and the service name.
1858 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(local_machine
)<<16) );
1859 len
= srvstr_push(outbuf
, pdata
+l2_vol_szVolLabel
, vname
, -1, STR_NOALIGN
);
1860 SCVAL(pdata
,l2_vol_cch
,len
);
1861 data_len
= l2_vol_szVolLabel
+ len
;
1862 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1863 (unsigned)st
.st_ctime
, len
, vname
));
1866 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
1867 case SMB_FS_ATTRIBUTE_INFORMATION
:
1870 #if defined(HAVE_SYS_QUOTAS)
1871 quota_flag
= FILE_VOLUME_QUOTAS
;
1874 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
1875 (lp_nt_acl_support(SNUM(conn
)) ? FILE_PERSISTENT_ACLS
: 0)|
1876 quota_flag
); /* FS ATTRIBUTES */
1878 SIVAL(pdata
,4,255); /* Max filename component length */
1879 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1880 and will think we can't do long filenames */
1881 len
= srvstr_push(outbuf
, pdata
+12, fstype
, -1, STR_UNICODE
);
1883 data_len
= 12 + len
;
1886 case SMB_QUERY_FS_LABEL_INFO
:
1887 case SMB_FS_LABEL_INFORMATION
:
1888 len
= srvstr_push(outbuf
, pdata
+4, vname
, -1, 0);
1893 case SMB_QUERY_FS_VOLUME_INFO
:
1894 case SMB_FS_VOLUME_INFORMATION
:
1897 * Add volume serial number - hash of a combination of
1898 * the called hostname and the service name.
1900 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
1901 (str_checksum(local_machine
)<<16));
1903 len
= srvstr_push(outbuf
, pdata
+18, vname
, -1, STR_UNICODE
);
1904 SIVAL(pdata
,12,len
);
1906 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1907 (int)strlen(vname
),vname
, lp_servicename(snum
)));
1910 case SMB_QUERY_FS_SIZE_INFO
:
1911 case SMB_FS_SIZE_INFORMATION
:
1913 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1915 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1916 block_size
= lp_block_size(snum
);
1917 if (bsize
< block_size
) {
1918 SMB_BIG_UINT factor
= block_size
/bsize
;
1923 if (bsize
> block_size
) {
1924 SMB_BIG_UINT factor
= bsize
/block_size
;
1929 bytes_per_sector
= 512;
1930 sectors_per_unit
= bsize
/bytes_per_sector
;
1931 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1932 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1933 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1934 SBIG_UINT(pdata
,0,dsize
);
1935 SBIG_UINT(pdata
,8,dfree
);
1936 SIVAL(pdata
,16,sectors_per_unit
);
1937 SIVAL(pdata
,20,bytes_per_sector
);
1941 case SMB_FS_FULL_SIZE_INFORMATION
:
1943 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1945 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1946 block_size
= lp_block_size(snum
);
1947 if (bsize
< block_size
) {
1948 SMB_BIG_UINT factor
= block_size
/bsize
;
1953 if (bsize
> block_size
) {
1954 SMB_BIG_UINT factor
= bsize
/block_size
;
1959 bytes_per_sector
= 512;
1960 sectors_per_unit
= bsize
/bytes_per_sector
;
1961 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1962 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1963 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1964 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
1965 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
1966 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
1967 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
1968 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
1972 case SMB_QUERY_FS_DEVICE_INFO
:
1973 case SMB_FS_DEVICE_INFORMATION
:
1975 SIVAL(pdata
,0,0); /* dev type */
1976 SIVAL(pdata
,4,0); /* characteristics */
1979 #ifdef HAVE_SYS_QUOTAS
1980 case SMB_FS_QUOTA_INFORMATION
:
1982 * what we have to send --metze:
1984 * Unknown1: 24 NULL bytes
1985 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1986 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1987 * Quota Flags: 2 byte :
1988 * Unknown3: 6 NULL bytes
1992 * details for Quota Flags:
1994 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1995 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1996 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1997 * 0x0001 Enable Quotas: enable quota for this fs
2001 /* we need to fake up a fsp here,
2002 * because its not send in this call
2005 SMB_NTQUOTA_STRUCT quotas
;
2008 ZERO_STRUCT(quotas
);
2015 if (current_user
.uid
!= 0) {
2016 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2017 lp_servicename(SNUM(conn
)),conn
->user
));
2018 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2021 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2022 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2023 return ERROR_DOS(ERRSRV
,ERRerror
);
2028 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
2030 /* Unknown1 24 NULL bytes*/
2031 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
2032 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
2033 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
2035 /* Default Soft Quota 8 bytes */
2036 SBIG_UINT(pdata
,24,quotas
.softlim
);
2038 /* Default Hard Quota 8 bytes */
2039 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2041 /* Quota flag 2 bytes */
2042 SSVAL(pdata
,40,quotas
.qflags
);
2044 /* Unknown3 6 NULL bytes */
2050 #endif /* HAVE_SYS_QUOTAS */
2051 case SMB_FS_OBJECTID_INFORMATION
:
2056 * Query the version and capabilities of the CIFS UNIX extensions
2060 case SMB_QUERY_CIFS_UNIX_INFO
:
2061 if (!lp_unix_extensions())
2062 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2064 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2065 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2066 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)0)); /* No capabilities for now... */
2069 case SMB_MAC_QUERY_FS_INFO
:
2071 * Thursby MAC extension... ONLY on NTFS filesystems
2072 * once we do streams then we don't need this
2074 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2076 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2081 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2085 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
);
2087 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf
,smb_com
)), info_level
) );
2092 #ifdef HAVE_SYS_QUOTAS
2093 /****************************************************************************
2094 Reply to a TRANS2_SETFSINFO (set filesystem info).
2095 ****************************************************************************/
2097 static int call_trans2setfsinfo(connection_struct
*conn
,
2098 char *inbuf
, char *outbuf
, int length
, int bufsize
,
2099 char **pparams
, int total_params
, char **ppdata
, int total_data
)
2101 char *pdata
= *ppdata
;
2102 char *params
= *pparams
;
2103 files_struct
*fsp
= NULL
;
2106 SMB_NTQUOTA_STRUCT quotas
;
2108 ZERO_STRUCT(quotas
);
2110 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn
))));
2113 if ((current_user
.uid
!= 0)||!CAN_WRITE(conn
)) {
2114 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2115 lp_servicename(SNUM(conn
)),conn
->user
));
2116 return ERROR_DOS(ERRSRV
,ERRaccess
);
2120 if (total_params
< 4) {
2121 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2123 return ERROR_DOS(ERRDOS
,ERRinvalidparam
);
2126 fsp
= file_fsp(params
,0);
2128 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
2129 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2130 return ERROR_NT(NT_STATUS_INVALID_HANDLE
);
2133 info_level
= SVAL(params
,2);
2135 switch(info_level
) {
2136 case SMB_FS_QUOTA_INFORMATION
:
2137 /* note: normaly there're 48 bytes,
2138 * but we didn't use the last 6 bytes for now
2141 if (total_data
< 42) {
2142 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2144 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2147 /* unknown_1 24 NULL bytes in pdata*/
2149 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2150 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
2151 #ifdef LARGE_SMB_OFF_T
2152 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
2153 #else /* LARGE_SMB_OFF_T */
2154 if ((IVAL(pdata
,28) != 0)&&
2155 ((quotas
.softlim
!= 0xFFFFFFFF)||
2156 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
2157 /* more than 32 bits? */
2158 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2160 #endif /* LARGE_SMB_OFF_T */
2162 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2163 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
2164 #ifdef LARGE_SMB_OFF_T
2165 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
2166 #else /* LARGE_SMB_OFF_T */
2167 if ((IVAL(pdata
,36) != 0)&&
2168 ((quotas
.hardlim
!= 0xFFFFFFFF)||
2169 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
2170 /* more than 32 bits? */
2171 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2173 #endif /* LARGE_SMB_OFF_T */
2175 /* quota_flags 2 bytes **/
2176 quotas
.qflags
= SVAL(pdata
,40);
2178 /* unknown_2 6 NULL bytes follow*/
2180 /* now set the quotas */
2181 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2182 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
2183 return ERROR_DOS(ERRSRV
,ERRerror
);
2188 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2190 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2195 * sending this reply works fine,
2196 * but I'm not sure it's the same
2197 * like windows do...
2200 outsize
= set_message(outbuf
,10,0,True
);
2204 #endif /* HAVE_SYS_QUOTAS */
2206 /****************************************************************************
2207 * Utility function to set bad path error.
2208 ****************************************************************************/
2210 int set_bad_path_error(int err
, BOOL bad_path
, char *outbuf
, int def_class
, uint32 def_code
)
2212 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2213 err
, (int)bad_path
));
2217 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
2219 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2222 return UNIXERROR(def_class
,def_code
);
2225 /****************************************************************************
2226 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2227 file name or file id).
2228 ****************************************************************************/
2230 static int call_trans2qfilepathinfo(connection_struct
*conn
,
2231 char *inbuf
, char *outbuf
, int length
,
2233 char **pparams
, int total_params
, char **ppdata
, int total_data
)
2235 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
2236 char *params
= *pparams
;
2237 char *pdata
= *ppdata
;
2238 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
2241 SMB_OFF_T file_size
=0;
2242 SMB_BIG_UINT allocation_size
=0;
2243 unsigned int data_size
;
2244 unsigned int param_size
= 2;
2245 SMB_STRUCT_STAT sbuf
;
2246 pstring fname
, dos_fname
;
2251 BOOL bad_path
= False
;
2252 BOOL delete_pending
= False
;
2255 files_struct
*fsp
= NULL
;
2256 uint32 desired_access
= 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2259 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2261 if (tran_call
== TRANSACT2_QFILEINFO
) {
2262 if (total_params
< 4)
2263 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2265 fsp
= file_fsp(params
,0);
2266 info_level
= SVAL(params
,2);
2268 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
2270 if(fsp
&& (fsp
->fake_file_handle
)) {
2272 * This is actually for the QUOTA_FAKE_FILE --metze
2275 pstrcpy(fname
, fsp
->fsp_name
);
2276 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2277 if (!check_name(fname
,conn
)) {
2278 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname
,strerror(errno
)));
2279 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2282 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fd
== -1)) {
2284 * This is actually a QFILEINFO on a directory
2285 * handle (returned from an NT SMB). NT5.0 seems
2286 * to do this call. JRA.
2288 pstrcpy(fname
, fsp
->fsp_name
);
2289 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2290 if (!check_name(fname
,conn
)) {
2291 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
2292 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2295 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2296 /* Always do lstat for UNIX calls. */
2297 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
2298 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
2299 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2301 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
2302 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
2303 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2306 delete_pending
= fsp
->directory_delete_on_close
;
2309 * Original code - this is an open file.
2311 CHECK_FSP(fsp
,conn
);
2313 pstrcpy(fname
, fsp
->fsp_name
);
2314 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&sbuf
) != 0) {
2315 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
2316 return(UNIXERROR(ERRDOS
,ERRbadfid
));
2318 pos
= fsp
->position_information
;
2319 delete_pending
= fsp
->delete_on_close
;
2320 desired_access
= fsp
->desired_access
;
2323 NTSTATUS status
= NT_STATUS_OK
;
2326 if (total_params
< 6)
2327 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2329 info_level
= SVAL(params
,0);
2331 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
2333 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
, &status
);
2334 if (!NT_STATUS_IS_OK(status
)) {
2335 return ERROR_NT(status
);
2338 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
2340 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2341 if (!check_name(fname
,conn
)) {
2342 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
2343 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2346 if (INFO_LEVEL_IS_UNIX(info_level
)) {
2347 /* Always do lstat for UNIX calls. */
2348 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
2349 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
2350 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2352 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
) && (info_level
!= SMB_INFO_IS_NAME_VALID
)) {
2353 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
2354 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2358 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
2359 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2361 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2362 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
2364 p
= strrchr_m(fname
,'/');
2370 mode
= dos_mode(conn
,fname
,&sbuf
);
2372 mode
= FILE_ATTRIBUTE_NORMAL
;
2374 fullpathname
= fname
;
2375 file_size
= get_file_size(sbuf
);
2376 allocation_size
= get_allocation_size(fsp
,&sbuf
);
2380 params
= Realloc(*pparams
,2);
2382 return ERROR_DOS(ERRDOS
,ERRnomem
);
2384 memset((char *)params
,'\0',2);
2385 data_size
= max_data_bytes
+ 1024;
2386 pdata
= Realloc(*ppdata
, data_size
);
2387 if ( pdata
== NULL
)
2388 return ERROR_DOS(ERRDOS
,ERRnomem
);
2391 if (total_data
> 0 && IVAL(pdata
,0) == total_data
) {
2392 /* uggh, EAs for OS2 */
2393 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data
));
2394 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
2397 memset((char *)pdata
,'\0',data_size
);
2399 c_time
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
2401 if (lp_dos_filetime_resolution(SNUM(conn
))) {
2403 sbuf
.st_atime
&= ~1;
2404 sbuf
.st_mtime
&= ~1;
2405 sbuf
.st_mtime
&= ~1;
2408 /* NT expects the name to be in an exact form of the *full*
2409 filename. See the trans2 torture test */
2410 if (strequal(base_name
,".")) {
2411 pstrcpy(dos_fname
, "\\");
2413 pstr_sprintf(dos_fname
, "\\%s", fname
);
2414 string_replace(dos_fname
, '/', '\\');
2417 switch (info_level
) {
2418 case SMB_INFO_STANDARD
:
2419 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2421 put_dos_date2(pdata
,l1_fdateCreation
,c_time
);
2422 put_dos_date2(pdata
,l1_fdateLastAccess
,sbuf
.st_atime
);
2423 put_dos_date2(pdata
,l1_fdateLastWrite
,sbuf
.st_mtime
); /* write time */
2424 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
2425 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
2426 SSVAL(pdata
,l1_attrFile
,mode
);
2429 case SMB_INFO_QUERY_EA_SIZE
:
2431 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
2432 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2434 put_dos_date2(pdata
,l1_fdateCreation
,c_time
);
2435 put_dos_date2(pdata
,l1_fdateLastAccess
,sbuf
.st_atime
);
2436 put_dos_date2(pdata
,l1_fdateLastWrite
,sbuf
.st_mtime
); /* write time */
2437 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
2438 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
2439 SSVAL(pdata
,l1_attrFile
,mode
);
2440 SIVAL(pdata
,l1_attrFile
+2,ea_size
);
2444 case SMB_INFO_IS_NAME_VALID
:
2445 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2446 if (tran_call
== TRANSACT2_QFILEINFO
) {
2447 /* os/2 needs this ? really ?*/
2448 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
2454 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2455 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2457 put_dos_date2(pdata
,0,c_time
);
2458 put_dos_date2(pdata
,4,sbuf
.st_atime
);
2459 put_dos_date2(pdata
,8,sbuf
.st_mtime
);
2460 SIVAL(pdata
,12,(uint32
)file_size
);
2461 SIVAL(pdata
,16,(uint32
)allocation_size
);
2462 SIVAL(pdata
,20,mode
);
2465 case SMB_INFO_QUERY_ALL_EAS
:
2466 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2467 /* We have data_size bytes to put EA's into. */
2468 data_size
= fill_ea_buffer(pdata
, data_size
, conn
, fsp
, fname
);
2471 case SMB_FILE_BASIC_INFORMATION
:
2472 case SMB_QUERY_FILE_BASIC_INFO
:
2474 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
2475 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2476 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
2478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2482 put_long_date(pdata
,c_time
);
2483 put_long_date(pdata
+8,sbuf
.st_atime
);
2484 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2485 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2486 SIVAL(pdata
,32,mode
);
2488 DEBUG(5,("SMB_QFBI - "));
2490 time_t create_time
= c_time
;
2491 DEBUG(5,("create: %s ", ctime(&create_time
)));
2493 DEBUG(5,("access: %s ", ctime(&sbuf
.st_atime
)));
2494 DEBUG(5,("write: %s ", ctime(&sbuf
.st_mtime
)));
2495 DEBUG(5,("change: %s ", ctime(&sbuf
.st_mtime
)));
2496 DEBUG(5,("mode: %x\n", mode
));
2500 case SMB_FILE_STANDARD_INFORMATION
:
2501 case SMB_QUERY_FILE_STANDARD_INFO
:
2503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2505 SOFF_T(pdata
,0,allocation_size
);
2506 SOFF_T(pdata
,8,file_size
);
2507 if (delete_pending
& sbuf
.st_nlink
)
2508 SIVAL(pdata
,16,sbuf
.st_nlink
- 1);
2510 SIVAL(pdata
,16,sbuf
.st_nlink
);
2512 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
2515 case SMB_FILE_EA_INFORMATION
:
2516 case SMB_QUERY_FILE_EA_INFO
:
2518 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
2519 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2521 SIVAL(pdata
,0,ea_size
);
2525 /* Get the 8.3 name - used if NT SMB was negotiated. */
2526 case SMB_QUERY_FILE_ALT_NAME_INFO
:
2527 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
2531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2532 pstrcpy(short_name
,base_name
);
2533 /* Mangle if not already 8.3 */
2534 if(!mangle_is_8_3(short_name
, True
)) {
2535 mangle_map(short_name
,True
,True
,SNUM(conn
));
2537 len
= srvstr_push(outbuf
, pdata
+4, short_name
, -1, STR_UNICODE
);
2538 data_size
= 4 + len
;
2543 case SMB_QUERY_FILE_NAME_INFO
:
2545 this must be *exactly* right for ACLs on mapped drives to work
2547 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
2548 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2549 data_size
= 4 + len
;
2553 case SMB_FILE_ALLOCATION_INFORMATION
:
2554 case SMB_QUERY_FILE_ALLOCATION_INFO
:
2555 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2557 SOFF_T(pdata
,0,allocation_size
);
2560 case SMB_FILE_END_OF_FILE_INFORMATION
:
2561 case SMB_QUERY_FILE_END_OF_FILEINFO
:
2562 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2564 SOFF_T(pdata
,0,file_size
);
2567 case SMB_QUERY_FILE_ALL_INFO
:
2568 case SMB_FILE_ALL_INFORMATION
:
2570 unsigned int ea_size
= estimate_ea_size(conn
, fsp
, fname
);
2571 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2572 put_long_date(pdata
,c_time
);
2573 put_long_date(pdata
+8,sbuf
.st_atime
);
2574 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2575 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2576 SIVAL(pdata
,32,mode
);
2578 SOFF_T(pdata
,0,allocation_size
);
2579 SOFF_T(pdata
,8,file_size
);
2580 if (delete_pending
&& sbuf
.st_nlink
)
2581 SIVAL(pdata
,16,sbuf
.st_nlink
- 1);
2583 SIVAL(pdata
,16,sbuf
.st_nlink
);
2584 SCVAL(pdata
,20,delete_pending
);
2585 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
2587 SIVAL(pdata
,0,ea_size
);
2588 pdata
+= 4; /* EA info */
2589 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
2592 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2595 case SMB_FILE_INTERNAL_INFORMATION
:
2596 /* This should be an index number - looks like
2599 I think this causes us to fail the IFSKIT
2600 BasicFileInformationTest. -tpot */
2602 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2603 SIVAL(pdata
,0,sbuf
.st_dev
);
2604 SIVAL(pdata
,4,sbuf
.st_ino
);
2608 case SMB_FILE_ACCESS_INFORMATION
:
2609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2610 SIVAL(pdata
,0,desired_access
);
2614 case SMB_FILE_NAME_INFORMATION
:
2615 /* Pathname with leading '\'. */
2618 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,max_data_bytes
,False
);
2619 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2620 SIVAL(pdata
,0,byte_len
);
2621 data_size
= 4 + byte_len
;
2625 case SMB_FILE_DISPOSITION_INFORMATION
:
2626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2628 SCVAL(pdata
,0,delete_pending
);
2631 case SMB_FILE_POSITION_INFORMATION
:
2632 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2634 SOFF_T(pdata
,0,pos
);
2637 case SMB_FILE_MODE_INFORMATION
:
2638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2639 SIVAL(pdata
,0,mode
);
2643 case SMB_FILE_ALIGNMENT_INFORMATION
:
2644 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2645 SIVAL(pdata
,0,0); /* No alignment needed. */
2651 * NT4 server just returns "invalid query" to this - if we try to answer
2652 * it then NTws gets a BSOD! (tridge).
2653 * W2K seems to want this. JRA.
2655 case SMB_QUERY_FILE_STREAM_INFO
:
2657 case SMB_FILE_STREAM_INFORMATION
:
2658 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2662 size_t byte_len
= dos_PutUniCode(pdata
+24,"::$DATA", 0xE, False
);
2663 SIVAL(pdata
,0,0); /* ??? */
2664 SIVAL(pdata
,4,byte_len
); /* Byte length of unicode string ::$DATA */
2665 SOFF_T(pdata
,8,file_size
);
2666 SIVAL(pdata
,16,allocation_size
);
2667 SIVAL(pdata
,20,0); /* ??? */
2668 data_size
= 24 + byte_len
;
2672 case SMB_QUERY_COMPRESSION_INFO
:
2673 case SMB_FILE_COMPRESSION_INFORMATION
:
2674 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2675 SOFF_T(pdata
,0,file_size
);
2676 SIVAL(pdata
,8,0); /* ??? */
2677 SIVAL(pdata
,12,0); /* ??? */
2681 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
2682 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2683 put_long_date(pdata
,c_time
);
2684 put_long_date(pdata
+8,sbuf
.st_atime
);
2685 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2686 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2687 SIVAL(pdata
,32,allocation_size
);
2688 SOFF_T(pdata
,40,file_size
);
2689 SIVAL(pdata
,48,mode
);
2690 SIVAL(pdata
,52,0); /* ??? */
2694 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
2695 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2696 SIVAL(pdata
,0,mode
);
2702 * CIFS UNIX Extensions.
2705 case SMB_QUERY_FILE_UNIX_BASIC
:
2707 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2708 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf
.st_mode
));
2710 SOFF_T(pdata
,0,get_file_size(sbuf
)); /* File size 64 Bit */
2713 SOFF_T(pdata
,0,get_allocation_size(fsp
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
2716 put_long_date(pdata
,sbuf
.st_ctime
); /* Creation Time 64 Bit */
2717 put_long_date(pdata
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
2718 put_long_date(pdata
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
2721 SIVAL(pdata
,0,sbuf
.st_uid
); /* user id for the owner */
2725 SIVAL(pdata
,0,sbuf
.st_gid
); /* group id of owner */
2729 SIVAL(pdata
,0,unix_filetype(sbuf
.st_mode
));
2732 SIVAL(pdata
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
2736 SIVAL(pdata
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
2740 SINO_T(pdata
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
2743 SIVAL(pdata
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
2747 SIVAL(pdata
,0,sbuf
.st_nlink
); /* number of hard links */
2750 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2754 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2756 for (i
=0; i
<100; i
++)
2757 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
2763 case SMB_QUERY_FILE_UNIX_LINK
:
2767 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2769 if(!S_ISLNK(sbuf
.st_mode
))
2770 return(UNIXERROR(ERRSRV
,ERRbadlink
));
2772 return(UNIXERROR(ERRDOS
,ERRbadlink
));
2774 len
= SMB_VFS_READLINK(conn
,fullpathname
, buffer
, sizeof(pstring
)-1); /* read link */
2776 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2778 len
= srvstr_push(outbuf
, pdata
, buffer
, -1, STR_TERMINATE
);
2780 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2786 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2789 send_trans2_replies(outbuf
, bufsize
, params
, param_size
, *ppdata
, data_size
);
2794 /****************************************************************************
2795 Deal with the internal needs of setting the delete on close flag. Note that
2796 as the tdb locking is recursive, it is safe to call this from within
2797 open_file_shared. JRA.
2798 ****************************************************************************/
2800 NTSTATUS
set_delete_on_close_internal(files_struct
*fsp
, BOOL delete_on_close
)
2803 * Only allow delete on close for writable shares.
2806 if (delete_on_close
&& !CAN_WRITE(fsp
->conn
)) {
2807 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2809 return NT_STATUS_ACCESS_DENIED
;
2812 * Only allow delete on close for files/directories opened with delete intent.
2815 if (delete_on_close
&& !(fsp
->desired_access
& DELETE_ACCESS
)) {
2816 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2818 return NT_STATUS_ACCESS_DENIED
;
2821 if(fsp
->is_directory
) {
2822 fsp
->directory_delete_on_close
= delete_on_close
;
2823 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2824 delete_on_close
? "Added" : "Removed", fsp
->fnum
, fsp
->fsp_name
));
2826 fsp
->delete_on_close
= delete_on_close
;
2827 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2828 delete_on_close
? "Added" : "Removed", fsp
->fnum
, fsp
->fsp_name
));
2831 return NT_STATUS_OK
;
2834 /****************************************************************************
2835 Sets the delete on close flag over all share modes on this file.
2836 Modify the share mode entry for all files open
2837 on this device and inode to tell other smbds we have
2838 changed the delete on close flag. This will be noticed
2839 in the close code, the last closer will delete the file
2841 ****************************************************************************/
2843 NTSTATUS
set_delete_on_close_over_all(files_struct
*fsp
, BOOL delete_on_close
)
2845 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2846 delete_on_close
? "Adding" : "Removing", fsp
->fnum
, fsp
->fsp_name
));
2848 if (fsp
->is_directory
|| fsp
->is_stat
)
2849 return NT_STATUS_OK
;
2851 if (lock_share_entry_fsp(fsp
) == False
)
2852 return NT_STATUS_ACCESS_DENIED
;
2854 if (!modify_delete_flag(fsp
->dev
, fsp
->inode
, delete_on_close
)) {
2855 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2857 unlock_share_entry_fsp(fsp
);
2858 return NT_STATUS_ACCESS_DENIED
;
2861 unlock_share_entry_fsp(fsp
);
2862 return NT_STATUS_OK
;
2865 /****************************************************************************
2866 Returns true if this pathname is within the share, and thus safe.
2867 ****************************************************************************/
2869 static int ensure_link_is_safe(connection_struct
*conn
, const char *link_dest_in
, char *link_dest_out
)
2872 char resolved_name
[PATH_MAX
+1];
2874 pstring resolved_name
;
2876 fstring last_component
;
2880 BOOL bad_path
= False
;
2881 SMB_STRUCT_STAT sbuf
;
2883 pstrcpy(link_dest
, link_dest_in
);
2884 unix_convert(link_dest
,conn
,0,&bad_path
,&sbuf
);
2886 /* Store the UNIX converted path. */
2887 pstrcpy(link_dest_out
, link_dest
);
2889 p
= strrchr(link_dest
, '/');
2891 fstrcpy(last_component
, p
+1);
2894 fstrcpy(last_component
, link_dest
);
2895 pstrcpy(link_dest
, "./");
2898 if (SMB_VFS_REALPATH(conn
,link_dest
,resolved_name
) == NULL
)
2901 pstrcpy(link_dest
, resolved_name
);
2902 pstrcat(link_dest
, "/");
2903 pstrcat(link_dest
, last_component
);
2905 if (*link_dest
!= '/') {
2906 /* Relative path. */
2907 pstrcpy(link_test
, conn
->connectpath
);
2908 pstrcat(link_test
, "/");
2909 pstrcat(link_test
, link_dest
);
2911 pstrcpy(link_test
, link_dest
);
2915 * Check if the link is within the share.
2918 if (strncmp(conn
->connectpath
, link_test
, strlen(conn
->connectpath
))) {
2925 /****************************************************************************
2926 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2928 ****************************************************************************/
2930 NTSTATUS
hardlink_internals(connection_struct
*conn
, char *oldname
, char *newname
)
2932 BOOL bad_path_oldname
= False
;
2933 BOOL bad_path_newname
= False
;
2934 SMB_STRUCT_STAT sbuf1
, sbuf2
;
2936 pstring last_component_oldname
;
2937 pstring last_component_newname
;
2938 NTSTATUS status
= NT_STATUS_OK
;
2944 if (ms_has_wild(newname
) || ms_has_wild(oldname
)) {
2945 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
2948 rc
= unix_convert(oldname
,conn
,last_component_oldname
,&bad_path_oldname
,&sbuf1
);
2949 if (!rc
&& bad_path_oldname
) {
2950 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
2953 /* Quick check for "." and ".." */
2954 if (last_component_oldname
[0] == '.') {
2955 if (!last_component_oldname
[1] || (last_component_oldname
[1] == '.' && !last_component_oldname
[2])) {
2956 return NT_STATUS_OBJECT_NAME_INVALID
;
2960 /* source must already exist. */
2961 if (!VALID_STAT(sbuf1
)) {
2962 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2965 rcdest
= unix_convert(newname
,conn
,last_component_newname
,&bad_path_newname
,&sbuf2
);
2966 if (!rcdest
&& bad_path_newname
) {
2967 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
2970 /* Quick check for "." and ".." */
2971 if (last_component_newname
[0] == '.') {
2972 if (!last_component_newname
[1] || (last_component_newname
[1] == '.' && !last_component_newname
[2])) {
2973 return NT_STATUS_OBJECT_NAME_INVALID
;
2977 /* Disallow if newname already exists. */
2978 if (VALID_STAT(sbuf2
)) {
2979 return NT_STATUS_OBJECT_NAME_COLLISION
;
2982 /* No links from a directory. */
2983 if (S_ISDIR(sbuf1
.st_mode
)) {
2984 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2987 if (ensure_link_is_safe(conn
, oldname
, oldname
) != 0)
2988 return NT_STATUS_ACCESS_DENIED
;
2990 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname
, oldname
));
2992 if (SMB_VFS_LINK(conn
,oldname
,newname
) != 0) {
2993 status
= map_nt_error_from_unix(errno
);
2994 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2995 nt_errstr(status
), newname
, oldname
));
3001 /****************************************************************************
3002 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3003 ****************************************************************************/
3005 static int call_trans2setfilepathinfo(connection_struct
*conn
,
3006 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3007 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3009 char *params
= *pparams
;
3010 char *pdata
= *ppdata
;
3011 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
3016 SMB_STRUCT_STAT sbuf
;
3019 BOOL bad_path
= False
;
3020 files_struct
*fsp
= NULL
;
3021 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
3022 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
3023 mode_t unixmode
= 0;
3024 NTSTATUS status
= NT_STATUS_OK
;
3027 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
3029 if (tran_call
== TRANSACT2_SETFILEINFO
) {
3030 if (total_params
< 4)
3031 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3033 fsp
= file_fsp(params
,0);
3034 info_level
= SVAL(params
,2);
3036 if(fsp
&& (fsp
->is_directory
|| fsp
->fd
== -1)) {
3038 * This is actually a SETFILEINFO on a directory
3039 * handle (returned from an NT SMB). NT5.0 seems
3040 * to do this call. JRA.
3042 pstrcpy(fname
, fsp
->fsp_name
);
3043 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
3044 if (!check_name(fname
,conn
) || (!VALID_STAT(sbuf
))) {
3045 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
3046 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3048 } else if (fsp
&& fsp
->print_file
) {
3050 * Doing a DELETE_ON_CLOSE should cancel a print job.
3052 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
3053 fsp
->share_mode
= FILE_DELETE_ON_CLOSE
;
3055 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
3058 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3061 return (UNIXERROR(ERRDOS
,ERRbadpath
));
3064 * Original code - this is an open file.
3066 CHECK_FSP(fsp
,conn
);
3068 pstrcpy(fname
, fsp
->fsp_name
);
3071 if (SMB_VFS_FSTAT(fsp
,fd
,&sbuf
) != 0) {
3072 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
3073 return(UNIXERROR(ERRDOS
,ERRbadfid
));
3078 if (total_params
< 6)
3079 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3081 info_level
= SVAL(params
,0);
3082 srvstr_get_path(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
, &status
);
3083 if (!NT_STATUS_IS_OK(status
)) {
3084 return ERROR_NT(status
);
3086 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
3089 * For CIFS UNIX extensions the target name may not exist.
3092 if(!VALID_STAT(sbuf
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
3093 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname
, strerror(errno
)));
3094 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3097 if(!check_name(fname
, conn
)) {
3098 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
3103 if (!CAN_WRITE(conn
))
3104 return ERROR_DOS(ERRSRV
,ERRaccess
);
3106 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
3107 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3109 if (VALID_STAT(sbuf
))
3110 unixmode
= sbuf
.st_mode
;
3112 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3113 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
3115 /* Realloc the parameter and data sizes */
3116 params
= Realloc(*pparams
,2);
3118 return ERROR_DOS(ERRDOS
,ERRnomem
);
3124 /* the pending modtime overrides the current modtime */
3125 sbuf
.st_mtime
= fsp
->pending_modtime
;
3128 size
= get_file_size(sbuf
);
3129 tvs
.modtime
= sbuf
.st_mtime
;
3130 tvs
.actime
= sbuf
.st_atime
;
3131 dosmode
= dos_mode(conn
,fname
,&sbuf
);
3132 unixmode
= sbuf
.st_mode
;
3134 set_owner
= VALID_STAT(sbuf
) ? sbuf
.st_uid
: (uid_t
)SMB_UID_NO_CHANGE
;
3135 set_grp
= VALID_STAT(sbuf
) ? sbuf
.st_gid
: (gid_t
)SMB_GID_NO_CHANGE
;
3137 switch (info_level
) {
3138 case SMB_INFO_STANDARD
:
3140 if (total_data
< 12)
3141 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3144 tvs
.actime
= make_unix_date2(pdata
+l1_fdateLastAccess
);
3146 tvs
.modtime
= make_unix_date2(pdata
+l1_fdateLastWrite
);
3150 case SMB_INFO_SET_EA
:
3151 status
= set_ea(conn
, fsp
, fname
, pdata
, total_data
);
3152 if (NT_STATUS_V(status
) != NT_STATUS_V(NT_STATUS_OK
))
3153 return ERROR_NT(status
);
3156 /* XXXX um, i don't think this is right.
3157 it's also not in the cifs6.txt spec.
3159 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3160 if (total_data
< 28)
3161 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3163 tvs
.actime
= make_unix_date2(pdata
+8);
3164 tvs
.modtime
= make_unix_date2(pdata
+12);
3165 size
= IVAL(pdata
,16);
3166 dosmode
= IVAL(pdata
,24);
3169 /* XXXX nor this. not in cifs6.txt, either. */
3170 case SMB_INFO_QUERY_ALL_EAS
:
3171 if (total_data
< 28)
3172 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3174 tvs
.actime
= make_unix_date2(pdata
+8);
3175 tvs
.modtime
= make_unix_date2(pdata
+12);
3176 size
= IVAL(pdata
,16);
3177 dosmode
= IVAL(pdata
,24);
3180 case SMB_SET_FILE_BASIC_INFO
:
3181 case SMB_FILE_BASIC_INFORMATION
:
3183 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3185 time_t changed_time
;
3187 if (total_data
< 36)
3188 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3190 /* Ignore create time at offset pdata. */
3193 tvs
.actime
= interpret_long_date(pdata
+8);
3195 write_time
= interpret_long_date(pdata
+16);
3196 changed_time
= interpret_long_date(pdata
+24);
3198 tvs
.modtime
= MIN(write_time
, changed_time
);
3200 if (write_time
> tvs
.modtime
&& write_time
!= 0xffffffff) {
3201 tvs
.modtime
= write_time
;
3203 /* Prefer a defined time to an undefined one. */
3204 if (tvs
.modtime
== (time_t)0 || tvs
.modtime
== (time_t)-1)
3205 tvs
.modtime
= (write_time
== (time_t)0 || write_time
== (time_t)-1
3206 ? changed_time
: write_time
);
3209 dosmode
= IVAL(pdata
,32);
3213 case SMB_FILE_ALLOCATION_INFORMATION
:
3214 case SMB_SET_FILE_ALLOCATION_INFO
:
3217 SMB_BIG_UINT allocation_size
;
3220 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3222 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
3223 #ifdef LARGE_SMB_OFF_T
3224 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
3225 #else /* LARGE_SMB_OFF_T */
3226 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3227 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3228 #endif /* LARGE_SMB_OFF_T */
3229 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3230 fname
, (double)allocation_size
));
3232 if (allocation_size
)
3233 allocation_size
= SMB_ROUNDUP(allocation_size
,SMB_ROUNDUP_ALLOCATION_SIZE
);
3235 if(allocation_size
!= get_file_size(sbuf
)) {
3236 SMB_STRUCT_STAT new_sbuf
;
3238 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3239 fname
, (double)allocation_size
));
3242 files_struct
*new_fsp
= NULL
;
3243 int access_mode
= 0;
3246 if(global_oplock_break
) {
3247 /* Queue this file modify as we are the process of an oplock break. */
3249 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3250 DEBUGADD(2,( "in oplock break state.\n"));
3252 push_oplock_pending_smb_message(inbuf
, length
);
3256 new_fsp
= open_file_shared1(conn
, fname
, &sbuf
,FILE_WRITE_DATA
,
3257 SET_OPEN_MODE(DOS_OPEN_RDWR
),
3258 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
3259 FILE_ATTRIBUTE_NORMAL
,
3260 0, &access_mode
, &action
);
3262 if (new_fsp
== NULL
)
3263 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3264 ret
= vfs_allocate_file_space(new_fsp
, allocation_size
);
3265 if (SMB_VFS_FSTAT(new_fsp
,new_fsp
->fd
,&new_sbuf
) != 0) {
3266 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3267 new_fsp
->fnum
, strerror(errno
)));
3270 close_file(new_fsp
,True
);
3272 ret
= vfs_allocate_file_space(fsp
, allocation_size
);
3273 if (SMB_VFS_FSTAT(fsp
,fd
,&new_sbuf
) != 0) {
3274 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3275 fsp
->fnum
, strerror(errno
)));
3280 return ERROR_NT(NT_STATUS_DISK_FULL
);
3282 /* Allocate can truncate size... */
3283 size
= get_file_size(new_sbuf
);
3289 case SMB_FILE_END_OF_FILE_INFORMATION
:
3290 case SMB_SET_FILE_END_OF_FILE_INFO
:
3293 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3295 size
= IVAL(pdata
,0);
3296 #ifdef LARGE_SMB_OFF_T
3297 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
3298 #else /* LARGE_SMB_OFF_T */
3299 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3300 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3301 #endif /* LARGE_SMB_OFF_T */
3302 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname
, (double)size
));
3306 case SMB_FILE_DISPOSITION_INFORMATION
:
3307 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
3309 BOOL delete_on_close
;
3312 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3314 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
3316 /* Just ignore this set on a path. */
3317 if (tran_call
!= TRANSACT2_SETFILEINFO
)
3321 return(UNIXERROR(ERRDOS
,ERRbadfid
));
3323 status
= set_delete_on_close_internal(fsp
, delete_on_close
);
3325 if (NT_STATUS_V(status
) != NT_STATUS_V(NT_STATUS_OK
))
3326 return ERROR_NT(status
);
3328 /* The set is across all open files on this dev/inode pair. */
3329 status
=set_delete_on_close_over_all(fsp
, delete_on_close
);
3330 if (NT_STATUS_V(status
) != NT_STATUS_V(NT_STATUS_OK
))
3331 return ERROR_NT(status
);
3336 case SMB_FILE_POSITION_INFORMATION
:
3338 SMB_BIG_UINT position_information
;
3341 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3343 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
3344 #ifdef LARGE_SMB_OFF_T
3345 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
3346 #else /* LARGE_SMB_OFF_T */
3347 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3348 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3349 #endif /* LARGE_SMB_OFF_T */
3350 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3351 fname
, (double)position_information
));
3353 fsp
->position_information
= position_information
;
3358 * CIFS UNIX extensions.
3361 case SMB_SET_FILE_UNIX_BASIC
:
3363 uint32 raw_unixmode
;
3365 if (total_data
< 100)
3366 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3368 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
3369 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
3370 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
3371 #ifdef LARGE_SMB_OFF_T
3372 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
3373 #else /* LARGE_SMB_OFF_T */
3374 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
3375 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3376 #endif /* LARGE_SMB_OFF_T */
3378 pdata
+=24; /* ctime & st_blocks are not changed */
3379 tvs
.actime
= interpret_long_unix_date(pdata
); /* access_time */
3380 tvs
.modtime
= interpret_long_unix_date(pdata
+8); /* modification_time */
3382 set_owner
= (uid_t
)IVAL(pdata
,0);
3384 set_grp
= (gid_t
)IVAL(pdata
,0);
3386 raw_unixmode
= IVAL(pdata
,28);
3387 unixmode
= unix_perms_from_wire(conn
, &sbuf
, raw_unixmode
);
3388 dosmode
= 0; /* Ensure dos mode change doesn't override this. */
3390 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3391 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3392 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
3394 if (!VALID_STAT(sbuf
)) {
3397 * The only valid use of this is to create character and block
3398 * devices, and named pipes. This is deprecated (IMHO) and
3399 * a new info level should be used for mknod. JRA.
3402 #if !defined(HAVE_MAKEDEV_FN)
3403 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3404 #else /* HAVE_MAKEDEV_FN */
3405 uint32 file_type
= IVAL(pdata
,0);
3406 uint32 dev_major
= IVAL(pdata
,4);
3407 uint32 dev_minor
= IVAL(pdata
,12);
3409 uid_t myuid
= geteuid();
3410 gid_t mygid
= getegid();
3413 if (tran_call
== TRANSACT2_SETFILEINFO
)
3414 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3416 if (raw_unixmode
== SMB_MODE_NO_CHANGE
)
3417 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3419 dev
= makedev(dev_major
, dev_minor
);
3421 /* We can only create as the owner/group we are. */
3423 if ((set_owner
!= myuid
) && (set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
))
3424 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3425 if ((set_grp
!= mygid
) && (set_grp
!= (gid_t
)SMB_GID_NO_CHANGE
))
3426 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3428 if (file_type
!= UNIX_TYPE_CHARDEV
&& file_type
!= UNIX_TYPE_BLKDEV
&&
3429 file_type
!= UNIX_TYPE_FIFO
)
3430 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3432 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3433 0%o for file %s\n", (double)dev
, unixmode
, fname
));
3435 /* Ok - do the mknod. */
3436 if (SMB_VFS_MKNOD(conn
,dos_to_unix_static(fname
), unixmode
, dev
) != 0)
3437 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3439 inherit_access_acl(conn
, fname
, unixmode
);
3442 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3444 #endif /* HAVE_MAKEDEV_FN */
3449 * Deal with the UNIX specific mode set.
3452 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
3453 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3454 (unsigned int)unixmode
, fname
));
3455 if (SMB_VFS_CHMOD(conn
,fname
,unixmode
) != 0)
3456 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3460 * Deal with the UNIX specific uid set.
3463 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (sbuf
.st_uid
!= set_owner
)) {
3464 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3465 (unsigned int)set_owner
, fname
));
3466 if (SMB_VFS_CHOWN(conn
,fname
,set_owner
, (gid_t
)-1) != 0)
3467 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3471 * Deal with the UNIX specific gid set.
3474 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (sbuf
.st_gid
!= set_grp
)) {
3475 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3476 (unsigned int)set_owner
, fname
));
3477 if (SMB_VFS_CHOWN(conn
,fname
,(uid_t
)-1, set_grp
) != 0)
3478 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3483 case SMB_SET_FILE_UNIX_LINK
:
3486 char *newname
= fname
;
3488 /* Set a symbolic link. */
3489 /* Don't allow this if follow links is false. */
3491 if (!lp_symlinks(SNUM(conn
)))
3492 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
3494 srvstr_get_path(inbuf
, oldname
, pdata
, sizeof(oldname
), -1, STR_TERMINATE
, &status
);
3495 if (!NT_STATUS_IS_OK(status
)) {
3496 return ERROR_NT(status
);
3499 if (ensure_link_is_safe(conn
, oldname
, oldname
) != 0)
3500 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3502 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3505 if (SMB_VFS_SYMLINK(conn
,oldname
,newname
) != 0)
3506 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3508 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3512 case SMB_SET_FILE_UNIX_HLINK
:
3515 char *newname
= fname
;
3517 /* Set a hard link. */
3518 srvstr_get_path(inbuf
, oldname
, pdata
, sizeof(oldname
), -1, STR_TERMINATE
, &status
);
3519 if (!NT_STATUS_IS_OK(status
)) {
3520 return ERROR_NT(status
);
3523 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3526 status
= hardlink_internals(conn
, oldname
, newname
);
3527 if (!NT_STATUS_IS_OK(status
)) {
3528 return ERROR_NT(status
);
3532 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3536 case SMB_FILE_RENAME_INFORMATION
:
3545 if (total_data
< 12)
3546 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3548 overwrite
= (CVAL(pdata
,0) ? True
: False
);
3549 root_fid
= IVAL(pdata
,4);
3550 len
= IVAL(pdata
,8);
3551 srvstr_get_path(inbuf
, newname
, &pdata
[12], sizeof(newname
), len
, 0, &status
);
3552 if (!NT_STATUS_IS_OK(status
)) {
3553 return ERROR_NT(status
);
3556 /* Check the new name has no '/' characters. */
3557 if (strchr_m(newname
, '/'))
3558 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
3560 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3562 /* Create the base directory. */
3563 pstrcpy(base_name
, fname
);
3564 p
= strrchr_m(base_name
, '/');
3567 /* Append the new name. */
3568 pstrcat(base_name
, "/");
3569 pstrcat(base_name
, newname
);
3572 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3573 fsp
->fnum
, fsp
->fsp_name
, base_name
));
3574 status
= rename_internals_fsp(conn
, fsp
, base_name
, overwrite
);
3576 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3578 status
= rename_internals(conn
, fname
, base_name
, 0, overwrite
);
3580 if (!NT_STATUS_IS_OK(status
)) {
3581 return ERROR_NT(status
);
3583 process_pending_change_notify_queue((time_t)0);
3585 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3589 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3592 /* get some defaults (no modifications) if any info is zero or -1. */
3593 if (tvs
.actime
== (time_t)0 || tvs
.actime
== (time_t)-1)
3594 tvs
.actime
= sbuf
.st_atime
;
3596 if (tvs
.modtime
== (time_t)0 || tvs
.modtime
== (time_t)-1)
3597 tvs
.modtime
= sbuf
.st_mtime
;
3599 DEBUG(6,("actime: %s " , ctime(&tvs
.actime
)));
3600 DEBUG(6,("modtime: %s ", ctime(&tvs
.modtime
)));
3601 DEBUG(6,("size: %.0f ", (double)size
));
3604 if (S_ISDIR(sbuf
.st_mode
))
3610 DEBUG(6,("dosmode: %x\n" , dosmode
));
3612 if(!((info_level
== SMB_SET_FILE_END_OF_FILE_INFO
) ||
3613 (info_level
== SMB_SET_FILE_ALLOCATION_INFO
) ||
3614 (info_level
== SMB_FILE_ALLOCATION_INFORMATION
) ||
3615 (info_level
== SMB_FILE_END_OF_FILE_INFORMATION
))) {
3618 * Only do this test if we are not explicitly
3619 * changing the size of a file.
3622 size
= get_file_size(sbuf
);
3626 * Try and set the times, size and mode of this file -
3627 * if they are different from the current values
3629 if (sbuf
.st_mtime
!= tvs
.modtime
|| sbuf
.st_atime
!= tvs
.actime
) {
3632 * This was a setfileinfo on an open file.
3633 * NT does this a lot. It's actually pointless
3634 * setting the time here, as it will be overwritten
3635 * on the next write, so we save the request
3636 * away and will set it on file close. JRA.
3639 if (tvs
.modtime
!= (time_t)0 && tvs
.modtime
!= (time_t)-1) {
3640 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs
.modtime
) ));
3641 fsp
->pending_modtime
= tvs
.modtime
;
3646 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3648 if(file_utime(conn
, fname
, &tvs
)!=0)
3649 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3653 /* check the mode isn't different, before changing it */
3654 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, &sbuf
))) {
3656 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname
, dosmode
));
3658 if(file_set_dosmode(conn
, fname
, dosmode
, NULL
)) {
3659 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname
, strerror(errno
)));
3660 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3664 if (size
!= get_file_size(sbuf
)) {
3668 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3669 fname
, (double)size
));
3672 files_struct
*new_fsp
= NULL
;
3673 int access_mode
= 0;
3676 if(global_oplock_break
) {
3677 /* Queue this file modify as we are the process of an oplock break. */
3679 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3680 DEBUGADD(2,( "in oplock break state.\n"));
3682 push_oplock_pending_smb_message(inbuf
, length
);
3686 new_fsp
= open_file_shared(conn
, fname
, &sbuf
,
3687 SET_OPEN_MODE(DOS_OPEN_RDWR
),
3688 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
3689 FILE_ATTRIBUTE_NORMAL
,
3690 0, &access_mode
, &action
);
3692 if (new_fsp
== NULL
)
3693 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3694 ret
= vfs_set_filelen(new_fsp
, size
);
3695 close_file(new_fsp
,True
);
3697 ret
= vfs_set_filelen(fsp
, size
);
3701 return (UNIXERROR(ERRHRD
,ERRdiskfull
));
3705 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3710 /****************************************************************************
3711 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3712 ****************************************************************************/
3714 static int call_trans2mkdir(connection_struct
*conn
,
3715 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3716 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3718 char *params
= *pparams
;
3721 SMB_STRUCT_STAT sbuf
;
3722 BOOL bad_path
= False
;
3723 NTSTATUS status
= NT_STATUS_OK
;
3725 if (!CAN_WRITE(conn
))
3726 return ERROR_DOS(ERRSRV
,ERRaccess
);
3728 if (total_params
< 4)
3729 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3731 srvstr_get_path(inbuf
, directory
, ¶ms
[4], sizeof(directory
), -1, STR_TERMINATE
, &status
);
3732 if (!NT_STATUS_IS_OK(status
)) {
3733 return ERROR_NT(status
);
3736 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
3738 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3739 if (check_name(directory
,conn
))
3740 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3743 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno
)));
3744 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
3747 /* Realloc the parameter and data sizes */
3748 params
= Realloc(*pparams
,2);
3750 return ERROR_DOS(ERRDOS
,ERRnomem
);
3755 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3760 /****************************************************************************
3761 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3762 We don't actually do this - we just send a null response.
3763 ****************************************************************************/
3765 static int call_trans2findnotifyfirst(connection_struct
*conn
,
3766 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3767 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3769 static uint16 fnf_handle
= 257;
3770 char *params
= *pparams
;
3773 if (total_params
< 6)
3774 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3776 info_level
= SVAL(params
,4);
3777 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
3779 switch (info_level
) {
3784 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3787 /* Realloc the parameter and data sizes */
3788 params
= Realloc(*pparams
,6);
3790 return ERROR_DOS(ERRDOS
,ERRnomem
);
3793 SSVAL(params
,0,fnf_handle
);
3794 SSVAL(params
,2,0); /* No changes */
3795 SSVAL(params
,4,0); /* No EA errors */
3802 send_trans2_replies(outbuf
, bufsize
, params
, 6, *ppdata
, 0);
3807 /****************************************************************************
3808 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3809 changes). Currently this does nothing.
3810 ****************************************************************************/
3812 static int call_trans2findnotifynext(connection_struct
*conn
,
3813 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3814 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3816 char *params
= *pparams
;
3818 DEBUG(3,("call_trans2findnotifynext\n"));
3820 /* Realloc the parameter and data sizes */
3821 params
= Realloc(*pparams
,4);
3823 return ERROR_DOS(ERRDOS
,ERRnomem
);
3826 SSVAL(params
,0,0); /* No changes */
3827 SSVAL(params
,2,0); /* No EA errors */
3829 send_trans2_replies(outbuf
, bufsize
, params
, 4, *ppdata
, 0);
3834 /****************************************************************************
3835 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3836 ****************************************************************************/
3838 static int call_trans2getdfsreferral(connection_struct
*conn
, char* inbuf
,
3839 char* outbuf
, int length
, int bufsize
,
3840 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3842 char *params
= *pparams
;
3845 int max_referral_level
;
3847 DEBUG(10,("call_trans2getdfsreferral\n"));
3849 if (total_params
< 2)
3850 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3852 max_referral_level
= SVAL(params
,0);
3854 if(!lp_host_msdfs())
3855 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
3857 srvstr_pull(inbuf
, pathname
, ¶ms
[2], sizeof(pathname
), -1, STR_TERMINATE
);
3858 if((reply_size
= setup_dfs_referral(conn
, pathname
,max_referral_level
,ppdata
)) < 0)
3859 return UNIXERROR(ERRDOS
,ERRbadfile
);
3861 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
3862 send_trans2_replies(outbuf
,bufsize
,0,0,*ppdata
,reply_size
);
3867 #define LMCAT_SPL 0x53
3868 #define LMFUNC_GETJOBID 0x60
3870 /****************************************************************************
3871 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3872 ****************************************************************************/
3874 static int call_trans2ioctl(connection_struct
*conn
, char* inbuf
,
3875 char* outbuf
, int length
, int bufsize
,
3876 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3878 char *pdata
= *ppdata
;
3879 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv15
);
3881 /* check for an invalid fid before proceeding */
3884 return(ERROR_DOS(ERRDOS
,ERRbadfid
));
3886 if ((SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
3887 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
3888 pdata
= Realloc(*ppdata
, 32);
3890 return ERROR_DOS(ERRDOS
,ERRnomem
);
3893 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3894 CAN ACCEPT THIS IN UNICODE. JRA. */
3896 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
3897 srvstr_push( outbuf
, pdata
+ 2, global_myname(), 15, STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
3898 srvstr_push( outbuf
, pdata
+18, lp_servicename(SNUM(conn
)), 13, STR_ASCII
|STR_TERMINATE
); /* Service name */
3899 send_trans2_replies(outbuf
,bufsize
,*pparams
,0,*ppdata
,32);
3902 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3903 return ERROR_DOS(ERRSRV
,ERRerror
);
3907 /****************************************************************************
3908 Reply to a SMBfindclose (stop trans2 directory search).
3909 ****************************************************************************/
3911 int reply_findclose(connection_struct
*conn
,
3912 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3915 int dptr_num
=SVALS(inbuf
,smb_vwv0
);
3916 START_PROFILE(SMBfindclose
);
3918 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
3920 dptr_close(&dptr_num
);
3922 outsize
= set_message(outbuf
,0,0,True
);
3924 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
3926 END_PROFILE(SMBfindclose
);
3930 /****************************************************************************
3931 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3932 ****************************************************************************/
3934 int reply_findnclose(connection_struct
*conn
,
3935 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3939 START_PROFILE(SMBfindnclose
);
3941 dptr_num
= SVAL(inbuf
,smb_vwv0
);
3943 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
3945 /* We never give out valid handles for a
3946 findnotifyfirst - so any dptr_num is ok here.
3949 outsize
= set_message(outbuf
,0,0,True
);
3951 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
3953 END_PROFILE(SMBfindnclose
);
3957 /****************************************************************************
3958 Reply to a SMBtranss2 - just ignore it!
3959 ****************************************************************************/
3961 int reply_transs2(connection_struct
*conn
,
3962 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3964 START_PROFILE(SMBtranss2
);
3965 DEBUG(4,("Ignoring transs2 of length %d\n",length
));
3966 END_PROFILE(SMBtranss2
);
3970 /****************************************************************************
3971 Reply to a SMBtrans2.
3972 ****************************************************************************/
3974 int reply_trans2(connection_struct
*conn
,
3975 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3978 unsigned int total_params
= SVAL(inbuf
, smb_tpscnt
);
3979 unsigned int total_data
=SVAL(inbuf
, smb_tdscnt
);
3981 unsigned int max_param_reply
= SVAL(inbuf
, smb_mprcnt
);
3982 unsigned int max_data_reply
= SVAL(inbuf
, smb_mdrcnt
);
3983 unsigned int max_setup_fields
= SVAL(inbuf
, smb_msrcnt
);
3984 BOOL close_tid
= BITSETW(inbuf
+smb_flags
,0);
3985 BOOL no_final_response
= BITSETW(inbuf
+smb_flags
,1);
3986 int32 timeout
= IVALS(inbuf
,smb_timeout
);
3988 unsigned int suwcnt
= SVAL(inbuf
, smb_suwcnt
);
3989 unsigned int tran_call
= SVAL(inbuf
, smb_setup0
);
3990 char *params
= NULL
, *data
= NULL
;
3991 unsigned int num_params
, num_params_sofar
, num_data
, num_data_sofar
;
3992 START_PROFILE(SMBtrans2
);
3994 if(global_oplock_break
&& (tran_call
== TRANSACT2_OPEN
)) {
3995 /* Queue this open message as we are the process of an
3998 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3999 DEBUGADD(2,( "in oplock break state.\n"));
4001 push_oplock_pending_smb_message(inbuf
, length
);
4002 END_PROFILE(SMBtrans2
);
4006 if (IS_IPC(conn
) && (tran_call
!= TRANSACT2_OPEN
)
4007 && (tran_call
!= TRANSACT2_GET_DFS_REFERRAL
)) {
4008 END_PROFILE(SMBtrans2
);
4009 return ERROR_DOS(ERRSRV
,ERRaccess
);
4012 outsize
= set_message(outbuf
,0,0,True
);
4014 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4015 is so as a sanity check */
4018 * Need to have rc=0 for ioctl to get job id for OS/2.
4019 * Network printing will fail if function is not successful.
4020 * Similar function in reply.c will be used if protocol
4021 * is LANMAN1.0 instead of LM1.2X002.
4022 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4023 * outbuf doesn't have to be set(only job id is used).
4025 if ( (suwcnt
== 4) && (tran_call
== TRANSACT2_IOCTL
) &&
4026 (SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
4027 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
4028 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4030 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt
));
4031 DEBUG(2,("Transaction is %d\n",tran_call
));
4032 END_PROFILE(SMBtrans2
);
4033 ERROR_DOS(ERRDOS
,ERRinvalidparam
);
4037 /* Allocate the space for the maximum needed parameters and data */
4038 if (total_params
> 0)
4039 params
= (char *)malloc(total_params
);
4041 data
= (char *)malloc(total_data
);
4043 if ((total_params
&& !params
) || (total_data
&& !data
)) {
4044 DEBUG(2,("Out of memory in reply_trans2\n"));
4047 END_PROFILE(SMBtrans2
);
4048 return ERROR_DOS(ERRDOS
,ERRnomem
);
4051 /* Copy the param and data bytes sent with this request into
4052 the params buffer */
4053 num_params
= num_params_sofar
= SVAL(inbuf
,smb_pscnt
);
4054 num_data
= num_data_sofar
= SVAL(inbuf
, smb_dscnt
);
4056 if (num_params
> total_params
|| num_data
> total_data
)
4057 exit_server("invalid params in reply_trans2");
4060 unsigned int psoff
= SVAL(inbuf
, smb_psoff
);
4061 if ((psoff
+ num_params
< psoff
) || (psoff
+ num_params
< num_params
))
4063 if ((smb_base(inbuf
) + psoff
+ num_params
> inbuf
+ length
) ||
4064 (smb_base(inbuf
) + psoff
+ num_params
< smb_base(inbuf
)))
4066 memcpy( params
, smb_base(inbuf
) + psoff
, num_params
);
4069 unsigned int dsoff
= SVAL(inbuf
, smb_dsoff
);
4070 if ((dsoff
+ num_data
< dsoff
) || (dsoff
+ num_data
< num_data
))
4072 if ((smb_base(inbuf
) + dsoff
+ num_data
> inbuf
+ length
) ||
4073 (smb_base(inbuf
) + dsoff
+ num_data
< smb_base(inbuf
)))
4075 memcpy( data
, smb_base(inbuf
) + dsoff
, num_data
);
4078 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
4080 if(num_data_sofar
< total_data
|| num_params_sofar
< total_params
) {
4081 /* We need to send an interim response then receive the rest
4082 of the parameter/data bytes */
4083 outsize
= set_message(outbuf
,0,0,True
);
4084 srv_signing_trans_stop();
4085 if (!send_smb(smbd_server_fd(),outbuf
))
4086 exit_server("reply_trans2: send_smb failed.");
4088 while (num_data_sofar
< total_data
||
4089 num_params_sofar
< total_params
) {
4091 unsigned int param_disp
;
4092 unsigned int param_off
;
4093 unsigned int data_disp
;
4094 unsigned int data_off
;
4096 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
4099 * The sequence number for the trans reply is always
4100 * based on the last secondary received.
4103 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
4106 (CVAL(inbuf
, smb_com
) != SMBtranss2
)) || !ret
) {
4107 outsize
= set_message(outbuf
,0,0,True
);
4109 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4111 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4112 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
4116 /* Revise total_params and total_data in case
4117 they have changed downwards */
4118 if (SVAL(inbuf
, smb_tpscnt
) < total_params
)
4119 total_params
= SVAL(inbuf
, smb_tpscnt
);
4120 if (SVAL(inbuf
, smb_tdscnt
) < total_data
)
4121 total_data
= SVAL(inbuf
, smb_tdscnt
);
4123 num_params
= SVAL(inbuf
,smb_spscnt
);
4124 param_off
= SVAL(inbuf
, smb_spsoff
);
4125 param_disp
= SVAL(inbuf
, smb_spsdisp
);
4126 num_params_sofar
+= num_params
;
4128 num_data
= SVAL(inbuf
, smb_sdscnt
);
4129 data_off
= SVAL(inbuf
, smb_sdsoff
);
4130 data_disp
= SVAL(inbuf
, smb_sdsdisp
);
4131 num_data_sofar
+= num_data
;
4133 if (num_params_sofar
> total_params
|| num_data_sofar
> total_data
)
4137 if (param_disp
+ num_params
>= total_params
)
4139 if ((param_disp
+ num_params
< param_disp
) ||
4140 (param_disp
+ num_params
< num_params
))
4142 if (param_disp
> total_params
)
4144 if ((smb_base(inbuf
) + param_off
+ num_params
>= inbuf
+ bufsize
) ||
4145 (smb_base(inbuf
) + param_off
+ num_params
< smb_base(inbuf
)))
4147 if (params
+ param_disp
< params
)
4150 memcpy( ¶ms
[param_disp
], smb_base(inbuf
) + param_off
, num_params
);
4153 if (data_disp
+ num_data
>= total_data
)
4155 if ((data_disp
+ num_data
< data_disp
) ||
4156 (data_disp
+ num_data
< num_data
))
4158 if (data_disp
> total_data
)
4160 if ((smb_base(inbuf
) + data_off
+ num_data
>= inbuf
+ bufsize
) ||
4161 (smb_base(inbuf
) + data_off
+ num_data
< smb_base(inbuf
)))
4163 if (data
+ data_disp
< data
)
4166 memcpy( &data
[data_disp
], smb_base(inbuf
) + data_off
, num_data
);
4171 if (Protocol
>= PROTOCOL_NT1
) {
4172 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | 0x40); /* IS_LONG_NAME */
4175 /* Now we must call the relevant TRANS2 function */
4177 case TRANSACT2_OPEN
:
4178 START_PROFILE_NESTED(Trans2_open
);
4179 outsize
= call_trans2open(conn
, inbuf
, outbuf
, bufsize
,
4180 ¶ms
, total_params
, &data
, total_data
);
4181 END_PROFILE_NESTED(Trans2_open
);
4184 case TRANSACT2_FINDFIRST
:
4185 START_PROFILE_NESTED(Trans2_findfirst
);
4186 outsize
= call_trans2findfirst(conn
, inbuf
, outbuf
, bufsize
,
4187 ¶ms
, total_params
, &data
, total_data
);
4188 END_PROFILE_NESTED(Trans2_findfirst
);
4191 case TRANSACT2_FINDNEXT
:
4192 START_PROFILE_NESTED(Trans2_findnext
);
4193 outsize
= call_trans2findnext(conn
, inbuf
, outbuf
, length
, bufsize
,
4194 ¶ms
, total_params
, &data
, total_data
);
4195 END_PROFILE_NESTED(Trans2_findnext
);
4198 case TRANSACT2_QFSINFO
:
4199 START_PROFILE_NESTED(Trans2_qfsinfo
);
4200 outsize
= call_trans2qfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
4201 ¶ms
, total_params
, &data
, total_data
);
4202 END_PROFILE_NESTED(Trans2_qfsinfo
);
4205 #ifdef HAVE_SYS_QUOTAS
4206 case TRANSACT2_SETFSINFO
:
4207 START_PROFILE_NESTED(Trans2_setfsinfo
);
4208 outsize
= call_trans2setfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
4209 ¶ms
, total_params
, &data
, total_data
);
4210 END_PROFILE_NESTED(Trans2_setfsinfo
);
4213 case TRANSACT2_QPATHINFO
:
4214 case TRANSACT2_QFILEINFO
:
4215 START_PROFILE_NESTED(Trans2_qpathinfo
);
4216 outsize
= call_trans2qfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
4217 ¶ms
, total_params
, &data
, total_data
);
4218 END_PROFILE_NESTED(Trans2_qpathinfo
);
4220 case TRANSACT2_SETPATHINFO
:
4221 case TRANSACT2_SETFILEINFO
:
4222 START_PROFILE_NESTED(Trans2_setpathinfo
);
4223 outsize
= call_trans2setfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
4224 ¶ms
, total_params
, &data
, total_data
);
4225 END_PROFILE_NESTED(Trans2_setpathinfo
);
4228 case TRANSACT2_FINDNOTIFYFIRST
:
4229 START_PROFILE_NESTED(Trans2_findnotifyfirst
);
4230 outsize
= call_trans2findnotifyfirst(conn
, inbuf
, outbuf
, length
, bufsize
,
4231 ¶ms
, total_params
, &data
, total_data
);
4232 END_PROFILE_NESTED(Trans2_findnotifyfirst
);
4235 case TRANSACT2_FINDNOTIFYNEXT
:
4236 START_PROFILE_NESTED(Trans2_findnotifynext
);
4237 outsize
= call_trans2findnotifynext(conn
, inbuf
, outbuf
, length
, bufsize
,
4238 ¶ms
, total_params
, &data
, total_data
);
4239 END_PROFILE_NESTED(Trans2_findnotifynext
);
4241 case TRANSACT2_MKDIR
:
4242 START_PROFILE_NESTED(Trans2_mkdir
);
4243 outsize
= call_trans2mkdir(conn
, inbuf
, outbuf
, length
, bufsize
,
4244 ¶ms
, total_params
, &data
, total_data
);
4245 END_PROFILE_NESTED(Trans2_mkdir
);
4248 case TRANSACT2_GET_DFS_REFERRAL
:
4249 START_PROFILE_NESTED(Trans2_get_dfs_referral
);
4250 outsize
= call_trans2getdfsreferral(conn
,inbuf
,outbuf
,length
, bufsize
,
4251 ¶ms
, total_params
, &data
, total_data
);
4252 END_PROFILE_NESTED(Trans2_get_dfs_referral
);
4254 case TRANSACT2_IOCTL
:
4255 START_PROFILE_NESTED(Trans2_ioctl
);
4256 outsize
= call_trans2ioctl(conn
,inbuf
,outbuf
,length
, bufsize
,
4257 ¶ms
, total_params
, &data
, total_data
);
4258 END_PROFILE_NESTED(Trans2_ioctl
);
4261 /* Error in request */
4262 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call
));
4265 END_PROFILE(SMBtrans2
);
4266 srv_signing_trans_stop();
4267 return ERROR_DOS(ERRSRV
,ERRerror
);
4270 /* As we do not know how many data packets will need to be
4271 returned here the various call_trans2xxxx calls
4272 must send their own. Thus a call_trans2xxx routine only
4273 returns a value other than -1 when it wants to send
4277 srv_signing_trans_stop();
4281 END_PROFILE(SMBtrans2
);
4282 return outsize
; /* If a correct response was needed the
4283 call_trans2xxx calls have already sent
4284 it. If outsize != -1 then it is returning */
4288 srv_signing_trans_stop();
4291 END_PROFILE(SMBtrans2
);
4292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);