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 BOOL case_sensitive;
31 extern int oplock_sock;
32 extern int smb_read_error;
33 extern fstring local_machine;
34 extern int global_oplock_break;
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 = 3;
59 int data_alignment_offset = 0;
61 /* Initially set the wcnt area to be 10 - this is true for all
63 set_message(outbuf,10,0,True);
65 /* If there genuinely are no parameters or data to send just send
67 if(params_to_send == 0 && data_to_send == 0)
69 send_smb(Client,outbuf);
73 /* When sending params and data ensure that both are nicely aligned */
74 /* Only do this alignment when there is also data to send - else
75 can cause NT redirector problems. */
76 if (((params_to_send % 4) != 0) && (data_to_send != 0))
77 data_alignment_offset = 4 - (params_to_send % 4);
79 /* Space is bufsize minus Netbios over TCP header minus SMB header */
80 /* The alignment_offset is to align the param bytes on an even byte
81 boundary. NT 4.0 Beta needs this to work correctly. */
82 useable_space = bufsize - ((smb_buf(outbuf)+
83 alignment_offset+data_alignment_offset) -
86 /* useable_space can never be more than max_send minus the
88 useable_space = MIN(useable_space,
89 max_send - (alignment_offset+data_alignment_offset));
92 while (params_to_send || data_to_send)
94 /* Calculate whether we will totally or partially fill this packet */
95 total_sent_thistime = params_to_send + data_to_send +
96 alignment_offset + data_alignment_offset;
97 /* We can never send more than useable_space */
98 total_sent_thistime = MIN(total_sent_thistime, useable_space);
100 set_message(outbuf, 10, total_sent_thistime, True);
102 /* Set total params and data to be sent */
103 SSVAL(outbuf,smb_tprcnt,paramsize);
104 SSVAL(outbuf,smb_tdrcnt,datasize);
106 /* Calculate how many parameters and data we can fit into
107 this packet. Parameters get precedence */
109 params_sent_thistime = MIN(params_to_send,useable_space);
110 data_sent_thistime = useable_space - params_sent_thistime;
111 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
113 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
114 if(params_sent_thistime == 0)
116 SSVAL(outbuf,smb_proff,0);
117 SSVAL(outbuf,smb_prdisp,0);
121 /* smb_proff is the offset from the start of the SMB header to the
122 parameter bytes, however the first 4 bytes of outbuf are
123 the Netbios over TCP header. Thus use smb_base() to subtract
124 them from the calculation */
125 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
126 /* Absolute displacement of param bytes sent in this packet */
127 SSVAL(outbuf,smb_prdisp,pp - params);
130 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
131 if(data_sent_thistime == 0)
133 SSVAL(outbuf,smb_droff,0);
134 SSVAL(outbuf,smb_drdisp, 0);
138 /* The offset of the data bytes is the offset of the
139 parameter bytes plus the number of parameters being sent this time */
140 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
141 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
142 SSVAL(outbuf,smb_drdisp, pd - pdata);
145 /* Copy the param bytes into the packet */
146 if(params_sent_thistime)
147 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
148 /* Copy in the data bytes */
149 if(data_sent_thistime)
150 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
151 data_alignment_offset,pd,data_sent_thistime);
153 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
154 params_sent_thistime, data_sent_thistime, useable_space));
155 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
156 params_to_send, data_to_send, paramsize, datasize));
158 /* Send the packet */
159 send_smb(Client,outbuf);
161 pp += params_sent_thistime;
162 pd += data_sent_thistime;
164 params_to_send -= params_sent_thistime;
165 data_to_send -= data_sent_thistime;
168 if(params_to_send < 0 || data_to_send < 0)
170 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
171 params_to_send, data_to_send));
180 /****************************************************************************
181 reply to a TRANSACT2_OPEN
182 ****************************************************************************/
183 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
185 char **pparams, char **ppdata)
187 char *params = *pparams;
188 int16 open_mode = SVAL(params, 2);
189 int16 open_attr = SVAL(params,6);
190 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
192 BOOL return_additional_info = BITSETW(params,0);
193 int16 open_sattr = SVAL(params, 4);
194 time_t open_time = make_unix_date3(params+8);
196 int16 open_ofun = SVAL(params,12);
197 int32 open_size = IVAL(params,14);
198 char *pname = ¶ms[28];
199 int16 namelen = strlen(pname)+1;
203 int size=0,fmode=0,mtime=0,rmode;
207 BOOL bad_path = False;
210 StrnCpy(fname,pname,namelen);
212 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
213 fname,open_mode, open_attr, open_ofun, open_size));
215 /* XXXX we need to handle passed times, sattr and flags */
217 unix_convert(fname,conn,0,&bad_path,NULL);
221 return(ERROR(ERRSRV,ERRnofids));
223 if (!check_name(fname,conn))
225 if((errno == ENOENT) && bad_path)
227 unix_ERR_class = ERRDOS;
228 unix_ERR_code = ERRbadpath;
231 return(UNIXERROR(ERRDOS,ERRnoaccess));
234 unixmode = unix_mode(conn,open_attr | aARCH);
236 open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
237 oplock_request, &rmode,&smb_action);
241 if((errno == ENOENT) && bad_path)
243 unix_ERR_class = ERRDOS;
244 unix_ERR_code = ERRbadpath;
247 return(UNIXERROR(ERRDOS,ERRnoaccess));
250 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
251 close_file(fsp,False);
252 return(ERROR(ERRDOS,ERRnoaccess));
256 fmode = dos_mode(conn,fname,&sbuf);
257 mtime = sbuf.st_mtime;
260 close_file(fsp,False);
261 return(ERROR(ERRDOS,ERRnoaccess));
264 /* Realloc the size of parameters and data we will return */
265 params = *pparams = Realloc(*pparams, 28);
267 return(ERROR(ERRDOS,ERRnomem));
270 SSVAL(params,0,fsp->fnum);
271 SSVAL(params,2,fmode);
272 put_dos_date2(params,4, mtime);
273 SIVAL(params,8, size);
274 SSVAL(params,12,rmode);
276 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
277 smb_action |= EXTENDED_OPLOCK_GRANTED;
280 SSVAL(params,18,smb_action);
281 SIVAL(params,20,inode);
283 /* Send the required number of replies */
284 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
289 /****************************************************************************
290 get a level dependent lanman2 dir entry.
291 ****************************************************************************/
292 static int get_lanman2_dir_entry(connection_struct *conn,
293 char *path_mask,int dirtype,int info_level,
294 int requires_resume_key,
295 BOOL dont_descend,char **ppdata,
296 char *base_data, int space_remaining,
307 char *p, *pdata = *ppdata;
312 uint32 mdate=0, adate=0, cdate=0;
314 BOOL isrootdir = (strequal(conn->dirpath,"./") ||
315 strequal(conn->dirpath,".") ||
316 strequal(conn->dirpath,"/"));
318 int nt_extmode; /* Used for NT connections instead of mode */
319 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
322 *out_of_space = False;
327 p = strrchr(path_mask,'/');
336 pstrcpy(mask, path_mask);
340 /* Needed if we run out of space */
341 prev_dirpos = TellDir(conn->dirptr);
342 dname = ReadDirName(conn->dirptr);
345 * Due to bugs in NT client redirectors we are not using
346 * resume keys any more - set them to zero.
347 * Check out the related comments in findfirst/findnext.
353 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
354 (unsigned)conn->dirptr,TellDir(conn->dirptr)));
361 pstrcpy(fname,dname);
363 if(mask_match(fname, mask, case_sensitive, True))
365 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
366 if (dont_descend && !isdots)
369 if (isrootdir && isdots)
372 pstrcpy(pathreal,conn->dirpath);
374 pstrcat(pathreal,"/");
375 pstrcat(pathreal,dname);
376 if (sys_stat(pathreal,&sbuf) != 0)
378 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
382 mode = dos_mode(conn,pathreal,&sbuf);
384 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
385 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
390 mdate = sbuf.st_mtime;
391 adate = sbuf.st_atime;
392 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
396 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
402 name_map_mangle(fname,False,SNUM(conn));
407 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
412 if(requires_resume_key) {
416 put_dos_date2(p,l1_fdateCreation,cdate);
417 put_dos_date2(p,l1_fdateLastAccess,adate);
418 put_dos_date2(p,l1_fdateLastWrite,mdate);
419 SIVAL(p,l1_cbFile,size);
420 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
421 SSVAL(p,l1_attrFile,mode);
422 SCVAL(p,l1_cchName,strlen(fname));
423 pstrcpy(p + l1_achName, fname);
424 nameptr = p + l1_achName;
425 p += l1_achName + strlen(fname) + 1;
430 if(requires_resume_key) {
434 put_dos_date2(p,l2_fdateCreation,cdate);
435 put_dos_date2(p,l2_fdateLastAccess,adate);
436 put_dos_date2(p,l2_fdateLastWrite,mdate);
437 SIVAL(p,l2_cbFile,size);
438 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
439 SSVAL(p,l2_attrFile,mode);
440 SIVAL(p,l2_cbList,0); /* No extended attributes */
441 SCVAL(p,l2_cchName,strlen(fname));
442 pstrcpy(p + l2_achName, fname);
443 nameptr = p + l2_achName;
444 p += l2_achName + strlen(fname) + 1;
449 put_dos_date2(p,4,cdate);
450 put_dos_date2(p,8,adate);
451 put_dos_date2(p,12,mdate);
453 SIVAL(p,20,ROUNDUP(size,1024));
456 CVAL(p,30) = strlen(fname);
457 pstrcpy(p+31, fname);
459 p += 31 + strlen(fname) + 1;
463 if(requires_resume_key) {
467 SIVAL(p,0,33+strlen(fname)+1);
468 put_dos_date2(p,4,cdate);
469 put_dos_date2(p,8,adate);
470 put_dos_date2(p,12,mdate);
472 SIVAL(p,20,ROUNDUP(size,1024));
474 CVAL(p,32) = strlen(fname);
475 pstrcpy(p + 33, fname);
477 p += 33 + strlen(fname) + 1;
480 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
481 was_8_3 = is_8_3(fname, True);
482 len = 94+strlen(fname);
483 len = (len + 3) & ~3;
484 SIVAL(p,0,len); p += 4;
485 SIVAL(p,0,reskey); p += 4;
486 put_long_date(p,cdate); p += 8;
487 put_long_date(p,adate); p += 8;
488 put_long_date(p,mdate); p += 8;
489 put_long_date(p,mdate); p += 8;
490 SIVAL(p,0,size); p += 8;
491 SIVAL(p,0,size); p += 8;
492 SIVAL(p,0,nt_extmode); p += 4;
493 SIVAL(p,0,strlen(fname)); p += 4;
494 SIVAL(p,0,0); p += 4;
497 if (!name_map_mangle(p+2,True,SNUM(conn)))
502 SSVAL(p,0,strlen(p+2));
505 pstrcpy(p,fname); p += strlen(p);
509 case SMB_FIND_FILE_DIRECTORY_INFO:
510 len = 64+strlen(fname);
511 len = (len + 3) & ~3;
512 SIVAL(p,0,len); p += 4;
513 SIVAL(p,0,reskey); p += 4;
514 put_long_date(p,cdate); p += 8;
515 put_long_date(p,adate); p += 8;
516 put_long_date(p,mdate); p += 8;
517 put_long_date(p,mdate); p += 8;
518 SIVAL(p,0,size); p += 8;
519 SIVAL(p,0,size); p += 8;
520 SIVAL(p,0,nt_extmode); p += 4;
521 SIVAL(p,0,strlen(fname)); p += 4;
527 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
528 len = 68+strlen(fname);
529 len = (len + 3) & ~3;
530 SIVAL(p,0,len); p += 4;
531 SIVAL(p,0,reskey); p += 4;
532 put_long_date(p,cdate); p += 8;
533 put_long_date(p,adate); p += 8;
534 put_long_date(p,mdate); p += 8;
535 put_long_date(p,mdate); p += 8;
536 SIVAL(p,0,size); p += 8;
537 SIVAL(p,0,size); p += 8;
538 SIVAL(p,0,nt_extmode); p += 4;
539 SIVAL(p,0,strlen(fname)); p += 4;
540 SIVAL(p,0,0); p += 4;
545 case SMB_FIND_FILE_NAMES_INFO:
546 len = 12+strlen(fname);
547 len = (len + 3) & ~3;
548 SIVAL(p,0,len); p += 4;
549 SIVAL(p,0,reskey); p += 4;
550 SIVAL(p,0,strlen(fname)); p += 4;
560 if (PTR_DIFF(p,pdata) > space_remaining) {
561 /* Move the dirptr back to prev_dirpos */
562 SeekDir(conn->dirptr, prev_dirpos);
563 *out_of_space = True;
564 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
565 return False; /* Not finished - just out of space */
568 /* Setup the last_filename pointer, as an offset from base_data */
569 *last_name_off = PTR_DIFF(nameptr,base_data);
570 /* Advance the data pointer to the next slot */
575 /****************************************************************************
576 Convert the directory masks formated for the wire.
577 ****************************************************************************/
579 void mask_convert( char *mask)
582 * We know mask is a pstring.
588 if(p[1] != '"' && p[1] != '.') {
589 pstrcpy( expnd, p+1 );
592 safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
596 if (*p == '>') *p = '?';
597 if (*p == '"') *p = '.';
602 /****************************************************************************
603 reply to a TRANS2_FINDFIRST
604 ****************************************************************************/
605 static int call_trans2findfirst(connection_struct *conn,
606 char *inbuf, char *outbuf, int bufsize,
607 char **pparams, char **ppdata)
609 /* We must be careful here that we don't return more than the
610 allowed number of data bytes. If this means returning fewer than
611 maxentries then so be it. We assume that the redirector has
612 enough room for the fixed number of parameter bytes it has
614 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
615 char *params = *pparams;
616 char *pdata = *ppdata;
617 int dirtype = SVAL(params,0);
618 int maxentries = SVAL(params,2);
619 BOOL close_after_first = BITSETW(params+4,0);
620 BOOL close_if_end = BITSETW(params+4,1);
621 BOOL requires_resume_key = BITSETW(params+4,2);
622 int info_level = SVAL(params,6);
630 BOOL finished = False;
631 BOOL dont_descend = False;
632 BOOL out_of_space = False;
634 BOOL bad_path = False;
636 *directory = *mask = 0;
638 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",
639 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
640 info_level, max_data_bytes));
648 case SMB_FIND_FILE_DIRECTORY_INFO:
649 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
650 case SMB_FIND_FILE_NAMES_INFO:
651 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
654 return(ERROR(ERRDOS,ERRunknownlevel));
657 pstrcpy(directory, params + 12); /* Complete directory path with
658 wildcard mask appended */
660 DEBUG(5,("path=%s\n",directory));
662 unix_convert(directory,conn,0,&bad_path,NULL);
663 if(!check_name(directory,conn)) {
664 if((errno == ENOENT) && bad_path)
666 unix_ERR_class = ERRDOS;
667 unix_ERR_code = ERRbadpath;
671 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
672 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
673 (get_remote_arch() == RA_WINNT))
675 unix_ERR_class = ERRDOS;
676 unix_ERR_code = ERRbaddirectory;
680 return(ERROR(ERRDOS,ERRbadpath));
683 p = strrchr(directory,'/');
685 pstrcpy(mask,directory);
686 pstrcpy(directory,"./");
692 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
694 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
696 return(ERROR(ERRDOS,ERRnomem));
697 bzero(pdata,max_data_bytes);
699 /* Realloc the params space */
700 params = *pparams = Realloc(*pparams, 10);
702 return(ERROR(ERRDOS,ERRnomem));
704 dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
706 return(ERROR(ERRDOS,ERRbadfile));
708 /* Convert the formatted mask. */
713 * Now we have a working mask_match in util.c, I believe
714 * we no longer need these hacks (in fact they break
718 /* a special case for 16 bit apps */
719 if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
721 /* handle broken clients that send us old 8.3 format */
722 string_sub(mask,"????????","*");
723 string_sub(mask,".???",".*");
726 /* Save the wildcard match and attribs we are using on this directory -
727 needed as lanman2 assumes these are being saved between calls */
729 if(!(wcard = strdup(mask))) {
730 dptr_close(dptr_num);
731 return(ERROR(ERRDOS,ERRnomem));
734 dptr_set_wcard(dptr_num, wcard);
735 dptr_set_attr(dptr_num, dirtype);
737 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
739 /* We don't need to check for VOL here as this is returned by
740 a different TRANS2 call. */
742 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
743 conn->dirpath,lp_dontdescend(SNUM(conn))));
744 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
748 space_remaining = max_data_bytes;
749 out_of_space = False;
751 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
754 /* this is a heuristic to avoid seeking the dirptr except when
755 absolutely necessary. It allows for a filename of about 40 chars */
756 if (space_remaining < DIRLEN_GUESS && numentries > 0)
764 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
765 requires_resume_key,dont_descend,
766 &p,pdata,space_remaining, &out_of_space,
770 if (finished && out_of_space)
773 if (!finished && !out_of_space)
775 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
778 /* Check if we can close the dirptr */
779 if(close_after_first || (finished && close_if_end))
781 dptr_close(dptr_num);
782 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
787 * If there are no matching entries we must return ERRDOS/ERRbadfile -
788 * from observation of NT.
792 return(ERROR(ERRDOS,ERRbadfile));
794 /* At this point pdata points to numentries directory entries. */
796 /* Set up the return parameter block */
797 SSVAL(params,0,dptr_num);
798 SSVAL(params,2,numentries);
799 SSVAL(params,4,finished);
800 SSVAL(params,6,0); /* Never an EA error */
801 SSVAL(params,8,last_name_off);
803 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
805 if ((! *directory) && dptr_path(dptr_num))
806 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
808 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
809 smb_fn_name(CVAL(inbuf,smb_com)),
810 mask, directory, dirtype, numentries ) );
816 /****************************************************************************
817 reply to a TRANS2_FINDNEXT
818 ****************************************************************************/
819 static int call_trans2findnext(connection_struct *conn,
820 char *inbuf, char *outbuf,
821 int length, int bufsize,
822 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(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
889 return(ERROR(ERRDOS,ERRnofiles));
891 string_set(&conn->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,conn->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 (unsigned)conn->dirptr,
907 TellDir(conn->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",conn->dirpath,lp_dontdescend(SNUM(conn))));
913 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),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 = conn->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
957 name_map_mangle( dname, False, SNUM(conn));
959 if(dname && strcsequal( resume_name, dname))
961 SeekDir(dirptr, current_pos+1);
962 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
968 * Scan forward from start if not found going backwards.
973 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
974 SeekDir(dirptr, start_pos);
975 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
978 * Remember, name_map_mangle is called by
979 * get_lanman2_dir_entry(), so the resume name
980 * could be mangled. Ensure we do the same
985 name_map_mangle( dname, False, SNUM(conn));
987 if(dname && strcsequal( resume_name, dname))
989 SeekDir(dirptr, current_pos+1);
990 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
994 } /* end if current_pos */
995 } /* end if requires_resume_key && !continue_bit */
997 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
999 /* this is a heuristic to avoid seeking the dirptr except when
1000 absolutely necessary. It allows for a filename of about 40 chars */
1001 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1003 out_of_space = True;
1009 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1010 requires_resume_key,dont_descend,
1011 &p,pdata,space_remaining, &out_of_space,
1015 if (finished && out_of_space)
1018 if (!finished && !out_of_space)
1020 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1023 /* Check if we can close the dirptr */
1024 if(close_after_request || (finished && close_if_end))
1026 dptr_close(dptr_num); /* This frees up the saved mask */
1027 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1032 /* Set up the return parameter block */
1033 SSVAL(params,0,numentries);
1034 SSVAL(params,2,finished);
1035 SSVAL(params,4,0); /* Never an EA error */
1036 SSVAL(params,6,last_name_off);
1038 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1040 if ((! *directory) && dptr_path(dptr_num))
1041 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1043 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1044 smb_fn_name(CVAL(inbuf,smb_com)),
1045 mask, directory, dirtype, numentries ) );
1050 /****************************************************************************
1051 reply to a TRANS2_QFSINFO (query filesystem info)
1052 ****************************************************************************/
1053 static int call_trans2qfsinfo(connection_struct *conn,
1054 char *inbuf, char *outbuf,
1055 int length, int bufsize,
1056 char **pparams, char **ppdata)
1058 char *pdata = *ppdata;
1059 char *params = *pparams;
1060 uint16 info_level = SVAL(params,0);
1063 char *vname = volume_label(SNUM(conn));
1064 int snum = SNUM(conn);
1066 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1068 if(sys_stat(".",&st)!=0) {
1069 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1070 return (ERROR(ERRSRV,ERRinvdevice));
1073 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1079 int dfree,dsize,bsize;
1081 sys_disk_free(".",&bsize,&dfree,&dsize);
1082 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1083 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1084 SIVAL(pdata,l1_cUnit,dsize);
1085 SIVAL(pdata,l1_cUnitAvail,dfree);
1086 SSVAL(pdata,l1_cbSector,512);
1087 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1088 bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512));
1093 /* Return volume name */
1094 int volname_len = MIN(strlen(vname),11);
1095 data_len = l2_vol_szVolLabel + volname_len + 1;
1097 * Add volume serial number - hash of a combination of
1098 * the called hostname and the service name.
1100 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1101 SCVAL(pdata,l2_vol_cch,volname_len);
1102 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1103 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1104 (unsigned)st.st_ctime, volname_len,
1105 pdata+l2_vol_szVolLabel));
1108 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1109 data_len = 12 + 2*strlen(FSTYPE_STRING);
1110 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1111 #if 0 /* Old code. JRA. */
1112 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1113 #endif /* Old code. */
1114 SIVAL(pdata,4,128); /* Max filename component length */
1115 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1116 PutUniCode(pdata+12,FSTYPE_STRING);
1118 case SMB_QUERY_FS_LABEL_INFO:
1119 data_len = 4 + strlen(vname);
1120 SIVAL(pdata,0,strlen(vname));
1121 pstrcpy(pdata+4,vname);
1123 case SMB_QUERY_FS_VOLUME_INFO:
1124 data_len = 18 + 2*strlen(vname);
1126 * Add volume serial number - hash of a combination of
1127 * the called hostname and the service name.
1129 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1130 SIVAL(pdata,12,2*strlen(vname));
1131 PutUniCode(pdata+18,vname);
1132 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1135 case SMB_QUERY_FS_SIZE_INFO:
1137 int dfree,dsize,bsize;
1139 sys_disk_free(".",&bsize,&dfree,&dsize);
1140 SIVAL(pdata,0,dsize);
1141 SIVAL(pdata,8,dfree);
1142 SIVAL(pdata,16,bsize/512);
1143 SIVAL(pdata,20,512);
1146 case SMB_QUERY_FS_DEVICE_INFO:
1148 SIVAL(pdata,0,0); /* dev type */
1149 SIVAL(pdata,4,0); /* characteristics */
1152 return(ERROR(ERRDOS,ERRunknownlevel));
1156 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1158 DEBUG( 4, ( "%s info_level = %d\n",
1159 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1164 /****************************************************************************
1165 reply to a TRANS2_SETFSINFO (set filesystem info)
1166 ****************************************************************************/
1167 static int call_trans2setfsinfo(connection_struct *conn,
1168 char *inbuf, char *outbuf, int length,
1170 char **pparams, char **ppdata)
1172 /* Just say yes we did it - there is nothing that
1173 can be set here so it doesn't matter. */
1175 DEBUG(3,("call_trans2setfsinfo\n"));
1177 if (!CAN_WRITE(conn))
1178 return(ERROR(ERRSRV,ERRaccess));
1180 outsize = set_message(outbuf,10,0,True);
1185 /****************************************************************************
1186 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1187 file name or file id).
1188 ****************************************************************************/
1190 static int call_trans2qfilepathinfo(connection_struct *conn,
1191 char *inbuf, char *outbuf, int length,
1193 char **pparams,char **ppdata,
1196 char *params = *pparams;
1197 char *pdata = *ppdata;
1198 uint16 tran_call = SVAL(inbuf, smb_setup0);
1202 unsigned int data_size;
1208 BOOL bad_path = False;
1210 if (tran_call == TRANSACT2_QFILEINFO) {
1211 files_struct *fsp = file_fsp(params,0);
1212 info_level = SVAL(params,2);
1214 CHECK_FSP(fsp,conn);
1217 fname = fsp->fsp_name;
1218 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1219 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1220 return(UNIXERROR(ERRDOS,ERRbadfid));
1222 pos = lseek(fsp->fd_ptr->fd,0,SEEK_CUR);
1225 info_level = SVAL(params,0);
1227 pstrcpy(fname,¶ms[6]);
1228 unix_convert(fname,conn,0,&bad_path,&sbuf);
1229 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && sys_stat(fname,&sbuf))) {
1230 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1231 if((errno == ENOENT) && bad_path)
1233 unix_ERR_class = ERRDOS;
1234 unix_ERR_code = ERRbadpath;
1236 return(UNIXERROR(ERRDOS,ERRbadpath));
1242 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1243 fname,info_level,tran_call,total_data));
1245 p = strrchr(fname,'/');
1251 mode = dos_mode(conn,fname,&sbuf);
1252 size = sbuf.st_size;
1253 if (mode & aDIR) size = 0;
1255 /* from now on we only want the part after the / */
1258 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1260 pdata = *ppdata = Realloc(*ppdata, data_size);
1262 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1263 /* uggh, EAs for OS2 */
1264 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1265 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1268 bzero(pdata,data_size);
1272 case SMB_INFO_STANDARD:
1273 case SMB_INFO_QUERY_EA_SIZE:
1274 data_size = (info_level==1?22:26);
1275 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1276 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1277 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1278 SIVAL(pdata,l1_cbFile,size);
1279 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1280 SSVAL(pdata,l1_attrFile,mode);
1281 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1284 case SMB_INFO_QUERY_EAS_FROM_LIST:
1286 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1287 put_dos_date2(pdata,4,sbuf.st_atime);
1288 put_dos_date2(pdata,8,sbuf.st_mtime);
1289 SIVAL(pdata,12,size);
1290 SIVAL(pdata,16,ROUNDUP(size,1024));
1291 SIVAL(pdata,20,mode);
1294 case SMB_INFO_QUERY_ALL_EAS:
1296 SIVAL(pdata,0,data_size);
1300 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1302 case SMB_QUERY_FILE_BASIC_INFO:
1303 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1304 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1305 put_long_date(pdata+8,sbuf.st_atime);
1306 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1307 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1308 SIVAL(pdata,32,mode);
1310 DEBUG(5,("SMB_QFBI - "));
1312 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1313 DEBUG(5,("create: %s ", ctime(&create_time)));
1315 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1316 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1317 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1318 DEBUG(5,("mode: %x\n", mode));
1322 case SMB_QUERY_FILE_STANDARD_INFO:
1324 SIVAL(pdata,0,size);
1325 SIVAL(pdata,8,size);
1326 SIVAL(pdata,16,sbuf.st_nlink);
1328 CVAL(pdata,21) = (mode&aDIR)?1:0;
1331 case SMB_QUERY_FILE_EA_INFO:
1335 /* Get the 8.3 name - used if NT SMB was negotiated. */
1336 case SMB_QUERY_FILE_ALT_NAME_INFO:
1339 pstrcpy(short_name,p);
1340 /* Mangle if not already 8.3 */
1341 if(!is_8_3(short_name, True))
1343 if(!name_map_mangle(short_name,True,SNUM(conn)))
1346 strupper(short_name);
1347 l = strlen(short_name);
1348 PutUniCode(pdata + 4, short_name);
1349 data_size = 4 + (2*l);
1354 case SMB_QUERY_FILE_NAME_INFO:
1357 pstrcpy(pdata+4,fname);
1360 case SMB_QUERY_FILE_ALLOCATION_INFO:
1361 case SMB_QUERY_FILE_END_OF_FILEINFO:
1363 SIVAL(pdata,0,size);
1366 case SMB_QUERY_FILE_ALL_INFO:
1367 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1368 put_long_date(pdata+8,sbuf.st_atime);
1369 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1370 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1371 SIVAL(pdata,32,mode);
1373 SIVAL(pdata,0,size);
1374 SIVAL(pdata,8,size);
1375 SIVAL(pdata,16,sbuf.st_nlink);
1377 CVAL(pdata,21) = (mode&aDIR)?1:0;
1379 pdata += 8; /* index number */
1380 pdata += 4; /* EA info */
1382 SIVAL(pdata,0,0xA9);
1384 SIVAL(pdata,0,0xd01BF);
1386 SIVAL(pdata,0,pos); /* current offset */
1388 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1390 pdata += 4; /* alignment */
1392 pstrcpy(pdata+4,fname);
1394 data_size = PTR_DIFF(pdata,(*ppdata));
1398 /* NT4 server just returns "invalid query" to this - if we try to answer
1399 it then NTws gets a BSOD! (tridge) */
1400 case SMB_QUERY_FILE_STREAM_INFO:
1403 SIVAL(pdata,4,size);
1404 SIVAL(pdata,12,size);
1406 pstrcpy(pdata+24,fname);
1411 return(ERROR(ERRDOS,ERRunknownlevel));
1414 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1419 /****************************************************************************
1420 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1421 ****************************************************************************/
1422 static int call_trans2setfilepathinfo(connection_struct *conn,
1423 char *inbuf, char *outbuf, int length,
1424 int bufsize, char **pparams,
1425 char **ppdata, int total_data)
1427 char *params = *pparams;
1428 char *pdata = *ppdata;
1429 uint16 tran_call = SVAL(inbuf, smb_setup0);
1438 BOOL bad_path = False;
1440 if (!CAN_WRITE(conn))
1441 return(ERROR(ERRSRV,ERRaccess));
1443 if (tran_call == TRANSACT2_SETFILEINFO) {
1444 files_struct *fsp = file_fsp(params,0);
1445 info_level = SVAL(params,2);
1447 CHECK_FSP(fsp,conn);
1450 fname = fsp->fsp_name;
1451 fd = fsp->fd_ptr->fd;
1453 if(fstat(fd,&st)!=0) {
1454 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1455 return(ERROR(ERRDOS,ERRbadpath));
1459 info_level = SVAL(params,0);
1461 pstrcpy(fname,¶ms[6]);
1462 unix_convert(fname,conn,0,&bad_path,&st);
1463 if(!check_name(fname, conn))
1465 if((errno == ENOENT) && bad_path)
1467 unix_ERR_class = ERRDOS;
1468 unix_ERR_code = ERRbadpath;
1470 return(UNIXERROR(ERRDOS,ERRbadpath));
1473 if(!VALID_STAT(st) && sys_stat(fname,&st)!=0) {
1474 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1475 if((errno == ENOENT) && bad_path)
1477 unix_ERR_class = ERRDOS;
1478 unix_ERR_code = ERRbadpath;
1480 return(UNIXERROR(ERRDOS,ERRbadpath));
1484 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1485 tran_call,fname,info_level,total_data));
1487 /* Realloc the parameter and data sizes */
1488 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1490 return(ERROR(ERRDOS,ERRnomem));
1493 tvs.modtime = st.st_mtime;
1494 tvs.actime = st.st_atime;
1495 mode = dos_mode(conn,fname,&st);
1497 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1498 /* uggh, EAs for OS2 */
1499 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1500 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1505 case SMB_INFO_STANDARD:
1506 case SMB_INFO_QUERY_EA_SIZE:
1509 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1512 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1514 mode = SVAL(pdata,l1_attrFile);
1515 size = IVAL(pdata,l1_cbFile);
1519 /* XXXX um, i don't think this is right.
1520 it's also not in the cifs6.txt spec.
1522 case SMB_INFO_QUERY_EAS_FROM_LIST:
1523 tvs.actime = make_unix_date2(pdata+8);
1524 tvs.modtime = make_unix_date2(pdata+12);
1525 size = IVAL(pdata,16);
1526 mode = IVAL(pdata,24);
1529 /* XXXX nor this. not in cifs6.txt, either. */
1530 case SMB_INFO_QUERY_ALL_EAS:
1531 tvs.actime = make_unix_date2(pdata+8);
1532 tvs.modtime = make_unix_date2(pdata+12);
1533 size = IVAL(pdata,16);
1534 mode = IVAL(pdata,24);
1537 case SMB_SET_FILE_BASIC_INFO:
1539 /* Ignore create time at offset pdata. */
1542 tvs.actime = interpret_long_date(pdata+8);
1544 /* write time + changed time, combined. */
1545 tvs.modtime=MAX(interpret_long_date(pdata+16),
1546 interpret_long_date(pdata+24));
1548 #if 0 /* Needs more testing... */
1549 /* Test from Luke to prevent Win95 from
1550 setting incorrect values here.
1552 if (tvs.actime < tvs.modtime)
1553 return(ERROR(ERRDOS,ERRnoaccess));
1554 #endif /* Needs more testing... */
1557 mode = IVAL(pdata,32);
1561 case SMB_SET_FILE_END_OF_FILE_INFO:
1563 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1564 return(ERROR(ERRDOS,ERRunknownlevel));
1565 size = IVAL(pdata,0);
1569 case SMB_SET_FILE_ALLOCATION_INFO:
1570 break; /* We don't need to do anything for this call. */
1572 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1575 return(ERROR(ERRDOS,ERRunknownlevel));
1579 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1580 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1581 DEBUG(6,("size: %x " , size));
1582 DEBUG(6,("mode: %x\n" , mode));
1584 /* get some defaults (no modifications) if any info is zero. */
1585 if (!tvs.actime) tvs.actime = st.st_atime;
1586 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1587 if (!size) size = st.st_size;
1589 /* Try and set the times, size and mode of this file -
1590 if they are different from the current values
1592 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1594 if(file_utime(conn, fname, &tvs)!=0)
1596 return(ERROR(ERRDOS,ERRnoaccess));
1600 /* check the mode isn't different, before changing it */
1601 if (mode != dos_mode(conn, fname, &st) && dos_chmod(conn, fname, mode, NULL))
1603 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1604 return(ERROR(ERRDOS,ERRnoaccess));
1607 if(size != st.st_size)
1611 fd = sys_open(fname,O_RDWR,0);
1614 return(ERROR(ERRDOS,ERRbadpath));
1616 set_filelen(fd, size);
1621 set_filelen(fd, size);
1627 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1632 /****************************************************************************
1633 reply to a TRANS2_MKDIR (make directory with extended attributes).
1634 ****************************************************************************/
1635 static int call_trans2mkdir(connection_struct *conn,
1636 char *inbuf, char *outbuf, int length, int bufsize,
1637 char **pparams, char **ppdata)
1639 char *params = *pparams;
1642 BOOL bad_path = False;
1644 if (!CAN_WRITE(conn))
1645 return(ERROR(ERRSRV,ERRaccess));
1647 pstrcpy(directory, ¶ms[4]);
1649 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1651 unix_convert(directory,conn,0,&bad_path,NULL);
1652 if (check_name(directory,conn))
1653 ret = sys_mkdir(directory,unix_mode(conn,aDIR));
1657 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1658 if((errno == ENOENT) && bad_path)
1660 unix_ERR_class = ERRDOS;
1661 unix_ERR_code = ERRbadpath;
1663 return(UNIXERROR(ERRDOS,ERRnoaccess));
1666 /* Realloc the parameter and data sizes */
1667 params = *pparams = Realloc(*pparams,2);
1669 return(ERROR(ERRDOS,ERRnomem));
1673 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1678 /****************************************************************************
1679 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1680 We don't actually do this - we just send a null response.
1681 ****************************************************************************/
1682 static int call_trans2findnotifyfirst(connection_struct *conn,
1683 char *inbuf, char *outbuf,
1684 int length, int bufsize,
1685 char **pparams, char **ppdata)
1687 static uint16 fnf_handle = 257;
1688 char *params = *pparams;
1689 uint16 info_level = SVAL(params,4);
1691 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1699 return(ERROR(ERRDOS,ERRunknownlevel));
1702 /* Realloc the parameter and data sizes */
1703 params = *pparams = Realloc(*pparams,6);
1705 return(ERROR(ERRDOS,ERRnomem));
1707 SSVAL(params,0,fnf_handle);
1708 SSVAL(params,2,0); /* No changes */
1709 SSVAL(params,4,0); /* No EA errors */
1716 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1721 /****************************************************************************
1722 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1723 changes). Currently this does nothing.
1724 ****************************************************************************/
1725 static int call_trans2findnotifynext(connection_struct *conn,
1726 char *inbuf, char *outbuf,
1727 int length, int bufsize,
1728 char **pparams, char **ppdata)
1730 char *params = *pparams;
1732 DEBUG(3,("call_trans2findnotifynext\n"));
1734 /* Realloc the parameter and data sizes */
1735 params = *pparams = Realloc(*pparams,4);
1737 return(ERROR(ERRDOS,ERRnomem));
1739 SSVAL(params,0,0); /* No changes */
1740 SSVAL(params,2,0); /* No EA errors */
1742 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1747 /****************************************************************************
1748 reply to a SMBfindclose (stop trans2 directory search)
1749 ****************************************************************************/
1750 int reply_findclose(connection_struct *conn,
1751 char *inbuf,char *outbuf,int length,int bufsize)
1754 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1756 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1758 dptr_close(dptr_num);
1760 outsize = set_message(outbuf,0,0,True);
1762 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1767 /****************************************************************************
1768 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1769 ****************************************************************************/
1770 int reply_findnclose(connection_struct *conn,
1771 char *inbuf,char *outbuf,int length,int bufsize)
1776 dptr_num = SVAL(inbuf,smb_vwv0);
1778 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1780 /* We never give out valid handles for a
1781 findnotifyfirst - so any dptr_num is ok here.
1784 outsize = set_message(outbuf,0,0,True);
1786 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1792 /****************************************************************************
1793 reply to a SMBtranss2 - just ignore it!
1794 ****************************************************************************/
1795 int reply_transs2(connection_struct *conn,
1796 char *inbuf,char *outbuf,int length,int bufsize)
1798 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1802 /****************************************************************************
1803 reply to a SMBtrans2
1804 ****************************************************************************/
1805 int reply_trans2(connection_struct *conn,
1806 char *inbuf,char *outbuf,int length,int bufsize)
1809 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1810 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1812 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1813 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1814 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1815 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1816 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1817 int32 timeout = IVALS(inbuf,smb_timeout);
1819 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1820 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1821 char *params = NULL, *data = NULL;
1822 int num_params, num_params_sofar, num_data, num_data_sofar;
1824 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1825 /* Queue this open message as we are the process of an
1828 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1829 DEBUGADD(2,( "in oplock break state.\n"));
1831 push_oplock_pending_smb_message(inbuf, length);
1835 outsize = set_message(outbuf,0,0,True);
1837 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1838 is so as a sanity check */
1840 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1841 return(ERROR(ERRSRV,ERRerror));
1844 /* Allocate the space for the maximum needed parameters and data */
1845 if (total_params > 0)
1846 params = (char *)malloc(total_params);
1848 data = (char *)malloc(total_data);
1850 if ((total_params && !params) || (total_data && !data)) {
1851 DEBUG(2,("Out of memory in reply_trans2\n"));
1852 return(ERROR(ERRDOS,ERRnomem));
1855 /* Copy the param and data bytes sent with this request into
1856 the params buffer */
1857 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1858 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1860 if (num_params > total_params || num_data > total_data)
1861 exit_server("invalid params in reply_trans2");
1864 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1866 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1868 if(num_data_sofar < total_data || num_params_sofar < total_params) {
1869 /* We need to send an interim response then receive the rest
1870 of the parameter/data bytes */
1871 outsize = set_message(outbuf,0,0,True);
1872 send_smb(Client,outbuf);
1874 while (num_data_sofar < total_data ||
1875 num_params_sofar < total_params) {
1878 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1879 SMB_SECONDARY_WAIT);
1882 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
1883 outsize = set_message(outbuf,0,0,True);
1885 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1887 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1888 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1893 return(ERROR(ERRSRV,ERRerror));
1896 /* Revise total_params and total_data in case
1897 they have changed downwards */
1898 total_params = SVAL(inbuf, smb_tpscnt);
1899 total_data = SVAL(inbuf, smb_tdscnt);
1900 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1901 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1902 if (num_params_sofar > total_params || num_data_sofar > total_data)
1903 exit_server("data overflow in trans2");
1905 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1906 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1907 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1908 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1912 if (Protocol >= PROTOCOL_NT1) {
1913 uint16 flg2 = SVAL(outbuf,smb_flg2);
1914 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1917 /* Now we must call the relevant TRANS2 function */
1919 case TRANSACT2_OPEN:
1920 outsize = call_trans2open(conn,
1921 inbuf, outbuf, bufsize,
1925 case TRANSACT2_FINDFIRST:
1926 outsize = call_trans2findfirst(conn, inbuf, outbuf,
1927 bufsize, ¶ms, &data);
1930 case TRANSACT2_FINDNEXT:
1931 outsize = call_trans2findnext(conn, inbuf, outbuf,
1936 case TRANSACT2_QFSINFO:
1937 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
1938 length, bufsize, ¶ms,
1942 case TRANSACT2_SETFSINFO:
1943 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
1948 case TRANSACT2_QPATHINFO:
1949 case TRANSACT2_QFILEINFO:
1950 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
1952 ¶ms, &data, total_data);
1954 case TRANSACT2_SETPATHINFO:
1955 case TRANSACT2_SETFILEINFO:
1956 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
1962 case TRANSACT2_FINDNOTIFYFIRST:
1963 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
1968 case TRANSACT2_FINDNOTIFYNEXT:
1969 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
1973 case TRANSACT2_MKDIR:
1974 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
1975 bufsize, ¶ms, &data);
1978 /* Error in request */
1979 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
1984 return (ERROR(ERRSRV,ERRerror));
1987 /* As we do not know how many data packets will need to be
1988 returned here the various call_trans2xxxx calls
1989 must send their own. Thus a call_trans2xxx routine only
1990 returns a value other than -1 when it wants to send
1998 return outsize; /* If a correct response was needed the
1999 call_trans2xxx calls have already sent
2000 it. If outsize != -1 then it is returning */