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;
611 /* Ugly - NT specific hack - but needed (JRA) */
612 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
613 (get_remote_arch() == RA_WINNT))
615 unix_ERR_class = ERRDOS;
616 unix_ERR_code = ERRbaddirectory;
619 return(ERROR(ERRDOS,ERRbadpath));
622 p = strrchr(directory,'/');
624 strcpy(mask,directory);
625 strcpy(directory,"./");
631 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
633 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
635 return(ERROR(ERRDOS,ERRnomem));
636 bzero(pdata,max_data_bytes);
638 /* Realloc the params space */
639 params = *pparams = Realloc(*pparams, 10);
641 return(ERROR(ERRDOS,ERRnomem));
643 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
648 if((errno == ENOENT) && bad_path)
650 unix_ERR_class = ERRDOS;
651 unix_ERR_code = ERRbadpath;
654 /* Ugly - NT specific hack - but needed (JRA) */
655 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
656 (get_remote_arch() == RA_WINNT))
658 unix_ERR_class = ERRDOS;
659 unix_ERR_code = ERRbaddirectory;
661 return (UNIXERROR(ERRDOS,ERRbadpath));
663 return(ERROR(ERRDOS,ERRbadpath));
666 /* convert the formatted masks */
670 if (*p == '<') *p = '*';
671 if (*p == '>') *p = '?';
672 if (*p == '"') *p = '.';
677 /* a special case for 16 bit apps */
678 if (strequal(mask,"????????.???")) strcpy(mask,"*");
680 /* handle broken clients that send us old 8.3 format */
681 string_sub(mask,"????????","*");
682 string_sub(mask,".???",".*");
684 /* Save the wildcard match and attribs we are using on this directory -
685 needed as lanman2 assumes these are being saved between calls */
687 if(!(wcard = strdup(mask))) {
688 dptr_close(dptr_num);
689 return(ERROR(ERRDOS,ERRnomem));
692 dptr_set_wcard(dptr_num, wcard);
693 dptr_set_attr(dptr_num, dirtype);
695 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
697 /* We don't need to check for VOL here as this is returned by
698 a different TRANS2 call. */
700 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
701 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
702 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
706 space_remaining = max_data_bytes;
707 out_of_space = False;
709 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
712 /* this is a heuristic to avoid seeking the dirptr except when
713 absolutely necessary. It allows for a filename of about 40 chars */
714 if (space_remaining < DIRLEN_GUESS && numentries > 0)
722 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
723 requires_resume_key,dont_descend,
724 &p,pdata,space_remaining, &out_of_space,
728 if (finished && out_of_space)
731 if (!finished && !out_of_space)
733 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
736 /* Check if we can close the dirptr */
737 if(close_after_first || (finished && close_if_end))
739 dptr_close(dptr_num);
740 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
744 /* At this point pdata points to numentries directory entries. */
746 /* Set up the return parameter block */
747 SSVAL(params,0,dptr_num);
748 SSVAL(params,2,numentries);
749 SSVAL(params,4,finished);
750 SSVAL(params,6,0); /* Never an EA error */
751 SSVAL(params,8,last_name_off);
753 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
755 if ((! *directory) && dptr_path(dptr_num))
756 sprintf(directory,"(%s)",dptr_path(dptr_num));
758 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
760 smb_fn_name(CVAL(inbuf,smb_com)),
761 mask,directory,cnum,dirtype,numentries));
767 /****************************************************************************
768 reply to a TRANS2_FINDNEXT
769 ****************************************************************************/
770 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
771 int cnum, char **pparams, char **ppdata)
773 /* We must be careful here that we don't return more than the
774 allowed number of data bytes. If this means returning fewer than
775 maxentries then so be it. We assume that the redirector has
776 enough room for the fixed number of parameter bytes it has
778 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
779 char *params = *pparams;
780 char *pdata = *ppdata;
781 int16 dptr_num = SVAL(params,0);
782 int maxentries = SVAL(params,2);
783 uint16 info_level = SVAL(params,4);
784 uint32 resume_key = IVAL(params,6);
785 BOOL close_after_request = BITSETW(params+10,0);
786 BOOL close_if_end = BITSETW(params+10,1);
787 BOOL requires_resume_key = BITSETW(params+10,2);
788 BOOL continue_bit = BITSETW(params+10,3);
794 int i, last_name_off=0;
795 BOOL finished = False;
796 BOOL dont_descend = False;
797 BOOL out_of_space = False;
800 *mask = *directory = 0;
802 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",
803 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
804 requires_resume_key, resume_key, continue_bit, info_level));
812 case SMB_FIND_FILE_DIRECTORY_INFO:
813 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
814 case SMB_FIND_FILE_NAMES_INFO:
815 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
818 return(ERROR(ERRDOS,ERRunknownlevel));
821 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
823 return(ERROR(ERRDOS,ERRnomem));
824 bzero(pdata,max_data_bytes);
826 /* Realloc the params space */
827 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
829 return(ERROR(ERRDOS,ERRnomem));
831 /* Check that the dptr is valid */
832 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
833 return(ERROR(ERRDOS,ERRnofiles));
835 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
837 /* Get the wildcard mask from the dptr */
838 if((p = dptr_wcard(dptr_num))== NULL) {
839 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
840 return (ERROR(ERRDOS,ERRnofiles));
843 strcpy(directory,Connections[cnum].dirpath);
845 /* Get the attr mask from the dptr */
846 dirtype = dptr_attr(dptr_num);
848 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
849 dptr_num, mask, dirtype,
850 Connections[cnum].dirptr,
851 TellDir(Connections[cnum].dirptr)));
853 /* We don't need to check for VOL here as this is returned by
854 a different TRANS2 call. */
856 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
857 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
861 space_remaining = max_data_bytes;
862 out_of_space = False;
864 /* If we have a resume key - seek to the correct position. */
865 if(requires_resume_key && !continue_bit)
866 SeekDir(Connections[cnum].dirptr, resume_key);
868 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
870 /* this is a heuristic to avoid seeking the dirptr except when
871 absolutely necessary. It allows for a filename of about 40 chars */
872 if (space_remaining < DIRLEN_GUESS && numentries > 0)
880 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
881 requires_resume_key,dont_descend,
882 &p,pdata,space_remaining, &out_of_space,
886 if (finished && out_of_space)
889 if (!finished && !out_of_space)
891 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
894 /* Check if we can close the dirptr */
895 if(close_after_request || (finished && close_if_end))
897 dptr_close(dptr_num); /* This frees up the saved mask */
898 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
903 /* Set up the return parameter block */
904 SSVAL(params,0,numentries);
905 SSVAL(params,2,finished);
906 SSVAL(params,4,0); /* Never an EA error */
907 SSVAL(params,6,last_name_off);
909 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
911 if ((! *directory) && dptr_path(dptr_num))
912 sprintf(directory,"(%s)",dptr_path(dptr_num));
914 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
916 smb_fn_name(CVAL(inbuf,smb_com)),
917 mask,directory,cnum,dirtype,numentries));
922 /****************************************************************************
923 reply to a TRANS2_QFSINFO (query filesystem info)
924 ****************************************************************************/
925 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
926 int cnum, char **pparams, char **ppdata)
928 char *pdata = *ppdata;
929 char *params = *pparams;
930 uint16 info_level = SVAL(params,0);
933 char *vname = volume_label(SNUM(cnum));
935 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
937 if(sys_stat(".",&st)!=0) {
938 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
939 return (ERROR(ERRSRV,ERRinvdevice));
942 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
948 int dfree,dsize,bsize;
950 sys_disk_free(".",&bsize,&dfree,&dsize);
951 SIVAL(pdata,l1_idFileSystem,st.st_dev);
952 SIVAL(pdata,l1_cSectorUnit,bsize/512);
953 SIVAL(pdata,l1_cUnit,dsize);
954 SIVAL(pdata,l1_cUnitAvail,dfree);
955 SSVAL(pdata,l1_cbSector,512);
956 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
957 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
962 /* Return volume name */
963 int volname_len = MIN(strlen(vname),11);
964 data_len = l2_vol_szVolLabel + volname_len + 1;
965 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
966 SCVAL(pdata,l2_vol_cch,volname_len);
967 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
968 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
969 pdata+l2_vol_szVolLabel));
972 case SMB_QUERY_FS_ATTRIBUTE_INFO:
973 data_len = 12 + 2*strlen(FSTYPE_STRING);
974 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
975 SIVAL(pdata,4,128); /* Max filename component length */
976 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
977 PutUniCode(pdata+12,FSTYPE_STRING);
979 case SMB_QUERY_FS_LABEL_INFO:
980 data_len = 4 + strlen(vname);
981 SIVAL(pdata,0,strlen(vname));
982 strcpy(pdata+4,vname);
984 case SMB_QUERY_FS_VOLUME_INFO:
985 data_len = 18 + 2*strlen(vname);
986 SIVAL(pdata,12,2*strlen(vname));
987 PutUniCode(pdata+18,vname);
988 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
991 case SMB_QUERY_FS_SIZE_INFO:
993 int dfree,dsize,bsize;
995 sys_disk_free(".",&bsize,&dfree,&dsize);
996 SIVAL(pdata,0,dsize);
997 SIVAL(pdata,8,dfree);
998 SIVAL(pdata,16,bsize/512);
1002 case SMB_QUERY_FS_DEVICE_INFO:
1004 SIVAL(pdata,0,0); /* dev type */
1005 SIVAL(pdata,4,0); /* characteristics */
1008 return(ERROR(ERRDOS,ERRunknownlevel));
1012 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1014 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1019 /****************************************************************************
1020 reply to a TRANS2_SETFSINFO (set filesystem info)
1021 ****************************************************************************/
1022 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1023 int cnum, char **pparams, char **ppdata)
1025 /* Just say yes we did it - there is nothing that
1026 can be set here so it doesn't matter. */
1028 DEBUG(3,("call_trans2setfsinfo\n"));
1030 if (!CAN_WRITE(cnum))
1031 return(ERROR(ERRSRV,ERRaccess));
1033 outsize = set_message(outbuf,10,0,True);
1038 /****************************************************************************
1039 reply to a TRANS2_QFILEINFO (query file info by fileid)
1040 ****************************************************************************/
1041 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1042 int bufsize,int cnum,
1043 char **pparams,char **ppdata,
1046 char *params = *pparams;
1047 char *pdata = *ppdata;
1048 uint16 tran_call = SVAL(inbuf, smb_setup0);
1052 unsigned int data_size;
1058 BOOL bad_path = False;
1060 if (tran_call == TRANSACT2_QFILEINFO) {
1061 int16 fnum = SVALS(params,0);
1062 info_level = SVAL(params,2);
1064 CHECK_FNUM(fnum,cnum);
1067 fname = Files[fnum].name;
1068 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1069 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1070 return(UNIXERROR(ERRDOS,ERRbadfid));
1072 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1075 info_level = SVAL(params,0);
1077 pstrcpy(fname,¶ms[6]);
1078 unix_convert(fname,cnum,0,&bad_path);
1079 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1080 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1081 if((errno == ENOENT) && bad_path)
1083 unix_ERR_class = ERRDOS;
1084 unix_ERR_code = ERRbadpath;
1086 return(UNIXERROR(ERRDOS,ERRbadpath));
1092 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1093 fname,info_level,tran_call,total_data));
1095 p = strrchr(fname,'/');
1101 mode = dos_mode(cnum,fname,&sbuf);
1102 size = sbuf.st_size;
1103 if (mode & aDIR) size = 0;
1105 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1107 pdata = *ppdata = Realloc(*ppdata, data_size);
1109 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1110 /* uggh, EAs for OS2 */
1111 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1112 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1115 bzero(pdata,data_size);
1119 case SMB_INFO_STANDARD:
1120 case SMB_INFO_QUERY_EA_SIZE:
1121 data_size = (info_level==1?22:26);
1122 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1123 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1124 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1125 SIVAL(pdata,l1_cbFile,size);
1126 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1127 SSVAL(pdata,l1_attrFile,mode);
1128 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1131 case SMB_INFO_QUERY_EAS_FROM_LIST:
1133 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1134 put_dos_date2(pdata,4,sbuf.st_atime);
1135 put_dos_date2(pdata,8,sbuf.st_mtime);
1136 SIVAL(pdata,12,size);
1137 SIVAL(pdata,16,ROUNDUP(size,1024));
1138 SIVAL(pdata,20,mode);
1141 case SMB_INFO_QUERY_ALL_EAS:
1143 SIVAL(pdata,0,data_size);
1147 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1149 case SMB_QUERY_FILE_BASIC_INFO:
1150 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1151 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1152 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1153 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1154 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1155 SIVAL(pdata,32,mode);
1157 DEBUG(5,("SMB_QFBI - "));
1158 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1159 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1160 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1161 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1162 DEBUG(5,("mode: %x\n", mode));
1166 case SMB_QUERY_FILE_STANDARD_INFO:
1168 SIVAL(pdata,0,size);
1169 SIVAL(pdata,8,size);
1170 SIVAL(pdata,16,sbuf.st_nlink);
1172 CVAL(pdata,21) = (mode&aDIR)?1:0;
1175 case SMB_QUERY_FILE_EA_INFO:
1179 case SMB_QUERY_FILE_NAME_INFO:
1180 case SMB_QUERY_FILE_ALT_NAME_INFO:
1183 pstrcpy(pdata+4,fname);
1185 case SMB_QUERY_FILE_ALLOCATION_INFO:
1186 case SMB_QUERY_FILE_END_OF_FILEINFO:
1188 SIVAL(pdata,0,size);
1191 case SMB_QUERY_FILE_ALL_INFO:
1192 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1193 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1194 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1195 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1196 SIVAL(pdata,32,mode);
1198 SIVAL(pdata,0,size);
1199 SIVAL(pdata,8,size);
1200 SIVAL(pdata,16,sbuf.st_nlink);
1202 CVAL(pdata,21) = (mode&aDIR)?1:0;
1204 pdata += 8; /* index number */
1205 pdata += 4; /* EA info */
1207 SIVAL(pdata,0,0xA9);
1209 SIVAL(pdata,0,0xd01BF);
1211 SIVAL(pdata,0,pos); /* current offset */
1213 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1215 pdata += 4; /* alignment */
1217 pstrcpy(pdata+4,fname);
1219 data_size = PTR_DIFF(pdata,(*ppdata));
1222 case SMB_QUERY_FILE_STREAM_INFO:
1225 SIVAL(pdata,4,size);
1226 SIVAL(pdata,12,size);
1228 pstrcpy(pdata+24,fname);
1231 return(ERROR(ERRDOS,ERRunknownlevel));
1234 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1239 /****************************************************************************
1240 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1241 ****************************************************************************/
1242 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1243 int bufsize, int cnum, char **pparams,
1244 char **ppdata, int total_data)
1246 char *params = *pparams;
1247 char *pdata = *ppdata;
1248 uint16 tran_call = SVAL(inbuf, smb_setup0);
1257 BOOL bad_path = False;
1259 if (!CAN_WRITE(cnum))
1260 return(ERROR(ERRSRV,ERRaccess));
1262 if (tran_call == TRANSACT2_SETFILEINFO) {
1263 int16 fnum = SVALS(params,0);
1264 info_level = SVAL(params,2);
1266 CHECK_FNUM(fnum,cnum);
1269 fname = Files[fnum].name;
1270 fd = Files[fnum].fd_ptr->fd;
1272 if(fstat(fd,&st)!=0) {
1273 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1274 return(ERROR(ERRDOS,ERRbadpath));
1278 info_level = SVAL(params,0);
1280 pstrcpy(fname,¶ms[6]);
1281 unix_convert(fname,cnum,0,&bad_path);
1282 if(!check_name(fname, cnum))
1284 if((errno == ENOENT) && bad_path)
1286 unix_ERR_class = ERRDOS;
1287 unix_ERR_code = ERRbadpath;
1289 return(UNIXERROR(ERRDOS,ERRbadpath));
1292 if(sys_stat(fname,&st)!=0) {
1293 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1294 if((errno == ENOENT) && bad_path)
1296 unix_ERR_class = ERRDOS;
1297 unix_ERR_code = ERRbadpath;
1299 return(UNIXERROR(ERRDOS,ERRbadpath));
1303 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1304 tran_call,fname,info_level,total_data));
1306 /* Realloc the parameter and data sizes */
1307 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1309 return(ERROR(ERRDOS,ERRnomem));
1312 tvs.modtime = st.st_mtime;
1313 tvs.actime = st.st_atime;
1314 mode = dos_mode(cnum,fname,&st);
1316 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1317 /* uggh, EAs for OS2 */
1318 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1319 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1324 case SMB_INFO_STANDARD:
1325 case SMB_INFO_QUERY_EA_SIZE:
1328 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1331 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1333 mode = SVAL(pdata,l1_attrFile);
1334 size = IVAL(pdata,l1_cbFile);
1338 /* XXXX um, i don't think this is right.
1339 it's also not in the cifs6.txt spec.
1341 case SMB_INFO_QUERY_EAS_FROM_LIST:
1342 tvs.actime = make_unix_date2(pdata+8);
1343 tvs.modtime = make_unix_date2(pdata+12);
1344 size = IVAL(pdata,16);
1345 mode = IVAL(pdata,24);
1348 /* XXXX nor this. not in cifs6.txt, either. */
1349 case SMB_INFO_QUERY_ALL_EAS:
1350 tvs.actime = make_unix_date2(pdata+8);
1351 tvs.modtime = make_unix_date2(pdata+12);
1352 size = IVAL(pdata,16);
1353 mode = IVAL(pdata,24);
1356 case SMB_SET_FILE_BASIC_INFO:
1358 /* Ignore create time at offset pdata. */
1361 tvs.actime = interpret_long_date(pdata+8);
1363 /* write time + changed time, combined. */
1364 tvs.modtime=MAX(interpret_long_date(pdata+16),
1365 interpret_long_date(pdata+24));
1367 #if 0 /* Needs more testing... */
1368 /* Test from Luke to prevent Win95 from
1369 setting incorrect values here.
1371 if (tvs.actime < tvs.modtime)
1372 return(ERROR(ERRDOS,ERRnoaccess));
1373 #endif /* Needs more testing... */
1376 mode = IVAL(pdata,32);
1380 case SMB_SET_FILE_END_OF_FILE_INFO:
1382 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1383 return(ERROR(ERRDOS,ERRunknownlevel));
1384 size = IVAL(pdata,0);
1388 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1389 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1392 return(ERROR(ERRDOS,ERRunknownlevel));
1396 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1397 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1398 DEBUG(6,("size: %x " , size));
1399 DEBUG(6,("mode: %x\n" , mode));
1401 /* get some defaults (no modifications) if any info is zero. */
1402 if (!tvs.actime) tvs.actime = st.st_atime;
1403 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1404 if (!size) size = st.st_size;
1406 /* Try and set the times, size and mode of this file -
1407 if they are different from the current values
1409 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1411 if(sys_utime(fname, &tvs)!=0)
1413 return(ERROR(ERRDOS,ERRnoaccess));
1417 /* check the mode isn't different, before changing it */
1418 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1420 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1421 return(ERROR(ERRDOS,ERRnoaccess));
1424 if(size != st.st_size)
1428 fd = sys_open(fname,O_RDWR,0);
1431 return(ERROR(ERRDOS,ERRbadpath));
1433 set_filelen(fd, size);
1438 set_filelen(fd, size);
1444 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1449 /****************************************************************************
1450 reply to a TRANS2_MKDIR (make directory with extended attributes).
1451 ****************************************************************************/
1452 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1453 int cnum, char **pparams, char **ppdata)
1455 char *params = *pparams;
1458 BOOL bad_path = False;
1460 if (!CAN_WRITE(cnum))
1461 return(ERROR(ERRSRV,ERRaccess));
1463 pstrcpy(directory, ¶ms[4]);
1465 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1467 unix_convert(directory,cnum,0,&bad_path);
1468 if (check_name(directory,cnum))
1469 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1473 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1474 if((errno == ENOENT) && bad_path)
1476 unix_ERR_class = ERRDOS;
1477 unix_ERR_code = ERRbadpath;
1479 return(UNIXERROR(ERRDOS,ERRnoaccess));
1482 /* Realloc the parameter and data sizes */
1483 params = *pparams = Realloc(*pparams,2);
1485 return(ERROR(ERRDOS,ERRnomem));
1489 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1494 /****************************************************************************
1495 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1496 We don't actually do this - we just send a null response.
1497 ****************************************************************************/
1498 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1499 int cnum, char **pparams, char **ppdata)
1501 static uint16 fnf_handle = 257;
1502 char *params = *pparams;
1503 uint16 info_level = SVAL(params,4);
1505 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1513 return(ERROR(ERRDOS,ERRunknownlevel));
1516 /* Realloc the parameter and data sizes */
1517 params = *pparams = Realloc(*pparams,6);
1519 return(ERROR(ERRDOS,ERRnomem));
1521 SSVAL(params,0,fnf_handle);
1522 SSVAL(params,2,0); /* No changes */
1523 SSVAL(params,4,0); /* No EA errors */
1530 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1535 /****************************************************************************
1536 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1537 changes). Currently this does nothing.
1538 ****************************************************************************/
1539 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1540 int cnum, char **pparams, char **ppdata)
1542 char *params = *pparams;
1544 DEBUG(3,("call_trans2findnotifynext\n"));
1546 /* Realloc the parameter and data sizes */
1547 params = *pparams = Realloc(*pparams,4);
1549 return(ERROR(ERRDOS,ERRnomem));
1551 SSVAL(params,0,0); /* No changes */
1552 SSVAL(params,2,0); /* No EA errors */
1554 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1559 /****************************************************************************
1560 reply to a SMBfindclose (stop trans2 directory search)
1561 ****************************************************************************/
1562 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1566 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1568 cnum = SVAL(inbuf,smb_tid);
1570 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1572 dptr_close(dptr_num);
1574 outsize = set_message(outbuf,0,0,True);
1576 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1581 /****************************************************************************
1582 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1583 ****************************************************************************/
1584 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1590 cnum = SVAL(inbuf,smb_tid);
1591 dptr_num = SVAL(inbuf,smb_vwv0);
1593 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1595 /* We never give out valid handles for a
1596 findnotifyfirst - so any dptr_num is ok here.
1599 outsize = set_message(outbuf,0,0,True);
1601 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1607 /****************************************************************************
1608 reply to a SMBtranss2 - just ignore it!
1609 ****************************************************************************/
1610 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1612 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1616 /****************************************************************************
1617 reply to a SMBtrans2
1618 ****************************************************************************/
1619 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1622 int cnum = SVAL(inbuf,smb_tid);
1623 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1624 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1626 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1627 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1628 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1629 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1630 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1631 int32 timeout = IVALS(inbuf,smb_timeout);
1633 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1634 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1635 char *params = NULL, *data = NULL;
1636 int num_params, num_params_sofar, num_data, num_data_sofar;
1638 outsize = set_message(outbuf,0,0,True);
1640 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1641 is so as a sanity check */
1644 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1645 return(ERROR(ERRSRV,ERRerror));
1648 /* Allocate the space for the maximum needed parameters and data */
1649 if (total_params > 0)
1650 params = (char *)malloc(total_params);
1652 data = (char *)malloc(total_data);
1654 if ((total_params && !params) || (total_data && !data))
1656 DEBUG(2,("Out of memory in reply_trans2\n"));
1657 return(ERROR(ERRDOS,ERRnomem));
1660 /* Copy the param and data bytes sent with this request into
1661 the params buffer */
1662 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1663 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1665 if (num_params > total_params || num_data > total_data)
1666 exit_server("invalid params in reply_trans2");
1668 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1669 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1671 if(num_data_sofar < total_data || num_params_sofar < total_params)
1673 /* We need to send an interim response then receive the rest
1674 of the parameter/data bytes */
1675 outsize = set_message(outbuf,0,0,True);
1676 send_smb(Client,outbuf);
1678 while( num_data_sofar < total_data || num_params_sofar < total_params)
1680 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1681 CVAL(inbuf, smb_com) != SMBtranss2)
1683 outsize = set_message(outbuf,0,0,True);
1684 DEBUG(2,("Invalid secondary trans2 packet\n"));
1687 return(ERROR(ERRSRV,ERRerror));
1690 /* Revise total_params and total_data in case they have changed downwards */
1691 total_params = SVAL(inbuf, smb_tpscnt);
1692 total_data = SVAL(inbuf, smb_tdscnt);
1693 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1694 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1695 if (num_params_sofar > total_params || num_data_sofar > total_data)
1696 exit_server("data overflow in trans2");
1698 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1699 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1700 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1701 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1705 if (Protocol >= PROTOCOL_NT1) {
1706 uint16 flg2 = SVAL(outbuf,smb_flg2);
1707 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1710 /* Now we must call the relevant TRANS2 function */
1713 case TRANSACT2_OPEN:
1714 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1716 case TRANSACT2_FINDFIRST:
1717 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1719 case TRANSACT2_FINDNEXT:
1720 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1722 case TRANSACT2_QFSINFO:
1723 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1725 case TRANSACT2_SETFSINFO:
1726 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1728 case TRANSACT2_QPATHINFO:
1729 case TRANSACT2_QFILEINFO:
1730 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1732 case TRANSACT2_SETPATHINFO:
1733 case TRANSACT2_SETFILEINFO:
1734 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1736 case TRANSACT2_FINDNOTIFYFIRST:
1737 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1739 case TRANSACT2_FINDNOTIFYNEXT:
1740 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1742 case TRANSACT2_MKDIR:
1743 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1746 /* Error in request */
1747 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1752 return (ERROR(ERRSRV,ERRerror));
1755 /* As we do not know how many data packets will need to be
1756 returned here the various call_trans2xxxx calls
1757 must send their own. Thus a call_trans2xxx routine only
1758 returns a value other than -1 when it wants to send
1766 return outsize; /* If a correct response was needed the call_trans2xxx
1767 calls have already sent it. If outsize != -1 then it is
1768 returning an error packet. */