2 Unix SMB/Netbios implementation.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1998
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;
33 extern int oplock_sock;
34 extern int smb_read_error;
36 /****************************************************************************
37 Send the required number of replies back.
38 We assume all fields other than the data fields are
39 set correctly for the type of call.
40 HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
43 int paramsize, char *pdata, int datasize)
45 /* As we are using a protocol > LANMAN1 then the max_send
46 variable must have been set in the sessetupX call.
47 This takes precedence over the max_xmit field in the
48 global struct. These different max_xmit variables should
49 be merged as this is now too confusing */
52 int data_to_send = datasize;
53 int params_to_send = paramsize;
57 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58 int alignment_offset = 3;
59 int data_alignment_offset = 0;
61 /* Initially set the wcnt area to be 10 - this is true for all
63 set_message(outbuf,10,0,True);
65 /* If there genuinely are no parameters or data to send just send
67 if(params_to_send == 0 && data_to_send == 0)
69 send_smb(Client,outbuf);
73 /* when sending params and data ensure that both are nicely aligned */
74 if ((params_to_send % 4) != 0)
75 data_alignment_offset = 4 - (params_to_send % 4);
77 /* Space is bufsize minus Netbios over TCP header minus SMB header */
78 /* The alignment_offset is to align the param bytes on an even byte
79 boundary. NT 4.0 Beta needs this to work correctly. */
80 useable_space = bufsize - ((smb_buf(outbuf)+
81 alignment_offset+data_alignment_offset) -
84 /* useable_space can never be more than max_send minus the
86 useable_space = MIN(useable_space,
87 max_send - (alignment_offset+data_alignment_offset));
90 while (params_to_send || data_to_send)
92 /* Calculate whether we will totally or partially fill this packet */
93 total_sent_thistime = params_to_send + data_to_send +
94 alignment_offset + data_alignment_offset;
95 /* We can never send more than useable_space */
96 total_sent_thistime = MIN(total_sent_thistime, useable_space);
98 set_message(outbuf, 10, total_sent_thistime, True);
100 /* Set total params and data to be sent */
101 SSVAL(outbuf,smb_tprcnt,paramsize);
102 SSVAL(outbuf,smb_tdrcnt,datasize);
104 /* Calculate how many parameters and data we can fit into
105 this packet. Parameters get precedence */
107 params_sent_thistime = MIN(params_to_send,useable_space);
108 data_sent_thistime = useable_space - params_sent_thistime;
109 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
111 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
112 if(params_sent_thistime == 0)
114 SSVAL(outbuf,smb_proff,0);
115 SSVAL(outbuf,smb_prdisp,0);
117 /* smb_proff is the offset from the start of the SMB header to the
118 parameter bytes, however the first 4 bytes of outbuf are
119 the Netbios over TCP header. Thus use smb_base() to subtract
120 them from the calculation */
121 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
122 /* Absolute displacement of param bytes sent in this packet */
123 SSVAL(outbuf,smb_prdisp,pp - params);
126 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
127 if(data_sent_thistime == 0)
129 SSVAL(outbuf,smb_droff,0);
130 SSVAL(outbuf,smb_drdisp, 0);
132 /* The offset of the data bytes is the offset of the
133 parameter bytes plus the number of parameters being sent this time */
134 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
136 params_sent_thistime + data_alignment_offset);
137 SSVAL(outbuf,smb_drdisp, pd - pdata);
140 /* Copy the param bytes into the packet */
141 if(params_sent_thistime)
142 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
143 /* Copy in the data bytes */
144 if(data_sent_thistime)
145 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime);
147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
148 params_sent_thistime, data_sent_thistime, useable_space));
149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
150 params_to_send, data_to_send, paramsize, datasize));
152 /* Send the packet */
153 send_smb(Client,outbuf);
155 pp += params_sent_thistime;
156 pd += data_sent_thistime;
158 params_to_send -= params_sent_thistime;
159 data_to_send -= data_sent_thistime;
162 if(params_to_send < 0 || data_to_send < 0)
164 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
165 params_to_send, data_to_send));
174 /****************************************************************************
175 reply to a TRANSACT2_OPEN
176 ****************************************************************************/
177 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
178 char **pparams, char **ppdata)
180 char *params = *pparams;
181 int16 open_mode = SVAL(params, 2);
182 int16 open_attr = SVAL(params,6);
183 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
185 BOOL return_additional_info = BITSETW(params,0);
186 int16 open_sattr = SVAL(params, 4);
187 time_t open_time = make_unix_date3(params+8);
189 int16 open_ofun = SVAL(params,12);
190 int32 open_size = IVAL(params,14);
191 char *pname = ¶ms[28];
192 int16 namelen = strlen(pname)+1;
197 int size=0,fmode=0,mtime=0,rmode;
201 BOOL bad_path = False;
203 StrnCpy(fname,pname,namelen);
205 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
206 fname,cnum,open_mode, open_attr, open_ofun, open_size));
208 /* XXXX we need to handle passed times, sattr and flags */
210 unix_convert(fname,cnum,0,&bad_path);
212 fnum = find_free_file();
214 return(ERROR(ERRSRV,ERRnofids));
216 if (!check_name(fname,cnum))
218 if((errno == ENOENT) && bad_path)
220 unix_ERR_class = ERRDOS;
221 unix_ERR_code = ERRbadpath;
223 Files[fnum].reserved = False;
224 return(UNIXERROR(ERRDOS,ERRnoaccess));
227 unixmode = unix_mode(cnum,open_attr | aARCH);
230 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
231 oplock_request, &rmode,&smb_action);
233 if (!Files[fnum].open)
235 if((errno == ENOENT) && bad_path)
237 unix_ERR_class = ERRDOS;
238 unix_ERR_code = ERRbadpath;
240 Files[fnum].reserved = False;
241 return(UNIXERROR(ERRDOS,ERRnoaccess));
244 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
245 close_file(fnum,False);
246 return(ERROR(ERRDOS,ERRnoaccess));
250 fmode = dos_mode(cnum,fname,&sbuf);
251 mtime = sbuf.st_mtime;
254 close_file(fnum,False);
255 return(ERROR(ERRDOS,ERRnoaccess));
258 /* Realloc the size of parameters and data we will return */
259 params = *pparams = Realloc(*pparams, 28);
261 return(ERROR(ERRDOS,ERRnomem));
264 SSVAL(params,0,fnum);
265 SSVAL(params,2,fmode);
266 put_dos_date2(params,4, mtime);
267 SIVAL(params,8, size);
268 SSVAL(params,12,rmode);
270 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
271 smb_action |= EXTENDED_OPLOCK_GRANTED;
274 SSVAL(params,18,smb_action);
275 SIVAL(params,20,inode);
277 /* Send the required number of replies */
278 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
283 /****************************************************************************
284 get a level dependent lanman2 dir entry.
285 ****************************************************************************/
286 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
287 int requires_resume_key,
288 BOOL dont_descend,char **ppdata,
289 char *base_data, int space_remaining,
300 char *p, *pdata = *ppdata;
301 int reskey=0, prev_dirpos=0;
304 uint32 mdate=0, adate=0, cdate=0;
306 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
307 strequal(Connections[cnum].dirpath,".") ||
308 strequal(Connections[cnum].dirpath,"/"));
310 int nt_extmode; /* Used for NT connections instead of mode */
311 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
314 *out_of_space = False;
316 if (!Connections[cnum].dirptr)
319 p = strrchr(path_mask,'/');
328 pstrcpy(mask, path_mask);
332 /* Needed if we run out of space */
333 prev_dirpos = TellDir(Connections[cnum].dirptr);
334 dname = ReadDirName(Connections[cnum].dirptr);
336 reskey = TellDir(Connections[cnum].dirptr);
338 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
339 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
346 pstrcpy(fname,dname);
348 if(mask_match(fname, mask, case_sensitive, True))
350 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
351 if (dont_descend && !isdots)
354 if (isrootdir && isdots)
357 pstrcpy(pathreal,Connections[cnum].dirpath);
359 strcat(pathreal,"/");
360 strcat(pathreal,dname);
361 if (sys_stat(pathreal,&sbuf) != 0)
363 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
367 mode = dos_mode(cnum,pathreal,&sbuf);
369 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
370 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
375 mdate = sbuf.st_mtime;
376 adate = sbuf.st_atime;
377 cdate = get_create_time(&sbuf);
381 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
387 name_map_mangle(fname,False,SNUM(cnum));
392 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
397 if(requires_resume_key) {
401 put_dos_date2(p,l1_fdateCreation,cdate);
402 put_dos_date2(p,l1_fdateLastAccess,adate);
403 put_dos_date2(p,l1_fdateLastWrite,mdate);
404 SIVAL(p,l1_cbFile,size);
405 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
406 SSVAL(p,l1_attrFile,mode);
407 SCVAL(p,l1_cchName,strlen(fname));
408 strcpy(p + l1_achName, fname);
409 nameptr = p + l1_achName;
410 p += l1_achName + strlen(fname) + 1;
415 if(requires_resume_key) {
419 put_dos_date2(p,l2_fdateCreation,cdate);
420 put_dos_date2(p,l2_fdateLastAccess,adate);
421 put_dos_date2(p,l2_fdateLastWrite,mdate);
422 SIVAL(p,l2_cbFile,size);
423 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
424 SSVAL(p,l2_attrFile,mode);
425 SIVAL(p,l2_cbList,0); /* No extended attributes */
426 SCVAL(p,l2_cchName,strlen(fname));
427 strcpy(p + l2_achName, fname);
428 nameptr = p + l2_achName;
429 p += l2_achName + strlen(fname) + 1;
434 put_dos_date2(p,4,cdate);
435 put_dos_date2(p,8,adate);
436 put_dos_date2(p,12,mdate);
438 SIVAL(p,20,ROUNDUP(size,1024));
441 CVAL(p,30) = strlen(fname);
444 p += 31 + strlen(fname) + 1;
448 if(requires_resume_key) {
452 SIVAL(p,0,33+strlen(fname)+1);
453 put_dos_date2(p,4,cdate);
454 put_dos_date2(p,8,adate);
455 put_dos_date2(p,12,mdate);
457 SIVAL(p,20,ROUNDUP(size,1024));
459 CVAL(p,32) = strlen(fname);
460 strcpy(p + 33, fname);
462 p += 33 + strlen(fname) + 1;
465 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
466 was_8_3 = is_8_3(fname, True);
467 len = 94+strlen(fname);
468 len = (len + 3) & ~3;
469 SIVAL(p,0,len); p += 4;
470 SIVAL(p,0,reskey); p += 4;
471 put_long_date(p,cdate); p += 8;
472 put_long_date(p,adate); p += 8;
473 put_long_date(p,mdate); p += 8;
474 put_long_date(p,mdate); p += 8;
475 SIVAL(p,0,size); p += 8;
476 SIVAL(p,0,size); p += 8;
477 SIVAL(p,0,nt_extmode); p += 4;
478 SIVAL(p,0,strlen(fname)); p += 4;
479 SIVAL(p,0,0); p += 4;
482 if (!name_map_mangle(p+2,True,SNUM(cnum)))
487 SSVAL(p,0,strlen(p+2));
490 strcpy(p,fname); p += strlen(p);
494 case SMB_FIND_FILE_DIRECTORY_INFO:
495 len = 64+strlen(fname);
496 len = (len + 3) & ~3;
497 SIVAL(p,0,len); p += 4;
498 SIVAL(p,0,reskey); p += 4;
499 put_long_date(p,cdate); p += 8;
500 put_long_date(p,adate); p += 8;
501 put_long_date(p,mdate); p += 8;
502 put_long_date(p,mdate); p += 8;
503 SIVAL(p,0,size); p += 8;
504 SIVAL(p,0,size); p += 8;
505 SIVAL(p,0,nt_extmode); p += 4;
506 SIVAL(p,0,strlen(fname)); p += 4;
512 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
513 len = 68+strlen(fname);
514 len = (len + 3) & ~3;
515 SIVAL(p,0,len); p += 4;
516 SIVAL(p,0,reskey); p += 4;
517 put_long_date(p,cdate); p += 8;
518 put_long_date(p,adate); p += 8;
519 put_long_date(p,mdate); p += 8;
520 put_long_date(p,mdate); p += 8;
521 SIVAL(p,0,size); p += 8;
522 SIVAL(p,0,size); p += 8;
523 SIVAL(p,0,nt_extmode); p += 4;
524 SIVAL(p,0,strlen(fname)); p += 4;
525 SIVAL(p,0,0); p += 4;
530 case SMB_FIND_FILE_NAMES_INFO:
531 len = 12+strlen(fname);
532 len = (len + 3) & ~3;
533 SIVAL(p,0,len); p += 4;
534 SIVAL(p,0,reskey); p += 4;
535 SIVAL(p,0,strlen(fname)); p += 4;
545 if (PTR_DIFF(p,pdata) > space_remaining) {
546 /* Move the dirptr back to prev_dirpos */
547 SeekDir(Connections[cnum].dirptr, prev_dirpos);
548 *out_of_space = True;
549 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
550 return False; /* Not finished - just out of space */
553 /* Setup the last_filename pointer, as an offset from base_data */
554 *last_name_off = PTR_DIFF(nameptr,base_data);
555 /* Advance the data pointer to the next slot */
560 /****************************************************************************
561 reply to a TRANS2_FINDFIRST
562 ****************************************************************************/
563 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
564 char **pparams, char **ppdata)
566 /* We must be careful here that we don't return more than the
567 allowed number of data bytes. If this means returning fewer than
568 maxentries then so be it. We assume that the redirector has
569 enough room for the fixed number of parameter bytes it has
571 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
572 char *params = *pparams;
573 char *pdata = *ppdata;
574 int dirtype = SVAL(params,0);
575 int maxentries = SVAL(params,2);
576 BOOL close_after_first = BITSETW(params+4,0);
577 BOOL close_if_end = BITSETW(params+4,1);
578 BOOL requires_resume_key = BITSETW(params+4,2);
579 int info_level = SVAL(params,6);
587 BOOL finished = False;
588 BOOL dont_descend = False;
589 BOOL out_of_space = False;
591 BOOL bad_path = False;
593 *directory = *mask = 0;
595 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",
596 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
597 info_level, max_data_bytes));
605 case SMB_FIND_FILE_DIRECTORY_INFO:
606 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
607 case SMB_FIND_FILE_NAMES_INFO:
608 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
611 return(ERROR(ERRDOS,ERRunknownlevel));
614 pstrcpy(directory, params + 12); /* Complete directory path with
615 wildcard mask appended */
617 DEBUG(5,("path=%s\n",directory));
619 unix_convert(directory,cnum,0,&bad_path);
620 if(!check_name(directory,cnum)) {
621 if((errno == ENOENT) && bad_path)
623 unix_ERR_class = ERRDOS;
624 unix_ERR_code = ERRbadpath;
628 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
629 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
630 (get_remote_arch() == RA_WINNT))
632 unix_ERR_class = ERRDOS;
633 unix_ERR_code = ERRbaddirectory;
637 return(ERROR(ERRDOS,ERRbadpath));
640 p = strrchr(directory,'/');
642 strcpy(mask,directory);
643 strcpy(directory,"./");
649 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
651 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
653 return(ERROR(ERRDOS,ERRnomem));
654 bzero(pdata,max_data_bytes);
656 /* Realloc the params space */
657 params = *pparams = Realloc(*pparams, 10);
659 return(ERROR(ERRDOS,ERRnomem));
661 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
663 return(ERROR(ERRDOS,ERRbadfile));
665 /* convert the formatted masks */
669 if (*p == '<') *p = '*';
670 if (*p == '>') *p = '?';
671 if (*p == '"') *p = '.';
676 /* a special case for 16 bit apps */
677 if (strequal(mask,"????????.???")) strcpy(mask,"*");
679 /* handle broken clients that send us old 8.3 format */
680 string_sub(mask,"????????","*");
681 string_sub(mask,".???",".*");
683 /* Save the wildcard match and attribs we are using on this directory -
684 needed as lanman2 assumes these are being saved between calls */
686 if(!(wcard = strdup(mask))) {
687 dptr_close(dptr_num);
688 return(ERROR(ERRDOS,ERRnomem));
691 dptr_set_wcard(dptr_num, wcard);
692 dptr_set_attr(dptr_num, dirtype);
694 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
696 /* We don't need to check for VOL here as this is returned by
697 a different TRANS2 call. */
699 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
700 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
701 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
705 space_remaining = max_data_bytes;
706 out_of_space = False;
708 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
711 /* this is a heuristic to avoid seeking the dirptr except when
712 absolutely necessary. It allows for a filename of about 40 chars */
713 if (space_remaining < DIRLEN_GUESS && numentries > 0)
721 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
722 requires_resume_key,dont_descend,
723 &p,pdata,space_remaining, &out_of_space,
727 if (finished && out_of_space)
730 if (!finished && !out_of_space)
732 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
735 /* Check if we can close the dirptr */
736 if(close_after_first || (finished && close_if_end))
738 dptr_close(dptr_num);
739 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
744 * If there are no matching entries we must return ERRDOS/ERRbadfile -
745 * from observation of NT.
749 return(ERROR(ERRDOS,ERRbadfile));
751 /* At this point pdata points to numentries directory entries. */
753 /* Set up the return parameter block */
754 SSVAL(params,0,dptr_num);
755 SSVAL(params,2,numentries);
756 SSVAL(params,4,finished);
757 SSVAL(params,6,0); /* Never an EA error */
758 SSVAL(params,8,last_name_off);
760 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
762 if ((! *directory) && dptr_path(dptr_num))
763 sprintf(directory,"(%s)",dptr_path(dptr_num));
765 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
767 smb_fn_name(CVAL(inbuf,smb_com)),
768 mask,directory,cnum,dirtype,numentries));
774 /****************************************************************************
775 reply to a TRANS2_FINDNEXT
776 ****************************************************************************/
777 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
778 int cnum, char **pparams, char **ppdata)
780 /* We must be careful here that we don't return more than the
781 allowed number of data bytes. If this means returning fewer than
782 maxentries then so be it. We assume that the redirector has
783 enough room for the fixed number of parameter bytes it has
785 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
786 char *params = *pparams;
787 char *pdata = *ppdata;
788 int16 dptr_num = SVAL(params,0);
789 int maxentries = SVAL(params,2);
790 uint16 info_level = SVAL(params,4);
791 uint32 resume_key = IVAL(params,6);
792 BOOL close_after_request = BITSETW(params+10,0);
793 BOOL close_if_end = BITSETW(params+10,1);
794 BOOL requires_resume_key = BITSETW(params+10,2);
795 BOOL continue_bit = BITSETW(params+10,3);
801 int i, last_name_off=0;
802 BOOL finished = False;
803 BOOL dont_descend = False;
804 BOOL out_of_space = False;
807 *mask = *directory = 0;
809 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",
810 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
811 requires_resume_key, resume_key, continue_bit, info_level));
819 case SMB_FIND_FILE_DIRECTORY_INFO:
820 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
821 case SMB_FIND_FILE_NAMES_INFO:
822 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
825 return(ERROR(ERRDOS,ERRunknownlevel));
828 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
830 return(ERROR(ERRDOS,ERRnomem));
831 bzero(pdata,max_data_bytes);
833 /* Realloc the params space */
834 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
836 return(ERROR(ERRDOS,ERRnomem));
838 /* Check that the dptr is valid */
839 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
840 return(ERROR(ERRDOS,ERRnofiles));
842 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
844 /* Get the wildcard mask from the dptr */
845 if((p = dptr_wcard(dptr_num))== NULL) {
846 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
847 return (ERROR(ERRDOS,ERRnofiles));
850 strcpy(directory,Connections[cnum].dirpath);
852 /* Get the attr mask from the dptr */
853 dirtype = dptr_attr(dptr_num);
855 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
856 dptr_num, mask, dirtype,
857 Connections[cnum].dirptr,
858 TellDir(Connections[cnum].dirptr)));
860 /* We don't need to check for VOL here as this is returned by
861 a different TRANS2 call. */
863 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
864 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
868 space_remaining = max_data_bytes;
869 out_of_space = False;
871 /* If we have a resume key - seek to the correct position. */
872 if(requires_resume_key && !continue_bit)
873 SeekDir(Connections[cnum].dirptr, resume_key);
875 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
877 /* this is a heuristic to avoid seeking the dirptr except when
878 absolutely necessary. It allows for a filename of about 40 chars */
879 if (space_remaining < DIRLEN_GUESS && numentries > 0)
887 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
888 requires_resume_key,dont_descend,
889 &p,pdata,space_remaining, &out_of_space,
893 if (finished && out_of_space)
896 if (!finished && !out_of_space)
898 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
901 /* Check if we can close the dirptr */
902 if(close_after_request || (finished && close_if_end))
904 dptr_close(dptr_num); /* This frees up the saved mask */
905 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
910 /* Set up the return parameter block */
911 SSVAL(params,0,numentries);
912 SSVAL(params,2,finished);
913 SSVAL(params,4,0); /* Never an EA error */
914 SSVAL(params,6,last_name_off);
916 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
918 if ((! *directory) && dptr_path(dptr_num))
919 sprintf(directory,"(%s)",dptr_path(dptr_num));
921 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
923 smb_fn_name(CVAL(inbuf,smb_com)),
924 mask,directory,cnum,dirtype,numentries));
929 /****************************************************************************
930 reply to a TRANS2_QFSINFO (query filesystem info)
931 ****************************************************************************/
932 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
933 int cnum, char **pparams, char **ppdata)
935 char *pdata = *ppdata;
936 char *params = *pparams;
937 uint16 info_level = SVAL(params,0);
940 char *vname = volume_label(SNUM(cnum));
942 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
944 if(sys_stat(".",&st)!=0) {
945 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
946 return (ERROR(ERRSRV,ERRinvdevice));
949 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
955 int dfree,dsize,bsize;
957 sys_disk_free(".",&bsize,&dfree,&dsize);
958 SIVAL(pdata,l1_idFileSystem,st.st_dev);
959 SIVAL(pdata,l1_cSectorUnit,bsize/512);
960 SIVAL(pdata,l1_cUnit,dsize);
961 SIVAL(pdata,l1_cUnitAvail,dfree);
962 SSVAL(pdata,l1_cbSector,512);
963 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
964 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
969 /* Return volume name */
970 int volname_len = MIN(strlen(vname),11);
971 data_len = l2_vol_szVolLabel + volname_len + 1;
972 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
973 SCVAL(pdata,l2_vol_cch,volname_len);
974 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
975 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
976 pdata+l2_vol_szVolLabel));
979 case SMB_QUERY_FS_ATTRIBUTE_INFO:
980 data_len = 12 + 2*strlen(FSTYPE_STRING);
981 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
982 SIVAL(pdata,4,128); /* Max filename component length */
983 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
984 PutUniCode(pdata+12,FSTYPE_STRING);
986 case SMB_QUERY_FS_LABEL_INFO:
987 data_len = 4 + strlen(vname);
988 SIVAL(pdata,0,strlen(vname));
989 strcpy(pdata+4,vname);
991 case SMB_QUERY_FS_VOLUME_INFO:
992 data_len = 18 + 2*strlen(vname);
993 SIVAL(pdata,12,2*strlen(vname));
994 PutUniCode(pdata+18,vname);
995 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
998 case SMB_QUERY_FS_SIZE_INFO:
1000 int dfree,dsize,bsize;
1002 sys_disk_free(".",&bsize,&dfree,&dsize);
1003 SIVAL(pdata,0,dsize);
1004 SIVAL(pdata,8,dfree);
1005 SIVAL(pdata,16,bsize/512);
1006 SIVAL(pdata,20,512);
1009 case SMB_QUERY_FS_DEVICE_INFO:
1011 SIVAL(pdata,0,0); /* dev type */
1012 SIVAL(pdata,4,0); /* characteristics */
1015 return(ERROR(ERRDOS,ERRunknownlevel));
1019 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1021 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1026 /****************************************************************************
1027 reply to a TRANS2_SETFSINFO (set filesystem info)
1028 ****************************************************************************/
1029 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1030 int cnum, char **pparams, char **ppdata)
1032 /* Just say yes we did it - there is nothing that
1033 can be set here so it doesn't matter. */
1035 DEBUG(3,("call_trans2setfsinfo\n"));
1037 if (!CAN_WRITE(cnum))
1038 return(ERROR(ERRSRV,ERRaccess));
1040 outsize = set_message(outbuf,10,0,True);
1045 /****************************************************************************
1046 reply to a TRANS2_QFILEINFO (query file info by fileid)
1047 ****************************************************************************/
1048 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1049 int bufsize,int cnum,
1050 char **pparams,char **ppdata,
1053 char *params = *pparams;
1054 char *pdata = *ppdata;
1055 uint16 tran_call = SVAL(inbuf, smb_setup0);
1059 unsigned int data_size;
1065 BOOL bad_path = False;
1067 if (tran_call == TRANSACT2_QFILEINFO) {
1068 int16 fnum = SVALS(params,0);
1069 info_level = SVAL(params,2);
1071 CHECK_FNUM(fnum,cnum);
1074 fname = Files[fnum].name;
1075 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1076 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1077 return(UNIXERROR(ERRDOS,ERRbadfid));
1079 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1082 info_level = SVAL(params,0);
1084 pstrcpy(fname,¶ms[6]);
1085 unix_convert(fname,cnum,0,&bad_path);
1086 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1087 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1088 if((errno == ENOENT) && bad_path)
1090 unix_ERR_class = ERRDOS;
1091 unix_ERR_code = ERRbadpath;
1093 return(UNIXERROR(ERRDOS,ERRbadpath));
1099 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1100 fname,info_level,tran_call,total_data));
1102 p = strrchr(fname,'/');
1108 mode = dos_mode(cnum,fname,&sbuf);
1109 size = sbuf.st_size;
1110 if (mode & aDIR) size = 0;
1112 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1114 pdata = *ppdata = Realloc(*ppdata, data_size);
1116 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1117 /* uggh, EAs for OS2 */
1118 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1119 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1122 bzero(pdata,data_size);
1126 case SMB_INFO_STANDARD:
1127 case SMB_INFO_QUERY_EA_SIZE:
1128 data_size = (info_level==1?22:26);
1129 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf));
1130 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1131 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1132 SIVAL(pdata,l1_cbFile,size);
1133 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1134 SSVAL(pdata,l1_attrFile,mode);
1135 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1138 case SMB_INFO_QUERY_EAS_FROM_LIST:
1140 put_dos_date2(pdata,0,get_create_time(&sbuf));
1141 put_dos_date2(pdata,4,sbuf.st_atime);
1142 put_dos_date2(pdata,8,sbuf.st_mtime);
1143 SIVAL(pdata,12,size);
1144 SIVAL(pdata,16,ROUNDUP(size,1024));
1145 SIVAL(pdata,20,mode);
1148 case SMB_INFO_QUERY_ALL_EAS:
1150 SIVAL(pdata,0,data_size);
1154 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1156 case SMB_QUERY_FILE_BASIC_INFO:
1157 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1158 put_long_date(pdata,get_create_time(&sbuf));
1159 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1160 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1161 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1162 SIVAL(pdata,32,mode);
1164 DEBUG(5,("SMB_QFBI - "));
1166 time_t create_time = get_create_time(&sbuf);
1167 DEBUG(5,("create: %s ", ctime(&create_time)));
1169 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1170 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1171 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1172 DEBUG(5,("mode: %x\n", mode));
1176 case SMB_QUERY_FILE_STANDARD_INFO:
1178 SIVAL(pdata,0,size);
1179 SIVAL(pdata,8,size);
1180 SIVAL(pdata,16,sbuf.st_nlink);
1182 CVAL(pdata,21) = (mode&aDIR)?1:0;
1185 case SMB_QUERY_FILE_EA_INFO:
1189 /* Get the 8.3 name - used if NT SMB was negotiated. */
1190 case SMB_QUERY_FILE_ALT_NAME_INFO:
1193 pstrcpy(short_name,fname);
1194 /* Mangle if not already 8.3 */
1195 if(!is_8_3(short_name, True))
1197 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1200 strncpy(pdata + 4,short_name,12);
1201 (pdata + 4)[12] = 0;
1202 strupper(pdata + 4);
1203 l = strlen(pdata + 4);
1209 case SMB_QUERY_FILE_NAME_INFO:
1212 pstrcpy(pdata+4,fname);
1215 case SMB_QUERY_FILE_ALLOCATION_INFO:
1216 case SMB_QUERY_FILE_END_OF_FILEINFO:
1218 SIVAL(pdata,0,size);
1221 case SMB_QUERY_FILE_ALL_INFO:
1222 put_long_date(pdata,get_create_time(&sbuf));
1223 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1224 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1225 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1226 SIVAL(pdata,32,mode);
1228 SIVAL(pdata,0,size);
1229 SIVAL(pdata,8,size);
1230 SIVAL(pdata,16,sbuf.st_nlink);
1232 CVAL(pdata,21) = (mode&aDIR)?1:0;
1234 pdata += 8; /* index number */
1235 pdata += 4; /* EA info */
1237 SIVAL(pdata,0,0xA9);
1239 SIVAL(pdata,0,0xd01BF);
1241 SIVAL(pdata,0,pos); /* current offset */
1243 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1245 pdata += 4; /* alignment */
1247 pstrcpy(pdata+4,fname);
1249 data_size = PTR_DIFF(pdata,(*ppdata));
1252 case SMB_QUERY_FILE_STREAM_INFO:
1255 SIVAL(pdata,4,size);
1256 SIVAL(pdata,12,size);
1258 pstrcpy(pdata+24,fname);
1261 return(ERROR(ERRDOS,ERRunknownlevel));
1264 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1269 /****************************************************************************
1270 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1271 ****************************************************************************/
1272 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1273 int bufsize, int cnum, char **pparams,
1274 char **ppdata, int total_data)
1276 char *params = *pparams;
1277 char *pdata = *ppdata;
1278 uint16 tran_call = SVAL(inbuf, smb_setup0);
1287 BOOL bad_path = False;
1289 if (!CAN_WRITE(cnum))
1290 return(ERROR(ERRSRV,ERRaccess));
1292 if (tran_call == TRANSACT2_SETFILEINFO) {
1293 int16 fnum = SVALS(params,0);
1294 info_level = SVAL(params,2);
1296 CHECK_FNUM(fnum,cnum);
1299 fname = Files[fnum].name;
1300 fd = Files[fnum].fd_ptr->fd;
1302 if(fstat(fd,&st)!=0) {
1303 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1304 return(ERROR(ERRDOS,ERRbadpath));
1308 info_level = SVAL(params,0);
1310 pstrcpy(fname,¶ms[6]);
1311 unix_convert(fname,cnum,0,&bad_path);
1312 if(!check_name(fname, cnum))
1314 if((errno == ENOENT) && bad_path)
1316 unix_ERR_class = ERRDOS;
1317 unix_ERR_code = ERRbadpath;
1319 return(UNIXERROR(ERRDOS,ERRbadpath));
1322 if(sys_stat(fname,&st)!=0) {
1323 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1324 if((errno == ENOENT) && bad_path)
1326 unix_ERR_class = ERRDOS;
1327 unix_ERR_code = ERRbadpath;
1329 return(UNIXERROR(ERRDOS,ERRbadpath));
1333 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1334 tran_call,fname,info_level,total_data));
1336 /* Realloc the parameter and data sizes */
1337 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1339 return(ERROR(ERRDOS,ERRnomem));
1342 tvs.modtime = st.st_mtime;
1343 tvs.actime = st.st_atime;
1344 mode = dos_mode(cnum,fname,&st);
1346 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1347 /* uggh, EAs for OS2 */
1348 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1349 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1354 case SMB_INFO_STANDARD:
1355 case SMB_INFO_QUERY_EA_SIZE:
1358 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1361 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1363 mode = SVAL(pdata,l1_attrFile);
1364 size = IVAL(pdata,l1_cbFile);
1368 /* XXXX um, i don't think this is right.
1369 it's also not in the cifs6.txt spec.
1371 case SMB_INFO_QUERY_EAS_FROM_LIST:
1372 tvs.actime = make_unix_date2(pdata+8);
1373 tvs.modtime = make_unix_date2(pdata+12);
1374 size = IVAL(pdata,16);
1375 mode = IVAL(pdata,24);
1378 /* XXXX nor this. not in cifs6.txt, either. */
1379 case SMB_INFO_QUERY_ALL_EAS:
1380 tvs.actime = make_unix_date2(pdata+8);
1381 tvs.modtime = make_unix_date2(pdata+12);
1382 size = IVAL(pdata,16);
1383 mode = IVAL(pdata,24);
1386 case SMB_SET_FILE_BASIC_INFO:
1388 /* Ignore create time at offset pdata. */
1391 tvs.actime = interpret_long_date(pdata+8);
1393 /* write time + changed time, combined. */
1394 tvs.modtime=MAX(interpret_long_date(pdata+16),
1395 interpret_long_date(pdata+24));
1397 #if 0 /* Needs more testing... */
1398 /* Test from Luke to prevent Win95 from
1399 setting incorrect values here.
1401 if (tvs.actime < tvs.modtime)
1402 return(ERROR(ERRDOS,ERRnoaccess));
1403 #endif /* Needs more testing... */
1406 mode = IVAL(pdata,32);
1410 case SMB_SET_FILE_END_OF_FILE_INFO:
1412 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1413 return(ERROR(ERRDOS,ERRunknownlevel));
1414 size = IVAL(pdata,0);
1418 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1419 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1422 return(ERROR(ERRDOS,ERRunknownlevel));
1426 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1427 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1428 DEBUG(6,("size: %x " , size));
1429 DEBUG(6,("mode: %x\n" , mode));
1431 /* get some defaults (no modifications) if any info is zero. */
1432 if (!tvs.actime) tvs.actime = st.st_atime;
1433 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1434 if (!size) size = st.st_size;
1436 /* Try and set the times, size and mode of this file -
1437 if they are different from the current values
1439 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1441 if(file_utime(cnum, fname, &tvs)!=0)
1443 return(ERROR(ERRDOS,ERRnoaccess));
1447 /* check the mode isn't different, before changing it */
1448 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1450 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1451 return(ERROR(ERRDOS,ERRnoaccess));
1454 if(size != st.st_size)
1458 fd = sys_open(fname,O_RDWR,0);
1461 return(ERROR(ERRDOS,ERRbadpath));
1463 set_filelen(fd, size);
1468 set_filelen(fd, size);
1474 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1479 /****************************************************************************
1480 reply to a TRANS2_MKDIR (make directory with extended attributes).
1481 ****************************************************************************/
1482 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1483 int cnum, char **pparams, char **ppdata)
1485 char *params = *pparams;
1488 BOOL bad_path = False;
1490 if (!CAN_WRITE(cnum))
1491 return(ERROR(ERRSRV,ERRaccess));
1493 pstrcpy(directory, ¶ms[4]);
1495 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1497 unix_convert(directory,cnum,0,&bad_path);
1498 if (check_name(directory,cnum))
1499 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1503 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1504 if((errno == ENOENT) && bad_path)
1506 unix_ERR_class = ERRDOS;
1507 unix_ERR_code = ERRbadpath;
1509 return(UNIXERROR(ERRDOS,ERRnoaccess));
1512 /* Realloc the parameter and data sizes */
1513 params = *pparams = Realloc(*pparams,2);
1515 return(ERROR(ERRDOS,ERRnomem));
1519 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1524 /****************************************************************************
1525 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1526 We don't actually do this - we just send a null response.
1527 ****************************************************************************/
1528 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1529 int cnum, char **pparams, char **ppdata)
1531 static uint16 fnf_handle = 257;
1532 char *params = *pparams;
1533 uint16 info_level = SVAL(params,4);
1535 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1543 return(ERROR(ERRDOS,ERRunknownlevel));
1546 /* Realloc the parameter and data sizes */
1547 params = *pparams = Realloc(*pparams,6);
1549 return(ERROR(ERRDOS,ERRnomem));
1551 SSVAL(params,0,fnf_handle);
1552 SSVAL(params,2,0); /* No changes */
1553 SSVAL(params,4,0); /* No EA errors */
1560 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1565 /****************************************************************************
1566 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1567 changes). Currently this does nothing.
1568 ****************************************************************************/
1569 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1570 int cnum, char **pparams, char **ppdata)
1572 char *params = *pparams;
1574 DEBUG(3,("call_trans2findnotifynext\n"));
1576 /* Realloc the parameter and data sizes */
1577 params = *pparams = Realloc(*pparams,4);
1579 return(ERROR(ERRDOS,ERRnomem));
1581 SSVAL(params,0,0); /* No changes */
1582 SSVAL(params,2,0); /* No EA errors */
1584 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1589 /****************************************************************************
1590 reply to a SMBfindclose (stop trans2 directory search)
1591 ****************************************************************************/
1592 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1596 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1598 cnum = SVAL(inbuf,smb_tid);
1600 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1602 dptr_close(dptr_num);
1604 outsize = set_message(outbuf,0,0,True);
1606 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1611 /****************************************************************************
1612 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1613 ****************************************************************************/
1614 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1620 cnum = SVAL(inbuf,smb_tid);
1621 dptr_num = SVAL(inbuf,smb_vwv0);
1623 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1625 /* We never give out valid handles for a
1626 findnotifyfirst - so any dptr_num is ok here.
1629 outsize = set_message(outbuf,0,0,True);
1631 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1637 /****************************************************************************
1638 reply to a SMBtranss2 - just ignore it!
1639 ****************************************************************************/
1640 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1642 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1646 /****************************************************************************
1647 reply to a SMBtrans2
1648 ****************************************************************************/
1649 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1652 int cnum = SVAL(inbuf,smb_tid);
1653 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1654 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1656 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1657 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1658 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1659 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1660 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1661 int32 timeout = IVALS(inbuf,smb_timeout);
1663 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1664 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1665 char *params = NULL, *data = NULL;
1666 int num_params, num_params_sofar, num_data, num_data_sofar;
1668 outsize = set_message(outbuf,0,0,True);
1670 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1671 is so as a sanity check */
1674 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1675 return(ERROR(ERRSRV,ERRerror));
1678 /* Allocate the space for the maximum needed parameters and data */
1679 if (total_params > 0)
1680 params = (char *)malloc(total_params);
1682 data = (char *)malloc(total_data);
1684 if ((total_params && !params) || (total_data && !data))
1686 DEBUG(2,("Out of memory in reply_trans2\n"));
1687 return(ERROR(ERRDOS,ERRnomem));
1690 /* Copy the param and data bytes sent with this request into
1691 the params buffer */
1692 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1693 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1695 if (num_params > total_params || num_data > total_data)
1696 exit_server("invalid params in reply_trans2");
1698 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1699 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1701 if(num_data_sofar < total_data || num_params_sofar < total_params)
1703 /* We need to send an interim response then receive the rest
1704 of the parameter/data bytes */
1705 outsize = set_message(outbuf,0,0,True);
1706 send_smb(Client,outbuf);
1708 while( num_data_sofar < total_data || num_params_sofar < total_params)
1712 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1713 SMB_SECONDARY_WAIT);
1715 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1717 outsize = set_message(outbuf,0,0,True);
1719 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1721 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1722 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1725 return(ERROR(ERRSRV,ERRerror));
1728 /* Revise total_params and total_data in case they have changed downwards */
1729 total_params = SVAL(inbuf, smb_tpscnt);
1730 total_data = SVAL(inbuf, smb_tdscnt);
1731 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1732 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1733 if (num_params_sofar > total_params || num_data_sofar > total_data)
1734 exit_server("data overflow in trans2");
1736 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1737 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1738 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1739 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1743 if (Protocol >= PROTOCOL_NT1) {
1744 uint16 flg2 = SVAL(outbuf,smb_flg2);
1745 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1748 /* Now we must call the relevant TRANS2 function */
1751 case TRANSACT2_OPEN:
1752 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1754 case TRANSACT2_FINDFIRST:
1755 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1757 case TRANSACT2_FINDNEXT:
1758 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1760 case TRANSACT2_QFSINFO:
1761 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1763 case TRANSACT2_SETFSINFO:
1764 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1766 case TRANSACT2_QPATHINFO:
1767 case TRANSACT2_QFILEINFO:
1768 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1770 case TRANSACT2_SETPATHINFO:
1771 case TRANSACT2_SETFILEINFO:
1772 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1774 case TRANSACT2_FINDNOTIFYFIRST:
1775 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1777 case TRANSACT2_FINDNOTIFYNEXT:
1778 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1780 case TRANSACT2_MKDIR:
1781 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1784 /* Error in request */
1785 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1790 return (ERROR(ERRSRV,ERRerror));
1793 /* As we do not know how many data packets will need to be
1794 returned here the various call_trans2xxxx calls
1795 must send their own. Thus a call_trans2xxx routine only
1796 returns a value other than -1 when it wants to send
1804 return outsize; /* If a correct response was needed the call_trans2xxx
1805 calls have already sent it. If outsize != -1 then it is
1806 returning an error packet. */