2 Unix SMB/Netbios implementation.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1998
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
33 extern int oplock_sock;
34 extern int smb_read_error;
35 extern fstring local_machine;
36 extern int global_oplock_break;
38 /****************************************************************************
39 Send the required number of replies back.
40 We assume all fields other than the data fields are
41 set correctly for the type of call.
42 HACK ! Always assumes smb_setup field is zero.
43 ****************************************************************************/
44 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
45 int paramsize, char *pdata, int datasize)
47 /* As we are using a protocol > LANMAN1 then the max_send
48 variable must have been set in the sessetupX call.
49 This takes precedence over the max_xmit field in the
50 global struct. These different max_xmit variables should
51 be merged as this is now too confusing */
54 int data_to_send = datasize;
55 int params_to_send = paramsize;
59 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
60 int alignment_offset = 3;
61 int data_alignment_offset = 0;
63 /* Initially set the wcnt area to be 10 - this is true for all
65 set_message(outbuf,10,0,True);
67 /* If there genuinely are no parameters or data to send just send
69 if(params_to_send == 0 && data_to_send == 0)
71 send_smb(Client,outbuf);
75 /* When sending params and data ensure that both are nicely aligned */
76 /* Only do this alignment when there is also data to send - else
77 can cause NT redirector problems. */
78 if (((params_to_send % 4) != 0) && (data_to_send != 0))
79 data_alignment_offset = 4 - (params_to_send % 4);
81 /* Space is bufsize minus Netbios over TCP header minus SMB header */
82 /* The alignment_offset is to align the param bytes on an even byte
83 boundary. NT 4.0 Beta needs this to work correctly. */
84 useable_space = bufsize - ((smb_buf(outbuf)+
85 alignment_offset+data_alignment_offset) -
88 /* useable_space can never be more than max_send minus the
90 useable_space = MIN(useable_space,
91 max_send - (alignment_offset+data_alignment_offset));
94 while (params_to_send || data_to_send)
96 /* Calculate whether we will totally or partially fill this packet */
97 total_sent_thistime = params_to_send + data_to_send +
98 alignment_offset + data_alignment_offset;
99 /* We can never send more than useable_space */
100 total_sent_thistime = MIN(total_sent_thistime, useable_space);
102 set_message(outbuf, 10, total_sent_thistime, True);
104 /* Set total params and data to be sent */
105 SSVAL(outbuf,smb_tprcnt,paramsize);
106 SSVAL(outbuf,smb_tdrcnt,datasize);
108 /* Calculate how many parameters and data we can fit into
109 this packet. Parameters get precedence */
111 params_sent_thistime = MIN(params_to_send,useable_space);
112 data_sent_thistime = useable_space - params_sent_thistime;
113 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
115 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
116 if(params_sent_thistime == 0)
118 SSVAL(outbuf,smb_proff,0);
119 SSVAL(outbuf,smb_prdisp,0);
121 /* smb_proff is the offset from the start of the SMB header to the
122 parameter bytes, however the first 4 bytes of outbuf are
123 the Netbios over TCP header. Thus use smb_base() to subtract
124 them from the calculation */
125 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
126 /* Absolute displacement of param bytes sent in this packet */
127 SSVAL(outbuf,smb_prdisp,pp - params);
130 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
131 if(data_sent_thistime == 0)
133 SSVAL(outbuf,smb_droff,0);
134 SSVAL(outbuf,smb_drdisp, 0);
136 /* The offset of the data bytes is the offset of the
137 parameter bytes plus the number of parameters being sent this time */
138 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
140 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+data_alignment_offset,pd,data_sent_thistime);
151 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
152 params_sent_thistime, data_sent_thistime, useable_space));
153 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
154 params_to_send, data_to_send, paramsize, datasize));
156 /* Send the packet */
157 send_smb(Client,outbuf);
159 pp += params_sent_thistime;
160 pd += data_sent_thistime;
162 params_to_send -= params_sent_thistime;
163 data_to_send -= data_sent_thistime;
166 if(params_to_send < 0 || data_to_send < 0)
168 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
169 params_to_send, data_to_send));
178 /****************************************************************************
179 reply to a TRANSACT2_OPEN
180 ****************************************************************************/
181 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
182 char **pparams, char **ppdata)
184 char *params = *pparams;
185 int16 open_mode = SVAL(params, 2);
186 int16 open_attr = SVAL(params,6);
187 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
189 BOOL return_additional_info = BITSETW(params,0);
190 int16 open_sattr = SVAL(params, 4);
191 time_t open_time = make_unix_date3(params+8);
193 int16 open_ofun = SVAL(params,12);
194 int32 open_size = IVAL(params,14);
195 char *pname = ¶ms[28];
196 int16 namelen = strlen(pname)+1;
201 int size=0,fmode=0,mtime=0,rmode;
205 BOOL bad_path = False;
207 StrnCpy(fname,pname,namelen);
209 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
210 fname,cnum,open_mode, open_attr, open_ofun, open_size));
212 /* XXXX we need to handle passed times, sattr and flags */
214 unix_convert(fname,cnum,0,&bad_path);
216 fnum = find_free_file();
218 return(ERROR(ERRSRV,ERRnofids));
220 if (!check_name(fname,cnum))
222 if((errno == ENOENT) && bad_path)
224 unix_ERR_class = ERRDOS;
225 unix_ERR_code = ERRbadpath;
227 Files[fnum].reserved = False;
228 return(UNIXERROR(ERRDOS,ERRnoaccess));
231 unixmode = unix_mode(cnum,open_attr | aARCH);
234 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
235 oplock_request, &rmode,&smb_action);
237 if (!Files[fnum].open)
239 if((errno == ENOENT) && bad_path)
241 unix_ERR_class = ERRDOS;
242 unix_ERR_code = ERRbadpath;
244 Files[fnum].reserved = False;
245 return(UNIXERROR(ERRDOS,ERRnoaccess));
248 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
249 close_file(fnum,False);
250 return(ERROR(ERRDOS,ERRnoaccess));
254 fmode = dos_mode(cnum,fname,&sbuf);
255 mtime = sbuf.st_mtime;
258 close_file(fnum,False);
259 return(ERROR(ERRDOS,ERRnoaccess));
262 /* Realloc the size of parameters and data we will return */
263 params = *pparams = Realloc(*pparams, 28);
265 return(ERROR(ERRDOS,ERRnomem));
268 SSVAL(params,0,fnum);
269 SSVAL(params,2,fmode);
270 put_dos_date2(params,4, mtime);
271 SIVAL(params,8, size);
272 SSVAL(params,12,rmode);
274 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
275 smb_action |= EXTENDED_OPLOCK_GRANTED;
278 SSVAL(params,18,smb_action);
279 SIVAL(params,20,inode);
281 /* Send the required number of replies */
282 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
287 /****************************************************************************
288 get a level dependent lanman2 dir entry.
289 ****************************************************************************/
290 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
291 int requires_resume_key,
292 BOOL dont_descend,char **ppdata,
293 char *base_data, int space_remaining,
304 char *p, *pdata = *ppdata;
309 uint32 mdate=0, adate=0, cdate=0;
311 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
312 strequal(Connections[cnum].dirpath,".") ||
313 strequal(Connections[cnum].dirpath,"/"));
315 int nt_extmode; /* Used for NT connections instead of mode */
316 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
319 *out_of_space = False;
321 if (!Connections[cnum].dirptr)
324 p = strrchr(path_mask,'/');
333 pstrcpy(mask, path_mask);
337 /* Needed if we run out of space */
338 prev_dirpos = TellDir(Connections[cnum].dirptr);
339 dname = ReadDirName(Connections[cnum].dirptr);
342 * Due to bugs in NT client redirectors we are not using
343 * resume keys any more - set them to zero.
344 * Check out the related comments in findfirst/findnext.
350 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
351 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
358 pstrcpy(fname,dname);
360 if(mask_match(fname, mask, case_sensitive, True))
362 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
363 if (dont_descend && !isdots)
366 if (isrootdir && isdots)
369 pstrcpy(pathreal,Connections[cnum].dirpath);
371 strcat(pathreal,"/");
372 strcat(pathreal,dname);
373 if (sys_stat(pathreal,&sbuf) != 0)
375 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
379 mode = dos_mode(cnum,pathreal,&sbuf);
381 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
382 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
387 mdate = sbuf.st_mtime;
388 adate = sbuf.st_atime;
389 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)));
393 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
399 name_map_mangle(fname,False,SNUM(cnum));
404 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
409 if(requires_resume_key) {
413 put_dos_date2(p,l1_fdateCreation,cdate);
414 put_dos_date2(p,l1_fdateLastAccess,adate);
415 put_dos_date2(p,l1_fdateLastWrite,mdate);
416 SIVAL(p,l1_cbFile,size);
417 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
418 SSVAL(p,l1_attrFile,mode);
419 SCVAL(p,l1_cchName,strlen(fname));
420 strcpy(p + l1_achName, fname);
421 nameptr = p + l1_achName;
422 p += l1_achName + strlen(fname) + 1;
427 if(requires_resume_key) {
431 put_dos_date2(p,l2_fdateCreation,cdate);
432 put_dos_date2(p,l2_fdateLastAccess,adate);
433 put_dos_date2(p,l2_fdateLastWrite,mdate);
434 SIVAL(p,l2_cbFile,size);
435 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
436 SSVAL(p,l2_attrFile,mode);
437 SIVAL(p,l2_cbList,0); /* No extended attributes */
438 SCVAL(p,l2_cchName,strlen(fname));
439 strcpy(p + l2_achName, fname);
440 nameptr = p + l2_achName;
441 p += l2_achName + strlen(fname) + 1;
446 put_dos_date2(p,4,cdate);
447 put_dos_date2(p,8,adate);
448 put_dos_date2(p,12,mdate);
450 SIVAL(p,20,ROUNDUP(size,1024));
453 CVAL(p,30) = strlen(fname);
456 p += 31 + strlen(fname) + 1;
460 if(requires_resume_key) {
464 SIVAL(p,0,33+strlen(fname)+1);
465 put_dos_date2(p,4,cdate);
466 put_dos_date2(p,8,adate);
467 put_dos_date2(p,12,mdate);
469 SIVAL(p,20,ROUNDUP(size,1024));
471 CVAL(p,32) = strlen(fname);
472 strcpy(p + 33, fname);
474 p += 33 + strlen(fname) + 1;
477 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
478 was_8_3 = is_8_3(fname, True);
479 len = 94+strlen(fname);
480 len = (len + 3) & ~3;
481 SIVAL(p,0,len); p += 4;
482 SIVAL(p,0,reskey); p += 4;
483 put_long_date(p,cdate); p += 8;
484 put_long_date(p,adate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 put_long_date(p,mdate); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,size); p += 8;
489 SIVAL(p,0,nt_extmode); p += 4;
490 SIVAL(p,0,strlen(fname)); p += 4;
491 SIVAL(p,0,0); p += 4;
494 if (!name_map_mangle(p+2,True,SNUM(cnum)))
499 SSVAL(p,0,strlen(p+2));
502 strcpy(p,fname); p += strlen(p);
506 case SMB_FIND_FILE_DIRECTORY_INFO:
507 len = 64+strlen(fname);
508 len = (len + 3) & ~3;
509 SIVAL(p,0,len); p += 4;
510 SIVAL(p,0,reskey); p += 4;
511 put_long_date(p,cdate); p += 8;
512 put_long_date(p,adate); p += 8;
513 put_long_date(p,mdate); p += 8;
514 put_long_date(p,mdate); p += 8;
515 SIVAL(p,0,size); p += 8;
516 SIVAL(p,0,size); p += 8;
517 SIVAL(p,0,nt_extmode); p += 4;
518 SIVAL(p,0,strlen(fname)); p += 4;
524 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
525 len = 68+strlen(fname);
526 len = (len + 3) & ~3;
527 SIVAL(p,0,len); p += 4;
528 SIVAL(p,0,reskey); p += 4;
529 put_long_date(p,cdate); p += 8;
530 put_long_date(p,adate); p += 8;
531 put_long_date(p,mdate); p += 8;
532 put_long_date(p,mdate); p += 8;
533 SIVAL(p,0,size); p += 8;
534 SIVAL(p,0,size); p += 8;
535 SIVAL(p,0,nt_extmode); p += 4;
536 SIVAL(p,0,strlen(fname)); p += 4;
537 SIVAL(p,0,0); p += 4;
542 case SMB_FIND_FILE_NAMES_INFO:
543 len = 12+strlen(fname);
544 len = (len + 3) & ~3;
545 SIVAL(p,0,len); p += 4;
546 SIVAL(p,0,reskey); p += 4;
547 SIVAL(p,0,strlen(fname)); p += 4;
557 if (PTR_DIFF(p,pdata) > space_remaining) {
558 /* Move the dirptr back to prev_dirpos */
559 SeekDir(Connections[cnum].dirptr, prev_dirpos);
560 *out_of_space = True;
561 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
562 return False; /* Not finished - just out of space */
565 /* Setup the last_filename pointer, as an offset from base_data */
566 *last_name_off = PTR_DIFF(nameptr,base_data);
567 /* Advance the data pointer to the next slot */
572 /****************************************************************************
573 reply to a TRANS2_FINDFIRST
574 ****************************************************************************/
575 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
576 char **pparams, char **ppdata)
578 /* We must be careful here that we don't return more than the
579 allowed number of data bytes. If this means returning fewer than
580 maxentries then so be it. We assume that the redirector has
581 enough room for the fixed number of parameter bytes it has
583 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
584 char *params = *pparams;
585 char *pdata = *ppdata;
586 int dirtype = SVAL(params,0);
587 int maxentries = SVAL(params,2);
588 BOOL close_after_first = BITSETW(params+4,0);
589 BOOL close_if_end = BITSETW(params+4,1);
590 BOOL requires_resume_key = BITSETW(params+4,2);
591 int info_level = SVAL(params,6);
599 BOOL finished = False;
600 BOOL dont_descend = False;
601 BOOL out_of_space = False;
603 BOOL bad_path = False;
605 *directory = *mask = 0;
607 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",
608 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
609 info_level, max_data_bytes));
617 case SMB_FIND_FILE_DIRECTORY_INFO:
618 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
619 case SMB_FIND_FILE_NAMES_INFO:
620 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
623 return(ERROR(ERRDOS,ERRunknownlevel));
626 pstrcpy(directory, params + 12); /* Complete directory path with
627 wildcard mask appended */
629 DEBUG(5,("path=%s\n",directory));
631 unix_convert(directory,cnum,0,&bad_path);
632 if(!check_name(directory,cnum)) {
633 if((errno == ENOENT) && bad_path)
635 unix_ERR_class = ERRDOS;
636 unix_ERR_code = ERRbadpath;
640 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
641 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
642 (get_remote_arch() == RA_WINNT))
644 unix_ERR_class = ERRDOS;
645 unix_ERR_code = ERRbaddirectory;
649 return(ERROR(ERRDOS,ERRbadpath));
652 p = strrchr(directory,'/');
654 strcpy(mask,directory);
655 strcpy(directory,"./");
661 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
663 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
665 return(ERROR(ERRDOS,ERRnomem));
666 bzero(pdata,max_data_bytes);
668 /* Realloc the params space */
669 params = *pparams = Realloc(*pparams, 10);
671 return(ERROR(ERRDOS,ERRnomem));
673 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
675 return(ERROR(ERRDOS,ERRbadfile));
677 /* convert the formatted masks */
681 if (*p == '<') *p = '*';
682 if (*p == '>') *p = '?';
683 if (*p == '"') *p = '.';
688 /* a special case for 16 bit apps */
689 if (strequal(mask,"????????.???")) strcpy(mask,"*");
691 /* handle broken clients that send us old 8.3 format */
692 string_sub(mask,"????????","*");
693 string_sub(mask,".???",".*");
695 /* Save the wildcard match and attribs we are using on this directory -
696 needed as lanman2 assumes these are being saved between calls */
698 if(!(wcard = strdup(mask))) {
699 dptr_close(dptr_num);
700 return(ERROR(ERRDOS,ERRnomem));
703 dptr_set_wcard(dptr_num, wcard);
704 dptr_set_attr(dptr_num, dirtype);
706 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
708 /* We don't need to check for VOL here as this is returned by
709 a different TRANS2 call. */
711 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
712 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
713 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
717 space_remaining = max_data_bytes;
718 out_of_space = False;
720 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
723 /* this is a heuristic to avoid seeking the dirptr except when
724 absolutely necessary. It allows for a filename of about 40 chars */
725 if (space_remaining < DIRLEN_GUESS && numentries > 0)
733 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
734 requires_resume_key,dont_descend,
735 &p,pdata,space_remaining, &out_of_space,
739 if (finished && out_of_space)
742 if (!finished && !out_of_space)
744 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
747 /* Check if we can close the dirptr */
748 if(close_after_first || (finished && close_if_end))
750 dptr_close(dptr_num);
751 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
756 * If there are no matching entries we must return ERRDOS/ERRbadfile -
757 * from observation of NT.
761 return(ERROR(ERRDOS,ERRbadfile));
763 /* At this point pdata points to numentries directory entries. */
765 /* Set up the return parameter block */
766 SSVAL(params,0,dptr_num);
767 SSVAL(params,2,numentries);
768 SSVAL(params,4,finished);
769 SSVAL(params,6,0); /* Never an EA error */
770 SSVAL(params,8,last_name_off);
772 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
774 if ((! *directory) && dptr_path(dptr_num))
775 sprintf(directory,"(%s)",dptr_path(dptr_num));
777 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
779 smb_fn_name(CVAL(inbuf,smb_com)),
780 mask,directory,cnum,dirtype,numentries));
786 /****************************************************************************
787 reply to a TRANS2_FINDNEXT
788 ****************************************************************************/
789 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
790 int cnum, char **pparams, char **ppdata)
792 /* We must be careful here that we don't return more than the
793 allowed number of data bytes. If this means returning fewer than
794 maxentries then so be it. We assume that the redirector has
795 enough room for the fixed number of parameter bytes it has
797 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
798 char *params = *pparams;
799 char *pdata = *ppdata;
800 int16 dptr_num = SVAL(params,0);
801 int maxentries = SVAL(params,2);
802 uint16 info_level = SVAL(params,4);
803 uint32 resume_key = IVAL(params,6);
804 BOOL close_after_request = BITSETW(params+10,0);
805 BOOL close_if_end = BITSETW(params+10,1);
806 BOOL requires_resume_key = BITSETW(params+10,2);
807 BOOL continue_bit = BITSETW(params+10,3);
814 int i, last_name_off=0;
815 BOOL finished = False;
816 BOOL dont_descend = False;
817 BOOL out_of_space = False;
820 *mask = *directory = *resume_name = 0;
822 pstrcpy( resume_name, params+12);
824 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
825 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
826 resume_key = %d resume name = %s continue=%d level = %d\n",
827 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
828 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
836 case SMB_FIND_FILE_DIRECTORY_INFO:
837 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
838 case SMB_FIND_FILE_NAMES_INFO:
839 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
842 return(ERROR(ERRDOS,ERRunknownlevel));
845 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
847 return(ERROR(ERRDOS,ERRnomem));
848 bzero(pdata,max_data_bytes);
850 /* Realloc the params space */
851 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
853 return(ERROR(ERRDOS,ERRnomem));
855 /* Check that the dptr is valid */
856 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(dptr_num)))
857 return(ERROR(ERRDOS,ERRnofiles));
859 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
861 /* Get the wildcard mask from the dptr */
862 if((p = dptr_wcard(dptr_num))== NULL) {
863 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
864 return (ERROR(ERRDOS,ERRnofiles));
867 strcpy(directory,Connections[cnum].dirpath);
869 /* Get the attr mask from the dptr */
870 dirtype = dptr_attr(dptr_num);
872 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
873 dptr_num, mask, dirtype,
874 Connections[cnum].dirptr,
875 TellDir(Connections[cnum].dirptr)));
877 /* We don't need to check for VOL here as this is returned by
878 a different TRANS2 call. */
880 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
881 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
885 space_remaining = max_data_bytes;
886 out_of_space = False;
889 * Seek to the correct position. We no longer use the resume key but
890 * depend on the last file name instead.
892 if(requires_resume_key && *resume_name && !continue_bit)
895 * Fix for NT redirector problem triggered by resume key indexes
896 * changing between directory scans. We now return a resume key of 0
897 * and instead look for the filename to continue from (also given
898 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
899 * findfirst/findnext (as is usual) then the directory pointer
900 * should already be at the correct place. Check this by scanning
901 * backwards looking for an exact (ie. case sensitive) filename match.
902 * If we get to the beginning of the directory and haven't found it then scan
903 * forwards again looking for a match. JRA.
906 int current_pos, start_pos;
908 void *dirptr = Connections[cnum].dirptr;
909 start_pos = TellDir(dirptr);
910 for(current_pos = start_pos; current_pos >= 0; current_pos--)
912 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
914 SeekDir(dirptr, current_pos);
915 dname = ReadDirName(dirptr);
916 if(dname && strcsequal( resume_name, dname))
918 SeekDir(dirptr, current_pos+1);
919 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
925 * Scan forward from start if not found going backwards.
930 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
931 SeekDir(dirptr, start_pos);
932 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
934 if(strcsequal( resume_name, dname))
936 SeekDir(dirptr, current_pos+1);
937 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
941 } /* end if current_pos */
942 } /* end if requires_resume_key && !continue_bit */
944 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
946 /* this is a heuristic to avoid seeking the dirptr except when
947 absolutely necessary. It allows for a filename of about 40 chars */
948 if (space_remaining < DIRLEN_GUESS && numentries > 0)
956 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
957 requires_resume_key,dont_descend,
958 &p,pdata,space_remaining, &out_of_space,
962 if (finished && out_of_space)
965 if (!finished && !out_of_space)
967 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
970 /* Check if we can close the dirptr */
971 if(close_after_request || (finished && close_if_end))
973 dptr_close(dptr_num); /* This frees up the saved mask */
974 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
979 /* Set up the return parameter block */
980 SSVAL(params,0,numentries);
981 SSVAL(params,2,finished);
982 SSVAL(params,4,0); /* Never an EA error */
983 SSVAL(params,6,last_name_off);
985 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
987 if ((! *directory) && dptr_path(dptr_num))
988 sprintf(directory,"(%s)",dptr_path(dptr_num));
990 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
992 smb_fn_name(CVAL(inbuf,smb_com)),
993 mask,directory,cnum,dirtype,numentries));
998 /****************************************************************************
999 reply to a TRANS2_QFSINFO (query filesystem info)
1000 ****************************************************************************/
1001 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1002 int cnum, char **pparams, char **ppdata)
1004 char *pdata = *ppdata;
1005 char *params = *pparams;
1006 uint16 info_level = SVAL(params,0);
1009 char *vname = volume_label(SNUM(cnum));
1010 int snum = SNUM(cnum);
1012 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
1014 if(sys_stat(".",&st)!=0) {
1015 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1016 return (ERROR(ERRSRV,ERRinvdevice));
1019 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1025 int dfree,dsize,bsize;
1027 sys_disk_free(".",&bsize,&dfree,&dsize);
1028 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1029 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1030 SIVAL(pdata,l1_cUnit,dsize);
1031 SIVAL(pdata,l1_cUnitAvail,dfree);
1032 SSVAL(pdata,l1_cbSector,512);
1033 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1034 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
1039 /* Return volume name */
1040 int volname_len = MIN(strlen(vname),11);
1041 data_len = l2_vol_szVolLabel + volname_len + 1;
1043 * Add volume serial number - hash of a combination of
1044 * the called hostname and the service name.
1046 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1047 SCVAL(pdata,l2_vol_cch,volname_len);
1048 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1049 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
1050 pdata+l2_vol_szVolLabel));
1053 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1054 data_len = 12 + 2*strlen(FSTYPE_STRING);
1055 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1056 SIVAL(pdata,4,128); /* Max filename component length */
1057 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1058 PutUniCode(pdata+12,FSTYPE_STRING);
1060 case SMB_QUERY_FS_LABEL_INFO:
1061 data_len = 4 + strlen(vname);
1062 SIVAL(pdata,0,strlen(vname));
1063 strcpy(pdata+4,vname);
1065 case SMB_QUERY_FS_VOLUME_INFO:
1066 data_len = 18 + 2*strlen(vname);
1068 * Add volume serial number - hash of a combination of
1069 * the called hostname and the service name.
1071 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1072 SIVAL(pdata,12,2*strlen(vname));
1073 PutUniCode(pdata+18,vname);
1074 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1077 case SMB_QUERY_FS_SIZE_INFO:
1079 int dfree,dsize,bsize;
1081 sys_disk_free(".",&bsize,&dfree,&dsize);
1082 SIVAL(pdata,0,dsize);
1083 SIVAL(pdata,8,dfree);
1084 SIVAL(pdata,16,bsize/512);
1085 SIVAL(pdata,20,512);
1088 case SMB_QUERY_FS_DEVICE_INFO:
1090 SIVAL(pdata,0,0); /* dev type */
1091 SIVAL(pdata,4,0); /* characteristics */
1094 return(ERROR(ERRDOS,ERRunknownlevel));
1098 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1100 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1105 /****************************************************************************
1106 reply to a TRANS2_SETFSINFO (set filesystem info)
1107 ****************************************************************************/
1108 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1109 int cnum, char **pparams, char **ppdata)
1111 /* Just say yes we did it - there is nothing that
1112 can be set here so it doesn't matter. */
1114 DEBUG(3,("call_trans2setfsinfo\n"));
1116 if (!CAN_WRITE(cnum))
1117 return(ERROR(ERRSRV,ERRaccess));
1119 outsize = set_message(outbuf,10,0,True);
1124 /****************************************************************************
1125 reply to a TRANS2_QFILEINFO (query file info by fileid)
1126 ****************************************************************************/
1127 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1128 int bufsize,int cnum,
1129 char **pparams,char **ppdata,
1132 char *params = *pparams;
1133 char *pdata = *ppdata;
1134 uint16 tran_call = SVAL(inbuf, smb_setup0);
1138 unsigned int data_size;
1144 BOOL bad_path = False;
1146 if (tran_call == TRANSACT2_QFILEINFO) {
1147 int16 fnum = SVALS(params,0);
1148 info_level = SVAL(params,2);
1150 CHECK_FNUM(fnum,cnum);
1153 fname = Files[fnum].name;
1154 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1155 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1156 return(UNIXERROR(ERRDOS,ERRbadfid));
1158 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1161 info_level = SVAL(params,0);
1163 pstrcpy(fname,¶ms[6]);
1164 unix_convert(fname,cnum,0,&bad_path);
1165 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1166 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1167 if((errno == ENOENT) && bad_path)
1169 unix_ERR_class = ERRDOS;
1170 unix_ERR_code = ERRbadpath;
1172 return(UNIXERROR(ERRDOS,ERRbadpath));
1178 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1179 fname,info_level,tran_call,total_data));
1181 p = strrchr(fname,'/');
1187 mode = dos_mode(cnum,fname,&sbuf);
1188 size = sbuf.st_size;
1189 if (mode & aDIR) size = 0;
1191 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1193 pdata = *ppdata = Realloc(*ppdata, data_size);
1195 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1196 /* uggh, EAs for OS2 */
1197 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1198 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1201 bzero(pdata,data_size);
1205 case SMB_INFO_STANDARD:
1206 case SMB_INFO_QUERY_EA_SIZE:
1207 data_size = (info_level==1?22:26);
1208 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1209 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1210 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1211 SIVAL(pdata,l1_cbFile,size);
1212 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1213 SSVAL(pdata,l1_attrFile,mode);
1214 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1217 case SMB_INFO_QUERY_EAS_FROM_LIST:
1219 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1220 put_dos_date2(pdata,4,sbuf.st_atime);
1221 put_dos_date2(pdata,8,sbuf.st_mtime);
1222 SIVAL(pdata,12,size);
1223 SIVAL(pdata,16,ROUNDUP(size,1024));
1224 SIVAL(pdata,20,mode);
1227 case SMB_INFO_QUERY_ALL_EAS:
1229 SIVAL(pdata,0,data_size);
1233 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1235 case SMB_QUERY_FILE_BASIC_INFO:
1236 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1237 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1238 put_long_date(pdata+8,sbuf.st_atime);
1239 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1240 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1241 SIVAL(pdata,32,mode);
1243 DEBUG(5,("SMB_QFBI - "));
1245 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum)));
1246 DEBUG(5,("create: %s ", ctime(&create_time)));
1248 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1249 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1250 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1251 DEBUG(5,("mode: %x\n", mode));
1255 case SMB_QUERY_FILE_STANDARD_INFO:
1257 SIVAL(pdata,0,size);
1258 SIVAL(pdata,8,size);
1259 SIVAL(pdata,16,sbuf.st_nlink);
1261 CVAL(pdata,21) = (mode&aDIR)?1:0;
1264 case SMB_QUERY_FILE_EA_INFO:
1268 /* Get the 8.3 name - used if NT SMB was negotiated. */
1269 case SMB_QUERY_FILE_ALT_NAME_INFO:
1272 pstrcpy(short_name,fname);
1273 /* Mangle if not already 8.3 */
1274 if(!is_8_3(short_name, True))
1276 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1279 strncpy(pdata + 4,short_name,12);
1280 (pdata + 4)[12] = 0;
1281 strupper(pdata + 4);
1282 l = strlen(pdata + 4);
1288 case SMB_QUERY_FILE_NAME_INFO:
1291 pstrcpy(pdata+4,fname);
1294 case SMB_QUERY_FILE_ALLOCATION_INFO:
1295 case SMB_QUERY_FILE_END_OF_FILEINFO:
1297 SIVAL(pdata,0,size);
1300 case SMB_QUERY_FILE_ALL_INFO:
1301 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
1302 put_long_date(pdata+8,sbuf.st_atime);
1303 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1304 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1305 SIVAL(pdata,32,mode);
1307 SIVAL(pdata,0,size);
1308 SIVAL(pdata,8,size);
1309 SIVAL(pdata,16,sbuf.st_nlink);
1311 CVAL(pdata,21) = (mode&aDIR)?1:0;
1313 pdata += 8; /* index number */
1314 pdata += 4; /* EA info */
1316 SIVAL(pdata,0,0xA9);
1318 SIVAL(pdata,0,0xd01BF);
1320 SIVAL(pdata,0,pos); /* current offset */
1322 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1324 pdata += 4; /* alignment */
1326 pstrcpy(pdata+4,fname);
1328 data_size = PTR_DIFF(pdata,(*ppdata));
1331 case SMB_QUERY_FILE_STREAM_INFO:
1334 SIVAL(pdata,4,size);
1335 SIVAL(pdata,12,size);
1337 pstrcpy(pdata+24,fname);
1340 return(ERROR(ERRDOS,ERRunknownlevel));
1343 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1348 /****************************************************************************
1349 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1350 ****************************************************************************/
1351 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1352 int bufsize, int cnum, char **pparams,
1353 char **ppdata, int total_data)
1355 char *params = *pparams;
1356 char *pdata = *ppdata;
1357 uint16 tran_call = SVAL(inbuf, smb_setup0);
1366 BOOL bad_path = False;
1368 if (!CAN_WRITE(cnum))
1369 return(ERROR(ERRSRV,ERRaccess));
1371 if (tran_call == TRANSACT2_SETFILEINFO) {
1372 int16 fnum = SVALS(params,0);
1373 info_level = SVAL(params,2);
1375 CHECK_FNUM(fnum,cnum);
1378 fname = Files[fnum].name;
1379 fd = Files[fnum].fd_ptr->fd;
1381 if(fstat(fd,&st)!=0) {
1382 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1383 return(ERROR(ERRDOS,ERRbadpath));
1387 info_level = SVAL(params,0);
1389 pstrcpy(fname,¶ms[6]);
1390 unix_convert(fname,cnum,0,&bad_path);
1391 if(!check_name(fname, cnum))
1393 if((errno == ENOENT) && bad_path)
1395 unix_ERR_class = ERRDOS;
1396 unix_ERR_code = ERRbadpath;
1398 return(UNIXERROR(ERRDOS,ERRbadpath));
1401 if(sys_stat(fname,&st)!=0) {
1402 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1403 if((errno == ENOENT) && bad_path)
1405 unix_ERR_class = ERRDOS;
1406 unix_ERR_code = ERRbadpath;
1408 return(UNIXERROR(ERRDOS,ERRbadpath));
1412 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1413 tran_call,fname,info_level,total_data));
1415 /* Realloc the parameter and data sizes */
1416 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1418 return(ERROR(ERRDOS,ERRnomem));
1421 tvs.modtime = st.st_mtime;
1422 tvs.actime = st.st_atime;
1423 mode = dos_mode(cnum,fname,&st);
1425 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1426 /* uggh, EAs for OS2 */
1427 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1428 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1433 case SMB_INFO_STANDARD:
1434 case SMB_INFO_QUERY_EA_SIZE:
1437 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1440 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1442 mode = SVAL(pdata,l1_attrFile);
1443 size = IVAL(pdata,l1_cbFile);
1447 /* XXXX um, i don't think this is right.
1448 it's also not in the cifs6.txt spec.
1450 case SMB_INFO_QUERY_EAS_FROM_LIST:
1451 tvs.actime = make_unix_date2(pdata+8);
1452 tvs.modtime = make_unix_date2(pdata+12);
1453 size = IVAL(pdata,16);
1454 mode = IVAL(pdata,24);
1457 /* XXXX nor this. not in cifs6.txt, either. */
1458 case SMB_INFO_QUERY_ALL_EAS:
1459 tvs.actime = make_unix_date2(pdata+8);
1460 tvs.modtime = make_unix_date2(pdata+12);
1461 size = IVAL(pdata,16);
1462 mode = IVAL(pdata,24);
1465 case SMB_SET_FILE_BASIC_INFO:
1467 /* Ignore create time at offset pdata. */
1470 tvs.actime = interpret_long_date(pdata+8);
1472 /* write time + changed time, combined. */
1473 tvs.modtime=MAX(interpret_long_date(pdata+16),
1474 interpret_long_date(pdata+24));
1476 #if 0 /* Needs more testing... */
1477 /* Test from Luke to prevent Win95 from
1478 setting incorrect values here.
1480 if (tvs.actime < tvs.modtime)
1481 return(ERROR(ERRDOS,ERRnoaccess));
1482 #endif /* Needs more testing... */
1485 mode = IVAL(pdata,32);
1489 case SMB_SET_FILE_END_OF_FILE_INFO:
1491 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1492 return(ERROR(ERRDOS,ERRunknownlevel));
1493 size = IVAL(pdata,0);
1497 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1498 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1501 return(ERROR(ERRDOS,ERRunknownlevel));
1505 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1506 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1507 DEBUG(6,("size: %x " , size));
1508 DEBUG(6,("mode: %x\n" , mode));
1510 /* get some defaults (no modifications) if any info is zero. */
1511 if (!tvs.actime) tvs.actime = st.st_atime;
1512 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1513 if (!size) size = st.st_size;
1515 /* Try and set the times, size and mode of this file -
1516 if they are different from the current values
1518 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1520 if(file_utime(cnum, fname, &tvs)!=0)
1522 return(ERROR(ERRDOS,ERRnoaccess));
1526 /* check the mode isn't different, before changing it */
1527 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1529 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1530 return(ERROR(ERRDOS,ERRnoaccess));
1533 if(size != st.st_size)
1537 fd = sys_open(fname,O_RDWR,0);
1540 return(ERROR(ERRDOS,ERRbadpath));
1542 set_filelen(fd, size);
1547 set_filelen(fd, size);
1553 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1558 /****************************************************************************
1559 reply to a TRANS2_MKDIR (make directory with extended attributes).
1560 ****************************************************************************/
1561 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1562 int cnum, char **pparams, char **ppdata)
1564 char *params = *pparams;
1567 BOOL bad_path = False;
1569 if (!CAN_WRITE(cnum))
1570 return(ERROR(ERRSRV,ERRaccess));
1572 pstrcpy(directory, ¶ms[4]);
1574 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1576 unix_convert(directory,cnum,0,&bad_path);
1577 if (check_name(directory,cnum))
1578 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1582 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1583 if((errno == ENOENT) && bad_path)
1585 unix_ERR_class = ERRDOS;
1586 unix_ERR_code = ERRbadpath;
1588 return(UNIXERROR(ERRDOS,ERRnoaccess));
1591 /* Realloc the parameter and data sizes */
1592 params = *pparams = Realloc(*pparams,2);
1594 return(ERROR(ERRDOS,ERRnomem));
1598 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1603 /****************************************************************************
1604 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1605 We don't actually do this - we just send a null response.
1606 ****************************************************************************/
1607 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1608 int cnum, char **pparams, char **ppdata)
1610 static uint16 fnf_handle = 257;
1611 char *params = *pparams;
1612 uint16 info_level = SVAL(params,4);
1614 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1622 return(ERROR(ERRDOS,ERRunknownlevel));
1625 /* Realloc the parameter and data sizes */
1626 params = *pparams = Realloc(*pparams,6);
1628 return(ERROR(ERRDOS,ERRnomem));
1630 SSVAL(params,0,fnf_handle);
1631 SSVAL(params,2,0); /* No changes */
1632 SSVAL(params,4,0); /* No EA errors */
1639 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1644 /****************************************************************************
1645 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1646 changes). Currently this does nothing.
1647 ****************************************************************************/
1648 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1649 int cnum, char **pparams, char **ppdata)
1651 char *params = *pparams;
1653 DEBUG(3,("call_trans2findnotifynext\n"));
1655 /* Realloc the parameter and data sizes */
1656 params = *pparams = Realloc(*pparams,4);
1658 return(ERROR(ERRDOS,ERRnomem));
1660 SSVAL(params,0,0); /* No changes */
1661 SSVAL(params,2,0); /* No EA errors */
1663 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1668 /****************************************************************************
1669 reply to a SMBfindclose (stop trans2 directory search)
1670 ****************************************************************************/
1671 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1675 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1677 cnum = SVAL(inbuf,smb_tid);
1679 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1681 dptr_close(dptr_num);
1683 outsize = set_message(outbuf,0,0,True);
1685 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1690 /****************************************************************************
1691 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1692 ****************************************************************************/
1693 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1699 cnum = SVAL(inbuf,smb_tid);
1700 dptr_num = SVAL(inbuf,smb_vwv0);
1702 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1704 /* We never give out valid handles for a
1705 findnotifyfirst - so any dptr_num is ok here.
1708 outsize = set_message(outbuf,0,0,True);
1710 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1716 /****************************************************************************
1717 reply to a SMBtranss2 - just ignore it!
1718 ****************************************************************************/
1719 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1721 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1725 /****************************************************************************
1726 reply to a SMBtrans2
1727 ****************************************************************************/
1728 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1731 int cnum = SVAL(inbuf,smb_tid);
1732 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1733 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1735 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1736 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1737 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1738 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1739 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1740 int32 timeout = IVALS(inbuf,smb_timeout);
1742 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1743 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1744 char *params = NULL, *data = NULL;
1745 int num_params, num_params_sofar, num_data, num_data_sofar;
1747 if(global_oplock_break && (tran_call == TRANSACT2_OPEN))
1750 * Queue this open message as we are the process of an oplock break.
1753 DEBUG(2,("%s: reply_trans2: queueing message trans2open due to being in oplock break state.\n",
1756 push_smb_message( inbuf, length);
1760 outsize = set_message(outbuf,0,0,True);
1762 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1763 is so as a sanity check */
1766 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1767 return(ERROR(ERRSRV,ERRerror));
1770 /* Allocate the space for the maximum needed parameters and data */
1771 if (total_params > 0)
1772 params = (char *)malloc(total_params);
1774 data = (char *)malloc(total_data);
1776 if ((total_params && !params) || (total_data && !data))
1778 DEBUG(2,("Out of memory in reply_trans2\n"));
1779 return(ERROR(ERRDOS,ERRnomem));
1782 /* Copy the param and data bytes sent with this request into
1783 the params buffer */
1784 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1785 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1787 if (num_params > total_params || num_data > total_data)
1788 exit_server("invalid params in reply_trans2");
1791 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1793 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1795 if(num_data_sofar < total_data || num_params_sofar < total_params)
1797 /* We need to send an interim response then receive the rest
1798 of the parameter/data bytes */
1799 outsize = set_message(outbuf,0,0,True);
1800 send_smb(Client,outbuf);
1802 while( num_data_sofar < total_data || num_params_sofar < total_params)
1806 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1807 SMB_SECONDARY_WAIT);
1809 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1811 outsize = set_message(outbuf,0,0,True);
1813 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1815 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1816 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1821 return(ERROR(ERRSRV,ERRerror));
1824 /* Revise total_params and total_data in case they have changed downwards */
1825 total_params = SVAL(inbuf, smb_tpscnt);
1826 total_data = SVAL(inbuf, smb_tdscnt);
1827 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1828 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1829 if (num_params_sofar > total_params || num_data_sofar > total_data)
1830 exit_server("data overflow in trans2");
1832 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1833 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1834 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1835 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1839 if (Protocol >= PROTOCOL_NT1) {
1840 uint16 flg2 = SVAL(outbuf,smb_flg2);
1841 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1844 /* Now we must call the relevant TRANS2 function */
1847 case TRANSACT2_OPEN:
1848 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1850 case TRANSACT2_FINDFIRST:
1851 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1853 case TRANSACT2_FINDNEXT:
1854 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1856 case TRANSACT2_QFSINFO:
1857 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1859 case TRANSACT2_SETFSINFO:
1860 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1862 case TRANSACT2_QPATHINFO:
1863 case TRANSACT2_QFILEINFO:
1864 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1866 case TRANSACT2_SETPATHINFO:
1867 case TRANSACT2_SETFILEINFO:
1868 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1870 case TRANSACT2_FINDNOTIFYFIRST:
1871 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1873 case TRANSACT2_FINDNOTIFYNEXT:
1874 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1876 case TRANSACT2_MKDIR:
1877 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1880 /* Error in request */
1881 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1886 return (ERROR(ERRSRV,ERRerror));
1889 /* As we do not know how many data packets will need to be
1890 returned here the various call_trans2xxxx calls
1891 must send their own. Thus a call_trans2xxx routine only
1892 returns a value other than -1 when it wants to send
1900 return outsize; /* If a correct response was needed the call_trans2xxx
1901 calls have already sent it. If outsize != -1 then it is
1902 returning an error packet. */