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;
33 extern int oplock_sock;
34 extern int smb_read_error;
36 /****************************************************************************
37 Send the required number of replies back.
38 We assume all fields other than the data fields are
39 set correctly for the type of call.
40 HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
43 int paramsize, char *pdata, int datasize)
45 /* As we are using a protocol > LANMAN1 then the max_send
46 variable must have been set in the sessetupX call.
47 This takes precedence over the max_xmit field in the
48 global struct. These different max_xmit variables should
49 be merged as this is now too confusing */
52 int data_to_send = datasize;
53 int params_to_send = paramsize;
57 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58 int alignment_offset = 1;
60 /* Initially set the wcnt area to be 10 - this is true for all
62 set_message(outbuf,10,0,True);
64 /* If there genuinely are no parameters or data to send just send
66 if(params_to_send == 0 && data_to_send == 0)
68 send_smb(Client,outbuf);
72 /* Space is bufsize minus Netbios over TCP header minus SMB header */
73 /* The alignment_offset is to align the param and data bytes on an even byte
74 boundary. NT 4.0 Beta needs this to work correctly. */
75 useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf);
76 /* useable_space can never be more than max_send minus the
78 useable_space = MIN(useable_space, max_send - alignment_offset);
80 while( params_to_send || data_to_send)
82 /* Calculate whether we will totally or partially fill this packet */
83 total_sent_thistime = params_to_send + data_to_send + alignment_offset;
84 /* We can never send more than useable_space */
85 total_sent_thistime = MIN(total_sent_thistime, useable_space);
87 set_message(outbuf, 10, total_sent_thistime, True);
89 /* Set total params and data to be sent */
90 SSVAL(outbuf,smb_tprcnt,paramsize);
91 SSVAL(outbuf,smb_tdrcnt,datasize);
93 /* Calculate how many parameters and data we can fit into
94 this packet. Parameters get precedence */
96 params_sent_thistime = MIN(params_to_send,useable_space);
97 data_sent_thistime = useable_space - params_sent_thistime;
98 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
100 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
101 if(params_sent_thistime == 0)
103 SSVAL(outbuf,smb_proff,0);
104 SSVAL(outbuf,smb_prdisp,0);
106 /* smb_proff is the offset from the start of the SMB header to the
107 parameter bytes, however the first 4 bytes of outbuf are
108 the Netbios over TCP header. Thus use smb_base() to subtract
109 them from the calculation */
110 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
111 /* Absolute displacement of param bytes sent in this packet */
112 SSVAL(outbuf,smb_prdisp,pp - params);
115 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
116 if(data_sent_thistime == 0)
118 SSVAL(outbuf,smb_droff,0);
119 SSVAL(outbuf,smb_drdisp, 0);
121 /* The offset of the data bytes is the offset of the
122 parameter bytes plus the number of parameters being sent this time */
123 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
124 smb_base(outbuf)) + params_sent_thistime);
125 SSVAL(outbuf,smb_drdisp, pd - pdata);
128 /* Copy the param bytes into the packet */
129 if(params_sent_thistime)
130 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
131 /* Copy in the data bytes */
132 if(data_sent_thistime)
133 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime);
135 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
136 params_sent_thistime, data_sent_thistime, useable_space));
137 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
138 params_to_send, data_to_send, paramsize, datasize));
140 /* Send the packet */
141 send_smb(Client,outbuf);
143 pp += params_sent_thistime;
144 pd += data_sent_thistime;
146 params_to_send -= params_sent_thistime;
147 data_to_send -= data_sent_thistime;
150 if(params_to_send < 0 || data_to_send < 0)
152 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
153 params_to_send, data_to_send));
162 /****************************************************************************
163 reply to a TRANSACT2_OPEN
164 ****************************************************************************/
165 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
166 char **pparams, char **ppdata)
168 char *params = *pparams;
169 int16 open_mode = SVAL(params, 2);
170 int16 open_attr = SVAL(params,6);
171 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
173 BOOL return_additional_info = BITSETW(params,0);
174 int16 open_sattr = SVAL(params, 4);
175 time_t open_time = make_unix_date3(params+8);
177 int16 open_ofun = SVAL(params,12);
178 int32 open_size = IVAL(params,14);
179 char *pname = ¶ms[28];
180 int16 namelen = strlen(pname)+1;
185 int size=0,fmode=0,mtime=0,rmode;
189 BOOL bad_path = False;
191 StrnCpy(fname,pname,namelen);
193 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
194 fname,cnum,open_mode, open_attr, open_ofun, open_size));
196 /* XXXX we need to handle passed times, sattr and flags */
198 unix_convert(fname,cnum,0,&bad_path);
200 fnum = find_free_file();
202 return(ERROR(ERRSRV,ERRnofids));
204 if (!check_name(fname,cnum))
206 if((errno == ENOENT) && bad_path)
208 unix_ERR_class = ERRDOS;
209 unix_ERR_code = ERRbadpath;
211 return(UNIXERROR(ERRDOS,ERRnoaccess));
214 unixmode = unix_mode(cnum,open_attr | aARCH);
217 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
218 oplock_request, &rmode,&smb_action);
220 if (!Files[fnum].open)
222 if((errno == ENOENT) && bad_path)
224 unix_ERR_class = ERRDOS;
225 unix_ERR_code = ERRbadpath;
227 return(UNIXERROR(ERRDOS,ERRnoaccess));
230 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
231 close_file(fnum,False);
232 return(ERROR(ERRDOS,ERRnoaccess));
236 fmode = dos_mode(cnum,fname,&sbuf);
237 mtime = sbuf.st_mtime;
240 close_file(fnum,False);
241 return(ERROR(ERRDOS,ERRnoaccess));
244 /* Realloc the size of parameters and data we will return */
245 params = *pparams = Realloc(*pparams, 28);
247 return(ERROR(ERRDOS,ERRnomem));
250 SSVAL(params,0,fnum);
251 SSVAL(params,2,fmode);
252 put_dos_date2(params,4, mtime);
253 SIVAL(params,8, size);
254 SSVAL(params,12,rmode);
256 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
257 smb_action |= EXTENDED_OPLOCK_GRANTED;
260 SSVAL(params,18,smb_action);
261 SIVAL(params,20,inode);
263 /* Send the required number of replies */
264 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
269 /****************************************************************************
270 get a level dependent lanman2 dir entry.
271 ****************************************************************************/
272 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
273 int requires_resume_key,
274 BOOL dont_descend,char **ppdata,
275 char *base_data, int space_remaining,
286 char *p, *pdata = *ppdata;
287 int reskey=0, prev_dirpos=0;
290 uint32 mdate=0, adate=0, cdate=0;
292 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
293 strequal(Connections[cnum].dirpath,".") ||
294 strequal(Connections[cnum].dirpath,"/"));
296 int nt_extmode; /* Used for NT connections instead of mode */
297 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
300 *out_of_space = False;
302 if (!Connections[cnum].dirptr)
305 p = strrchr(path_mask,'/');
314 pstrcpy(mask, path_mask);
318 /* Needed if we run out of space */
319 prev_dirpos = TellDir(Connections[cnum].dirptr);
320 dname = ReadDirName(Connections[cnum].dirptr);
322 reskey = TellDir(Connections[cnum].dirptr);
324 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
325 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
332 pstrcpy(fname,dname);
334 if(mask_match(fname, mask, case_sensitive, True))
336 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
337 if (dont_descend && !isdots)
340 if (isrootdir && isdots)
343 pstrcpy(pathreal,Connections[cnum].dirpath);
345 strcat(pathreal,"/");
346 strcat(pathreal,dname);
347 if (sys_stat(pathreal,&sbuf) != 0)
349 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
353 mode = dos_mode(cnum,pathreal,&sbuf);
355 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
356 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
361 mdate = sbuf.st_mtime;
362 adate = sbuf.st_atime;
363 cdate = sbuf.st_ctime;
367 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
373 name_map_mangle(fname,False,SNUM(cnum));
378 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
383 if(requires_resume_key) {
387 put_dos_date2(p,l1_fdateCreation,cdate);
388 put_dos_date2(p,l1_fdateLastAccess,adate);
389 put_dos_date2(p,l1_fdateLastWrite,mdate);
390 SIVAL(p,l1_cbFile,size);
391 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
392 SSVAL(p,l1_attrFile,mode);
393 SCVAL(p,l1_cchName,strlen(fname));
394 strcpy(p + l1_achName, fname);
395 nameptr = p + l1_achName;
396 p += l1_achName + strlen(fname) + 1;
401 if(requires_resume_key) {
405 put_dos_date2(p,l2_fdateCreation,cdate);
406 put_dos_date2(p,l2_fdateLastAccess,adate);
407 put_dos_date2(p,l2_fdateLastWrite,mdate);
408 SIVAL(p,l2_cbFile,size);
409 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
410 SSVAL(p,l2_attrFile,mode);
411 SIVAL(p,l2_cbList,0); /* No extended attributes */
412 SCVAL(p,l2_cchName,strlen(fname));
413 strcpy(p + l2_achName, fname);
414 nameptr = p + l2_achName;
415 p += l2_achName + strlen(fname) + 1;
420 put_dos_date2(p,4,cdate);
421 put_dos_date2(p,8,adate);
422 put_dos_date2(p,12,mdate);
424 SIVAL(p,20,ROUNDUP(size,1024));
427 CVAL(p,30) = strlen(fname);
430 p += 31 + strlen(fname) + 1;
434 if(requires_resume_key) {
438 SIVAL(p,0,33+strlen(fname)+1);
439 put_dos_date2(p,4,cdate);
440 put_dos_date2(p,8,adate);
441 put_dos_date2(p,12,mdate);
443 SIVAL(p,20,ROUNDUP(size,1024));
445 CVAL(p,32) = strlen(fname);
446 strcpy(p + 33, fname);
448 p += 33 + strlen(fname) + 1;
451 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
452 was_8_3 = is_8_3(fname, True);
453 len = 94+strlen(fname);
454 len = (len + 3) & ~3;
455 SIVAL(p,0,len); p += 4;
456 SIVAL(p,0,reskey); p += 4;
457 put_long_date(p,cdate); p += 8;
458 put_long_date(p,adate); p += 8;
459 put_long_date(p,mdate); p += 8;
460 put_long_date(p,mdate); p += 8;
461 SIVAL(p,0,size); p += 8;
462 SIVAL(p,0,size); p += 8;
463 SIVAL(p,0,nt_extmode); p += 4;
464 SIVAL(p,0,strlen(fname)); p += 4;
465 SIVAL(p,0,0); p += 4;
468 if (!name_map_mangle(p+2,True,SNUM(cnum)))
473 SSVAL(p,0,strlen(p+2));
476 strcpy(p,fname); p += strlen(p);
480 case SMB_FIND_FILE_DIRECTORY_INFO:
481 len = 64+strlen(fname);
482 len = (len + 3) & ~3;
483 SIVAL(p,0,len); p += 4;
484 SIVAL(p,0,reskey); p += 4;
485 put_long_date(p,cdate); p += 8;
486 put_long_date(p,adate); p += 8;
487 put_long_date(p,mdate); p += 8;
488 put_long_date(p,mdate); p += 8;
489 SIVAL(p,0,size); p += 8;
490 SIVAL(p,0,size); p += 8;
491 SIVAL(p,0,nt_extmode); p += 4;
492 SIVAL(p,0,strlen(fname)); p += 4;
498 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
499 len = 68+strlen(fname);
500 len = (len + 3) & ~3;
501 SIVAL(p,0,len); p += 4;
502 SIVAL(p,0,reskey); p += 4;
503 put_long_date(p,cdate); p += 8;
504 put_long_date(p,adate); p += 8;
505 put_long_date(p,mdate); p += 8;
506 put_long_date(p,mdate); p += 8;
507 SIVAL(p,0,size); p += 8;
508 SIVAL(p,0,size); p += 8;
509 SIVAL(p,0,nt_extmode); p += 4;
510 SIVAL(p,0,strlen(fname)); p += 4;
511 SIVAL(p,0,0); p += 4;
516 case SMB_FIND_FILE_NAMES_INFO:
517 len = 12+strlen(fname);
518 len = (len + 3) & ~3;
519 SIVAL(p,0,len); p += 4;
520 SIVAL(p,0,reskey); p += 4;
521 SIVAL(p,0,strlen(fname)); p += 4;
531 if (PTR_DIFF(p,pdata) > space_remaining) {
532 /* Move the dirptr back to prev_dirpos */
533 SeekDir(Connections[cnum].dirptr, prev_dirpos);
534 *out_of_space = True;
535 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
536 return False; /* Not finished - just out of space */
539 /* Setup the last_filename pointer, as an offset from base_data */
540 *last_name_off = PTR_DIFF(nameptr,base_data);
541 /* Advance the data pointer to the next slot */
546 /****************************************************************************
547 reply to a TRANS2_FINDFIRST
548 ****************************************************************************/
549 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
550 char **pparams, char **ppdata)
552 /* We must be careful here that we don't return more than the
553 allowed number of data bytes. If this means returning fewer than
554 maxentries then so be it. We assume that the redirector has
555 enough room for the fixed number of parameter bytes it has
557 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
558 char *params = *pparams;
559 char *pdata = *ppdata;
560 int dirtype = SVAL(params,0);
561 int maxentries = SVAL(params,2);
562 BOOL close_after_first = BITSETW(params+4,0);
563 BOOL close_if_end = BITSETW(params+4,1);
564 BOOL requires_resume_key = BITSETW(params+4,2);
565 int info_level = SVAL(params,6);
573 BOOL finished = False;
574 BOOL dont_descend = False;
575 BOOL out_of_space = False;
577 BOOL bad_path = False;
579 *directory = *mask = 0;
581 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
582 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
583 info_level, max_data_bytes));
591 case SMB_FIND_FILE_DIRECTORY_INFO:
592 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
593 case SMB_FIND_FILE_NAMES_INFO:
594 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
597 return(ERROR(ERRDOS,ERRunknownlevel));
600 pstrcpy(directory, params + 12); /* Complete directory path with
601 wildcard mask appended */
603 DEBUG(5,("path=%s\n",directory));
605 unix_convert(directory,cnum,0,&bad_path);
606 if(!check_name(directory,cnum)) {
607 if((errno == ENOENT) && bad_path)
609 unix_ERR_class = ERRDOS;
610 unix_ERR_code = ERRbadpath;
614 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
615 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
616 (get_remote_arch() == RA_WINNT))
618 unix_ERR_class = ERRDOS;
619 unix_ERR_code = ERRbaddirectory;
623 return(ERROR(ERRDOS,ERRbadpath));
626 p = strrchr(directory,'/');
628 strcpy(mask,directory);
629 strcpy(directory,"./");
635 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
637 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
639 return(ERROR(ERRDOS,ERRnomem));
640 bzero(pdata,max_data_bytes);
642 /* Realloc the params space */
643 params = *pparams = Realloc(*pparams, 10);
645 return(ERROR(ERRDOS,ERRnomem));
647 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
649 return(ERROR(ERRDOS,ERRbadfile));
651 /* convert the formatted masks */
655 if (*p == '<') *p = '*';
656 if (*p == '>') *p = '?';
657 if (*p == '"') *p = '.';
662 /* a special case for 16 bit apps */
663 if (strequal(mask,"????????.???")) strcpy(mask,"*");
665 /* handle broken clients that send us old 8.3 format */
666 string_sub(mask,"????????","*");
667 string_sub(mask,".???",".*");
669 /* Save the wildcard match and attribs we are using on this directory -
670 needed as lanman2 assumes these are being saved between calls */
672 if(!(wcard = strdup(mask))) {
673 dptr_close(dptr_num);
674 return(ERROR(ERRDOS,ERRnomem));
677 dptr_set_wcard(dptr_num, wcard);
678 dptr_set_attr(dptr_num, dirtype);
680 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
682 /* We don't need to check for VOL here as this is returned by
683 a different TRANS2 call. */
685 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
686 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
687 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
691 space_remaining = max_data_bytes;
692 out_of_space = False;
694 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
697 /* this is a heuristic to avoid seeking the dirptr except when
698 absolutely necessary. It allows for a filename of about 40 chars */
699 if (space_remaining < DIRLEN_GUESS && numentries > 0)
707 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
708 requires_resume_key,dont_descend,
709 &p,pdata,space_remaining, &out_of_space,
713 if (finished && out_of_space)
716 if (!finished && !out_of_space)
718 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
721 /* Check if we can close the dirptr */
722 if(close_after_first || (finished && close_if_end))
724 dptr_close(dptr_num);
725 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
730 * If there are no matching entries we must return ERRDOS/ERRbadfile -
731 * from observation of NT.
735 return(ERROR(ERRDOS,ERRbadfile));
737 /* At this point pdata points to numentries directory entries. */
739 /* Set up the return parameter block */
740 SSVAL(params,0,dptr_num);
741 SSVAL(params,2,numentries);
742 SSVAL(params,4,finished);
743 SSVAL(params,6,0); /* Never an EA error */
744 SSVAL(params,8,last_name_off);
746 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
748 if ((! *directory) && dptr_path(dptr_num))
749 sprintf(directory,"(%s)",dptr_path(dptr_num));
751 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
753 smb_fn_name(CVAL(inbuf,smb_com)),
754 mask,directory,cnum,dirtype,numentries));
760 /****************************************************************************
761 reply to a TRANS2_FINDNEXT
762 ****************************************************************************/
763 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
764 int cnum, char **pparams, char **ppdata)
766 /* We must be careful here that we don't return more than the
767 allowed number of data bytes. If this means returning fewer than
768 maxentries then so be it. We assume that the redirector has
769 enough room for the fixed number of parameter bytes it has
771 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
772 char *params = *pparams;
773 char *pdata = *ppdata;
774 int16 dptr_num = SVAL(params,0);
775 int maxentries = SVAL(params,2);
776 uint16 info_level = SVAL(params,4);
777 uint32 resume_key = IVAL(params,6);
778 BOOL close_after_request = BITSETW(params+10,0);
779 BOOL close_if_end = BITSETW(params+10,1);
780 BOOL requires_resume_key = BITSETW(params+10,2);
781 BOOL continue_bit = BITSETW(params+10,3);
787 int i, last_name_off=0;
788 BOOL finished = False;
789 BOOL dont_descend = False;
790 BOOL out_of_space = False;
793 *mask = *directory = 0;
795 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",
796 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
797 requires_resume_key, resume_key, continue_bit, info_level));
805 case SMB_FIND_FILE_DIRECTORY_INFO:
806 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
807 case SMB_FIND_FILE_NAMES_INFO:
808 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
811 return(ERROR(ERRDOS,ERRunknownlevel));
814 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
816 return(ERROR(ERRDOS,ERRnomem));
817 bzero(pdata,max_data_bytes);
819 /* Realloc the params space */
820 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
822 return(ERROR(ERRDOS,ERRnomem));
824 /* Check that the dptr is valid */
825 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
826 return(ERROR(ERRDOS,ERRnofiles));
828 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
830 /* Get the wildcard mask from the dptr */
831 if((p = dptr_wcard(dptr_num))== NULL) {
832 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
833 return (ERROR(ERRDOS,ERRnofiles));
836 strcpy(directory,Connections[cnum].dirpath);
838 /* Get the attr mask from the dptr */
839 dirtype = dptr_attr(dptr_num);
841 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
842 dptr_num, mask, dirtype,
843 Connections[cnum].dirptr,
844 TellDir(Connections[cnum].dirptr)));
846 /* We don't need to check for VOL here as this is returned by
847 a different TRANS2 call. */
849 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
850 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
854 space_remaining = max_data_bytes;
855 out_of_space = False;
857 /* If we have a resume key - seek to the correct position. */
858 if(requires_resume_key && !continue_bit)
859 SeekDir(Connections[cnum].dirptr, resume_key);
861 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
863 /* this is a heuristic to avoid seeking the dirptr except when
864 absolutely necessary. It allows for a filename of about 40 chars */
865 if (space_remaining < DIRLEN_GUESS && numentries > 0)
873 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
874 requires_resume_key,dont_descend,
875 &p,pdata,space_remaining, &out_of_space,
879 if (finished && out_of_space)
882 if (!finished && !out_of_space)
884 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
887 /* Check if we can close the dirptr */
888 if(close_after_request || (finished && close_if_end))
890 dptr_close(dptr_num); /* This frees up the saved mask */
891 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
896 /* Set up the return parameter block */
897 SSVAL(params,0,numentries);
898 SSVAL(params,2,finished);
899 SSVAL(params,4,0); /* Never an EA error */
900 SSVAL(params,6,last_name_off);
902 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
904 if ((! *directory) && dptr_path(dptr_num))
905 sprintf(directory,"(%s)",dptr_path(dptr_num));
907 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
909 smb_fn_name(CVAL(inbuf,smb_com)),
910 mask,directory,cnum,dirtype,numentries));
915 /****************************************************************************
916 reply to a TRANS2_QFSINFO (query filesystem info)
917 ****************************************************************************/
918 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
919 int cnum, char **pparams, char **ppdata)
921 char *pdata = *ppdata;
922 char *params = *pparams;
923 uint16 info_level = SVAL(params,0);
926 char *vname = volume_label(SNUM(cnum));
928 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
930 if(sys_stat(".",&st)!=0) {
931 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
932 return (ERROR(ERRSRV,ERRinvdevice));
935 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
941 int dfree,dsize,bsize;
943 sys_disk_free(".",&bsize,&dfree,&dsize);
944 SIVAL(pdata,l1_idFileSystem,st.st_dev);
945 SIVAL(pdata,l1_cSectorUnit,bsize/512);
946 SIVAL(pdata,l1_cUnit,dsize);
947 SIVAL(pdata,l1_cUnitAvail,dfree);
948 SSVAL(pdata,l1_cbSector,512);
949 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
950 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
955 /* Return volume name */
956 int volname_len = MIN(strlen(vname),11);
957 data_len = l2_vol_szVolLabel + volname_len + 1;
958 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
959 SCVAL(pdata,l2_vol_cch,volname_len);
960 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
961 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
962 pdata+l2_vol_szVolLabel));
965 case SMB_QUERY_FS_ATTRIBUTE_INFO:
966 data_len = 12 + 2*strlen(FSTYPE_STRING);
967 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
968 SIVAL(pdata,4,128); /* Max filename component length */
969 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
970 PutUniCode(pdata+12,FSTYPE_STRING);
972 case SMB_QUERY_FS_LABEL_INFO:
973 data_len = 4 + strlen(vname);
974 SIVAL(pdata,0,strlen(vname));
975 strcpy(pdata+4,vname);
977 case SMB_QUERY_FS_VOLUME_INFO:
978 data_len = 18 + 2*strlen(vname);
979 SIVAL(pdata,12,2*strlen(vname));
980 PutUniCode(pdata+18,vname);
981 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
984 case SMB_QUERY_FS_SIZE_INFO:
986 int dfree,dsize,bsize;
988 sys_disk_free(".",&bsize,&dfree,&dsize);
989 SIVAL(pdata,0,dsize);
990 SIVAL(pdata,8,dfree);
991 SIVAL(pdata,16,bsize/512);
995 case SMB_QUERY_FS_DEVICE_INFO:
997 SIVAL(pdata,0,0); /* dev type */
998 SIVAL(pdata,4,0); /* characteristics */
1001 return(ERROR(ERRDOS,ERRunknownlevel));
1005 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1007 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1012 /****************************************************************************
1013 reply to a TRANS2_SETFSINFO (set filesystem info)
1014 ****************************************************************************/
1015 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1016 int cnum, char **pparams, char **ppdata)
1018 /* Just say yes we did it - there is nothing that
1019 can be set here so it doesn't matter. */
1021 DEBUG(3,("call_trans2setfsinfo\n"));
1023 if (!CAN_WRITE(cnum))
1024 return(ERROR(ERRSRV,ERRaccess));
1026 outsize = set_message(outbuf,10,0,True);
1031 /****************************************************************************
1032 reply to a TRANS2_QFILEINFO (query file info by fileid)
1033 ****************************************************************************/
1034 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1035 int bufsize,int cnum,
1036 char **pparams,char **ppdata,
1039 char *params = *pparams;
1040 char *pdata = *ppdata;
1041 uint16 tran_call = SVAL(inbuf, smb_setup0);
1045 unsigned int data_size;
1051 BOOL bad_path = False;
1053 if (tran_call == TRANSACT2_QFILEINFO) {
1054 int16 fnum = SVALS(params,0);
1055 info_level = SVAL(params,2);
1057 CHECK_FNUM(fnum,cnum);
1060 fname = Files[fnum].name;
1061 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1062 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1063 return(UNIXERROR(ERRDOS,ERRbadfid));
1065 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1068 info_level = SVAL(params,0);
1070 pstrcpy(fname,¶ms[6]);
1071 unix_convert(fname,cnum,0,&bad_path);
1072 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1073 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1074 if((errno == ENOENT) && bad_path)
1076 unix_ERR_class = ERRDOS;
1077 unix_ERR_code = ERRbadpath;
1079 return(UNIXERROR(ERRDOS,ERRbadpath));
1085 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1086 fname,info_level,tran_call,total_data));
1088 p = strrchr(fname,'/');
1094 mode = dos_mode(cnum,fname,&sbuf);
1095 size = sbuf.st_size;
1096 if (mode & aDIR) size = 0;
1098 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1100 pdata = *ppdata = Realloc(*ppdata, data_size);
1102 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1103 /* uggh, EAs for OS2 */
1104 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1105 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1108 bzero(pdata,data_size);
1112 case SMB_INFO_STANDARD:
1113 case SMB_INFO_QUERY_EA_SIZE:
1114 data_size = (info_level==1?22:26);
1115 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1116 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1117 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1118 SIVAL(pdata,l1_cbFile,size);
1119 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1120 SSVAL(pdata,l1_attrFile,mode);
1121 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1124 case SMB_INFO_QUERY_EAS_FROM_LIST:
1126 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1127 put_dos_date2(pdata,4,sbuf.st_atime);
1128 put_dos_date2(pdata,8,sbuf.st_mtime);
1129 SIVAL(pdata,12,size);
1130 SIVAL(pdata,16,ROUNDUP(size,1024));
1131 SIVAL(pdata,20,mode);
1134 case SMB_INFO_QUERY_ALL_EAS:
1136 SIVAL(pdata,0,data_size);
1140 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1142 case SMB_QUERY_FILE_BASIC_INFO:
1143 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1144 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1145 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1146 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1147 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1148 SIVAL(pdata,32,mode);
1150 DEBUG(5,("SMB_QFBI - "));
1151 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1152 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1153 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1154 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1155 DEBUG(5,("mode: %x\n", mode));
1159 case SMB_QUERY_FILE_STANDARD_INFO:
1161 SIVAL(pdata,0,size);
1162 SIVAL(pdata,8,size);
1163 SIVAL(pdata,16,sbuf.st_nlink);
1165 CVAL(pdata,21) = (mode&aDIR)?1:0;
1168 case SMB_QUERY_FILE_EA_INFO:
1172 /* Get the 8.3 name - used if NT SMB was negotiated. */
1173 case SMB_QUERY_FILE_ALT_NAME_INFO:
1176 pstrcpy(short_name,fname);
1177 /* Mangle if not already 8.3 */
1178 if(!is_8_3(short_name, True))
1180 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1183 strncpy(pdata + 4,short_name,12);
1184 (pdata + 4)[12] = 0;
1185 strupper(pdata + 4);
1186 l = strlen(pdata + 4);
1192 case SMB_QUERY_FILE_NAME_INFO:
1195 pstrcpy(pdata+4,fname);
1198 case SMB_QUERY_FILE_ALLOCATION_INFO:
1199 case SMB_QUERY_FILE_END_OF_FILEINFO:
1201 SIVAL(pdata,0,size);
1204 case SMB_QUERY_FILE_ALL_INFO:
1205 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1206 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1207 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1208 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1209 SIVAL(pdata,32,mode);
1211 SIVAL(pdata,0,size);
1212 SIVAL(pdata,8,size);
1213 SIVAL(pdata,16,sbuf.st_nlink);
1215 CVAL(pdata,21) = (mode&aDIR)?1:0;
1217 pdata += 8; /* index number */
1218 pdata += 4; /* EA info */
1220 SIVAL(pdata,0,0xA9);
1222 SIVAL(pdata,0,0xd01BF);
1224 SIVAL(pdata,0,pos); /* current offset */
1226 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1228 pdata += 4; /* alignment */
1230 pstrcpy(pdata+4,fname);
1232 data_size = PTR_DIFF(pdata,(*ppdata));
1235 case SMB_QUERY_FILE_STREAM_INFO:
1238 SIVAL(pdata,4,size);
1239 SIVAL(pdata,12,size);
1241 pstrcpy(pdata+24,fname);
1244 return(ERROR(ERRDOS,ERRunknownlevel));
1247 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1252 /****************************************************************************
1253 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1254 ****************************************************************************/
1255 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1256 int bufsize, int cnum, char **pparams,
1257 char **ppdata, int total_data)
1259 char *params = *pparams;
1260 char *pdata = *ppdata;
1261 uint16 tran_call = SVAL(inbuf, smb_setup0);
1270 BOOL bad_path = False;
1272 if (!CAN_WRITE(cnum))
1273 return(ERROR(ERRSRV,ERRaccess));
1275 if (tran_call == TRANSACT2_SETFILEINFO) {
1276 int16 fnum = SVALS(params,0);
1277 info_level = SVAL(params,2);
1279 CHECK_FNUM(fnum,cnum);
1282 fname = Files[fnum].name;
1283 fd = Files[fnum].fd_ptr->fd;
1285 if(fstat(fd,&st)!=0) {
1286 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1287 return(ERROR(ERRDOS,ERRbadpath));
1291 info_level = SVAL(params,0);
1293 pstrcpy(fname,¶ms[6]);
1294 unix_convert(fname,cnum,0,&bad_path);
1295 if(!check_name(fname, cnum))
1297 if((errno == ENOENT) && bad_path)
1299 unix_ERR_class = ERRDOS;
1300 unix_ERR_code = ERRbadpath;
1302 return(UNIXERROR(ERRDOS,ERRbadpath));
1305 if(sys_stat(fname,&st)!=0) {
1306 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1307 if((errno == ENOENT) && bad_path)
1309 unix_ERR_class = ERRDOS;
1310 unix_ERR_code = ERRbadpath;
1312 return(UNIXERROR(ERRDOS,ERRbadpath));
1316 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1317 tran_call,fname,info_level,total_data));
1319 /* Realloc the parameter and data sizes */
1320 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1322 return(ERROR(ERRDOS,ERRnomem));
1325 tvs.modtime = st.st_mtime;
1326 tvs.actime = st.st_atime;
1327 mode = dos_mode(cnum,fname,&st);
1329 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1330 /* uggh, EAs for OS2 */
1331 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1332 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1337 case SMB_INFO_STANDARD:
1338 case SMB_INFO_QUERY_EA_SIZE:
1341 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1344 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1346 mode = SVAL(pdata,l1_attrFile);
1347 size = IVAL(pdata,l1_cbFile);
1351 /* XXXX um, i don't think this is right.
1352 it's also not in the cifs6.txt spec.
1354 case SMB_INFO_QUERY_EAS_FROM_LIST:
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 /* XXXX nor this. not in cifs6.txt, either. */
1362 case SMB_INFO_QUERY_ALL_EAS:
1363 tvs.actime = make_unix_date2(pdata+8);
1364 tvs.modtime = make_unix_date2(pdata+12);
1365 size = IVAL(pdata,16);
1366 mode = IVAL(pdata,24);
1369 case SMB_SET_FILE_BASIC_INFO:
1371 /* Ignore create time at offset pdata. */
1374 tvs.actime = interpret_long_date(pdata+8);
1376 /* write time + changed time, combined. */
1377 tvs.modtime=MAX(interpret_long_date(pdata+16),
1378 interpret_long_date(pdata+24));
1380 #if 0 /* Needs more testing... */
1381 /* Test from Luke to prevent Win95 from
1382 setting incorrect values here.
1384 if (tvs.actime < tvs.modtime)
1385 return(ERROR(ERRDOS,ERRnoaccess));
1386 #endif /* Needs more testing... */
1389 mode = IVAL(pdata,32);
1393 case SMB_SET_FILE_END_OF_FILE_INFO:
1395 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1396 return(ERROR(ERRDOS,ERRunknownlevel));
1397 size = IVAL(pdata,0);
1401 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1402 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1405 return(ERROR(ERRDOS,ERRunknownlevel));
1409 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1410 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1411 DEBUG(6,("size: %x " , size));
1412 DEBUG(6,("mode: %x\n" , mode));
1414 /* get some defaults (no modifications) if any info is zero. */
1415 if (!tvs.actime) tvs.actime = st.st_atime;
1416 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1417 if (!size) size = st.st_size;
1419 /* Try and set the times, size and mode of this file -
1420 if they are different from the current values
1422 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1424 if(file_utime(cnum, fname, &tvs)!=0)
1426 return(ERROR(ERRDOS,ERRnoaccess));
1430 /* check the mode isn't different, before changing it */
1431 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1433 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1434 return(ERROR(ERRDOS,ERRnoaccess));
1437 if(size != st.st_size)
1441 fd = sys_open(fname,O_RDWR,0);
1444 return(ERROR(ERRDOS,ERRbadpath));
1446 set_filelen(fd, size);
1451 set_filelen(fd, size);
1457 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1462 /****************************************************************************
1463 reply to a TRANS2_MKDIR (make directory with extended attributes).
1464 ****************************************************************************/
1465 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1466 int cnum, char **pparams, char **ppdata)
1468 char *params = *pparams;
1471 BOOL bad_path = False;
1473 if (!CAN_WRITE(cnum))
1474 return(ERROR(ERRSRV,ERRaccess));
1476 pstrcpy(directory, ¶ms[4]);
1478 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1480 unix_convert(directory,cnum,0,&bad_path);
1481 if (check_name(directory,cnum))
1482 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1486 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1487 if((errno == ENOENT) && bad_path)
1489 unix_ERR_class = ERRDOS;
1490 unix_ERR_code = ERRbadpath;
1492 return(UNIXERROR(ERRDOS,ERRnoaccess));
1495 /* Realloc the parameter and data sizes */
1496 params = *pparams = Realloc(*pparams,2);
1498 return(ERROR(ERRDOS,ERRnomem));
1502 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1507 /****************************************************************************
1508 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1509 We don't actually do this - we just send a null response.
1510 ****************************************************************************/
1511 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1512 int cnum, char **pparams, char **ppdata)
1514 static uint16 fnf_handle = 257;
1515 char *params = *pparams;
1516 uint16 info_level = SVAL(params,4);
1518 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1526 return(ERROR(ERRDOS,ERRunknownlevel));
1529 /* Realloc the parameter and data sizes */
1530 params = *pparams = Realloc(*pparams,6);
1532 return(ERROR(ERRDOS,ERRnomem));
1534 SSVAL(params,0,fnf_handle);
1535 SSVAL(params,2,0); /* No changes */
1536 SSVAL(params,4,0); /* No EA errors */
1543 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1548 /****************************************************************************
1549 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1550 changes). Currently this does nothing.
1551 ****************************************************************************/
1552 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1553 int cnum, char **pparams, char **ppdata)
1555 char *params = *pparams;
1557 DEBUG(3,("call_trans2findnotifynext\n"));
1559 /* Realloc the parameter and data sizes */
1560 params = *pparams = Realloc(*pparams,4);
1562 return(ERROR(ERRDOS,ERRnomem));
1564 SSVAL(params,0,0); /* No changes */
1565 SSVAL(params,2,0); /* No EA errors */
1567 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1572 /****************************************************************************
1573 reply to a SMBfindclose (stop trans2 directory search)
1574 ****************************************************************************/
1575 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1579 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1581 cnum = SVAL(inbuf,smb_tid);
1583 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1585 dptr_close(dptr_num);
1587 outsize = set_message(outbuf,0,0,True);
1589 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1594 /****************************************************************************
1595 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1596 ****************************************************************************/
1597 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1603 cnum = SVAL(inbuf,smb_tid);
1604 dptr_num = SVAL(inbuf,smb_vwv0);
1606 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1608 /* We never give out valid handles for a
1609 findnotifyfirst - so any dptr_num is ok here.
1612 outsize = set_message(outbuf,0,0,True);
1614 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1620 /****************************************************************************
1621 reply to a SMBtranss2 - just ignore it!
1622 ****************************************************************************/
1623 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1625 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1629 /****************************************************************************
1630 reply to a SMBtrans2
1631 ****************************************************************************/
1632 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1635 int cnum = SVAL(inbuf,smb_tid);
1636 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1637 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1639 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1640 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1641 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1642 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1643 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1644 int32 timeout = IVALS(inbuf,smb_timeout);
1646 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1647 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1648 char *params = NULL, *data = NULL;
1649 int num_params, num_params_sofar, num_data, num_data_sofar;
1651 outsize = set_message(outbuf,0,0,True);
1653 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1654 is so as a sanity check */
1657 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1658 return(ERROR(ERRSRV,ERRerror));
1661 /* Allocate the space for the maximum needed parameters and data */
1662 if (total_params > 0)
1663 params = (char *)malloc(total_params);
1665 data = (char *)malloc(total_data);
1667 if ((total_params && !params) || (total_data && !data))
1669 DEBUG(2,("Out of memory in reply_trans2\n"));
1670 return(ERROR(ERRDOS,ERRnomem));
1673 /* Copy the param and data bytes sent with this request into
1674 the params buffer */
1675 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1676 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1678 if (num_params > total_params || num_data > total_data)
1679 exit_server("invalid params in reply_trans2");
1681 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1682 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1684 if(num_data_sofar < total_data || num_params_sofar < total_params)
1686 /* We need to send an interim response then receive the rest
1687 of the parameter/data bytes */
1688 outsize = set_message(outbuf,0,0,True);
1689 send_smb(Client,outbuf);
1691 while( num_data_sofar < total_data || num_params_sofar < total_params)
1695 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1696 SMB_SECONDARY_WAIT);
1698 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1700 outsize = set_message(outbuf,0,0,True);
1702 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1704 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1705 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1708 return(ERROR(ERRSRV,ERRerror));
1711 /* Revise total_params and total_data in case they have changed downwards */
1712 total_params = SVAL(inbuf, smb_tpscnt);
1713 total_data = SVAL(inbuf, smb_tdscnt);
1714 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1715 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1716 if (num_params_sofar > total_params || num_data_sofar > total_data)
1717 exit_server("data overflow in trans2");
1719 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1720 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1721 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1722 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1726 if (Protocol >= PROTOCOL_NT1) {
1727 uint16 flg2 = SVAL(outbuf,smb_flg2);
1728 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1731 /* Now we must call the relevant TRANS2 function */
1734 case TRANSACT2_OPEN:
1735 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1737 case TRANSACT2_FINDFIRST:
1738 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1740 case TRANSACT2_FINDNEXT:
1741 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1743 case TRANSACT2_QFSINFO:
1744 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1746 case TRANSACT2_SETFSINFO:
1747 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1749 case TRANSACT2_QPATHINFO:
1750 case TRANSACT2_QFILEINFO:
1751 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1753 case TRANSACT2_SETPATHINFO:
1754 case TRANSACT2_SETFILEINFO:
1755 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1757 case TRANSACT2_FINDNOTIFYFIRST:
1758 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1760 case TRANSACT2_FINDNOTIFYNEXT:
1761 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1763 case TRANSACT2_MKDIR:
1764 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1767 /* Error in request */
1768 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1773 return (ERROR(ERRSRV,ERRerror));
1776 /* As we do not know how many data packets will need to be
1777 returned here the various call_trans2xxxx calls
1778 must send their own. Thus a call_trans2xxx routine only
1779 returns a value other than -1 when it wants to send
1787 return outsize; /* If a correct response was needed the call_trans2xxx
1788 calls have already sent it. If outsize != -1 then it is
1789 returning an error packet. */