2 Unix SMB/Netbios implementation.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1997
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 int DEBUGLEVEL
;
29 extern connection_struct Connections
[];
30 extern files_struct Files
[];
31 extern BOOL case_sensitive
;
34 /****************************************************************************
35 Send the required number of replies back.
36 We assume all fields other than the data fields are
37 set correctly for the type of call.
38 HACK ! Always assumes smb_setup field is zero.
39 ****************************************************************************/
40 static int send_trans2_replies(char *outbuf
, int bufsize
, char *params
,
41 int paramsize
, char *pdata
, int datasize
)
43 /* As we are using a protocol > LANMAN1 then the max_send
44 variable must have been set in the sessetupX call.
45 This takes precedence over the max_xmit field in the
46 global struct. These different max_xmit variables should
47 be merged as this is now too confusing */
50 int data_to_send
= datasize
;
51 int params_to_send
= paramsize
;
55 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
56 int alignment_offset
= 1;
58 /* Initially set the wcnt area to be 10 - this is true for all
60 set_message(outbuf
,10,0,True
);
62 /* If there genuinely are no parameters or data to send just send
64 if(params_to_send
== 0 && data_to_send
== 0)
66 send_smb(Client
,outbuf
);
70 /* Space is bufsize minus Netbios over TCP header minus SMB header */
71 /* The alignment_offset is to align the param and data bytes on an even byte
72 boundary. NT 4.0 Beta needs this to work correctly. */
73 useable_space
= bufsize
- ((smb_buf(outbuf
)+alignment_offset
) - outbuf
);
74 /* useable_space can never be more than max_send minus the
76 useable_space
= MIN(useable_space
, max_send
- alignment_offset
);
78 while( params_to_send
|| data_to_send
)
80 /* Calculate whether we will totally or partially fill this packet */
81 total_sent_thistime
= params_to_send
+ data_to_send
+ alignment_offset
;
82 /* We can never send more than useable_space */
83 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
85 set_message(outbuf
, 10, total_sent_thistime
, True
);
87 /* Set total params and data to be sent */
88 SSVAL(outbuf
,smb_tprcnt
,paramsize
);
89 SSVAL(outbuf
,smb_tdrcnt
,datasize
);
91 /* Calculate how many parameters and data we can fit into
92 this packet. Parameters get precedence */
94 params_sent_thistime
= MIN(params_to_send
,useable_space
);
95 data_sent_thistime
= useable_space
- params_sent_thistime
;
96 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
98 SSVAL(outbuf
,smb_prcnt
, params_sent_thistime
);
99 if(params_sent_thistime
== 0)
101 SSVAL(outbuf
,smb_proff
,0);
102 SSVAL(outbuf
,smb_prdisp
,0);
104 /* smb_proff is the offset from the start of the SMB header to the
105 parameter bytes, however the first 4 bytes of outbuf are
106 the Netbios over TCP header. Thus use smb_base() to subtract
107 them from the calculation */
108 SSVAL(outbuf
,smb_proff
,((smb_buf(outbuf
)+alignment_offset
) - smb_base(outbuf
)));
109 /* Absolute displacement of param bytes sent in this packet */
110 SSVAL(outbuf
,smb_prdisp
,pp
- params
);
113 SSVAL(outbuf
,smb_drcnt
, data_sent_thistime
);
114 if(data_sent_thistime
== 0)
116 SSVAL(outbuf
,smb_droff
,0);
117 SSVAL(outbuf
,smb_drdisp
, 0);
119 /* The offset of the data bytes is the offset of the
120 parameter bytes plus the number of parameters being sent this time */
121 SSVAL(outbuf
,smb_droff
,((smb_buf(outbuf
)+alignment_offset
) -
122 smb_base(outbuf
)) + params_sent_thistime
);
123 SSVAL(outbuf
,smb_drdisp
, pd
- pdata
);
126 /* Copy the param bytes into the packet */
127 if(params_sent_thistime
)
128 memcpy((smb_buf(outbuf
)+alignment_offset
),pp
,params_sent_thistime
);
129 /* Copy in the data bytes */
130 if(data_sent_thistime
)
131 memcpy(smb_buf(outbuf
)+alignment_offset
+params_sent_thistime
,pd
,data_sent_thistime
);
133 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
134 params_sent_thistime
, data_sent_thistime
, useable_space
));
135 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
136 params_to_send
, data_to_send
, paramsize
, datasize
));
138 /* Send the packet */
139 send_smb(Client
,outbuf
);
141 pp
+= params_sent_thistime
;
142 pd
+= data_sent_thistime
;
144 params_to_send
-= params_sent_thistime
;
145 data_to_send
-= data_sent_thistime
;
148 if(params_to_send
< 0 || data_to_send
< 0)
150 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
151 params_to_send
, data_to_send
));
160 /****************************************************************************
161 reply to a TRANSACT2_OPEN
162 ****************************************************************************/
163 static int call_trans2open(char *inbuf
, char *outbuf
, int bufsize
, int cnum
,
164 char **pparams
, char **ppdata
)
166 char *params
= *pparams
;
167 int16 open_mode
= SVAL(params
, 2);
168 int16 open_attr
= SVAL(params
,6);
169 BOOL oplock_request
= BITSETW(params
,1);
171 BOOL return_additional_info
= BITSETW(params
,0);
172 int16 open_sattr
= SVAL(params
, 4);
173 time_t open_time
= make_unix_date3(params
+8);
175 int16 open_ofun
= SVAL(params
,12);
176 int32 open_size
= IVAL(params
,14);
177 char *pname
= ¶ms
[28];
178 int16 namelen
= strlen(pname
)+1;
183 int size
=0,fmode
=0,mtime
=0,rmode
;
187 BOOL bad_path
= False
;
189 StrnCpy(fname
,pname
,namelen
);
191 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
192 fname
,cnum
,open_mode
, open_attr
, open_ofun
, open_size
));
194 /* XXXX we need to handle passed times, sattr and flags */
196 unix_convert(fname
,cnum
,0,&bad_path
);
198 fnum
= find_free_file();
200 return(ERROR(ERRSRV
,ERRnofids
));
202 if (!check_name(fname
,cnum
))
204 if((errno
== ENOENT
) && bad_path
)
206 unix_ERR_class
= ERRDOS
;
207 unix_ERR_code
= ERRbadpath
;
209 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
212 unixmode
= unix_mode(cnum
,open_attr
| aARCH
);
215 open_file_shared(fnum
,cnum
,fname
,open_mode
,open_ofun
,unixmode
,
218 if (!Files
[fnum
].open
)
220 if((errno
== ENOENT
) && bad_path
)
222 unix_ERR_class
= ERRDOS
;
223 unix_ERR_code
= ERRbadpath
;
225 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
228 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
230 return(ERROR(ERRDOS
,ERRnoaccess
));
234 fmode
= dos_mode(cnum
,fname
,&sbuf
);
235 mtime
= sbuf
.st_mtime
;
239 return(ERROR(ERRDOS
,ERRnoaccess
));
242 /* Realloc the size of parameters and data we will return */
243 params
= *pparams
= Realloc(*pparams
, 28);
245 return(ERROR(ERRDOS
,ERRnomem
));
248 SSVAL(params
,0,fnum
);
249 SSVAL(params
,2,fmode
);
250 put_dos_date2(params
,4, mtime
);
251 SIVAL(params
,8, size
);
252 SSVAL(params
,12,rmode
);
254 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
255 smb_action
|= (1<<15);
258 SSVAL(params
,18,smb_action
);
259 SIVAL(params
,20,inode
);
261 /* Send the required number of replies */
262 send_trans2_replies(outbuf
, bufsize
, params
, 28, *ppdata
, 0);
267 /****************************************************************************
268 get a level dependent lanman2 dir entry.
269 ****************************************************************************/
270 static int get_lanman2_dir_entry(int cnum
,char *path_mask
,int dirtype
,int info_level
,
271 int requires_resume_key
,
272 BOOL dont_descend
,char **ppdata
,
273 char *base_data
, int space_remaining
,
284 char *p
, *pdata
= *ppdata
;
285 int reskey
=0, prev_dirpos
=0;
288 uint32 mdate
=0, adate
=0, cdate
=0;
290 BOOL isrootdir
= (strequal(Connections
[cnum
].dirpath
,"./") ||
291 strequal(Connections
[cnum
].dirpath
,".") ||
292 strequal(Connections
[cnum
].dirpath
,"/"));
294 int nt_extmode
; /* Used for NT connections instead of mode */
295 BOOL needslash
= ( Connections
[cnum
].dirpath
[strlen(Connections
[cnum
].dirpath
) -1] != '/');
298 *out_of_space
= False
;
300 if (!Connections
[cnum
].dirptr
)
303 p
= strrchr(path_mask
,'/');
312 strcpy(mask
, path_mask
);
316 /* Needed if we run out of space */
317 prev_dirpos
= TellDir(Connections
[cnum
].dirptr
);
318 dname
= ReadDirName(Connections
[cnum
].dirptr
);
320 reskey
= TellDir(Connections
[cnum
].dirptr
);
322 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
323 Connections
[cnum
].dirptr
,TellDir(Connections
[cnum
].dirptr
)));
332 if(mask_match(fname
, mask
, case_sensitive
, True
))
334 BOOL isdots
= (strequal(fname
,"..") || strequal(fname
,"."));
335 if (dont_descend
&& !isdots
)
338 if (isrootdir
&& isdots
)
341 strcpy(pathreal
,Connections
[cnum
].dirpath
);
343 strcat(pathreal
,"/");
344 strcat(pathreal
,fname
);
345 if (sys_stat(pathreal
,&sbuf
) != 0)
347 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal
,strerror(errno
)));
351 mode
= dos_mode(cnum
,pathreal
,&sbuf
);
353 if (!dir_check_ftype(cnum
,mode
,&sbuf
,dirtype
)) {
354 DEBUG(5,("[%s] attribs didn't match %x\n",fname
,dirtype
));
359 mdate
= sbuf
.st_mtime
;
360 adate
= sbuf
.st_atime
;
361 cdate
= sbuf
.st_ctime
;
365 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal
,fname
));
376 name_map_mangle(fname
,False
,SNUM(cnum
));
378 nt_extmode
= mode
? mode
: NT_FILE_ATTRIBUTE_NORMAL
;
383 if(requires_resume_key
) {
387 put_dos_date2(p
,l1_fdateCreation
,cdate
);
388 put_dos_date2(p
,l1_fdateLastAccess
,adate
);
389 put_dos_date2(p
,l1_fdateLastWrite
,mdate
);
390 SIVAL(p
,l1_cbFile
,size
);
391 SIVAL(p
,l1_cbFileAlloc
,ROUNDUP(size
,1024));
392 SSVAL(p
,l1_attrFile
,mode
);
393 SCVAL(p
,l1_cchName
,strlen(fname
));
394 strcpy(p
+ l1_achName
, fname
);
395 nameptr
= p
+ l1_achName
;
396 p
+= l1_achName
+ strlen(fname
) + 1;
401 if(requires_resume_key
) {
405 put_dos_date2(p
,l2_fdateCreation
,cdate
);
406 put_dos_date2(p
,l2_fdateLastAccess
,adate
);
407 put_dos_date2(p
,l2_fdateLastWrite
,mdate
);
408 SIVAL(p
,l2_cbFile
,size
);
409 SIVAL(p
,l2_cbFileAlloc
,ROUNDUP(size
,1024));
410 SSVAL(p
,l2_attrFile
,mode
);
411 SIVAL(p
,l2_cbList
,0); /* No extended attributes */
412 SCVAL(p
,l2_cchName
,strlen(fname
));
413 strcpy(p
+ l2_achName
, fname
);
414 nameptr
= p
+ l2_achName
;
415 p
+= l2_achName
+ strlen(fname
) + 1;
420 put_dos_date2(p
,4,cdate
);
421 put_dos_date2(p
,8,adate
);
422 put_dos_date2(p
,12,mdate
);
424 SIVAL(p
,20,ROUNDUP(size
,1024));
427 CVAL(p
,30) = strlen(fname
);
430 p
+= 31 + strlen(fname
) + 1;
434 if(requires_resume_key
) {
438 SIVAL(p
,0,33+strlen(fname
)+1);
439 put_dos_date2(p
,4,cdate
);
440 put_dos_date2(p
,8,adate
);
441 put_dos_date2(p
,12,mdate
);
443 SIVAL(p
,20,ROUNDUP(size
,1024));
445 CVAL(p
,32) = strlen(fname
);
446 strcpy(p
+ 33, fname
);
448 p
+= 33 + strlen(fname
) + 1;
451 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
452 was_8_3
= is_8_3(fname
, True
);
453 len
= 94+strlen(fname
);
454 len
= (len
+ 3) & ~3;
455 SIVAL(p
,0,len
); p
+= 4;
456 SIVAL(p
,0,reskey
); p
+= 4;
457 put_long_date(p
,cdate
); p
+= 8;
458 put_long_date(p
,adate
); p
+= 8;
459 put_long_date(p
,mdate
); p
+= 8;
460 put_long_date(p
,mdate
); p
+= 8;
461 SIVAL(p
,0,size
); p
+= 8;
462 SIVAL(p
,0,size
); p
+= 8;
463 SIVAL(p
,0,nt_extmode
); p
+= 4;
464 SIVAL(p
,0,strlen(fname
)); p
+= 4;
465 SIVAL(p
,0,0); p
+= 4;
468 if (!name_map_mangle(p
+2,True
,SNUM(cnum
)))
473 SSVAL(p
,0,strlen(p
+2));
476 strcpy(p
,fname
); p
+= strlen(p
);
480 case SMB_FIND_FILE_DIRECTORY_INFO
:
481 len
= 64+strlen(fname
);
482 len
= (len
+ 3) & ~3;
483 SIVAL(p
,0,len
); p
+= 4;
484 SIVAL(p
,0,reskey
); p
+= 4;
485 put_long_date(p
,cdate
); p
+= 8;
486 put_long_date(p
,adate
); p
+= 8;
487 put_long_date(p
,mdate
); p
+= 8;
488 put_long_date(p
,mdate
); p
+= 8;
489 SIVAL(p
,0,size
); p
+= 8;
490 SIVAL(p
,0,size
); p
+= 8;
491 SIVAL(p
,0,nt_extmode
); p
+= 4;
492 SIVAL(p
,0,strlen(fname
)); p
+= 4;
498 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
499 len
= 68+strlen(fname
);
500 len
= (len
+ 3) & ~3;
501 SIVAL(p
,0,len
); p
+= 4;
502 SIVAL(p
,0,reskey
); p
+= 4;
503 put_long_date(p
,cdate
); p
+= 8;
504 put_long_date(p
,adate
); p
+= 8;
505 put_long_date(p
,mdate
); p
+= 8;
506 put_long_date(p
,mdate
); p
+= 8;
507 SIVAL(p
,0,size
); p
+= 8;
508 SIVAL(p
,0,size
); p
+= 8;
509 SIVAL(p
,0,nt_extmode
); p
+= 4;
510 SIVAL(p
,0,strlen(fname
)); p
+= 4;
511 SIVAL(p
,0,0); p
+= 4;
516 case SMB_FIND_FILE_NAMES_INFO
:
517 len
= 12+strlen(fname
);
518 len
= (len
+ 3) & ~3;
519 SIVAL(p
,0,len
); p
+= 4;
520 SIVAL(p
,0,reskey
); p
+= 4;
521 SIVAL(p
,0,strlen(fname
)); p
+= 4;
531 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
532 /* Move the dirptr back to prev_dirpos */
533 SeekDir(Connections
[cnum
].dirptr
, prev_dirpos
);
534 *out_of_space
= True
;
535 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
536 return False
; /* Not finished - just out of space */
539 /* Setup the last_filename pointer, as an offset from base_data */
540 *last_name_off
= PTR_DIFF(nameptr
,base_data
);
541 /* Advance the data pointer to the next slot */
546 /****************************************************************************
547 reply to a TRANS2_FINDFIRST
548 ****************************************************************************/
549 static int call_trans2findfirst(char *inbuf
, char *outbuf
, int bufsize
, int cnum
,
550 char **pparams
, char **ppdata
)
552 /* We must be careful here that we don't return more than the
553 allowed number of data bytes. If this means returning fewer than
554 maxentries then so be it. We assume that the redirector has
555 enough room for the fixed number of parameter bytes it has
557 uint32 max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
558 char *params
= *pparams
;
559 char *pdata
= *ppdata
;
560 int dirtype
= SVAL(params
,0);
561 int maxentries
= SVAL(params
,2);
562 BOOL close_after_first
= BITSETW(params
+4,0);
563 BOOL close_if_end
= BITSETW(params
+4,1);
564 BOOL requires_resume_key
= BITSETW(params
+4,2);
565 int info_level
= SVAL(params
,6);
573 BOOL finished
= False
;
574 BOOL dont_descend
= False
;
575 BOOL out_of_space
= False
;
577 BOOL bad_path
= False
;
579 *directory
= *mask
= 0;
581 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
582 dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
583 info_level
, max_data_bytes
));
591 case SMB_FIND_FILE_DIRECTORY_INFO
:
592 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
593 case SMB_FIND_FILE_NAMES_INFO
:
594 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
597 return(ERROR(ERRDOS
,ERRunknownlevel
));
600 strcpy(directory
, params
+ 12); /* Complete directory path with
601 wildcard mask appended */
603 DEBUG(5,("path=%s\n",directory
));
605 unix_convert(directory
,cnum
,0,&bad_path
);
606 if(!check_name(directory
,cnum
)) {
607 if((errno
== ENOENT
) && bad_path
)
609 unix_ERR_class
= ERRDOS
;
610 unix_ERR_code
= ERRbadpath
;
612 return(ERROR(ERRDOS
,ERRbadpath
));
615 p
= strrchr(directory
,'/');
617 strcpy(mask
,directory
);
618 strcpy(directory
,"./");
624 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
626 pdata
= *ppdata
= Realloc(*ppdata
, max_data_bytes
+ 1024);
628 return(ERROR(ERRDOS
,ERRnomem
));
629 bzero(pdata
,max_data_bytes
);
631 /* Realloc the params space */
632 params
= *pparams
= Realloc(*pparams
, 10);
634 return(ERROR(ERRDOS
,ERRnomem
));
636 dptr_num
= dptr_create(cnum
,directory
, True
,SVAL(inbuf
,smb_pid
));
641 if((errno
== ENOENT
) && bad_path
)
643 unix_ERR_class
= ERRDOS
;
644 unix_ERR_code
= ERRbadpath
;
646 return (UNIXERROR(ERRDOS
,ERRbadpath
));
648 return(ERROR(ERRDOS
,ERRbadpath
));
651 /* convert the formatted masks */
655 if (*p
== '<') *p
= '*';
656 if (*p
== '>') *p
= '?';
657 if (*p
== '"') *p
= '.';
662 /* a special case for 16 bit apps */
663 if (strequal(mask
,"????????.???")) strcpy(mask
,"*");
665 /* handle broken clients that send us old 8.3 format */
666 string_sub(mask
,"????????","*");
667 string_sub(mask
,".???",".*");
669 /* Save the wildcard match and attribs we are using on this directory -
670 needed as lanman2 assumes these are being saved between calls */
672 if(!(wcard
= strdup(mask
))) {
673 dptr_close(dptr_num
);
674 return(ERROR(ERRDOS
,ERRnomem
));
677 dptr_set_wcard(dptr_num
, wcard
);
678 dptr_set_attr(dptr_num
, dirtype
);
680 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num
, wcard
, dirtype
));
682 /* We don't need to check for VOL here as this is returned by
683 a different TRANS2 call. */
685 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
686 Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
687 if (in_list(Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
)),case_sensitive
))
691 space_remaining
= max_data_bytes
;
692 out_of_space
= False
;
694 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++)
697 /* this is a heuristic to avoid seeking the dirptr except when
698 absolutely necessary. It allows for a filename of about 40 chars */
699 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0)
707 !get_lanman2_dir_entry(cnum
,mask
,dirtype
,info_level
,
708 requires_resume_key
,dont_descend
,
709 &p
,pdata
,space_remaining
, &out_of_space
,
713 if (finished
&& out_of_space
)
716 if (!finished
&& !out_of_space
)
718 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
721 /* Check if we can close the dirptr */
722 if(close_after_first
|| (finished
&& close_if_end
))
724 dptr_close(dptr_num
);
725 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
729 /* At this point pdata points to numentries directory entries. */
731 /* Set up the return parameter block */
732 SSVAL(params
,0,dptr_num
);
733 SSVAL(params
,2,numentries
);
734 SSVAL(params
,4,finished
);
735 SSVAL(params
,6,0); /* Never an EA error */
736 SSVAL(params
,8,last_name_off
);
738 send_trans2_replies( outbuf
, bufsize
, params
, 10, pdata
, PTR_DIFF(p
,pdata
));
740 if ((! *directory
) && dptr_path(dptr_num
))
741 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
743 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
745 smb_fn_name(CVAL(inbuf
,smb_com
)),
746 mask
,directory
,cnum
,dirtype
,numentries
));
752 /****************************************************************************
753 reply to a TRANS2_FINDNEXT
754 ****************************************************************************/
755 static int call_trans2findnext(char *inbuf
, char *outbuf
, int length
, int bufsize
,
756 int cnum
, char **pparams
, char **ppdata
)
758 /* We must be careful here that we don't return more than the
759 allowed number of data bytes. If this means returning fewer than
760 maxentries then so be it. We assume that the redirector has
761 enough room for the fixed number of parameter bytes it has
763 int max_data_bytes
= SVAL(inbuf
, smb_mdrcnt
);
764 char *params
= *pparams
;
765 char *pdata
= *ppdata
;
766 int16 dptr_num
= SVAL(params
,0);
767 int maxentries
= SVAL(params
,2);
768 uint16 info_level
= SVAL(params
,4);
769 uint32 resume_key
= IVAL(params
,6);
770 BOOL close_after_request
= BITSETW(params
+10,0);
771 BOOL close_if_end
= BITSETW(params
+10,1);
772 BOOL requires_resume_key
= BITSETW(params
+10,2);
773 BOOL continue_bit
= BITSETW(params
+10,3);
779 int i
, last_name_off
=0;
780 BOOL finished
= False
;
781 BOOL dont_descend
= False
;
782 BOOL out_of_space
= False
;
785 *mask
= *directory
= 0;
787 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n",
788 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
789 requires_resume_key
, resume_key
, continue_bit
, info_level
));
797 case SMB_FIND_FILE_DIRECTORY_INFO
:
798 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
799 case SMB_FIND_FILE_NAMES_INFO
:
800 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
803 return(ERROR(ERRDOS
,ERRunknownlevel
));
806 pdata
= *ppdata
= Realloc( *ppdata
, max_data_bytes
+ 1024);
808 return(ERROR(ERRDOS
,ERRnomem
));
809 bzero(pdata
,max_data_bytes
);
811 /* Realloc the params space */
812 params
= *pparams
= Realloc(*pparams
, 6*SIZEOFWORD
);
814 return(ERROR(ERRDOS
,ERRnomem
));
816 /* Check that the dptr is valid */
817 if(!(Connections
[cnum
].dirptr
= dptr_fetch_lanman2(params
, dptr_num
)))
818 return(ERROR(ERRDOS
,ERRnofiles
));
820 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
822 /* Get the wildcard mask from the dptr */
823 if((p
= dptr_wcard(dptr_num
))== NULL
) {
824 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
825 return (ERROR(ERRDOS
,ERRnofiles
));
828 strcpy(directory
,Connections
[cnum
].dirpath
);
830 /* Get the attr mask from the dptr */
831 dirtype
= dptr_attr(dptr_num
);
833 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
834 dptr_num
, mask
, dirtype
,
835 Connections
[cnum
].dirptr
,
836 TellDir(Connections
[cnum
].dirptr
)));
838 /* We don't need to check for VOL here as this is returned by
839 a different TRANS2 call. */
841 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
842 if (in_list(Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
)),case_sensitive
))
846 space_remaining
= max_data_bytes
;
847 out_of_space
= False
;
849 /* If we have a resume key - seek to the correct position. */
850 if(requires_resume_key
&& !continue_bit
)
851 SeekDir(Connections
[cnum
].dirptr
, resume_key
);
853 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++)
855 /* this is a heuristic to avoid seeking the dirptr except when
856 absolutely necessary. It allows for a filename of about 40 chars */
857 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0)
865 !get_lanman2_dir_entry(cnum
,mask
,dirtype
,info_level
,
866 requires_resume_key
,dont_descend
,
867 &p
,pdata
,space_remaining
, &out_of_space
,
871 if (finished
&& out_of_space
)
874 if (!finished
&& !out_of_space
)
876 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
879 /* Check if we can close the dirptr */
880 if(close_after_request
|| (finished
&& close_if_end
))
882 dptr_close(dptr_num
); /* This frees up the saved mask */
883 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
888 /* Set up the return parameter block */
889 SSVAL(params
,0,numentries
);
890 SSVAL(params
,2,finished
);
891 SSVAL(params
,4,0); /* Never an EA error */
892 SSVAL(params
,6,last_name_off
);
894 send_trans2_replies( outbuf
, bufsize
, params
, 8, pdata
, PTR_DIFF(p
,pdata
));
896 if ((! *directory
) && dptr_path(dptr_num
))
897 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
899 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
901 smb_fn_name(CVAL(inbuf
,smb_com
)),
902 mask
,directory
,cnum
,dirtype
,numentries
));
907 /****************************************************************************
908 reply to a TRANS2_QFSINFO (query filesystem info)
909 ****************************************************************************/
910 static int call_trans2qfsinfo(char *inbuf
, char *outbuf
, int length
, int bufsize
,
911 int cnum
, char **pparams
, char **ppdata
)
913 char *pdata
= *ppdata
;
914 char *params
= *pparams
;
915 uint16 info_level
= SVAL(params
,0);
918 char *vname
= volume_label(SNUM(cnum
));
920 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum
, info_level
));
922 if(sys_stat(".",&st
)!=0) {
923 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno
)));
924 return (ERROR(ERRSRV
,ERRinvdevice
));
927 pdata
= *ppdata
= Realloc(*ppdata
, 1024); bzero(pdata
,1024);
933 int dfree
,dsize
,bsize
;
935 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
936 SIVAL(pdata
,l1_idFileSystem
,st
.st_dev
);
937 SIVAL(pdata
,l1_cSectorUnit
,bsize
/512);
938 SIVAL(pdata
,l1_cUnit
,dsize
);
939 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
940 SSVAL(pdata
,l1_cbSector
,512);
941 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
942 bsize
, st
.st_dev
, bsize
/512, dsize
, dfree
, 512));
947 /* Return volume name */
948 int volname_len
= MIN(strlen(vname
),11);
949 data_len
= l2_vol_szVolLabel
+ volname_len
+ 1;
950 put_dos_date2(pdata
,l2_vol_fdateCreation
,st
.st_ctime
);
951 SCVAL(pdata
,l2_vol_cch
,volname_len
);
952 StrnCpy(pdata
+l2_vol_szVolLabel
,vname
,volname_len
);
953 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st
.st_ctime
, volname_len
,
954 pdata
+l2_vol_szVolLabel
));
957 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
958 data_len
= 12 + 2*strlen(FSTYPE_STRING
);
959 SIVAL(pdata
,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
960 SIVAL(pdata
,4,128); /* Max filename component length */
961 SIVAL(pdata
,8,2*strlen(FSTYPE_STRING
));
962 PutUniCode(pdata
+12,FSTYPE_STRING
);
964 case SMB_QUERY_FS_LABEL_INFO
:
965 data_len
= 4 + strlen(vname
);
966 SIVAL(pdata
,0,strlen(vname
));
967 strcpy(pdata
+4,vname
);
969 case SMB_QUERY_FS_VOLUME_INFO
:
970 data_len
= 18 + 2*strlen(vname
);
971 SIVAL(pdata
,12,2*strlen(vname
));
972 PutUniCode(pdata
+18,vname
);
973 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname
),
976 case SMB_QUERY_FS_SIZE_INFO
:
978 int dfree
,dsize
,bsize
;
980 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
981 SIVAL(pdata
,0,dsize
);
982 SIVAL(pdata
,8,dfree
);
983 SIVAL(pdata
,16,bsize
/512);
987 case SMB_QUERY_FS_DEVICE_INFO
:
989 SIVAL(pdata
,0,0); /* dev type */
990 SIVAL(pdata
,4,0); /* characteristics */
993 return(ERROR(ERRDOS
,ERRunknownlevel
));
997 send_trans2_replies( outbuf
, bufsize
, params
, 0, pdata
, data_len
);
999 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf
,smb_com
)), info_level
));
1004 /****************************************************************************
1005 reply to a TRANS2_SETFSINFO (set filesystem info)
1006 ****************************************************************************/
1007 static int call_trans2setfsinfo(char *inbuf
, char *outbuf
, int length
, int bufsize
,
1008 int cnum
, char **pparams
, char **ppdata
)
1010 /* Just say yes we did it - there is nothing that
1011 can be set here so it doesn't matter. */
1013 DEBUG(3,("call_trans2setfsinfo\n"));
1015 if (!CAN_WRITE(cnum
))
1016 return(ERROR(ERRSRV
,ERRaccess
));
1018 outsize
= set_message(outbuf
,10,0,True
);
1023 /****************************************************************************
1024 reply to a TRANS2_QFILEINFO (query file info by fileid)
1025 ****************************************************************************/
1026 static int call_trans2qfilepathinfo(char *inbuf
, char *outbuf
, int length
,
1027 int bufsize
,int cnum
,
1028 char **pparams
,char **ppdata
,
1031 char *params
= *pparams
;
1032 char *pdata
= *ppdata
;
1033 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
1037 unsigned int data_size
;
1043 BOOL bad_path
= False
;
1045 if (tran_call
== TRANSACT2_QFILEINFO
) {
1046 int16 fnum
= SVALS(params
,0);
1047 info_level
= SVAL(params
,2);
1049 CHECK_FNUM(fnum
,cnum
);
1052 fname
= Files
[fnum
].name
;
1053 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
1054 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum
, strerror(errno
)));
1055 return(UNIXERROR(ERRDOS
,ERRbadfid
));
1057 pos
= lseek(Files
[fnum
].fd_ptr
->fd
,0,SEEK_CUR
);
1060 info_level
= SVAL(params
,0);
1062 strcpy(fname
,¶ms
[6]);
1063 unix_convert(fname
,cnum
,0,&bad_path
);
1064 if (!check_name(fname
,cnum
) || sys_stat(fname
,&sbuf
)) {
1065 DEBUG(3,("fileinfo of %s failed (%s)\n",fname
,strerror(errno
)));
1066 if((errno
== ENOENT
) && bad_path
)
1068 unix_ERR_class
= ERRDOS
;
1069 unix_ERR_code
= ERRbadpath
;
1071 return(UNIXERROR(ERRDOS
,ERRbadpath
));
1077 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1078 fname
,info_level
,tran_call
,total_data
));
1080 p
= strrchr(fname
,'/');
1086 mode
= dos_mode(cnum
,fname
,&sbuf
);
1087 size
= sbuf
.st_size
;
1088 if (mode
& aDIR
) size
= 0;
1090 params
= *pparams
= Realloc(*pparams
,2); bzero(params
,2);
1092 pdata
= *ppdata
= Realloc(*ppdata
, data_size
);
1094 if (total_data
> 0 && IVAL(pdata
,0) == total_data
) {
1095 /* uggh, EAs for OS2 */
1096 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data
));
1098 SSVAL(params
,0,ERROR_EAS_NOT_SUPPORTED
);
1099 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
1102 return(ERROR(ERRDOS
,ERROR_EAS_NOT_SUPPORTED
));
1106 bzero(pdata
,data_size
);
1110 case SMB_INFO_STANDARD
:
1111 case SMB_INFO_QUERY_EA_SIZE
:
1112 data_size
= (info_level
==1?22:26);
1113 put_dos_date2(pdata
,l1_fdateCreation
,sbuf
.st_ctime
); /* create = inode mod */
1114 put_dos_date2(pdata
,l1_fdateLastAccess
,sbuf
.st_atime
); /* access time */
1115 put_dos_date2(pdata
,l1_fdateLastWrite
,sbuf
.st_mtime
); /* write time */
1116 SIVAL(pdata
,l1_cbFile
,size
);
1117 SIVAL(pdata
,l1_cbFileAlloc
,ROUNDUP(size
,1024));
1118 SSVAL(pdata
,l1_attrFile
,mode
);
1119 SIVAL(pdata
,l1_attrFile
+2,4); /* this is what OS2 does */
1122 case SMB_INFO_QUERY_EAS_FROM_LIST
:
1124 put_dos_date2(pdata
,0,sbuf
.st_ctime
); /* create time = inode mod time */
1125 put_dos_date2(pdata
,4,sbuf
.st_atime
);
1126 put_dos_date2(pdata
,8,sbuf
.st_mtime
);
1127 SIVAL(pdata
,12,size
);
1128 SIVAL(pdata
,16,ROUNDUP(size
,1024));
1129 SIVAL(pdata
,20,mode
);
1132 case SMB_INFO_QUERY_ALL_EAS
:
1134 SIVAL(pdata
,0,data_size
);
1138 return(ERROR(ERRDOS
,ERRbadfunc
)); /* os/2 needs this */
1140 case SMB_QUERY_FILE_BASIC_INFO
:
1141 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
1142 put_long_date(pdata
,sbuf
.st_ctime
); /* create time = inode mod time */
1143 put_long_date(pdata
+8,sbuf
.st_atime
); /* access time */
1144 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
1145 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
1146 SIVAL(pdata
,32,mode
);
1148 DEBUG(5,("SMB_QFBI - "));
1149 DEBUG(5,("create: %s ", ctime(&sbuf
.st_ctime
)));
1150 DEBUG(5,("access: %s ", ctime(&sbuf
.st_atime
)));
1151 DEBUG(5,("write: %s ", ctime(&sbuf
.st_mtime
)));
1152 DEBUG(5,("change: %s ", ctime(&sbuf
.st_mtime
)));
1153 DEBUG(5,("mode: %x\n", mode
));
1157 case SMB_QUERY_FILE_STANDARD_INFO
:
1159 SIVAL(pdata
,0,size
);
1160 SIVAL(pdata
,8,size
);
1161 SIVAL(pdata
,16,sbuf
.st_nlink
);
1163 CVAL(pdata
,21) = (mode
&aDIR
)?1:0;
1166 case SMB_QUERY_FILE_EA_INFO
:
1170 case SMB_QUERY_FILE_NAME_INFO
:
1171 case SMB_QUERY_FILE_ALT_NAME_INFO
:
1174 strcpy(pdata
+4,fname
);
1176 case SMB_QUERY_FILE_ALLOCATION_INFO
:
1177 case SMB_QUERY_FILE_END_OF_FILEINFO
:
1179 SIVAL(pdata
,0,size
);
1182 case SMB_QUERY_FILE_ALL_INFO
:
1183 put_long_date(pdata
,sbuf
.st_ctime
); /* create time = inode mod time */
1184 put_long_date(pdata
+8,sbuf
.st_atime
); /* access time */
1185 put_long_date(pdata
+16,sbuf
.st_mtime
); /* write time */
1186 put_long_date(pdata
+24,sbuf
.st_mtime
); /* change time */
1187 SIVAL(pdata
,32,mode
);
1189 SIVAL(pdata
,0,size
);
1190 SIVAL(pdata
,8,size
);
1191 SIVAL(pdata
,16,sbuf
.st_nlink
);
1193 CVAL(pdata
,21) = (mode
&aDIR
)?1:0;
1195 pdata
+= 8; /* index number */
1196 pdata
+= 4; /* EA info */
1198 SIVAL(pdata
,0,0xA9);
1200 SIVAL(pdata
,0,0xd01BF);
1202 SIVAL(pdata
,0,pos
); /* current offset */
1204 SIVAL(pdata
,0,mode
); /* is this the right sort of mode info? */
1206 pdata
+= 4; /* alignment */
1208 strcpy(pdata
+4,fname
);
1210 data_size
= PTR_DIFF(pdata
,(*ppdata
));
1213 case SMB_QUERY_FILE_STREAM_INFO
:
1216 SIVAL(pdata
,4,size
);
1217 SIVAL(pdata
,12,size
);
1219 strcpy(pdata
+24,fname
);
1222 return(ERROR(ERRDOS
,ERRunknownlevel
));
1225 send_trans2_replies( outbuf
, bufsize
, params
, 2, *ppdata
, data_size
);
1230 /****************************************************************************
1231 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1232 ****************************************************************************/
1233 static int call_trans2setfilepathinfo(char *inbuf
, char *outbuf
, int length
,
1234 int bufsize
, int cnum
, char **pparams
,
1235 char **ppdata
, int total_data
)
1237 char *params
= *pparams
;
1238 char *pdata
= *ppdata
;
1239 uint16 tran_call
= SVAL(inbuf
, smb_setup0
);
1248 BOOL bad_path
= False
;
1250 if (!CAN_WRITE(cnum
))
1251 return(ERROR(ERRSRV
,ERRaccess
));
1253 if (tran_call
== TRANSACT2_SETFILEINFO
) {
1254 int16 fnum
= SVALS(params
,0);
1255 info_level
= SVAL(params
,2);
1257 CHECK_FNUM(fnum
,cnum
);
1260 fname
= Files
[fnum
].name
;
1261 fd
= Files
[fnum
].fd_ptr
->fd
;
1263 if(fstat(fd
,&st
)!=0) {
1264 DEBUG(3,("fstat of %s failed (%s)\n", fname
, strerror(errno
)));
1265 return(ERROR(ERRDOS
,ERRbadpath
));
1269 info_level
= SVAL(params
,0);
1271 strcpy(fname
,¶ms
[6]);
1272 unix_convert(fname
,cnum
,0,&bad_path
);
1273 if(!check_name(fname
, cnum
))
1275 if((errno
== ENOENT
) && bad_path
)
1277 unix_ERR_class
= ERRDOS
;
1278 unix_ERR_code
= ERRbadpath
;
1280 return(UNIXERROR(ERRDOS
,ERRbadpath
));
1283 if(sys_stat(fname
,&st
)!=0) {
1284 DEBUG(3,("stat of %s failed (%s)\n", fname
, strerror(errno
)));
1285 if((errno
== ENOENT
) && bad_path
)
1287 unix_ERR_class
= ERRDOS
;
1288 unix_ERR_code
= ERRbadpath
;
1290 return(UNIXERROR(ERRDOS
,ERRbadpath
));
1294 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1295 tran_call
,fname
,info_level
,total_data
));
1297 /* Realloc the parameter and data sizes */
1298 params
= *pparams
= Realloc(*pparams
,2); SSVAL(params
,0,0);
1300 return(ERROR(ERRDOS
,ERRnomem
));
1303 tvs
.modtime
= st
.st_mtime
;
1304 tvs
.actime
= st
.st_atime
;
1305 mode
= dos_mode(cnum
,fname
,&st
);
1307 if (total_data
> 0 && IVAL(pdata
,0) == total_data
) {
1308 /* uggh, EAs for OS2 */
1309 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data
));
1310 SSVAL(params
,0,ERROR_EAS_NOT_SUPPORTED
);
1312 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
1319 case SMB_INFO_STANDARD
:
1320 case SMB_INFO_QUERY_EA_SIZE
:
1323 tvs
.actime
= make_unix_date2(pdata
+l1_fdateLastAccess
);
1326 tvs
.modtime
= make_unix_date2(pdata
+l1_fdateLastWrite
);
1328 mode
= SVAL(pdata
,l1_attrFile
);
1329 size
= IVAL(pdata
,l1_cbFile
);
1333 /* XXXX um, i don't think this is right.
1334 it's also not in the cifs6.txt spec.
1336 case SMB_INFO_QUERY_EAS_FROM_LIST
:
1337 tvs
.actime
= make_unix_date2(pdata
+8);
1338 tvs
.modtime
= make_unix_date2(pdata
+12);
1339 size
= IVAL(pdata
,16);
1340 mode
= IVAL(pdata
,24);
1343 /* XXXX nor this. not in cifs6.txt, either. */
1344 case SMB_INFO_QUERY_ALL_EAS
:
1345 tvs
.actime
= make_unix_date2(pdata
+8);
1346 tvs
.modtime
= make_unix_date2(pdata
+12);
1347 size
= IVAL(pdata
,16);
1348 mode
= IVAL(pdata
,24);
1351 case SMB_SET_FILE_BASIC_INFO
:
1353 /* Ignore create time at offset pdata. */
1356 tvs
.actime
= interpret_long_date(pdata
+8);
1358 /* write time + changed time, combined. */
1359 tvs
.modtime
=MAX(interpret_long_date(pdata
+16),
1360 interpret_long_date(pdata
+24));
1363 mode
= IVAL(pdata
,32);
1367 case SMB_SET_FILE_END_OF_FILE_INFO
:
1369 if (IVAL(pdata
,4) != 0) /* more than 32 bits? */
1370 return(ERROR(ERRDOS
,ERRunknownlevel
));
1371 size
= IVAL(pdata
,0);
1375 case SMB_SET_FILE_DISPOSITION_INFO
: /* not supported yet */
1376 case SMB_SET_FILE_ALLOCATION_INFO
: /* not supported yet */
1379 return(ERROR(ERRDOS
,ERRunknownlevel
));
1383 DEBUG(6,("actime: %s " , ctime(&tvs
.actime
)));
1384 DEBUG(6,("modtime: %s ", ctime(&tvs
.modtime
)));
1385 DEBUG(6,("size: %x " , size
));
1386 DEBUG(6,("mode: %x\n" , mode
));
1388 /* get some defaults (no modifications) if any info is zero. */
1389 if (!tvs
.actime
) tvs
.actime
= st
.st_atime
;
1390 if (!tvs
.modtime
) tvs
.modtime
= st
.st_mtime
;
1391 if (!size
) size
= st
.st_size
;
1393 /* Try and set the times, size and mode of this file -
1394 if they are different from the current values
1396 if (st
.st_mtime
!= tvs
.modtime
|| st
.st_atime
!= tvs
.actime
)
1398 if(sys_utime(fname
, &tvs
)!=0)
1400 return(ERROR(ERRDOS
,ERRnoaccess
));
1404 /* check the mode isn't different, before changing it */
1405 if (mode
!= dos_mode(cnum
, fname
, &st
) && dos_chmod(cnum
, fname
, mode
, NULL
))
1407 DEBUG(2,("chmod of %s failed (%s)\n", fname
, strerror(errno
)));
1408 return(ERROR(ERRDOS
,ERRnoaccess
));
1411 if(size
!= st
.st_size
)
1415 fd
= sys_open(fname
,O_RDWR
,0);
1418 return(ERROR(ERRDOS
,ERRbadpath
));
1420 set_filelen(fd
, size
);
1425 set_filelen(fd
, size
);
1431 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
1436 /****************************************************************************
1437 reply to a TRANS2_MKDIR (make directory with extended attributes).
1438 ****************************************************************************/
1439 static int call_trans2mkdir(char *inbuf
, char *outbuf
, int length
, int bufsize
,
1440 int cnum
, char **pparams
, char **ppdata
)
1442 char *params
= *pparams
;
1445 BOOL bad_path
= False
;
1447 if (!CAN_WRITE(cnum
))
1448 return(ERROR(ERRSRV
,ERRaccess
));
1450 strcpy(directory
, ¶ms
[4]);
1452 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
1454 unix_convert(directory
,cnum
,0,&bad_path
);
1455 if (check_name(directory
,cnum
))
1456 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
1460 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno
)));
1461 if((errno
== ENOENT
) && bad_path
)
1463 unix_ERR_class
= ERRDOS
;
1464 unix_ERR_code
= ERRbadpath
;
1466 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1469 /* Realloc the parameter and data sizes */
1470 params
= *pparams
= Realloc(*pparams
,2);
1472 return(ERROR(ERRDOS
,ERRnomem
));
1476 send_trans2_replies(outbuf
, bufsize
, params
, 2, *ppdata
, 0);
1481 /****************************************************************************
1482 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1483 We don't actually do this - we just send a null response.
1484 ****************************************************************************/
1485 static int call_trans2findnotifyfirst(char *inbuf
, char *outbuf
, int length
, int bufsize
,
1486 int cnum
, char **pparams
, char **ppdata
)
1488 static uint16 fnf_handle
= 257;
1489 char *params
= *pparams
;
1490 uint16 info_level
= SVAL(params
,4);
1492 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
1500 return(ERROR(ERRDOS
,ERRunknownlevel
));
1503 /* Realloc the parameter and data sizes */
1504 params
= *pparams
= Realloc(*pparams
,6);
1506 return(ERROR(ERRDOS
,ERRnomem
));
1508 SSVAL(params
,0,fnf_handle
);
1509 SSVAL(params
,2,0); /* No changes */
1510 SSVAL(params
,4,0); /* No EA errors */
1517 send_trans2_replies(outbuf
, bufsize
, params
, 6, *ppdata
, 0);
1522 /****************************************************************************
1523 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1524 changes). Currently this does nothing.
1525 ****************************************************************************/
1526 static int call_trans2findnotifynext(char *inbuf
, char *outbuf
, int length
, int bufsize
,
1527 int cnum
, char **pparams
, char **ppdata
)
1529 char *params
= *pparams
;
1531 DEBUG(3,("call_trans2findnotifynext\n"));
1533 /* Realloc the parameter and data sizes */
1534 params
= *pparams
= Realloc(*pparams
,4);
1536 return(ERROR(ERRDOS
,ERRnomem
));
1538 SSVAL(params
,0,0); /* No changes */
1539 SSVAL(params
,2,0); /* No EA errors */
1541 send_trans2_replies(outbuf
, bufsize
, params
, 4, *ppdata
, 0);
1546 /****************************************************************************
1547 reply to a SMBfindclose (stop trans2 directory search)
1548 ****************************************************************************/
1549 int reply_findclose(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1553 int16 dptr_num
=SVALS(inbuf
,smb_vwv0
);
1555 cnum
= SVAL(inbuf
,smb_tid
);
1557 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum
, dptr_num
));
1559 dptr_close(dptr_num
);
1561 outsize
= set_message(outbuf
,0,0,True
);
1563 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum
,dptr_num
));
1568 /****************************************************************************
1569 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1570 ****************************************************************************/
1571 int reply_findnclose(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1577 cnum
= SVAL(inbuf
,smb_tid
);
1578 dptr_num
= SVAL(inbuf
,smb_vwv0
);
1580 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum
, dptr_num
));
1582 /* We never give out valid handles for a
1583 findnotifyfirst - so any dptr_num is ok here.
1586 outsize
= set_message(outbuf
,0,0,True
);
1588 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum
,dptr_num
));
1594 /****************************************************************************
1595 reply to a SMBtranss2 - just ignore it!
1596 ****************************************************************************/
1597 int reply_transs2(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1599 DEBUG(4,("Ignoring transs2 of length %d\n",length
));
1603 /****************************************************************************
1604 reply to a SMBtrans2
1605 ****************************************************************************/
1606 int reply_trans2(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1609 int cnum
= SVAL(inbuf
,smb_tid
);
1610 unsigned int total_params
= SVAL(inbuf
, smb_tpscnt
);
1611 unsigned int total_data
=SVAL(inbuf
, smb_tdscnt
);
1613 unsigned int max_param_reply
= SVAL(inbuf
, smb_mprcnt
);
1614 unsigned int max_data_reply
= SVAL(inbuf
, smb_mdrcnt
);
1615 unsigned int max_setup_fields
= SVAL(inbuf
, smb_msrcnt
);
1616 BOOL close_tid
= BITSETW(inbuf
+smb_flags
,0);
1617 BOOL no_final_response
= BITSETW(inbuf
+smb_flags
,1);
1618 int32 timeout
= IVALS(inbuf
,smb_timeout
);
1620 unsigned int suwcnt
= SVAL(inbuf
, smb_suwcnt
);
1621 unsigned int tran_call
= SVAL(inbuf
, smb_setup0
);
1622 char *params
= NULL
, *data
= NULL
;
1623 int num_params
, num_params_sofar
, num_data
, num_data_sofar
;
1625 outsize
= set_message(outbuf
,0,0,True
);
1627 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1628 is so as a sanity check */
1631 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1632 return(ERROR(ERRSRV
,ERRerror
));
1635 /* Allocate the space for the maximum needed parameters and data */
1636 if (total_params
> 0)
1637 params
= (char *)malloc(total_params
);
1639 data
= (char *)malloc(total_data
);
1641 if ((total_params
&& !params
) || (total_data
&& !data
))
1643 DEBUG(2,("Out of memory in reply_trans2\n"));
1644 return(ERROR(ERRDOS
,ERRnomem
));
1647 /* Copy the param and data bytes sent with this request into
1648 the params buffer */
1649 num_params
= num_params_sofar
= SVAL(inbuf
,smb_pscnt
);
1650 num_data
= num_data_sofar
= SVAL(inbuf
, smb_dscnt
);
1652 memcpy( params
, smb_base(inbuf
) + SVAL(inbuf
, smb_psoff
), num_params
);
1653 memcpy( data
, smb_base(inbuf
) + SVAL(inbuf
, smb_dsoff
), num_data
);
1655 if(num_data_sofar
< total_data
|| num_params_sofar
< total_params
)
1657 /* We need to send an interim response then receive the rest
1658 of the parameter/data bytes */
1659 outsize
= set_message(outbuf
,0,0,True
);
1660 send_smb(Client
,outbuf
);
1662 while( num_data_sofar
< total_data
|| num_params_sofar
< total_params
)
1664 if(!receive_smb(Client
,inbuf
, SMB_SECONDARY_WAIT
) ||
1665 CVAL(inbuf
, smb_com
) != SMBtranss2
)
1667 outsize
= set_message(outbuf
,0,0,True
);
1668 DEBUG(2,("Invalid secondary trans2 packet\n"));
1671 return(ERROR(ERRSRV
,ERRerror
));
1674 /* Revise total_params and total_data in case they have changed downwards */
1675 total_params
= SVAL(inbuf
, smb_tpscnt
);
1676 total_data
= SVAL(inbuf
, smb_tdscnt
);
1677 num_params_sofar
+= (num_params
= SVAL(inbuf
,smb_spscnt
));
1678 num_data_sofar
+= ( num_data
= SVAL(inbuf
, smb_sdscnt
));
1679 memcpy( ¶ms
[ SVAL(inbuf
, smb_spsdisp
)],
1680 smb_base(inbuf
) + SVAL(inbuf
, smb_spsoff
), num_params
);
1681 memcpy( &data
[SVAL(inbuf
, smb_sdsdisp
)],
1682 smb_base(inbuf
)+ SVAL(inbuf
, smb_sdsoff
), num_data
);
1686 if (Protocol
>= PROTOCOL_NT1
) {
1687 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1688 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1691 /* Now we must call the relevant TRANS2 function */
1694 case TRANSACT2_OPEN
:
1695 outsize
= call_trans2open(inbuf
, outbuf
, bufsize
, cnum
, ¶ms
, &data
);
1697 case TRANSACT2_FINDFIRST
:
1698 outsize
= call_trans2findfirst(inbuf
, outbuf
, bufsize
, cnum
, ¶ms
, &data
);
1700 case TRANSACT2_FINDNEXT
:
1701 outsize
= call_trans2findnext(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1703 case TRANSACT2_QFSINFO
:
1704 outsize
= call_trans2qfsinfo(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1706 case TRANSACT2_SETFSINFO
:
1707 outsize
= call_trans2setfsinfo(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1709 case TRANSACT2_QPATHINFO
:
1710 case TRANSACT2_QFILEINFO
:
1711 outsize
= call_trans2qfilepathinfo(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
, total_data
);
1713 case TRANSACT2_SETPATHINFO
:
1714 case TRANSACT2_SETFILEINFO
:
1715 outsize
= call_trans2setfilepathinfo(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
, total_data
);
1717 case TRANSACT2_FINDNOTIFYFIRST
:
1718 outsize
= call_trans2findnotifyfirst(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1720 case TRANSACT2_FINDNOTIFYNEXT
:
1721 outsize
= call_trans2findnotifynext(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1723 case TRANSACT2_MKDIR
:
1724 outsize
= call_trans2mkdir(inbuf
, outbuf
, length
, bufsize
, cnum
, ¶ms
, &data
);
1727 /* Error in request */
1728 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call
));
1733 return (ERROR(ERRSRV
,ERRerror
));
1736 /* As we do not know how many data packets will need to be
1737 returned here the various call_trans2xxxx calls
1738 must send their own. Thus a call_trans2xxx routine only
1739 returns a value other than -1 when it wants to send
1747 return outsize
; /* If a correct response was needed the call_trans2xxx
1748 calls have already sent it. If outsize != -1 then it is
1749 returning an error packet. */