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;
34 extern dfs_internal dfs_struct;
36 /****************************************************************************
37 Send the required number of replies back.
38 We assume all fields other than the data fields are
39 set correctly for the type of call.
40 HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
43 int paramsize, char *pdata, int datasize)
45 /* As we are using a protocol > LANMAN1 then the max_send
46 variable must have been set in the sessetupX call.
47 This takes precedence over the max_xmit field in the
48 global struct. These different max_xmit variables should
49 be merged as this is now too confusing */
52 int data_to_send = datasize;
53 int params_to_send = paramsize;
57 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58 int alignment_offset = 3;
59 int data_alignment_offset = 0;
61 /* Initially set the wcnt area to be 10 - this is true for all
63 set_message(outbuf,10,0,True);
65 /* If there genuinely are no parameters or data to send just send
67 if(params_to_send == 0 && data_to_send == 0)
69 send_smb(Client,outbuf);
73 /* When sending params and data ensure that both are nicely aligned */
74 /* Only do this alignment when there is also data to send - else
75 can cause NT redirector problems. */
76 if (((params_to_send % 4) != 0) && (data_to_send != 0))
77 data_alignment_offset = 4 - (params_to_send % 4);
79 /* Space is bufsize minus Netbios over TCP header minus SMB header */
80 /* The alignment_offset is to align the param bytes on an even byte
81 boundary. NT 4.0 Beta needs this to work correctly. */
82 useable_space = bufsize - ((smb_buf(outbuf)+
83 alignment_offset+data_alignment_offset) -
86 /* useable_space can never be more than max_send minus the
88 useable_space = MIN(useable_space,
89 max_send - (alignment_offset+data_alignment_offset));
92 while (params_to_send || data_to_send)
94 /* Calculate whether we will totally or partially fill this packet */
95 total_sent_thistime = params_to_send + data_to_send +
96 alignment_offset + data_alignment_offset;
97 /* We can never send more than useable_space */
98 total_sent_thistime = MIN(total_sent_thistime, useable_space);
100 set_message(outbuf, 10, total_sent_thistime, True);
102 /* Set total params and data to be sent */
103 SSVAL(outbuf,smb_tprcnt,paramsize);
104 SSVAL(outbuf,smb_tdrcnt,datasize);
106 /* Calculate how many parameters and data we can fit into
107 this packet. Parameters get precedence */
109 params_sent_thistime = MIN(params_to_send,useable_space);
110 data_sent_thistime = useable_space - params_sent_thistime;
111 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
113 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
114 if(params_sent_thistime == 0)
116 /*SSVAL(outbuf,smb_proff,0);*/
117 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
118 SSVAL(outbuf,smb_prdisp,0);
122 /* smb_proff is the offset from the start of the SMB header to the
123 parameter bytes, however the first 4 bytes of outbuf are
124 the Netbios over TCP header. Thus use smb_base() to subtract
125 them from the calculation */
126 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
127 /* Absolute displacement of param bytes sent in this packet */
128 SSVAL(outbuf,smb_prdisp,pp - params);
131 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
132 if(data_sent_thistime == 0)
134 SSVAL(outbuf,smb_droff,0);
135 SSVAL(outbuf,smb_drdisp, 0);
139 /* The offset of the data bytes is the offset of the
140 parameter bytes plus the number of parameters being sent this time */
141 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
142 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
143 SSVAL(outbuf,smb_drdisp, pd - pdata);
146 /* Copy the param bytes into the packet */
147 if(params_sent_thistime)
148 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
149 /* Copy in the data bytes */
150 if(data_sent_thistime)
151 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
152 data_alignment_offset,pd,data_sent_thistime);
154 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
155 params_sent_thistime, data_sent_thistime, useable_space));
156 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
157 params_to_send, data_to_send, paramsize, datasize));
159 /* Send the packet */
160 send_smb(Client,outbuf);
162 pp += params_sent_thistime;
163 pd += data_sent_thistime;
165 params_to_send -= params_sent_thistime;
166 data_to_send -= data_sent_thistime;
169 if(params_to_send < 0 || data_to_send < 0)
171 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
172 params_to_send, data_to_send));
181 /****************************************************************************
182 reply to a TRANSACT2_OPEN
183 ****************************************************************************/
184 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
186 char **pparams, char **ppdata)
188 char *params = *pparams;
189 int16 open_mode = SVAL(params, 2);
190 int16 open_attr = SVAL(params,6);
191 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
193 BOOL return_additional_info = BITSETW(params,0);
194 int16 open_sattr = SVAL(params, 4);
195 time_t open_time = make_unix_date3(params+8);
197 int16 open_ofun = SVAL(params,12);
198 int32 open_size = IVAL(params,14);
199 char *pname = ¶ms[28];
200 int16 namelen = strlen(pname)+1;
205 int fmode=0,mtime=0,rmode;
207 SMB_STRUCT_STAT sbuf;
209 BOOL bad_path = False;
212 StrnCpy(fname,pname,namelen);
214 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
215 fname,open_mode, open_attr, open_ofun, open_size));
217 /* XXXX we need to handle passed times, sattr and flags */
219 unix_convert(fname,conn,0,&bad_path,NULL);
223 return(ERROR(ERRSRV,ERRnofids));
225 if (!check_name(fname,conn))
227 if((errno == ENOENT) && bad_path)
229 unix_ERR_class = ERRDOS;
230 unix_ERR_code = ERRbadpath;
233 return(UNIXERROR(ERRDOS,ERRnoaccess));
236 unixmode = unix_mode(conn,open_attr | aARCH);
238 open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
239 oplock_request, &rmode,&smb_action);
243 if((errno == ENOENT) && bad_path)
245 unix_ERR_class = ERRDOS;
246 unix_ERR_code = ERRbadpath;
249 return(UNIXERROR(ERRDOS,ERRnoaccess));
252 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
253 close_file(fsp,False);
254 return(UNIXERROR(ERRDOS,ERRnoaccess));
258 fmode = dos_mode(conn,fname,&sbuf);
259 mtime = sbuf.st_mtime;
262 close_file(fsp,False);
263 return(ERROR(ERRDOS,ERRnoaccess));
266 /* Realloc the size of parameters and data we will return */
267 params = *pparams = Realloc(*pparams, 28);
269 return(ERROR(ERRDOS,ERRnomem));
272 SSVAL(params,0,fsp->fnum);
273 SSVAL(params,2,fmode);
274 put_dos_date2(params,4, mtime);
275 SIVAL(params,8, (uint32)size);
276 SSVAL(params,12,rmode);
278 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
279 smb_action |= EXTENDED_OPLOCK_GRANTED;
282 SSVAL(params,18,smb_action);
284 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
286 SIVAL(params,20,inode);
288 /* Send the required number of replies */
289 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
294 /****************************************************************************
295 get a level dependent lanman2 dir entry.
296 ****************************************************************************/
297 static int get_lanman2_dir_entry(connection_struct *conn,
298 char *path_mask,int dirtype,int info_level,
299 int requires_resume_key,
300 BOOL dont_descend,char **ppdata,
301 char *base_data, int space_remaining,
307 SMB_STRUCT_STAT sbuf;
311 char *p, *pdata = *ppdata;
317 time_t mdate=0, adate=0, cdate=0;
319 BOOL isrootdir = (strequal(conn->dirpath,"./") ||
320 strequal(conn->dirpath,".") ||
321 strequal(conn->dirpath,"/"));
323 int nt_extmode; /* Used for NT connections instead of mode */
324 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
327 *out_of_space = False;
332 p = strrchr(path_mask,'/');
341 pstrcpy(mask, path_mask);
345 /* Needed if we run out of space */
346 prev_dirpos = TellDir(conn->dirptr);
347 dname = ReadDirName(conn->dirptr);
350 * Due to bugs in NT client redirectors we are not using
351 * resume keys any more - set them to zero.
352 * Check out the related comments in findfirst/findnext.
358 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
359 (long)conn->dirptr,TellDir(conn->dirptr)));
364 pstrcpy(fname,dname);
366 if(mask_match(fname, mask, case_sensitive, True))
368 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
369 if (dont_descend && !isdots)
372 if (isrootdir && isdots)
375 pstrcpy(pathreal,conn->dirpath);
377 pstrcat(pathreal,"/");
378 pstrcat(pathreal,dname);
379 if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0)
381 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
385 mode = dos_mode(conn,pathreal,&sbuf);
387 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
388 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
393 mdate = sbuf.st_mtime;
394 adate = sbuf.st_atime;
395 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
399 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
405 name_map_mangle(fname,False,SNUM(conn));
410 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
415 if(requires_resume_key) {
419 put_dos_date2(p,l1_fdateCreation,cdate);
420 put_dos_date2(p,l1_fdateLastAccess,adate);
421 put_dos_date2(p,l1_fdateLastWrite,mdate);
422 SIVAL(p,l1_cbFile,(uint32)size);
423 SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
424 SSVAL(p,l1_attrFile,mode);
425 SCVAL(p,l1_cchName,strlen(fname));
426 pstrcpy(p + l1_achName, fname);
427 nameptr = p + l1_achName;
428 p += l1_achName + strlen(fname) + 1;
433 if(requires_resume_key) {
437 put_dos_date2(p,l2_fdateCreation,cdate);
438 put_dos_date2(p,l2_fdateLastAccess,adate);
439 put_dos_date2(p,l2_fdateLastWrite,mdate);
440 SIVAL(p,l2_cbFile,(uint32)size);
441 SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
442 SSVAL(p,l2_attrFile,mode);
443 SIVAL(p,l2_cbList,0); /* No extended attributes */
444 SCVAL(p,l2_cchName,strlen(fname));
445 pstrcpy(p + l2_achName, fname);
446 nameptr = p + l2_achName;
447 p += l2_achName + strlen(fname) + 1;
452 put_dos_date2(p,4,cdate);
453 put_dos_date2(p,8,adate);
454 put_dos_date2(p,12,mdate);
455 SIVAL(p,16,(uint32)size);
456 SIVAL(p,20,SMB_ROUNDUP(size,1024));
459 CVAL(p,30) = strlen(fname);
460 pstrcpy(p+31, fname);
462 p += 31 + strlen(fname) + 1;
466 if(requires_resume_key) {
470 SIVAL(p,0,33+strlen(fname)+1);
471 put_dos_date2(p,4,cdate);
472 put_dos_date2(p,8,adate);
473 put_dos_date2(p,12,mdate);
474 SIVAL(p,16,(uint32)size);
475 SIVAL(p,20,SMB_ROUNDUP(size,1024));
477 CVAL(p,32) = strlen(fname);
478 pstrcpy(p + 33, fname);
480 p += 33 + strlen(fname) + 1;
483 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
484 was_8_3 = is_8_3(fname, True);
485 len = 94+strlen(fname);
486 len = (len + 3) & ~3;
487 SIVAL(p,0,len); p += 4;
488 SIVAL(p,0,reskey); p += 4;
489 put_long_date(p,cdate); p += 8;
490 put_long_date(p,adate); p += 8;
491 put_long_date(p,mdate); p += 8;
492 put_long_date(p,mdate); p += 8;
496 SIVAL(p,0,nt_extmode); p += 4;
497 SIVAL(p,0,strlen(fname)); p += 4;
498 SIVAL(p,0,0); p += 4;
501 if (!name_map_mangle(p+2,True,SNUM(conn)))
506 SSVAL(p,0,strlen(p+2));
509 pstrcpy(p,fname); p += strlen(p);
513 case SMB_FIND_FILE_DIRECTORY_INFO:
514 len = 64+strlen(fname);
515 len = (len + 3) & ~3;
516 SIVAL(p,0,len); p += 4;
517 SIVAL(p,0,reskey); p += 4;
518 put_long_date(p,cdate); p += 8;
519 put_long_date(p,adate); p += 8;
520 put_long_date(p,mdate); p += 8;
521 put_long_date(p,mdate); p += 8;
525 SIVAL(p,0,nt_extmode); p += 4;
526 SIVAL(p,0,strlen(fname)); p += 4;
532 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
533 len = 68+strlen(fname);
534 len = (len + 3) & ~3;
535 SIVAL(p,0,len); p += 4;
536 SIVAL(p,0,reskey); p += 4;
537 put_long_date(p,cdate); p += 8;
538 put_long_date(p,adate); p += 8;
539 put_long_date(p,mdate); p += 8;
540 put_long_date(p,mdate); p += 8;
544 SIVAL(p,0,nt_extmode); p += 4;
545 SIVAL(p,0,strlen(fname)); p += 4;
546 SIVAL(p,0,0); p += 4;
551 case SMB_FIND_FILE_NAMES_INFO:
552 len = 12+strlen(fname);
553 len = (len + 3) & ~3;
554 SIVAL(p,0,len); p += 4;
555 SIVAL(p,0,reskey); p += 4;
556 SIVAL(p,0,strlen(fname)); p += 4;
566 if (PTR_DIFF(p,pdata) > space_remaining) {
567 /* Move the dirptr back to prev_dirpos */
568 SeekDir(conn->dirptr, prev_dirpos);
569 *out_of_space = True;
570 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
571 return False; /* Not finished - just out of space */
574 /* Setup the last_filename pointer, as an offset from base_data */
575 *last_name_off = PTR_DIFF(nameptr,base_data);
576 /* Advance the data pointer to the next slot */
581 /****************************************************************************
582 Convert the directory masks formated for the wire.
583 ****************************************************************************/
585 void mask_convert( char *mask)
588 * We know mask is a pstring.
594 if(p[1] != '"' && p[1] != '.') {
595 pstrcpy( expnd, p+1 );
598 safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
602 if (*p == '>') *p = '?';
603 if (*p == '"') *p = '.';
608 /****************************************************************************
609 reply to a TRANS2_FINDFIRST
610 ****************************************************************************/
611 static int call_trans2findfirst(connection_struct *conn,
612 char *inbuf, char *outbuf, int bufsize,
613 char **pparams, char **ppdata)
615 /* We must be careful here that we don't return more than the
616 allowed number of data bytes. If this means returning fewer than
617 maxentries then so be it. We assume that the redirector has
618 enough room for the fixed number of parameter bytes it has
620 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
621 char *params = *pparams;
622 char *pdata = *ppdata;
623 int dirtype = SVAL(params,0);
624 int maxentries = SVAL(params,2);
625 BOOL close_after_first = BITSETW(params+4,0);
626 BOOL close_if_end = BITSETW(params+4,1);
627 BOOL requires_resume_key = BITSETW(params+4,2);
628 int info_level = SVAL(params,6);
636 BOOL finished = False;
637 BOOL dont_descend = False;
638 BOOL out_of_space = False;
640 BOOL bad_path = False;
642 *directory = *mask = 0;
644 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",
645 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
646 info_level, max_data_bytes));
654 case SMB_FIND_FILE_DIRECTORY_INFO:
655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
656 case SMB_FIND_FILE_NAMES_INFO:
657 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
660 return(ERROR(ERRDOS,ERRunknownlevel));
663 pstrcpy(directory, params + 12); /* Complete directory path with
664 wildcard mask appended */
666 DEBUG(5,("path=%s\n",directory));
668 unix_convert(directory,conn,0,&bad_path,NULL);
669 if(!check_name(directory,conn)) {
670 if((errno == ENOENT) && bad_path)
672 unix_ERR_class = ERRDOS;
673 unix_ERR_code = ERRbadpath;
677 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
678 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
679 (get_remote_arch() == RA_WINNT))
681 unix_ERR_class = ERRDOS;
682 unix_ERR_code = ERRbaddirectory;
686 return(UNIXERROR(ERRDOS,ERRbadpath));
689 p = strrchr(directory,'/');
691 pstrcpy(mask,directory);
692 pstrcpy(directory,"./");
698 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
700 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
702 return(ERROR(ERRDOS,ERRnomem));
703 bzero(pdata,max_data_bytes);
705 /* Realloc the params space */
706 params = *pparams = Realloc(*pparams, 10);
708 return(ERROR(ERRDOS,ERRnomem));
710 dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
712 return(UNIXERROR(ERRDOS,ERRbadfile));
714 /* Convert the formatted mask. */
719 * Now we have a working mask_match in util.c, I believe
720 * we no longer need these hacks (in fact they break
724 /* a special case for 16 bit apps */
725 if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
727 /* handle broken clients that send us old 8.3 format */
728 string_sub(mask,"????????","*");
729 string_sub(mask,".???",".*");
732 /* Save the wildcard match and attribs we are using on this directory -
733 needed as lanman2 assumes these are being saved between calls */
735 if(!(wcard = strdup(mask))) {
736 dptr_close(dptr_num);
737 return(ERROR(ERRDOS,ERRnomem));
740 dptr_set_wcard(dptr_num, wcard);
741 dptr_set_attr(dptr_num, dirtype);
743 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
745 /* We don't need to check for VOL here as this is returned by
746 a different TRANS2 call. */
748 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
749 conn->dirpath,lp_dontdescend(SNUM(conn))));
750 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
754 space_remaining = max_data_bytes;
755 out_of_space = False;
757 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
760 /* this is a heuristic to avoid seeking the dirptr except when
761 absolutely necessary. It allows for a filename of about 40 chars */
762 if (space_remaining < DIRLEN_GUESS && numentries > 0)
770 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
771 requires_resume_key,dont_descend,
772 &p,pdata,space_remaining, &out_of_space,
776 if (finished && out_of_space)
779 if (!finished && !out_of_space)
781 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
784 /* Check if we can close the dirptr */
785 if(close_after_first || (finished && close_if_end))
787 dptr_close(dptr_num);
788 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
793 * If there are no matching entries we must return ERRDOS/ERRbadfile -
794 * from observation of NT.
798 return(ERROR(ERRDOS,ERRbadfile));
800 /* At this point pdata points to numentries directory entries. */
802 /* Set up the return parameter block */
803 SSVAL(params,0,dptr_num);
804 SSVAL(params,2,numentries);
805 SSVAL(params,4,finished);
806 SSVAL(params,6,0); /* Never an EA error */
807 SSVAL(params,8,last_name_off);
809 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
811 if ((! *directory) && dptr_path(dptr_num))
812 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
814 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
815 smb_fn_name(CVAL(inbuf,smb_com)),
816 mask, directory, dirtype, numentries ) );
822 /****************************************************************************
823 reply to a TRANS2_FINDNEXT
824 ****************************************************************************/
825 static int call_trans2findnext(connection_struct *conn,
826 char *inbuf, char *outbuf,
827 int length, int bufsize,
828 char **pparams, char **ppdata)
830 /* We must be careful here that we don't return more than the
831 allowed number of data bytes. If this means returning fewer than
832 maxentries then so be it. We assume that the redirector has
833 enough room for the fixed number of parameter bytes it has
835 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
836 char *params = *pparams;
837 char *pdata = *ppdata;
838 int16 dptr_num = SVAL(params,0);
839 int maxentries = SVAL(params,2);
840 uint16 info_level = SVAL(params,4);
841 uint32 resume_key = IVAL(params,6);
842 BOOL close_after_request = BITSETW(params+10,0);
843 BOOL close_if_end = BITSETW(params+10,1);
844 BOOL requires_resume_key = BITSETW(params+10,2);
845 BOOL continue_bit = BITSETW(params+10,3);
852 int i, last_name_off=0;
853 BOOL finished = False;
854 BOOL dont_descend = False;
855 BOOL out_of_space = False;
858 *mask = *directory = *resume_name = 0;
860 pstrcpy( resume_name, params+12);
862 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
863 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
864 resume_key = %d resume name = %s continue=%d level = %d\n",
865 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
866 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
874 case SMB_FIND_FILE_DIRECTORY_INFO:
875 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
876 case SMB_FIND_FILE_NAMES_INFO:
877 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
880 return(ERROR(ERRDOS,ERRunknownlevel));
883 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
885 return(ERROR(ERRDOS,ERRnomem));
886 bzero(pdata,max_data_bytes);
888 /* Realloc the params space */
889 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
891 return(ERROR(ERRDOS,ERRnomem));
893 /* Check that the dptr is valid */
894 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
895 return(ERROR(ERRDOS,ERRnofiles));
897 string_set(&conn->dirpath,dptr_path(dptr_num));
899 /* Get the wildcard mask from the dptr */
900 if((p = dptr_wcard(dptr_num))== NULL) {
901 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
902 return (ERROR(ERRDOS,ERRnofiles));
905 pstrcpy(directory,conn->dirpath);
907 /* Get the attr mask from the dptr */
908 dirtype = dptr_attr(dptr_num);
910 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
911 dptr_num, mask, dirtype,
913 TellDir(conn->dirptr)));
915 /* We don't need to check for VOL here as this is returned by
916 a different TRANS2 call. */
918 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
919 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
923 space_remaining = max_data_bytes;
924 out_of_space = False;
927 * Seek to the correct position. We no longer use the resume key but
928 * depend on the last file name instead.
930 if(requires_resume_key && *resume_name && !continue_bit)
933 * Fix for NT redirector problem triggered by resume key indexes
934 * changing between directory scans. We now return a resume key of 0
935 * and instead look for the filename to continue from (also given
936 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
937 * findfirst/findnext (as is usual) then the directory pointer
938 * should already be at the correct place. Check this by scanning
939 * backwards looking for an exact (ie. case sensitive) filename match.
940 * If we get to the beginning of the directory and haven't found it then scan
941 * forwards again looking for a match. JRA.
944 int current_pos, start_pos;
946 void *dirptr = conn->dirptr;
947 start_pos = TellDir(dirptr);
948 for(current_pos = start_pos; current_pos >= 0; current_pos--)
950 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
952 SeekDir(dirptr, current_pos);
953 dname = ReadDirName(dirptr);
956 * Remember, name_map_mangle is called by
957 * get_lanman2_dir_entry(), so the resume name
958 * could be mangled. Ensure we do the same
963 name_map_mangle( dname, False, SNUM(conn));
965 if(dname && strcsequal( resume_name, dname))
967 SeekDir(dirptr, current_pos+1);
968 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
974 * Scan forward from start if not found going backwards.
979 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
980 SeekDir(dirptr, start_pos);
981 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
984 * Remember, name_map_mangle is called by
985 * get_lanman2_dir_entry(), so the resume name
986 * could be mangled. Ensure we do the same
991 name_map_mangle( dname, False, SNUM(conn));
993 if(dname && strcsequal( resume_name, dname))
995 SeekDir(dirptr, current_pos+1);
996 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1000 } /* end if current_pos */
1001 } /* end if requires_resume_key && !continue_bit */
1003 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1005 /* this is a heuristic to avoid seeking the dirptr except when
1006 absolutely necessary. It allows for a filename of about 40 chars */
1007 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1009 out_of_space = True;
1015 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1016 requires_resume_key,dont_descend,
1017 &p,pdata,space_remaining, &out_of_space,
1021 if (finished && out_of_space)
1024 if (!finished && !out_of_space)
1026 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1029 /* Check if we can close the dirptr */
1030 if(close_after_request || (finished && close_if_end))
1032 dptr_close(dptr_num); /* This frees up the saved mask */
1033 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1038 /* Set up the return parameter block */
1039 SSVAL(params,0,numentries);
1040 SSVAL(params,2,finished);
1041 SSVAL(params,4,0); /* Never an EA error */
1042 SSVAL(params,6,last_name_off);
1044 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1046 if ((! *directory) && dptr_path(dptr_num))
1047 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1049 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1050 smb_fn_name(CVAL(inbuf,smb_com)),
1051 mask, directory, dirtype, numentries ) );
1056 /****************************************************************************
1057 reply to a TRANS2_QFSINFO (query filesystem info)
1058 ****************************************************************************/
1060 static int call_trans2qfsinfo(connection_struct *conn,
1061 char *inbuf, char *outbuf,
1062 int length, int bufsize,
1063 char **pparams, char **ppdata)
1065 char *pdata = *ppdata;
1066 char *params = *pparams;
1067 uint16 info_level = SVAL(params,0);
1070 char *vname = volume_label(SNUM(conn));
1071 int snum = SNUM(conn);
1072 char *fstype = lp_fstype(SNUM(conn));
1073 extern uint32 global_client_caps;
1075 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1077 if(conn->vfs_ops.stat(".",&st)!=0) {
1078 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1079 return (ERROR(ERRSRV,ERRinvdevice));
1082 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1088 SMB_BIG_UINT dfree,dsize,bsize;
1090 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1091 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1092 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1093 SIVAL(pdata,l1_cUnit,dsize);
1094 SIVAL(pdata,l1_cUnitAvail,dfree);
1095 SSVAL(pdata,l1_cbSector,512);
1096 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1097 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1098 (unsigned int)dfree, 512));
1103 /* Return volume name */
1104 int volname_len = MIN(strlen(vname),11);
1105 data_len = l2_vol_szVolLabel + volname_len + 1;
1107 * Add volume serial number - hash of a combination of
1108 * the called hostname and the service name.
1110 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1111 SCVAL(pdata,l2_vol_cch,volname_len);
1112 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1113 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1114 (unsigned)st.st_ctime, volname_len,
1115 pdata+l2_vol_szVolLabel));
1118 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1119 data_len = 12 + 2*strlen(fstype);
1120 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */
1121 #if 0 /* Old code. JRA. */
1122 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1123 #endif /* Old code. */
1124 SIVAL(pdata,4,128); /* Max filename component length */
1125 SIVAL(pdata,8,2*strlen(fstype));
1126 ascii_to_unibuf(pdata+12, fstype, 1024-2-12);
1127 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1129 case SMB_QUERY_FS_LABEL_INFO:
1130 data_len = 4 + strlen(vname);
1131 SIVAL(pdata,0,strlen(vname));
1132 pstrcpy(pdata+4,vname);
1134 case SMB_QUERY_FS_VOLUME_INFO:
1137 * Add volume serial number - hash of a combination of
1138 * the called hostname and the service name.
1140 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1141 (str_checksum(local_machine)<<16));
1143 /* NT4 always serves this up as unicode but expects it to be
1144 * delivered as ascii! (tridge && JRA)
1146 if (global_client_caps & CAP_NT_SMBS) {
1147 data_len = 18 + strlen(vname);
1148 SIVAL(pdata,12,strlen(vname));
1149 pstrcpy(pdata+18,vname);
1151 data_len = 18 + 2*strlen(vname);
1152 SIVAL(pdata,12,strlen(vname)*2);
1153 ascii_to_unibuf(pdata+18, vname, 1024-2-18);
1156 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1157 strlen(vname),vname));
1159 case SMB_QUERY_FS_SIZE_INFO:
1161 SMB_BIG_UINT dfree,dsize,bsize;
1163 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1164 SIVAL(pdata,0,dsize);
1165 SIVAL(pdata,8,dfree);
1166 SIVAL(pdata,16,bsize/512);
1167 SIVAL(pdata,20,512);
1170 case SMB_QUERY_FS_DEVICE_INFO:
1172 SIVAL(pdata,0,0); /* dev type */
1173 SIVAL(pdata,4,0); /* characteristics */
1175 case SMB_MAC_QUERY_FS_INFO:
1177 * Thursby MAC extension... ONLY on NTFS filesystems
1178 * once we do streams then we don't need this
1180 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1182 SIVAL(pdata,84,0x100); /* Don't support mac... */
1187 return(ERROR(ERRDOS,ERRunknownlevel));
1191 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1193 DEBUG( 4, ( "%s info_level = %d\n",
1194 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1199 /****************************************************************************
1200 reply to a TRANS2_SETFSINFO (set filesystem info)
1201 ****************************************************************************/
1202 static int call_trans2setfsinfo(connection_struct *conn,
1203 char *inbuf, char *outbuf, int length,
1205 char **pparams, char **ppdata)
1207 /* Just say yes we did it - there is nothing that
1208 can be set here so it doesn't matter. */
1210 DEBUG(3,("call_trans2setfsinfo\n"));
1212 if (!CAN_WRITE(conn))
1213 return(ERROR(ERRSRV,ERRaccess));
1215 outsize = set_message(outbuf,10,0,True);
1220 /****************************************************************************
1221 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1222 file name or file id).
1223 ****************************************************************************/
1225 static int call_trans2qfilepathinfo(connection_struct *conn,
1226 char *inbuf, char *outbuf, int length,
1228 char **pparams,char **ppdata,
1231 char *params = *pparams;
1232 char *pdata = *ppdata;
1233 uint16 tran_call = SVAL(inbuf, smb_setup0);
1237 unsigned int data_size;
1238 SMB_STRUCT_STAT sbuf;
1244 BOOL bad_path = False;
1245 BOOL delete_pending = False;
1247 if (tran_call == TRANSACT2_QFILEINFO) {
1248 files_struct *fsp = file_fsp(params,0);
1249 info_level = SVAL(params,2);
1251 if(fsp && fsp->open && fsp->is_directory) {
1253 * This is actually a QFILEINFO on a directory
1254 * handle (returned from an NT SMB). NT5.0 seems
1255 * to do this call. JRA.
1257 fname = fsp->fsp_name;
1258 unix_convert(fname,conn,0,&bad_path,&sbuf);
1259 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) &&
1260 conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
1261 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1262 if((errno == ENOENT) && bad_path)
1264 unix_ERR_class = ERRDOS;
1265 unix_ERR_code = ERRbadpath;
1267 return(UNIXERROR(ERRDOS,ERRbadpath));
1271 * Original code - this is an open file.
1273 CHECK_FSP(fsp,conn);
1276 fname = fsp->fsp_name;
1277 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1278 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1279 return(UNIXERROR(ERRDOS,ERRbadfid));
1281 if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1282 return(UNIXERROR(ERRDOS,ERRnoaccess));
1284 delete_pending = fsp->fd_ptr->delete_on_close;
1288 info_level = SVAL(params,0);
1290 pstrcpy(fname,¶ms[6]);
1291 unix_convert(fname,conn,0,&bad_path,&sbuf);
1292 if (!check_name(fname,conn) ||
1293 (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),
1295 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1296 if((errno == ENOENT) && bad_path)
1298 unix_ERR_class = ERRDOS;
1299 unix_ERR_code = ERRbadpath;
1301 return(UNIXERROR(ERRDOS,ERRbadpath));
1306 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1307 fname,info_level,tran_call,total_data));
1309 p = strrchr(fname,'/');
1315 mode = dos_mode(conn,fname,&sbuf);
1316 size = sbuf.st_size;
1317 if (mode & aDIR) size = 0;
1319 /* from now on we only want the part after the / */
1322 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1324 pdata = *ppdata = Realloc(*ppdata, data_size);
1326 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1327 /* uggh, EAs for OS2 */
1328 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1329 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1332 bzero(pdata,data_size);
1336 case SMB_INFO_STANDARD:
1337 case SMB_INFO_QUERY_EA_SIZE:
1338 data_size = (info_level==1?22:26);
1339 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1340 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1341 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1342 SIVAL(pdata,l1_cbFile,(uint32)size);
1343 SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1344 SSVAL(pdata,l1_attrFile,mode);
1345 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1348 case SMB_INFO_QUERY_EAS_FROM_LIST:
1350 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1351 put_dos_date2(pdata,4,sbuf.st_atime);
1352 put_dos_date2(pdata,8,sbuf.st_mtime);
1353 SIVAL(pdata,12,(uint32)size);
1354 SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1355 SIVAL(pdata,20,mode);
1358 case SMB_INFO_QUERY_ALL_EAS:
1360 SIVAL(pdata,0,data_size);
1364 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1366 case SMB_QUERY_FILE_BASIC_INFO:
1367 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1368 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1369 put_long_date(pdata+8,sbuf.st_atime);
1370 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1371 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1372 SIVAL(pdata,32,mode);
1374 DEBUG(5,("SMB_QFBI - "));
1376 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1377 DEBUG(5,("create: %s ", ctime(&create_time)));
1379 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1380 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1381 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1382 DEBUG(5,("mode: %x\n", mode));
1386 case SMB_QUERY_FILE_STANDARD_INFO:
1388 SOFF_T(pdata,0,size);
1389 SOFF_T(pdata,8,size);
1390 SIVAL(pdata,16,sbuf.st_nlink);
1392 CVAL(pdata,21) = (mode&aDIR)?1:0;
1395 case SMB_QUERY_FILE_EA_INFO:
1399 /* Get the 8.3 name - used if NT SMB was negotiated. */
1400 case SMB_QUERY_FILE_ALT_NAME_INFO:
1405 pstrcpy(short_name,p);
1406 /* Mangle if not already 8.3 */
1407 if(!is_8_3(short_name, True))
1409 if(!name_map_mangle(short_name,True,SNUM(conn)))
1412 strupper(short_name);
1413 data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4);
1414 data_size = data_end - pdata;
1415 SIVAL(pdata,0,2*(data_size-4));
1419 case SMB_QUERY_FILE_NAME_INFO:
1422 pstrcpy(pdata+4,fname);
1425 case SMB_QUERY_FILE_ALLOCATION_INFO:
1426 case SMB_QUERY_FILE_END_OF_FILEINFO:
1428 SOFF_T(pdata,0,size);
1431 case SMB_QUERY_FILE_ALL_INFO:
1432 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1433 put_long_date(pdata+8,sbuf.st_atime);
1434 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1435 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1436 SIVAL(pdata,32,mode);
1438 SOFF_T(pdata,0,size);
1439 SOFF_T(pdata,8,size);
1440 SIVAL(pdata,16,sbuf.st_nlink);
1441 CVAL(pdata,20) = delete_pending;
1442 CVAL(pdata,21) = (mode&aDIR)?1:0;
1444 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1445 pdata += 8; /* index number */
1446 pdata += 4; /* EA info */
1448 SIVAL(pdata,0,0xA9);
1450 SIVAL(pdata,0,0xd01BF);
1452 SOFF_T(pdata,0,pos); /* current offset */
1454 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1456 pdata += 4; /* alignment */
1458 pstrcpy(pdata+4,fname);
1460 data_size = PTR_DIFF(pdata,(*ppdata));
1464 /* NT4 server just returns "invalid query" to this - if we try to answer
1465 it then NTws gets a BSOD! (tridge) */
1466 case SMB_QUERY_FILE_STREAM_INFO:
1469 SIVAL(pdata,4,size);
1470 SIVAL(pdata,12,size);
1472 pstrcpy(pdata+24,fname);
1477 return(ERROR(ERRDOS,ERRunknownlevel));
1480 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1485 /****************************************************************************
1486 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1487 ****************************************************************************/
1488 static int call_trans2setfilepathinfo(connection_struct *conn,
1489 char *inbuf, char *outbuf, int length,
1490 int bufsize, char **pparams,
1491 char **ppdata, int total_data)
1493 char *params = *pparams;
1494 char *pdata = *ppdata;
1495 uint16 tran_call = SVAL(inbuf, smb_setup0);
1504 BOOL bad_path = False;
1505 files_struct *fsp = NULL;
1507 if (!CAN_WRITE(conn))
1508 return(ERROR(ERRSRV,ERRaccess));
1510 if (tran_call == TRANSACT2_SETFILEINFO) {
1511 fsp = file_fsp(params,0);
1512 info_level = SVAL(params,2);
1514 if(fsp && fsp->open && fsp->is_directory) {
1516 * This is actually a SETFILEINFO on a directory
1517 * handle (returned from an NT SMB). NT5.0 seems
1518 * to do this call. JRA.
1520 fname = fsp->fsp_name;
1521 unix_convert(fname,conn,0,&bad_path,&st);
1522 if (!check_name(fname,conn) || (!VALID_STAT(st) &&
1523 conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
1524 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1525 if((errno == ENOENT) && bad_path)
1527 unix_ERR_class = ERRDOS;
1528 unix_ERR_code = ERRbadpath;
1530 return(UNIXERROR(ERRDOS,ERRbadpath));
1534 * Original code - this is an open file.
1536 CHECK_FSP(fsp,conn);
1539 fname = fsp->fsp_name;
1540 fd = fsp->fd_ptr->fd;
1542 if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
1543 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1544 return(UNIXERROR(ERRDOS,ERRbadfid));
1549 info_level = SVAL(params,0);
1551 pstrcpy(fname,¶ms[6]);
1552 unix_convert(fname,conn,0,&bad_path,&st);
1553 if(!check_name(fname, conn))
1555 if((errno == ENOENT) && bad_path)
1557 unix_ERR_class = ERRDOS;
1558 unix_ERR_code = ERRbadpath;
1560 return(UNIXERROR(ERRDOS,ERRbadpath));
1563 if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
1564 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1565 if((errno == ENOENT) && bad_path)
1567 unix_ERR_class = ERRDOS;
1568 unix_ERR_code = ERRbadpath;
1570 return(UNIXERROR(ERRDOS,ERRbadpath));
1574 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1575 tran_call,fname,info_level,total_data));
1577 /* Realloc the parameter and data sizes */
1578 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1580 return(ERROR(ERRDOS,ERRnomem));
1583 tvs.modtime = st.st_mtime;
1584 tvs.actime = st.st_atime;
1585 mode = dos_mode(conn,fname,&st);
1587 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1588 /* uggh, EAs for OS2 */
1589 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1590 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1595 case SMB_INFO_STANDARD:
1596 case SMB_INFO_QUERY_EA_SIZE:
1599 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1602 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1604 mode = SVAL(pdata,l1_attrFile);
1605 size = IVAL(pdata,l1_cbFile);
1609 /* XXXX um, i don't think this is right.
1610 it's also not in the cifs6.txt spec.
1612 case SMB_INFO_QUERY_EAS_FROM_LIST:
1613 tvs.actime = make_unix_date2(pdata+8);
1614 tvs.modtime = make_unix_date2(pdata+12);
1615 size = IVAL(pdata,16);
1616 mode = IVAL(pdata,24);
1619 /* XXXX nor this. not in cifs6.txt, either. */
1620 case SMB_INFO_QUERY_ALL_EAS:
1621 tvs.actime = make_unix_date2(pdata+8);
1622 tvs.modtime = make_unix_date2(pdata+12);
1623 size = IVAL(pdata,16);
1624 mode = IVAL(pdata,24);
1627 case SMB_SET_FILE_BASIC_INFO:
1629 /* Ignore create time at offset pdata. */
1632 tvs.actime = interpret_long_date(pdata+8);
1634 /* write time + changed time, combined. */
1635 tvs.modtime=MAX(interpret_long_date(pdata+16),
1636 interpret_long_date(pdata+24));
1638 #if 0 /* Needs more testing... */
1639 /* Test from Luke to prevent Win95 from
1640 setting incorrect values here.
1642 if (tvs.actime < tvs.modtime)
1643 return(ERROR(ERRDOS,ERRnoaccess));
1644 #endif /* Needs more testing... */
1647 mode = IVAL(pdata,32);
1651 case SMB_SET_FILE_END_OF_FILE_INFO:
1653 size = IVAL(pdata,0);
1654 #ifdef LARGE_SMB_OFF_T
1655 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1656 #else /* LARGE_SMB_OFF_T */
1657 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1658 return(ERROR(ERRDOS,ERRunknownlevel));
1659 #endif /* LARGE_SMB_OFF_T */
1663 case SMB_SET_FILE_ALLOCATION_INFO:
1664 break; /* We don't need to do anything for this call. */
1666 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1668 if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1670 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1672 if(fsp->is_directory)
1673 return(ERROR(ERRDOS,ERRnoaccess));
1676 * We can only set the delete on close flag if
1677 * the share mode contained ALLOW_SHARE_DELETE
1680 if(lp_share_modes(SNUM(conn)))
1682 if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1683 return(ERROR(ERRDOS,ERRnoaccess));
1686 * If the flag has been set then
1687 * modify the share mode entry for all files we have open
1688 * on this device and inode to tell other smbds we have
1689 * changed the delete on close flag.
1692 if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1696 files_struct *iterate_fsp;
1697 SMB_DEV_T dev = fsp->fd_ptr->dev;
1698 SMB_INO_T inode = fsp->fd_ptr->inode;
1699 int num_share_modes;
1700 share_mode_entry *current_shares = NULL;
1702 if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1703 return(ERROR(ERRDOS,ERRnoaccess));
1706 * Before we allow this we need to ensure that all current opens
1707 * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1708 * do not then we deny this (as we are essentially deleting the
1709 * file at this point.
1712 num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares);
1713 for(i = 0; i < num_share_modes; i++)
1715 if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1717 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1718 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1719 fsp->fnum, fsp->fsp_name ));
1724 unlock_share_entry(fsp->conn, dev, inode, token);
1727 * current_shares was malloced by get_share_modes - free it here.
1730 free((char *)current_shares);
1733 * Even though share violation would be more appropriate here,
1734 * return ERRnoaccess as that's what NT does.
1737 return(ERROR(ERRDOS,ERRnoaccess));
1742 * current_shares was malloced by get_share_modes - free it here.
1745 free((char *)current_shares);
1747 DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1748 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1751 * Go through all files we have open on the same device and
1752 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1753 * Other smbd's that have this file open will have to fend for themselves. We
1754 * take care of this (rare) case in close_file(). See the comment there.
1757 for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1758 iterate_fsp = file_find_di_next(iterate_fsp))
1760 int new_share_mode = (delete_on_close ?
1761 (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1762 (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1764 DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1765 dev = %x, inode = %.0f from %x to %x\n",
1766 iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
1767 (double)inode, iterate_fsp->share_mode, new_share_mode ));
1769 if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1770 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1771 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1775 * Set the delete on close flag in the reference
1776 * counted struct. Delete when the last reference
1779 fsp->fd_ptr->delete_on_close = delete_on_close;
1780 unlock_share_entry(fsp->conn, dev, inode, token);
1782 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1783 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1785 } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1786 } /* end if lp_share_modes() */
1789 return(ERROR(ERRDOS,ERRunknownlevel));
1795 return(ERROR(ERRDOS,ERRunknownlevel));
1799 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1800 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1801 DEBUG(6,("size: %.0f ", (double)size));
1802 DEBUG(6,("mode: %x\n" , mode));
1804 /* get some defaults (no modifications) if any info is zero. */
1805 if (!tvs.actime) tvs.actime = st.st_atime;
1806 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1807 if (!size) size = st.st_size;
1809 /* Try and set the times, size and mode of this file -
1810 if they are different from the current values
1812 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1817 * This was a setfileinfo on an open file.
1818 * NT does this a lot. It's actually pointless
1819 * setting the time here, as it will be overwritten
1820 * on the next write, so we save the request
1821 * away and will set it on file code. JRA.
1823 fsp->pending_modtime = tvs.modtime;
1825 else if(file_utime(conn, fname, &tvs)!=0)
1827 return(UNIXERROR(ERRDOS,ERRnoaccess));
1831 /* check the mode isn't different, before changing it */
1832 if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1834 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1835 return(UNIXERROR(ERRDOS,ERRnoaccess));
1838 if(size != st.st_size)
1842 DEBUG(0, ("@@@ 23 @@@\n"));
1843 fd = dos_open(fname,O_RDWR,0);
1846 return(UNIXERROR(ERRDOS,ERRbadpath));
1848 set_filelen(fd, size);
1853 set_filelen(fd, size);
1859 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1864 /****************************************************************************
1865 reply to a TRANS2_MKDIR (make directory with extended attributes).
1866 ****************************************************************************/
1867 static int call_trans2mkdir(connection_struct *conn,
1868 char *inbuf, char *outbuf, int length, int bufsize,
1869 char **pparams, char **ppdata)
1871 char *params = *pparams;
1874 BOOL bad_path = False;
1876 if (!CAN_WRITE(conn))
1877 return(ERROR(ERRSRV,ERRaccess));
1879 pstrcpy(directory, ¶ms[4]);
1881 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1883 unix_convert(directory,conn,0,&bad_path,NULL);
1884 if (check_name(directory,conn))
1885 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
1886 unix_mode(conn,aDIR));
1890 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1891 if((errno == ENOENT) && bad_path)
1893 unix_ERR_class = ERRDOS;
1894 unix_ERR_code = ERRbadpath;
1896 return(UNIXERROR(ERRDOS,ERRnoaccess));
1899 /* Realloc the parameter and data sizes */
1900 params = *pparams = Realloc(*pparams,2);
1902 return(ERROR(ERRDOS,ERRnomem));
1906 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1911 /****************************************************************************
1912 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1913 We don't actually do this - we just send a null response.
1914 ****************************************************************************/
1915 static int call_trans2findnotifyfirst(connection_struct *conn,
1916 char *inbuf, char *outbuf,
1917 int length, int bufsize,
1918 char **pparams, char **ppdata)
1920 static uint16 fnf_handle = 257;
1921 char *params = *pparams;
1922 uint16 info_level = SVAL(params,4);
1924 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1932 return(ERROR(ERRDOS,ERRunknownlevel));
1935 /* Realloc the parameter and data sizes */
1936 params = *pparams = Realloc(*pparams,6);
1938 return(ERROR(ERRDOS,ERRnomem));
1940 SSVAL(params,0,fnf_handle);
1941 SSVAL(params,2,0); /* No changes */
1942 SSVAL(params,4,0); /* No EA errors */
1949 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1954 /****************************************************************************
1955 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1956 changes). Currently this does nothing.
1957 ****************************************************************************/
1958 static int call_trans2findnotifynext(connection_struct *conn,
1959 char *inbuf, char *outbuf,
1960 int length, int bufsize,
1961 char **pparams, char **ppdata)
1963 char *params = *pparams;
1965 DEBUG(3,("call_trans2findnotifynext\n"));
1967 /* Realloc the parameter and data sizes */
1968 params = *pparams = Realloc(*pparams,4);
1970 return(ERROR(ERRDOS,ERRnomem));
1972 SSVAL(params,0,0); /* No changes */
1973 SSVAL(params,2,0); /* No EA errors */
1975 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1980 /****************************************************************************
1981 reply to a SMBfindclose (stop trans2 directory search)
1982 ****************************************************************************/
1983 int reply_findclose(connection_struct *conn,
1984 char *inbuf,char *outbuf,int length,int bufsize)
1987 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1989 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1991 dptr_close(dptr_num);
1993 outsize = set_message(outbuf,0,0,True);
1995 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2000 /****************************************************************************
2001 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2002 ****************************************************************************/
2003 int reply_findnclose(connection_struct *conn,
2004 char *inbuf,char *outbuf,int length,int bufsize)
2009 dptr_num = SVAL(inbuf,smb_vwv0);
2011 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2013 /* We never give out valid handles for a
2014 findnotifyfirst - so any dptr_num is ok here.
2017 outsize = set_message(outbuf,0,0,True);
2019 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2024 /****************************************************************************
2025 reply to a TRANS2_GET_DFS_REFERRAL
2026 ****************************************************************************/
2027 static int call_trans2getdfsreferral(connection_struct *conn,
2028 char *inbuf, char *outbuf, int length,
2030 char **pparams, char **ppdata,
2033 char *params = *pparams;
2036 char *localstring_offset;
2037 char *mangledstring_offset;
2038 char *sharename_offset;
2039 char *referal_offset;
2043 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2044 int query_file_len=0;
2048 BOOL first_one=True;
2050 referal_trans_param rtp;
2051 dfs_internal_table *list=dfs_struct.table;
2054 DEBUG(0,("call_trans2getdfsreferral:1\n"));
2057 /* decode the param member of query */
2058 rtp.level=SVAL(params, 0);
2059 DEBUGADD(0,("rtp.level:[%d]\n",rtp.level));
2061 DEBUGADD(0,("total_params:[%d]\n",total_params));
2062 for (i=0; i<(total_params-2)/2; i++)
2064 rtp.directory[i]=SVAL(params, 2+2*i);
2067 strupper(rtp.directory);
2069 query_file_len=strlen(rtp.directory);
2070 DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory));
2071 DEBUGADD(0,("query_file_len:[%d]\n",query_file_len));
2074 lookup in the internal DFS table all the entries
2075 and calculate the required data buffer size
2077 bytesreq=8; /* the header */
2078 reply.number_of_referal=0;
2079 DEBUGADD(0,("call_trans2getdfsreferral:2\n"));
2081 for(i=0; i<dfs_struct.size; i++)
2083 filename_len=list[i].localpath_length;
2084 DEBUGADD(0,("checking against [%s][%d]\n", list[i].localpath, filename_len));
2086 if( (filename_len==query_file_len) &&
2087 (!strncmp(rtp.directory, list[i].localpath, query_file_len)) )
2090 bytesreq+=22; /* the referal size */
2091 bytesreq+=2*(list[i].sharename_length+1); /* the string length */
2092 reply.number_of_referal++;
2093 DEBUGADD(0,("found\n"));
2096 DEBUGADD(0,("first one\n"));
2097 bytesreq+=2*(list[i].localpath_length+1);
2098 bytesreq+=2*(list[i].mangledpath_length+1);
2100 reply.path_consumed=list[i].localpath_length;
2102 strncpy(reply.filename, list[i].localpath, list[i].localpath_length+1);
2103 strncpy(reply.mangledname, list[i].mangledpath, list[i].mangledpath_length+1);
2104 rtp.type=list[i].type;
2109 DEBUGADD(0,("call_trans2getdfsreferral:3\n"));
2111 /* allocate memory for the reply data */
2112 pdata = *ppdata = Realloc(*ppdata, bytesreq + 1024);
2113 bzero(*ppdata, bytesreq+22);
2118 localstring_offset = pdata + 8 + reply.number_of_referal*22;
2120 /* unicode version */
2121 mangledstring_offset = localstring_offset + 2*(1+strlen(reply.filename));
2122 sharename_offset = mangledstring_offset + 2*(1+strlen(reply.mangledname));
2125 mangledstring_offset = localstring_offset + (1+strlen(reply.filename));
2126 sharename_offset = mangledstring_offset + (1+strlen(reply.mangledname));
2128 referal_offset = pdata + 8;
2130 /* right now respond storage server */
2132 reply.server_function=rtp.type;
2134 reply.server_function=1;
2136 /* write the header */
2137 /* unicode version*/
2138 /*SSVAL(pheader, 0, reply.path_consumed*2);*/
2141 SSVAL(pheader, 0, reply.path_consumed);
2144 SSVAL(pheader, 0, 6);
2146 SSVAL(pheader, 2, reply.number_of_referal);
2147 SIVAL(pheader, 4, reply.server_function);
2149 /* write the local path string */
2150 /* unicode version*/
2151 for(i=0; i<strlen(reply.filename); i++)
2153 SSVAL(localstring_offset, 2*i, (uint16) reply.filename[i]);
2155 SSVAL(localstring_offset, 2*strlen(reply.filename), 0);
2158 for(i=0; i<strlen(reply.filename); i++)
2160 localstring_offset[i]=reply.filename[i];
2162 localstring_offset[strlen(reply.filename)]=0;
2164 DEBUG(0,("reply.filename is [%s]:[%d], i is [%d]\n", reply.filename, strlen(reply.filename), i));
2166 /* write the mangled local path string */
2167 /* unicode version*/
2168 for(i=0; i<strlen(reply.mangledname); i++)
2170 SSVAL(mangledstring_offset, 2*i, (uint16) reply.mangledname[i]);
2172 SSVAL(mangledstring_offset, 2*i, 0);
2175 for(i=0; i<strlen(reply.mangledname); i++)
2177 mangledstring_offset[i]=reply.mangledname[i];
2179 mangledstring_offset[i]=0;
2181 DEBUGADD(0,("call_trans2getdfsreferral:4\n"));
2183 /* the order of the referals defines the load balancing */
2185 /* write each referal */
2186 for(i=0; i<dfs_struct.size; i++)
2188 filename_len=list[i].localpath_length;
2190 if(filename_len==query_file_len &&
2191 !strncasecmp(rtp.directory, list[i].localpath, query_file_len))
2194 SSVAL(referal_offset, 0, 2); /* version */
2195 SSVAL(referal_offset, 2, 22); /* size */
2198 SSVAL(referal_offset, 4, 1); /* type SMB server*/
2200 SSVAL(referal_offset, 4, 0); /* type unknown */
2201 SSVAL(referal_offset, 6, 1); /* flags */
2202 SIVAL(referal_offset, 8, list[i].proximity); /* proximity */
2203 SIVAL(referal_offset, 12, 300); /* ttl */
2204 SSVAL(referal_offset, 16, localstring_offset-referal_offset);
2205 SSVAL(referal_offset, 18, mangledstring_offset-referal_offset);
2206 SSVAL(referal_offset, 20, sharename_offset-referal_offset);
2208 /* unicode version */
2209 for(j=0; j<list[i].sharename_length; j++)
2211 SSVAL(sharename_offset, 2*j, (uint16) list[i].sharename[j]);
2213 SSVAL(sharename_offset, 2*j, 0);
2215 sharename_offset=sharename_offset + 2*(1+list[i].sharename_length);
2217 for(j=0; j<list[i].sharename_length; j++)
2219 sharename_offset[j]=list[i].sharename[j];
2221 sharename_offset[j]=0;
2223 sharename_offset=sharename_offset + (1+list[i].sharename_length);
2226 referal_offset=referal_offset+22;
2230 DEBUGADD(0,("call_trans2getdfsreferral:5\n"));
2232 send_trans2_replies(outbuf, bufsize, params, 0, *ppdata, bytesreq+22);
2234 /* send_trans2_replies(outbuf, bufsize, *ppdata, bytesreq, params, 0);*/
2235 DEBUGADD(0,("call_trans2getdfsreferral:6\n"));
2241 /****************************************************************************
2242 reply to a TRANS2_REPORT_DFS_INCONSISTANCY
2243 ****************************************************************************/
2244 static int call_trans2reportdfsinconsistancy(connection_struct *conn,
2245 char *inbuf, char *outbuf, int length,
2247 char **pparams, char **ppdata)
2249 char *params = *pparams;
2251 DEBUG(4,("call_trans2reportdfsinconsistancy\n"));
2252 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2257 /****************************************************************************
2258 reply to a SMBtranss2 - just ignore it!
2259 ****************************************************************************/
2260 int reply_transs2(connection_struct *conn,
2261 char *inbuf,char *outbuf,int length,int bufsize)
2263 DEBUG(4,("Ignoring transs2 of length %d\n",length));
2267 /****************************************************************************
2268 reply to a SMBtrans2
2269 ****************************************************************************/
2270 int reply_trans2(connection_struct *conn,
2271 char *inbuf,char *outbuf,int length,int bufsize)
2274 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2275 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2277 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2278 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2279 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2280 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2281 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2282 int32 timeout = IVALS(inbuf,smb_timeout);
2284 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2285 unsigned int tran_call = SVAL(inbuf, smb_setup0);
2286 char *params = NULL, *data = NULL;
2287 int num_params, num_params_sofar, num_data, num_data_sofar;
2289 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2290 /* Queue this open message as we are the process of an
2293 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2294 DEBUGADD(2,( "in oplock break state.\n"));
2296 push_oplock_pending_smb_message(inbuf, length);
2300 outsize = set_message(outbuf,0,0,True);
2302 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2303 is so as a sanity check */
2305 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2306 return(ERROR(ERRSRV,ERRerror));
2309 /* Allocate the space for the maximum needed parameters and data */
2310 if (total_params > 0)
2311 params = (char *)malloc(total_params);
2313 data = (char *)malloc(total_data);
2315 if ((total_params && !params) || (total_data && !data)) {
2316 DEBUG(2,("Out of memory in reply_trans2\n"));
2321 return(ERROR(ERRDOS,ERRnomem));
2324 /* Copy the param and data bytes sent with this request into
2325 the params buffer */
2326 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2327 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2329 if (num_params > total_params || num_data > total_data)
2330 exit_server("invalid params in reply_trans2");
2333 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2335 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2337 if(num_data_sofar < total_data || num_params_sofar < total_params) {
2338 /* We need to send an interim response then receive the rest
2339 of the parameter/data bytes */
2340 outsize = set_message(outbuf,0,0,True);
2341 send_smb(Client,outbuf);
2343 while (num_data_sofar < total_data ||
2344 num_params_sofar < total_params) {
2347 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2350 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2351 outsize = set_message(outbuf,0,0,True);
2353 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2355 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2356 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2361 return(ERROR(ERRSRV,ERRerror));
2364 /* Revise total_params and total_data in case
2365 they have changed downwards */
2366 total_params = SVAL(inbuf, smb_tpscnt);
2367 total_data = SVAL(inbuf, smb_tdscnt);
2368 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2369 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2370 if (num_params_sofar > total_params || num_data_sofar > total_data)
2371 exit_server("data overflow in trans2");
2373 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
2374 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2375 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2376 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2380 if (Protocol >= PROTOCOL_NT1) {
2381 uint16 flg2 = SVAL(outbuf,smb_flg2);
2382 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2385 /* Now we must call the relevant TRANS2 function */
2388 case TRANSACT2_OPEN:
2390 outsize = call_trans2open(conn,
2391 inbuf, outbuf, bufsize,
2395 case TRANSACT2_FINDFIRST:
2397 outsize = call_trans2findfirst(conn, inbuf, outbuf,
2398 bufsize, ¶ms, &data);
2401 case TRANSACT2_FINDNEXT:
2403 outsize = call_trans2findnext(conn, inbuf, outbuf,
2408 case TRANSACT2_QFSINFO:
2410 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
2411 length, bufsize, ¶ms,
2415 case TRANSACT2_SETFSINFO:
2417 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2422 case TRANSACT2_QPATHINFO:
2423 case TRANSACT2_QFILEINFO:
2425 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2427 ¶ms, &data, total_data);
2430 case TRANSACT2_SETPATHINFO:
2431 case TRANSACT2_SETFILEINFO:
2433 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2439 case TRANSACT2_FINDNOTIFYFIRST:
2441 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2446 case TRANSACT2_FINDNOTIFYNEXT:
2448 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2453 case TRANSACT2_MKDIR:
2455 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2456 bufsize, ¶ms, &data);
2459 case TRANSACT2_GET_DFS_REFERRAL:
2461 outsize = call_trans2getdfsreferral(conn, inbuf, outbuf,
2462 length, bufsize, ¶ms,
2466 case TRANSACT2_REPORT_DFS_INCONSISTANCY:
2468 outsize = call_trans2reportdfsinconsistancy(conn, inbuf, outbuf,
2475 /* Error in request */
2476 DEBUG(2,("Unknown request %d in trans2 call\n",
2482 return (ERROR(ERRSRV,ERRerror));
2486 /* As we do not know how many data packets will need to be
2487 returned here the various call_trans2xxxx calls
2488 must send their own. Thus a call_trans2xxx routine only
2489 returns a value other than -1 when it wants to send
2497 return outsize; /* If a correct response was needed the
2498 call_trans2xxx calls have already sent
2499 it. If outsize != -1 then it is returning */