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|FILE_CASE_SENSITIVE_SEARCH); /* 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 if(fsp && fsp->open && fsp->is_directory) {
1250 * This is actually a QFILEINFO on a directory
1251 * handle (returned from an NT SMB). NT5.0 seems
1252 * to do this call. JRA.
1254 fname = fsp->fsp_name;
1255 unix_convert(fname,conn,0,&bad_path,&sbuf);
1256 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1257 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1258 if((errno == ENOENT) && bad_path)
1260 unix_ERR_class = ERRDOS;
1261 unix_ERR_code = ERRbadpath;
1263 return(UNIXERROR(ERRDOS,ERRbadpath));
1267 * Original code - this is an open file.
1269 CHECK_FSP(fsp,conn);
1272 fname = fsp->fsp_name;
1273 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1274 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1275 return(UNIXERROR(ERRDOS,ERRbadfid));
1277 if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1278 return(UNIXERROR(ERRDOS,ERRnoaccess));
1282 info_level = SVAL(params,0);
1284 pstrcpy(fname,¶ms[6]);
1285 unix_convert(fname,conn,0,&bad_path,&sbuf);
1286 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1287 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1288 if((errno == ENOENT) && bad_path)
1290 unix_ERR_class = ERRDOS;
1291 unix_ERR_code = ERRbadpath;
1293 return(UNIXERROR(ERRDOS,ERRbadpath));
1298 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1299 fname,info_level,tran_call,total_data));
1301 p = strrchr(fname,'/');
1307 mode = dos_mode(conn,fname,&sbuf);
1308 size = sbuf.st_size;
1309 if (mode & aDIR) size = 0;
1311 /* from now on we only want the part after the / */
1314 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1316 pdata = *ppdata = Realloc(*ppdata, data_size);
1318 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1319 /* uggh, EAs for OS2 */
1320 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1321 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1324 bzero(pdata,data_size);
1328 case SMB_INFO_STANDARD:
1329 case SMB_INFO_QUERY_EA_SIZE:
1330 data_size = (info_level==1?22:26);
1331 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1332 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1333 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1334 SIVAL(pdata,l1_cbFile,(uint32)size);
1335 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1336 SSVAL(pdata,l1_attrFile,mode);
1337 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1340 case SMB_INFO_QUERY_EAS_FROM_LIST:
1342 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1343 put_dos_date2(pdata,4,sbuf.st_atime);
1344 put_dos_date2(pdata,8,sbuf.st_mtime);
1345 SIVAL(pdata,12,(uint32)size);
1346 SIVAL(pdata,16,ROUNDUP(size,1024));
1347 SIVAL(pdata,20,mode);
1350 case SMB_INFO_QUERY_ALL_EAS:
1352 SIVAL(pdata,0,data_size);
1356 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1358 case SMB_QUERY_FILE_BASIC_INFO:
1359 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1360 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1361 put_long_date(pdata+8,sbuf.st_atime);
1362 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1363 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1364 SIVAL(pdata,32,mode);
1366 DEBUG(5,("SMB_QFBI - "));
1368 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1369 DEBUG(5,("create: %s ", ctime(&create_time)));
1371 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1372 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1373 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1374 DEBUG(5,("mode: %x\n", mode));
1378 case SMB_QUERY_FILE_STANDARD_INFO:
1380 SOFF_T(pdata,0,size);
1381 SOFF_T(pdata,8,size);
1382 SIVAL(pdata,16,sbuf.st_nlink);
1384 CVAL(pdata,21) = (mode&aDIR)?1:0;
1387 case SMB_QUERY_FILE_EA_INFO:
1391 /* Get the 8.3 name - used if NT SMB was negotiated. */
1392 case SMB_QUERY_FILE_ALT_NAME_INFO:
1395 pstrcpy(short_name,p);
1396 /* Mangle if not already 8.3 */
1397 if(!is_8_3(short_name, True))
1399 if(!name_map_mangle(short_name,True,SNUM(conn)))
1402 strupper(short_name);
1403 l = strlen(short_name);
1404 PutUniCode(pdata + 4, short_name);
1405 data_size = 4 + (2*l);
1410 case SMB_QUERY_FILE_NAME_INFO:
1413 pstrcpy(pdata+4,fname);
1416 case SMB_QUERY_FILE_ALLOCATION_INFO:
1417 case SMB_QUERY_FILE_END_OF_FILEINFO:
1419 SOFF_T(pdata,0,size);
1422 case SMB_QUERY_FILE_ALL_INFO:
1423 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1424 put_long_date(pdata+8,sbuf.st_atime);
1425 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1426 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1427 SIVAL(pdata,32,mode);
1429 SOFF_T(pdata,0,size);
1430 SOFF_T(pdata,8,size);
1431 SIVAL(pdata,16,sbuf.st_nlink);
1433 CVAL(pdata,21) = (mode&aDIR)?1:0;
1435 pdata += 8; /* index number */
1436 pdata += 4; /* EA info */
1438 SIVAL(pdata,0,0xA9);
1440 SIVAL(pdata,0,0xd01BF);
1442 SIVAL(pdata,0,pos); /* current offset */
1444 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1446 pdata += 4; /* alignment */
1448 pstrcpy(pdata+4,fname);
1450 data_size = PTR_DIFF(pdata,(*ppdata));
1454 /* NT4 server just returns "invalid query" to this - if we try to answer
1455 it then NTws gets a BSOD! (tridge) */
1456 case SMB_QUERY_FILE_STREAM_INFO:
1459 SIVAL(pdata,4,size);
1460 SIVAL(pdata,12,size);
1462 pstrcpy(pdata+24,fname);
1467 return(ERROR(ERRDOS,ERRunknownlevel));
1470 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1475 /****************************************************************************
1476 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1477 ****************************************************************************/
1478 static int call_trans2setfilepathinfo(connection_struct *conn,
1479 char *inbuf, char *outbuf, int length,
1480 int bufsize, char **pparams,
1481 char **ppdata, int total_data)
1483 char *params = *pparams;
1484 char *pdata = *ppdata;
1485 uint16 tran_call = SVAL(inbuf, smb_setup0);
1494 BOOL bad_path = False;
1496 if (!CAN_WRITE(conn))
1497 return(ERROR(ERRSRV,ERRaccess));
1499 if (tran_call == TRANSACT2_SETFILEINFO) {
1500 files_struct *fsp = file_fsp(params,0);
1501 info_level = SVAL(params,2);
1503 if(fsp && fsp->open && fsp->is_directory) {
1505 * This is actually a SETFILEINFO on a directory
1506 * handle (returned from an NT SMB). NT5.0 seems
1507 * to do this call. JRA.
1509 fname = fsp->fsp_name;
1510 unix_convert(fname,conn,0,&bad_path,&st);
1511 if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) {
1512 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1513 if((errno == ENOENT) && bad_path)
1515 unix_ERR_class = ERRDOS;
1516 unix_ERR_code = ERRbadpath;
1518 return(UNIXERROR(ERRDOS,ERRbadpath));
1522 * Original code - this is an open file.
1524 CHECK_FSP(fsp,conn);
1527 fname = fsp->fsp_name;
1528 fd = fsp->fd_ptr->fd;
1530 if (sys_fstat(fd,&st) != 0) {
1531 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1532 return(UNIXERROR(ERRDOS,ERRbadfid));
1537 info_level = SVAL(params,0);
1539 pstrcpy(fname,¶ms[6]);
1540 unix_convert(fname,conn,0,&bad_path,&st);
1541 if(!check_name(fname, conn))
1543 if((errno == ENOENT) && bad_path)
1545 unix_ERR_class = ERRDOS;
1546 unix_ERR_code = ERRbadpath;
1548 return(UNIXERROR(ERRDOS,ERRbadpath));
1551 if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
1552 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1553 if((errno == ENOENT) && bad_path)
1555 unix_ERR_class = ERRDOS;
1556 unix_ERR_code = ERRbadpath;
1558 return(UNIXERROR(ERRDOS,ERRbadpath));
1562 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1563 tran_call,fname,info_level,total_data));
1565 /* Realloc the parameter and data sizes */
1566 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1568 return(ERROR(ERRDOS,ERRnomem));
1571 tvs.modtime = st.st_mtime;
1572 tvs.actime = st.st_atime;
1573 mode = dos_mode(conn,fname,&st);
1575 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1576 /* uggh, EAs for OS2 */
1577 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1578 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1583 case SMB_INFO_STANDARD:
1584 case SMB_INFO_QUERY_EA_SIZE:
1587 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1590 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1592 mode = SVAL(pdata,l1_attrFile);
1593 size = IVAL(pdata,l1_cbFile);
1597 /* XXXX um, i don't think this is right.
1598 it's also not in the cifs6.txt spec.
1600 case SMB_INFO_QUERY_EAS_FROM_LIST:
1601 tvs.actime = make_unix_date2(pdata+8);
1602 tvs.modtime = make_unix_date2(pdata+12);
1603 size = IVAL(pdata,16);
1604 mode = IVAL(pdata,24);
1607 /* XXXX nor this. not in cifs6.txt, either. */
1608 case SMB_INFO_QUERY_ALL_EAS:
1609 tvs.actime = make_unix_date2(pdata+8);
1610 tvs.modtime = make_unix_date2(pdata+12);
1611 size = IVAL(pdata,16);
1612 mode = IVAL(pdata,24);
1615 case SMB_SET_FILE_BASIC_INFO:
1617 /* Ignore create time at offset pdata. */
1620 tvs.actime = interpret_long_date(pdata+8);
1622 /* write time + changed time, combined. */
1623 tvs.modtime=MAX(interpret_long_date(pdata+16),
1624 interpret_long_date(pdata+24));
1626 #if 0 /* Needs more testing... */
1627 /* Test from Luke to prevent Win95 from
1628 setting incorrect values here.
1630 if (tvs.actime < tvs.modtime)
1631 return(ERROR(ERRDOS,ERRnoaccess));
1632 #endif /* Needs more testing... */
1635 mode = IVAL(pdata,32);
1639 case SMB_SET_FILE_END_OF_FILE_INFO:
1641 size = IVAL(pdata,0);
1642 #ifdef LARGE_SMB_OFF_T
1643 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1644 #else /* LARGE_SMB_OFF_T */
1645 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1646 return(ERROR(ERRDOS,ERRunknownlevel));
1647 #endif /* LARGE_SMB_OFF_T */
1651 case SMB_SET_FILE_ALLOCATION_INFO:
1652 break; /* We don't need to do anything for this call. */
1654 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1656 if (tran_call == TRANSACT2_SETFILEINFO) {
1657 files_struct *fsp = file_fsp(params,0);
1658 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1660 if(fsp->is_directory)
1661 return(ERROR(ERRDOS,ERRnoaccess));
1664 * We can only set the delete on close flag if
1665 * the share mode contained ALLOW_SHARE_DELETE
1668 if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1669 return(ERROR(ERRDOS,ERRnoaccess));
1672 * If the flag has changed from its previous value then
1673 * modify the share mode entry for all files we have open
1674 * on this device and inode to tell other smbds we have
1675 * changed the delete on close flag.
1678 if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close)
1681 files_struct *iterate_fsp;
1682 SMB_DEV_T dev = fsp->fd_ptr->dev;
1683 SMB_INO_T inode = fsp->fd_ptr->inode;
1685 DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1686 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1688 if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1689 return(ERROR(ERRDOS,ERRnoaccess));
1692 * Go through all files we have open on the same device and
1693 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1696 for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1697 iterate_fsp = file_find_di_next(iterate_fsp))
1699 int new_share_mode = (delete_on_close ?
1700 (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1701 (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1703 DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\
1704 dev = %x, inode = %.0f from %x to %x\n",
1705 iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
1706 (double)inode, iterate_fsp->share_mode, new_share_mode ));
1708 if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1709 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1710 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1713 unlock_share_entry(fsp->conn, dev, inode, token);
1717 * Set the delete on close flag in the reference
1718 * counted struct. Delete when the last reference
1721 fsp->fd_ptr->delete_on_close = delete_on_close;
1723 return(ERROR(ERRDOS,ERRunknownlevel));
1729 return(ERROR(ERRDOS,ERRunknownlevel));
1733 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1734 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1735 DEBUG(6,("size: %.0f ", (double)size));
1736 DEBUG(6,("mode: %x\n" , mode));
1738 /* get some defaults (no modifications) if any info is zero. */
1739 if (!tvs.actime) tvs.actime = st.st_atime;
1740 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1741 if (!size) size = st.st_size;
1743 /* Try and set the times, size and mode of this file -
1744 if they are different from the current values
1746 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1748 if(file_utime(conn, fname, &tvs)!=0)
1750 return(UNIXERROR(ERRDOS,ERRnoaccess));
1754 /* check the mode isn't different, before changing it */
1755 if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1757 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1758 return(UNIXERROR(ERRDOS,ERRnoaccess));
1761 if(size != st.st_size)
1765 fd = dos_open(fname,O_RDWR,0);
1768 return(UNIXERROR(ERRDOS,ERRbadpath));
1770 set_filelen(fd, size);
1775 set_filelen(fd, size);
1781 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1786 /****************************************************************************
1787 reply to a TRANS2_MKDIR (make directory with extended attributes).
1788 ****************************************************************************/
1789 static int call_trans2mkdir(connection_struct *conn,
1790 char *inbuf, char *outbuf, int length, int bufsize,
1791 char **pparams, char **ppdata)
1793 char *params = *pparams;
1796 BOOL bad_path = False;
1798 if (!CAN_WRITE(conn))
1799 return(ERROR(ERRSRV,ERRaccess));
1801 pstrcpy(directory, ¶ms[4]);
1803 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1805 unix_convert(directory,conn,0,&bad_path,NULL);
1806 if (check_name(directory,conn))
1807 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
1811 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1812 if((errno == ENOENT) && bad_path)
1814 unix_ERR_class = ERRDOS;
1815 unix_ERR_code = ERRbadpath;
1817 return(UNIXERROR(ERRDOS,ERRnoaccess));
1820 /* Realloc the parameter and data sizes */
1821 params = *pparams = Realloc(*pparams,2);
1823 return(ERROR(ERRDOS,ERRnomem));
1827 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1832 /****************************************************************************
1833 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1834 We don't actually do this - we just send a null response.
1835 ****************************************************************************/
1836 static int call_trans2findnotifyfirst(connection_struct *conn,
1837 char *inbuf, char *outbuf,
1838 int length, int bufsize,
1839 char **pparams, char **ppdata)
1841 static uint16 fnf_handle = 257;
1842 char *params = *pparams;
1843 uint16 info_level = SVAL(params,4);
1845 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1853 return(ERROR(ERRDOS,ERRunknownlevel));
1856 /* Realloc the parameter and data sizes */
1857 params = *pparams = Realloc(*pparams,6);
1859 return(ERROR(ERRDOS,ERRnomem));
1861 SSVAL(params,0,fnf_handle);
1862 SSVAL(params,2,0); /* No changes */
1863 SSVAL(params,4,0); /* No EA errors */
1870 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1875 /****************************************************************************
1876 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1877 changes). Currently this does nothing.
1878 ****************************************************************************/
1879 static int call_trans2findnotifynext(connection_struct *conn,
1880 char *inbuf, char *outbuf,
1881 int length, int bufsize,
1882 char **pparams, char **ppdata)
1884 char *params = *pparams;
1886 DEBUG(3,("call_trans2findnotifynext\n"));
1888 /* Realloc the parameter and data sizes */
1889 params = *pparams = Realloc(*pparams,4);
1891 return(ERROR(ERRDOS,ERRnomem));
1893 SSVAL(params,0,0); /* No changes */
1894 SSVAL(params,2,0); /* No EA errors */
1896 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1901 /****************************************************************************
1902 reply to a SMBfindclose (stop trans2 directory search)
1903 ****************************************************************************/
1904 int reply_findclose(connection_struct *conn,
1905 char *inbuf,char *outbuf,int length,int bufsize)
1908 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1910 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1912 dptr_close(dptr_num);
1914 outsize = set_message(outbuf,0,0,True);
1916 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1921 /****************************************************************************
1922 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1923 ****************************************************************************/
1924 int reply_findnclose(connection_struct *conn,
1925 char *inbuf,char *outbuf,int length,int bufsize)
1930 dptr_num = SVAL(inbuf,smb_vwv0);
1932 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1934 /* We never give out valid handles for a
1935 findnotifyfirst - so any dptr_num is ok here.
1938 outsize = set_message(outbuf,0,0,True);
1940 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1946 /****************************************************************************
1947 reply to a SMBtranss2 - just ignore it!
1948 ****************************************************************************/
1949 int reply_transs2(connection_struct *conn,
1950 char *inbuf,char *outbuf,int length,int bufsize)
1952 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1956 /****************************************************************************
1957 reply to a SMBtrans2
1958 ****************************************************************************/
1959 int reply_trans2(connection_struct *conn,
1960 char *inbuf,char *outbuf,int length,int bufsize)
1963 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1964 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1966 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1967 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1968 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1969 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1970 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1971 int32 timeout = IVALS(inbuf,smb_timeout);
1973 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1974 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1975 char *params = NULL, *data = NULL;
1976 int num_params, num_params_sofar, num_data, num_data_sofar;
1978 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1979 /* Queue this open message as we are the process of an
1982 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1983 DEBUGADD(2,( "in oplock break state.\n"));
1985 push_oplock_pending_smb_message(inbuf, length);
1989 outsize = set_message(outbuf,0,0,True);
1991 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1992 is so as a sanity check */
1994 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1995 return(ERROR(ERRSRV,ERRerror));
1998 /* Allocate the space for the maximum needed parameters and data */
1999 if (total_params > 0)
2000 params = (char *)malloc(total_params);
2002 data = (char *)malloc(total_data);
2004 if ((total_params && !params) || (total_data && !data)) {
2005 DEBUG(2,("Out of memory in reply_trans2\n"));
2010 return(ERROR(ERRDOS,ERRnomem));
2013 /* Copy the param and data bytes sent with this request into
2014 the params buffer */
2015 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2016 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2018 if (num_params > total_params || num_data > total_data)
2019 exit_server("invalid params in reply_trans2");
2022 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2024 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2026 if(num_data_sofar < total_data || num_params_sofar < total_params) {
2027 /* We need to send an interim response then receive the rest
2028 of the parameter/data bytes */
2029 outsize = set_message(outbuf,0,0,True);
2030 send_smb(Client,outbuf);
2032 while (num_data_sofar < total_data ||
2033 num_params_sofar < total_params) {
2036 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2039 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2040 outsize = set_message(outbuf,0,0,True);
2042 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2044 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2045 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2050 return(ERROR(ERRSRV,ERRerror));
2053 /* Revise total_params and total_data in case
2054 they have changed downwards */
2055 total_params = SVAL(inbuf, smb_tpscnt);
2056 total_data = SVAL(inbuf, smb_tdscnt);
2057 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2058 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2059 if (num_params_sofar > total_params || num_data_sofar > total_data)
2060 exit_server("data overflow in trans2");
2062 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
2063 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2064 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2065 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2069 if (Protocol >= PROTOCOL_NT1) {
2070 uint16 flg2 = SVAL(outbuf,smb_flg2);
2071 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2074 /* Now we must call the relevant TRANS2 function */
2076 case TRANSACT2_OPEN:
2077 outsize = call_trans2open(conn,
2078 inbuf, outbuf, bufsize,
2082 case TRANSACT2_FINDFIRST:
2083 outsize = call_trans2findfirst(conn, inbuf, outbuf,
2084 bufsize, ¶ms, &data);
2087 case TRANSACT2_FINDNEXT:
2088 outsize = call_trans2findnext(conn, inbuf, outbuf,
2093 case TRANSACT2_QFSINFO:
2094 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
2095 length, bufsize, ¶ms,
2099 case TRANSACT2_SETFSINFO:
2100 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2105 case TRANSACT2_QPATHINFO:
2106 case TRANSACT2_QFILEINFO:
2107 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2109 ¶ms, &data, total_data);
2111 case TRANSACT2_SETPATHINFO:
2112 case TRANSACT2_SETFILEINFO:
2113 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2119 case TRANSACT2_FINDNOTIFYFIRST:
2120 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2125 case TRANSACT2_FINDNOTIFYNEXT:
2126 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2130 case TRANSACT2_MKDIR:
2131 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2132 bufsize, ¶ms, &data);
2135 /* Error in request */
2136 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2141 return (ERROR(ERRSRV,ERRerror));
2144 /* As we do not know how many data packets will need to be
2145 returned here the various call_trans2xxxx calls
2146 must send their own. Thus a call_trans2xxx routine only
2147 returns a value other than -1 when it wants to send
2155 return outsize; /* If a correct response was needed the
2156 call_trans2xxx calls have already sent
2157 it. If outsize != -1 then it is returning */