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 = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>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,
216 oplock_request, &rmode,&smb_action);
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 |= EXTENDED_OPLOCK_GRANTED;
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 pstrcpy(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(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
323 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
330 pstrcpy(fname,dname);
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 pstrcpy(pathreal,Connections[cnum].dirpath);
343 strcat(pathreal,"/");
344 strcat(pathreal,dname);
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));
371 name_map_mangle(fname,False,SNUM(cnum));
376 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
381 if(requires_resume_key) {
385 put_dos_date2(p,l1_fdateCreation,cdate);
386 put_dos_date2(p,l1_fdateLastAccess,adate);
387 put_dos_date2(p,l1_fdateLastWrite,mdate);
388 SIVAL(p,l1_cbFile,size);
389 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
390 SSVAL(p,l1_attrFile,mode);
391 SCVAL(p,l1_cchName,strlen(fname));
392 strcpy(p + l1_achName, fname);
393 nameptr = p + l1_achName;
394 p += l1_achName + strlen(fname) + 1;
399 if(requires_resume_key) {
403 put_dos_date2(p,l2_fdateCreation,cdate);
404 put_dos_date2(p,l2_fdateLastAccess,adate);
405 put_dos_date2(p,l2_fdateLastWrite,mdate);
406 SIVAL(p,l2_cbFile,size);
407 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
408 SSVAL(p,l2_attrFile,mode);
409 SIVAL(p,l2_cbList,0); /* No extended attributes */
410 SCVAL(p,l2_cchName,strlen(fname));
411 strcpy(p + l2_achName, fname);
412 nameptr = p + l2_achName;
413 p += l2_achName + strlen(fname) + 1;
418 put_dos_date2(p,4,cdate);
419 put_dos_date2(p,8,adate);
420 put_dos_date2(p,12,mdate);
422 SIVAL(p,20,ROUNDUP(size,1024));
425 CVAL(p,30) = strlen(fname);
428 p += 31 + strlen(fname) + 1;
432 if(requires_resume_key) {
436 SIVAL(p,0,33+strlen(fname)+1);
437 put_dos_date2(p,4,cdate);
438 put_dos_date2(p,8,adate);
439 put_dos_date2(p,12,mdate);
441 SIVAL(p,20,ROUNDUP(size,1024));
443 CVAL(p,32) = strlen(fname);
444 strcpy(p + 33, fname);
446 p += 33 + strlen(fname) + 1;
449 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
450 was_8_3 = is_8_3(fname, True);
451 len = 94+strlen(fname);
452 len = (len + 3) & ~3;
453 SIVAL(p,0,len); p += 4;
454 SIVAL(p,0,reskey); p += 4;
455 put_long_date(p,cdate); p += 8;
456 put_long_date(p,adate); p += 8;
457 put_long_date(p,mdate); p += 8;
458 put_long_date(p,mdate); p += 8;
459 SIVAL(p,0,size); p += 8;
460 SIVAL(p,0,size); p += 8;
461 SIVAL(p,0,nt_extmode); p += 4;
462 SIVAL(p,0,strlen(fname)); p += 4;
463 SIVAL(p,0,0); p += 4;
466 if (!name_map_mangle(p+2,True,SNUM(cnum)))
471 SSVAL(p,0,strlen(p+2));
474 strcpy(p,fname); p += strlen(p);
478 case SMB_FIND_FILE_DIRECTORY_INFO:
479 len = 64+strlen(fname);
480 len = (len + 3) & ~3;
481 SIVAL(p,0,len); p += 4;
482 SIVAL(p,0,reskey); p += 4;
483 put_long_date(p,cdate); p += 8;
484 put_long_date(p,adate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 put_long_date(p,mdate); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,size); p += 8;
489 SIVAL(p,0,nt_extmode); p += 4;
490 SIVAL(p,0,strlen(fname)); p += 4;
496 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
497 len = 68+strlen(fname);
498 len = (len + 3) & ~3;
499 SIVAL(p,0,len); p += 4;
500 SIVAL(p,0,reskey); p += 4;
501 put_long_date(p,cdate); p += 8;
502 put_long_date(p,adate); p += 8;
503 put_long_date(p,mdate); p += 8;
504 put_long_date(p,mdate); p += 8;
505 SIVAL(p,0,size); p += 8;
506 SIVAL(p,0,size); p += 8;
507 SIVAL(p,0,nt_extmode); p += 4;
508 SIVAL(p,0,strlen(fname)); p += 4;
509 SIVAL(p,0,0); p += 4;
514 case SMB_FIND_FILE_NAMES_INFO:
515 len = 12+strlen(fname);
516 len = (len + 3) & ~3;
517 SIVAL(p,0,len); p += 4;
518 SIVAL(p,0,reskey); p += 4;
519 SIVAL(p,0,strlen(fname)); p += 4;
529 if (PTR_DIFF(p,pdata) > space_remaining) {
530 /* Move the dirptr back to prev_dirpos */
531 SeekDir(Connections[cnum].dirptr, prev_dirpos);
532 *out_of_space = True;
533 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
534 return False; /* Not finished - just out of space */
537 /* Setup the last_filename pointer, as an offset from base_data */
538 *last_name_off = PTR_DIFF(nameptr,base_data);
539 /* Advance the data pointer to the next slot */
544 /****************************************************************************
545 reply to a TRANS2_FINDFIRST
546 ****************************************************************************/
547 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
548 char **pparams, char **ppdata)
550 /* We must be careful here that we don't return more than the
551 allowed number of data bytes. If this means returning fewer than
552 maxentries then so be it. We assume that the redirector has
553 enough room for the fixed number of parameter bytes it has
555 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
556 char *params = *pparams;
557 char *pdata = *ppdata;
558 int dirtype = SVAL(params,0);
559 int maxentries = SVAL(params,2);
560 BOOL close_after_first = BITSETW(params+4,0);
561 BOOL close_if_end = BITSETW(params+4,1);
562 BOOL requires_resume_key = BITSETW(params+4,2);
563 int info_level = SVAL(params,6);
571 BOOL finished = False;
572 BOOL dont_descend = False;
573 BOOL out_of_space = False;
575 BOOL bad_path = False;
577 *directory = *mask = 0;
579 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",
580 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
581 info_level, max_data_bytes));
589 case SMB_FIND_FILE_DIRECTORY_INFO:
590 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
591 case SMB_FIND_FILE_NAMES_INFO:
592 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
595 return(ERROR(ERRDOS,ERRunknownlevel));
598 pstrcpy(directory, params + 12); /* Complete directory path with
599 wildcard mask appended */
601 DEBUG(5,("path=%s\n",directory));
603 unix_convert(directory,cnum,0,&bad_path);
604 if(!check_name(directory,cnum)) {
605 if((errno == ENOENT) && bad_path)
607 unix_ERR_class = ERRDOS;
608 unix_ERR_code = ERRbadpath;
610 return(ERROR(ERRDOS,ERRbadpath));
613 p = strrchr(directory,'/');
615 strcpy(mask,directory);
616 strcpy(directory,"./");
622 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
624 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
626 return(ERROR(ERRDOS,ERRnomem));
627 bzero(pdata,max_data_bytes);
629 /* Realloc the params space */
630 params = *pparams = Realloc(*pparams, 10);
632 return(ERROR(ERRDOS,ERRnomem));
634 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
639 if((errno == ENOENT) && bad_path)
641 unix_ERR_class = ERRDOS;
642 unix_ERR_code = ERRbadpath;
644 return (UNIXERROR(ERRDOS,ERRbadpath));
646 return(ERROR(ERRDOS,ERRbadpath));
649 /* convert the formatted masks */
653 if (*p == '<') *p = '*';
654 if (*p == '>') *p = '?';
655 if (*p == '"') *p = '.';
660 /* a special case for 16 bit apps */
661 if (strequal(mask,"????????.???")) strcpy(mask,"*");
663 /* handle broken clients that send us old 8.3 format */
664 string_sub(mask,"????????","*");
665 string_sub(mask,".???",".*");
667 /* Save the wildcard match and attribs we are using on this directory -
668 needed as lanman2 assumes these are being saved between calls */
670 if(!(wcard = strdup(mask))) {
671 dptr_close(dptr_num);
672 return(ERROR(ERRDOS,ERRnomem));
675 dptr_set_wcard(dptr_num, wcard);
676 dptr_set_attr(dptr_num, dirtype);
678 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
680 /* We don't need to check for VOL here as this is returned by
681 a different TRANS2 call. */
683 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
684 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
685 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
689 space_remaining = max_data_bytes;
690 out_of_space = False;
692 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
695 /* this is a heuristic to avoid seeking the dirptr except when
696 absolutely necessary. It allows for a filename of about 40 chars */
697 if (space_remaining < DIRLEN_GUESS && numentries > 0)
705 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
706 requires_resume_key,dont_descend,
707 &p,pdata,space_remaining, &out_of_space,
711 if (finished && out_of_space)
714 if (!finished && !out_of_space)
716 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
719 /* Check if we can close the dirptr */
720 if(close_after_first || (finished && close_if_end))
722 dptr_close(dptr_num);
723 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
727 /* At this point pdata points to numentries directory entries. */
729 /* Set up the return parameter block */
730 SSVAL(params,0,dptr_num);
731 SSVAL(params,2,numentries);
732 SSVAL(params,4,finished);
733 SSVAL(params,6,0); /* Never an EA error */
734 SSVAL(params,8,last_name_off);
736 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
738 if ((! *directory) && dptr_path(dptr_num))
739 sprintf(directory,"(%s)",dptr_path(dptr_num));
741 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
743 smb_fn_name(CVAL(inbuf,smb_com)),
744 mask,directory,cnum,dirtype,numentries));
750 /****************************************************************************
751 reply to a TRANS2_FINDNEXT
752 ****************************************************************************/
753 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
754 int cnum, char **pparams, char **ppdata)
756 /* We must be careful here that we don't return more than the
757 allowed number of data bytes. If this means returning fewer than
758 maxentries then so be it. We assume that the redirector has
759 enough room for the fixed number of parameter bytes it has
761 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
762 char *params = *pparams;
763 char *pdata = *ppdata;
764 int16 dptr_num = SVAL(params,0);
765 int maxentries = SVAL(params,2);
766 uint16 info_level = SVAL(params,4);
767 uint32 resume_key = IVAL(params,6);
768 BOOL close_after_request = BITSETW(params+10,0);
769 BOOL close_if_end = BITSETW(params+10,1);
770 BOOL requires_resume_key = BITSETW(params+10,2);
771 BOOL continue_bit = BITSETW(params+10,3);
777 int i, last_name_off=0;
778 BOOL finished = False;
779 BOOL dont_descend = False;
780 BOOL out_of_space = False;
783 *mask = *directory = 0;
785 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",
786 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
787 requires_resume_key, resume_key, continue_bit, info_level));
795 case SMB_FIND_FILE_DIRECTORY_INFO:
796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
797 case SMB_FIND_FILE_NAMES_INFO:
798 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
801 return(ERROR(ERRDOS,ERRunknownlevel));
804 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
806 return(ERROR(ERRDOS,ERRnomem));
807 bzero(pdata,max_data_bytes);
809 /* Realloc the params space */
810 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
812 return(ERROR(ERRDOS,ERRnomem));
814 /* Check that the dptr is valid */
815 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
816 return(ERROR(ERRDOS,ERRnofiles));
818 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
820 /* Get the wildcard mask from the dptr */
821 if((p = dptr_wcard(dptr_num))== NULL) {
822 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
823 return (ERROR(ERRDOS,ERRnofiles));
826 strcpy(directory,Connections[cnum].dirpath);
828 /* Get the attr mask from the dptr */
829 dirtype = dptr_attr(dptr_num);
831 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
832 dptr_num, mask, dirtype,
833 Connections[cnum].dirptr,
834 TellDir(Connections[cnum].dirptr)));
836 /* We don't need to check for VOL here as this is returned by
837 a different TRANS2 call. */
839 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
840 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
844 space_remaining = max_data_bytes;
845 out_of_space = False;
847 /* If we have a resume key - seek to the correct position. */
848 if(requires_resume_key && !continue_bit)
849 SeekDir(Connections[cnum].dirptr, resume_key);
851 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
853 /* this is a heuristic to avoid seeking the dirptr except when
854 absolutely necessary. It allows for a filename of about 40 chars */
855 if (space_remaining < DIRLEN_GUESS && numentries > 0)
863 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
864 requires_resume_key,dont_descend,
865 &p,pdata,space_remaining, &out_of_space,
869 if (finished && out_of_space)
872 if (!finished && !out_of_space)
874 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
877 /* Check if we can close the dirptr */
878 if(close_after_request || (finished && close_if_end))
880 dptr_close(dptr_num); /* This frees up the saved mask */
881 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
886 /* Set up the return parameter block */
887 SSVAL(params,0,numentries);
888 SSVAL(params,2,finished);
889 SSVAL(params,4,0); /* Never an EA error */
890 SSVAL(params,6,last_name_off);
892 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
894 if ((! *directory) && dptr_path(dptr_num))
895 sprintf(directory,"(%s)",dptr_path(dptr_num));
897 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
899 smb_fn_name(CVAL(inbuf,smb_com)),
900 mask,directory,cnum,dirtype,numentries));
905 /****************************************************************************
906 reply to a TRANS2_QFSINFO (query filesystem info)
907 ****************************************************************************/
908 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
909 int cnum, char **pparams, char **ppdata)
911 char *pdata = *ppdata;
912 char *params = *pparams;
913 uint16 info_level = SVAL(params,0);
916 char *vname = volume_label(SNUM(cnum));
918 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
920 if(sys_stat(".",&st)!=0) {
921 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
922 return (ERROR(ERRSRV,ERRinvdevice));
925 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
931 int dfree,dsize,bsize;
933 sys_disk_free(".",&bsize,&dfree,&dsize);
934 SIVAL(pdata,l1_idFileSystem,st.st_dev);
935 SIVAL(pdata,l1_cSectorUnit,bsize/512);
936 SIVAL(pdata,l1_cUnit,dsize);
937 SIVAL(pdata,l1_cUnitAvail,dfree);
938 SSVAL(pdata,l1_cbSector,512);
939 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
940 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
945 /* Return volume name */
946 int volname_len = MIN(strlen(vname),11);
947 data_len = l2_vol_szVolLabel + volname_len + 1;
948 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
949 SCVAL(pdata,l2_vol_cch,volname_len);
950 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
951 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
952 pdata+l2_vol_szVolLabel));
955 case SMB_QUERY_FS_ATTRIBUTE_INFO:
956 data_len = 12 + 2*strlen(FSTYPE_STRING);
957 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
958 SIVAL(pdata,4,128); /* Max filename component length */
959 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
960 PutUniCode(pdata+12,FSTYPE_STRING);
962 case SMB_QUERY_FS_LABEL_INFO:
963 data_len = 4 + strlen(vname);
964 SIVAL(pdata,0,strlen(vname));
965 strcpy(pdata+4,vname);
967 case SMB_QUERY_FS_VOLUME_INFO:
968 data_len = 18 + 2*strlen(vname);
969 SIVAL(pdata,12,2*strlen(vname));
970 PutUniCode(pdata+18,vname);
971 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
974 case SMB_QUERY_FS_SIZE_INFO:
976 int dfree,dsize,bsize;
978 sys_disk_free(".",&bsize,&dfree,&dsize);
979 SIVAL(pdata,0,dsize);
980 SIVAL(pdata,8,dfree);
981 SIVAL(pdata,16,bsize/512);
985 case SMB_QUERY_FS_DEVICE_INFO:
987 SIVAL(pdata,0,0); /* dev type */
988 SIVAL(pdata,4,0); /* characteristics */
991 return(ERROR(ERRDOS,ERRunknownlevel));
995 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
997 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1002 /****************************************************************************
1003 reply to a TRANS2_SETFSINFO (set filesystem info)
1004 ****************************************************************************/
1005 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1006 int cnum, char **pparams, char **ppdata)
1008 /* Just say yes we did it - there is nothing that
1009 can be set here so it doesn't matter. */
1011 DEBUG(3,("call_trans2setfsinfo\n"));
1013 if (!CAN_WRITE(cnum))
1014 return(ERROR(ERRSRV,ERRaccess));
1016 outsize = set_message(outbuf,10,0,True);
1021 /****************************************************************************
1022 reply to a TRANS2_QFILEINFO (query file info by fileid)
1023 ****************************************************************************/
1024 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1025 int bufsize,int cnum,
1026 char **pparams,char **ppdata,
1029 char *params = *pparams;
1030 char *pdata = *ppdata;
1031 uint16 tran_call = SVAL(inbuf, smb_setup0);
1035 unsigned int data_size;
1041 BOOL bad_path = False;
1043 if (tran_call == TRANSACT2_QFILEINFO) {
1044 int16 fnum = SVALS(params,0);
1045 info_level = SVAL(params,2);
1047 CHECK_FNUM(fnum,cnum);
1050 fname = Files[fnum].name;
1051 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1052 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1053 return(UNIXERROR(ERRDOS,ERRbadfid));
1055 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1058 info_level = SVAL(params,0);
1060 pstrcpy(fname,¶ms[6]);
1061 unix_convert(fname,cnum,0,&bad_path);
1062 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1063 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1064 if((errno == ENOENT) && bad_path)
1066 unix_ERR_class = ERRDOS;
1067 unix_ERR_code = ERRbadpath;
1069 return(UNIXERROR(ERRDOS,ERRbadpath));
1075 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1076 fname,info_level,tran_call,total_data));
1078 p = strrchr(fname,'/');
1084 mode = dos_mode(cnum,fname,&sbuf);
1085 size = sbuf.st_size;
1086 if (mode & aDIR) size = 0;
1088 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1090 pdata = *ppdata = Realloc(*ppdata, data_size);
1092 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1093 /* uggh, EAs for OS2 */
1094 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1095 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1098 bzero(pdata,data_size);
1102 case SMB_INFO_STANDARD:
1103 case SMB_INFO_QUERY_EA_SIZE:
1104 data_size = (info_level==1?22:26);
1105 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1106 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1107 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1108 SIVAL(pdata,l1_cbFile,size);
1109 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1110 SSVAL(pdata,l1_attrFile,mode);
1111 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1114 case SMB_INFO_QUERY_EAS_FROM_LIST:
1116 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1117 put_dos_date2(pdata,4,sbuf.st_atime);
1118 put_dos_date2(pdata,8,sbuf.st_mtime);
1119 SIVAL(pdata,12,size);
1120 SIVAL(pdata,16,ROUNDUP(size,1024));
1121 SIVAL(pdata,20,mode);
1124 case SMB_INFO_QUERY_ALL_EAS:
1126 SIVAL(pdata,0,data_size);
1130 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1132 case SMB_QUERY_FILE_BASIC_INFO:
1133 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1134 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1135 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1136 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1137 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1138 SIVAL(pdata,32,mode);
1140 DEBUG(5,("SMB_QFBI - "));
1141 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1142 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1143 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1144 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1145 DEBUG(5,("mode: %x\n", mode));
1149 case SMB_QUERY_FILE_STANDARD_INFO:
1151 SIVAL(pdata,0,size);
1152 SIVAL(pdata,8,size);
1153 SIVAL(pdata,16,sbuf.st_nlink);
1155 CVAL(pdata,21) = (mode&aDIR)?1:0;
1158 case SMB_QUERY_FILE_EA_INFO:
1162 case SMB_QUERY_FILE_NAME_INFO:
1163 case SMB_QUERY_FILE_ALT_NAME_INFO:
1166 pstrcpy(pdata+4,fname);
1168 case SMB_QUERY_FILE_ALLOCATION_INFO:
1169 case SMB_QUERY_FILE_END_OF_FILEINFO:
1171 SIVAL(pdata,0,size);
1174 case SMB_QUERY_FILE_ALL_INFO:
1175 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1176 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1177 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1178 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1179 SIVAL(pdata,32,mode);
1181 SIVAL(pdata,0,size);
1182 SIVAL(pdata,8,size);
1183 SIVAL(pdata,16,sbuf.st_nlink);
1185 CVAL(pdata,21) = (mode&aDIR)?1:0;
1187 pdata += 8; /* index number */
1188 pdata += 4; /* EA info */
1190 SIVAL(pdata,0,0xA9);
1192 SIVAL(pdata,0,0xd01BF);
1194 SIVAL(pdata,0,pos); /* current offset */
1196 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1198 pdata += 4; /* alignment */
1200 pstrcpy(pdata+4,fname);
1202 data_size = PTR_DIFF(pdata,(*ppdata));
1205 case SMB_QUERY_FILE_STREAM_INFO:
1208 SIVAL(pdata,4,size);
1209 SIVAL(pdata,12,size);
1211 pstrcpy(pdata+24,fname);
1214 return(ERROR(ERRDOS,ERRunknownlevel));
1217 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1222 /****************************************************************************
1223 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1224 ****************************************************************************/
1225 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1226 int bufsize, int cnum, char **pparams,
1227 char **ppdata, int total_data)
1229 char *params = *pparams;
1230 char *pdata = *ppdata;
1231 uint16 tran_call = SVAL(inbuf, smb_setup0);
1240 BOOL bad_path = False;
1242 if (!CAN_WRITE(cnum))
1243 return(ERROR(ERRSRV,ERRaccess));
1245 if (tran_call == TRANSACT2_SETFILEINFO) {
1246 int16 fnum = SVALS(params,0);
1247 info_level = SVAL(params,2);
1249 CHECK_FNUM(fnum,cnum);
1252 fname = Files[fnum].name;
1253 fd = Files[fnum].fd_ptr->fd;
1255 if(fstat(fd,&st)!=0) {
1256 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1257 return(ERROR(ERRDOS,ERRbadpath));
1261 info_level = SVAL(params,0);
1263 pstrcpy(fname,¶ms[6]);
1264 unix_convert(fname,cnum,0,&bad_path);
1265 if(!check_name(fname, cnum))
1267 if((errno == ENOENT) && bad_path)
1269 unix_ERR_class = ERRDOS;
1270 unix_ERR_code = ERRbadpath;
1272 return(UNIXERROR(ERRDOS,ERRbadpath));
1275 if(sys_stat(fname,&st)!=0) {
1276 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1277 if((errno == ENOENT) && bad_path)
1279 unix_ERR_class = ERRDOS;
1280 unix_ERR_code = ERRbadpath;
1282 return(UNIXERROR(ERRDOS,ERRbadpath));
1286 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1287 tran_call,fname,info_level,total_data));
1289 /* Realloc the parameter and data sizes */
1290 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1292 return(ERROR(ERRDOS,ERRnomem));
1295 tvs.modtime = st.st_mtime;
1296 tvs.actime = st.st_atime;
1297 mode = dos_mode(cnum,fname,&st);
1299 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1300 /* uggh, EAs for OS2 */
1301 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1302 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1307 case SMB_INFO_STANDARD:
1308 case SMB_INFO_QUERY_EA_SIZE:
1311 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1314 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1316 mode = SVAL(pdata,l1_attrFile);
1317 size = IVAL(pdata,l1_cbFile);
1321 /* XXXX um, i don't think this is right.
1322 it's also not in the cifs6.txt spec.
1324 case SMB_INFO_QUERY_EAS_FROM_LIST:
1325 tvs.actime = make_unix_date2(pdata+8);
1326 tvs.modtime = make_unix_date2(pdata+12);
1327 size = IVAL(pdata,16);
1328 mode = IVAL(pdata,24);
1331 /* XXXX nor this. not in cifs6.txt, either. */
1332 case SMB_INFO_QUERY_ALL_EAS:
1333 tvs.actime = make_unix_date2(pdata+8);
1334 tvs.modtime = make_unix_date2(pdata+12);
1335 size = IVAL(pdata,16);
1336 mode = IVAL(pdata,24);
1339 case SMB_SET_FILE_BASIC_INFO:
1341 /* Ignore create time at offset pdata. */
1344 tvs.actime = interpret_long_date(pdata+8);
1346 /* write time + changed time, combined. */
1347 tvs.modtime=MAX(interpret_long_date(pdata+16),
1348 interpret_long_date(pdata+24));
1350 #if 0 /* Needs more testing... */
1351 /* Test from Luke to prevent Win95 from
1352 setting incorrect values here.
1354 if (tvs.actime < tvs.modtime)
1355 return(ERROR(ERRDOS,ERRnoaccess));
1356 #endif /* Needs more testing... */
1359 mode = IVAL(pdata,32);
1363 case SMB_SET_FILE_END_OF_FILE_INFO:
1365 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1366 return(ERROR(ERRDOS,ERRunknownlevel));
1367 size = IVAL(pdata,0);
1371 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1372 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1375 return(ERROR(ERRDOS,ERRunknownlevel));
1379 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1380 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1381 DEBUG(6,("size: %x " , size));
1382 DEBUG(6,("mode: %x\n" , mode));
1384 /* get some defaults (no modifications) if any info is zero. */
1385 if (!tvs.actime) tvs.actime = st.st_atime;
1386 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1387 if (!size) size = st.st_size;
1389 /* Try and set the times, size and mode of this file -
1390 if they are different from the current values
1392 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1394 if(sys_utime(fname, &tvs)!=0)
1396 return(ERROR(ERRDOS,ERRnoaccess));
1400 /* check the mode isn't different, before changing it */
1401 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1403 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1404 return(ERROR(ERRDOS,ERRnoaccess));
1407 if(size != st.st_size)
1411 fd = sys_open(fname,O_RDWR,0);
1414 return(ERROR(ERRDOS,ERRbadpath));
1416 set_filelen(fd, size);
1421 set_filelen(fd, size);
1427 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1432 /****************************************************************************
1433 reply to a TRANS2_MKDIR (make directory with extended attributes).
1434 ****************************************************************************/
1435 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1436 int cnum, char **pparams, char **ppdata)
1438 char *params = *pparams;
1441 BOOL bad_path = False;
1443 if (!CAN_WRITE(cnum))
1444 return(ERROR(ERRSRV,ERRaccess));
1446 pstrcpy(directory, ¶ms[4]);
1448 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1450 unix_convert(directory,cnum,0,&bad_path);
1451 if (check_name(directory,cnum))
1452 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1456 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1457 if((errno == ENOENT) && bad_path)
1459 unix_ERR_class = ERRDOS;
1460 unix_ERR_code = ERRbadpath;
1462 return(UNIXERROR(ERRDOS,ERRnoaccess));
1465 /* Realloc the parameter and data sizes */
1466 params = *pparams = Realloc(*pparams,2);
1468 return(ERROR(ERRDOS,ERRnomem));
1472 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1477 /****************************************************************************
1478 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1479 We don't actually do this - we just send a null response.
1480 ****************************************************************************/
1481 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1482 int cnum, char **pparams, char **ppdata)
1484 static uint16 fnf_handle = 257;
1485 char *params = *pparams;
1486 uint16 info_level = SVAL(params,4);
1488 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1496 return(ERROR(ERRDOS,ERRunknownlevel));
1499 /* Realloc the parameter and data sizes */
1500 params = *pparams = Realloc(*pparams,6);
1502 return(ERROR(ERRDOS,ERRnomem));
1504 SSVAL(params,0,fnf_handle);
1505 SSVAL(params,2,0); /* No changes */
1506 SSVAL(params,4,0); /* No EA errors */
1513 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1518 /****************************************************************************
1519 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1520 changes). Currently this does nothing.
1521 ****************************************************************************/
1522 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1523 int cnum, char **pparams, char **ppdata)
1525 char *params = *pparams;
1527 DEBUG(3,("call_trans2findnotifynext\n"));
1529 /* Realloc the parameter and data sizes */
1530 params = *pparams = Realloc(*pparams,4);
1532 return(ERROR(ERRDOS,ERRnomem));
1534 SSVAL(params,0,0); /* No changes */
1535 SSVAL(params,2,0); /* No EA errors */
1537 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1542 /****************************************************************************
1543 reply to a SMBfindclose (stop trans2 directory search)
1544 ****************************************************************************/
1545 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1549 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1551 cnum = SVAL(inbuf,smb_tid);
1553 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1555 dptr_close(dptr_num);
1557 outsize = set_message(outbuf,0,0,True);
1559 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1564 /****************************************************************************
1565 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1566 ****************************************************************************/
1567 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1573 cnum = SVAL(inbuf,smb_tid);
1574 dptr_num = SVAL(inbuf,smb_vwv0);
1576 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1578 /* We never give out valid handles for a
1579 findnotifyfirst - so any dptr_num is ok here.
1582 outsize = set_message(outbuf,0,0,True);
1584 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1590 /****************************************************************************
1591 reply to a SMBtranss2 - just ignore it!
1592 ****************************************************************************/
1593 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1595 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1599 /****************************************************************************
1600 reply to a SMBtrans2
1601 ****************************************************************************/
1602 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1605 int cnum = SVAL(inbuf,smb_tid);
1606 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1607 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1609 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1610 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1611 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1612 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1613 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1614 int32 timeout = IVALS(inbuf,smb_timeout);
1616 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1617 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1618 char *params = NULL, *data = NULL;
1619 int num_params, num_params_sofar, num_data, num_data_sofar;
1621 outsize = set_message(outbuf,0,0,True);
1623 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1624 is so as a sanity check */
1627 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1628 return(ERROR(ERRSRV,ERRerror));
1631 /* Allocate the space for the maximum needed parameters and data */
1632 if (total_params > 0)
1633 params = (char *)malloc(total_params);
1635 data = (char *)malloc(total_data);
1637 if ((total_params && !params) || (total_data && !data))
1639 DEBUG(2,("Out of memory in reply_trans2\n"));
1640 return(ERROR(ERRDOS,ERRnomem));
1643 /* Copy the param and data bytes sent with this request into
1644 the params buffer */
1645 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1646 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1648 if (num_params > total_params || num_data > total_data)
1649 exit_server("invalid params in reply_trans2");
1651 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1652 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1654 if(num_data_sofar < total_data || num_params_sofar < total_params)
1656 /* We need to send an interim response then receive the rest
1657 of the parameter/data bytes */
1658 outsize = set_message(outbuf,0,0,True);
1659 send_smb(Client,outbuf);
1661 while( num_data_sofar < total_data || num_params_sofar < total_params)
1663 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1664 CVAL(inbuf, smb_com) != SMBtranss2)
1666 outsize = set_message(outbuf,0,0,True);
1667 DEBUG(2,("Invalid secondary trans2 packet\n"));
1670 return(ERROR(ERRSRV,ERRerror));
1673 /* Revise total_params and total_data in case they have changed downwards */
1674 total_params = SVAL(inbuf, smb_tpscnt);
1675 total_data = SVAL(inbuf, smb_tdscnt);
1676 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1677 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1678 if (num_params_sofar > total_params || num_data_sofar > total_data)
1679 exit_server("data overflow in trans2");
1681 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1682 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1683 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1684 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1688 if (Protocol >= PROTOCOL_NT1) {
1689 uint16 flg2 = SVAL(outbuf,smb_flg2);
1690 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1693 /* Now we must call the relevant TRANS2 function */
1696 case TRANSACT2_OPEN:
1697 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1699 case TRANSACT2_FINDFIRST:
1700 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1702 case TRANSACT2_FINDNEXT:
1703 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1705 case TRANSACT2_QFSINFO:
1706 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1708 case TRANSACT2_SETFSINFO:
1709 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1711 case TRANSACT2_QPATHINFO:
1712 case TRANSACT2_QFILEINFO:
1713 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1715 case TRANSACT2_SETPATHINFO:
1716 case TRANSACT2_SETFILEINFO:
1717 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1719 case TRANSACT2_FINDNOTIFYFIRST:
1720 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1722 case TRANSACT2_FINDNOTIFYNEXT:
1723 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1725 case TRANSACT2_MKDIR:
1726 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1729 /* Error in request */
1730 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1735 return (ERROR(ERRSRV,ERRerror));
1738 /* As we do not know how many data packets will need to be
1739 returned here the various call_trans2xxxx calls
1740 must send their own. Thus a call_trans2xxx routine only
1741 returns a value other than -1 when it wants to send
1749 return outsize; /* If a correct response was needed the call_trans2xxx
1750 calls have already sent it. If outsize != -1 then it is
1751 returning an error packet. */