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 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static int send_trans2_replies(char *outbuf
,
66 /* As we are using a protocol > LANMAN1 then the max_send
67 variable must have been set in the sessetupX call.
68 This takes precedence over the max_xmit field in the
69 global struct. These different max_xmit variables should
70 be merged as this is now too confusing */
73 int data_to_send
= datasize
;
74 int params_to_send
= paramsize
;
78 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
79 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
80 int data_alignment_offset
= 0;
82 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
84 set_message(outbuf
,10,0,True
);
86 /* If there genuinely are no parameters or data to send just send the empty packet */
88 if(params_to_send
== 0 && data_to_send
== 0) {
89 if (!send_smb(smbd_server_fd(),outbuf
))
90 exit_server("send_trans2_replies: send_smb failed.");
94 /* When sending params and data ensure that both are nicely aligned */
95 /* Only do this alignment when there is also data to send - else
96 can cause NT redirector problems. */
98 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
99 data_alignment_offset
= 4 - (params_to_send
% 4);
101 /* Space is bufsize minus Netbios over TCP header minus SMB header */
102 /* The alignment_offset is to align the param bytes on an even byte
103 boundary. NT 4.0 Beta needs this to work correctly. */
105 useable_space
= bufsize
- ((smb_buf(outbuf
)+ alignment_offset
+data_alignment_offset
) - outbuf
);
107 /* useable_space can never be more than max_send minus the alignment offset. */
109 useable_space
= MIN(useable_space
, max_send
- (alignment_offset
+data_alignment_offset
));
111 while (params_to_send
|| data_to_send
) {
112 /* Calculate whether we will totally or partially fill this packet */
114 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
+ data_alignment_offset
;
116 /* We can never send more than useable_space */
118 * Note that 'useable_space' does not include the alignment offsets,
119 * but we must include the alignment offsets in the calculation of
120 * the length of the data we send over the wire, as the alignment offsets
121 * are sent here. Fix from Marc_Jacobsen@hp.com.
124 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
+ alignment_offset
+ data_alignment_offset
);
126 set_message(outbuf
, 10, total_sent_thistime
, True
);
128 /* Set total params and data to be sent */
129 SSVAL(outbuf
,smb_tprcnt
,paramsize
);
130 SSVAL(outbuf
,smb_tdrcnt
,datasize
);
132 /* Calculate how many parameters and data we can fit into
133 * this packet. Parameters get precedence
136 params_sent_thistime
= MIN(params_to_send
,useable_space
);
137 data_sent_thistime
= useable_space
- params_sent_thistime
;
138 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
140 SSVAL(outbuf
,smb_prcnt
, params_sent_thistime
);
142 /* smb_proff is the offset from the start of the SMB header to the
143 parameter bytes, however the first 4 bytes of outbuf are
144 the Netbios over TCP header. Thus use smb_base() to subtract
145 them from the calculation */
147 SSVAL(outbuf
,smb_proff
,((smb_buf(outbuf
)+alignment_offset
) - smb_base(outbuf
)));
149 if(params_sent_thistime
== 0)
150 SSVAL(outbuf
,smb_prdisp
,0);
152 /* Absolute displacement of param bytes sent in this packet */
153 SSVAL(outbuf
,smb_prdisp
,pp
- params
);
155 SSVAL(outbuf
,smb_drcnt
, data_sent_thistime
);
156 if(data_sent_thistime
== 0) {
157 SSVAL(outbuf
,smb_droff
,0);
158 SSVAL(outbuf
,smb_drdisp
, 0);
160 /* The offset of the data bytes is the offset of the
161 parameter bytes plus the number of parameters being sent this time */
162 SSVAL(outbuf
,smb_droff
,((smb_buf(outbuf
)+alignment_offset
) -
163 smb_base(outbuf
)) + params_sent_thistime
+ data_alignment_offset
);
164 SSVAL(outbuf
,smb_drdisp
, pd
- pdata
);
167 /* Copy the param bytes into the packet */
169 if(params_sent_thistime
)
170 memcpy((smb_buf(outbuf
)+alignment_offset
),pp
,params_sent_thistime
);
172 /* Copy in the data bytes */
173 if(data_sent_thistime
)
174 memcpy(smb_buf(outbuf
)+alignment_offset
+params_sent_thistime
+
175 data_alignment_offset
,pd
,data_sent_thistime
);
177 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
178 params_sent_thistime
, data_sent_thistime
, useable_space
));
179 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
180 params_to_send
, data_to_send
, paramsize
, datasize
));
182 /* Send the packet */
183 if (!send_smb(smbd_server_fd(),outbuf
))
184 exit_server("send_trans2_replies: send_smb failed.");
186 pp
+= params_sent_thistime
;
187 pd
+= data_sent_thistime
;
189 params_to_send
-= params_sent_thistime
;
190 data_to_send
-= data_sent_thistime
;
193 if(params_to_send
< 0 || data_to_send
< 0) {
194 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
195 params_to_send
, data_to_send
));
203 /****************************************************************************
204 Reply to a TRANSACT2_OPEN.
205 ****************************************************************************/
207 static int call_trans2open(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
208 char **pparams
, int total_params
, char **ppdata
, int total_data
)
210 char *params
= *pparams
;
215 BOOL return_additional_info
;
225 int fmode
=0,mtime
=0,rmode
;
227 SMB_STRUCT_STAT sbuf
;
229 BOOL bad_path
= False
;
233 * Ensure we have enough parameters to perform the operation.
236 if (total_params
< 29)
237 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
239 open_mode
= SVAL(params
, 2);
240 open_attr
= SVAL(params
,6);
241 oplock_request
= (((SVAL(params
,0)|(1<<1))>>1) | ((SVAL(params
,0)|(1<<2))>>1));
243 return_additional_info
= BITSETW(params
,0);
244 open_sattr
= SVAL(params
, 4);
245 open_time
= make_unix_date3(params
+8);
247 open_ofun
= SVAL(params
,12);
248 open_size
= IVAL(params
,14);
251 srvstr_pull(inbuf
, fname
, pname
, sizeof(fname
), -1, STR_TERMINATE
);
253 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
254 fname
,open_mode
, open_attr
, open_ofun
, open_size
));
257 return(ERROR_DOS(ERRSRV
,ERRaccess
));
259 /* XXXX we need to handle passed times, sattr and flags */
261 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
263 if (!check_name(fname
,conn
)) {
264 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
267 unixmode
= unix_mode(conn
,open_attr
| aARCH
, fname
);
269 fsp
= open_file_shared(conn
,fname
,&sbuf
,open_mode
,open_ofun
,unixmode
,
270 oplock_request
, &rmode
,&smb_action
);
273 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
276 size
= get_file_size(sbuf
);
277 fmode
= dos_mode(conn
,fname
,&sbuf
);
278 mtime
= sbuf
.st_mtime
;
281 close_file(fsp
,False
);
282 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
285 /* Realloc the size of parameters and data we will return */
286 params
= Realloc(*pparams
, 28);
288 return(ERROR_DOS(ERRDOS
,ERRnomem
));
291 memset((char *)params
,'\0',28);
292 SSVAL(params
,0,fsp
->fnum
);
293 SSVAL(params
,2,fmode
);
294 put_dos_date2(params
,4, mtime
);
295 SIVAL(params
,8, (uint32
)size
);
296 SSVAL(params
,12,rmode
);
298 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
299 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
301 SSVAL(params
,18,smb_action
);
304 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
306 SIVAL(params
,20,inode
);
308 /* Send the required number of replies */
309 send_trans2_replies(outbuf
, bufsize
, params
, 28, *ppdata
, 0);
314 /*********************************************************
315 Routine to check if a given string matches exactly.
316 as a special case a mask of "." does NOT match. That
317 is required for correct wildcard semantics
318 Case can be significant or not.
319 **********************************************************/
321 static BOOL
exact_match(char *str
,char *mask
, BOOL case_sig
)
323 if (mask
[0] == '.' && mask
[1] == 0)
326 return strcmp(str
,mask
)==0;
327 if (StrCaseCmp(str
,mask
) != 0) {
330 if (ms_has_wild(str
)) {
336 /****************************************************************************
337 Return the filetype for UNIX extensions.
338 ****************************************************************************/
340 static uint32
unix_filetype(mode_t mode
)
343 return UNIX_TYPE_FILE
;
344 else if(S_ISDIR(mode
))
345 return UNIX_TYPE_DIR
;
347 else if(S_ISLNK(mode
))
348 return UNIX_TYPE_SYMLINK
;
351 else if(S_ISCHR(mode
))
352 return UNIX_TYPE_CHARDEV
;
355 else if(S_ISBLK(mode
))
356 return UNIX_TYPE_BLKDEV
;
359 else if(S_ISFIFO(mode
))
360 return UNIX_TYPE_FIFO
;
363 else if(S_ISSOCK(mode
))
364 return UNIX_TYPE_SOCKET
;
367 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode
));
368 return UNIX_TYPE_UNKNOWN
;
371 /****************************************************************************
372 Return the major devicenumber for UNIX extensions.
373 ****************************************************************************/
375 static uint32
unix_dev_major(SMB_DEV_T dev
)
377 #if defined(HAVE_DEVICE_MAJOR_FN)
378 return (uint32
)major(dev
);
380 return (uint32
)(dev
>> 8);
384 /****************************************************************************
385 Return the minor devicenumber for UNIX extensions.
386 ****************************************************************************/
388 static uint32
unix_dev_minor(SMB_DEV_T dev
)
390 #if defined(HAVE_DEVICE_MINOR_FN)
391 return (uint32
)minor(dev
);
393 return (uint32
)(dev
& 0xff);
397 /****************************************************************************
398 Map wire perms onto standard UNIX permissions. Obey share restrictions.
399 ****************************************************************************/
401 static mode_t
unix_perms_from_wire( connection_struct
*conn
, SMB_STRUCT_STAT
*pst
, uint32 perms
)
405 if (perms
== SMB_MODE_NO_CHANGE
)
408 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
409 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
410 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
411 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
412 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
413 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
414 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
415 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
416 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
418 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
421 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
424 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
427 if (VALID_STAT(*pst
) && S_ISDIR(pst
->st_mode
)) {
428 ret
&= lp_dir_mask(SNUM(conn
));
429 /* Add in force bits */
430 ret
|= lp_force_dir_mode(SNUM(conn
));
432 /* Apply mode mask */
433 ret
&= lp_create_mask(SNUM(conn
));
434 /* Add in force bits */
435 ret
|= lp_force_create_mode(SNUM(conn
));
441 /****************************************************************************
442 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
443 ****************************************************************************/
445 time_t interpret_long_unix_date(char *p
)
447 DEBUG(1,("interpret_long_unix_date\n"));
448 if(IVAL(p
,0) == SMB_TIME_NO_CHANGE_LO
&&
449 IVAL(p
,4) == SMB_TIME_NO_CHANGE_HI
) {
452 return interpret_long_date(p
);
456 /****************************************************************************
457 Get a level dependent lanman2 dir entry.
458 ****************************************************************************/
460 static BOOL
get_lanman2_dir_entry(connection_struct
*conn
,
461 void *inbuf
, void *outbuf
,
462 char *path_mask
,int dirtype
,int info_level
,
463 int requires_resume_key
,
464 BOOL dont_descend
,char **ppdata
,
465 char *base_data
, int space_remaining
,
466 BOOL
*out_of_space
, BOOL
*got_exact_match
,
471 SMB_STRUCT_STAT sbuf
;
475 char *p
, *q
, *pdata
= *ppdata
;
479 SMB_OFF_T file_size
= 0;
480 SMB_BIG_UINT allocation_size
= 0;
482 time_t mdate
=0, adate
=0, cdate
=0;
485 int nt_extmode
; /* Used for NT connections instead of mode */
486 BOOL needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
489 *out_of_space
= False
;
490 *got_exact_match
= False
;
495 p
= strrchr_m(path_mask
,'/');
502 pstrcpy(mask
, path_mask
);
507 /* Needed if we run out of space */
508 prev_dirpos
= TellDir(conn
->dirptr
);
509 dname
= ReadDirName(conn
->dirptr
);
512 * Due to bugs in NT client redirectors we are not using
513 * resume keys any more - set them to zero.
514 * Check out the related comments in findfirst/findnext.
520 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
521 (long)conn
->dirptr
,TellDir(conn
->dirptr
)));
526 pstrcpy(fname
,dname
);
528 if(!(got_match
= *got_exact_match
= exact_match(fname
, mask
, case_sensitive
)))
529 got_match
= mask_match(fname
, mask
, case_sensitive
);
531 if(!got_match
&& !mangle_is_8_3(fname
, False
)) {
534 * It turns out that NT matches wildcards against
535 * both long *and* short names. This may explain some
536 * of the wildcard wierdness from old DOS clients
537 * that some people have been seeing.... JRA.
541 pstrcpy( newname
, fname
);
542 mangle_map( newname
, True
, False
, SNUM(conn
));
543 if(!(got_match
= *got_exact_match
= exact_match(newname
, mask
, case_sensitive
)))
544 got_match
= mask_match(newname
, mask
, case_sensitive
);
548 BOOL isdots
= (strequal(fname
,"..") || strequal(fname
,"."));
549 if (dont_descend
&& !isdots
)
552 pstrcpy(pathreal
,conn
->dirpath
);
554 pstrcat(pathreal
,"/");
555 pstrcat(pathreal
,dname
);
557 if (INFO_LEVEL_IS_UNIX(info_level
)) {
558 if (SMB_VFS_LSTAT(conn
,pathreal
,&sbuf
) != 0) {
559 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
560 pathreal
,strerror(errno
)));
563 } else if (SMB_VFS_STAT(conn
,pathreal
,&sbuf
) != 0) {
565 /* Needed to show the msdfs symlinks as
568 if(lp_host_msdfs() &&
569 lp_msdfs_root(SNUM(conn
)) &&
570 is_msdfs_link(conn
, pathreal
, NULL
, NULL
,
573 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal
));
574 sbuf
.st_mode
= (sbuf
.st_mode
& 0xFFF) | S_IFDIR
;
578 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
579 pathreal
,strerror(errno
)));
584 mode
= dos_mode(conn
,pathreal
,&sbuf
);
586 if (!dir_check_ftype(conn
,mode
,&sbuf
,dirtype
)) {
587 DEBUG(5,("[%s] attribs didn't match %x\n",fname
,dirtype
));
591 file_size
= get_file_size(sbuf
);
592 allocation_size
= get_allocation_size(NULL
,&sbuf
);
593 mdate
= sbuf
.st_mtime
;
594 adate
= sbuf
.st_atime
;
595 cdate
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
597 if (lp_dos_filetime_resolution(SNUM(conn
))) {
606 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal
,fname
));
612 mangle_map(fname
,False
,True
,SNUM(conn
));
617 nt_extmode
= mode
? mode
: FILE_ATTRIBUTE_NORMAL
;
619 switch (info_level
) {
620 case SMB_INFO_STANDARD
:
621 if(requires_resume_key
) {
625 put_dos_date2(p
,l1_fdateCreation
,cdate
);
626 put_dos_date2(p
,l1_fdateLastAccess
,adate
);
627 put_dos_date2(p
,l1_fdateLastWrite
,mdate
);
628 SIVAL(p
,l1_cbFile
,(uint32
)file_size
);
629 SIVAL(p
,l1_cbFileAlloc
,(uint32
)allocation_size
);
630 SSVAL(p
,l1_attrFile
,mode
);
633 p
+= align_string(outbuf
, p
, 0);
634 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
635 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
)
636 SCVAL(nameptr
, -1, len
-2);
638 SCVAL(nameptr
, -1, len
-1);
642 case SMB_INFO_QUERY_EA_SIZE
:
643 if(requires_resume_key
) {
647 put_dos_date2(p
,l2_fdateCreation
,cdate
);
648 put_dos_date2(p
,l2_fdateLastAccess
,adate
);
649 put_dos_date2(p
,l2_fdateLastWrite
,mdate
);
650 SIVAL(p
,l2_cbFile
,(uint32
)file_size
);
651 SIVAL(p
,l2_cbFileAlloc
,(uint32
)allocation_size
);
652 SSVAL(p
,l2_attrFile
,mode
);
653 SIVAL(p
,l2_cbList
,0); /* No extended attributes */
656 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
| STR_NOALIGN
);
657 if (SVAL(outbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
)
658 SCVAL(nameptr
, -1, len
-2);
660 SCVAL(nameptr
, -1, len
-1);
664 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
665 was_8_3
= mangle_is_8_3(fname
, True
);
667 SIVAL(p
,0,reskey
); p
+= 4;
668 put_long_date(p
,cdate
); p
+= 8;
669 put_long_date(p
,adate
); p
+= 8;
670 put_long_date(p
,mdate
); p
+= 8;
671 put_long_date(p
,mdate
); p
+= 8;
672 SOFF_T(p
,0,file_size
);
673 SOFF_T(p
,8,allocation_size
);
675 SIVAL(p
,0,nt_extmode
); p
+= 4;
677 SIVAL(p
,0,0); p
+= 4;
678 /* Clear the short name buffer. This is
679 * IMPORTANT as not doing so will trigger
680 * a Win2k client bug. JRA.
684 pstring mangled_name
;
685 pstrcpy(mangled_name
, fname
);
686 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
687 mangled_name
[12] = 0;
688 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
695 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
698 len
= PTR_DIFF(p
, pdata
);
699 len
= (len
+ 3) & ~3;
704 case SMB_FIND_FILE_DIRECTORY_INFO
:
706 SIVAL(p
,0,reskey
); p
+= 4;
707 put_long_date(p
,cdate
); p
+= 8;
708 put_long_date(p
,adate
); p
+= 8;
709 put_long_date(p
,mdate
); p
+= 8;
710 put_long_date(p
,mdate
); p
+= 8;
711 SOFF_T(p
,0,file_size
);
712 SOFF_T(p
,8,allocation_size
);
714 SIVAL(p
,0,nt_extmode
); p
+= 4;
716 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
719 len
= PTR_DIFF(p
, pdata
);
720 len
= (len
+ 3) & ~3;
725 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
727 SIVAL(p
,0,reskey
); p
+= 4;
728 put_long_date(p
,cdate
); p
+= 8;
729 put_long_date(p
,adate
); p
+= 8;
730 put_long_date(p
,mdate
); p
+= 8;
731 put_long_date(p
,mdate
); p
+= 8;
732 SOFF_T(p
,0,file_size
);
733 SOFF_T(p
,8,allocation_size
);
735 SIVAL(p
,0,nt_extmode
);
738 SIVAL(p
,4,0); /* ea size */
739 len
= srvstr_push(outbuf
, p
+8, fname
, -1, STR_TERMINATE_ASCII
);
743 len
= PTR_DIFF(p
, pdata
);
744 len
= (len
+ 3) & ~3;
749 case SMB_FIND_FILE_NAMES_INFO
:
751 SIVAL(p
,0,reskey
); p
+= 4;
753 /* this must *not* be null terminated or w2k gets in a loop trying to set an
754 acl on a dir (tridge) */
755 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
758 len
= PTR_DIFF(p
, pdata
);
759 len
= (len
+ 3) & ~3;
764 case SMB_FIND_FILE_LEVEL_261
:
766 SIVAL(p
,0,reskey
); p
+= 4;
767 put_long_date(p
,cdate
); p
+= 8;
768 put_long_date(p
,adate
); p
+= 8;
769 put_long_date(p
,mdate
); p
+= 8;
770 put_long_date(p
,mdate
); p
+= 8;
771 SOFF_T(p
,0,file_size
);
772 SOFF_T(p
,8,allocation_size
);
774 SIVAL(p
,0,nt_extmode
);
776 len
= srvstr_push(outbuf
, p
+ 20, fname
, -1, STR_TERMINATE_ASCII
);
778 memset(p
+4,'\0',16); /* EA size. Unknown 0 1 2 */
779 p
+= 20 + len
; /* Strlen, EA size. Unknown 0 1 2, string itself */
780 len
= PTR_DIFF(p
, pdata
);
781 len
= (len
+ 3) & ~3;
786 case SMB_FIND_FILE_LEVEL_262
:
787 was_8_3
= mangle_is_8_3(fname
, True
);
789 SIVAL(p
,0,reskey
); p
+= 4;
790 put_long_date(p
,cdate
); p
+= 8;
791 put_long_date(p
,adate
); p
+= 8;
792 put_long_date(p
,mdate
); p
+= 8;
793 put_long_date(p
,mdate
); p
+= 8;
794 SOFF_T(p
,0,file_size
);
795 SOFF_T(p
,8,allocation_size
);
797 SIVAL(p
,0,nt_extmode
); p
+= 4;
799 SIVAL(p
,0,0); p
+= 4;
800 /* Clear the short name buffer. This is
801 * IMPORTANT as not doing so will trigger
802 * a Win2k client bug. JRA.
806 pstring mangled_name
;
807 pstrcpy(mangled_name
, fname
);
808 mangle_map(mangled_name
,True
,True
,SNUM(conn
));
809 mangled_name
[12] = 0;
810 len
= srvstr_push(outbuf
, p
+2, mangled_name
, 24, STR_UPPER
|STR_UNICODE
);
817 memset(p
, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
819 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE_ASCII
);
822 len
= PTR_DIFF(p
, pdata
);
823 len
= (len
+ 3) & ~3;
828 /* CIFS UNIX Extension. */
830 case SMB_FIND_FILE_UNIX
:
832 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
834 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
835 SOFF_T(p
,0,get_file_size(sbuf
)); /* File size 64 Bit */
838 SOFF_T(p
,0,get_allocation_size(NULL
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
841 put_long_date(p
,sbuf
.st_ctime
); /* Creation Time 64 Bit */
842 put_long_date(p
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
843 put_long_date(p
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
846 SIVAL(p
,0,sbuf
.st_uid
); /* user id for the owner */
850 SIVAL(p
,0,sbuf
.st_gid
); /* group id of owner */
854 SIVAL(p
,0,unix_filetype(sbuf
.st_mode
));
857 SIVAL(p
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
861 SIVAL(p
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
865 SINO_T(p
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
868 SIVAL(p
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
872 SIVAL(p
,0,sbuf
.st_nlink
); /* number of hard links */
876 len
= srvstr_push(outbuf
, p
, fname
, -1, STR_TERMINATE
);
879 len
= PTR_DIFF(p
, pdata
);
880 len
= (len
+ 3) & ~3;
881 SIVAL(pdata
,0,len
); /* Offset from this structure to the beginning of the next one */
883 /* End of SMB_QUERY_FILE_UNIX_BASIC */
892 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
893 /* Move the dirptr back to prev_dirpos */
894 SeekDir(conn
->dirptr
, prev_dirpos
);
895 *out_of_space
= True
;
896 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
897 return False
; /* Not finished - just out of space */
900 /* Setup the last_filename pointer, as an offset from base_data */
901 *last_name_off
= PTR_DIFF(nameptr
,base_data
);
902 /* Advance the data pointer to the next slot */
908 /****************************************************************************
909 Reply to a TRANS2_FINDFIRST.
910 ****************************************************************************/
912 static int call_trans2findfirst(connection_struct
*conn
, char *inbuf
, char *outbuf
, int bufsize
,
913 char **pparams
, int total_params
, char **ppdata
, int total_data
)
915 /* We must be careful here that we don't return more than the
916 allowed number of data bytes. If this means returning fewer than
917 maxentries then so be it. We assume that the redirector has
918 enough room for the fixed number of parameter bytes it has
920 uint32 max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
921 char *params
= *pparams
;
922 char *pdata
= *ppdata
;
923 int dirtype
= SVAL(params
,0);
924 int maxentries
= SVAL(params
,2);
925 BOOL close_after_first
= BITSETW(params
+4,0);
926 BOOL close_if_end
= BITSETW(params
+4,1);
927 BOOL requires_resume_key
= BITSETW(params
+4,2);
928 int info_level
= SVAL(params
,6);
936 BOOL finished
= False
;
937 BOOL dont_descend
= False
;
938 BOOL out_of_space
= False
;
940 BOOL bad_path
= False
;
941 SMB_STRUCT_STAT sbuf
;
943 if (total_params
< 12)
944 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
946 *directory
= *mask
= 0;
948 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
949 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
950 dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
951 info_level
, max_data_bytes
));
953 switch (info_level
) {
954 case SMB_INFO_STANDARD
:
955 case SMB_INFO_QUERY_EA_SIZE
:
956 case SMB_FIND_FILE_DIRECTORY_INFO
:
957 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
958 case SMB_FIND_FILE_NAMES_INFO
:
959 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
960 case SMB_FIND_FILE_LEVEL_261
:
961 case SMB_FIND_FILE_LEVEL_262
:
963 case SMB_FIND_FILE_UNIX
:
964 if (!lp_unix_extensions())
965 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
968 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
971 srvstr_pull(inbuf
, directory
, params
+12, sizeof(directory
), -1, STR_TERMINATE
);
973 RESOLVE_FINDFIRST_DFSPATH(directory
, conn
, inbuf
, outbuf
);
975 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
976 if(!check_name(directory
,conn
)) {
977 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
980 p
= strrchr_m(directory
,'/');
982 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
983 if((directory
[0] == '.') && (directory
[1] == '\0'))
986 pstrcpy(mask
,directory
);
987 pstrcpy(directory
,"./");
993 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
995 pdata
= Realloc(*ppdata
, max_data_bytes
+ 1024);
997 return(ERROR_DOS(ERRDOS
,ERRnomem
));
1000 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1002 /* Realloc the params space */
1003 params
= Realloc(*pparams
, 10);
1005 return ERROR_DOS(ERRDOS
,ERRnomem
);
1008 dptr_num
= dptr_create(conn
,directory
, False
, True
,SVAL(inbuf
,smb_pid
));
1010 return(UNIXERROR(ERRDOS
,ERRbadfile
));
1012 /* Save the wildcard match and attribs we are using on this directory -
1013 needed as lanman2 assumes these are being saved between calls */
1015 if(!(wcard
= strdup(mask
))) {
1016 dptr_close(&dptr_num
);
1017 return ERROR_DOS(ERRDOS
,ERRnomem
);
1020 dptr_set_wcard(dptr_num
, wcard
);
1021 dptr_set_attr(dptr_num
, dirtype
);
1023 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num
, wcard
, dirtype
));
1025 /* We don't need to check for VOL here as this is returned by
1026 a different TRANS2 call. */
1028 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1029 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),case_sensitive
))
1030 dont_descend
= True
;
1033 space_remaining
= max_data_bytes
;
1034 out_of_space
= False
;
1036 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
1037 BOOL got_exact_match
= False
;
1039 /* this is a heuristic to avoid seeking the dirptr except when
1040 absolutely necessary. It allows for a filename of about 40 chars */
1041 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1042 out_of_space
= True
;
1045 finished
= !get_lanman2_dir_entry(conn
,
1047 mask
,dirtype
,info_level
,
1048 requires_resume_key
,dont_descend
,
1049 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1053 if (finished
&& out_of_space
)
1056 if (!finished
&& !out_of_space
)
1060 * As an optimisation if we know we aren't looking
1061 * for a wildcard name (ie. the name matches the wildcard exactly)
1062 * then we can finish on any (first) match.
1063 * This speeds up large directory searches. JRA.
1069 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1072 /* Check if we can close the dirptr */
1073 if(close_after_first
|| (finished
&& close_if_end
)) {
1074 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
1075 dptr_close(&dptr_num
);
1079 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1080 * from observation of NT.
1083 if(numentries
== 0) {
1084 dptr_close(&dptr_num
);
1085 return ERROR_DOS(ERRDOS
,ERRbadfile
);
1088 /* At this point pdata points to numentries directory entries. */
1090 /* Set up the return parameter block */
1091 SSVAL(params
,0,dptr_num
);
1092 SSVAL(params
,2,numentries
);
1093 SSVAL(params
,4,finished
);
1094 SSVAL(params
,6,0); /* Never an EA error */
1095 SSVAL(params
,8,last_name_off
);
1097 send_trans2_replies( outbuf
, bufsize
, params
, 10, pdata
, PTR_DIFF(p
,pdata
));
1099 if ((! *directory
) && dptr_path(dptr_num
))
1100 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1102 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1103 smb_fn_name(CVAL(inbuf
,smb_com
)),
1104 mask
, directory
, dirtype
, numentries
) );
1107 * Force a name mangle here to ensure that the
1108 * mask as an 8.3 name is top of the mangled cache.
1109 * The reasons for this are subtle. Don't remove
1110 * this code unless you know what you are doing
1111 * (see PR#13758). JRA.
1114 if(!mangle_is_8_3_wildcards( mask
, False
))
1115 mangle_map(mask
, True
, True
, SNUM(conn
));
1120 /****************************************************************************
1121 Reply to a TRANS2_FINDNEXT.
1122 ****************************************************************************/
1124 static int call_trans2findnext(connection_struct
*conn
, char *inbuf
, char *outbuf
, int length
, int bufsize
,
1125 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1127 /* We must be careful here that we don't return more than the
1128 allowed number of data bytes. If this means returning fewer than
1129 maxentries then so be it. We assume that the redirector has
1130 enough room for the fixed number of parameter bytes it has
1132 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1133 char *params
= *pparams
;
1134 char *pdata
= *ppdata
;
1135 int dptr_num
= SVAL(params
,0);
1136 int maxentries
= SVAL(params
,2);
1137 uint16 info_level
= SVAL(params
,4);
1138 uint32 resume_key
= IVAL(params
,6);
1139 BOOL close_after_request
= BITSETW(params
+10,0);
1140 BOOL close_if_end
= BITSETW(params
+10,1);
1141 BOOL requires_resume_key
= BITSETW(params
+10,2);
1142 BOOL continue_bit
= BITSETW(params
+10,3);
1143 pstring resume_name
;
1149 int i
, last_name_off
=0;
1150 BOOL finished
= False
;
1151 BOOL dont_descend
= False
;
1152 BOOL out_of_space
= False
;
1153 int space_remaining
;
1155 if (total_params
< 12)
1156 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
1158 *mask
= *directory
= *resume_name
= 0;
1160 srvstr_pull(inbuf
, resume_name
, params
+12, sizeof(resume_name
), -1, STR_TERMINATE
);
1162 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1163 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1164 resume_key = %d resume name = %s continue=%d level = %d\n",
1165 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
1166 requires_resume_key
, resume_key
, resume_name
, continue_bit
, info_level
));
1168 switch (info_level
) {
1169 case SMB_INFO_STANDARD
:
1170 case SMB_INFO_QUERY_EA_SIZE
:
1171 case SMB_FIND_FILE_DIRECTORY_INFO
:
1172 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1173 case SMB_FIND_FILE_NAMES_INFO
:
1174 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1176 case SMB_FIND_FILE_UNIX
:
1177 if (!lp_unix_extensions())
1178 return(ERROR_DOS(ERRDOS
,ERRunknownlevel
));
1181 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1184 pdata
= Realloc( *ppdata
, max_data_bytes
+ 1024);
1186 return ERROR_DOS(ERRDOS
,ERRnomem
);
1189 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1191 /* Realloc the params space */
1192 params
= Realloc(*pparams
, 6*SIZEOFWORD
);
1193 if( params
== NULL
)
1194 return ERROR_DOS(ERRDOS
,ERRnomem
);
1198 /* Check that the dptr is valid */
1199 if(!(conn
->dirptr
= dptr_fetch_lanman2(dptr_num
)))
1200 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1202 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1204 /* Get the wildcard mask from the dptr */
1205 if((p
= dptr_wcard(dptr_num
))== NULL
) {
1206 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
1207 return ERROR_DOS(ERRDOS
,ERRnofiles
);
1211 pstrcpy(directory
,conn
->dirpath
);
1213 /* Get the attr mask from the dptr */
1214 dirtype
= dptr_attr(dptr_num
);
1216 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1217 dptr_num
, mask
, dirtype
,
1219 TellDir(conn
->dirptr
)));
1221 /* We don't need to check for VOL here as this is returned by
1222 a different TRANS2 call. */
1224 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1225 if (in_list(conn
->dirpath
,lp_dontdescend(SNUM(conn
)),case_sensitive
))
1226 dont_descend
= True
;
1229 space_remaining
= max_data_bytes
;
1230 out_of_space
= False
;
1233 * Seek to the correct position. We no longer use the resume key but
1234 * depend on the last file name instead.
1237 if(requires_resume_key
&& *resume_name
&& !continue_bit
) {
1240 * Fix for NT redirector problem triggered by resume key indexes
1241 * changing between directory scans. We now return a resume key of 0
1242 * and instead look for the filename to continue from (also given
1243 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1244 * findfirst/findnext (as is usual) then the directory pointer
1245 * should already be at the correct place. Check this by scanning
1246 * backwards looking for an exact (ie. case sensitive) filename match.
1247 * If we get to the beginning of the directory and haven't found it then scan
1248 * forwards again looking for a match. JRA.
1251 int current_pos
, start_pos
;
1252 const char *dname
= NULL
;
1253 pstring dname_pstring
;
1254 void *dirptr
= conn
->dirptr
;
1255 start_pos
= TellDir(dirptr
);
1256 for(current_pos
= start_pos
; current_pos
>= 0; current_pos
--) {
1257 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos
));
1259 SeekDir(dirptr
, current_pos
);
1260 dname
= ReadDirName(dirptr
);
1263 * Remember, mangle_map is called by
1264 * get_lanman2_dir_entry(), so the resume name
1265 * could be mangled. Ensure we do the same
1269 /* make sure we get a copy that mangle_map can modify */
1271 pstrcpy(dname_pstring
, dname
);
1272 mangle_map( dname_pstring
, False
, True
, SNUM(conn
));
1274 if(strcsequal( resume_name
, dname_pstring
)) {
1275 SeekDir(dirptr
, current_pos
+1);
1276 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos
+1 ));
1283 * Scan forward from start if not found going backwards.
1286 if(current_pos
< 0) {
1287 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos
));
1288 SeekDir(dirptr
, start_pos
);
1289 for(current_pos
= start_pos
; (dname
= ReadDirName(dirptr
)) != NULL
; SeekDir(dirptr
,++current_pos
)) {
1292 * Remember, mangle_map is called by
1293 * get_lanman2_dir_entry(), so the resume name
1294 * could be mangled. Ensure we do the same
1299 /* make sure we get a copy that mangle_map can modify */
1301 pstrcpy(dname_pstring
, dname
);
1302 mangle_map(dname_pstring
, False
, True
, SNUM(conn
));
1304 if(strcsequal( resume_name
, dname_pstring
)) {
1305 SeekDir(dirptr
, current_pos
+1);
1306 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos
+1 ));
1311 } /* end if current_pos */
1312 } /* end if requires_resume_key && !continue_bit */
1314 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
1315 BOOL got_exact_match
= False
;
1317 /* this is a heuristic to avoid seeking the dirptr except when
1318 absolutely necessary. It allows for a filename of about 40 chars */
1319 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
1320 out_of_space
= True
;
1323 finished
= !get_lanman2_dir_entry(conn
,
1325 mask
,dirtype
,info_level
,
1326 requires_resume_key
,dont_descend
,
1327 &p
,pdata
,space_remaining
, &out_of_space
, &got_exact_match
,
1331 if (finished
&& out_of_space
)
1334 if (!finished
&& !out_of_space
)
1338 * As an optimisation if we know we aren't looking
1339 * for a wildcard name (ie. the name matches the wildcard exactly)
1340 * then we can finish on any (first) match.
1341 * This speeds up large directory searches. JRA.
1347 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
1350 /* Check if we can close the dirptr */
1351 if(close_after_request
|| (finished
&& close_if_end
)) {
1352 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
1353 dptr_close(&dptr_num
); /* This frees up the saved mask */
1356 /* Set up the return parameter block */
1357 SSVAL(params
,0,numentries
);
1358 SSVAL(params
,2,finished
);
1359 SSVAL(params
,4,0); /* Never an EA error */
1360 SSVAL(params
,6,last_name_off
);
1362 send_trans2_replies( outbuf
, bufsize
, params
, 8, pdata
, PTR_DIFF(p
,pdata
));
1364 if ((! *directory
) && dptr_path(dptr_num
))
1365 slprintf(directory
,sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1367 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1368 smb_fn_name(CVAL(inbuf
,smb_com
)),
1369 mask
, directory
, dirtype
, numentries
) );
1374 /****************************************************************************
1375 Reply to a TRANS2_QFSINFO (query filesystem info).
1376 ****************************************************************************/
1378 static int call_trans2qfsinfo(connection_struct
*conn
, char *inbuf
, char *outbuf
,
1379 int length
, int bufsize
,
1380 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1382 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1383 char *pdata
= *ppdata
;
1384 char *params
= *pparams
;
1385 uint16 info_level
= SVAL(params
,0);
1388 char *vname
= volume_label(SNUM(conn
));
1389 int snum
= SNUM(conn
);
1390 char *fstype
= lp_fstype(SNUM(conn
));
1393 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
1395 if(SMB_VFS_STAT(conn
,".",&st
)!=0) {
1396 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
1397 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
1400 pdata
= Realloc(*ppdata
, max_data_bytes
+ 1024);
1401 if ( pdata
== NULL
)
1402 return ERROR_DOS(ERRDOS
,ERRnomem
);
1405 memset((char *)pdata
,'\0',max_data_bytes
+ 1024);
1407 switch (info_level
) {
1408 case SMB_INFO_ALLOCATION
:
1410 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1412 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1413 block_size
= lp_block_size(snum
);
1414 if (bsize
< block_size
) {
1415 SMB_BIG_UINT factor
= block_size
/bsize
;
1420 if (bsize
> block_size
) {
1421 SMB_BIG_UINT factor
= bsize
/block_size
;
1426 bytes_per_sector
= 512;
1427 sectors_per_unit
= bsize
/bytes_per_sector
;
1429 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1430 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1431 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1433 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
1434 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
1435 SIVAL(pdata
,l1_cUnit
,dsize
);
1436 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
1437 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
1441 case SMB_INFO_VOLUME
:
1442 /* Return volume name */
1444 * Add volume serial number - hash of a combination of
1445 * the called hostname and the service name.
1447 SIVAL(pdata
,0,str_checksum(lp_servicename(snum
)) ^ (str_checksum(local_machine
)<<16) );
1448 len
= srvstr_push(outbuf
, pdata
+l2_vol_szVolLabel
, vname
, -1, STR_NOALIGN
);
1449 SCVAL(pdata
,l2_vol_cch
,len
);
1450 data_len
= l2_vol_szVolLabel
+ len
;
1451 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1452 (unsigned)st
.st_ctime
, len
, vname
));
1455 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
1456 case SMB_FS_ATTRIBUTE_INFORMATION
:
1459 #if defined(HAVE_SYS_QUOTAS)
1460 quota_flag
= FILE_VOLUME_QUOTAS
;
1463 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
1464 (lp_nt_acl_support(SNUM(conn
)) ? FILE_PERSISTENT_ACLS
: 0)|
1465 quota_flag
); /* FS ATTRIBUTES */
1467 SIVAL(pdata
,4,255); /* Max filename component length */
1468 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1469 and will think we can't do long filenames */
1470 len
= srvstr_push(outbuf
, pdata
+12, fstype
, -1, STR_UNICODE
);
1472 data_len
= 12 + len
;
1475 case SMB_QUERY_FS_LABEL_INFO
:
1476 case SMB_FS_LABEL_INFORMATION
:
1477 len
= srvstr_push(outbuf
, pdata
+4, vname
, -1, 0);
1482 case SMB_QUERY_FS_VOLUME_INFO
:
1483 case SMB_FS_VOLUME_INFORMATION
:
1486 * Add volume serial number - hash of a combination of
1487 * the called hostname and the service name.
1489 SIVAL(pdata
,8,str_checksum(lp_servicename(snum
)) ^
1490 (str_checksum(local_machine
)<<16));
1492 len
= srvstr_push(outbuf
, pdata
+18, vname
, -1, STR_UNICODE
);
1493 SIVAL(pdata
,12,len
);
1495 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1496 (int)strlen(vname
),vname
, lp_servicename(snum
)));
1499 case SMB_QUERY_FS_SIZE_INFO
:
1500 case SMB_FS_SIZE_INFORMATION
:
1502 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1504 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1505 block_size
= lp_block_size(snum
);
1506 if (bsize
< block_size
) {
1507 SMB_BIG_UINT factor
= block_size
/bsize
;
1512 if (bsize
> block_size
) {
1513 SMB_BIG_UINT factor
= bsize
/block_size
;
1518 bytes_per_sector
= 512;
1519 sectors_per_unit
= bsize
/bytes_per_sector
;
1520 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1521 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1522 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1523 SBIG_UINT(pdata
,0,dsize
);
1524 SBIG_UINT(pdata
,8,dfree
);
1525 SIVAL(pdata
,16,sectors_per_unit
);
1526 SIVAL(pdata
,20,bytes_per_sector
);
1530 case SMB_FS_FULL_SIZE_INFORMATION
:
1532 SMB_BIG_UINT dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
1534 SMB_VFS_DISK_FREE(conn
,".",False
,&bsize
,&dfree
,&dsize
);
1535 block_size
= lp_block_size(snum
);
1536 if (bsize
< block_size
) {
1537 SMB_BIG_UINT factor
= block_size
/bsize
;
1542 if (bsize
> block_size
) {
1543 SMB_BIG_UINT factor
= bsize
/block_size
;
1548 bytes_per_sector
= 512;
1549 sectors_per_unit
= bsize
/bytes_per_sector
;
1550 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1551 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
1552 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
1553 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
1554 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
1555 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
1556 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
1557 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
1561 case SMB_QUERY_FS_DEVICE_INFO
:
1562 case SMB_FS_DEVICE_INFORMATION
:
1564 SIVAL(pdata
,0,0); /* dev type */
1565 SIVAL(pdata
,4,0); /* characteristics */
1568 #ifdef HAVE_SYS_QUOTAS
1569 case SMB_FS_QUOTA_INFORMATION
:
1571 * what we have to send --metze:
1573 * Unknown1: 24 NULL bytes
1574 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1575 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1576 * Quota Flags: 2 byte :
1577 * Unknown3: 6 NULL bytes
1581 * details for Quota Flags:
1583 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1584 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1585 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1586 * 0x0001 Enable Quotas: enable quota for this fs
1590 /* we need to fake up a fsp here,
1591 * because its not send in this call
1594 SMB_NTQUOTA_STRUCT quotas
;
1597 ZERO_STRUCT(quotas
);
1604 if (conn
->admin_user
!= True
) {
1605 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1606 lp_servicename(SNUM(conn
)),conn
->user
));
1607 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1610 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
1611 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
1612 return ERROR_DOS(ERRSRV
,ERRerror
);
1617 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn
))));
1619 /* Unknown1 24 NULL bytes*/
1620 SBIG_UINT(pdata
,0,(SMB_BIG_UINT
)0);
1621 SBIG_UINT(pdata
,8,(SMB_BIG_UINT
)0);
1622 SBIG_UINT(pdata
,16,(SMB_BIG_UINT
)0);
1624 /* Default Soft Quota 8 bytes */
1625 SBIG_UINT(pdata
,24,quotas
.softlim
);
1627 /* Default Hard Quota 8 bytes */
1628 SBIG_UINT(pdata
,32,quotas
.hardlim
);
1630 /* Quota flag 2 bytes */
1631 SSVAL(pdata
,40,quotas
.qflags
);
1633 /* Unknown3 6 NULL bytes */
1639 #endif /* HAVE_SYS_QUOTAS */
1640 case SMB_FS_OBJECTID_INFORMATION
:
1645 * Query the version and capabilities of the CIFS UNIX extensions
1649 case SMB_QUERY_CIFS_UNIX_INFO
:
1650 if (!lp_unix_extensions())
1651 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1653 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
1654 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
1655 SBIG_UINT(pdata
,4,((SMB_BIG_UINT
)0)); /* No capabilities for now... */
1658 case SMB_MAC_QUERY_FS_INFO
:
1660 * Thursby MAC extension... ONLY on NTFS filesystems
1661 * once we do streams then we don't need this
1663 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
1665 SIVAL(pdata
,84,0x100); /* Don't support mac... */
1670 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1674 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
);
1676 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf
,smb_com
)), info_level
) );
1681 #ifdef HAVE_SYS_QUOTAS
1682 /****************************************************************************
1683 Reply to a TRANS2_SETFSINFO (set filesystem info).
1684 ****************************************************************************/
1686 static int call_trans2setfsinfo(connection_struct
*conn
,
1687 char *inbuf
, char *outbuf
, int length
, int bufsize
,
1688 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1690 char *pdata
= *ppdata
;
1691 char *params
= *pparams
;
1692 files_struct
*fsp
= NULL
;
1695 SMB_NTQUOTA_STRUCT quotas
;
1697 ZERO_STRUCT(quotas
);
1699 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn
))));
1702 if ((conn
->admin_user
!= True
)||!CAN_WRITE(conn
)) {
1703 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1704 lp_servicename(SNUM(conn
)),conn
->user
));
1705 return ERROR_DOS(ERRSRV
,ERRaccess
);
1709 if (total_params
< 4) {
1710 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1712 return ERROR_DOS(ERRDOS
,ERRinvalidparam
);
1715 fsp
= file_fsp(params
,0);
1717 if (!CHECK_NTQUOTA_HANDLE_OK(fsp
,conn
)) {
1718 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1719 return ERROR_NT(NT_STATUS_INVALID_HANDLE
);
1722 info_level
= SVAL(params
,2);
1724 switch(info_level
) {
1725 case SMB_FS_QUOTA_INFORMATION
:
1726 /* note: normaly there're 48 bytes,
1727 * but we didn't use the last 6 bytes for now
1730 if (total_data
< 42) {
1731 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1733 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1736 /* unknown_1 24 NULL bytes in pdata*/
1738 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1739 quotas
.softlim
= (SMB_BIG_UINT
)IVAL(pdata
,24);
1740 #ifdef LARGE_SMB_OFF_T
1741 quotas
.softlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,28)) << 32);
1742 #else /* LARGE_SMB_OFF_T */
1743 if ((IVAL(pdata
,28) != 0)&&
1744 ((quotas
.softlim
!= 0xFFFFFFFF)||
1745 (IVAL(pdata
,28)!=0xFFFFFFFF))) {
1746 /* more than 32 bits? */
1747 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1749 #endif /* LARGE_SMB_OFF_T */
1751 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1752 quotas
.hardlim
= (SMB_BIG_UINT
)IVAL(pdata
,32);
1753 #ifdef LARGE_SMB_OFF_T
1754 quotas
.hardlim
|= (((SMB_BIG_UINT
)IVAL(pdata
,36)) << 32);
1755 #else /* LARGE_SMB_OFF_T */
1756 if ((IVAL(pdata
,36) != 0)&&
1757 ((quotas
.hardlim
!= 0xFFFFFFFF)||
1758 (IVAL(pdata
,36)!=0xFFFFFFFF))) {
1759 /* more than 32 bits? */
1760 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1762 #endif /* LARGE_SMB_OFF_T */
1764 /* quota_flags 2 bytes **/
1765 quotas
.qflags
= SVAL(pdata
,40);
1767 /* unknown_2 6 NULL bytes follow*/
1769 /* now set the quotas */
1770 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
1771 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn
))));
1772 return ERROR_DOS(ERRSRV
,ERRerror
);
1777 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1779 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1784 * sending this reply works fine,
1785 * but I'm not sure it's the same
1786 * like windows do...
1789 outsize
= set_message(outbuf
,10,0,True
);
1793 #endif /* HAVE_SYS_QUOTAS */
1795 /****************************************************************************
1796 * Utility function to set bad path error.
1797 ****************************************************************************/
1799 int set_bad_path_error(int err
, BOOL bad_path
, char *outbuf
, int def_class
, uint32 def_code
)
1801 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
1802 err
, (int)bad_path
));
1806 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
1808 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1811 return UNIXERROR(def_class
,def_code
);
1814 /****************************************************************************
1815 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1816 file name or file id).
1817 ****************************************************************************/
1819 static int call_trans2qfilepathinfo(connection_struct
*conn
,
1820 char *inbuf
, char *outbuf
, int length
,
1822 char **pparams
, int total_params
, char **ppdata
, int total_data
)
1824 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
1825 char *params
= *pparams
;
1826 char *pdata
= *ppdata
;
1827 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
1830 SMB_OFF_T file_size
=0;
1831 SMB_BIG_UINT allocation_size
=0;
1832 unsigned int data_size
;
1833 SMB_STRUCT_STAT sbuf
;
1834 pstring fname
, dos_fname
;
1839 BOOL bad_path
= False
;
1840 BOOL delete_pending
= False
;
1843 files_struct
*fsp
= NULL
;
1846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1848 if (tran_call
== TRANSACT2_QFILEINFO
) {
1849 if (total_params
< 4)
1850 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
1852 fsp
= file_fsp(params
,0);
1853 info_level
= SVAL(params
,2);
1855 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
1857 if(fsp
&& (fsp
->fake_file_handle
)) {
1859 * This is actually for the QUOTA_FAKE_FILE --metze
1862 pstrcpy(fname
, fsp
->fsp_name
);
1863 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1864 if (!check_name(fname
,conn
)) {
1865 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname
,strerror(errno
)));
1866 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1869 } else if(fsp
&& (fsp
->is_directory
|| fsp
->fd
== -1)) {
1871 * This is actually a QFILEINFO on a directory
1872 * handle (returned from an NT SMB). NT5.0 seems
1873 * to do this call. JRA.
1875 pstrcpy(fname
, fsp
->fsp_name
);
1876 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1877 if (!check_name(fname
,conn
)) {
1878 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
1879 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1882 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1883 /* Always do lstat for UNIX calls. */
1884 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
1885 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
1886 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1888 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
1889 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
1890 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1893 delete_pending
= fsp
->directory_delete_on_close
;
1896 * Original code - this is an open file.
1898 CHECK_FSP(fsp
,conn
);
1900 pstrcpy(fname
, fsp
->fsp_name
);
1901 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&sbuf
) != 0) {
1902 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp
->fnum
, strerror(errno
)));
1903 return(UNIXERROR(ERRDOS
,ERRbadfid
));
1905 pos
= fsp
->position_information
;
1906 delete_pending
= fsp
->delete_on_close
;
1910 if (total_params
< 6)
1911 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
1913 info_level
= SVAL(params
,0);
1915 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
1917 srvstr_pull(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
);
1919 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1921 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1922 if (!check_name(fname
,conn
)) {
1923 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
1924 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1927 if (INFO_LEVEL_IS_UNIX(info_level
)) {
1928 /* Always do lstat for UNIX calls. */
1929 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
)) {
1930 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname
,strerror(errno
)));
1931 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1933 } else if (!VALID_STAT(sbuf
) && SMB_VFS_STAT(conn
,fname
,&sbuf
)) {
1934 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname
,strerror(errno
)));
1935 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
1939 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
1940 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
1942 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
1943 fname
,fsp
? fsp
->fnum
: -1, info_level
,tran_call
,total_data
));
1945 p
= strrchr_m(fname
,'/');
1951 mode
= dos_mode(conn
,fname
,&sbuf
);
1953 mode
= FILE_ATTRIBUTE_NORMAL
;
1955 fullpathname
= fname
;
1956 file_size
= get_file_size(sbuf
);
1957 allocation_size
= get_allocation_size(fsp
,&sbuf
);
1961 params
= Realloc(*pparams
,2);
1963 return ERROR_DOS(ERRDOS
,ERRnomem
);
1965 memset((char *)params
,'\0',2);
1966 data_size
= max_data_bytes
+ 1024;
1967 pdata
= Realloc(*ppdata
, data_size
);
1968 if ( pdata
== NULL
)
1969 return ERROR_DOS(ERRDOS
,ERRnomem
);
1972 if (total_data
> 0 && IVAL(pdata
,0) == total_data
) {
1973 /* uggh, EAs for OS2 */
1974 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data
));
1975 return ERROR_DOS(ERRDOS
,ERReasnotsupported
);
1978 memset((char *)pdata
,'\0',data_size
);
1980 c_time
= get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
)));
1982 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1984 sbuf
.st_atime
&= ~1;
1985 sbuf
.st_mtime
&= ~1;
1986 sbuf
.st_mtime
&= ~1;
1989 /* NT expects the name to be in an exact form of the *full*
1990 filename. See the trans2 torture test */
1991 if (strequal(base_name
,".")) {
1992 pstrcpy(dos_fname
, "\\");
1994 pstr_sprintf(dos_fname
, "\\%s", fname
);
1995 string_replace(dos_fname
, '/', '\\');
1998 switch (info_level
) {
1999 case SMB_INFO_STANDARD
:
2000 case SMB_INFO_QUERY_EA_SIZE
:
2001 data_size
= (info_level
==1?22:26);
2002 put_dos_date2(pdata
,l1_fdateCreation
,c_time
);
2003 put_dos_date2(pdata
,l1_fdateLastAccess
,sbuf
.st_atime
);
2004 put_dos_date2(pdata
,l1_fdateLastWrite
,sbuf
.st_mtime
); /* write time */
2005 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
2006 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
2007 SSVAL(pdata
,l1_attrFile
,mode
);
2008 SIVAL(pdata
,l1_attrFile
+2,0); /* this is what win2003 does */
2011 case SMB_INFO_IS_NAME_VALID
:
2012 if (tran_call
== TRANSACT2_QFILEINFO
) {
2013 /* os/2 needs this ? really ?*/
2014 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
2019 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2021 put_dos_date2(pdata
,0,c_time
);
2022 put_dos_date2(pdata
,4,sbuf
.st_atime
);
2023 put_dos_date2(pdata
,8,sbuf
.st_mtime
);
2024 SIVAL(pdata
,12,(uint32
)file_size
);
2025 SIVAL(pdata
,16,(uint32
)allocation_size
);
2026 SIVAL(pdata
,20,mode
);
2029 case SMB_INFO_QUERY_ALL_EAS
:
2031 SIVAL(pdata
,0,0); /* ea size */
2034 case SMB_FILE_BASIC_INFORMATION
:
2035 case SMB_QUERY_FILE_BASIC_INFO
:
2037 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
)
2038 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
2043 put_long_date(pdata
,c_time
);
2044 put_long_date(pdata
+8,sbuf
.st_atime
);
2045 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2046 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2047 SIVAL(pdata
,32,mode
);
2049 DEBUG(5,("SMB_QFBI - "));
2051 time_t create_time
= c_time
;
2052 DEBUG(5,("create: %s ", ctime(&create_time
)));
2054 DEBUG(5,("access: %s ", ctime(&sbuf
.st_atime
)));
2055 DEBUG(5,("write: %s ", ctime(&sbuf
.st_mtime
)));
2056 DEBUG(5,("change: %s ", ctime(&sbuf
.st_mtime
)));
2057 DEBUG(5,("mode: %x\n", mode
));
2061 case SMB_FILE_STANDARD_INFORMATION
:
2062 case SMB_QUERY_FILE_STANDARD_INFO
:
2065 SOFF_T(pdata
,0,allocation_size
);
2066 SOFF_T(pdata
,8,file_size
);
2067 if (delete_pending
& sbuf
.st_nlink
)
2068 SIVAL(pdata
,16,sbuf
.st_nlink
- 1);
2070 SIVAL(pdata
,16,sbuf
.st_nlink
);
2072 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
2075 case SMB_FILE_EA_INFORMATION
:
2076 case SMB_QUERY_FILE_EA_INFO
:
2080 /* Get the 8.3 name - used if NT SMB was negotiated. */
2081 case SMB_QUERY_FILE_ALT_NAME_INFO
:
2082 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
2086 pstrcpy(short_name
,base_name
);
2087 /* Mangle if not already 8.3 */
2088 if(!mangle_is_8_3(short_name
, True
)) {
2089 mangle_map(short_name
,True
,True
,SNUM(conn
));
2091 len
= srvstr_push(outbuf
, pdata
+4, short_name
, -1, STR_UNICODE
);
2092 data_size
= 4 + len
;
2097 case SMB_QUERY_FILE_NAME_INFO
:
2099 this must be *exactly* right for ACLs on mapped drives to work
2101 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
2102 data_size
= 4 + len
;
2106 case SMB_FILE_ALLOCATION_INFORMATION
:
2107 case SMB_QUERY_FILE_ALLOCATION_INFO
:
2109 SOFF_T(pdata
,0,allocation_size
);
2112 case SMB_FILE_END_OF_FILE_INFORMATION
:
2113 case SMB_QUERY_FILE_END_OF_FILEINFO
:
2115 SOFF_T(pdata
,0,file_size
);
2118 case SMB_QUERY_FILE_ALL_INFO
:
2119 case SMB_FILE_ALL_INFORMATION
:
2120 put_long_date(pdata
,c_time
);
2121 put_long_date(pdata
+8,sbuf
.st_atime
);
2122 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2123 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2124 SIVAL(pdata
,32,mode
);
2126 SOFF_T(pdata
,0,allocation_size
);
2127 SOFF_T(pdata
,8,file_size
);
2128 if (delete_pending
&& sbuf
.st_nlink
)
2129 SIVAL(pdata
,16,sbuf
.st_nlink
- 1);
2131 SIVAL(pdata
,16,sbuf
.st_nlink
);
2132 SCVAL(pdata
,20,delete_pending
);
2133 SCVAL(pdata
,21,(mode
&aDIR
)?1:0);
2135 pdata
+= 4; /* EA info */
2136 len
= srvstr_push(outbuf
, pdata
+4, dos_fname
, -1, STR_UNICODE
);
2139 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2142 case SMB_FILE_INTERNAL_INFORMATION
:
2143 /* This should be an index number - looks like
2146 I think this causes us to fail the IFSKIT
2147 BasicFileInformationTest. -tpot */
2149 SIVAL(pdata
,0,sbuf
.st_dev
);
2150 SIVAL(pdata
,4,sbuf
.st_ino
);
2154 case SMB_FILE_ACCESS_INFORMATION
:
2155 SIVAL(pdata
,0,0x12019F); /* ??? */
2159 case SMB_FILE_NAME_INFORMATION
:
2160 /* Pathname with leading '\'. */
2163 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,max_data_bytes
,False
);
2164 SIVAL(pdata
,0,byte_len
);
2165 data_size
= 4 + byte_len
;
2169 case SMB_FILE_DISPOSITION_INFORMATION
:
2171 SCVAL(pdata
,0,delete_pending
);
2174 case SMB_FILE_POSITION_INFORMATION
:
2176 SOFF_T(pdata
,0,pos
);
2179 case SMB_FILE_MODE_INFORMATION
:
2180 SIVAL(pdata
,0,mode
);
2184 case SMB_FILE_ALIGNMENT_INFORMATION
:
2185 SIVAL(pdata
,0,0); /* No alignment needed. */
2191 * NT4 server just returns "invalid query" to this - if we try to answer
2192 * it then NTws gets a BSOD! (tridge).
2193 * W2K seems to want this. JRA.
2195 case SMB_QUERY_FILE_STREAM_INFO
:
2197 case SMB_FILE_STREAM_INFORMATION
:
2201 size_t byte_len
= dos_PutUniCode(pdata
+24,"::$DATA", 0xE, False
);
2202 SIVAL(pdata
,0,0); /* ??? */
2203 SIVAL(pdata
,4,byte_len
); /* Byte length of unicode string ::$DATA */
2204 SOFF_T(pdata
,8,file_size
);
2205 SIVAL(pdata
,16,allocation_size
);
2206 SIVAL(pdata
,20,0); /* ??? */
2207 data_size
= 24 + byte_len
;
2211 case SMB_QUERY_COMPRESSION_INFO
:
2212 case SMB_FILE_COMPRESSION_INFORMATION
:
2213 SOFF_T(pdata
,0,file_size
);
2214 SIVAL(pdata
,8,0); /* ??? */
2215 SIVAL(pdata
,12,0); /* ??? */
2219 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
2220 put_long_date(pdata
,c_time
);
2221 put_long_date(pdata
+8,sbuf
.st_atime
);
2222 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
2223 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
2224 SIVAL(pdata
,32,allocation_size
);
2225 SOFF_T(pdata
,40,file_size
);
2226 SIVAL(pdata
,48,mode
);
2227 SIVAL(pdata
,52,0); /* ??? */
2231 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
2232 SIVAL(pdata
,0,mode
);
2238 * CIFS UNIX Extensions.
2241 case SMB_QUERY_FILE_UNIX_BASIC
:
2243 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf
.st_mode
));
2245 SOFF_T(pdata
,0,get_file_size(sbuf
)); /* File size 64 Bit */
2248 SOFF_T(pdata
,0,get_allocation_size(fsp
,&sbuf
)); /* Number of bytes used on disk - 64 Bit */
2251 put_long_date(pdata
,sbuf
.st_ctime
); /* Creation Time 64 Bit */
2252 put_long_date(pdata
+8,sbuf
.st_atime
); /* Last access time 64 Bit */
2253 put_long_date(pdata
+16,sbuf
.st_mtime
); /* Last modification time 64 Bit */
2256 SIVAL(pdata
,0,sbuf
.st_uid
); /* user id for the owner */
2260 SIVAL(pdata
,0,sbuf
.st_gid
); /* group id of owner */
2264 SIVAL(pdata
,0,unix_filetype(sbuf
.st_mode
));
2267 SIVAL(pdata
,0,unix_dev_major(sbuf
.st_rdev
)); /* Major device number if type is device */
2271 SIVAL(pdata
,0,unix_dev_minor(sbuf
.st_rdev
)); /* Minor device number if type is device */
2275 SINO_T(pdata
,0,(SMB_INO_T
)sbuf
.st_ino
); /* inode number */
2278 SIVAL(pdata
,0, unix_perms_to_wire(sbuf
.st_mode
)); /* Standard UNIX file permissions */
2282 SIVAL(pdata
,0,sbuf
.st_nlink
); /* number of hard links */
2285 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2289 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2291 for (i
=0; i
<100; i
++)
2292 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
2298 case SMB_QUERY_FILE_UNIX_LINK
:
2303 if(!S_ISLNK(sbuf
.st_mode
))
2304 return(UNIXERROR(ERRSRV
,ERRbadlink
));
2306 return(UNIXERROR(ERRDOS
,ERRbadlink
));
2308 len
= SMB_VFS_READLINK(conn
,fullpathname
, buffer
, sizeof(pstring
)-1); /* read link */
2310 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2312 len
= srvstr_push(outbuf
, pdata
, buffer
, -1, STR_TERMINATE
);
2314 data_size
= PTR_DIFF(pdata
,(*ppdata
));
2320 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2323 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, data_size
);
2328 /****************************************************************************
2329 Deal with the internal needs of setting the delete on close flag. Note that
2330 as the tdb locking is recursive, it is safe to call this from within
2331 open_file_shared. JRA.
2332 ****************************************************************************/
2334 NTSTATUS
set_delete_on_close_internal(files_struct
*fsp
, BOOL delete_on_close
)
2337 * Only allow delete on close for writable shares.
2340 if (delete_on_close
&& !CAN_WRITE(fsp
->conn
)) {
2341 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2343 return NT_STATUS_ACCESS_DENIED
;
2346 * Only allow delete on close for files/directories opened with delete intent.
2349 if (delete_on_close
&& !(fsp
->desired_access
& DELETE_ACCESS
)) {
2350 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2352 return NT_STATUS_ACCESS_DENIED
;
2355 if(fsp
->is_directory
) {
2356 fsp
->directory_delete_on_close
= delete_on_close
;
2357 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2358 delete_on_close
? "Added" : "Removed", fsp
->fnum
, fsp
->fsp_name
));
2360 fsp
->delete_on_close
= delete_on_close
;
2361 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2362 delete_on_close
? "Added" : "Removed", fsp
->fnum
, fsp
->fsp_name
));
2365 return NT_STATUS_OK
;
2368 /****************************************************************************
2369 Sets the delete on close flag over all share modes on this file.
2370 Modify the share mode entry for all files open
2371 on this device and inode to tell other smbds we have
2372 changed the delete on close flag. This will be noticed
2373 in the close code, the last closer will delete the file
2375 ****************************************************************************/
2377 NTSTATUS
set_delete_on_close_over_all(files_struct
*fsp
, BOOL delete_on_close
)
2379 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2380 delete_on_close
? "Adding" : "Removing", fsp
->fnum
, fsp
->fsp_name
));
2382 if (fsp
->is_directory
|| fsp
->is_stat
)
2383 return NT_STATUS_OK
;
2385 if (lock_share_entry_fsp(fsp
) == False
)
2386 return NT_STATUS_ACCESS_DENIED
;
2388 if (!modify_delete_flag(fsp
->dev
, fsp
->inode
, delete_on_close
)) {
2389 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2391 unlock_share_entry_fsp(fsp
);
2392 return NT_STATUS_ACCESS_DENIED
;
2395 unlock_share_entry_fsp(fsp
);
2396 return NT_STATUS_OK
;
2399 /****************************************************************************
2400 Returns true if this pathname is within the share, and thus safe.
2401 ****************************************************************************/
2403 static int ensure_link_is_safe(connection_struct
*conn
, const char *link_dest_in
, char *link_dest_out
)
2406 char resolved_name
[PATH_MAX
+1];
2408 pstring resolved_name
;
2410 fstring last_component
;
2414 BOOL bad_path
= False
;
2415 SMB_STRUCT_STAT sbuf
;
2417 pstrcpy(link_dest
, link_dest_in
);
2418 unix_convert(link_dest
,conn
,0,&bad_path
,&sbuf
);
2420 /* Store the UNIX converted path. */
2421 pstrcpy(link_dest_out
, link_dest
);
2423 p
= strrchr(link_dest
, '/');
2425 fstrcpy(last_component
, p
+1);
2428 fstrcpy(last_component
, link_dest
);
2429 pstrcpy(link_dest
, "./");
2432 if (SMB_VFS_REALPATH(conn
,link_dest
,resolved_name
) == NULL
)
2435 pstrcpy(link_dest
, resolved_name
);
2436 pstrcat(link_dest
, "/");
2437 pstrcat(link_dest
, last_component
);
2439 if (*link_dest
!= '/') {
2440 /* Relative path. */
2441 pstrcpy(link_test
, conn
->connectpath
);
2442 pstrcat(link_test
, "/");
2443 pstrcat(link_test
, link_dest
);
2445 pstrcpy(link_test
, link_dest
);
2449 * Check if the link is within the share.
2452 if (strncmp(conn
->connectpath
, link_test
, strlen(conn
->connectpath
))) {
2459 /****************************************************************************
2460 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2461 ****************************************************************************/
2463 static int call_trans2setfilepathinfo(connection_struct
*conn
,
2464 char *inbuf
, char *outbuf
, int length
, int bufsize
,
2465 char **pparams
, int total_params
, char **ppdata
, int total_data
)
2467 char *params
= *pparams
;
2468 char *pdata
= *ppdata
;
2469 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
2474 SMB_STRUCT_STAT sbuf
;
2477 BOOL bad_path
= False
;
2478 files_struct
*fsp
= NULL
;
2479 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
2480 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
2481 mode_t unixmode
= 0;
2484 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2486 if (tran_call
== TRANSACT2_SETFILEINFO
) {
2487 if (total_params
< 4)
2488 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2490 fsp
= file_fsp(params
,0);
2491 info_level
= SVAL(params
,2);
2493 if(fsp
&& (fsp
->is_directory
|| fsp
->fd
== -1)) {
2495 * This is actually a SETFILEINFO on a directory
2496 * handle (returned from an NT SMB). NT5.0 seems
2497 * to do this call. JRA.
2499 pstrcpy(fname
, fsp
->fsp_name
);
2500 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2501 if (!check_name(fname
,conn
) || (!VALID_STAT(sbuf
))) {
2502 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
2503 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2505 } else if (fsp
&& fsp
->print_file
) {
2507 * Doing a DELETE_ON_CLOSE should cancel a print job.
2509 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
2510 fsp
->share_mode
= FILE_DELETE_ON_CLOSE
;
2512 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp
->fsp_name
));
2515 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
2518 return (UNIXERROR(ERRDOS
,ERRbadpath
));
2521 * Original code - this is an open file.
2523 CHECK_FSP(fsp
,conn
);
2525 pstrcpy(fname
, fsp
->fsp_name
);
2528 if (SMB_VFS_FSTAT(fsp
,fd
,&sbuf
) != 0) {
2529 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp
->fnum
, strerror(errno
)));
2530 return(UNIXERROR(ERRDOS
,ERRbadfid
));
2535 if (total_params
< 6)
2536 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2538 info_level
= SVAL(params
,0);
2539 srvstr_pull(inbuf
, fname
, ¶ms
[6], sizeof(fname
), -1, STR_TERMINATE
);
2540 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
2541 if(!check_name(fname
, conn
)) {
2542 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadpath
);
2546 * For CIFS UNIX extensions the target name may not exist.
2549 if(!VALID_STAT(sbuf
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
2550 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname
, strerror(errno
)));
2551 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2555 if (!CAN_WRITE(conn
))
2556 return ERROR_DOS(ERRSRV
,ERRaccess
);
2558 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions())
2559 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2561 if (VALID_STAT(sbuf
))
2562 unixmode
= sbuf
.st_mode
;
2564 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2565 tran_call
,fname
, fsp
? fsp
->fnum
: -1, info_level
,total_data
));
2567 /* Realloc the parameter and data sizes */
2568 params
= Realloc(*pparams
,2);
2570 return ERROR_DOS(ERRDOS
,ERRnomem
);
2576 /* the pending modtime overrides the current modtime */
2577 sbuf
.st_mtime
= fsp
->pending_modtime
;
2580 size
= get_file_size(sbuf
);
2581 tvs
.modtime
= sbuf
.st_mtime
;
2582 tvs
.actime
= sbuf
.st_atime
;
2583 dosmode
= dos_mode(conn
,fname
,&sbuf
);
2584 unixmode
= sbuf
.st_mode
;
2586 set_owner
= VALID_STAT(sbuf
) ? sbuf
.st_uid
: (uid_t
)SMB_UID_NO_CHANGE
;
2587 set_grp
= VALID_STAT(sbuf
) ? sbuf
.st_gid
: (gid_t
)SMB_GID_NO_CHANGE
;
2589 switch (info_level
) {
2590 case SMB_INFO_STANDARD
:
2592 if (total_data
< 12)
2593 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2596 tvs
.actime
= make_unix_date2(pdata
+l1_fdateLastAccess
);
2598 tvs
.modtime
= make_unix_date2(pdata
+l1_fdateLastWrite
);
2602 case SMB_INFO_SET_EA
:
2603 return(ERROR_DOS(ERRDOS
,ERReasnotsupported
));
2605 /* XXXX um, i don't think this is right.
2606 it's also not in the cifs6.txt spec.
2608 case SMB_INFO_QUERY_EAS_FROM_LIST
:
2609 if (total_data
< 28)
2610 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2612 tvs
.actime
= make_unix_date2(pdata
+8);
2613 tvs
.modtime
= make_unix_date2(pdata
+12);
2614 size
= IVAL(pdata
,16);
2615 dosmode
= IVAL(pdata
,24);
2618 /* XXXX nor this. not in cifs6.txt, either. */
2619 case SMB_INFO_QUERY_ALL_EAS
:
2620 if (total_data
< 28)
2621 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2623 tvs
.actime
= make_unix_date2(pdata
+8);
2624 tvs
.modtime
= make_unix_date2(pdata
+12);
2625 size
= IVAL(pdata
,16);
2626 dosmode
= IVAL(pdata
,24);
2629 case SMB_SET_FILE_BASIC_INFO
:
2630 case SMB_FILE_BASIC_INFORMATION
:
2632 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2634 time_t changed_time
;
2636 if (total_data
< 36)
2637 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2639 /* Ignore create time at offset pdata. */
2642 tvs
.actime
= interpret_long_date(pdata
+8);
2644 write_time
= interpret_long_date(pdata
+16);
2645 changed_time
= interpret_long_date(pdata
+24);
2647 tvs
.modtime
= MIN(write_time
, changed_time
);
2649 if (write_time
> tvs
.modtime
&& write_time
!= 0xffffffff) {
2650 tvs
.modtime
= write_time
;
2652 /* Prefer a defined time to an undefined one. */
2653 if (tvs
.modtime
== (time_t)0 || tvs
.modtime
== (time_t)-1)
2654 tvs
.modtime
= (write_time
== (time_t)0 || write_time
== (time_t)-1
2655 ? changed_time
: write_time
);
2658 dosmode
= IVAL(pdata
,32);
2662 case SMB_FILE_ALLOCATION_INFORMATION
:
2663 case SMB_SET_FILE_ALLOCATION_INFO
:
2666 SMB_BIG_UINT allocation_size
;
2669 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2671 allocation_size
= (SMB_BIG_UINT
)IVAL(pdata
,0);
2672 #ifdef LARGE_SMB_OFF_T
2673 allocation_size
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
2674 #else /* LARGE_SMB_OFF_T */
2675 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
2676 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2677 #endif /* LARGE_SMB_OFF_T */
2678 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2679 fname
, (double)allocation_size
));
2681 if (allocation_size
)
2682 allocation_size
= SMB_ROUNDUP(allocation_size
,SMB_ROUNDUP_ALLOCATION_SIZE
);
2684 if(allocation_size
!= get_file_size(sbuf
)) {
2685 SMB_STRUCT_STAT new_sbuf
;
2687 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2688 fname
, (double)allocation_size
));
2691 files_struct
*new_fsp
= NULL
;
2692 int access_mode
= 0;
2695 if(global_oplock_break
) {
2696 /* Queue this file modify as we are the process of an oplock break. */
2698 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2699 DEBUGADD(2,( "in oplock break state.\n"));
2701 push_oplock_pending_smb_message(inbuf
, length
);
2705 new_fsp
= open_file_shared1(conn
, fname
, &sbuf
,FILE_WRITE_DATA
,
2706 SET_OPEN_MODE(DOS_OPEN_RDWR
),
2707 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
2708 0, 0, &access_mode
, &action
);
2710 if (new_fsp
== NULL
)
2711 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2712 ret
= vfs_allocate_file_space(new_fsp
, allocation_size
);
2713 if (SMB_VFS_FSTAT(new_fsp
,new_fsp
->fd
,&new_sbuf
) != 0) {
2714 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2715 new_fsp
->fnum
, strerror(errno
)));
2718 close_file(new_fsp
,True
);
2720 ret
= vfs_allocate_file_space(fsp
, allocation_size
);
2721 if (SMB_VFS_FSTAT(fsp
,fd
,&new_sbuf
) != 0) {
2722 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2723 fsp
->fnum
, strerror(errno
)));
2728 return ERROR_NT(NT_STATUS_DISK_FULL
);
2730 /* Allocate can truncate size... */
2731 size
= get_file_size(new_sbuf
);
2737 case SMB_FILE_END_OF_FILE_INFORMATION
:
2738 case SMB_SET_FILE_END_OF_FILE_INFO
:
2741 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2743 size
= IVAL(pdata
,0);
2744 #ifdef LARGE_SMB_OFF_T
2745 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
2746 #else /* LARGE_SMB_OFF_T */
2747 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
2748 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2749 #endif /* LARGE_SMB_OFF_T */
2750 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname
, (double)size
));
2754 case SMB_FILE_DISPOSITION_INFORMATION
:
2755 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
2757 BOOL delete_on_close
;
2761 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2763 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
2765 /* Just ignore this set on a path. */
2766 if (tran_call
!= TRANSACT2_SETFILEINFO
)
2770 return(UNIXERROR(ERRDOS
,ERRbadfid
));
2772 status
= set_delete_on_close_internal(fsp
, delete_on_close
);
2774 if (NT_STATUS_V(status
) != NT_STATUS_V(NT_STATUS_OK
))
2775 return ERROR_NT(status
);
2777 /* The set is across all open files on this dev/inode pair. */
2778 status
=set_delete_on_close_over_all(fsp
, delete_on_close
);
2779 if (NT_STATUS_V(status
) != NT_STATUS_V(NT_STATUS_OK
))
2780 return ERROR_NT(status
);
2785 case SMB_FILE_POSITION_INFORMATION
:
2787 SMB_BIG_UINT position_information
;
2790 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2792 position_information
= (SMB_BIG_UINT
)IVAL(pdata
,0);
2793 #ifdef LARGE_SMB_OFF_T
2794 position_information
|= (((SMB_BIG_UINT
)IVAL(pdata
,4)) << 32);
2795 #else /* LARGE_SMB_OFF_T */
2796 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
2797 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2798 #endif /* LARGE_SMB_OFF_T */
2799 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2800 fname
, (double)position_information
));
2802 fsp
->position_information
= position_information
;
2807 * CIFS UNIX extensions.
2810 case SMB_SET_FILE_UNIX_BASIC
:
2812 uint32 raw_unixmode
;
2814 if (total_data
< 100)
2815 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2817 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
2818 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
2819 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
2820 #ifdef LARGE_SMB_OFF_T
2821 size
|= (((SMB_OFF_T
)IVAL(pdata
,4)) << 32);
2822 #else /* LARGE_SMB_OFF_T */
2823 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
2824 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
2825 #endif /* LARGE_SMB_OFF_T */
2827 pdata
+=24; /* ctime & st_blocks are not changed */
2828 tvs
.actime
= interpret_long_unix_date(pdata
); /* access_time */
2829 tvs
.modtime
= interpret_long_unix_date(pdata
+8); /* modification_time */
2831 set_owner
= (uid_t
)IVAL(pdata
,0);
2833 set_grp
= (gid_t
)IVAL(pdata
,0);
2835 raw_unixmode
= IVAL(pdata
,28);
2836 unixmode
= unix_perms_from_wire(conn
, &sbuf
, raw_unixmode
);
2837 dosmode
= 0; /* Ensure dos mode change doesn't override this. */
2839 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2840 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2841 fname
, (double)size
, (unsigned int)set_owner
, (unsigned int)set_grp
, (int)raw_unixmode
));
2843 if (!VALID_STAT(sbuf
)) {
2846 * The only valid use of this is to create character and block
2847 * devices, and named pipes. This is deprecated (IMHO) and
2848 * a new info level should be used for mknod. JRA.
2851 #if !defined(HAVE_MAKEDEV_FN)
2852 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2853 #else /* HAVE_MAKEDEV_FN */
2854 uint32 file_type
= IVAL(pdata
,0);
2855 uint32 dev_major
= IVAL(pdata
,4);
2856 uint32 dev_minor
= IVAL(pdata
,12);
2858 uid_t myuid
= geteuid();
2859 gid_t mygid
= getegid();
2862 if (tran_call
== TRANSACT2_SETFILEINFO
)
2863 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2865 if (raw_unixmode
== SMB_MODE_NO_CHANGE
)
2866 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2868 dev
= makedev(dev_major
, dev_minor
);
2870 /* We can only create as the owner/group we are. */
2872 if ((set_owner
!= myuid
) && (set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
))
2873 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2874 if ((set_grp
!= mygid
) && (set_grp
!= (gid_t
)SMB_GID_NO_CHANGE
))
2875 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2877 if (file_type
!= UNIX_TYPE_CHARDEV
&& file_type
!= UNIX_TYPE_BLKDEV
&&
2878 file_type
!= UNIX_TYPE_FIFO
)
2879 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2881 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2882 0%o for file %s\n", (double)dev
, unixmode
, fname
));
2884 /* Ok - do the mknod. */
2885 if (SMB_VFS_MKNOD(conn
,dos_to_unix_static(fname
), unixmode
, dev
) != 0)
2886 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2888 inherit_access_acl(conn
, fname
, unixmode
);
2891 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
2893 #endif /* HAVE_MAKEDEV_FN */
2898 * Deal with the UNIX specific mode set.
2901 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
2902 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2903 (unsigned int)unixmode
, fname
));
2904 if (SMB_VFS_CHMOD(conn
,fname
,unixmode
) != 0)
2905 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2909 * Deal with the UNIX specific uid set.
2912 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) && (sbuf
.st_uid
!= set_owner
)) {
2913 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2914 (unsigned int)set_owner
, fname
));
2915 if (SMB_VFS_CHOWN(conn
,fname
,set_owner
, (gid_t
)-1) != 0)
2916 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2920 * Deal with the UNIX specific gid set.
2923 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) && (sbuf
.st_gid
!= set_grp
)) {
2924 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2925 (unsigned int)set_owner
, fname
));
2926 if (SMB_VFS_CHOWN(conn
,fname
,(uid_t
)-1, set_grp
) != 0)
2927 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2932 case SMB_SET_FILE_UNIX_LINK
:
2935 /* Set a symbolic link. */
2936 /* Don't allow this if follow links is false. */
2938 if (!lp_symlinks(SNUM(conn
)))
2939 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
2941 /* Disallow if already exists. */
2942 if (VALID_STAT(sbuf
))
2943 return(ERROR_DOS(ERRDOS
,ERRbadpath
));
2945 srvstr_pull(inbuf
, link_dest
, pdata
, sizeof(link_dest
), -1, STR_TERMINATE
);
2947 if (ensure_link_is_safe(conn
, link_dest
, link_dest
) != 0)
2948 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2950 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2951 fname
, link_dest
));
2953 if (SMB_VFS_SYMLINK(conn
,link_dest
,fname
) != 0)
2954 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2956 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
2960 case SMB_SET_FILE_UNIX_HLINK
:
2964 /* Set a hard link. */
2966 /* Disallow if already exists. */
2967 if (VALID_STAT(sbuf
))
2968 return(ERROR_DOS(ERRDOS
,ERRbadpath
));
2970 srvstr_pull(inbuf
, link_dest
, pdata
, sizeof(link_dest
), -1, STR_TERMINATE
);
2972 if (ensure_link_is_safe(conn
, link_dest
, link_dest
) != 0)
2973 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2975 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2976 fname
, link_dest
));
2978 if (SMB_VFS_LINK(conn
,link_dest
,fname
) != 0)
2979 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2981 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
2985 case SMB_FILE_RENAME_INFORMATION
:
2995 if (total_data
< 12)
2996 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
2998 overwrite
= (CVAL(pdata
,0) ? True
: False
);
2999 root_fid
= IVAL(pdata
,4);
3000 len
= IVAL(pdata
,8);
3001 srvstr_pull(inbuf
, newname
, &pdata
[12], sizeof(newname
), len
, 0);
3003 /* Check the new name has no '\' characters. */
3004 if (strchr_m(newname
, '\\') || strchr_m(newname
, '/'))
3005 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
3007 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3009 /* Create the base directory. */
3010 pstrcpy(base_name
, fname
);
3011 p
= strrchr_m(base_name
, '/');
3014 /* Append the new name. */
3015 pstrcat(base_name
, "/");
3016 pstrcat(base_name
, newname
);
3019 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3020 fsp
->fnum
, fsp
->fsp_name
, base_name
));
3021 status
= rename_internals_fsp(conn
, fsp
, base_name
, overwrite
);
3023 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3025 status
= rename_internals(conn
, fname
, base_name
, overwrite
);
3027 if (!NT_STATUS_IS_OK(status
))
3028 return ERROR_NT(status
);
3029 process_pending_change_notify_queue((time_t)0);
3031 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3035 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3038 /* get some defaults (no modifications) if any info is zero or -1. */
3039 if (tvs
.actime
== (time_t)0 || tvs
.actime
== (time_t)-1)
3040 tvs
.actime
= sbuf
.st_atime
;
3042 if (tvs
.modtime
== (time_t)0 || tvs
.modtime
== (time_t)-1)
3043 tvs
.modtime
= sbuf
.st_mtime
;
3045 DEBUG(6,("actime: %s " , ctime(&tvs
.actime
)));
3046 DEBUG(6,("modtime: %s ", ctime(&tvs
.modtime
)));
3047 DEBUG(6,("size: %.0f ", (double)size
));
3050 if (S_ISDIR(sbuf
.st_mode
))
3056 DEBUG(6,("dosmode: %x\n" , dosmode
));
3058 if(!((info_level
== SMB_SET_FILE_END_OF_FILE_INFO
) ||
3059 (info_level
== SMB_SET_FILE_ALLOCATION_INFO
) ||
3060 (info_level
== SMB_FILE_ALLOCATION_INFORMATION
) ||
3061 (info_level
== SMB_FILE_END_OF_FILE_INFORMATION
))) {
3064 * Only do this test if we are not explicitly
3065 * changing the size of a file.
3068 size
= get_file_size(sbuf
);
3072 * Try and set the times, size and mode of this file -
3073 * if they are different from the current values
3075 if (sbuf
.st_mtime
!= tvs
.modtime
|| sbuf
.st_atime
!= tvs
.actime
) {
3078 * This was a setfileinfo on an open file.
3079 * NT does this a lot. It's actually pointless
3080 * setting the time here, as it will be overwritten
3081 * on the next write, so we save the request
3082 * away and will set it on file close. JRA.
3085 if (tvs
.modtime
!= (time_t)0 && tvs
.modtime
!= (time_t)-1) {
3086 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs
.modtime
) ));
3087 fsp
->pending_modtime
= tvs
.modtime
;
3092 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3094 if(file_utime(conn
, fname
, &tvs
)!=0)
3095 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3099 /* check the mode isn't different, before changing it */
3100 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, fname
, &sbuf
))) {
3102 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname
, dosmode
));
3104 if(file_chmod(conn
, fname
, dosmode
, NULL
)) {
3105 DEBUG(2,("chmod of %s failed (%s)\n", fname
, strerror(errno
)));
3106 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3110 if (size
!= get_file_size(sbuf
)) {
3114 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3115 fname
, (double)size
));
3118 files_struct
*new_fsp
= NULL
;
3119 int access_mode
= 0;
3122 if(global_oplock_break
) {
3123 /* Queue this file modify as we are the process of an oplock break. */
3125 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3126 DEBUGADD(2,( "in oplock break state.\n"));
3128 push_oplock_pending_smb_message(inbuf
, length
);
3132 new_fsp
= open_file_shared(conn
, fname
, &sbuf
,
3133 SET_OPEN_MODE(DOS_OPEN_RDWR
),
3134 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
3135 0, 0, &access_mode
, &action
);
3137 if (new_fsp
== NULL
)
3138 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3139 ret
= vfs_set_filelen(new_fsp
, size
);
3140 close_file(new_fsp
,True
);
3142 ret
= vfs_set_filelen(fsp
, size
);
3146 return (UNIXERROR(ERRHRD
,ERRdiskfull
));
3150 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3155 /****************************************************************************
3156 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3157 ****************************************************************************/
3159 static int call_trans2mkdir(connection_struct
*conn
,
3160 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3161 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3163 char *params
= *pparams
;
3166 SMB_STRUCT_STAT sbuf
;
3167 BOOL bad_path
= False
;
3169 if (!CAN_WRITE(conn
))
3170 return ERROR_DOS(ERRSRV
,ERRaccess
);
3172 if (total_params
< 4)
3173 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3175 srvstr_pull(inbuf
, directory
, ¶ms
[4], sizeof(directory
), -1, STR_TERMINATE
);
3177 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
3179 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3180 if (check_name(directory
,conn
))
3181 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3184 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno
)));
3185 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRnoaccess
);
3188 /* Realloc the parameter and data sizes */
3189 params
= Realloc(*pparams
,2);
3191 return ERROR_DOS(ERRDOS
,ERRnomem
);
3196 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
3201 /****************************************************************************
3202 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3203 We don't actually do this - we just send a null response.
3204 ****************************************************************************/
3206 static int call_trans2findnotifyfirst(connection_struct
*conn
,
3207 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3208 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3210 static uint16 fnf_handle
= 257;
3211 char *params
= *pparams
;
3214 if (total_params
< 6)
3215 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3217 info_level
= SVAL(params
,4);
3218 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
3220 switch (info_level
) {
3225 return ERROR_DOS(ERRDOS
,ERRunknownlevel
);
3228 /* Realloc the parameter and data sizes */
3229 params
= Realloc(*pparams
,6);
3231 return ERROR_DOS(ERRDOS
,ERRnomem
);
3234 SSVAL(params
,0,fnf_handle
);
3235 SSVAL(params
,2,0); /* No changes */
3236 SSVAL(params
,4,0); /* No EA errors */
3243 send_trans2_replies(outbuf
, bufsize
, params
, 6, *ppdata
, 0);
3248 /****************************************************************************
3249 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3250 changes). Currently this does nothing.
3251 ****************************************************************************/
3253 static int call_trans2findnotifynext(connection_struct
*conn
,
3254 char *inbuf
, char *outbuf
, int length
, int bufsize
,
3255 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3257 char *params
= *pparams
;
3259 DEBUG(3,("call_trans2findnotifynext\n"));
3261 /* Realloc the parameter and data sizes */
3262 params
= Realloc(*pparams
,4);
3264 return ERROR_DOS(ERRDOS
,ERRnomem
);
3267 SSVAL(params
,0,0); /* No changes */
3268 SSVAL(params
,2,0); /* No EA errors */
3270 send_trans2_replies(outbuf
, bufsize
, params
, 4, *ppdata
, 0);
3275 /****************************************************************************
3276 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3277 ****************************************************************************/
3279 static int call_trans2getdfsreferral(connection_struct
*conn
, char* inbuf
,
3280 char* outbuf
, int length
, int bufsize
,
3281 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3283 char *params
= *pparams
;
3286 int max_referral_level
;
3288 DEBUG(10,("call_trans2getdfsreferral\n"));
3290 if (total_params
< 2)
3291 return(ERROR_DOS(ERRDOS
,ERRinvalidparam
));
3293 max_referral_level
= SVAL(params
,0);
3295 if(!lp_host_msdfs())
3296 return ERROR_DOS(ERRDOS
,ERRbadfunc
);
3298 srvstr_pull(inbuf
, pathname
, ¶ms
[2], sizeof(pathname
), -1, STR_TERMINATE
);
3300 if((reply_size
= setup_dfs_referral(conn
, pathname
,max_referral_level
,ppdata
)) < 0)
3301 return UNIXERROR(ERRDOS
,ERRbadfile
);
3303 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
3304 send_trans2_replies(outbuf
,bufsize
,0,0,*ppdata
,reply_size
);
3309 #define LMCAT_SPL 0x53
3310 #define LMFUNC_GETJOBID 0x60
3312 /****************************************************************************
3313 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3314 ****************************************************************************/
3316 static int call_trans2ioctl(connection_struct
*conn
, char* inbuf
,
3317 char* outbuf
, int length
, int bufsize
,
3318 char **pparams
, int total_params
, char **ppdata
, int total_data
)
3320 char *pdata
= *ppdata
;
3321 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv15
);
3323 /* check for an invalid fid before proceeding */
3326 return(ERROR_DOS(ERRDOS
,ERRbadfid
));
3328 if ((SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
3329 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
3330 pdata
= Realloc(*ppdata
, 32);
3332 return ERROR_DOS(ERRDOS
,ERRnomem
);
3335 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3336 CAN ACCEPT THIS IN UNICODE. JRA. */
3338 SSVAL(pdata
,0,fsp
->rap_print_jobid
); /* Job number */
3339 srvstr_push( outbuf
, pdata
+ 2, global_myname(), 15, STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
3340 srvstr_push( outbuf
, pdata
+18, lp_servicename(SNUM(conn
)), 13, STR_ASCII
|STR_TERMINATE
); /* Service name */
3341 send_trans2_replies(outbuf
,bufsize
,*pparams
,0,*ppdata
,32);
3344 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3345 return ERROR_DOS(ERRSRV
,ERRerror
);
3349 /****************************************************************************
3350 Reply to a SMBfindclose (stop trans2 directory search).
3351 ****************************************************************************/
3353 int reply_findclose(connection_struct
*conn
,
3354 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3357 int dptr_num
=SVALS(inbuf
,smb_vwv0
);
3358 START_PROFILE(SMBfindclose
);
3360 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
3362 dptr_close(&dptr_num
);
3364 outsize
= set_message(outbuf
,0,0,True
);
3366 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
3368 END_PROFILE(SMBfindclose
);
3372 /****************************************************************************
3373 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3374 ****************************************************************************/
3376 int reply_findnclose(connection_struct
*conn
,
3377 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3381 START_PROFILE(SMBfindnclose
);
3383 dptr_num
= SVAL(inbuf
,smb_vwv0
);
3385 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
3387 /* We never give out valid handles for a
3388 findnotifyfirst - so any dptr_num is ok here.
3391 outsize
= set_message(outbuf
,0,0,True
);
3393 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
3395 END_PROFILE(SMBfindnclose
);
3399 /****************************************************************************
3400 Reply to a SMBtranss2 - just ignore it!
3401 ****************************************************************************/
3403 int reply_transs2(connection_struct
*conn
,
3404 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3406 START_PROFILE(SMBtranss2
);
3407 DEBUG(4,("Ignoring transs2 of length %d\n",length
));
3408 END_PROFILE(SMBtranss2
);
3412 /****************************************************************************
3413 Reply to a SMBtrans2.
3414 ****************************************************************************/
3416 int reply_trans2(connection_struct
*conn
,
3417 char *inbuf
,char *outbuf
,int length
,int bufsize
)
3420 unsigned int total_params
= SVAL(inbuf
, smb_tpscnt
);
3421 unsigned int total_data
=SVAL(inbuf
, smb_tdscnt
);
3423 unsigned int max_param_reply
= SVAL(inbuf
, smb_mprcnt
);
3424 unsigned int max_data_reply
= SVAL(inbuf
, smb_mdrcnt
);
3425 unsigned int max_setup_fields
= SVAL(inbuf
, smb_msrcnt
);
3426 BOOL close_tid
= BITSETW(inbuf
+smb_flags
,0);
3427 BOOL no_final_response
= BITSETW(inbuf
+smb_flags
,1);
3428 int32 timeout
= IVALS(inbuf
,smb_timeout
);
3430 unsigned int suwcnt
= SVAL(inbuf
, smb_suwcnt
);
3431 unsigned int tran_call
= SVAL(inbuf
, smb_setup0
);
3432 char *params
= NULL
, *data
= NULL
;
3433 unsigned int num_params
, num_params_sofar
, num_data
, num_data_sofar
;
3434 START_PROFILE(SMBtrans2
);
3436 if(global_oplock_break
&& (tran_call
== TRANSACT2_OPEN
)) {
3437 /* Queue this open message as we are the process of an
3440 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3441 DEBUGADD(2,( "in oplock break state.\n"));
3443 push_oplock_pending_smb_message(inbuf
, length
);
3444 END_PROFILE(SMBtrans2
);
3448 if (IS_IPC(conn
) && (tran_call
!= TRANSACT2_OPEN
)
3449 && (tran_call
!= TRANSACT2_GET_DFS_REFERRAL
)) {
3450 END_PROFILE(SMBtrans2
);
3451 return ERROR_DOS(ERRSRV
,ERRaccess
);
3454 outsize
= set_message(outbuf
,0,0,True
);
3456 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3457 is so as a sanity check */
3460 * Need to have rc=0 for ioctl to get job id for OS/2.
3461 * Network printing will fail if function is not successful.
3462 * Similar function in reply.c will be used if protocol
3463 * is LANMAN1.0 instead of LM1.2X002.
3464 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3465 * outbuf doesn't have to be set(only job id is used).
3467 if ( (suwcnt
== 4) && (tran_call
== TRANSACT2_IOCTL
) &&
3468 (SVAL(inbuf
,(smb_setup
+4)) == LMCAT_SPL
) &&
3469 (SVAL(inbuf
,(smb_setup
+6)) == LMFUNC_GETJOBID
)) {
3470 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3472 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt
));
3473 DEBUG(2,("Transaction is %d\n",tran_call
));
3474 END_PROFILE(SMBtrans2
);
3475 ERROR_DOS(ERRDOS
,ERRinvalidparam
);
3479 /* Allocate the space for the maximum needed parameters and data */
3480 if (total_params
> 0)
3481 params
= (char *)malloc(total_params
);
3483 data
= (char *)malloc(total_data
);
3485 if ((total_params
&& !params
) || (total_data
&& !data
)) {
3486 DEBUG(2,("Out of memory in reply_trans2\n"));
3489 END_PROFILE(SMBtrans2
);
3490 return ERROR_DOS(ERRDOS
,ERRnomem
);
3493 /* Copy the param and data bytes sent with this request into
3494 the params buffer */
3495 num_params
= num_params_sofar
= SVAL(inbuf
,smb_pscnt
);
3496 num_data
= num_data_sofar
= SVAL(inbuf
, smb_dscnt
);
3498 if (num_params
> total_params
|| num_data
> total_data
)
3499 exit_server("invalid params in reply_trans2");
3502 unsigned int psoff
= SVAL(inbuf
, smb_psoff
);
3503 if ((psoff
+ num_params
< psoff
) || (psoff
+ num_params
< num_params
))
3505 if ((smb_base(inbuf
) + psoff
+ num_params
> inbuf
+ length
) ||
3506 (smb_base(inbuf
) + psoff
+ num_params
< smb_base(inbuf
)))
3508 memcpy( params
, smb_base(inbuf
) + psoff
, num_params
);
3511 unsigned int dsoff
= SVAL(inbuf
, smb_dsoff
);
3512 if ((dsoff
+ num_data
< dsoff
) || (dsoff
+ num_data
< num_data
))
3514 if ((smb_base(inbuf
) + dsoff
+ num_data
> inbuf
+ length
) ||
3515 (smb_base(inbuf
) + dsoff
+ num_data
< smb_base(inbuf
)))
3517 memcpy( data
, smb_base(inbuf
) + dsoff
, num_data
);
3520 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
3522 if(num_data_sofar
< total_data
|| num_params_sofar
< total_params
) {
3523 /* We need to send an interim response then receive the rest
3524 of the parameter/data bytes */
3525 outsize
= set_message(outbuf
,0,0,True
);
3526 srv_signing_trans_stop();
3527 if (!send_smb(smbd_server_fd(),outbuf
))
3528 exit_server("reply_trans2: send_smb failed.");
3530 while (num_data_sofar
< total_data
||
3531 num_params_sofar
< total_params
) {
3533 unsigned int param_disp
;
3534 unsigned int param_off
;
3535 unsigned int data_disp
;
3536 unsigned int data_off
;
3538 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
3541 * The sequence number for the trans reply is always
3542 * based on the last secondary received.
3545 srv_signing_trans_start(SVAL(inbuf
,smb_mid
));
3548 (CVAL(inbuf
, smb_com
) != SMBtranss2
)) || !ret
) {
3549 outsize
= set_message(outbuf
,0,0,True
);
3551 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3553 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3554 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
3558 /* Revise total_params and total_data in case
3559 they have changed downwards */
3560 if (SVAL(inbuf
, smb_tpscnt
) < total_params
)
3561 total_params
= SVAL(inbuf
, smb_tpscnt
);
3562 if (SVAL(inbuf
, smb_tdscnt
) < total_data
)
3563 total_data
= SVAL(inbuf
, smb_tdscnt
);
3565 num_params
= SVAL(inbuf
,smb_spscnt
);
3566 param_off
= SVAL(inbuf
, smb_spsoff
);
3567 param_disp
= SVAL(inbuf
, smb_spsdisp
);
3568 num_params_sofar
+= num_params
;
3570 num_data
= SVAL(inbuf
, smb_sdscnt
);
3571 data_off
= SVAL(inbuf
, smb_sdsoff
);
3572 data_disp
= SVAL(inbuf
, smb_sdsdisp
);
3573 num_data_sofar
+= num_data
;
3575 if (num_params_sofar
> total_params
|| num_data_sofar
> total_data
)
3579 if (param_disp
+ num_params
>= total_params
)
3581 if ((param_disp
+ num_params
< param_disp
) ||
3582 (param_disp
+ num_params
< num_params
))
3584 if (param_disp
> total_params
)
3586 if ((smb_base(inbuf
) + param_off
+ num_params
>= inbuf
+ bufsize
) ||
3587 (smb_base(inbuf
) + param_off
+ num_params
< smb_base(inbuf
)))
3589 if (params
+ param_disp
< params
)
3592 memcpy( ¶ms
[param_disp
], smb_base(inbuf
) + param_off
, num_params
);
3595 if (data_disp
+ num_data
>= total_data
)
3597 if ((data_disp
+ num_data
< data_disp
) ||
3598 (data_disp
+ num_data
< num_data
))
3600 if (data_disp
> total_data
)
3602 if ((smb_base(inbuf
) + data_off
+ num_data
>= inbuf
+ bufsize
) ||
3603 (smb_base(inbuf
) + data_off
+ num_data
< smb_base(inbuf
)))
3605 if (data
+ data_disp
< data
)
3608 memcpy( &data
[data_disp
], smb_base(inbuf
) + data_off
, num_data
);
3613 if (Protocol
>= PROTOCOL_NT1
) {
3614 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
,smb_flg2
) | 0x40); /* IS_LONG_NAME */
3617 /* Now we must call the relevant TRANS2 function */
3619 case TRANSACT2_OPEN
:
3620 START_PROFILE_NESTED(Trans2_open
);
3621 outsize
= call_trans2open(conn
, inbuf
, outbuf
, bufsize
,
3622 ¶ms
, total_params
, &data
, total_data
);
3623 END_PROFILE_NESTED(Trans2_open
);
3626 case TRANSACT2_FINDFIRST
:
3627 START_PROFILE_NESTED(Trans2_findfirst
);
3628 outsize
= call_trans2findfirst(conn
, inbuf
, outbuf
, bufsize
,
3629 ¶ms
, total_params
, &data
, total_data
);
3630 END_PROFILE_NESTED(Trans2_findfirst
);
3633 case TRANSACT2_FINDNEXT
:
3634 START_PROFILE_NESTED(Trans2_findnext
);
3635 outsize
= call_trans2findnext(conn
, inbuf
, outbuf
, length
, bufsize
,
3636 ¶ms
, total_params
, &data
, total_data
);
3637 END_PROFILE_NESTED(Trans2_findnext
);
3640 case TRANSACT2_QFSINFO
:
3641 START_PROFILE_NESTED(Trans2_qfsinfo
);
3642 outsize
= call_trans2qfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
3643 ¶ms
, total_params
, &data
, total_data
);
3644 END_PROFILE_NESTED(Trans2_qfsinfo
);
3647 #ifdef HAVE_SYS_QUOTAS
3648 case TRANSACT2_SETFSINFO
:
3649 START_PROFILE_NESTED(Trans2_setfsinfo
);
3650 outsize
= call_trans2setfsinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
3651 ¶ms
, total_params
, &data
, total_data
);
3652 END_PROFILE_NESTED(Trans2_setfsinfo
);
3655 case TRANSACT2_QPATHINFO
:
3656 case TRANSACT2_QFILEINFO
:
3657 START_PROFILE_NESTED(Trans2_qpathinfo
);
3658 outsize
= call_trans2qfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
3659 ¶ms
, total_params
, &data
, total_data
);
3660 END_PROFILE_NESTED(Trans2_qpathinfo
);
3662 case TRANSACT2_SETPATHINFO
:
3663 case TRANSACT2_SETFILEINFO
:
3664 START_PROFILE_NESTED(Trans2_setpathinfo
);
3665 outsize
= call_trans2setfilepathinfo(conn
, inbuf
, outbuf
, length
, bufsize
,
3666 ¶ms
, total_params
, &data
, total_data
);
3667 END_PROFILE_NESTED(Trans2_setpathinfo
);
3670 case TRANSACT2_FINDNOTIFYFIRST
:
3671 START_PROFILE_NESTED(Trans2_findnotifyfirst
);
3672 outsize
= call_trans2findnotifyfirst(conn
, inbuf
, outbuf
, length
, bufsize
,
3673 ¶ms
, total_params
, &data
, total_data
);
3674 END_PROFILE_NESTED(Trans2_findnotifyfirst
);
3677 case TRANSACT2_FINDNOTIFYNEXT
:
3678 START_PROFILE_NESTED(Trans2_findnotifynext
);
3679 outsize
= call_trans2findnotifynext(conn
, inbuf
, outbuf
, length
, bufsize
,
3680 ¶ms
, total_params
, &data
, total_data
);
3681 END_PROFILE_NESTED(Trans2_findnotifynext
);
3683 case TRANSACT2_MKDIR
:
3684 START_PROFILE_NESTED(Trans2_mkdir
);
3685 outsize
= call_trans2mkdir(conn
, inbuf
, outbuf
, length
, bufsize
,
3686 ¶ms
, total_params
, &data
, total_data
);
3687 END_PROFILE_NESTED(Trans2_mkdir
);
3690 case TRANSACT2_GET_DFS_REFERRAL
:
3691 START_PROFILE_NESTED(Trans2_get_dfs_referral
);
3692 outsize
= call_trans2getdfsreferral(conn
,inbuf
,outbuf
,length
, bufsize
,
3693 ¶ms
, total_params
, &data
, total_data
);
3694 END_PROFILE_NESTED(Trans2_get_dfs_referral
);
3696 case TRANSACT2_IOCTL
:
3697 START_PROFILE_NESTED(Trans2_ioctl
);
3698 outsize
= call_trans2ioctl(conn
,inbuf
,outbuf
,length
, bufsize
,
3699 ¶ms
, total_params
, &data
, total_data
);
3700 END_PROFILE_NESTED(Trans2_ioctl
);
3703 /* Error in request */
3704 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call
));
3707 END_PROFILE(SMBtrans2
);
3708 srv_signing_trans_stop();
3709 return ERROR_DOS(ERRSRV
,ERRerror
);
3712 /* As we do not know how many data packets will need to be
3713 returned here the various call_trans2xxxx calls
3714 must send their own. Thus a call_trans2xxx routine only
3715 returns a value other than -1 when it wants to send
3719 srv_signing_trans_stop();
3723 END_PROFILE(SMBtrans2
);
3724 return outsize
; /* If a correct response was needed the
3725 call_trans2xxx calls have already sent
3726 it. If outsize != -1 then it is returning */
3730 srv_signing_trans_stop();
3733 END_PROFILE(SMBtrans2
);
3734 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);