2 Unix SMB/Netbios implementation.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1998
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
33 extern int oplock_sock;
34 extern int smb_read_error;
36 /****************************************************************************
37 Send the required number of replies back.
38 We assume all fields other than the data fields are
39 set correctly for the type of call.
40 HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
43 int paramsize, char *pdata, int datasize)
45 /* As we are using a protocol > LANMAN1 then the max_send
46 variable must have been set in the sessetupX call.
47 This takes precedence over the max_xmit field in the
48 global struct. These different max_xmit variables should
49 be merged as this is now too confusing */
52 int data_to_send = datasize;
53 int params_to_send = paramsize;
57 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58 int alignment_offset = 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 Files[fnum].reserved = False;
212 return(UNIXERROR(ERRDOS,ERRnoaccess));
215 unixmode = unix_mode(cnum,open_attr | aARCH);
218 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
219 oplock_request, &rmode,&smb_action);
221 if (!Files[fnum].open)
223 if((errno == ENOENT) && bad_path)
225 unix_ERR_class = ERRDOS;
226 unix_ERR_code = ERRbadpath;
228 Files[fnum].reserved = False;
229 return(UNIXERROR(ERRDOS,ERRnoaccess));
232 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
233 close_file(fnum,False);
234 return(ERROR(ERRDOS,ERRnoaccess));
238 fmode = dos_mode(cnum,fname,&sbuf);
239 mtime = sbuf.st_mtime;
242 close_file(fnum,False);
243 return(ERROR(ERRDOS,ERRnoaccess));
246 /* Realloc the size of parameters and data we will return */
247 params = *pparams = Realloc(*pparams, 28);
249 return(ERROR(ERRDOS,ERRnomem));
252 SSVAL(params,0,fnum);
253 SSVAL(params,2,fmode);
254 put_dos_date2(params,4, mtime);
255 SIVAL(params,8, size);
256 SSVAL(params,12,rmode);
258 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
259 smb_action |= EXTENDED_OPLOCK_GRANTED;
262 SSVAL(params,18,smb_action);
263 SIVAL(params,20,inode);
265 /* Send the required number of replies */
266 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
271 /****************************************************************************
272 get a level dependent lanman2 dir entry.
273 ****************************************************************************/
274 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
275 int requires_resume_key,
276 BOOL dont_descend,char **ppdata,
277 char *base_data, int space_remaining,
288 char *p, *pdata = *ppdata;
289 int reskey=0, prev_dirpos=0;
292 uint32 mdate=0, adate=0, cdate=0;
294 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
295 strequal(Connections[cnum].dirpath,".") ||
296 strequal(Connections[cnum].dirpath,"/"));
298 int nt_extmode; /* Used for NT connections instead of mode */
299 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
302 *out_of_space = False;
304 if (!Connections[cnum].dirptr)
307 p = strrchr(path_mask,'/');
316 pstrcpy(mask, path_mask);
320 /* Needed if we run out of space */
321 prev_dirpos = TellDir(Connections[cnum].dirptr);
322 dname = ReadDirName(Connections[cnum].dirptr);
324 reskey = TellDir(Connections[cnum].dirptr);
326 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
327 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
334 pstrcpy(fname,dname);
336 if(mask_match(fname, mask, case_sensitive, True))
338 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
339 if (dont_descend && !isdots)
342 if (isrootdir && isdots)
345 pstrcpy(pathreal,Connections[cnum].dirpath);
347 strcat(pathreal,"/");
348 strcat(pathreal,dname);
349 if (sys_stat(pathreal,&sbuf) != 0)
351 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
355 mode = dos_mode(cnum,pathreal,&sbuf);
357 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
358 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
363 mdate = sbuf.st_mtime;
364 adate = sbuf.st_atime;
365 cdate = sbuf.st_ctime;
369 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
375 name_map_mangle(fname,False,SNUM(cnum));
380 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
385 if(requires_resume_key) {
389 put_dos_date2(p,l1_fdateCreation,cdate);
390 put_dos_date2(p,l1_fdateLastAccess,adate);
391 put_dos_date2(p,l1_fdateLastWrite,mdate);
392 SIVAL(p,l1_cbFile,size);
393 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
394 SSVAL(p,l1_attrFile,mode);
395 SCVAL(p,l1_cchName,strlen(fname));
396 strcpy(p + l1_achName, fname);
397 nameptr = p + l1_achName;
398 p += l1_achName + strlen(fname) + 1;
403 if(requires_resume_key) {
407 put_dos_date2(p,l2_fdateCreation,cdate);
408 put_dos_date2(p,l2_fdateLastAccess,adate);
409 put_dos_date2(p,l2_fdateLastWrite,mdate);
410 SIVAL(p,l2_cbFile,size);
411 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
412 SSVAL(p,l2_attrFile,mode);
413 SIVAL(p,l2_cbList,0); /* No extended attributes */
414 SCVAL(p,l2_cchName,strlen(fname));
415 strcpy(p + l2_achName, fname);
416 nameptr = p + l2_achName;
417 p += l2_achName + strlen(fname) + 1;
422 put_dos_date2(p,4,cdate);
423 put_dos_date2(p,8,adate);
424 put_dos_date2(p,12,mdate);
426 SIVAL(p,20,ROUNDUP(size,1024));
429 CVAL(p,30) = strlen(fname);
432 p += 31 + strlen(fname) + 1;
436 if(requires_resume_key) {
440 SIVAL(p,0,33+strlen(fname)+1);
441 put_dos_date2(p,4,cdate);
442 put_dos_date2(p,8,adate);
443 put_dos_date2(p,12,mdate);
445 SIVAL(p,20,ROUNDUP(size,1024));
447 CVAL(p,32) = strlen(fname);
448 strcpy(p + 33, fname);
450 p += 33 + strlen(fname) + 1;
453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
454 was_8_3 = is_8_3(fname, True);
455 len = 94+strlen(fname);
456 len = (len + 3) & ~3;
457 SIVAL(p,0,len); p += 4;
458 SIVAL(p,0,reskey); p += 4;
459 put_long_date(p,cdate); p += 8;
460 put_long_date(p,adate); p += 8;
461 put_long_date(p,mdate); p += 8;
462 put_long_date(p,mdate); p += 8;
463 SIVAL(p,0,size); p += 8;
464 SIVAL(p,0,size); p += 8;
465 SIVAL(p,0,nt_extmode); p += 4;
466 SIVAL(p,0,strlen(fname)); p += 4;
467 SIVAL(p,0,0); p += 4;
470 if (!name_map_mangle(p+2,True,SNUM(cnum)))
475 SSVAL(p,0,strlen(p+2));
478 strcpy(p,fname); p += strlen(p);
482 case SMB_FIND_FILE_DIRECTORY_INFO:
483 len = 64+strlen(fname);
484 len = (len + 3) & ~3;
485 SIVAL(p,0,len); p += 4;
486 SIVAL(p,0,reskey); p += 4;
487 put_long_date(p,cdate); p += 8;
488 put_long_date(p,adate); p += 8;
489 put_long_date(p,mdate); p += 8;
490 put_long_date(p,mdate); p += 8;
491 SIVAL(p,0,size); p += 8;
492 SIVAL(p,0,size); p += 8;
493 SIVAL(p,0,nt_extmode); p += 4;
494 SIVAL(p,0,strlen(fname)); p += 4;
500 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
501 len = 68+strlen(fname);
502 len = (len + 3) & ~3;
503 SIVAL(p,0,len); p += 4;
504 SIVAL(p,0,reskey); p += 4;
505 put_long_date(p,cdate); p += 8;
506 put_long_date(p,adate); p += 8;
507 put_long_date(p,mdate); p += 8;
508 put_long_date(p,mdate); p += 8;
509 SIVAL(p,0,size); p += 8;
510 SIVAL(p,0,size); p += 8;
511 SIVAL(p,0,nt_extmode); p += 4;
512 SIVAL(p,0,strlen(fname)); p += 4;
513 SIVAL(p,0,0); p += 4;
518 case SMB_FIND_FILE_NAMES_INFO:
519 len = 12+strlen(fname);
520 len = (len + 3) & ~3;
521 SIVAL(p,0,len); p += 4;
522 SIVAL(p,0,reskey); p += 4;
523 SIVAL(p,0,strlen(fname)); p += 4;
533 if (PTR_DIFF(p,pdata) > space_remaining) {
534 /* Move the dirptr back to prev_dirpos */
535 SeekDir(Connections[cnum].dirptr, prev_dirpos);
536 *out_of_space = True;
537 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
538 return False; /* Not finished - just out of space */
541 /* Setup the last_filename pointer, as an offset from base_data */
542 *last_name_off = PTR_DIFF(nameptr,base_data);
543 /* Advance the data pointer to the next slot */
548 /****************************************************************************
549 reply to a TRANS2_FINDFIRST
550 ****************************************************************************/
551 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
552 char **pparams, char **ppdata)
554 /* We must be careful here that we don't return more than the
555 allowed number of data bytes. If this means returning fewer than
556 maxentries then so be it. We assume that the redirector has
557 enough room for the fixed number of parameter bytes it has
559 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
560 char *params = *pparams;
561 char *pdata = *ppdata;
562 int dirtype = SVAL(params,0);
563 int maxentries = SVAL(params,2);
564 BOOL close_after_first = BITSETW(params+4,0);
565 BOOL close_if_end = BITSETW(params+4,1);
566 BOOL requires_resume_key = BITSETW(params+4,2);
567 int info_level = SVAL(params,6);
575 BOOL finished = False;
576 BOOL dont_descend = False;
577 BOOL out_of_space = False;
579 BOOL bad_path = False;
581 *directory = *mask = 0;
583 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",
584 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
585 info_level, max_data_bytes));
593 case SMB_FIND_FILE_DIRECTORY_INFO:
594 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
595 case SMB_FIND_FILE_NAMES_INFO:
596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
599 return(ERROR(ERRDOS,ERRunknownlevel));
602 pstrcpy(directory, params + 12); /* Complete directory path with
603 wildcard mask appended */
605 DEBUG(5,("path=%s\n",directory));
607 unix_convert(directory,cnum,0,&bad_path);
608 if(!check_name(directory,cnum)) {
609 if((errno == ENOENT) && bad_path)
611 unix_ERR_class = ERRDOS;
612 unix_ERR_code = ERRbadpath;
616 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
617 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
618 (get_remote_arch() == RA_WINNT))
620 unix_ERR_class = ERRDOS;
621 unix_ERR_code = ERRbaddirectory;
625 return(ERROR(ERRDOS,ERRbadpath));
628 p = strrchr(directory,'/');
630 strcpy(mask,directory);
631 strcpy(directory,"./");
637 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
639 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
641 return(ERROR(ERRDOS,ERRnomem));
642 bzero(pdata,max_data_bytes);
644 /* Realloc the params space */
645 params = *pparams = Realloc(*pparams, 10);
647 return(ERROR(ERRDOS,ERRnomem));
649 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
651 return(ERROR(ERRDOS,ERRbadfile));
653 /* convert the formatted masks */
657 if (*p == '<') *p = '*';
658 if (*p == '>') *p = '?';
659 if (*p == '"') *p = '.';
664 /* a special case for 16 bit apps */
665 if (strequal(mask,"????????.???")) strcpy(mask,"*");
667 /* handle broken clients that send us old 8.3 format */
668 string_sub(mask,"????????","*");
669 string_sub(mask,".???",".*");
671 /* Save the wildcard match and attribs we are using on this directory -
672 needed as lanman2 assumes these are being saved between calls */
674 if(!(wcard = strdup(mask))) {
675 dptr_close(dptr_num);
676 return(ERROR(ERRDOS,ERRnomem));
679 dptr_set_wcard(dptr_num, wcard);
680 dptr_set_attr(dptr_num, dirtype);
682 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
684 /* We don't need to check for VOL here as this is returned by
685 a different TRANS2 call. */
687 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
688 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
689 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
693 space_remaining = max_data_bytes;
694 out_of_space = False;
696 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
699 /* this is a heuristic to avoid seeking the dirptr except when
700 absolutely necessary. It allows for a filename of about 40 chars */
701 if (space_remaining < DIRLEN_GUESS && numentries > 0)
709 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
710 requires_resume_key,dont_descend,
711 &p,pdata,space_remaining, &out_of_space,
715 if (finished && out_of_space)
718 if (!finished && !out_of_space)
720 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
723 /* Check if we can close the dirptr */
724 if(close_after_first || (finished && close_if_end))
726 dptr_close(dptr_num);
727 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
732 * If there are no matching entries we must return ERRDOS/ERRbadfile -
733 * from observation of NT.
737 return(ERROR(ERRDOS,ERRbadfile));
739 /* At this point pdata points to numentries directory entries. */
741 /* Set up the return parameter block */
742 SSVAL(params,0,dptr_num);
743 SSVAL(params,2,numentries);
744 SSVAL(params,4,finished);
745 SSVAL(params,6,0); /* Never an EA error */
746 SSVAL(params,8,last_name_off);
748 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
750 if ((! *directory) && dptr_path(dptr_num))
751 sprintf(directory,"(%s)",dptr_path(dptr_num));
753 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
755 smb_fn_name(CVAL(inbuf,smb_com)),
756 mask,directory,cnum,dirtype,numentries));
762 /****************************************************************************
763 reply to a TRANS2_FINDNEXT
764 ****************************************************************************/
765 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
766 int cnum, char **pparams, char **ppdata)
768 /* We must be careful here that we don't return more than the
769 allowed number of data bytes. If this means returning fewer than
770 maxentries then so be it. We assume that the redirector has
771 enough room for the fixed number of parameter bytes it has
773 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
774 char *params = *pparams;
775 char *pdata = *ppdata;
776 int16 dptr_num = SVAL(params,0);
777 int maxentries = SVAL(params,2);
778 uint16 info_level = SVAL(params,4);
779 uint32 resume_key = IVAL(params,6);
780 BOOL close_after_request = BITSETW(params+10,0);
781 BOOL close_if_end = BITSETW(params+10,1);
782 BOOL requires_resume_key = BITSETW(params+10,2);
783 BOOL continue_bit = BITSETW(params+10,3);
789 int i, last_name_off=0;
790 BOOL finished = False;
791 BOOL dont_descend = False;
792 BOOL out_of_space = False;
795 *mask = *directory = 0;
797 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",
798 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
799 requires_resume_key, resume_key, continue_bit, info_level));
807 case SMB_FIND_FILE_DIRECTORY_INFO:
808 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
809 case SMB_FIND_FILE_NAMES_INFO:
810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
813 return(ERROR(ERRDOS,ERRunknownlevel));
816 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
818 return(ERROR(ERRDOS,ERRnomem));
819 bzero(pdata,max_data_bytes);
821 /* Realloc the params space */
822 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
824 return(ERROR(ERRDOS,ERRnomem));
826 /* Check that the dptr is valid */
827 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
828 return(ERROR(ERRDOS,ERRnofiles));
830 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
832 /* Get the wildcard mask from the dptr */
833 if((p = dptr_wcard(dptr_num))== NULL) {
834 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
835 return (ERROR(ERRDOS,ERRnofiles));
838 strcpy(directory,Connections[cnum].dirpath);
840 /* Get the attr mask from the dptr */
841 dirtype = dptr_attr(dptr_num);
843 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
844 dptr_num, mask, dirtype,
845 Connections[cnum].dirptr,
846 TellDir(Connections[cnum].dirptr)));
848 /* We don't need to check for VOL here as this is returned by
849 a different TRANS2 call. */
851 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
852 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
856 space_remaining = max_data_bytes;
857 out_of_space = False;
859 /* If we have a resume key - seek to the correct position. */
860 if(requires_resume_key && !continue_bit)
861 SeekDir(Connections[cnum].dirptr, resume_key);
863 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
865 /* this is a heuristic to avoid seeking the dirptr except when
866 absolutely necessary. It allows for a filename of about 40 chars */
867 if (space_remaining < DIRLEN_GUESS && numentries > 0)
875 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
876 requires_resume_key,dont_descend,
877 &p,pdata,space_remaining, &out_of_space,
881 if (finished && out_of_space)
884 if (!finished && !out_of_space)
886 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
889 /* Check if we can close the dirptr */
890 if(close_after_request || (finished && close_if_end))
892 dptr_close(dptr_num); /* This frees up the saved mask */
893 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
898 /* Set up the return parameter block */
899 SSVAL(params,0,numentries);
900 SSVAL(params,2,finished);
901 SSVAL(params,4,0); /* Never an EA error */
902 SSVAL(params,6,last_name_off);
904 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
906 if ((! *directory) && dptr_path(dptr_num))
907 sprintf(directory,"(%s)",dptr_path(dptr_num));
909 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
911 smb_fn_name(CVAL(inbuf,smb_com)),
912 mask,directory,cnum,dirtype,numentries));
917 /****************************************************************************
918 reply to a TRANS2_QFSINFO (query filesystem info)
919 ****************************************************************************/
920 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
921 int cnum, char **pparams, char **ppdata)
923 char *pdata = *ppdata;
924 char *params = *pparams;
925 uint16 info_level = SVAL(params,0);
928 char *vname = volume_label(SNUM(cnum));
930 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
932 if(sys_stat(".",&st)!=0) {
933 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
934 return (ERROR(ERRSRV,ERRinvdevice));
937 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
943 int dfree,dsize,bsize;
945 sys_disk_free(".",&bsize,&dfree,&dsize);
946 SIVAL(pdata,l1_idFileSystem,st.st_dev);
947 SIVAL(pdata,l1_cSectorUnit,bsize/512);
948 SIVAL(pdata,l1_cUnit,dsize);
949 SIVAL(pdata,l1_cUnitAvail,dfree);
950 SSVAL(pdata,l1_cbSector,512);
951 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
952 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
957 /* Return volume name */
958 int volname_len = MIN(strlen(vname),11);
959 data_len = l2_vol_szVolLabel + volname_len + 1;
960 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
961 SCVAL(pdata,l2_vol_cch,volname_len);
962 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
963 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
964 pdata+l2_vol_szVolLabel));
967 case SMB_QUERY_FS_ATTRIBUTE_INFO:
968 data_len = 12 + 2*strlen(FSTYPE_STRING);
969 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
970 SIVAL(pdata,4,128); /* Max filename component length */
971 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
972 PutUniCode(pdata+12,FSTYPE_STRING);
974 case SMB_QUERY_FS_LABEL_INFO:
975 data_len = 4 + strlen(vname);
976 SIVAL(pdata,0,strlen(vname));
977 strcpy(pdata+4,vname);
979 case SMB_QUERY_FS_VOLUME_INFO:
980 data_len = 18 + 2*strlen(vname);
981 SIVAL(pdata,12,2*strlen(vname));
982 PutUniCode(pdata+18,vname);
983 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
986 case SMB_QUERY_FS_SIZE_INFO:
988 int dfree,dsize,bsize;
990 sys_disk_free(".",&bsize,&dfree,&dsize);
991 SIVAL(pdata,0,dsize);
992 SIVAL(pdata,8,dfree);
993 SIVAL(pdata,16,bsize/512);
997 case SMB_QUERY_FS_DEVICE_INFO:
999 SIVAL(pdata,0,0); /* dev type */
1000 SIVAL(pdata,4,0); /* characteristics */
1003 return(ERROR(ERRDOS,ERRunknownlevel));
1007 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1009 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1014 /****************************************************************************
1015 reply to a TRANS2_SETFSINFO (set filesystem info)
1016 ****************************************************************************/
1017 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1018 int cnum, char **pparams, char **ppdata)
1020 /* Just say yes we did it - there is nothing that
1021 can be set here so it doesn't matter. */
1023 DEBUG(3,("call_trans2setfsinfo\n"));
1025 if (!CAN_WRITE(cnum))
1026 return(ERROR(ERRSRV,ERRaccess));
1028 outsize = set_message(outbuf,10,0,True);
1033 /****************************************************************************
1034 reply to a TRANS2_QFILEINFO (query file info by fileid)
1035 ****************************************************************************/
1036 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1037 int bufsize,int cnum,
1038 char **pparams,char **ppdata,
1041 char *params = *pparams;
1042 char *pdata = *ppdata;
1043 uint16 tran_call = SVAL(inbuf, smb_setup0);
1047 unsigned int data_size;
1053 BOOL bad_path = False;
1055 if (tran_call == TRANSACT2_QFILEINFO) {
1056 int16 fnum = SVALS(params,0);
1057 info_level = SVAL(params,2);
1059 CHECK_FNUM(fnum,cnum);
1062 fname = Files[fnum].name;
1063 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1064 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1065 return(UNIXERROR(ERRDOS,ERRbadfid));
1067 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1070 info_level = SVAL(params,0);
1072 pstrcpy(fname,¶ms[6]);
1073 unix_convert(fname,cnum,0,&bad_path);
1074 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1075 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1076 if((errno == ENOENT) && bad_path)
1078 unix_ERR_class = ERRDOS;
1079 unix_ERR_code = ERRbadpath;
1081 return(UNIXERROR(ERRDOS,ERRbadpath));
1087 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1088 fname,info_level,tran_call,total_data));
1090 p = strrchr(fname,'/');
1096 mode = dos_mode(cnum,fname,&sbuf);
1097 size = sbuf.st_size;
1098 if (mode & aDIR) size = 0;
1100 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1102 pdata = *ppdata = Realloc(*ppdata, data_size);
1104 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1105 /* uggh, EAs for OS2 */
1106 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1107 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1110 bzero(pdata,data_size);
1114 case SMB_INFO_STANDARD:
1115 case SMB_INFO_QUERY_EA_SIZE:
1116 data_size = (info_level==1?22:26);
1117 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1118 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1119 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1120 SIVAL(pdata,l1_cbFile,size);
1121 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1122 SSVAL(pdata,l1_attrFile,mode);
1123 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1126 case SMB_INFO_QUERY_EAS_FROM_LIST:
1128 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1129 put_dos_date2(pdata,4,sbuf.st_atime);
1130 put_dos_date2(pdata,8,sbuf.st_mtime);
1131 SIVAL(pdata,12,size);
1132 SIVAL(pdata,16,ROUNDUP(size,1024));
1133 SIVAL(pdata,20,mode);
1136 case SMB_INFO_QUERY_ALL_EAS:
1138 SIVAL(pdata,0,data_size);
1142 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1144 case SMB_QUERY_FILE_BASIC_INFO:
1145 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1146 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1147 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1148 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1149 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1150 SIVAL(pdata,32,mode);
1152 DEBUG(5,("SMB_QFBI - "));
1153 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1154 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1155 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1156 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1157 DEBUG(5,("mode: %x\n", mode));
1161 case SMB_QUERY_FILE_STANDARD_INFO:
1163 SIVAL(pdata,0,size);
1164 SIVAL(pdata,8,size);
1165 SIVAL(pdata,16,sbuf.st_nlink);
1167 CVAL(pdata,21) = (mode&aDIR)?1:0;
1170 case SMB_QUERY_FILE_EA_INFO:
1174 /* Get the 8.3 name - used if NT SMB was negotiated. */
1175 case SMB_QUERY_FILE_ALT_NAME_INFO:
1178 pstrcpy(short_name,fname);
1179 /* Mangle if not already 8.3 */
1180 if(!is_8_3(short_name, True))
1182 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1185 strncpy(pdata + 4,short_name,12);
1186 (pdata + 4)[12] = 0;
1187 strupper(pdata + 4);
1188 l = strlen(pdata + 4);
1194 case SMB_QUERY_FILE_NAME_INFO:
1197 pstrcpy(pdata+4,fname);
1200 case SMB_QUERY_FILE_ALLOCATION_INFO:
1201 case SMB_QUERY_FILE_END_OF_FILEINFO:
1203 SIVAL(pdata,0,size);
1206 case SMB_QUERY_FILE_ALL_INFO:
1207 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1208 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1209 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1210 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1211 SIVAL(pdata,32,mode);
1213 SIVAL(pdata,0,size);
1214 SIVAL(pdata,8,size);
1215 SIVAL(pdata,16,sbuf.st_nlink);
1217 CVAL(pdata,21) = (mode&aDIR)?1:0;
1219 pdata += 8; /* index number */
1220 pdata += 4; /* EA info */
1222 SIVAL(pdata,0,0xA9);
1224 SIVAL(pdata,0,0xd01BF);
1226 SIVAL(pdata,0,pos); /* current offset */
1228 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1230 pdata += 4; /* alignment */
1232 pstrcpy(pdata+4,fname);
1234 data_size = PTR_DIFF(pdata,(*ppdata));
1237 case SMB_QUERY_FILE_STREAM_INFO:
1240 SIVAL(pdata,4,size);
1241 SIVAL(pdata,12,size);
1243 pstrcpy(pdata+24,fname);
1246 return(ERROR(ERRDOS,ERRunknownlevel));
1249 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1254 /****************************************************************************
1255 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1256 ****************************************************************************/
1257 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1258 int bufsize, int cnum, char **pparams,
1259 char **ppdata, int total_data)
1261 char *params = *pparams;
1262 char *pdata = *ppdata;
1263 uint16 tran_call = SVAL(inbuf, smb_setup0);
1272 BOOL bad_path = False;
1274 if (!CAN_WRITE(cnum))
1275 return(ERROR(ERRSRV,ERRaccess));
1277 if (tran_call == TRANSACT2_SETFILEINFO) {
1278 int16 fnum = SVALS(params,0);
1279 info_level = SVAL(params,2);
1281 CHECK_FNUM(fnum,cnum);
1284 fname = Files[fnum].name;
1285 fd = Files[fnum].fd_ptr->fd;
1287 if(fstat(fd,&st)!=0) {
1288 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1289 return(ERROR(ERRDOS,ERRbadpath));
1293 info_level = SVAL(params,0);
1295 pstrcpy(fname,¶ms[6]);
1296 unix_convert(fname,cnum,0,&bad_path);
1297 if(!check_name(fname, cnum))
1299 if((errno == ENOENT) && bad_path)
1301 unix_ERR_class = ERRDOS;
1302 unix_ERR_code = ERRbadpath;
1304 return(UNIXERROR(ERRDOS,ERRbadpath));
1307 if(sys_stat(fname,&st)!=0) {
1308 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1309 if((errno == ENOENT) && bad_path)
1311 unix_ERR_class = ERRDOS;
1312 unix_ERR_code = ERRbadpath;
1314 return(UNIXERROR(ERRDOS,ERRbadpath));
1318 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1319 tran_call,fname,info_level,total_data));
1321 /* Realloc the parameter and data sizes */
1322 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1324 return(ERROR(ERRDOS,ERRnomem));
1327 tvs.modtime = st.st_mtime;
1328 tvs.actime = st.st_atime;
1329 mode = dos_mode(cnum,fname,&st);
1331 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1332 /* uggh, EAs for OS2 */
1333 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1334 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1339 case SMB_INFO_STANDARD:
1340 case SMB_INFO_QUERY_EA_SIZE:
1343 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1346 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1348 mode = SVAL(pdata,l1_attrFile);
1349 size = IVAL(pdata,l1_cbFile);
1353 /* XXXX um, i don't think this is right.
1354 it's also not in the cifs6.txt spec.
1356 case SMB_INFO_QUERY_EAS_FROM_LIST:
1357 tvs.actime = make_unix_date2(pdata+8);
1358 tvs.modtime = make_unix_date2(pdata+12);
1359 size = IVAL(pdata,16);
1360 mode = IVAL(pdata,24);
1363 /* XXXX nor this. not in cifs6.txt, either. */
1364 case SMB_INFO_QUERY_ALL_EAS:
1365 tvs.actime = make_unix_date2(pdata+8);
1366 tvs.modtime = make_unix_date2(pdata+12);
1367 size = IVAL(pdata,16);
1368 mode = IVAL(pdata,24);
1371 case SMB_SET_FILE_BASIC_INFO:
1373 /* Ignore create time at offset pdata. */
1376 tvs.actime = interpret_long_date(pdata+8);
1378 /* write time + changed time, combined. */
1379 tvs.modtime=MAX(interpret_long_date(pdata+16),
1380 interpret_long_date(pdata+24));
1382 #if 0 /* Needs more testing... */
1383 /* Test from Luke to prevent Win95 from
1384 setting incorrect values here.
1386 if (tvs.actime < tvs.modtime)
1387 return(ERROR(ERRDOS,ERRnoaccess));
1388 #endif /* Needs more testing... */
1391 mode = IVAL(pdata,32);
1395 case SMB_SET_FILE_END_OF_FILE_INFO:
1397 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1398 return(ERROR(ERRDOS,ERRunknownlevel));
1399 size = IVAL(pdata,0);
1403 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1404 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1407 return(ERROR(ERRDOS,ERRunknownlevel));
1411 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1412 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1413 DEBUG(6,("size: %x " , size));
1414 DEBUG(6,("mode: %x\n" , mode));
1416 /* get some defaults (no modifications) if any info is zero. */
1417 if (!tvs.actime) tvs.actime = st.st_atime;
1418 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1419 if (!size) size = st.st_size;
1421 /* Try and set the times, size and mode of this file -
1422 if they are different from the current values
1424 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1426 if(file_utime(cnum, fname, &tvs)!=0)
1428 return(ERROR(ERRDOS,ERRnoaccess));
1432 /* check the mode isn't different, before changing it */
1433 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1435 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1436 return(ERROR(ERRDOS,ERRnoaccess));
1439 if(size != st.st_size)
1443 fd = sys_open(fname,O_RDWR,0);
1446 return(ERROR(ERRDOS,ERRbadpath));
1448 set_filelen(fd, size);
1453 set_filelen(fd, size);
1459 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1464 /****************************************************************************
1465 reply to a TRANS2_MKDIR (make directory with extended attributes).
1466 ****************************************************************************/
1467 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1468 int cnum, char **pparams, char **ppdata)
1470 char *params = *pparams;
1473 BOOL bad_path = False;
1475 if (!CAN_WRITE(cnum))
1476 return(ERROR(ERRSRV,ERRaccess));
1478 pstrcpy(directory, ¶ms[4]);
1480 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1482 unix_convert(directory,cnum,0,&bad_path);
1483 if (check_name(directory,cnum))
1484 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1488 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1489 if((errno == ENOENT) && bad_path)
1491 unix_ERR_class = ERRDOS;
1492 unix_ERR_code = ERRbadpath;
1494 return(UNIXERROR(ERRDOS,ERRnoaccess));
1497 /* Realloc the parameter and data sizes */
1498 params = *pparams = Realloc(*pparams,2);
1500 return(ERROR(ERRDOS,ERRnomem));
1504 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1509 /****************************************************************************
1510 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1511 We don't actually do this - we just send a null response.
1512 ****************************************************************************/
1513 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1514 int cnum, char **pparams, char **ppdata)
1516 static uint16 fnf_handle = 257;
1517 char *params = *pparams;
1518 uint16 info_level = SVAL(params,4);
1520 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1528 return(ERROR(ERRDOS,ERRunknownlevel));
1531 /* Realloc the parameter and data sizes */
1532 params = *pparams = Realloc(*pparams,6);
1534 return(ERROR(ERRDOS,ERRnomem));
1536 SSVAL(params,0,fnf_handle);
1537 SSVAL(params,2,0); /* No changes */
1538 SSVAL(params,4,0); /* No EA errors */
1545 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1550 /****************************************************************************
1551 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1552 changes). Currently this does nothing.
1553 ****************************************************************************/
1554 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1555 int cnum, char **pparams, char **ppdata)
1557 char *params = *pparams;
1559 DEBUG(3,("call_trans2findnotifynext\n"));
1561 /* Realloc the parameter and data sizes */
1562 params = *pparams = Realloc(*pparams,4);
1564 return(ERROR(ERRDOS,ERRnomem));
1566 SSVAL(params,0,0); /* No changes */
1567 SSVAL(params,2,0); /* No EA errors */
1569 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1574 /****************************************************************************
1575 reply to a SMBfindclose (stop trans2 directory search)
1576 ****************************************************************************/
1577 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1581 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1583 cnum = SVAL(inbuf,smb_tid);
1585 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1587 dptr_close(dptr_num);
1589 outsize = set_message(outbuf,0,0,True);
1591 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1596 /****************************************************************************
1597 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1598 ****************************************************************************/
1599 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1605 cnum = SVAL(inbuf,smb_tid);
1606 dptr_num = SVAL(inbuf,smb_vwv0);
1608 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1610 /* We never give out valid handles for a
1611 findnotifyfirst - so any dptr_num is ok here.
1614 outsize = set_message(outbuf,0,0,True);
1616 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1622 /****************************************************************************
1623 reply to a SMBtranss2 - just ignore it!
1624 ****************************************************************************/
1625 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1627 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1631 /****************************************************************************
1632 reply to a SMBtrans2
1633 ****************************************************************************/
1634 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1637 int cnum = SVAL(inbuf,smb_tid);
1638 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1639 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1641 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1642 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1643 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1644 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1645 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1646 int32 timeout = IVALS(inbuf,smb_timeout);
1648 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1649 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1650 char *params = NULL, *data = NULL;
1651 int num_params, num_params_sofar, num_data, num_data_sofar;
1653 outsize = set_message(outbuf,0,0,True);
1655 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1656 is so as a sanity check */
1659 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1660 return(ERROR(ERRSRV,ERRerror));
1663 /* Allocate the space for the maximum needed parameters and data */
1664 if (total_params > 0)
1665 params = (char *)malloc(total_params);
1667 data = (char *)malloc(total_data);
1669 if ((total_params && !params) || (total_data && !data))
1671 DEBUG(2,("Out of memory in reply_trans2\n"));
1672 return(ERROR(ERRDOS,ERRnomem));
1675 /* Copy the param and data bytes sent with this request into
1676 the params buffer */
1677 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1678 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1680 if (num_params > total_params || num_data > total_data)
1681 exit_server("invalid params in reply_trans2");
1683 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1684 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1686 if(num_data_sofar < total_data || num_params_sofar < total_params)
1688 /* We need to send an interim response then receive the rest
1689 of the parameter/data bytes */
1690 outsize = set_message(outbuf,0,0,True);
1691 send_smb(Client,outbuf);
1693 while( num_data_sofar < total_data || num_params_sofar < total_params)
1697 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1698 SMB_SECONDARY_WAIT);
1700 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1702 outsize = set_message(outbuf,0,0,True);
1704 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1706 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1707 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1710 return(ERROR(ERRSRV,ERRerror));
1713 /* Revise total_params and total_data in case they have changed downwards */
1714 total_params = SVAL(inbuf, smb_tpscnt);
1715 total_data = SVAL(inbuf, smb_tdscnt);
1716 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1717 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1718 if (num_params_sofar > total_params || num_data_sofar > total_data)
1719 exit_server("data overflow in trans2");
1721 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1722 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1723 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1724 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1728 if (Protocol >= PROTOCOL_NT1) {
1729 uint16 flg2 = SVAL(outbuf,smb_flg2);
1730 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1733 /* Now we must call the relevant TRANS2 function */
1736 case TRANSACT2_OPEN:
1737 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1739 case TRANSACT2_FINDFIRST:
1740 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1742 case TRANSACT2_FINDNEXT:
1743 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1745 case TRANSACT2_QFSINFO:
1746 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1748 case TRANSACT2_SETFSINFO:
1749 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1751 case TRANSACT2_QPATHINFO:
1752 case TRANSACT2_QFILEINFO:
1753 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1755 case TRANSACT2_SETPATHINFO:
1756 case TRANSACT2_SETFILEINFO:
1757 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1759 case TRANSACT2_FINDNOTIFYFIRST:
1760 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1762 case TRANSACT2_FINDNOTIFYNEXT:
1763 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1765 case TRANSACT2_MKDIR:
1766 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1769 /* Error in request */
1770 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1775 return (ERROR(ERRSRV,ERRerror));
1778 /* As we do not know how many data packets will need to be
1779 returned here the various call_trans2xxxx calls
1780 must send their own. Thus a call_trans2xxx routine only
1781 returns a value other than -1 when it wants to send
1789 return outsize; /* If a correct response was needed the call_trans2xxx
1790 calls have already sent it. If outsize != -1 then it is
1791 returning an error packet. */