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;
35 extern fstring local_machine;
36 extern int global_oplock_break;
38 /****************************************************************************
39 Send the required number of replies back.
40 We assume all fields other than the data fields are
41 set correctly for the type of call.
42 HACK ! Always assumes smb_setup field is zero.
43 ****************************************************************************/
44 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
45 int paramsize, char *pdata, int datasize)
47 /* As we are using a protocol > LANMAN1 then the max_send
48 variable must have been set in the sessetupX call.
49 This takes precedence over the max_xmit field in the
50 global struct. These different max_xmit variables should
51 be merged as this is now too confusing */
54 int data_to_send = datasize;
55 int params_to_send = paramsize;
59 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
60 int alignment_offset = 3;
61 int data_alignment_offset = 0;
63 /* Initially set the wcnt area to be 10 - this is true for all
65 set_message(outbuf,10,0,True);
67 /* If there genuinely are no parameters or data to send just send
69 if(params_to_send == 0 && data_to_send == 0)
71 send_smb(Client,outbuf);
75 /* When sending params and data ensure that both are nicely aligned */
76 /* Only do this alignment when there is also data to send - else
77 can cause NT redirector problems. */
78 if (((params_to_send % 4) != 0) && (data_to_send != 0))
79 data_alignment_offset = 4 - (params_to_send % 4);
81 /* Space is bufsize minus Netbios over TCP header minus SMB header */
82 /* The alignment_offset is to align the param bytes on an even byte
83 boundary. NT 4.0 Beta needs this to work correctly. */
84 useable_space = bufsize - ((smb_buf(outbuf)+
85 alignment_offset+data_alignment_offset) -
88 /* useable_space can never be more than max_send minus the
90 useable_space = MIN(useable_space,
91 max_send - (alignment_offset+data_alignment_offset));
94 while (params_to_send || data_to_send)
96 /* Calculate whether we will totally or partially fill this packet */
97 total_sent_thistime = params_to_send + data_to_send +
98 alignment_offset + data_alignment_offset;
99 /* We can never send more than useable_space */
100 total_sent_thistime = MIN(total_sent_thistime, useable_space);
102 set_message(outbuf, 10, total_sent_thistime, True);
104 /* Set total params and data to be sent */
105 SSVAL(outbuf,smb_tprcnt,paramsize);
106 SSVAL(outbuf,smb_tdrcnt,datasize);
108 /* Calculate how many parameters and data we can fit into
109 this packet. Parameters get precedence */
111 params_sent_thistime = MIN(params_to_send,useable_space);
112 data_sent_thistime = useable_space - params_sent_thistime;
113 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
115 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
116 if(params_sent_thistime == 0)
118 SSVAL(outbuf,smb_proff,0);
119 SSVAL(outbuf,smb_prdisp,0);
123 /* smb_proff is the offset from the start of the SMB header to the
124 parameter bytes, however the first 4 bytes of outbuf are
125 the Netbios over TCP header. Thus use smb_base() to subtract
126 them from the calculation */
127 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
128 /* Absolute displacement of param bytes sent in this packet */
129 SSVAL(outbuf,smb_prdisp,pp - params);
132 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
133 if(data_sent_thistime == 0)
135 SSVAL(outbuf,smb_droff,0);
136 SSVAL(outbuf,smb_drdisp, 0);
140 /* The offset of the data bytes is the offset of the
141 parameter bytes plus the number of parameters being sent this time */
142 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
143 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
144 SSVAL(outbuf,smb_drdisp, pd - pdata);
147 /* Copy the param bytes into the packet */
148 if(params_sent_thistime)
149 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
150 /* Copy in the data bytes */
151 if(data_sent_thistime)
152 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
153 data_alignment_offset,pd,data_sent_thistime);
155 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
156 params_sent_thistime, data_sent_thistime, useable_space));
157 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
158 params_to_send, data_to_send, paramsize, datasize));
160 /* Send the packet */
161 send_smb(Client,outbuf);
163 pp += params_sent_thistime;
164 pd += data_sent_thistime;
166 params_to_send -= params_sent_thistime;
167 data_to_send -= data_sent_thistime;
170 if(params_to_send < 0 || data_to_send < 0)
172 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
173 params_to_send, data_to_send));
182 /****************************************************************************
183 reply to a TRANSACT2_OPEN
184 ****************************************************************************/
185 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
186 char **pparams, char **ppdata)
188 char *params = *pparams;
189 int16 open_mode = SVAL(params, 2);
190 int16 open_attr = SVAL(params,6);
191 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
193 BOOL return_additional_info = BITSETW(params,0);
194 int16 open_sattr = SVAL(params, 4);
195 time_t open_time = make_unix_date3(params+8);
197 int16 open_ofun = SVAL(params,12);
198 int32 open_size = IVAL(params,14);
199 char *pname = ¶ms[28];
200 int16 namelen = strlen(pname)+1;
205 int size=0,fmode=0,mtime=0,rmode;
209 BOOL bad_path = False;
212 StrnCpy(fname,pname,namelen);
214 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
215 fname,cnum,open_mode, open_attr, open_ofun, open_size));
217 /* XXXX we need to handle passed times, sattr and flags */
219 unix_convert(fname,cnum,0,&bad_path);
221 fnum = find_free_file();
223 return(ERROR(ERRSRV,ERRnofids));
227 if (!check_name(fname,cnum))
229 if((errno == ENOENT) && bad_path)
231 unix_ERR_class = ERRDOS;
232 unix_ERR_code = ERRbadpath;
234 fsp->reserved = False;
235 return(UNIXERROR(ERRDOS,ERRnoaccess));
238 unixmode = unix_mode(cnum,open_attr | aARCH);
240 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
241 oplock_request, &rmode,&smb_action);
245 if((errno == ENOENT) && bad_path)
247 unix_ERR_class = ERRDOS;
248 unix_ERR_code = ERRbadpath;
250 fsp->reserved = False;
251 return(UNIXERROR(ERRDOS,ERRnoaccess));
254 if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) {
255 close_file(fnum,False);
256 return(ERROR(ERRDOS,ERRnoaccess));
260 fmode = dos_mode(cnum,fname,&sbuf);
261 mtime = sbuf.st_mtime;
264 close_file(fnum,False);
265 return(ERROR(ERRDOS,ERRnoaccess));
268 /* Realloc the size of parameters and data we will return */
269 params = *pparams = Realloc(*pparams, 28);
271 return(ERROR(ERRDOS,ERRnomem));
274 SSVAL(params,0,fnum);
275 SSVAL(params,2,fmode);
276 put_dos_date2(params,4, mtime);
277 SIVAL(params,8, size);
278 SSVAL(params,12,rmode);
280 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
281 smb_action |= EXTENDED_OPLOCK_GRANTED;
284 SSVAL(params,18,smb_action);
285 SIVAL(params,20,inode);
287 /* Send the required number of replies */
288 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
293 /****************************************************************************
294 get a level dependent lanman2 dir entry.
295 ****************************************************************************/
296 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
297 int requires_resume_key,
298 BOOL dont_descend,char **ppdata,
299 char *base_data, int space_remaining,
310 char *p, *pdata = *ppdata;
315 uint32 mdate=0, adate=0, cdate=0;
317 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
318 strequal(Connections[cnum].dirpath,".") ||
319 strequal(Connections[cnum].dirpath,"/"));
321 int nt_extmode; /* Used for NT connections instead of mode */
322 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
325 *out_of_space = False;
327 if (!Connections[cnum].dirptr)
330 p = strrchr(path_mask,'/');
339 pstrcpy(mask, path_mask);
343 /* Needed if we run out of space */
344 prev_dirpos = TellDir(Connections[cnum].dirptr);
345 dname = ReadDirName(Connections[cnum].dirptr);
348 * Due to bugs in NT client redirectors we are not using
349 * resume keys any more - set them to zero.
350 * Check out the related comments in findfirst/findnext.
356 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
357 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
364 pstrcpy(fname,dname);
366 if(mask_match(fname, mask, case_sensitive, True))
368 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
369 if (dont_descend && !isdots)
372 if (isrootdir && isdots)
375 pstrcpy(pathreal,Connections[cnum].dirpath);
377 pstrcat(pathreal,"/");
378 pstrcat(pathreal,dname);
379 if (sys_stat(pathreal,&sbuf) != 0)
381 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
385 mode = dos_mode(cnum,pathreal,&sbuf);
387 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
388 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
393 mdate = sbuf.st_mtime;
394 adate = sbuf.st_atime;
395 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)));
399 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
405 name_map_mangle(fname,False,SNUM(cnum));
410 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
415 if(requires_resume_key) {
419 put_dos_date2(p,l1_fdateCreation,cdate);
420 put_dos_date2(p,l1_fdateLastAccess,adate);
421 put_dos_date2(p,l1_fdateLastWrite,mdate);
422 SIVAL(p,l1_cbFile,size);
423 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
424 SSVAL(p,l1_attrFile,mode);
425 SCVAL(p,l1_cchName,strlen(fname));
426 pstrcpy(p + l1_achName, fname);
427 nameptr = p + l1_achName;
428 p += l1_achName + strlen(fname) + 1;
433 if(requires_resume_key) {
437 put_dos_date2(p,l2_fdateCreation,cdate);
438 put_dos_date2(p,l2_fdateLastAccess,adate);
439 put_dos_date2(p,l2_fdateLastWrite,mdate);
440 SIVAL(p,l2_cbFile,size);
441 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
442 SSVAL(p,l2_attrFile,mode);
443 SIVAL(p,l2_cbList,0); /* No extended attributes */
444 SCVAL(p,l2_cchName,strlen(fname));
445 pstrcpy(p + l2_achName, fname);
446 nameptr = p + l2_achName;
447 p += l2_achName + strlen(fname) + 1;
452 put_dos_date2(p,4,cdate);
453 put_dos_date2(p,8,adate);
454 put_dos_date2(p,12,mdate);
456 SIVAL(p,20,ROUNDUP(size,1024));
459 CVAL(p,30) = strlen(fname);
460 pstrcpy(p+31, fname);
462 p += 31 + strlen(fname) + 1;
466 if(requires_resume_key) {
470 SIVAL(p,0,33+strlen(fname)+1);
471 put_dos_date2(p,4,cdate);
472 put_dos_date2(p,8,adate);
473 put_dos_date2(p,12,mdate);
475 SIVAL(p,20,ROUNDUP(size,1024));
477 CVAL(p,32) = strlen(fname);
478 pstrcpy(p + 33, fname);
480 p += 33 + strlen(fname) + 1;
483 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
484 was_8_3 = is_8_3(fname, True);
485 len = 94+strlen(fname);
486 len = (len + 3) & ~3;
487 SIVAL(p,0,len); p += 4;
488 SIVAL(p,0,reskey); p += 4;
489 put_long_date(p,cdate); p += 8;
490 put_long_date(p,adate); p += 8;
491 put_long_date(p,mdate); p += 8;
492 put_long_date(p,mdate); p += 8;
493 SIVAL(p,0,size); p += 8;
494 SIVAL(p,0,size); p += 8;
495 SIVAL(p,0,nt_extmode); p += 4;
496 SIVAL(p,0,strlen(fname)); p += 4;
497 SIVAL(p,0,0); p += 4;
500 if (!name_map_mangle(p+2,True,SNUM(cnum)))
505 SSVAL(p,0,strlen(p+2));
508 pstrcpy(p,fname); p += strlen(p);
512 case SMB_FIND_FILE_DIRECTORY_INFO:
513 len = 64+strlen(fname);
514 len = (len + 3) & ~3;
515 SIVAL(p,0,len); p += 4;
516 SIVAL(p,0,reskey); p += 4;
517 put_long_date(p,cdate); p += 8;
518 put_long_date(p,adate); p += 8;
519 put_long_date(p,mdate); p += 8;
520 put_long_date(p,mdate); p += 8;
521 SIVAL(p,0,size); p += 8;
522 SIVAL(p,0,size); p += 8;
523 SIVAL(p,0,nt_extmode); p += 4;
524 SIVAL(p,0,strlen(fname)); p += 4;
530 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
531 len = 68+strlen(fname);
532 len = (len + 3) & ~3;
533 SIVAL(p,0,len); p += 4;
534 SIVAL(p,0,reskey); p += 4;
535 put_long_date(p,cdate); p += 8;
536 put_long_date(p,adate); p += 8;
537 put_long_date(p,mdate); p += 8;
538 put_long_date(p,mdate); p += 8;
539 SIVAL(p,0,size); p += 8;
540 SIVAL(p,0,size); p += 8;
541 SIVAL(p,0,nt_extmode); p += 4;
542 SIVAL(p,0,strlen(fname)); p += 4;
543 SIVAL(p,0,0); p += 4;
548 case SMB_FIND_FILE_NAMES_INFO:
549 len = 12+strlen(fname);
550 len = (len + 3) & ~3;
551 SIVAL(p,0,len); p += 4;
552 SIVAL(p,0,reskey); p += 4;
553 SIVAL(p,0,strlen(fname)); p += 4;
563 if (PTR_DIFF(p,pdata) > space_remaining) {
564 /* Move the dirptr back to prev_dirpos */
565 SeekDir(Connections[cnum].dirptr, prev_dirpos);
566 *out_of_space = True;
567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
568 return False; /* Not finished - just out of space */
571 /* Setup the last_filename pointer, as an offset from base_data */
572 *last_name_off = PTR_DIFF(nameptr,base_data);
573 /* Advance the data pointer to the next slot */
578 /****************************************************************************
579 Convert the directory masks formated for the wire.
580 ****************************************************************************/
582 void mask_convert( char *mask)
585 * We know mask is a pstring.
591 if(p[1] != '"' && p[1] != '.') {
592 pstrcpy( expnd, p+1 );
595 safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
599 if (*p == '>') *p = '?';
600 if (*p == '"') *p = '.';
605 /****************************************************************************
606 reply to a TRANS2_FINDFIRST
607 ****************************************************************************/
608 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
609 char **pparams, char **ppdata)
611 /* We must be careful here that we don't return more than the
612 allowed number of data bytes. If this means returning fewer than
613 maxentries then so be it. We assume that the redirector has
614 enough room for the fixed number of parameter bytes it has
616 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
617 char *params = *pparams;
618 char *pdata = *ppdata;
619 int dirtype = SVAL(params,0);
620 int maxentries = SVAL(params,2);
621 BOOL close_after_first = BITSETW(params+4,0);
622 BOOL close_if_end = BITSETW(params+4,1);
623 BOOL requires_resume_key = BITSETW(params+4,2);
624 int info_level = SVAL(params,6);
632 BOOL finished = False;
633 BOOL dont_descend = False;
634 BOOL out_of_space = False;
636 BOOL bad_path = False;
638 *directory = *mask = 0;
640 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",
641 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
642 info_level, max_data_bytes));
650 case SMB_FIND_FILE_DIRECTORY_INFO:
651 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
652 case SMB_FIND_FILE_NAMES_INFO:
653 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
656 return(ERROR(ERRDOS,ERRunknownlevel));
659 pstrcpy(directory, params + 12); /* Complete directory path with
660 wildcard mask appended */
662 DEBUG(5,("path=%s\n",directory));
664 unix_convert(directory,cnum,0,&bad_path);
665 if(!check_name(directory,cnum)) {
666 if((errno == ENOENT) && bad_path)
668 unix_ERR_class = ERRDOS;
669 unix_ERR_code = ERRbadpath;
673 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
674 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
675 (get_remote_arch() == RA_WINNT))
677 unix_ERR_class = ERRDOS;
678 unix_ERR_code = ERRbaddirectory;
682 return(ERROR(ERRDOS,ERRbadpath));
685 p = strrchr(directory,'/');
687 pstrcpy(mask,directory);
688 pstrcpy(directory,"./");
694 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
696 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
698 return(ERROR(ERRDOS,ERRnomem));
699 bzero(pdata,max_data_bytes);
701 /* Realloc the params space */
702 params = *pparams = Realloc(*pparams, 10);
704 return(ERROR(ERRDOS,ERRnomem));
706 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
708 return(ERROR(ERRDOS,ERRbadfile));
710 /* Convert the formatted mask. */
715 * Now we have a working mask_match in util.c, I believe
716 * we no longer need these hacks (in fact they break
720 /* a special case for 16 bit apps */
721 if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
723 /* handle broken clients that send us old 8.3 format */
724 string_sub(mask,"????????","*");
725 string_sub(mask,".???",".*");
728 /* Save the wildcard match and attribs we are using on this directory -
729 needed as lanman2 assumes these are being saved between calls */
731 if(!(wcard = strdup(mask))) {
732 dptr_close(dptr_num);
733 return(ERROR(ERRDOS,ERRnomem));
736 dptr_set_wcard(dptr_num, wcard);
737 dptr_set_attr(dptr_num, dirtype);
739 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
741 /* We don't need to check for VOL here as this is returned by
742 a different TRANS2 call. */
744 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
745 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
746 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
750 space_remaining = max_data_bytes;
751 out_of_space = False;
753 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
756 /* this is a heuristic to avoid seeking the dirptr except when
757 absolutely necessary. It allows for a filename of about 40 chars */
758 if (space_remaining < DIRLEN_GUESS && numentries > 0)
766 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
767 requires_resume_key,dont_descend,
768 &p,pdata,space_remaining, &out_of_space,
772 if (finished && out_of_space)
775 if (!finished && !out_of_space)
777 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
780 /* Check if we can close the dirptr */
781 if(close_after_first || (finished && close_if_end))
783 dptr_close(dptr_num);
784 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
789 * If there are no matching entries we must return ERRDOS/ERRbadfile -
790 * from observation of NT.
794 return(ERROR(ERRDOS,ERRbadfile));
796 /* At this point pdata points to numentries directory entries. */
798 /* Set up the return parameter block */
799 SSVAL(params,0,dptr_num);
800 SSVAL(params,2,numentries);
801 SSVAL(params,4,finished);
802 SSVAL(params,6,0); /* Never an EA error */
803 SSVAL(params,8,last_name_off);
805 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
807 if ((! *directory) && dptr_path(dptr_num))
808 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
810 DEBUG( 4, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
811 smb_fn_name(CVAL(inbuf,smb_com)),
812 mask, directory, cnum, dirtype, numentries ) );
818 /****************************************************************************
819 reply to a TRANS2_FINDNEXT
820 ****************************************************************************/
821 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
822 int cnum, char **pparams, char **ppdata)
824 /* We must be careful here that we don't return more than the
825 allowed number of data bytes. If this means returning fewer than
826 maxentries then so be it. We assume that the redirector has
827 enough room for the fixed number of parameter bytes it has
829 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
830 char *params = *pparams;
831 char *pdata = *ppdata;
832 int16 dptr_num = SVAL(params,0);
833 int maxentries = SVAL(params,2);
834 uint16 info_level = SVAL(params,4);
835 uint32 resume_key = IVAL(params,6);
836 BOOL close_after_request = BITSETW(params+10,0);
837 BOOL close_if_end = BITSETW(params+10,1);
838 BOOL requires_resume_key = BITSETW(params+10,2);
839 BOOL continue_bit = BITSETW(params+10,3);
846 int i, last_name_off=0;
847 BOOL finished = False;
848 BOOL dont_descend = False;
849 BOOL out_of_space = False;
852 *mask = *directory = *resume_name = 0;
854 pstrcpy( resume_name, params+12);
856 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
857 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
858 resume_key = %d resume name = %s continue=%d level = %d\n",
859 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
860 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
868 case SMB_FIND_FILE_DIRECTORY_INFO:
869 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
870 case SMB_FIND_FILE_NAMES_INFO:
871 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
874 return(ERROR(ERRDOS,ERRunknownlevel));
877 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
879 return(ERROR(ERRDOS,ERRnomem));
880 bzero(pdata,max_data_bytes);
882 /* Realloc the params space */
883 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
885 return(ERROR(ERRDOS,ERRnomem));
887 /* Check that the dptr is valid */
888 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(dptr_num)))
889 return(ERROR(ERRDOS,ERRnofiles));
891 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
893 /* Get the wildcard mask from the dptr */
894 if((p = dptr_wcard(dptr_num))== NULL) {
895 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
896 return (ERROR(ERRDOS,ERRnofiles));
899 pstrcpy(directory,Connections[cnum].dirpath);
901 /* Get the attr mask from the dptr */
902 dirtype = dptr_attr(dptr_num);
904 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
905 dptr_num, mask, dirtype,
906 Connections[cnum].dirptr,
907 TellDir(Connections[cnum].dirptr)));
909 /* We don't need to check for VOL here as this is returned by
910 a different TRANS2 call. */
912 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
913 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
917 space_remaining = max_data_bytes;
918 out_of_space = False;
921 * Seek to the correct position. We no longer use the resume key but
922 * depend on the last file name instead.
924 if(requires_resume_key && *resume_name && !continue_bit)
927 * Fix for NT redirector problem triggered by resume key indexes
928 * changing between directory scans. We now return a resume key of 0
929 * and instead look for the filename to continue from (also given
930 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
931 * findfirst/findnext (as is usual) then the directory pointer
932 * should already be at the correct place. Check this by scanning
933 * backwards looking for an exact (ie. case sensitive) filename match.
934 * If we get to the beginning of the directory and haven't found it then scan
935 * forwards again looking for a match. JRA.
938 int current_pos, start_pos;
940 void *dirptr = Connections[cnum].dirptr;
941 start_pos = TellDir(dirptr);
942 for(current_pos = start_pos; current_pos >= 0; current_pos--)
944 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
946 SeekDir(dirptr, current_pos);
947 dname = ReadDirName(dirptr);
950 * Remember, name_map_mangle is called by
951 * get_lanman2_dir_entry(), so the resume name
952 * could be mangled. Ensure we do the same
956 name_map_mangle( dname, False, SNUM(cnum));
958 if(dname && strcsequal( resume_name, dname))
960 SeekDir(dirptr, current_pos+1);
961 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
967 * Scan forward from start if not found going backwards.
972 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
973 SeekDir(dirptr, start_pos);
974 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
977 * Remember, name_map_mangle is called by
978 * get_lanman2_dir_entry(), so the resume name
979 * could be mangled. Ensure we do the same
983 name_map_mangle( dname, False, SNUM(cnum));
985 if(strcsequal( resume_name, dname))
987 SeekDir(dirptr, current_pos+1);
988 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
992 } /* end if current_pos */
993 } /* end if requires_resume_key && !continue_bit */
995 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
997 /* this is a heuristic to avoid seeking the dirptr except when
998 absolutely necessary. It allows for a filename of about 40 chars */
999 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1001 out_of_space = True;
1007 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
1008 requires_resume_key,dont_descend,
1009 &p,pdata,space_remaining, &out_of_space,
1013 if (finished && out_of_space)
1016 if (!finished && !out_of_space)
1018 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1021 /* Check if we can close the dirptr */
1022 if(close_after_request || (finished && close_if_end))
1024 dptr_close(dptr_num); /* This frees up the saved mask */
1025 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1030 /* Set up the return parameter block */
1031 SSVAL(params,0,numentries);
1032 SSVAL(params,2,finished);
1033 SSVAL(params,4,0); /* Never an EA error */
1034 SSVAL(params,6,last_name_off);
1036 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1038 if ((! *directory) && dptr_path(dptr_num))
1039 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1041 DEBUG( 3, ( "%s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
1042 smb_fn_name(CVAL(inbuf,smb_com)),
1043 mask, directory, cnum, dirtype, numentries ) );
1048 /****************************************************************************
1049 reply to a TRANS2_QFSINFO (query filesystem info)
1050 ****************************************************************************/
1051 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1052 int cnum, char **pparams, char **ppdata)
1054 char *pdata = *ppdata;
1055 char *params = *pparams;
1056 uint16 info_level = SVAL(params,0);
1059 char *vname = volume_label(SNUM(cnum));
1060 int snum = SNUM(cnum);
1062 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
1064 if(sys_stat(".",&st)!=0) {
1065 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1066 return (ERROR(ERRSRV,ERRinvdevice));
1069 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1075 int dfree,dsize,bsize;
1077 sys_disk_free(".",&bsize,&dfree,&dsize);
1078 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1079 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1080 SIVAL(pdata,l1_cUnit,dsize);
1081 SIVAL(pdata,l1_cUnitAvail,dfree);
1082 SSVAL(pdata,l1_cbSector,512);
1083 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1084 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
1089 /* Return volume name */
1090 int volname_len = MIN(strlen(vname),11);
1091 data_len = l2_vol_szVolLabel + volname_len + 1;
1093 * Add volume serial number - hash of a combination of
1094 * the called hostname and the service name.
1096 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1097 SCVAL(pdata,l2_vol_cch,volname_len);
1098 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1099 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
1100 pdata+l2_vol_szVolLabel));
1103 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1104 data_len = 12 + 2*strlen(FSTYPE_STRING);
1105 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1106 #if 0 /* Old code. JRA. */
1107 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1108 #endif /* Old code. */
1109 SIVAL(pdata,4,128); /* Max filename component length */
1110 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1111 PutUniCode(pdata+12,FSTYPE_STRING);
1113 case SMB_QUERY_FS_LABEL_INFO:
1114 data_len = 4 + strlen(vname);
1115 SIVAL(pdata,0,strlen(vname));
1116 pstrcpy(pdata+4,vname);
1118 case SMB_QUERY_FS_VOLUME_INFO:
1119 data_len = 18 + 2*strlen(vname);
1121 * Add volume serial number - hash of a combination of
1122 * the called hostname and the service name.
1124 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1125 SIVAL(pdata,12,2*strlen(vname));
1126 PutUniCode(pdata+18,vname);
1127 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1130 case SMB_QUERY_FS_SIZE_INFO:
1132 int dfree,dsize,bsize;
1134 sys_disk_free(".",&bsize,&dfree,&dsize);
1135 SIVAL(pdata,0,dsize);
1136 SIVAL(pdata,8,dfree);
1137 SIVAL(pdata,16,bsize/512);
1138 SIVAL(pdata,20,512);
1141 case SMB_QUERY_FS_DEVICE_INFO:
1143 SIVAL(pdata,0,0); /* dev type */
1144 SIVAL(pdata,4,0); /* characteristics */
1147 return(ERROR(ERRDOS,ERRunknownlevel));
1151 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1153 DEBUG( 4, ( "%s info_level = %d\n",
1154 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1159 /****************************************************************************
1160 reply to a TRANS2_SETFSINFO (set filesystem info)
1161 ****************************************************************************/
1162 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1163 int cnum, char **pparams, char **ppdata)
1165 /* Just say yes we did it - there is nothing that
1166 can be set here so it doesn't matter. */
1168 DEBUG(3,("call_trans2setfsinfo\n"));
1170 if (!CAN_WRITE(cnum))
1171 return(ERROR(ERRSRV,ERRaccess));
1173 outsize = set_message(outbuf,10,0,True);
1178 /****************************************************************************
1179 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1180 file name or file id).
1181 ****************************************************************************/
1183 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1184 int bufsize,int cnum,
1185 char **pparams,char **ppdata,
1188 char *params = *pparams;
1189 char *pdata = *ppdata;
1190 uint16 tran_call = SVAL(inbuf, smb_setup0);
1194 unsigned int data_size;
1200 BOOL bad_path = False;
1202 if (tran_call == TRANSACT2_QFILEINFO) {
1203 int16 fnum = SVALS(params,0);
1204 info_level = SVAL(params,2);
1206 CHECK_FNUM(fnum,cnum);
1209 fname = Files[fnum].name;
1210 if (fstat(Files[fnum].f_u.fd_ptr->fd,&sbuf) != 0) {
1211 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1212 return(UNIXERROR(ERRDOS,ERRbadfid));
1214 pos = lseek(Files[fnum].f_u.fd_ptr->fd,0,SEEK_CUR);
1217 info_level = SVAL(params,0);
1219 pstrcpy(fname,¶ms[6]);
1220 unix_convert(fname,cnum,0,&bad_path);
1221 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1222 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1223 if((errno == ENOENT) && bad_path)
1225 unix_ERR_class = ERRDOS;
1226 unix_ERR_code = ERRbadpath;
1228 return(UNIXERROR(ERRDOS,ERRbadpath));
1234 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1235 fname,info_level,tran_call,total_data));
1237 p = strrchr(fname,'/');
1243 mode = dos_mode(cnum,fname,&sbuf);
1244 size = sbuf.st_size;
1245 if (mode & aDIR) size = 0;
1247 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1249 pdata = *ppdata = Realloc(*ppdata, data_size);
1251 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1252 /* uggh, EAs for OS2 */
1253 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1254 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1257 bzero(pdata,data_size);
1261 case SMB_INFO_STANDARD:
1262 case SMB_INFO_QUERY_EA_SIZE:
1263 data_size = (info_level==1?22:26);
1264 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1265 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1266 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1267 SIVAL(pdata,l1_cbFile,size);
1268 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1269 SSVAL(pdata,l1_attrFile,mode);
1270 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1273 case SMB_INFO_QUERY_EAS_FROM_LIST:
1275 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1276 put_dos_date2(pdata,4,sbuf.st_atime);
1277 put_dos_date2(pdata,8,sbuf.st_mtime);
1278 SIVAL(pdata,12,size);
1279 SIVAL(pdata,16,ROUNDUP(size,1024));
1280 SIVAL(pdata,20,mode);
1283 case SMB_INFO_QUERY_ALL_EAS:
1285 SIVAL(pdata,0,data_size);
1289 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1291 case SMB_QUERY_FILE_BASIC_INFO:
1292 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1293 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1294 put_long_date(pdata+8,sbuf.st_atime);
1295 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1296 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1297 SIVAL(pdata,32,mode);
1299 DEBUG(5,("SMB_QFBI - "));
1301 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)));
1302 DEBUG(5,("create: %s ", ctime(&create_time)));
1304 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1305 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1306 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1307 DEBUG(5,("mode: %x\n", mode));
1311 case SMB_QUERY_FILE_STANDARD_INFO:
1313 SIVAL(pdata,0,size);
1314 SIVAL(pdata,8,size);
1315 SIVAL(pdata,16,sbuf.st_nlink);
1317 CVAL(pdata,21) = (mode&aDIR)?1:0;
1320 case SMB_QUERY_FILE_EA_INFO:
1324 /* Get the 8.3 name - used if NT SMB was negotiated. */
1325 case SMB_QUERY_FILE_ALT_NAME_INFO:
1328 pstrcpy(short_name,p);
1329 /* Mangle if not already 8.3 */
1330 if(!is_8_3(short_name, True))
1332 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1335 strupper(short_name);
1336 l = strlen(short_name);
1337 PutUniCode(pdata + 4, short_name);
1338 data_size = 4 + (2*l);
1343 case SMB_QUERY_FILE_NAME_INFO:
1346 pstrcpy(pdata+4,fname);
1349 case SMB_QUERY_FILE_ALLOCATION_INFO:
1350 case SMB_QUERY_FILE_END_OF_FILEINFO:
1352 SIVAL(pdata,0,size);
1355 case SMB_QUERY_FILE_ALL_INFO:
1356 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1357 put_long_date(pdata+8,sbuf.st_atime);
1358 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1359 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1360 SIVAL(pdata,32,mode);
1362 SIVAL(pdata,0,size);
1363 SIVAL(pdata,8,size);
1364 SIVAL(pdata,16,sbuf.st_nlink);
1366 CVAL(pdata,21) = (mode&aDIR)?1:0;
1368 pdata += 8; /* index number */
1369 pdata += 4; /* EA info */
1371 SIVAL(pdata,0,0xA9);
1373 SIVAL(pdata,0,0xd01BF);
1375 SIVAL(pdata,0,pos); /* current offset */
1377 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1379 pdata += 4; /* alignment */
1381 pstrcpy(pdata+4,fname);
1383 data_size = PTR_DIFF(pdata,(*ppdata));
1386 case SMB_QUERY_FILE_STREAM_INFO:
1389 SIVAL(pdata,4,size);
1390 SIVAL(pdata,12,size);
1392 pstrcpy(pdata+24,fname);
1395 return(ERROR(ERRDOS,ERRunknownlevel));
1398 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1403 /****************************************************************************
1404 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1405 ****************************************************************************/
1406 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1407 int bufsize, int cnum, char **pparams,
1408 char **ppdata, int total_data)
1410 char *params = *pparams;
1411 char *pdata = *ppdata;
1412 uint16 tran_call = SVAL(inbuf, smb_setup0);
1421 BOOL bad_path = False;
1423 if (!CAN_WRITE(cnum))
1424 return(ERROR(ERRSRV,ERRaccess));
1426 if (tran_call == TRANSACT2_SETFILEINFO) {
1427 int16 fnum = SVALS(params,0);
1428 info_level = SVAL(params,2);
1430 CHECK_FNUM(fnum,cnum);
1433 fname = Files[fnum].name;
1434 fd = Files[fnum].f_u.fd_ptr->fd;
1436 if(fstat(fd,&st)!=0) {
1437 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1438 return(ERROR(ERRDOS,ERRbadpath));
1442 info_level = SVAL(params,0);
1444 pstrcpy(fname,¶ms[6]);
1445 unix_convert(fname,cnum,0,&bad_path);
1446 if(!check_name(fname, cnum))
1448 if((errno == ENOENT) && bad_path)
1450 unix_ERR_class = ERRDOS;
1451 unix_ERR_code = ERRbadpath;
1453 return(UNIXERROR(ERRDOS,ERRbadpath));
1456 if(sys_stat(fname,&st)!=0) {
1457 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1458 if((errno == ENOENT) && bad_path)
1460 unix_ERR_class = ERRDOS;
1461 unix_ERR_code = ERRbadpath;
1463 return(UNIXERROR(ERRDOS,ERRbadpath));
1467 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1468 tran_call,fname,info_level,total_data));
1470 /* Realloc the parameter and data sizes */
1471 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1473 return(ERROR(ERRDOS,ERRnomem));
1476 tvs.modtime = st.st_mtime;
1477 tvs.actime = st.st_atime;
1478 mode = dos_mode(cnum,fname,&st);
1480 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1481 /* uggh, EAs for OS2 */
1482 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1483 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1488 case SMB_INFO_STANDARD:
1489 case SMB_INFO_QUERY_EA_SIZE:
1492 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1495 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1497 mode = SVAL(pdata,l1_attrFile);
1498 size = IVAL(pdata,l1_cbFile);
1502 /* XXXX um, i don't think this is right.
1503 it's also not in the cifs6.txt spec.
1505 case SMB_INFO_QUERY_EAS_FROM_LIST:
1506 tvs.actime = make_unix_date2(pdata+8);
1507 tvs.modtime = make_unix_date2(pdata+12);
1508 size = IVAL(pdata,16);
1509 mode = IVAL(pdata,24);
1512 /* XXXX nor this. not in cifs6.txt, either. */
1513 case SMB_INFO_QUERY_ALL_EAS:
1514 tvs.actime = make_unix_date2(pdata+8);
1515 tvs.modtime = make_unix_date2(pdata+12);
1516 size = IVAL(pdata,16);
1517 mode = IVAL(pdata,24);
1520 case SMB_SET_FILE_BASIC_INFO:
1522 /* Ignore create time at offset pdata. */
1525 tvs.actime = interpret_long_date(pdata+8);
1527 /* write time + changed time, combined. */
1528 tvs.modtime=MAX(interpret_long_date(pdata+16),
1529 interpret_long_date(pdata+24));
1531 #if 0 /* Needs more testing... */
1532 /* Test from Luke to prevent Win95 from
1533 setting incorrect values here.
1535 if (tvs.actime < tvs.modtime)
1536 return(ERROR(ERRDOS,ERRnoaccess));
1537 #endif /* Needs more testing... */
1540 mode = IVAL(pdata,32);
1544 case SMB_SET_FILE_END_OF_FILE_INFO:
1546 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1547 return(ERROR(ERRDOS,ERRunknownlevel));
1548 size = IVAL(pdata,0);
1552 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1553 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1556 return(ERROR(ERRDOS,ERRunknownlevel));
1560 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1561 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1562 DEBUG(6,("size: %x " , size));
1563 DEBUG(6,("mode: %x\n" , mode));
1565 /* get some defaults (no modifications) if any info is zero. */
1566 if (!tvs.actime) tvs.actime = st.st_atime;
1567 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1568 if (!size) size = st.st_size;
1570 /* Try and set the times, size and mode of this file -
1571 if they are different from the current values
1573 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1575 if(file_utime(cnum, fname, &tvs)!=0)
1577 return(ERROR(ERRDOS,ERRnoaccess));
1581 /* check the mode isn't different, before changing it */
1582 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1584 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1585 return(ERROR(ERRDOS,ERRnoaccess));
1588 if(size != st.st_size)
1592 fd = sys_open(fname,O_RDWR,0);
1595 return(ERROR(ERRDOS,ERRbadpath));
1597 set_filelen(fd, size);
1602 set_filelen(fd, size);
1608 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1613 /****************************************************************************
1614 reply to a TRANS2_MKDIR (make directory with extended attributes).
1615 ****************************************************************************/
1616 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1617 int cnum, char **pparams, char **ppdata)
1619 char *params = *pparams;
1622 BOOL bad_path = False;
1624 if (!CAN_WRITE(cnum))
1625 return(ERROR(ERRSRV,ERRaccess));
1627 pstrcpy(directory, ¶ms[4]);
1629 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1631 unix_convert(directory,cnum,0,&bad_path);
1632 if (check_name(directory,cnum))
1633 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1637 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1638 if((errno == ENOENT) && bad_path)
1640 unix_ERR_class = ERRDOS;
1641 unix_ERR_code = ERRbadpath;
1643 return(UNIXERROR(ERRDOS,ERRnoaccess));
1646 /* Realloc the parameter and data sizes */
1647 params = *pparams = Realloc(*pparams,2);
1649 return(ERROR(ERRDOS,ERRnomem));
1653 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1658 /****************************************************************************
1659 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1660 We don't actually do this - we just send a null response.
1661 ****************************************************************************/
1662 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1663 int cnum, char **pparams, char **ppdata)
1665 static uint16 fnf_handle = 257;
1666 char *params = *pparams;
1667 uint16 info_level = SVAL(params,4);
1669 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1677 return(ERROR(ERRDOS,ERRunknownlevel));
1680 /* Realloc the parameter and data sizes */
1681 params = *pparams = Realloc(*pparams,6);
1683 return(ERROR(ERRDOS,ERRnomem));
1685 SSVAL(params,0,fnf_handle);
1686 SSVAL(params,2,0); /* No changes */
1687 SSVAL(params,4,0); /* No EA errors */
1694 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1699 /****************************************************************************
1700 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1701 changes). Currently this does nothing.
1702 ****************************************************************************/
1703 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1704 int cnum, char **pparams, char **ppdata)
1706 char *params = *pparams;
1708 DEBUG(3,("call_trans2findnotifynext\n"));
1710 /* Realloc the parameter and data sizes */
1711 params = *pparams = Realloc(*pparams,4);
1713 return(ERROR(ERRDOS,ERRnomem));
1715 SSVAL(params,0,0); /* No changes */
1716 SSVAL(params,2,0); /* No EA errors */
1718 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1723 /****************************************************************************
1724 reply to a SMBfindclose (stop trans2 directory search)
1725 ****************************************************************************/
1726 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1730 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1732 cnum = SVAL(inbuf,smb_tid);
1734 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1736 dptr_close(dptr_num);
1738 outsize = set_message(outbuf,0,0,True);
1740 DEBUG( 3, ( "SMBfindclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) );
1745 /****************************************************************************
1746 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1747 ****************************************************************************/
1748 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1754 cnum = SVAL(inbuf,smb_tid);
1755 dptr_num = SVAL(inbuf,smb_vwv0);
1757 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1759 /* We never give out valid handles for a
1760 findnotifyfirst - so any dptr_num is ok here.
1763 outsize = set_message(outbuf,0,0,True);
1765 DEBUG( 3, ( "SMB_findnclose cnum=%d, dptr_num = %d\n", cnum, dptr_num ) );
1771 /****************************************************************************
1772 reply to a SMBtranss2 - just ignore it!
1773 ****************************************************************************/
1774 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1776 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1780 /****************************************************************************
1781 reply to a SMBtrans2
1782 ****************************************************************************/
1783 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1786 int cnum = SVAL(inbuf,smb_tid);
1787 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1788 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1790 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1791 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1792 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1793 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1794 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1795 int32 timeout = IVALS(inbuf,smb_timeout);
1797 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1798 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1799 char *params = NULL, *data = NULL;
1800 int num_params, num_params_sofar, num_data, num_data_sofar;
1802 if(global_oplock_break && (tran_call == TRANSACT2_OPEN))
1805 * Queue this open message as we are the process of an oplock break.
1808 DEBUG( 2, ( "reply_trans2: queueing message trans2open due to being " ) );
1809 DEBUGADD( 2, ( "in oplock break state.\n" ) );
1811 push_oplock_pending_smb_message( inbuf, length);
1815 outsize = set_message(outbuf,0,0,True);
1817 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1818 is so as a sanity check */
1821 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1822 return(ERROR(ERRSRV,ERRerror));
1825 /* Allocate the space for the maximum needed parameters and data */
1826 if (total_params > 0)
1827 params = (char *)malloc(total_params);
1829 data = (char *)malloc(total_data);
1831 if ((total_params && !params) || (total_data && !data))
1833 DEBUG(2,("Out of memory in reply_trans2\n"));
1834 return(ERROR(ERRDOS,ERRnomem));
1837 /* Copy the param and data bytes sent with this request into
1838 the params buffer */
1839 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1840 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1842 if (num_params > total_params || num_data > total_data)
1843 exit_server("invalid params in reply_trans2");
1846 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1848 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1850 if(num_data_sofar < total_data || num_params_sofar < total_params)
1852 /* We need to send an interim response then receive the rest
1853 of the parameter/data bytes */
1854 outsize = set_message(outbuf,0,0,True);
1855 send_smb(Client,outbuf);
1857 while( num_data_sofar < total_data || num_params_sofar < total_params)
1861 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1862 SMB_SECONDARY_WAIT);
1864 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1866 outsize = set_message(outbuf,0,0,True);
1868 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1870 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1871 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1876 return(ERROR(ERRSRV,ERRerror));
1879 /* Revise total_params and total_data in case they have changed downwards */
1880 total_params = SVAL(inbuf, smb_tpscnt);
1881 total_data = SVAL(inbuf, smb_tdscnt);
1882 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1883 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1884 if (num_params_sofar > total_params || num_data_sofar > total_data)
1885 exit_server("data overflow in trans2");
1887 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1888 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1889 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1890 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1894 if (Protocol >= PROTOCOL_NT1) {
1895 uint16 flg2 = SVAL(outbuf,smb_flg2);
1896 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1899 /* Now we must call the relevant TRANS2 function */
1902 case TRANSACT2_OPEN:
1903 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1905 case TRANSACT2_FINDFIRST:
1906 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1908 case TRANSACT2_FINDNEXT:
1909 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1911 case TRANSACT2_QFSINFO:
1912 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1914 case TRANSACT2_SETFSINFO:
1915 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1917 case TRANSACT2_QPATHINFO:
1918 case TRANSACT2_QFILEINFO:
1919 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1921 case TRANSACT2_SETPATHINFO:
1922 case TRANSACT2_SETFILEINFO:
1923 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1925 case TRANSACT2_FINDNOTIFYFIRST:
1926 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1928 case TRANSACT2_FINDNOTIFYNEXT:
1929 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1931 case TRANSACT2_MKDIR:
1932 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1935 /* Error in request */
1936 DEBUG( 2, ( "Unknown request %d in trans2 call\n", tran_call ) );
1941 return (ERROR(ERRSRV,ERRerror));
1944 /* As we do not know how many data packets will need to be
1945 returned here the various call_trans2xxxx calls
1946 must send their own. Thus a call_trans2xxx routine only
1947 returns a value other than -1 when it wants to send
1955 return outsize; /* If a correct response was needed the call_trans2xxx
1956 calls have already sent it. If outsize != -1 then it is
1957 returning an error packet. */