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 smb_read_error;
32 extern fstring local_machine;
33 extern int global_oplock_break;
35 /****************************************************************************
36 Send the required number of replies back.
37 We assume all fields other than the data fields are
38 set correctly for the type of call.
39 HACK ! Always assumes smb_setup field is zero.
40 ****************************************************************************/
41 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
42 int paramsize, char *pdata, int datasize)
44 /* As we are using a protocol > LANMAN1 then the max_send
45 variable must have been set in the sessetupX call.
46 This takes precedence over the max_xmit field in the
47 global struct. These different max_xmit variables should
48 be merged as this is now too confusing */
51 int data_to_send = datasize;
52 int params_to_send = paramsize;
56 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
57 int alignment_offset = 3;
58 int data_alignment_offset = 0;
60 /* Initially set the wcnt area to be 10 - this is true for all
62 set_message(outbuf,10,0,True);
64 /* If there genuinely are no parameters or data to send just send
66 if(params_to_send == 0 && data_to_send == 0)
68 send_smb(Client,outbuf);
72 /* When sending params and data ensure that both are nicely aligned */
73 /* Only do this alignment when there is also data to send - else
74 can cause NT redirector problems. */
75 if (((params_to_send % 4) != 0) && (data_to_send != 0))
76 data_alignment_offset = 4 - (params_to_send % 4);
78 /* Space is bufsize minus Netbios over TCP header minus SMB header */
79 /* The alignment_offset is to align the param bytes on an even byte
80 boundary. NT 4.0 Beta needs this to work correctly. */
81 useable_space = bufsize - ((smb_buf(outbuf)+
82 alignment_offset+data_alignment_offset) -
85 /* useable_space can never be more than max_send minus the
87 useable_space = MIN(useable_space,
88 max_send - (alignment_offset+data_alignment_offset));
91 while (params_to_send || data_to_send)
93 /* Calculate whether we will totally or partially fill this packet */
94 total_sent_thistime = params_to_send + data_to_send +
95 alignment_offset + data_alignment_offset;
96 /* We can never send more than useable_space */
97 total_sent_thistime = MIN(total_sent_thistime, useable_space);
99 set_message(outbuf, 10, total_sent_thistime, True);
101 /* Set total params and data to be sent */
102 SSVAL(outbuf,smb_tprcnt,paramsize);
103 SSVAL(outbuf,smb_tdrcnt,datasize);
105 /* Calculate how many parameters and data we can fit into
106 this packet. Parameters get precedence */
108 params_sent_thistime = MIN(params_to_send,useable_space);
109 data_sent_thistime = useable_space - params_sent_thistime;
110 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
112 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
113 if(params_sent_thistime == 0)
115 SSVAL(outbuf,smb_proff,0);
116 SSVAL(outbuf,smb_prdisp,0);
120 /* smb_proff is the offset from the start of the SMB header to the
121 parameter bytes, however the first 4 bytes of outbuf are
122 the Netbios over TCP header. Thus use smb_base() to subtract
123 them from the calculation */
124 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
125 /* Absolute displacement of param bytes sent in this packet */
126 SSVAL(outbuf,smb_prdisp,pp - params);
129 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
130 if(data_sent_thistime == 0)
132 SSVAL(outbuf,smb_droff,0);
133 SSVAL(outbuf,smb_drdisp, 0);
137 /* The offset of the data bytes is the offset of the
138 parameter bytes plus the number of parameters being sent this time */
139 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
140 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
141 SSVAL(outbuf,smb_drdisp, pd - pdata);
144 /* Copy the param bytes into the packet */
145 if(params_sent_thistime)
146 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
147 /* Copy in the data bytes */
148 if(data_sent_thistime)
149 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
150 data_alignment_offset,pd,data_sent_thistime);
152 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
153 params_sent_thistime, data_sent_thistime, useable_space));
154 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
155 params_to_send, data_to_send, paramsize, datasize));
157 /* Send the packet */
158 send_smb(Client,outbuf);
160 pp += params_sent_thistime;
161 pd += data_sent_thistime;
163 params_to_send -= params_sent_thistime;
164 data_to_send -= data_sent_thistime;
167 if(params_to_send < 0 || data_to_send < 0)
169 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
170 params_to_send, data_to_send));
179 /****************************************************************************
180 reply to a TRANSACT2_OPEN
181 ****************************************************************************/
182 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
184 char **pparams, char **ppdata)
186 char *params = *pparams;
187 int16 open_mode = SVAL(params, 2);
188 int16 open_attr = SVAL(params,6);
189 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
191 BOOL return_additional_info = BITSETW(params,0);
192 int16 open_sattr = SVAL(params, 4);
193 time_t open_time = make_unix_date3(params+8);
195 int16 open_ofun = SVAL(params,12);
196 int32 open_size = IVAL(params,14);
197 char *pname = ¶ms[28];
198 int16 namelen = strlen(pname)+1;
203 int fmode=0,mtime=0,rmode;
205 SMB_STRUCT_STAT sbuf;
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 (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
251 close_file(fsp,False);
252 return(UNIXERROR(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, (uint32)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);
282 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
284 SIVAL(params,20,inode);
286 /* Send the required number of replies */
287 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
292 /****************************************************************************
293 get a level dependent lanman2 dir entry.
294 ****************************************************************************/
295 static int get_lanman2_dir_entry(connection_struct *conn,
296 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,
305 SMB_STRUCT_STAT sbuf;
309 char *p, *pdata = *ppdata;
315 time_t mdate=0, adate=0, cdate=0;
317 BOOL isrootdir = (strequal(conn->dirpath,"./") ||
318 strequal(conn->dirpath,".") ||
319 strequal(conn->dirpath,"/"));
321 int nt_extmode; /* Used for NT connections instead of mode */
322 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
325 *out_of_space = False;
330 p = strrchr(path_mask,'/');
339 pstrcpy(mask, path_mask);
343 /* Needed if we run out of space */
344 prev_dirpos = TellDir(conn->dirptr);
345 dname = ReadDirName(conn->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%lx now at offset %d\n",
357 (long)conn->dirptr,TellDir(conn->dirptr)));
362 pstrcpy(fname,dname);
364 if(mask_match(fname, mask, case_sensitive, True))
366 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
367 if (dont_descend && !isdots)
370 if (isrootdir && isdots)
373 pstrcpy(pathreal,conn->dirpath);
375 pstrcat(pathreal,"/");
376 pstrcat(pathreal,dname);
377 if (dos_stat(pathreal,&sbuf) != 0)
379 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
383 mode = dos_mode(conn,pathreal,&sbuf);
385 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
386 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
391 mdate = sbuf.st_mtime;
392 adate = sbuf.st_atime;
393 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
397 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
403 name_map_mangle(fname,False,SNUM(conn));
408 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
413 if(requires_resume_key) {
417 put_dos_date2(p,l1_fdateCreation,cdate);
418 put_dos_date2(p,l1_fdateLastAccess,adate);
419 put_dos_date2(p,l1_fdateLastWrite,mdate);
420 SIVAL(p,l1_cbFile,(uint32)size);
421 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
422 SSVAL(p,l1_attrFile,mode);
423 SCVAL(p,l1_cchName,strlen(fname));
424 pstrcpy(p + l1_achName, fname);
425 nameptr = p + l1_achName;
426 p += l1_achName + strlen(fname) + 1;
431 if(requires_resume_key) {
435 put_dos_date2(p,l2_fdateCreation,cdate);
436 put_dos_date2(p,l2_fdateLastAccess,adate);
437 put_dos_date2(p,l2_fdateLastWrite,mdate);
438 SIVAL(p,l2_cbFile,(uint32)size);
439 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
440 SSVAL(p,l2_attrFile,mode);
441 SIVAL(p,l2_cbList,0); /* No extended attributes */
442 SCVAL(p,l2_cchName,strlen(fname));
443 pstrcpy(p + l2_achName, fname);
444 nameptr = p + l2_achName;
445 p += l2_achName + strlen(fname) + 1;
450 put_dos_date2(p,4,cdate);
451 put_dos_date2(p,8,adate);
452 put_dos_date2(p,12,mdate);
453 SIVAL(p,16,(uint32)size);
454 SIVAL(p,20,ROUNDUP(size,1024));
457 CVAL(p,30) = strlen(fname);
458 pstrcpy(p+31, fname);
460 p += 31 + strlen(fname) + 1;
464 if(requires_resume_key) {
468 SIVAL(p,0,33+strlen(fname)+1);
469 put_dos_date2(p,4,cdate);
470 put_dos_date2(p,8,adate);
471 put_dos_date2(p,12,mdate);
472 SIVAL(p,16,(uint32)size);
473 SIVAL(p,20,ROUNDUP(size,1024));
475 CVAL(p,32) = strlen(fname);
476 pstrcpy(p + 33, fname);
478 p += 33 + strlen(fname) + 1;
481 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
482 was_8_3 = is_8_3(fname, True);
483 len = 94+strlen(fname);
484 len = (len + 3) & ~3;
485 SIVAL(p,0,len); p += 4;
486 SIVAL(p,0,reskey); p += 4;
487 put_long_date(p,cdate); p += 8;
488 put_long_date(p,adate); p += 8;
489 put_long_date(p,mdate); p += 8;
490 put_long_date(p,mdate); p += 8;
494 SIVAL(p,0,nt_extmode); p += 4;
495 SIVAL(p,0,strlen(fname)); p += 4;
496 SIVAL(p,0,0); p += 4;
499 if (!name_map_mangle(p+2,True,SNUM(conn)))
504 SSVAL(p,0,strlen(p+2));
507 pstrcpy(p,fname); p += strlen(p);
511 case SMB_FIND_FILE_DIRECTORY_INFO:
512 len = 64+strlen(fname);
513 len = (len + 3) & ~3;
514 SIVAL(p,0,len); p += 4;
515 SIVAL(p,0,reskey); p += 4;
516 put_long_date(p,cdate); p += 8;
517 put_long_date(p,adate); p += 8;
518 put_long_date(p,mdate); p += 8;
519 put_long_date(p,mdate); 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;
542 SIVAL(p,0,nt_extmode); p += 4;
543 SIVAL(p,0,strlen(fname)); p += 4;
544 SIVAL(p,0,0); p += 4;
549 case SMB_FIND_FILE_NAMES_INFO:
550 len = 12+strlen(fname);
551 len = (len + 3) & ~3;
552 SIVAL(p,0,len); p += 4;
553 SIVAL(p,0,reskey); p += 4;
554 SIVAL(p,0,strlen(fname)); p += 4;
564 if (PTR_DIFF(p,pdata) > space_remaining) {
565 /* Move the dirptr back to prev_dirpos */
566 SeekDir(conn->dirptr, prev_dirpos);
567 *out_of_space = True;
568 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
569 return False; /* Not finished - just out of space */
572 /* Setup the last_filename pointer, as an offset from base_data */
573 *last_name_off = PTR_DIFF(nameptr,base_data);
574 /* Advance the data pointer to the next slot */
579 /****************************************************************************
580 Convert the directory masks formated for the wire.
581 ****************************************************************************/
583 void mask_convert( char *mask)
586 * We know mask is a pstring.
592 if(p[1] != '"' && p[1] != '.') {
593 pstrcpy( expnd, p+1 );
596 safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
600 if (*p == '>') *p = '?';
601 if (*p == '"') *p = '.';
606 /****************************************************************************
607 reply to a TRANS2_FINDFIRST
608 ****************************************************************************/
609 static int call_trans2findfirst(connection_struct *conn,
610 char *inbuf, char *outbuf, int bufsize,
611 char **pparams, char **ppdata)
613 /* We must be careful here that we don't return more than the
614 allowed number of data bytes. If this means returning fewer than
615 maxentries then so be it. We assume that the redirector has
616 enough room for the fixed number of parameter bytes it has
618 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
619 char *params = *pparams;
620 char *pdata = *ppdata;
621 int dirtype = SVAL(params,0);
622 int maxentries = SVAL(params,2);
623 BOOL close_after_first = BITSETW(params+4,0);
624 BOOL close_if_end = BITSETW(params+4,1);
625 BOOL requires_resume_key = BITSETW(params+4,2);
626 int info_level = SVAL(params,6);
634 BOOL finished = False;
635 BOOL dont_descend = False;
636 BOOL out_of_space = False;
638 BOOL bad_path = False;
640 *directory = *mask = 0;
642 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",
643 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
644 info_level, max_data_bytes));
652 case SMB_FIND_FILE_DIRECTORY_INFO:
653 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
654 case SMB_FIND_FILE_NAMES_INFO:
655 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
658 return(ERROR(ERRDOS,ERRunknownlevel));
661 pstrcpy(directory, params + 12); /* Complete directory path with
662 wildcard mask appended */
664 DEBUG(5,("path=%s\n",directory));
666 unix_convert(directory,conn,0,&bad_path,NULL);
667 if(!check_name(directory,conn)) {
668 if((errno == ENOENT) && bad_path)
670 unix_ERR_class = ERRDOS;
671 unix_ERR_code = ERRbadpath;
675 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
676 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
677 (get_remote_arch() == RA_WINNT))
679 unix_ERR_class = ERRDOS;
680 unix_ERR_code = ERRbaddirectory;
684 return(UNIXERROR(ERRDOS,ERRbadpath));
687 p = strrchr(directory,'/');
689 pstrcpy(mask,directory);
690 pstrcpy(directory,"./");
696 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
698 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
700 return(ERROR(ERRDOS,ERRnomem));
701 bzero(pdata,max_data_bytes);
703 /* Realloc the params space */
704 params = *pparams = Realloc(*pparams, 10);
706 return(ERROR(ERRDOS,ERRnomem));
708 dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
710 return(UNIXERROR(ERRDOS,ERRbadfile));
712 /* Convert the formatted mask. */
717 * Now we have a working mask_match in util.c, I believe
718 * we no longer need these hacks (in fact they break
722 /* a special case for 16 bit apps */
723 if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
725 /* handle broken clients that send us old 8.3 format */
726 string_sub(mask,"????????","*");
727 string_sub(mask,".???",".*");
730 /* Save the wildcard match and attribs we are using on this directory -
731 needed as lanman2 assumes these are being saved between calls */
733 if(!(wcard = strdup(mask))) {
734 dptr_close(dptr_num);
735 return(ERROR(ERRDOS,ERRnomem));
738 dptr_set_wcard(dptr_num, wcard);
739 dptr_set_attr(dptr_num, dirtype);
741 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
743 /* We don't need to check for VOL here as this is returned by
744 a different TRANS2 call. */
746 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
747 conn->dirpath,lp_dontdescend(SNUM(conn))));
748 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
752 space_remaining = max_data_bytes;
753 out_of_space = False;
755 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
758 /* this is a heuristic to avoid seeking the dirptr except when
759 absolutely necessary. It allows for a filename of about 40 chars */
760 if (space_remaining < DIRLEN_GUESS && numentries > 0)
768 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
769 requires_resume_key,dont_descend,
770 &p,pdata,space_remaining, &out_of_space,
774 if (finished && out_of_space)
777 if (!finished && !out_of_space)
779 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
782 /* Check if we can close the dirptr */
783 if(close_after_first || (finished && close_if_end))
785 dptr_close(dptr_num);
786 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
791 * If there are no matching entries we must return ERRDOS/ERRbadfile -
792 * from observation of NT.
796 return(ERROR(ERRDOS,ERRbadfile));
798 /* At this point pdata points to numentries directory entries. */
800 /* Set up the return parameter block */
801 SSVAL(params,0,dptr_num);
802 SSVAL(params,2,numentries);
803 SSVAL(params,4,finished);
804 SSVAL(params,6,0); /* Never an EA error */
805 SSVAL(params,8,last_name_off);
807 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
809 if ((! *directory) && dptr_path(dptr_num))
810 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
812 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
813 smb_fn_name(CVAL(inbuf,smb_com)),
814 mask, directory, dirtype, numentries ) );
820 /****************************************************************************
821 reply to a TRANS2_FINDNEXT
822 ****************************************************************************/
823 static int call_trans2findnext(connection_struct *conn,
824 char *inbuf, char *outbuf,
825 int length, int bufsize,
826 char **pparams, char **ppdata)
828 /* We must be careful here that we don't return more than the
829 allowed number of data bytes. If this means returning fewer than
830 maxentries then so be it. We assume that the redirector has
831 enough room for the fixed number of parameter bytes it has
833 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
834 char *params = *pparams;
835 char *pdata = *ppdata;
836 int16 dptr_num = SVAL(params,0);
837 int maxentries = SVAL(params,2);
838 uint16 info_level = SVAL(params,4);
839 uint32 resume_key = IVAL(params,6);
840 BOOL close_after_request = BITSETW(params+10,0);
841 BOOL close_if_end = BITSETW(params+10,1);
842 BOOL requires_resume_key = BITSETW(params+10,2);
843 BOOL continue_bit = BITSETW(params+10,3);
850 int i, last_name_off=0;
851 BOOL finished = False;
852 BOOL dont_descend = False;
853 BOOL out_of_space = False;
856 *mask = *directory = *resume_name = 0;
858 pstrcpy( resume_name, params+12);
860 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
861 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
862 resume_key = %d resume name = %s continue=%d level = %d\n",
863 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
864 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
872 case SMB_FIND_FILE_DIRECTORY_INFO:
873 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
874 case SMB_FIND_FILE_NAMES_INFO:
875 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
878 return(ERROR(ERRDOS,ERRunknownlevel));
881 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
883 return(ERROR(ERRDOS,ERRnomem));
884 bzero(pdata,max_data_bytes);
886 /* Realloc the params space */
887 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
889 return(ERROR(ERRDOS,ERRnomem));
891 /* Check that the dptr is valid */
892 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
893 return(ERROR(ERRDOS,ERRnofiles));
895 string_set(&conn->dirpath,dptr_path(dptr_num));
897 /* Get the wildcard mask from the dptr */
898 if((p = dptr_wcard(dptr_num))== NULL) {
899 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
900 return (ERROR(ERRDOS,ERRnofiles));
903 pstrcpy(directory,conn->dirpath);
905 /* Get the attr mask from the dptr */
906 dirtype = dptr_attr(dptr_num);
908 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
909 dptr_num, mask, dirtype,
911 TellDir(conn->dirptr)));
913 /* We don't need to check for VOL here as this is returned by
914 a different TRANS2 call. */
916 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
917 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
921 space_remaining = max_data_bytes;
922 out_of_space = False;
925 * Seek to the correct position. We no longer use the resume key but
926 * depend on the last file name instead.
928 if(requires_resume_key && *resume_name && !continue_bit)
931 * Fix for NT redirector problem triggered by resume key indexes
932 * changing between directory scans. We now return a resume key of 0
933 * and instead look for the filename to continue from (also given
934 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
935 * findfirst/findnext (as is usual) then the directory pointer
936 * should already be at the correct place. Check this by scanning
937 * backwards looking for an exact (ie. case sensitive) filename match.
938 * If we get to the beginning of the directory and haven't found it then scan
939 * forwards again looking for a match. JRA.
942 int current_pos, start_pos;
944 void *dirptr = conn->dirptr;
945 start_pos = TellDir(dirptr);
946 for(current_pos = start_pos; current_pos >= 0; current_pos--)
948 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
950 SeekDir(dirptr, current_pos);
951 dname = ReadDirName(dirptr);
954 * Remember, name_map_mangle is called by
955 * get_lanman2_dir_entry(), so the resume name
956 * could be mangled. Ensure we do the same
961 name_map_mangle( dname, False, SNUM(conn));
963 if(dname && strcsequal( resume_name, dname))
965 SeekDir(dirptr, current_pos+1);
966 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
972 * Scan forward from start if not found going backwards.
977 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
978 SeekDir(dirptr, start_pos);
979 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
982 * Remember, name_map_mangle is called by
983 * get_lanman2_dir_entry(), so the resume name
984 * could be mangled. Ensure we do the same
989 name_map_mangle( dname, False, SNUM(conn));
991 if(dname && strcsequal( resume_name, dname))
993 SeekDir(dirptr, current_pos+1);
994 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
998 } /* end if current_pos */
999 } /* end if requires_resume_key && !continue_bit */
1001 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1003 /* this is a heuristic to avoid seeking the dirptr except when
1004 absolutely necessary. It allows for a filename of about 40 chars */
1005 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1007 out_of_space = True;
1013 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1014 requires_resume_key,dont_descend,
1015 &p,pdata,space_remaining, &out_of_space,
1019 if (finished && out_of_space)
1022 if (!finished && !out_of_space)
1024 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1027 /* Check if we can close the dirptr */
1028 if(close_after_request || (finished && close_if_end))
1030 dptr_close(dptr_num); /* This frees up the saved mask */
1031 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1036 /* Set up the return parameter block */
1037 SSVAL(params,0,numentries);
1038 SSVAL(params,2,finished);
1039 SSVAL(params,4,0); /* Never an EA error */
1040 SSVAL(params,6,last_name_off);
1042 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1044 if ((! *directory) && dptr_path(dptr_num))
1045 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1047 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1048 smb_fn_name(CVAL(inbuf,smb_com)),
1049 mask, directory, dirtype, numentries ) );
1054 /****************************************************************************
1055 reply to a TRANS2_QFSINFO (query filesystem info)
1056 ****************************************************************************/
1058 static int call_trans2qfsinfo(connection_struct *conn,
1059 char *inbuf, char *outbuf,
1060 int length, int bufsize,
1061 char **pparams, char **ppdata)
1063 char *pdata = *ppdata;
1064 char *params = *pparams;
1065 uint16 info_level = SVAL(params,0);
1068 char *vname = volume_label(SNUM(conn));
1069 int snum = SNUM(conn);
1070 char *fstype = lp_fstype(SNUM(conn));
1071 extern uint32 global_client_caps;
1073 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1075 if(dos_stat(".",&st)!=0) {
1076 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1077 return (ERROR(ERRSRV,ERRinvdevice));
1080 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1086 SMB_BIG_UINT dfree,dsize,bsize;
1088 sys_disk_free(".",&bsize,&dfree,&dsize);
1089 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1090 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1091 SIVAL(pdata,l1_cUnit,dsize);
1092 SIVAL(pdata,l1_cUnitAvail,dfree);
1093 SSVAL(pdata,l1_cbSector,512);
1094 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1095 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1096 (unsigned int)dfree, 512));
1101 /* Return volume name */
1102 int volname_len = MIN(strlen(vname),11);
1103 data_len = l2_vol_szVolLabel + volname_len + 1;
1105 * Add volume serial number - hash of a combination of
1106 * the called hostname and the service name.
1108 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1109 SCVAL(pdata,l2_vol_cch,volname_len);
1110 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1111 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1112 (unsigned)st.st_ctime, volname_len,
1113 pdata+l2_vol_szVolLabel));
1116 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1117 data_len = 12 + 2*strlen(fstype);
1118 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1119 #if 0 /* Old code. JRA. */
1120 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1121 #endif /* Old code. */
1122 SIVAL(pdata,4,128); /* Max filename component length */
1123 SIVAL(pdata,8,2*strlen(fstype));
1124 PutUniCode(pdata+12,fstype);
1125 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1127 case SMB_QUERY_FS_LABEL_INFO:
1128 data_len = 4 + strlen(vname);
1129 SIVAL(pdata,0,strlen(vname));
1130 pstrcpy(pdata+4,vname);
1132 case SMB_QUERY_FS_VOLUME_INFO:
1135 * Add volume serial number - hash of a combination of
1136 * the called hostname and the service name.
1138 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1139 (str_checksum(local_machine)<<16));
1141 /* NT4 always serves this up as unicode but expects it to be
1142 * delivered as ascii! (tridge && JRA)
1144 if (global_client_caps & CAP_NT_SMBS) {
1145 data_len = 18 + strlen(vname);
1146 SIVAL(pdata,12,strlen(vname));
1147 pstrcpy(pdata+18,vname);
1149 data_len = 18 + 2*strlen(vname);
1150 SIVAL(pdata,12,strlen(vname)*2);
1151 PutUniCode(pdata+18,vname);
1154 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1155 strlen(vname),vname));
1157 case SMB_QUERY_FS_SIZE_INFO:
1159 SMB_BIG_UINT dfree,dsize,bsize;
1161 sys_disk_free(".",&bsize,&dfree,&dsize);
1162 SIVAL(pdata,0,dsize);
1163 SIVAL(pdata,8,dfree);
1164 SIVAL(pdata,16,bsize/512);
1165 SIVAL(pdata,20,512);
1168 case SMB_QUERY_FS_DEVICE_INFO:
1170 SIVAL(pdata,0,0); /* dev type */
1171 SIVAL(pdata,4,0); /* characteristics */
1173 case SMB_MAC_QUERY_FS_INFO:
1175 * Thursby MAC extension... ONLY on NTFS filesystems
1176 * once we do streams then we don't need this
1178 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1180 SIVAL(pdata,84,0x100); /* Don't support mac... */
1185 return(ERROR(ERRDOS,ERRunknownlevel));
1189 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1191 DEBUG( 4, ( "%s info_level = %d\n",
1192 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1197 /****************************************************************************
1198 reply to a TRANS2_SETFSINFO (set filesystem info)
1199 ****************************************************************************/
1200 static int call_trans2setfsinfo(connection_struct *conn,
1201 char *inbuf, char *outbuf, int length,
1203 char **pparams, char **ppdata)
1205 /* Just say yes we did it - there is nothing that
1206 can be set here so it doesn't matter. */
1208 DEBUG(3,("call_trans2setfsinfo\n"));
1210 if (!CAN_WRITE(conn))
1211 return(ERROR(ERRSRV,ERRaccess));
1213 outsize = set_message(outbuf,10,0,True);
1218 /****************************************************************************
1219 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1220 file name or file id).
1221 ****************************************************************************/
1223 static int call_trans2qfilepathinfo(connection_struct *conn,
1224 char *inbuf, char *outbuf, int length,
1226 char **pparams,char **ppdata,
1229 char *params = *pparams;
1230 char *pdata = *ppdata;
1231 uint16 tran_call = SVAL(inbuf, smb_setup0);
1235 unsigned int data_size;
1236 SMB_STRUCT_STAT sbuf;
1242 BOOL bad_path = False;
1244 if (tran_call == TRANSACT2_QFILEINFO) {
1245 files_struct *fsp = file_fsp(params,0);
1246 info_level = SVAL(params,2);
1248 CHECK_FSP(fsp,conn);
1251 fname = fsp->fsp_name;
1252 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1253 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1254 return(UNIXERROR(ERRDOS,ERRbadfid));
1256 if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1257 return(UNIXERROR(ERRDOS,ERRnoaccess));
1260 info_level = SVAL(params,0);
1262 pstrcpy(fname,¶ms[6]);
1263 unix_convert(fname,conn,0,&bad_path,&sbuf);
1264 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1265 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1266 if((errno == ENOENT) && bad_path)
1268 unix_ERR_class = ERRDOS;
1269 unix_ERR_code = ERRbadpath;
1271 return(UNIXERROR(ERRDOS,ERRbadpath));
1277 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1278 fname,info_level,tran_call,total_data));
1280 p = strrchr(fname,'/');
1286 mode = dos_mode(conn,fname,&sbuf);
1287 size = sbuf.st_size;
1288 if (mode & aDIR) size = 0;
1290 /* from now on we only want the part after the / */
1293 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1295 pdata = *ppdata = Realloc(*ppdata, data_size);
1297 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1298 /* uggh, EAs for OS2 */
1299 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1300 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1303 bzero(pdata,data_size);
1307 case SMB_INFO_STANDARD:
1308 case SMB_INFO_QUERY_EA_SIZE:
1309 data_size = (info_level==1?22:26);
1310 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1311 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1312 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1313 SIVAL(pdata,l1_cbFile,(uint32)size);
1314 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1315 SSVAL(pdata,l1_attrFile,mode);
1316 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1319 case SMB_INFO_QUERY_EAS_FROM_LIST:
1321 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1322 put_dos_date2(pdata,4,sbuf.st_atime);
1323 put_dos_date2(pdata,8,sbuf.st_mtime);
1324 SIVAL(pdata,12,(uint32)size);
1325 SIVAL(pdata,16,ROUNDUP(size,1024));
1326 SIVAL(pdata,20,mode);
1329 case SMB_INFO_QUERY_ALL_EAS:
1331 SIVAL(pdata,0,data_size);
1335 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1337 case SMB_QUERY_FILE_BASIC_INFO:
1338 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1339 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1340 put_long_date(pdata+8,sbuf.st_atime);
1341 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1342 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1343 SIVAL(pdata,32,mode);
1345 DEBUG(5,("SMB_QFBI - "));
1347 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1348 DEBUG(5,("create: %s ", ctime(&create_time)));
1350 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1351 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1352 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1353 DEBUG(5,("mode: %x\n", mode));
1357 case SMB_QUERY_FILE_STANDARD_INFO:
1359 SOFF_T(pdata,0,size);
1360 SOFF_T(pdata,8,size);
1361 SIVAL(pdata,16,sbuf.st_nlink);
1363 CVAL(pdata,21) = (mode&aDIR)?1:0;
1366 case SMB_QUERY_FILE_EA_INFO:
1370 /* Get the 8.3 name - used if NT SMB was negotiated. */
1371 case SMB_QUERY_FILE_ALT_NAME_INFO:
1374 pstrcpy(short_name,p);
1375 /* Mangle if not already 8.3 */
1376 if(!is_8_3(short_name, True))
1378 if(!name_map_mangle(short_name,True,SNUM(conn)))
1381 strupper(short_name);
1382 l = strlen(short_name);
1383 PutUniCode(pdata + 4, short_name);
1384 data_size = 4 + (2*l);
1389 case SMB_QUERY_FILE_NAME_INFO:
1392 pstrcpy(pdata+4,fname);
1395 case SMB_QUERY_FILE_ALLOCATION_INFO:
1396 case SMB_QUERY_FILE_END_OF_FILEINFO:
1398 SOFF_T(pdata,0,size);
1401 case SMB_QUERY_FILE_ALL_INFO:
1402 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1403 put_long_date(pdata+8,sbuf.st_atime);
1404 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1405 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1406 SIVAL(pdata,32,mode);
1408 SOFF_T(pdata,0,size);
1409 SOFF_T(pdata,8,size);
1410 SIVAL(pdata,16,sbuf.st_nlink);
1412 CVAL(pdata,21) = (mode&aDIR)?1:0;
1414 pdata += 8; /* index number */
1415 pdata += 4; /* EA info */
1417 SIVAL(pdata,0,0xA9);
1419 SIVAL(pdata,0,0xd01BF);
1421 SIVAL(pdata,0,pos); /* current offset */
1423 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1425 pdata += 4; /* alignment */
1427 pstrcpy(pdata+4,fname);
1429 data_size = PTR_DIFF(pdata,(*ppdata));
1433 /* NT4 server just returns "invalid query" to this - if we try to answer
1434 it then NTws gets a BSOD! (tridge) */
1435 case SMB_QUERY_FILE_STREAM_INFO:
1438 SIVAL(pdata,4,size);
1439 SIVAL(pdata,12,size);
1441 pstrcpy(pdata+24,fname);
1446 return(ERROR(ERRDOS,ERRunknownlevel));
1449 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1454 /****************************************************************************
1455 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1456 ****************************************************************************/
1457 static int call_trans2setfilepathinfo(connection_struct *conn,
1458 char *inbuf, char *outbuf, int length,
1459 int bufsize, char **pparams,
1460 char **ppdata, int total_data)
1462 char *params = *pparams;
1463 char *pdata = *ppdata;
1464 uint16 tran_call = SVAL(inbuf, smb_setup0);
1473 BOOL bad_path = False;
1475 if (!CAN_WRITE(conn))
1476 return(ERROR(ERRSRV,ERRaccess));
1478 if (tran_call == TRANSACT2_SETFILEINFO) {
1479 files_struct *fsp = file_fsp(params,0);
1480 info_level = SVAL(params,2);
1482 CHECK_FSP(fsp,conn);
1485 fname = fsp->fsp_name;
1486 fd = fsp->fd_ptr->fd;
1488 if(sys_fstat(fd,&st)!=0) {
1489 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1490 return(UNIXERROR(ERRDOS,ERRbadpath));
1494 info_level = SVAL(params,0);
1496 pstrcpy(fname,¶ms[6]);
1497 unix_convert(fname,conn,0,&bad_path,&st);
1498 if(!check_name(fname, conn))
1500 if((errno == ENOENT) && bad_path)
1502 unix_ERR_class = ERRDOS;
1503 unix_ERR_code = ERRbadpath;
1505 return(UNIXERROR(ERRDOS,ERRbadpath));
1508 if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
1509 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1510 if((errno == ENOENT) && bad_path)
1512 unix_ERR_class = ERRDOS;
1513 unix_ERR_code = ERRbadpath;
1515 return(UNIXERROR(ERRDOS,ERRbadpath));
1519 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1520 tran_call,fname,info_level,total_data));
1522 /* Realloc the parameter and data sizes */
1523 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1525 return(ERROR(ERRDOS,ERRnomem));
1528 tvs.modtime = st.st_mtime;
1529 tvs.actime = st.st_atime;
1530 mode = dos_mode(conn,fname,&st);
1532 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1533 /* uggh, EAs for OS2 */
1534 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1535 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1540 case SMB_INFO_STANDARD:
1541 case SMB_INFO_QUERY_EA_SIZE:
1544 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1547 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1549 mode = SVAL(pdata,l1_attrFile);
1550 size = IVAL(pdata,l1_cbFile);
1554 /* XXXX um, i don't think this is right.
1555 it's also not in the cifs6.txt spec.
1557 case SMB_INFO_QUERY_EAS_FROM_LIST:
1558 tvs.actime = make_unix_date2(pdata+8);
1559 tvs.modtime = make_unix_date2(pdata+12);
1560 size = IVAL(pdata,16);
1561 mode = IVAL(pdata,24);
1564 /* XXXX nor this. not in cifs6.txt, either. */
1565 case SMB_INFO_QUERY_ALL_EAS:
1566 tvs.actime = make_unix_date2(pdata+8);
1567 tvs.modtime = make_unix_date2(pdata+12);
1568 size = IVAL(pdata,16);
1569 mode = IVAL(pdata,24);
1572 case SMB_SET_FILE_BASIC_INFO:
1574 /* Ignore create time at offset pdata. */
1577 tvs.actime = interpret_long_date(pdata+8);
1579 /* write time + changed time, combined. */
1580 tvs.modtime=MAX(interpret_long_date(pdata+16),
1581 interpret_long_date(pdata+24));
1583 #if 0 /* Needs more testing... */
1584 /* Test from Luke to prevent Win95 from
1585 setting incorrect values here.
1587 if (tvs.actime < tvs.modtime)
1588 return(ERROR(ERRDOS,ERRnoaccess));
1589 #endif /* Needs more testing... */
1592 mode = IVAL(pdata,32);
1596 case SMB_SET_FILE_END_OF_FILE_INFO:
1598 size = IVAL(pdata,0);
1599 #ifdef LARGE_SMB_OFF_T
1600 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1601 #else /* LARGE_SMB_OFF_T */
1602 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1603 return(ERROR(ERRDOS,ERRunknownlevel));
1604 #endif /* LARGE_SMB_OFF_T */
1608 case SMB_SET_FILE_ALLOCATION_INFO:
1609 break; /* We don't need to do anything for this call. */
1611 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1613 if (tran_call == TRANSACT2_SETFILEINFO) {
1614 files_struct *fsp = file_fsp(params,0);
1615 if(fsp->is_directory)
1616 return(ERROR(ERRDOS,ERRnoaccess));
1618 * TODO - check here is this means set
1619 * this flag bit on all open files that
1620 * reference this particular dev/inode pair.
1621 * If so we'll need to search the open
1622 * file entries here and set this flag on
1623 * all of them that match. JRA.
1625 fsp->delete_on_close = CVAL(pdata,0);
1627 return(ERROR(ERRDOS,ERRunknownlevel));
1633 return(ERROR(ERRDOS,ERRunknownlevel));
1637 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1638 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1639 DEBUG(6,("size: %.0f ", (double)size));
1640 DEBUG(6,("mode: %x\n" , mode));
1642 /* get some defaults (no modifications) if any info is zero. */
1643 if (!tvs.actime) tvs.actime = st.st_atime;
1644 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1645 if (!size) size = st.st_size;
1647 /* Try and set the times, size and mode of this file -
1648 if they are different from the current values
1650 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1652 if(file_utime(conn, fname, &tvs)!=0)
1654 return(UNIXERROR(ERRDOS,ERRnoaccess));
1658 /* check the mode isn't different, before changing it */
1659 if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1661 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1662 return(UNIXERROR(ERRDOS,ERRnoaccess));
1665 if(size != st.st_size)
1669 fd = dos_open(fname,O_RDWR,0);
1672 return(UNIXERROR(ERRDOS,ERRbadpath));
1674 set_filelen(fd, size);
1679 set_filelen(fd, size);
1685 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1690 /****************************************************************************
1691 reply to a TRANS2_MKDIR (make directory with extended attributes).
1692 ****************************************************************************/
1693 static int call_trans2mkdir(connection_struct *conn,
1694 char *inbuf, char *outbuf, int length, int bufsize,
1695 char **pparams, char **ppdata)
1697 char *params = *pparams;
1700 BOOL bad_path = False;
1702 if (!CAN_WRITE(conn))
1703 return(ERROR(ERRSRV,ERRaccess));
1705 pstrcpy(directory, ¶ms[4]);
1707 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1709 unix_convert(directory,conn,0,&bad_path,NULL);
1710 if (check_name(directory,conn))
1711 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
1715 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1716 if((errno == ENOENT) && bad_path)
1718 unix_ERR_class = ERRDOS;
1719 unix_ERR_code = ERRbadpath;
1721 return(UNIXERROR(ERRDOS,ERRnoaccess));
1724 /* Realloc the parameter and data sizes */
1725 params = *pparams = Realloc(*pparams,2);
1727 return(ERROR(ERRDOS,ERRnomem));
1731 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1736 /****************************************************************************
1737 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1738 We don't actually do this - we just send a null response.
1739 ****************************************************************************/
1740 static int call_trans2findnotifyfirst(connection_struct *conn,
1741 char *inbuf, char *outbuf,
1742 int length, int bufsize,
1743 char **pparams, char **ppdata)
1745 static uint16 fnf_handle = 257;
1746 char *params = *pparams;
1747 uint16 info_level = SVAL(params,4);
1749 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1757 return(ERROR(ERRDOS,ERRunknownlevel));
1760 /* Realloc the parameter and data sizes */
1761 params = *pparams = Realloc(*pparams,6);
1763 return(ERROR(ERRDOS,ERRnomem));
1765 SSVAL(params,0,fnf_handle);
1766 SSVAL(params,2,0); /* No changes */
1767 SSVAL(params,4,0); /* No EA errors */
1774 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1779 /****************************************************************************
1780 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1781 changes). Currently this does nothing.
1782 ****************************************************************************/
1783 static int call_trans2findnotifynext(connection_struct *conn,
1784 char *inbuf, char *outbuf,
1785 int length, int bufsize,
1786 char **pparams, char **ppdata)
1788 char *params = *pparams;
1790 DEBUG(3,("call_trans2findnotifynext\n"));
1792 /* Realloc the parameter and data sizes */
1793 params = *pparams = Realloc(*pparams,4);
1795 return(ERROR(ERRDOS,ERRnomem));
1797 SSVAL(params,0,0); /* No changes */
1798 SSVAL(params,2,0); /* No EA errors */
1800 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1805 /****************************************************************************
1806 reply to a SMBfindclose (stop trans2 directory search)
1807 ****************************************************************************/
1808 int reply_findclose(connection_struct *conn,
1809 char *inbuf,char *outbuf,int length,int bufsize)
1812 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1814 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1816 dptr_close(dptr_num);
1818 outsize = set_message(outbuf,0,0,True);
1820 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1825 /****************************************************************************
1826 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1827 ****************************************************************************/
1828 int reply_findnclose(connection_struct *conn,
1829 char *inbuf,char *outbuf,int length,int bufsize)
1834 dptr_num = SVAL(inbuf,smb_vwv0);
1836 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1838 /* We never give out valid handles for a
1839 findnotifyfirst - so any dptr_num is ok here.
1842 outsize = set_message(outbuf,0,0,True);
1844 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1850 /****************************************************************************
1851 reply to a SMBtranss2 - just ignore it!
1852 ****************************************************************************/
1853 int reply_transs2(connection_struct *conn,
1854 char *inbuf,char *outbuf,int length,int bufsize)
1856 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1860 /****************************************************************************
1861 reply to a SMBtrans2
1862 ****************************************************************************/
1863 int reply_trans2(connection_struct *conn,
1864 char *inbuf,char *outbuf,int length,int bufsize)
1867 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1868 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1870 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1871 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1872 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1873 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1874 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1875 int32 timeout = IVALS(inbuf,smb_timeout);
1877 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1878 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1879 char *params = NULL, *data = NULL;
1880 int num_params, num_params_sofar, num_data, num_data_sofar;
1882 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1883 /* Queue this open message as we are the process of an
1886 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1887 DEBUGADD(2,( "in oplock break state.\n"));
1889 push_oplock_pending_smb_message(inbuf, length);
1893 outsize = set_message(outbuf,0,0,True);
1895 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1896 is so as a sanity check */
1898 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1899 return(ERROR(ERRSRV,ERRerror));
1902 /* Allocate the space for the maximum needed parameters and data */
1903 if (total_params > 0)
1904 params = (char *)malloc(total_params);
1906 data = (char *)malloc(total_data);
1908 if ((total_params && !params) || (total_data && !data)) {
1909 DEBUG(2,("Out of memory in reply_trans2\n"));
1914 return(ERROR(ERRDOS,ERRnomem));
1917 /* Copy the param and data bytes sent with this request into
1918 the params buffer */
1919 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1920 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1922 if (num_params > total_params || num_data > total_data)
1923 exit_server("invalid params in reply_trans2");
1926 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1928 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1930 if(num_data_sofar < total_data || num_params_sofar < total_params) {
1931 /* We need to send an interim response then receive the rest
1932 of the parameter/data bytes */
1933 outsize = set_message(outbuf,0,0,True);
1934 send_smb(Client,outbuf);
1936 while (num_data_sofar < total_data ||
1937 num_params_sofar < total_params) {
1940 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
1943 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
1944 outsize = set_message(outbuf,0,0,True);
1946 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1948 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1949 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1954 return(ERROR(ERRSRV,ERRerror));
1957 /* Revise total_params and total_data in case
1958 they have changed downwards */
1959 total_params = SVAL(inbuf, smb_tpscnt);
1960 total_data = SVAL(inbuf, smb_tdscnt);
1961 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1962 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1963 if (num_params_sofar > total_params || num_data_sofar > total_data)
1964 exit_server("data overflow in trans2");
1966 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1967 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1968 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1969 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1973 if (Protocol >= PROTOCOL_NT1) {
1974 uint16 flg2 = SVAL(outbuf,smb_flg2);
1975 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1978 /* Now we must call the relevant TRANS2 function */
1980 case TRANSACT2_OPEN:
1981 outsize = call_trans2open(conn,
1982 inbuf, outbuf, bufsize,
1986 case TRANSACT2_FINDFIRST:
1987 outsize = call_trans2findfirst(conn, inbuf, outbuf,
1988 bufsize, ¶ms, &data);
1991 case TRANSACT2_FINDNEXT:
1992 outsize = call_trans2findnext(conn, inbuf, outbuf,
1997 case TRANSACT2_QFSINFO:
1998 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
1999 length, bufsize, ¶ms,
2003 case TRANSACT2_SETFSINFO:
2004 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2009 case TRANSACT2_QPATHINFO:
2010 case TRANSACT2_QFILEINFO:
2011 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2013 ¶ms, &data, total_data);
2015 case TRANSACT2_SETPATHINFO:
2016 case TRANSACT2_SETFILEINFO:
2017 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2023 case TRANSACT2_FINDNOTIFYFIRST:
2024 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2029 case TRANSACT2_FINDNOTIFYNEXT:
2030 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2034 case TRANSACT2_MKDIR:
2035 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2036 bufsize, ¶ms, &data);
2039 /* Error in request */
2040 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2045 return (ERROR(ERRSRV,ERRerror));
2048 /* As we do not know how many data packets will need to be
2049 returned here the various call_trans2xxxx calls
2050 must send their own. Thus a call_trans2xxx routine only
2051 returns a value other than -1 when it wants to send
2059 return outsize; /* If a correct response was needed the
2060 call_trans2xxx calls have already sent
2061 it. If outsize != -1 then it is returning */