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;
612 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
613 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
614 (get_remote_arch() == RA_WINNT))
616 unix_ERR_class = ERRDOS;
617 unix_ERR_code = ERRbaddirectory;
621 return(ERROR(ERRDOS,ERRbadpath));
624 p = strrchr(directory,'/');
626 strcpy(mask,directory);
627 strcpy(directory,"./");
633 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
635 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
637 return(ERROR(ERRDOS,ERRnomem));
638 bzero(pdata,max_data_bytes);
640 /* Realloc the params space */
641 params = *pparams = Realloc(*pparams, 10);
643 return(ERROR(ERRDOS,ERRnomem));
645 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
650 if((errno == ENOENT) && bad_path)
652 unix_ERR_class = ERRDOS;
653 unix_ERR_code = ERRbadpath;
657 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
658 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
659 (get_remote_arch() == RA_WINNT))
661 unix_ERR_class = ERRDOS;
662 unix_ERR_code = ERRbaddirectory;
666 return (UNIXERROR(ERRDOS,ERRbadpath));
668 return(ERROR(ERRDOS,ERRbadpath));
671 /* convert the formatted masks */
675 if (*p == '<') *p = '*';
676 if (*p == '>') *p = '?';
677 if (*p == '"') *p = '.';
682 /* a special case for 16 bit apps */
683 if (strequal(mask,"????????.???")) strcpy(mask,"*");
685 /* handle broken clients that send us old 8.3 format */
686 string_sub(mask,"????????","*");
687 string_sub(mask,".???",".*");
689 /* Save the wildcard match and attribs we are using on this directory -
690 needed as lanman2 assumes these are being saved between calls */
692 if(!(wcard = strdup(mask))) {
693 dptr_close(dptr_num);
694 return(ERROR(ERRDOS,ERRnomem));
697 dptr_set_wcard(dptr_num, wcard);
698 dptr_set_attr(dptr_num, dirtype);
700 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
702 /* We don't need to check for VOL here as this is returned by
703 a different TRANS2 call. */
705 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
706 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
707 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
711 space_remaining = max_data_bytes;
712 out_of_space = False;
714 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
717 /* this is a heuristic to avoid seeking the dirptr except when
718 absolutely necessary. It allows for a filename of about 40 chars */
719 if (space_remaining < DIRLEN_GUESS && numentries > 0)
727 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
728 requires_resume_key,dont_descend,
729 &p,pdata,space_remaining, &out_of_space,
733 if (finished && out_of_space)
736 if (!finished && !out_of_space)
738 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
741 /* Check if we can close the dirptr */
742 if(close_after_first || (finished && close_if_end))
744 dptr_close(dptr_num);
745 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
749 /* At this point pdata points to numentries directory entries. */
751 /* Set up the return parameter block */
752 SSVAL(params,0,dptr_num);
753 SSVAL(params,2,numentries);
754 SSVAL(params,4,finished);
755 SSVAL(params,6,0); /* Never an EA error */
756 SSVAL(params,8,last_name_off);
758 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
760 if ((! *directory) && dptr_path(dptr_num))
761 sprintf(directory,"(%s)",dptr_path(dptr_num));
763 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
765 smb_fn_name(CVAL(inbuf,smb_com)),
766 mask,directory,cnum,dirtype,numentries));
772 /****************************************************************************
773 reply to a TRANS2_FINDNEXT
774 ****************************************************************************/
775 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
776 int cnum, char **pparams, char **ppdata)
778 /* We must be careful here that we don't return more than the
779 allowed number of data bytes. If this means returning fewer than
780 maxentries then so be it. We assume that the redirector has
781 enough room for the fixed number of parameter bytes it has
783 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
784 char *params = *pparams;
785 char *pdata = *ppdata;
786 int16 dptr_num = SVAL(params,0);
787 int maxentries = SVAL(params,2);
788 uint16 info_level = SVAL(params,4);
789 uint32 resume_key = IVAL(params,6);
790 BOOL close_after_request = BITSETW(params+10,0);
791 BOOL close_if_end = BITSETW(params+10,1);
792 BOOL requires_resume_key = BITSETW(params+10,2);
793 BOOL continue_bit = BITSETW(params+10,3);
799 int i, last_name_off=0;
800 BOOL finished = False;
801 BOOL dont_descend = False;
802 BOOL out_of_space = False;
805 *mask = *directory = 0;
807 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",
808 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
809 requires_resume_key, resume_key, continue_bit, info_level));
817 case SMB_FIND_FILE_DIRECTORY_INFO:
818 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
819 case SMB_FIND_FILE_NAMES_INFO:
820 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
823 return(ERROR(ERRDOS,ERRunknownlevel));
826 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
828 return(ERROR(ERRDOS,ERRnomem));
829 bzero(pdata,max_data_bytes);
831 /* Realloc the params space */
832 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
834 return(ERROR(ERRDOS,ERRnomem));
836 /* Check that the dptr is valid */
837 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
838 return(ERROR(ERRDOS,ERRnofiles));
840 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
842 /* Get the wildcard mask from the dptr */
843 if((p = dptr_wcard(dptr_num))== NULL) {
844 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
845 return (ERROR(ERRDOS,ERRnofiles));
848 strcpy(directory,Connections[cnum].dirpath);
850 /* Get the attr mask from the dptr */
851 dirtype = dptr_attr(dptr_num);
853 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
854 dptr_num, mask, dirtype,
855 Connections[cnum].dirptr,
856 TellDir(Connections[cnum].dirptr)));
858 /* We don't need to check for VOL here as this is returned by
859 a different TRANS2 call. */
861 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
862 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
866 space_remaining = max_data_bytes;
867 out_of_space = False;
869 /* If we have a resume key - seek to the correct position. */
870 if(requires_resume_key && !continue_bit)
871 SeekDir(Connections[cnum].dirptr, resume_key);
873 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
875 /* this is a heuristic to avoid seeking the dirptr except when
876 absolutely necessary. It allows for a filename of about 40 chars */
877 if (space_remaining < DIRLEN_GUESS && numentries > 0)
885 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
886 requires_resume_key,dont_descend,
887 &p,pdata,space_remaining, &out_of_space,
891 if (finished && out_of_space)
894 if (!finished && !out_of_space)
896 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
899 /* Check if we can close the dirptr */
900 if(close_after_request || (finished && close_if_end))
902 dptr_close(dptr_num); /* This frees up the saved mask */
903 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
908 /* Set up the return parameter block */
909 SSVAL(params,0,numentries);
910 SSVAL(params,2,finished);
911 SSVAL(params,4,0); /* Never an EA error */
912 SSVAL(params,6,last_name_off);
914 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
916 if ((! *directory) && dptr_path(dptr_num))
917 sprintf(directory,"(%s)",dptr_path(dptr_num));
919 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
921 smb_fn_name(CVAL(inbuf,smb_com)),
922 mask,directory,cnum,dirtype,numentries));
927 /****************************************************************************
928 reply to a TRANS2_QFSINFO (query filesystem info)
929 ****************************************************************************/
930 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
931 int cnum, char **pparams, char **ppdata)
933 char *pdata = *ppdata;
934 char *params = *pparams;
935 uint16 info_level = SVAL(params,0);
938 char *vname = volume_label(SNUM(cnum));
940 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
942 if(sys_stat(".",&st)!=0) {
943 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
944 return (ERROR(ERRSRV,ERRinvdevice));
947 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
953 int dfree,dsize,bsize;
955 sys_disk_free(".",&bsize,&dfree,&dsize);
956 SIVAL(pdata,l1_idFileSystem,st.st_dev);
957 SIVAL(pdata,l1_cSectorUnit,bsize/512);
958 SIVAL(pdata,l1_cUnit,dsize);
959 SIVAL(pdata,l1_cUnitAvail,dfree);
960 SSVAL(pdata,l1_cbSector,512);
961 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
962 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
967 /* Return volume name */
968 int volname_len = MIN(strlen(vname),11);
969 data_len = l2_vol_szVolLabel + volname_len + 1;
970 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
971 SCVAL(pdata,l2_vol_cch,volname_len);
972 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
973 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
974 pdata+l2_vol_szVolLabel));
977 case SMB_QUERY_FS_ATTRIBUTE_INFO:
978 data_len = 12 + 2*strlen(FSTYPE_STRING);
979 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
980 SIVAL(pdata,4,128); /* Max filename component length */
981 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
982 PutUniCode(pdata+12,FSTYPE_STRING);
984 case SMB_QUERY_FS_LABEL_INFO:
985 data_len = 4 + strlen(vname);
986 SIVAL(pdata,0,strlen(vname));
987 strcpy(pdata+4,vname);
989 case SMB_QUERY_FS_VOLUME_INFO:
990 data_len = 18 + 2*strlen(vname);
991 SIVAL(pdata,12,2*strlen(vname));
992 PutUniCode(pdata+18,vname);
993 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
996 case SMB_QUERY_FS_SIZE_INFO:
998 int dfree,dsize,bsize;
1000 sys_disk_free(".",&bsize,&dfree,&dsize);
1001 SIVAL(pdata,0,dsize);
1002 SIVAL(pdata,8,dfree);
1003 SIVAL(pdata,16,bsize/512);
1004 SIVAL(pdata,20,512);
1007 case SMB_QUERY_FS_DEVICE_INFO:
1009 SIVAL(pdata,0,0); /* dev type */
1010 SIVAL(pdata,4,0); /* characteristics */
1013 return(ERROR(ERRDOS,ERRunknownlevel));
1017 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1019 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1024 /****************************************************************************
1025 reply to a TRANS2_SETFSINFO (set filesystem info)
1026 ****************************************************************************/
1027 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1028 int cnum, char **pparams, char **ppdata)
1030 /* Just say yes we did it - there is nothing that
1031 can be set here so it doesn't matter. */
1033 DEBUG(3,("call_trans2setfsinfo\n"));
1035 if (!CAN_WRITE(cnum))
1036 return(ERROR(ERRSRV,ERRaccess));
1038 outsize = set_message(outbuf,10,0,True);
1043 /****************************************************************************
1044 reply to a TRANS2_QFILEINFO (query file info by fileid)
1045 ****************************************************************************/
1046 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1047 int bufsize,int cnum,
1048 char **pparams,char **ppdata,
1051 char *params = *pparams;
1052 char *pdata = *ppdata;
1053 uint16 tran_call = SVAL(inbuf, smb_setup0);
1057 unsigned int data_size;
1063 BOOL bad_path = False;
1065 if (tran_call == TRANSACT2_QFILEINFO) {
1066 int16 fnum = SVALS(params,0);
1067 info_level = SVAL(params,2);
1069 CHECK_FNUM(fnum,cnum);
1072 fname = Files[fnum].name;
1073 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1074 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1075 return(UNIXERROR(ERRDOS,ERRbadfid));
1077 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1080 info_level = SVAL(params,0);
1082 pstrcpy(fname,¶ms[6]);
1083 unix_convert(fname,cnum,0,&bad_path);
1084 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1085 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1086 if((errno == ENOENT) && bad_path)
1088 unix_ERR_class = ERRDOS;
1089 unix_ERR_code = ERRbadpath;
1091 return(UNIXERROR(ERRDOS,ERRbadpath));
1097 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1098 fname,info_level,tran_call,total_data));
1100 p = strrchr(fname,'/');
1106 mode = dos_mode(cnum,fname,&sbuf);
1107 size = sbuf.st_size;
1108 if (mode & aDIR) size = 0;
1110 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1112 pdata = *ppdata = Realloc(*ppdata, data_size);
1114 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1115 /* uggh, EAs for OS2 */
1116 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1117 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1120 bzero(pdata,data_size);
1124 case SMB_INFO_STANDARD:
1125 case SMB_INFO_QUERY_EA_SIZE:
1126 data_size = (info_level==1?22:26);
1127 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1128 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1129 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1130 SIVAL(pdata,l1_cbFile,size);
1131 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1132 SSVAL(pdata,l1_attrFile,mode);
1133 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1136 case SMB_INFO_QUERY_EAS_FROM_LIST:
1138 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1139 put_dos_date2(pdata,4,sbuf.st_atime);
1140 put_dos_date2(pdata,8,sbuf.st_mtime);
1141 SIVAL(pdata,12,size);
1142 SIVAL(pdata,16,ROUNDUP(size,1024));
1143 SIVAL(pdata,20,mode);
1146 case SMB_INFO_QUERY_ALL_EAS:
1148 SIVAL(pdata,0,data_size);
1152 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1154 case SMB_QUERY_FILE_BASIC_INFO:
1155 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1156 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1157 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1158 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1159 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1160 SIVAL(pdata,32,mode);
1162 DEBUG(5,("SMB_QFBI - "));
1163 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1164 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1165 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1166 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1167 DEBUG(5,("mode: %x\n", mode));
1171 case SMB_QUERY_FILE_STANDARD_INFO:
1173 SIVAL(pdata,0,size);
1174 SIVAL(pdata,8,size);
1175 SIVAL(pdata,16,sbuf.st_nlink);
1177 CVAL(pdata,21) = (mode&aDIR)?1:0;
1180 case SMB_QUERY_FILE_EA_INFO:
1184 case SMB_QUERY_FILE_NAME_INFO:
1185 case SMB_QUERY_FILE_ALT_NAME_INFO:
1188 pstrcpy(pdata+4,fname);
1190 case SMB_QUERY_FILE_ALLOCATION_INFO:
1191 case SMB_QUERY_FILE_END_OF_FILEINFO:
1193 SIVAL(pdata,0,size);
1196 case SMB_QUERY_FILE_ALL_INFO:
1197 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1198 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1199 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1200 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1201 SIVAL(pdata,32,mode);
1203 SIVAL(pdata,0,size);
1204 SIVAL(pdata,8,size);
1205 SIVAL(pdata,16,sbuf.st_nlink);
1207 CVAL(pdata,21) = (mode&aDIR)?1:0;
1209 pdata += 8; /* index number */
1210 pdata += 4; /* EA info */
1212 SIVAL(pdata,0,0xA9);
1214 SIVAL(pdata,0,0xd01BF);
1216 SIVAL(pdata,0,pos); /* current offset */
1218 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1220 pdata += 4; /* alignment */
1222 pstrcpy(pdata+4,fname);
1224 data_size = PTR_DIFF(pdata,(*ppdata));
1227 case SMB_QUERY_FILE_STREAM_INFO:
1230 SIVAL(pdata,4,size);
1231 SIVAL(pdata,12,size);
1233 pstrcpy(pdata+24,fname);
1236 return(ERROR(ERRDOS,ERRunknownlevel));
1239 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1244 /****************************************************************************
1245 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1246 ****************************************************************************/
1247 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1248 int bufsize, int cnum, char **pparams,
1249 char **ppdata, int total_data)
1251 char *params = *pparams;
1252 char *pdata = *ppdata;
1253 uint16 tran_call = SVAL(inbuf, smb_setup0);
1262 BOOL bad_path = False;
1264 if (!CAN_WRITE(cnum))
1265 return(ERROR(ERRSRV,ERRaccess));
1267 if (tran_call == TRANSACT2_SETFILEINFO) {
1268 int16 fnum = SVALS(params,0);
1269 info_level = SVAL(params,2);
1271 CHECK_FNUM(fnum,cnum);
1274 fname = Files[fnum].name;
1275 fd = Files[fnum].fd_ptr->fd;
1277 if(fstat(fd,&st)!=0) {
1278 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1279 return(ERROR(ERRDOS,ERRbadpath));
1283 info_level = SVAL(params,0);
1285 pstrcpy(fname,¶ms[6]);
1286 unix_convert(fname,cnum,0,&bad_path);
1287 if(!check_name(fname, cnum))
1289 if((errno == ENOENT) && bad_path)
1291 unix_ERR_class = ERRDOS;
1292 unix_ERR_code = ERRbadpath;
1294 return(UNIXERROR(ERRDOS,ERRbadpath));
1297 if(sys_stat(fname,&st)!=0) {
1298 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1299 if((errno == ENOENT) && bad_path)
1301 unix_ERR_class = ERRDOS;
1302 unix_ERR_code = ERRbadpath;
1304 return(UNIXERROR(ERRDOS,ERRbadpath));
1308 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1309 tran_call,fname,info_level,total_data));
1311 /* Realloc the parameter and data sizes */
1312 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1314 return(ERROR(ERRDOS,ERRnomem));
1317 tvs.modtime = st.st_mtime;
1318 tvs.actime = st.st_atime;
1319 mode = dos_mode(cnum,fname,&st);
1321 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1322 /* uggh, EAs for OS2 */
1323 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1324 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1329 case SMB_INFO_STANDARD:
1330 case SMB_INFO_QUERY_EA_SIZE:
1333 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1336 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1338 mode = SVAL(pdata,l1_attrFile);
1339 size = IVAL(pdata,l1_cbFile);
1343 /* XXXX um, i don't think this is right.
1344 it's also not in the cifs6.txt spec.
1346 case SMB_INFO_QUERY_EAS_FROM_LIST:
1347 tvs.actime = make_unix_date2(pdata+8);
1348 tvs.modtime = make_unix_date2(pdata+12);
1349 size = IVAL(pdata,16);
1350 mode = IVAL(pdata,24);
1353 /* XXXX nor this. not in cifs6.txt, either. */
1354 case SMB_INFO_QUERY_ALL_EAS:
1355 tvs.actime = make_unix_date2(pdata+8);
1356 tvs.modtime = make_unix_date2(pdata+12);
1357 size = IVAL(pdata,16);
1358 mode = IVAL(pdata,24);
1361 case SMB_SET_FILE_BASIC_INFO:
1363 /* Ignore create time at offset pdata. */
1366 tvs.actime = interpret_long_date(pdata+8);
1368 /* write time + changed time, combined. */
1369 tvs.modtime=MAX(interpret_long_date(pdata+16),
1370 interpret_long_date(pdata+24));
1372 #if 0 /* Needs more testing... */
1373 /* Test from Luke to prevent Win95 from
1374 setting incorrect values here.
1376 if (tvs.actime < tvs.modtime)
1377 return(ERROR(ERRDOS,ERRnoaccess));
1378 #endif /* Needs more testing... */
1381 mode = IVAL(pdata,32);
1385 case SMB_SET_FILE_END_OF_FILE_INFO:
1387 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1388 return(ERROR(ERRDOS,ERRunknownlevel));
1389 size = IVAL(pdata,0);
1393 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1394 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1397 return(ERROR(ERRDOS,ERRunknownlevel));
1401 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1402 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1403 DEBUG(6,("size: %x " , size));
1404 DEBUG(6,("mode: %x\n" , mode));
1406 /* get some defaults (no modifications) if any info is zero. */
1407 if (!tvs.actime) tvs.actime = st.st_atime;
1408 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1409 if (!size) size = st.st_size;
1411 /* Try and set the times, size and mode of this file -
1412 if they are different from the current values
1414 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1416 if(sys_utime(fname, &tvs)!=0)
1418 return(ERROR(ERRDOS,ERRnoaccess));
1422 /* check the mode isn't different, before changing it */
1423 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1425 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1426 return(ERROR(ERRDOS,ERRnoaccess));
1429 if(size != st.st_size)
1433 fd = sys_open(fname,O_RDWR,0);
1436 return(ERROR(ERRDOS,ERRbadpath));
1438 set_filelen(fd, size);
1443 set_filelen(fd, size);
1449 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1454 /****************************************************************************
1455 reply to a TRANS2_MKDIR (make directory with extended attributes).
1456 ****************************************************************************/
1457 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1458 int cnum, char **pparams, char **ppdata)
1460 char *params = *pparams;
1463 BOOL bad_path = False;
1465 if (!CAN_WRITE(cnum))
1466 return(ERROR(ERRSRV,ERRaccess));
1468 pstrcpy(directory, ¶ms[4]);
1470 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1472 unix_convert(directory,cnum,0,&bad_path);
1473 if (check_name(directory,cnum))
1474 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1478 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1479 if((errno == ENOENT) && bad_path)
1481 unix_ERR_class = ERRDOS;
1482 unix_ERR_code = ERRbadpath;
1484 return(UNIXERROR(ERRDOS,ERRnoaccess));
1487 /* Realloc the parameter and data sizes */
1488 params = *pparams = Realloc(*pparams,2);
1490 return(ERROR(ERRDOS,ERRnomem));
1494 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1499 /****************************************************************************
1500 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1501 We don't actually do this - we just send a null response.
1502 ****************************************************************************/
1503 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1504 int cnum, char **pparams, char **ppdata)
1506 static uint16 fnf_handle = 257;
1507 char *params = *pparams;
1508 uint16 info_level = SVAL(params,4);
1510 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1518 return(ERROR(ERRDOS,ERRunknownlevel));
1521 /* Realloc the parameter and data sizes */
1522 params = *pparams = Realloc(*pparams,6);
1524 return(ERROR(ERRDOS,ERRnomem));
1526 SSVAL(params,0,fnf_handle);
1527 SSVAL(params,2,0); /* No changes */
1528 SSVAL(params,4,0); /* No EA errors */
1535 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1540 /****************************************************************************
1541 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1542 changes). Currently this does nothing.
1543 ****************************************************************************/
1544 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1545 int cnum, char **pparams, char **ppdata)
1547 char *params = *pparams;
1549 DEBUG(3,("call_trans2findnotifynext\n"));
1551 /* Realloc the parameter and data sizes */
1552 params = *pparams = Realloc(*pparams,4);
1554 return(ERROR(ERRDOS,ERRnomem));
1556 SSVAL(params,0,0); /* No changes */
1557 SSVAL(params,2,0); /* No EA errors */
1559 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1564 /****************************************************************************
1565 reply to a SMBfindclose (stop trans2 directory search)
1566 ****************************************************************************/
1567 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1571 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1573 cnum = SVAL(inbuf,smb_tid);
1575 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1577 dptr_close(dptr_num);
1579 outsize = set_message(outbuf,0,0,True);
1581 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1586 /****************************************************************************
1587 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1588 ****************************************************************************/
1589 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1595 cnum = SVAL(inbuf,smb_tid);
1596 dptr_num = SVAL(inbuf,smb_vwv0);
1598 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1600 /* We never give out valid handles for a
1601 findnotifyfirst - so any dptr_num is ok here.
1604 outsize = set_message(outbuf,0,0,True);
1606 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1612 /****************************************************************************
1613 reply to a SMBtranss2 - just ignore it!
1614 ****************************************************************************/
1615 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1617 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1621 /****************************************************************************
1622 reply to a SMBtrans2
1623 ****************************************************************************/
1624 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1627 int cnum = SVAL(inbuf,smb_tid);
1628 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1629 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1631 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1632 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1633 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1634 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1635 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1636 int32 timeout = IVALS(inbuf,smb_timeout);
1638 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1639 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1640 char *params = NULL, *data = NULL;
1641 int num_params, num_params_sofar, num_data, num_data_sofar;
1643 outsize = set_message(outbuf,0,0,True);
1645 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1646 is so as a sanity check */
1649 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1650 return(ERROR(ERRSRV,ERRerror));
1653 /* Allocate the space for the maximum needed parameters and data */
1654 if (total_params > 0)
1655 params = (char *)malloc(total_params);
1657 data = (char *)malloc(total_data);
1659 if ((total_params && !params) || (total_data && !data))
1661 DEBUG(2,("Out of memory in reply_trans2\n"));
1662 return(ERROR(ERRDOS,ERRnomem));
1665 /* Copy the param and data bytes sent with this request into
1666 the params buffer */
1667 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1668 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1670 if (num_params > total_params || num_data > total_data)
1671 exit_server("invalid params in reply_trans2");
1673 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1674 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1676 if(num_data_sofar < total_data || num_params_sofar < total_params)
1678 /* We need to send an interim response then receive the rest
1679 of the parameter/data bytes */
1680 outsize = set_message(outbuf,0,0,True);
1681 send_smb(Client,outbuf);
1683 while( num_data_sofar < total_data || num_params_sofar < total_params)
1685 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1686 CVAL(inbuf, smb_com) != SMBtranss2)
1688 outsize = set_message(outbuf,0,0,True);
1689 DEBUG(2,("Invalid secondary trans2 packet\n"));
1692 return(ERROR(ERRSRV,ERRerror));
1695 /* Revise total_params and total_data in case they have changed downwards */
1696 total_params = SVAL(inbuf, smb_tpscnt);
1697 total_data = SVAL(inbuf, smb_tdscnt);
1698 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1699 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1700 if (num_params_sofar > total_params || num_data_sofar > total_data)
1701 exit_server("data overflow in trans2");
1703 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1704 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1705 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1706 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1710 if (Protocol >= PROTOCOL_NT1) {
1711 uint16 flg2 = SVAL(outbuf,smb_flg2);
1712 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1715 /* Now we must call the relevant TRANS2 function */
1718 case TRANSACT2_OPEN:
1719 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1721 case TRANSACT2_FINDFIRST:
1722 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1724 case TRANSACT2_FINDNEXT:
1725 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1727 case TRANSACT2_QFSINFO:
1728 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1730 case TRANSACT2_SETFSINFO:
1731 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1733 case TRANSACT2_QPATHINFO:
1734 case TRANSACT2_QFILEINFO:
1735 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1737 case TRANSACT2_SETPATHINFO:
1738 case TRANSACT2_SETFILEINFO:
1739 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1741 case TRANSACT2_FINDNOTIFYFIRST:
1742 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1744 case TRANSACT2_FINDNOTIFYNEXT:
1745 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1747 case TRANSACT2_MKDIR:
1748 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1751 /* Error in request */
1752 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1757 return (ERROR(ERRSRV,ERRerror));
1760 /* As we do not know how many data packets will need to be
1761 returned here the various call_trans2xxxx calls
1762 must send their own. Thus a call_trans2xxx routine only
1763 returns a value other than -1 when it wants to send
1771 return outsize; /* If a correct response was needed the call_trans2xxx
1772 calls have already sent it. If outsize != -1 then it is
1773 returning an error packet. */