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 (fsp->conn->vfs_ops.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 (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&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,SMB_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,SMB_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,SMB_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,SMB_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(conn->vfs_ops.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 conn->vfs_ops.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 ascii_to_unibuf(pdata+12, fstype, 1024-2-12);
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 ascii_to_unibuf(pdata+18, vname, 1024-2-18);
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 conn->vfs_ops.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;
1243 BOOL delete_pending = False;
1245 if (tran_call == TRANSACT2_QFILEINFO) {
1246 files_struct *fsp = file_fsp(params,0);
1247 info_level = SVAL(params,2);
1249 if(fsp && fsp->open && fsp->is_directory) {
1251 * This is actually a QFILEINFO on a directory
1252 * handle (returned from an NT SMB). NT5.0 seems
1253 * to do this call. JRA.
1255 fname = fsp->fsp_name;
1256 unix_convert(fname,conn,0,&bad_path,&sbuf);
1257 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) &&
1258 conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
1259 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1260 if((errno == ENOENT) && bad_path)
1262 unix_ERR_class = ERRDOS;
1263 unix_ERR_code = ERRbadpath;
1265 return(UNIXERROR(ERRDOS,ERRbadpath));
1269 * Original code - this is an open file.
1271 CHECK_FSP(fsp,conn);
1274 fname = fsp->fsp_name;
1275 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1276 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1277 return(UNIXERROR(ERRDOS,ERRbadfid));
1279 if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1280 return(UNIXERROR(ERRDOS,ERRnoaccess));
1282 delete_pending = fsp->fd_ptr->delete_on_close;
1286 info_level = SVAL(params,0);
1288 pstrcpy(fname,¶ms[6]);
1289 unix_convert(fname,conn,0,&bad_path,&sbuf);
1290 if (!check_name(fname,conn) ||
1291 (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),
1293 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1294 if((errno == ENOENT) && bad_path)
1296 unix_ERR_class = ERRDOS;
1297 unix_ERR_code = ERRbadpath;
1299 return(UNIXERROR(ERRDOS,ERRbadpath));
1304 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1305 fname,info_level,tran_call,total_data));
1307 p = strrchr(fname,'/');
1313 mode = dos_mode(conn,fname,&sbuf);
1314 size = sbuf.st_size;
1315 if (mode & aDIR) size = 0;
1317 /* from now on we only want the part after the / */
1320 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1322 pdata = *ppdata = Realloc(*ppdata, data_size);
1324 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1325 /* uggh, EAs for OS2 */
1326 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1327 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1330 bzero(pdata,data_size);
1334 case SMB_INFO_STANDARD:
1335 case SMB_INFO_QUERY_EA_SIZE:
1336 data_size = (info_level==1?22:26);
1337 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1338 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1339 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1340 SIVAL(pdata,l1_cbFile,(uint32)size);
1341 SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1342 SSVAL(pdata,l1_attrFile,mode);
1343 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1346 case SMB_INFO_QUERY_EAS_FROM_LIST:
1348 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1349 put_dos_date2(pdata,4,sbuf.st_atime);
1350 put_dos_date2(pdata,8,sbuf.st_mtime);
1351 SIVAL(pdata,12,(uint32)size);
1352 SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1353 SIVAL(pdata,20,mode);
1356 case SMB_INFO_QUERY_ALL_EAS:
1358 SIVAL(pdata,0,data_size);
1362 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1364 case SMB_QUERY_FILE_BASIC_INFO:
1365 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1366 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1367 put_long_date(pdata+8,sbuf.st_atime);
1368 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1369 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1370 SIVAL(pdata,32,mode);
1372 DEBUG(5,("SMB_QFBI - "));
1374 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1375 DEBUG(5,("create: %s ", ctime(&create_time)));
1377 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1378 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1379 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1380 DEBUG(5,("mode: %x\n", mode));
1384 case SMB_QUERY_FILE_STANDARD_INFO:
1386 SOFF_T(pdata,0,size);
1387 SOFF_T(pdata,8,size);
1388 SIVAL(pdata,16,sbuf.st_nlink);
1390 CVAL(pdata,21) = (mode&aDIR)?1:0;
1393 case SMB_QUERY_FILE_EA_INFO:
1397 /* Get the 8.3 name - used if NT SMB was negotiated. */
1398 case SMB_QUERY_FILE_ALT_NAME_INFO:
1403 pstrcpy(short_name,p);
1404 /* Mangle if not already 8.3 */
1405 if(!is_8_3(short_name, True))
1407 if(!name_map_mangle(short_name,True,SNUM(conn)))
1410 strupper(short_name);
1411 data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4);
1412 data_size = data_end - pdata;
1413 SIVAL(pdata,0,2*(data_size-4));
1417 case SMB_QUERY_FILE_NAME_INFO:
1420 pstrcpy(pdata+4,fname);
1423 case SMB_QUERY_FILE_ALLOCATION_INFO:
1424 case SMB_QUERY_FILE_END_OF_FILEINFO:
1426 SOFF_T(pdata,0,size);
1429 case SMB_QUERY_FILE_ALL_INFO:
1430 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1431 put_long_date(pdata+8,sbuf.st_atime);
1432 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1433 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1434 SIVAL(pdata,32,mode);
1436 SOFF_T(pdata,0,size);
1437 SOFF_T(pdata,8,size);
1438 SIVAL(pdata,16,sbuf.st_nlink);
1439 CVAL(pdata,20) = delete_pending;
1440 CVAL(pdata,21) = (mode&aDIR)?1:0;
1442 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1443 pdata += 8; /* index number */
1444 pdata += 4; /* EA info */
1446 SIVAL(pdata,0,0xA9);
1448 SIVAL(pdata,0,0xd01BF);
1450 SOFF_T(pdata,0,pos); /* current offset */
1452 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1454 pdata += 4; /* alignment */
1456 pstrcpy(pdata+4,fname);
1458 data_size = PTR_DIFF(pdata,(*ppdata));
1462 /* NT4 server just returns "invalid query" to this - if we try to answer
1463 it then NTws gets a BSOD! (tridge) */
1464 case SMB_QUERY_FILE_STREAM_INFO:
1467 SIVAL(pdata,4,size);
1468 SIVAL(pdata,12,size);
1470 pstrcpy(pdata+24,fname);
1475 return(ERROR(ERRDOS,ERRunknownlevel));
1478 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1483 /****************************************************************************
1484 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1485 ****************************************************************************/
1486 static int call_trans2setfilepathinfo(connection_struct *conn,
1487 char *inbuf, char *outbuf, int length,
1488 int bufsize, char **pparams,
1489 char **ppdata, int total_data)
1491 char *params = *pparams;
1492 char *pdata = *ppdata;
1493 uint16 tran_call = SVAL(inbuf, smb_setup0);
1502 BOOL bad_path = False;
1503 files_struct *fsp = NULL;
1505 if (!CAN_WRITE(conn))
1506 return(ERROR(ERRSRV,ERRaccess));
1508 if (tran_call == TRANSACT2_SETFILEINFO) {
1509 fsp = file_fsp(params,0);
1510 info_level = SVAL(params,2);
1512 if(fsp && fsp->open && fsp->is_directory) {
1514 * This is actually a SETFILEINFO on a directory
1515 * handle (returned from an NT SMB). NT5.0 seems
1516 * to do this call. JRA.
1518 fname = fsp->fsp_name;
1519 unix_convert(fname,conn,0,&bad_path,&st);
1520 if (!check_name(fname,conn) || (!VALID_STAT(st) &&
1521 conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
1522 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1523 if((errno == ENOENT) && bad_path)
1525 unix_ERR_class = ERRDOS;
1526 unix_ERR_code = ERRbadpath;
1528 return(UNIXERROR(ERRDOS,ERRbadpath));
1532 * Original code - this is an open file.
1534 CHECK_FSP(fsp,conn);
1537 fname = fsp->fsp_name;
1538 fd = fsp->fd_ptr->fd;
1540 if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
1541 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1542 return(UNIXERROR(ERRDOS,ERRbadfid));
1547 info_level = SVAL(params,0);
1549 pstrcpy(fname,¶ms[6]);
1550 unix_convert(fname,conn,0,&bad_path,&st);
1551 if(!check_name(fname, conn))
1553 if((errno == ENOENT) && bad_path)
1555 unix_ERR_class = ERRDOS;
1556 unix_ERR_code = ERRbadpath;
1558 return(UNIXERROR(ERRDOS,ERRbadpath));
1561 if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
1562 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1563 if((errno == ENOENT) && bad_path)
1565 unix_ERR_class = ERRDOS;
1566 unix_ERR_code = ERRbadpath;
1568 return(UNIXERROR(ERRDOS,ERRbadpath));
1572 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1573 tran_call,fname,info_level,total_data));
1575 /* Realloc the parameter and data sizes */
1576 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1578 return(ERROR(ERRDOS,ERRnomem));
1581 tvs.modtime = st.st_mtime;
1582 tvs.actime = st.st_atime;
1583 mode = dos_mode(conn,fname,&st);
1585 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1586 /* uggh, EAs for OS2 */
1587 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1588 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1593 case SMB_INFO_STANDARD:
1594 case SMB_INFO_QUERY_EA_SIZE:
1597 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1600 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1602 mode = SVAL(pdata,l1_attrFile);
1603 size = IVAL(pdata,l1_cbFile);
1607 /* XXXX um, i don't think this is right.
1608 it's also not in the cifs6.txt spec.
1610 case SMB_INFO_QUERY_EAS_FROM_LIST:
1611 tvs.actime = make_unix_date2(pdata+8);
1612 tvs.modtime = make_unix_date2(pdata+12);
1613 size = IVAL(pdata,16);
1614 mode = IVAL(pdata,24);
1617 /* XXXX nor this. not in cifs6.txt, either. */
1618 case SMB_INFO_QUERY_ALL_EAS:
1619 tvs.actime = make_unix_date2(pdata+8);
1620 tvs.modtime = make_unix_date2(pdata+12);
1621 size = IVAL(pdata,16);
1622 mode = IVAL(pdata,24);
1625 case SMB_SET_FILE_BASIC_INFO:
1627 /* Ignore create time at offset pdata. */
1630 tvs.actime = interpret_long_date(pdata+8);
1632 /* write time + changed time, combined. */
1633 tvs.modtime=MAX(interpret_long_date(pdata+16),
1634 interpret_long_date(pdata+24));
1636 #if 0 /* Needs more testing... */
1637 /* Test from Luke to prevent Win95 from
1638 setting incorrect values here.
1640 if (tvs.actime < tvs.modtime)
1641 return(ERROR(ERRDOS,ERRnoaccess));
1642 #endif /* Needs more testing... */
1645 mode = IVAL(pdata,32);
1649 case SMB_SET_FILE_END_OF_FILE_INFO:
1651 size = IVAL(pdata,0);
1652 #ifdef LARGE_SMB_OFF_T
1653 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1654 #else /* LARGE_SMB_OFF_T */
1655 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1656 return(ERROR(ERRDOS,ERRunknownlevel));
1657 #endif /* LARGE_SMB_OFF_T */
1661 case SMB_SET_FILE_ALLOCATION_INFO:
1662 break; /* We don't need to do anything for this call. */
1664 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1666 if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1668 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1670 if(fsp->is_directory)
1671 return(ERROR(ERRDOS,ERRnoaccess));
1674 * We can only set the delete on close flag if
1675 * the share mode contained ALLOW_SHARE_DELETE
1678 if(lp_share_modes(SNUM(conn)))
1680 if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1681 return(ERROR(ERRDOS,ERRnoaccess));
1684 * If the flag has been set then
1685 * modify the share mode entry for all files we have open
1686 * on this device and inode to tell other smbds we have
1687 * changed the delete on close flag.
1690 if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1694 files_struct *iterate_fsp;
1695 SMB_DEV_T dev = fsp->fd_ptr->dev;
1696 SMB_INO_T inode = fsp->fd_ptr->inode;
1697 int num_share_modes;
1698 share_mode_entry *current_shares = NULL;
1700 if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1701 return(ERROR(ERRDOS,ERRnoaccess));
1704 * Before we allow this we need to ensure that all current opens
1705 * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1706 * do not then we deny this (as we are essentially deleting the
1707 * file at this point.
1710 num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares);
1711 for(i = 0; i < num_share_modes; i++)
1713 if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1715 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1716 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1717 fsp->fnum, fsp->fsp_name ));
1722 unlock_share_entry(fsp->conn, dev, inode, token);
1725 * current_shares was malloced by get_share_modes - free it here.
1728 free((char *)current_shares);
1731 * Even though share violation would be more appropriate here,
1732 * return ERRnoaccess as that's what NT does.
1735 return(ERROR(ERRDOS,ERRnoaccess));
1740 * current_shares was malloced by get_share_modes - free it here.
1743 free((char *)current_shares);
1745 DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1746 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1749 * Go through all files we have open on the same device and
1750 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1751 * Other smbd's that have this file open will have to fend for themselves. We
1752 * take care of this (rare) case in close_file(). See the comment there.
1755 for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1756 iterate_fsp = file_find_di_next(iterate_fsp))
1758 int new_share_mode = (delete_on_close ?
1759 (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1760 (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1762 DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1763 dev = %x, inode = %.0f from %x to %x\n",
1764 iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
1765 (double)inode, iterate_fsp->share_mode, new_share_mode ));
1767 if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1768 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1769 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1773 * Set the delete on close flag in the reference
1774 * counted struct. Delete when the last reference
1777 fsp->fd_ptr->delete_on_close = delete_on_close;
1778 unlock_share_entry(fsp->conn, dev, inode, token);
1780 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1781 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1783 } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1784 } /* end if lp_share_modes() */
1787 return(ERROR(ERRDOS,ERRunknownlevel));
1793 return(ERROR(ERRDOS,ERRunknownlevel));
1797 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1798 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1799 DEBUG(6,("size: %.0f ", (double)size));
1800 DEBUG(6,("mode: %x\n" , mode));
1802 /* get some defaults (no modifications) if any info is zero. */
1803 if (!tvs.actime) tvs.actime = st.st_atime;
1804 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1805 if (!size) size = st.st_size;
1807 /* Try and set the times, size and mode of this file -
1808 if they are different from the current values
1810 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1815 * This was a setfileinfo on an open file.
1816 * NT does this a lot. It's actually pointless
1817 * setting the time here, as it will be overwritten
1818 * on the next write, so we save the request
1819 * away and will set it on file code. JRA.
1821 fsp->pending_modtime = tvs.modtime;
1823 else if(file_utime(conn, fname, &tvs)!=0)
1825 return(UNIXERROR(ERRDOS,ERRnoaccess));
1829 /* check the mode isn't different, before changing it */
1830 if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1832 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1833 return(UNIXERROR(ERRDOS,ERRnoaccess));
1836 if(size != st.st_size)
1840 DEBUG(0, ("@@@ 23 @@@\n"));
1841 fd = dos_open(fname,O_RDWR,0);
1844 return(UNIXERROR(ERRDOS,ERRbadpath));
1846 set_filelen(fd, size);
1851 set_filelen(fd, size);
1857 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1862 /****************************************************************************
1863 reply to a TRANS2_MKDIR (make directory with extended attributes).
1864 ****************************************************************************/
1865 static int call_trans2mkdir(connection_struct *conn,
1866 char *inbuf, char *outbuf, int length, int bufsize,
1867 char **pparams, char **ppdata)
1869 char *params = *pparams;
1872 BOOL bad_path = False;
1874 if (!CAN_WRITE(conn))
1875 return(ERROR(ERRSRV,ERRaccess));
1877 pstrcpy(directory, ¶ms[4]);
1879 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1881 unix_convert(directory,conn,0,&bad_path,NULL);
1882 if (check_name(directory,conn))
1883 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
1884 unix_mode(conn,aDIR));
1888 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1889 if((errno == ENOENT) && bad_path)
1891 unix_ERR_class = ERRDOS;
1892 unix_ERR_code = ERRbadpath;
1894 return(UNIXERROR(ERRDOS,ERRnoaccess));
1897 /* Realloc the parameter and data sizes */
1898 params = *pparams = Realloc(*pparams,2);
1900 return(ERROR(ERRDOS,ERRnomem));
1904 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1909 /****************************************************************************
1910 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1911 We don't actually do this - we just send a null response.
1912 ****************************************************************************/
1913 static int call_trans2findnotifyfirst(connection_struct *conn,
1914 char *inbuf, char *outbuf,
1915 int length, int bufsize,
1916 char **pparams, char **ppdata)
1918 static uint16 fnf_handle = 257;
1919 char *params = *pparams;
1920 uint16 info_level = SVAL(params,4);
1922 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1930 return(ERROR(ERRDOS,ERRunknownlevel));
1933 /* Realloc the parameter and data sizes */
1934 params = *pparams = Realloc(*pparams,6);
1936 return(ERROR(ERRDOS,ERRnomem));
1938 SSVAL(params,0,fnf_handle);
1939 SSVAL(params,2,0); /* No changes */
1940 SSVAL(params,4,0); /* No EA errors */
1947 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1952 /****************************************************************************
1953 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1954 changes). Currently this does nothing.
1955 ****************************************************************************/
1956 static int call_trans2findnotifynext(connection_struct *conn,
1957 char *inbuf, char *outbuf,
1958 int length, int bufsize,
1959 char **pparams, char **ppdata)
1961 char *params = *pparams;
1963 DEBUG(3,("call_trans2findnotifynext\n"));
1965 /* Realloc the parameter and data sizes */
1966 params = *pparams = Realloc(*pparams,4);
1968 return(ERROR(ERRDOS,ERRnomem));
1970 SSVAL(params,0,0); /* No changes */
1971 SSVAL(params,2,0); /* No EA errors */
1973 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1978 /****************************************************************************
1979 reply to a SMBfindclose (stop trans2 directory search)
1980 ****************************************************************************/
1981 int reply_findclose(connection_struct *conn,
1982 char *inbuf,char *outbuf,int length,int bufsize)
1985 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1987 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1989 dptr_close(dptr_num);
1991 outsize = set_message(outbuf,0,0,True);
1993 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1998 /****************************************************************************
1999 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2000 ****************************************************************************/
2001 int reply_findnclose(connection_struct *conn,
2002 char *inbuf,char *outbuf,int length,int bufsize)
2007 dptr_num = SVAL(inbuf,smb_vwv0);
2009 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2011 /* We never give out valid handles for a
2012 findnotifyfirst - so any dptr_num is ok here.
2015 outsize = set_message(outbuf,0,0,True);
2017 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2023 /****************************************************************************
2024 reply to a SMBtranss2 - just ignore it!
2025 ****************************************************************************/
2026 int reply_transs2(connection_struct *conn,
2027 char *inbuf,char *outbuf,int length,int bufsize)
2029 DEBUG(4,("Ignoring transs2 of length %d\n",length));
2033 /****************************************************************************
2034 reply to a SMBtrans2
2035 ****************************************************************************/
2036 int reply_trans2(connection_struct *conn,
2037 char *inbuf,char *outbuf,int length,int bufsize)
2040 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2041 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2043 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2044 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2045 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2046 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2047 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2048 int32 timeout = IVALS(inbuf,smb_timeout);
2050 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2051 unsigned int tran_call = SVAL(inbuf, smb_setup0);
2052 char *params = NULL, *data = NULL;
2053 int num_params, num_params_sofar, num_data, num_data_sofar;
2055 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2056 /* Queue this open message as we are the process of an
2059 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2060 DEBUGADD(2,( "in oplock break state.\n"));
2062 push_oplock_pending_smb_message(inbuf, length);
2066 outsize = set_message(outbuf,0,0,True);
2068 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2069 is so as a sanity check */
2071 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2072 return(ERROR(ERRSRV,ERRerror));
2075 /* Allocate the space for the maximum needed parameters and data */
2076 if (total_params > 0)
2077 params = (char *)malloc(total_params);
2079 data = (char *)malloc(total_data);
2081 if ((total_params && !params) || (total_data && !data)) {
2082 DEBUG(2,("Out of memory in reply_trans2\n"));
2087 return(ERROR(ERRDOS,ERRnomem));
2090 /* Copy the param and data bytes sent with this request into
2091 the params buffer */
2092 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2093 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2095 if (num_params > total_params || num_data > total_data)
2096 exit_server("invalid params in reply_trans2");
2099 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2101 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2103 if(num_data_sofar < total_data || num_params_sofar < total_params) {
2104 /* We need to send an interim response then receive the rest
2105 of the parameter/data bytes */
2106 outsize = set_message(outbuf,0,0,True);
2107 send_smb(Client,outbuf);
2109 while (num_data_sofar < total_data ||
2110 num_params_sofar < total_params) {
2113 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2116 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2117 outsize = set_message(outbuf,0,0,True);
2119 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2121 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2122 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2127 return(ERROR(ERRSRV,ERRerror));
2130 /* Revise total_params and total_data in case
2131 they have changed downwards */
2132 total_params = SVAL(inbuf, smb_tpscnt);
2133 total_data = SVAL(inbuf, smb_tdscnt);
2134 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2135 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2136 if (num_params_sofar > total_params || num_data_sofar > total_data)
2137 exit_server("data overflow in trans2");
2139 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
2140 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2141 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2142 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2146 if (Protocol >= PROTOCOL_NT1) {
2147 uint16 flg2 = SVAL(outbuf,smb_flg2);
2148 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2151 /* Now we must call the relevant TRANS2 function */
2153 case TRANSACT2_OPEN:
2154 outsize = call_trans2open(conn,
2155 inbuf, outbuf, bufsize,
2159 case TRANSACT2_FINDFIRST:
2160 outsize = call_trans2findfirst(conn, inbuf, outbuf,
2161 bufsize, ¶ms, &data);
2164 case TRANSACT2_FINDNEXT:
2165 outsize = call_trans2findnext(conn, inbuf, outbuf,
2170 case TRANSACT2_QFSINFO:
2171 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
2172 length, bufsize, ¶ms,
2176 case TRANSACT2_SETFSINFO:
2177 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2182 case TRANSACT2_QPATHINFO:
2183 case TRANSACT2_QFILEINFO:
2184 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2186 ¶ms, &data, total_data);
2188 case TRANSACT2_SETPATHINFO:
2189 case TRANSACT2_SETFILEINFO:
2190 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2196 case TRANSACT2_FINDNOTIFYFIRST:
2197 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2202 case TRANSACT2_FINDNOTIFYNEXT:
2203 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2207 case TRANSACT2_MKDIR:
2208 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2209 bufsize, ¶ms, &data);
2212 /* Error in request */
2213 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2218 return (ERROR(ERRSRV,ERRerror));
2221 /* As we do not know how many data packets will need to be
2222 returned here the various call_trans2xxxx calls
2223 must send their own. Thus a call_trans2xxx routine only
2224 returns a value other than -1 when it wants to send
2232 return outsize; /* If a correct response was needed the
2233 call_trans2xxx calls have already sent
2234 it. If outsize != -1 then it is returning */