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 if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
221 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
222 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
227 return(ERROR(ERRSRV,ERRnofids));
229 if (!check_name(fname,conn))
231 if((errno == ENOENT) && bad_path)
233 unix_ERR_class = ERRDOS;
234 unix_ERR_code = ERRbadpath;
237 return(UNIXERROR(ERRDOS,ERRnoaccess));
240 unixmode = unix_mode(conn,open_attr | aARCH);
242 open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
243 oplock_request, &rmode,&smb_action);
247 if((errno == ENOENT) && bad_path)
249 unix_ERR_class = ERRDOS;
250 unix_ERR_code = ERRbadpath;
253 return(UNIXERROR(ERRDOS,ERRnoaccess));
256 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
257 close_file(fsp,False);
258 return(UNIXERROR(ERRDOS,ERRnoaccess));
262 fmode = dos_mode(conn,fname,&sbuf);
263 mtime = sbuf.st_mtime;
266 close_file(fsp,False);
267 return(ERROR(ERRDOS,ERRnoaccess));
270 /* Realloc the size of parameters and data we will return */
271 params = *pparams = Realloc(*pparams, 28);
273 return(ERROR(ERRDOS,ERRnomem));
276 SSVAL(params,0,fsp->fnum);
277 SSVAL(params,2,fmode);
278 put_dos_date2(params,4, mtime);
279 SIVAL(params,8, (uint32)size);
280 SSVAL(params,12,rmode);
282 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
283 smb_action |= EXTENDED_OPLOCK_GRANTED;
286 SSVAL(params,18,smb_action);
288 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
290 SIVAL(params,20,inode);
292 /* Send the required number of replies */
293 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
298 /****************************************************************************
299 get a level dependent lanman2 dir entry.
300 ****************************************************************************/
301 static int get_lanman2_dir_entry(connection_struct *conn,
302 char *path_mask,int dirtype,int info_level,
303 int requires_resume_key,
304 BOOL dont_descend,char **ppdata,
305 char *base_data, int space_remaining,
311 SMB_STRUCT_STAT sbuf;
315 char *p, *pdata = *ppdata;
321 time_t mdate=0, adate=0, cdate=0;
323 BOOL isrootdir = (strequal(conn->dirpath,"./") ||
324 strequal(conn->dirpath,".") ||
325 strequal(conn->dirpath,"/"));
327 int nt_extmode; /* Used for NT connections instead of mode */
328 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
331 *out_of_space = False;
336 p = strrchr(path_mask,'/');
345 pstrcpy(mask, path_mask);
349 /* Needed if we run out of space */
350 prev_dirpos = TellDir(conn->dirptr);
351 dname = ReadDirName(conn->dirptr);
354 * Due to bugs in NT client redirectors we are not using
355 * resume keys any more - set them to zero.
356 * Check out the related comments in findfirst/findnext.
362 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
363 (long)conn->dirptr,TellDir(conn->dirptr)));
368 pstrcpy(fname,dname);
370 if(mask_match(fname, mask, case_sensitive, True))
372 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
373 if (dont_descend && !isdots)
376 if (isrootdir && isdots)
379 pstrcpy(pathreal,conn->dirpath);
381 pstrcat(pathreal,"/");
382 pstrcat(pathreal,dname);
383 if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0)
385 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
389 mode = dos_mode(conn,pathreal,&sbuf);
391 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
392 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
397 mdate = sbuf.st_mtime;
398 adate = sbuf.st_atime;
399 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
403 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
409 name_map_mangle(fname,False,SNUM(conn));
414 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
419 if(requires_resume_key) {
423 put_dos_date2(p,l1_fdateCreation,cdate);
424 put_dos_date2(p,l1_fdateLastAccess,adate);
425 put_dos_date2(p,l1_fdateLastWrite,mdate);
426 SIVAL(p,l1_cbFile,(uint32)size);
427 SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
428 SSVAL(p,l1_attrFile,mode);
429 SCVAL(p,l1_cchName,strlen(fname));
430 pstrcpy(p + l1_achName, fname);
431 nameptr = p + l1_achName;
432 p += l1_achName + strlen(fname) + 1;
437 if(requires_resume_key) {
441 put_dos_date2(p,l2_fdateCreation,cdate);
442 put_dos_date2(p,l2_fdateLastAccess,adate);
443 put_dos_date2(p,l2_fdateLastWrite,mdate);
444 SIVAL(p,l2_cbFile,(uint32)size);
445 SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
446 SSVAL(p,l2_attrFile,mode);
447 SIVAL(p,l2_cbList,0); /* No extended attributes */
448 SCVAL(p,l2_cchName,strlen(fname));
449 pstrcpy(p + l2_achName, fname);
450 nameptr = p + l2_achName;
451 p += l2_achName + strlen(fname) + 1;
456 put_dos_date2(p,4,cdate);
457 put_dos_date2(p,8,adate);
458 put_dos_date2(p,12,mdate);
459 SIVAL(p,16,(uint32)size);
460 SIVAL(p,20,SMB_ROUNDUP(size,1024));
463 CVAL(p,30) = strlen(fname);
464 pstrcpy(p+31, fname);
466 p += 31 + strlen(fname) + 1;
470 if(requires_resume_key) {
474 SIVAL(p,0,33+strlen(fname)+1);
475 put_dos_date2(p,4,cdate);
476 put_dos_date2(p,8,adate);
477 put_dos_date2(p,12,mdate);
478 SIVAL(p,16,(uint32)size);
479 SIVAL(p,20,SMB_ROUNDUP(size,1024));
481 CVAL(p,32) = strlen(fname);
482 pstrcpy(p + 33, fname);
484 p += 33 + strlen(fname) + 1;
487 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
488 was_8_3 = is_8_3(fname, True);
489 len = 94+strlen(fname);
490 len = (len + 3) & ~3;
491 SIVAL(p,0,len); p += 4;
492 SIVAL(p,0,reskey); p += 4;
493 put_long_date(p,cdate); p += 8;
494 put_long_date(p,adate); p += 8;
495 put_long_date(p,mdate); p += 8;
496 put_long_date(p,mdate); p += 8;
500 SIVAL(p,0,nt_extmode); p += 4;
501 SIVAL(p,0,strlen(fname)); p += 4;
502 SIVAL(p,0,0); p += 4;
505 if (!name_map_mangle(p+2,True,SNUM(conn)))
510 SSVAL(p,0,strlen(p+2));
513 pstrcpy(p,fname); p += strlen(p);
517 case SMB_FIND_FILE_DIRECTORY_INFO:
518 len = 64+strlen(fname);
519 len = (len + 3) & ~3;
520 SIVAL(p,0,len); p += 4;
521 SIVAL(p,0,reskey); p += 4;
522 put_long_date(p,cdate); p += 8;
523 put_long_date(p,adate); p += 8;
524 put_long_date(p,mdate); p += 8;
525 put_long_date(p,mdate); p += 8;
529 SIVAL(p,0,nt_extmode); p += 4;
530 SIVAL(p,0,strlen(fname)); p += 4;
536 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
537 len = 68+strlen(fname);
538 len = (len + 3) & ~3;
539 SIVAL(p,0,len); p += 4;
540 SIVAL(p,0,reskey); p += 4;
541 put_long_date(p,cdate); p += 8;
542 put_long_date(p,adate); p += 8;
543 put_long_date(p,mdate); p += 8;
544 put_long_date(p,mdate); p += 8;
548 SIVAL(p,0,nt_extmode); p += 4;
549 SIVAL(p,0,strlen(fname)); p += 4;
550 SIVAL(p,0,0); p += 4;
555 case SMB_FIND_FILE_NAMES_INFO:
556 len = 12+strlen(fname);
557 len = (len + 3) & ~3;
558 SIVAL(p,0,len); p += 4;
559 SIVAL(p,0,reskey); p += 4;
560 SIVAL(p,0,strlen(fname)); p += 4;
570 if (PTR_DIFF(p,pdata) > space_remaining) {
571 /* Move the dirptr back to prev_dirpos */
572 SeekDir(conn->dirptr, prev_dirpos);
573 *out_of_space = True;
574 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
575 return False; /* Not finished - just out of space */
578 /* Setup the last_filename pointer, as an offset from base_data */
579 *last_name_off = PTR_DIFF(nameptr,base_data);
580 /* Advance the data pointer to the next slot */
585 /****************************************************************************
586 Convert the directory masks formated for the wire.
587 ****************************************************************************/
589 void mask_convert( char *mask)
592 * We know mask is a pstring.
598 if(p[1] != '"' && p[1] != '.') {
599 pstrcpy( expnd, p+1 );
602 safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
606 if (*p == '>') *p = '?';
607 if (*p == '"') *p = '.';
612 /****************************************************************************
613 reply to a TRANS2_FINDFIRST
614 ****************************************************************************/
615 static int call_trans2findfirst(connection_struct *conn,
616 char *inbuf, char *outbuf, int bufsize,
617 char **pparams, char **ppdata)
619 /* We must be careful here that we don't return more than the
620 allowed number of data bytes. If this means returning fewer than
621 maxentries then so be it. We assume that the redirector has
622 enough room for the fixed number of parameter bytes it has
624 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
625 char *params = *pparams;
626 char *pdata = *ppdata;
627 int dirtype = SVAL(params,0);
628 int maxentries = SVAL(params,2);
629 BOOL close_after_first = BITSETW(params+4,0);
630 BOOL close_if_end = BITSETW(params+4,1);
631 BOOL requires_resume_key = BITSETW(params+4,2);
632 int info_level = SVAL(params,6);
640 BOOL finished = False;
641 BOOL dont_descend = False;
642 BOOL out_of_space = False;
644 BOOL bad_path = False;
646 *directory = *mask = 0;
648 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",
649 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
650 info_level, max_data_bytes));
658 case SMB_FIND_FILE_DIRECTORY_INFO:
659 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
660 case SMB_FIND_FILE_NAMES_INFO:
661 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
664 return(ERROR(ERRDOS,ERRunknownlevel));
667 pstrcpy(directory, params + 12); /* Complete directory path with
668 wildcard mask appended */
670 DEBUG(5,("path=%s\n",directory));
672 if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
674 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
675 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
677 if(!check_name(directory,conn)) {
678 if((errno == ENOENT) && bad_path)
680 unix_ERR_class = ERRDOS;
681 unix_ERR_code = ERRbadpath;
685 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
686 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
687 (get_remote_arch() == RA_WINNT))
689 unix_ERR_class = ERRDOS;
690 unix_ERR_code = ERRbaddirectory;
694 return(UNIXERROR(ERRDOS,ERRbadpath));
697 p = strrchr(directory,'/');
699 pstrcpy(mask,directory);
700 pstrcpy(directory,"./");
706 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
708 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
710 return(ERROR(ERRDOS,ERRnomem));
711 bzero(pdata,max_data_bytes);
713 /* Realloc the params space */
714 params = *pparams = Realloc(*pparams, 10);
716 return(ERROR(ERRDOS,ERRnomem));
718 dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
720 return(UNIXERROR(ERRDOS,ERRbadfile));
722 /* Convert the formatted mask. */
727 * Now we have a working mask_match in util.c, I believe
728 * we no longer need these hacks (in fact they break
732 /* a special case for 16 bit apps */
733 if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
735 /* handle broken clients that send us old 8.3 format */
736 string_sub(mask,"????????","*");
737 string_sub(mask,".???",".*");
740 /* Save the wildcard match and attribs we are using on this directory -
741 needed as lanman2 assumes these are being saved between calls */
743 if(!(wcard = strdup(mask))) {
744 dptr_close(dptr_num);
745 return(ERROR(ERRDOS,ERRnomem));
748 dptr_set_wcard(dptr_num, wcard);
749 dptr_set_attr(dptr_num, dirtype);
751 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
753 /* We don't need to check for VOL here as this is returned by
754 a different TRANS2 call. */
756 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
757 conn->dirpath,lp_dontdescend(SNUM(conn))));
758 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
762 space_remaining = max_data_bytes;
763 out_of_space = False;
765 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
768 /* this is a heuristic to avoid seeking the dirptr except when
769 absolutely necessary. It allows for a filename of about 40 chars */
770 if (space_remaining < DIRLEN_GUESS && numentries > 0)
778 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
779 requires_resume_key,dont_descend,
780 &p,pdata,space_remaining, &out_of_space,
784 if (finished && out_of_space)
787 if (!finished && !out_of_space)
789 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
792 /* Check if we can close the dirptr */
793 if(close_after_first || (finished && close_if_end))
795 dptr_close(dptr_num);
796 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
801 * If there are no matching entries we must return ERRDOS/ERRbadfile -
802 * from observation of NT.
806 return(ERROR(ERRDOS,ERRbadfile));
808 /* At this point pdata points to numentries directory entries. */
810 /* Set up the return parameter block */
811 SSVAL(params,0,dptr_num);
812 SSVAL(params,2,numentries);
813 SSVAL(params,4,finished);
814 SSVAL(params,6,0); /* Never an EA error */
815 SSVAL(params,8,last_name_off);
817 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
819 if ((! *directory) && dptr_path(dptr_num))
820 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
822 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
823 smb_fn_name(CVAL(inbuf,smb_com)),
824 mask, directory, dirtype, numentries ) );
830 /****************************************************************************
831 reply to a TRANS2_FINDNEXT
832 ****************************************************************************/
833 static int call_trans2findnext(connection_struct *conn,
834 char *inbuf, char *outbuf,
835 int length, int bufsize,
836 char **pparams, char **ppdata)
838 /* We must be careful here that we don't return more than the
839 allowed number of data bytes. If this means returning fewer than
840 maxentries then so be it. We assume that the redirector has
841 enough room for the fixed number of parameter bytes it has
843 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
844 char *params = *pparams;
845 char *pdata = *ppdata;
846 int16 dptr_num = SVAL(params,0);
847 int maxentries = SVAL(params,2);
848 uint16 info_level = SVAL(params,4);
849 uint32 resume_key = IVAL(params,6);
850 BOOL close_after_request = BITSETW(params+10,0);
851 BOOL close_if_end = BITSETW(params+10,1);
852 BOOL requires_resume_key = BITSETW(params+10,2);
853 BOOL continue_bit = BITSETW(params+10,3);
860 int i, last_name_off=0;
861 BOOL finished = False;
862 BOOL dont_descend = False;
863 BOOL out_of_space = False;
866 *mask = *directory = *resume_name = 0;
868 pstrcpy( resume_name, params+12);
870 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
871 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
872 resume_key = %d resume name = %s continue=%d level = %d\n",
873 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
874 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
882 case SMB_FIND_FILE_DIRECTORY_INFO:
883 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
884 case SMB_FIND_FILE_NAMES_INFO:
885 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
888 return(ERROR(ERRDOS,ERRunknownlevel));
891 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
893 return(ERROR(ERRDOS,ERRnomem));
894 bzero(pdata,max_data_bytes);
896 /* Realloc the params space */
897 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
899 return(ERROR(ERRDOS,ERRnomem));
901 /* Check that the dptr is valid */
902 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
903 return(ERROR(ERRDOS,ERRnofiles));
905 string_set(&conn->dirpath,dptr_path(dptr_num));
907 /* Get the wildcard mask from the dptr */
908 if((p = dptr_wcard(dptr_num))== NULL) {
909 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
910 return (ERROR(ERRDOS,ERRnofiles));
913 pstrcpy(directory,conn->dirpath);
915 /* Get the attr mask from the dptr */
916 dirtype = dptr_attr(dptr_num);
918 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
919 dptr_num, mask, dirtype,
921 TellDir(conn->dirptr)));
923 /* We don't need to check for VOL here as this is returned by
924 a different TRANS2 call. */
926 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
927 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
931 space_remaining = max_data_bytes;
932 out_of_space = False;
935 * Seek to the correct position. We no longer use the resume key but
936 * depend on the last file name instead.
938 if(requires_resume_key && *resume_name && !continue_bit)
941 * Fix for NT redirector problem triggered by resume key indexes
942 * changing between directory scans. We now return a resume key of 0
943 * and instead look for the filename to continue from (also given
944 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
945 * findfirst/findnext (as is usual) then the directory pointer
946 * should already be at the correct place. Check this by scanning
947 * backwards looking for an exact (ie. case sensitive) filename match.
948 * If we get to the beginning of the directory and haven't found it then scan
949 * forwards again looking for a match. JRA.
952 int current_pos, start_pos;
954 void *dirptr = conn->dirptr;
955 start_pos = TellDir(dirptr);
956 for(current_pos = start_pos; current_pos >= 0; current_pos--)
958 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
960 SeekDir(dirptr, current_pos);
961 dname = ReadDirName(dirptr);
964 * Remember, name_map_mangle is called by
965 * get_lanman2_dir_entry(), so the resume name
966 * could be mangled. Ensure we do the same
971 name_map_mangle( dname, False, SNUM(conn));
973 if(dname && strcsequal( resume_name, dname))
975 SeekDir(dirptr, current_pos+1);
976 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
982 * Scan forward from start if not found going backwards.
987 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
988 SeekDir(dirptr, start_pos);
989 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
992 * Remember, name_map_mangle is called by
993 * get_lanman2_dir_entry(), so the resume name
994 * could be mangled. Ensure we do the same
999 name_map_mangle( dname, False, SNUM(conn));
1001 if(dname && strcsequal( resume_name, dname))
1003 SeekDir(dirptr, current_pos+1);
1004 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1008 } /* end if current_pos */
1009 } /* end if requires_resume_key && !continue_bit */
1011 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1013 /* this is a heuristic to avoid seeking the dirptr except when
1014 absolutely necessary. It allows for a filename of about 40 chars */
1015 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1017 out_of_space = True;
1023 !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1024 requires_resume_key,dont_descend,
1025 &p,pdata,space_remaining, &out_of_space,
1029 if (finished && out_of_space)
1032 if (!finished && !out_of_space)
1034 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1037 /* Check if we can close the dirptr */
1038 if(close_after_request || (finished && close_if_end))
1040 dptr_close(dptr_num); /* This frees up the saved mask */
1041 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1046 /* Set up the return parameter block */
1047 SSVAL(params,0,numentries);
1048 SSVAL(params,2,finished);
1049 SSVAL(params,4,0); /* Never an EA error */
1050 SSVAL(params,6,last_name_off);
1052 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1054 if ((! *directory) && dptr_path(dptr_num))
1055 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1057 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1058 smb_fn_name(CVAL(inbuf,smb_com)),
1059 mask, directory, dirtype, numentries ) );
1064 /****************************************************************************
1065 reply to a TRANS2_QFSINFO (query filesystem info)
1066 ****************************************************************************/
1068 static int call_trans2qfsinfo(connection_struct *conn,
1069 char *inbuf, char *outbuf,
1070 int length, int bufsize,
1071 char **pparams, char **ppdata)
1073 char *pdata = *ppdata;
1074 char *params = *pparams;
1075 uint16 info_level = SVAL(params,0);
1078 char *vname = volume_label(SNUM(conn));
1079 int snum = SNUM(conn);
1080 char *fstype = lp_fstype(SNUM(conn));
1081 extern uint32 global_client_caps;
1083 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1085 if(conn->vfs_ops.stat(".",&st)!=0) {
1086 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1087 return (ERROR(ERRSRV,ERRinvdevice));
1090 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1096 SMB_BIG_UINT dfree,dsize,bsize;
1098 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1099 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1100 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1101 SIVAL(pdata,l1_cUnit,dsize);
1102 SIVAL(pdata,l1_cUnitAvail,dfree);
1103 SSVAL(pdata,l1_cbSector,512);
1104 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1105 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1106 (unsigned int)dfree, 512));
1111 /* Return volume name */
1112 int volname_len = MIN(strlen(vname),11);
1113 data_len = l2_vol_szVolLabel + volname_len + 1;
1115 * Add volume serial number - hash of a combination of
1116 * the called hostname and the service name.
1118 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1119 SCVAL(pdata,l2_vol_cch,volname_len);
1120 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1121 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1122 (unsigned)st.st_ctime, volname_len,
1123 pdata+l2_vol_szVolLabel));
1126 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1127 data_len = 12 + 2*strlen(fstype);
1128 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */
1129 #if 0 /* Old code. JRA. */
1130 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1131 #endif /* Old code. */
1132 SIVAL(pdata,4,128); /* Max filename component length */
1133 SIVAL(pdata,8,2*strlen(fstype));
1134 ascii_to_unibuf(pdata+12, fstype, 1024-2-12);
1135 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1137 case SMB_QUERY_FS_LABEL_INFO:
1138 data_len = 4 + strlen(vname);
1139 SIVAL(pdata,0,strlen(vname));
1140 pstrcpy(pdata+4,vname);
1142 case SMB_QUERY_FS_VOLUME_INFO:
1145 * Add volume serial number - hash of a combination of
1146 * the called hostname and the service name.
1148 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1149 (str_checksum(local_machine)<<16));
1151 /* NT4 always serves this up as unicode but expects it to be
1152 * delivered as ascii! (tridge && JRA)
1154 if (global_client_caps & CAP_NT_SMBS) {
1155 data_len = 18 + strlen(vname);
1156 SIVAL(pdata,12,strlen(vname));
1157 pstrcpy(pdata+18,vname);
1159 data_len = 18 + 2*strlen(vname);
1160 SIVAL(pdata,12,strlen(vname)*2);
1161 ascii_to_unibuf(pdata+18, vname, 1024-2-18);
1164 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1165 strlen(vname),vname));
1167 case SMB_QUERY_FS_SIZE_INFO:
1169 SMB_BIG_UINT dfree,dsize,bsize;
1171 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1172 SIVAL(pdata,0,dsize);
1173 SIVAL(pdata,8,dfree);
1174 SIVAL(pdata,16,bsize/512);
1175 SIVAL(pdata,20,512);
1178 case SMB_QUERY_FS_DEVICE_INFO:
1180 SIVAL(pdata,0,0); /* dev type */
1181 SIVAL(pdata,4,0); /* characteristics */
1183 case SMB_MAC_QUERY_FS_INFO:
1185 * Thursby MAC extension... ONLY on NTFS filesystems
1186 * once we do streams then we don't need this
1188 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1190 SIVAL(pdata,84,0x100); /* Don't support mac... */
1195 return(ERROR(ERRDOS,ERRunknownlevel));
1199 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1201 DEBUG( 4, ( "%s info_level = %d\n",
1202 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1207 /****************************************************************************
1208 reply to a TRANS2_SETFSINFO (set filesystem info)
1209 ****************************************************************************/
1210 static int call_trans2setfsinfo(connection_struct *conn,
1211 char *inbuf, char *outbuf, int length,
1213 char **pparams, char **ppdata)
1215 /* Just say yes we did it - there is nothing that
1216 can be set here so it doesn't matter. */
1218 DEBUG(3,("call_trans2setfsinfo\n"));
1220 if (!CAN_WRITE(conn))
1221 return(ERROR(ERRSRV,ERRaccess));
1223 outsize = set_message(outbuf,10,0,True);
1228 /****************************************************************************
1229 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1230 file name or file id).
1231 ****************************************************************************/
1233 static int call_trans2qfilepathinfo(connection_struct *conn,
1234 char *inbuf, char *outbuf, int length,
1236 char **pparams,char **ppdata,
1239 char *params = *pparams;
1240 char *pdata = *ppdata;
1241 uint16 tran_call = SVAL(inbuf, smb_setup0);
1245 unsigned int data_size;
1246 SMB_STRUCT_STAT sbuf;
1252 BOOL bad_path = False;
1253 BOOL delete_pending = False;
1255 if (tran_call == TRANSACT2_QFILEINFO) {
1256 files_struct *fsp = file_fsp(params,0);
1257 info_level = SVAL(params,2);
1259 if(fsp && fsp->open && fsp->is_directory) {
1261 * This is actually a QFILEINFO on a directory
1262 * handle (returned from an NT SMB). NT5.0 seems
1263 * to do this call. JRA.
1265 fname = fsp->fsp_name;
1266 if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf))
1268 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1269 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1271 if (!check_name(fname,conn) || (!VALID_STAT(sbuf) &&
1272 conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
1273 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1274 if((errno == ENOENT) && bad_path)
1276 unix_ERR_class = ERRDOS;
1277 unix_ERR_code = ERRbadpath;
1279 return(UNIXERROR(ERRDOS,ERRbadpath));
1283 * Original code - this is an open file.
1285 CHECK_FSP(fsp,conn);
1288 fname = fsp->fsp_name;
1289 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1290 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1291 return(UNIXERROR(ERRDOS,ERRbadfid));
1293 if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1294 return(UNIXERROR(ERRDOS,ERRnoaccess));
1296 delete_pending = fsp->fd_ptr->delete_on_close;
1300 info_level = SVAL(params,0);
1302 pstrcpy(fname,¶ms[6]);
1303 if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf))
1305 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1306 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1308 if (!check_name(fname,conn) ||
1309 (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),
1311 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1312 if((errno == ENOENT) && bad_path)
1314 unix_ERR_class = ERRDOS;
1315 unix_ERR_code = ERRbadpath;
1317 return(UNIXERROR(ERRDOS,ERRbadpath));
1322 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1323 fname,info_level,tran_call,total_data));
1325 p = strrchr(fname,'/');
1331 mode = dos_mode(conn,fname,&sbuf);
1332 size = sbuf.st_size;
1333 if (mode & aDIR) size = 0;
1335 /* from now on we only want the part after the / */
1338 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1340 pdata = *ppdata = Realloc(*ppdata, data_size);
1342 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1343 /* uggh, EAs for OS2 */
1344 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1345 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1348 bzero(pdata,data_size);
1352 case SMB_INFO_STANDARD:
1353 case SMB_INFO_QUERY_EA_SIZE:
1354 data_size = (info_level==1?22:26);
1355 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1356 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1357 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1358 SIVAL(pdata,l1_cbFile,(uint32)size);
1359 SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1360 SSVAL(pdata,l1_attrFile,mode);
1361 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1364 case SMB_INFO_QUERY_EAS_FROM_LIST:
1366 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1367 put_dos_date2(pdata,4,sbuf.st_atime);
1368 put_dos_date2(pdata,8,sbuf.st_mtime);
1369 SIVAL(pdata,12,(uint32)size);
1370 SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1371 SIVAL(pdata,20,mode);
1374 case SMB_INFO_QUERY_ALL_EAS:
1376 SIVAL(pdata,0,data_size);
1380 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1382 case SMB_QUERY_FILE_BASIC_INFO:
1383 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1384 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1385 put_long_date(pdata+8,sbuf.st_atime);
1386 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1387 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1388 SIVAL(pdata,32,mode);
1390 DEBUG(5,("SMB_QFBI - "));
1392 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1393 DEBUG(5,("create: %s ", ctime(&create_time)));
1395 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1396 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1397 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1398 DEBUG(5,("mode: %x\n", mode));
1402 case SMB_QUERY_FILE_STANDARD_INFO:
1404 SOFF_T(pdata,0,size);
1405 SOFF_T(pdata,8,size);
1406 SIVAL(pdata,16,sbuf.st_nlink);
1408 CVAL(pdata,21) = (mode&aDIR)?1:0;
1411 case SMB_QUERY_FILE_EA_INFO:
1415 /* Get the 8.3 name - used if NT SMB was negotiated. */
1416 case SMB_QUERY_FILE_ALT_NAME_INFO:
1421 pstrcpy(short_name,p);
1422 /* Mangle if not already 8.3 */
1423 if(!is_8_3(short_name, True))
1425 if(!name_map_mangle(short_name,True,SNUM(conn)))
1428 strupper(short_name);
1429 data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4);
1430 data_size = data_end - pdata;
1431 SIVAL(pdata,0,2*(data_size-4));
1435 case SMB_QUERY_FILE_NAME_INFO:
1438 pstrcpy(pdata+4,fname);
1441 case SMB_QUERY_FILE_ALLOCATION_INFO:
1442 case SMB_QUERY_FILE_END_OF_FILEINFO:
1444 SOFF_T(pdata,0,size);
1447 case SMB_QUERY_FILE_ALL_INFO:
1448 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1449 put_long_date(pdata+8,sbuf.st_atime);
1450 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1451 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1452 SIVAL(pdata,32,mode);
1454 SOFF_T(pdata,0,size);
1455 SOFF_T(pdata,8,size);
1456 SIVAL(pdata,16,sbuf.st_nlink);
1457 CVAL(pdata,20) = delete_pending;
1458 CVAL(pdata,21) = (mode&aDIR)?1:0;
1460 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1461 pdata += 8; /* index number */
1462 pdata += 4; /* EA info */
1464 SIVAL(pdata,0,0xA9);
1466 SIVAL(pdata,0,0xd01BF);
1468 SOFF_T(pdata,0,pos); /* current offset */
1470 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1472 pdata += 4; /* alignment */
1474 pstrcpy(pdata+4,fname);
1476 data_size = PTR_DIFF(pdata,(*ppdata));
1480 /* NT4 server just returns "invalid query" to this - if we try to answer
1481 it then NTws gets a BSOD! (tridge) */
1482 case SMB_QUERY_FILE_STREAM_INFO:
1485 SIVAL(pdata,4,size);
1486 SIVAL(pdata,12,size);
1488 pstrcpy(pdata+24,fname);
1493 return(ERROR(ERRDOS,ERRunknownlevel));
1496 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1501 /****************************************************************************
1502 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1503 ****************************************************************************/
1504 static int call_trans2setfilepathinfo(connection_struct *conn,
1505 char *inbuf, char *outbuf, int length,
1506 int bufsize, char **pparams,
1507 char **ppdata, int total_data)
1509 char *params = *pparams;
1510 char *pdata = *ppdata;
1511 uint16 tran_call = SVAL(inbuf, smb_setup0);
1520 BOOL bad_path = False;
1521 files_struct *fsp = NULL;
1523 if (!CAN_WRITE(conn))
1524 return(ERROR(ERRSRV,ERRaccess));
1526 if (tran_call == TRANSACT2_SETFILEINFO) {
1527 fsp = file_fsp(params,0);
1528 info_level = SVAL(params,2);
1530 if(fsp && fsp->open && fsp->is_directory) {
1532 * This is actually a SETFILEINFO on a directory
1533 * handle (returned from an NT SMB). NT5.0 seems
1534 * to do this call. JRA.
1536 fname = fsp->fsp_name;
1537 if (!unix_dfs_convert(fname,conn,0,&bad_path,&st))
1539 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1540 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1542 if (!check_name(fname,conn) || (!VALID_STAT(st) &&
1543 conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
1544 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1545 if((errno == ENOENT) && bad_path)
1547 unix_ERR_class = ERRDOS;
1548 unix_ERR_code = ERRbadpath;
1550 return(UNIXERROR(ERRDOS,ERRbadpath));
1554 * Original code - this is an open file.
1556 CHECK_FSP(fsp,conn);
1559 fname = fsp->fsp_name;
1560 fd = fsp->fd_ptr->fd;
1562 if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
1563 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1564 return(UNIXERROR(ERRDOS,ERRbadfid));
1569 info_level = SVAL(params,0);
1571 pstrcpy(fname,¶ms[6]);
1572 if (!unix_dfs_convert(fname,conn,0,&bad_path,&st))
1574 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1575 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1577 if(!check_name(fname, conn))
1579 if((errno == ENOENT) && bad_path)
1581 unix_ERR_class = ERRDOS;
1582 unix_ERR_code = ERRbadpath;
1584 return(UNIXERROR(ERRDOS,ERRbadpath));
1587 if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
1588 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1589 if((errno == ENOENT) && bad_path)
1591 unix_ERR_class = ERRDOS;
1592 unix_ERR_code = ERRbadpath;
1594 return(UNIXERROR(ERRDOS,ERRbadpath));
1598 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1599 tran_call,fname,info_level,total_data));
1601 /* Realloc the parameter and data sizes */
1602 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1604 return(ERROR(ERRDOS,ERRnomem));
1607 tvs.modtime = st.st_mtime;
1608 tvs.actime = st.st_atime;
1609 mode = dos_mode(conn,fname,&st);
1611 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1612 /* uggh, EAs for OS2 */
1613 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1614 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1619 case SMB_INFO_STANDARD:
1620 case SMB_INFO_QUERY_EA_SIZE:
1623 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1626 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1628 mode = SVAL(pdata,l1_attrFile);
1629 size = IVAL(pdata,l1_cbFile);
1633 /* XXXX um, i don't think this is right.
1634 it's also not in the cifs6.txt spec.
1636 case SMB_INFO_QUERY_EAS_FROM_LIST:
1637 tvs.actime = make_unix_date2(pdata+8);
1638 tvs.modtime = make_unix_date2(pdata+12);
1639 size = IVAL(pdata,16);
1640 mode = IVAL(pdata,24);
1643 /* XXXX nor this. not in cifs6.txt, either. */
1644 case SMB_INFO_QUERY_ALL_EAS:
1645 tvs.actime = make_unix_date2(pdata+8);
1646 tvs.modtime = make_unix_date2(pdata+12);
1647 size = IVAL(pdata,16);
1648 mode = IVAL(pdata,24);
1651 case SMB_SET_FILE_BASIC_INFO:
1653 /* Ignore create time at offset pdata. */
1656 tvs.actime = interpret_long_date(pdata+8);
1658 /* write time + changed time, combined. */
1659 tvs.modtime=MAX(interpret_long_date(pdata+16),
1660 interpret_long_date(pdata+24));
1662 #if 0 /* Needs more testing... */
1663 /* Test from Luke to prevent Win95 from
1664 setting incorrect values here.
1666 if (tvs.actime < tvs.modtime)
1667 return(ERROR(ERRDOS,ERRnoaccess));
1668 #endif /* Needs more testing... */
1671 mode = IVAL(pdata,32);
1675 case SMB_SET_FILE_END_OF_FILE_INFO:
1677 size = IVAL(pdata,0);
1678 #ifdef LARGE_SMB_OFF_T
1679 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1680 #else /* LARGE_SMB_OFF_T */
1681 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1682 return(ERROR(ERRDOS,ERRunknownlevel));
1683 #endif /* LARGE_SMB_OFF_T */
1687 case SMB_SET_FILE_ALLOCATION_INFO:
1688 break; /* We don't need to do anything for this call. */
1690 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1692 if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1694 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1696 if(fsp->is_directory)
1697 return(ERROR(ERRDOS,ERRnoaccess));
1700 * We can only set the delete on close flag if
1701 * the share mode contained ALLOW_SHARE_DELETE
1704 if(lp_share_modes(SNUM(conn)))
1706 if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1707 return(ERROR(ERRDOS,ERRnoaccess));
1710 * If the flag has been set then
1711 * modify the share mode entry for all files we have open
1712 * on this device and inode to tell other smbds we have
1713 * changed the delete on close flag.
1716 if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1720 files_struct *iterate_fsp;
1721 SMB_DEV_T dev = fsp->fd_ptr->dev;
1722 SMB_INO_T inode = fsp->fd_ptr->inode;
1723 int num_share_modes;
1724 share_mode_entry *current_shares = NULL;
1726 if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1727 return(ERROR(ERRDOS,ERRnoaccess));
1730 * Before we allow this we need to ensure that all current opens
1731 * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1732 * do not then we deny this (as we are essentially deleting the
1733 * file at this point.
1736 num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares);
1737 for(i = 0; i < num_share_modes; i++)
1739 if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1741 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1742 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1743 fsp->fnum, fsp->fsp_name ));
1748 unlock_share_entry(fsp->conn, dev, inode, token);
1751 * current_shares was malloced by get_share_modes - free it here.
1754 free((char *)current_shares);
1757 * Even though share violation would be more appropriate here,
1758 * return ERRnoaccess as that's what NT does.
1761 return(ERROR(ERRDOS,ERRnoaccess));
1766 * current_shares was malloced by get_share_modes - free it here.
1769 free((char *)current_shares);
1771 DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1772 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1775 * Go through all files we have open on the same device and
1776 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1777 * Other smbd's that have this file open will have to fend for themselves. We
1778 * take care of this (rare) case in close_file(). See the comment there.
1781 for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1782 iterate_fsp = file_find_di_next(iterate_fsp))
1784 int new_share_mode = (delete_on_close ?
1785 (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1786 (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1788 DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1789 dev = %x, inode = %.0f from %x to %x\n",
1790 iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
1791 (double)inode, iterate_fsp->share_mode, new_share_mode ));
1793 if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1794 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1795 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1799 * Set the delete on close flag in the reference
1800 * counted struct. Delete when the last reference
1803 fsp->fd_ptr->delete_on_close = delete_on_close;
1804 unlock_share_entry(fsp->conn, dev, inode, token);
1806 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1807 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1809 } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1810 } /* end if lp_share_modes() */
1813 return(ERROR(ERRDOS,ERRunknownlevel));
1819 return(ERROR(ERRDOS,ERRunknownlevel));
1823 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1824 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1825 DEBUG(6,("size: %.0f ", (double)size));
1826 DEBUG(6,("mode: %x\n" , mode));
1828 /* get some defaults (no modifications) if any info is zero. */
1829 if (!tvs.actime) tvs.actime = st.st_atime;
1830 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1831 if (!size) size = st.st_size;
1833 /* Try and set the times, size and mode of this file -
1834 if they are different from the current values
1836 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1841 * This was a setfileinfo on an open file.
1842 * NT does this a lot. It's actually pointless
1843 * setting the time here, as it will be overwritten
1844 * on the next write, so we save the request
1845 * away and will set it on file code. JRA.
1847 fsp->pending_modtime = tvs.modtime;
1849 else if(file_utime(conn, fname, &tvs)!=0)
1851 return(UNIXERROR(ERRDOS,ERRnoaccess));
1855 /* check the mode isn't different, before changing it */
1856 if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1858 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1859 return(UNIXERROR(ERRDOS,ERRnoaccess));
1862 if(size != st.st_size)
1866 DEBUG(0, ("@@@ 23 @@@\n"));
1867 fd = dos_open(fname,O_RDWR,0);
1870 return(UNIXERROR(ERRDOS,ERRbadpath));
1872 set_filelen(fd, size);
1877 set_filelen(fd, size);
1883 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1888 /****************************************************************************
1889 reply to a TRANS2_MKDIR (make directory with extended attributes).
1890 ****************************************************************************/
1891 static int call_trans2mkdir(connection_struct *conn,
1892 char *inbuf, char *outbuf, int length, int bufsize,
1893 char **pparams, char **ppdata)
1895 char *params = *pparams;
1898 BOOL bad_path = False;
1900 if (!CAN_WRITE(conn))
1901 return(ERROR(ERRSRV,ERRaccess));
1903 pstrcpy(directory, ¶ms[4]);
1905 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1907 if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
1909 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1910 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1912 if (check_name(directory,conn))
1913 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
1914 unix_mode(conn,aDIR));
1918 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1919 if((errno == ENOENT) && bad_path)
1921 unix_ERR_class = ERRDOS;
1922 unix_ERR_code = ERRbadpath;
1924 return(UNIXERROR(ERRDOS,ERRnoaccess));
1927 /* Realloc the parameter and data sizes */
1928 params = *pparams = Realloc(*pparams,2);
1930 return(ERROR(ERRDOS,ERRnomem));
1934 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1939 /****************************************************************************
1940 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1941 We don't actually do this - we just send a null response.
1942 ****************************************************************************/
1943 static int call_trans2findnotifyfirst(connection_struct *conn,
1944 char *inbuf, char *outbuf,
1945 int length, int bufsize,
1946 char **pparams, char **ppdata)
1948 static uint16 fnf_handle = 257;
1949 char *params = *pparams;
1950 uint16 info_level = SVAL(params,4);
1952 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1960 return(ERROR(ERRDOS,ERRunknownlevel));
1963 /* Realloc the parameter and data sizes */
1964 params = *pparams = Realloc(*pparams,6);
1966 return(ERROR(ERRDOS,ERRnomem));
1968 SSVAL(params,0,fnf_handle);
1969 SSVAL(params,2,0); /* No changes */
1970 SSVAL(params,4,0); /* No EA errors */
1977 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1982 /****************************************************************************
1983 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1984 changes). Currently this does nothing.
1985 ****************************************************************************/
1986 static int call_trans2findnotifynext(connection_struct *conn,
1987 char *inbuf, char *outbuf,
1988 int length, int bufsize,
1989 char **pparams, char **ppdata)
1991 char *params = *pparams;
1993 DEBUG(3,("call_trans2findnotifynext\n"));
1995 /* Realloc the parameter and data sizes */
1996 params = *pparams = Realloc(*pparams,4);
1998 return(ERROR(ERRDOS,ERRnomem));
2000 SSVAL(params,0,0); /* No changes */
2001 SSVAL(params,2,0); /* No EA errors */
2003 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2008 /****************************************************************************
2009 reply to a SMBfindclose (stop trans2 directory search)
2010 ****************************************************************************/
2011 int reply_findclose(connection_struct *conn,
2012 char *inbuf,char *outbuf,int length,int bufsize)
2015 int16 dptr_num=SVALS(inbuf,smb_vwv0);
2017 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2019 dptr_close(dptr_num);
2021 outsize = set_message(outbuf,0,0,True);
2023 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2028 /****************************************************************************
2029 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2030 ****************************************************************************/
2031 int reply_findnclose(connection_struct *conn,
2032 char *inbuf,char *outbuf,int length,int bufsize)
2037 dptr_num = SVAL(inbuf,smb_vwv0);
2039 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2041 /* We never give out valid handles for a
2042 findnotifyfirst - so any dptr_num is ok here.
2045 outsize = set_message(outbuf,0,0,True);
2047 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2054 /****************************************************************************
2055 reply to a TRANS2_GET_DFS_REFERRAL
2056 ****************************************************************************/
2057 static int call_trans2getdfsreferral(connection_struct *conn,
2058 char *inbuf, char *outbuf, int length,
2060 char **pparams, char **ppdata,
2063 char *params = *pparams;
2066 char *localstring_offset;
2067 char *mangledstring_offset;
2068 char *sharename_offset;
2069 char *referal_offset;
2073 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2074 int query_file_len=0;
2078 BOOL first_one=True;
2080 referal_trans_param rtp;
2081 dfs_internal_table *list=dfs_struct.table;
2084 DEBUG(0,("call_trans2getdfsreferral:1\n"));
2089 /* decode the param member of query */
2090 rtp.level=SVAL(params, 0);
2091 DEBUGADD(0,("rtp.level:[%d]\n",rtp.level));
2093 DEBUGADD(0,("total_params:[%d]\n",total_params));
2094 for (i=0; i<(total_params-2)/2; i++)
2096 rtp.directory[i]=SVAL(params, 2+2*i);
2099 strupper(rtp.directory);
2101 query_file_len=strlen(rtp.directory);
2102 DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory));
2103 DEBUGADD(0,("query_file_len:[%d]\n",query_file_len));
2106 lookup in the internal DFS table all the entries
2107 and calculate the required data buffer size
2109 bytesreq=8; /* the header */
2110 reply.number_of_referal=0;
2111 DEBUGADD(0,("call_trans2getdfsreferral:2\n"));
2113 for(i=0; i<dfs_struct.size; i++)
2115 filename_len=list[i].localpath_length;
2116 DEBUGADD(0,("checking against [%s][%d]\n", list[i].localpath, filename_len));
2118 if( (filename_len==query_file_len) &&
2119 (!StrnCaseCmp(rtp.directory, list[i].localpath, query_file_len)) )
2122 bytesreq+=22; /* the referal size */
2123 bytesreq+=2*(list[i].sharename_length+1); /* the string length */
2124 reply.number_of_referal++;
2125 DEBUGADD(0,("found\n"));
2128 DEBUGADD(0,("first one\n"));
2129 bytesreq+=2*(list[i].localpath_length+1);
2130 bytesreq+=2*(list[i].mangledpath_length+1);
2132 reply.path_consumed=list[i].localpath_length;
2134 strncpy(reply.filename, list[i].localpath, list[i].localpath_length+1);
2135 strncpy(reply.mangledname, list[i].mangledpath, list[i].mangledpath_length+1);
2136 rtp.type=list[i].type;
2141 DEBUGADD(0,("call_trans2getdfsreferral:3\n"));
2143 /* allocate memory for the reply data */
2144 pdata = *ppdata = Realloc(*ppdata, bytesreq + 1024);
2145 bzero(*ppdata, bytesreq+22);
2150 localstring_offset = pdata + 8 + reply.number_of_referal*22;
2153 mangledstring_offset = localstring_offset + 2*(1+strlen(reply.filename));
2154 sharename_offset = mangledstring_offset + 2*(1+strlen(reply.mangledname));
2157 mangledstring_offset = localstring_offset + (1+strlen(reply.filename));
2158 sharename_offset = mangledstring_offset + (1+strlen(reply.mangledname));
2160 referal_offset = pdata + 8;
2162 /* right now respond storage server */
2164 reply.server_function=rtp.type;
2166 reply.server_function=0x3;
2168 /* write the header */
2170 SSVAL(pheader, 0, reply.path_consumed*2);
2172 SSVAL(pheader, 0, reply.path_consumed);
2174 SSVAL(pheader, 2, reply.number_of_referal);
2175 SIVAL(pheader, 4, reply.server_function);
2177 /* write the local path string */
2179 for(i=0; i<strlen(reply.filename); i++)
2181 SSVAL(localstring_offset, 2*i, (uint16) reply.filename[i]);
2183 SSVAL(localstring_offset, 2*strlen(reply.filename), 0);
2186 for(i=0; i<strlen(reply.filename); i++)
2188 localstring_offset[i]=reply.filename[i];
2190 localstring_offset[strlen(reply.filename)]=0;
2192 DEBUG(0,("reply.filename is [%s]:[%d], i is [%d]\n", reply.filename, strlen(reply.filename), i));
2194 /* write the mangled local path string */
2196 for(i=0; i<strlen(reply.mangledname); i++)
2198 SSVAL(mangledstring_offset, 2*i, (uint16) reply.mangledname[i]);
2200 SSVAL(mangledstring_offset, 2*i, 0);
2202 for(i=0; i<strlen(reply.mangledname); i++)
2204 mangledstring_offset[i]=reply.mangledname[i];
2206 mangledstring_offset[i]=0;
2208 DEBUGADD(0,("call_trans2getdfsreferral:4\n"));
2210 /* the order of the referals defines the load balancing */
2212 /* write each referal */
2213 for(i=0; i<dfs_struct.size; i++)
2215 filename_len=list[i].localpath_length;
2217 if(filename_len==query_file_len &&
2218 !strncasecmp(rtp.directory, list[i].localpath, query_file_len))
2221 SSVAL(referal_offset, 0, 2); /* version */
2222 SSVAL(referal_offset, 2, 22); /* size */
2225 SSVAL(referal_offset, 4, 1); /* type SMB server*/
2227 SSVAL(referal_offset, 4, 0); /* type unknown */
2228 SSVAL(referal_offset, 6, 1); /* flags */
2229 SIVAL(referal_offset, 8, list[i].proximity); /* proximity */
2230 SIVAL(referal_offset, 12, 300); /* ttl */
2231 SSVAL(referal_offset, 16, localstring_offset-referal_offset);
2232 SSVAL(referal_offset, 18, mangledstring_offset-referal_offset);
2233 SSVAL(referal_offset, 20, sharename_offset-referal_offset);
2236 for(j=0; j<list[i].sharename_length; j++)
2238 SSVAL(sharename_offset, 2*j, (uint16) list[i].sharename[j]);
2240 SSVAL(sharename_offset, 2*j, 0);
2242 sharename_offset=sharename_offset + 2*(1+list[i].sharename_length);
2244 for(j=0; j<list[i].sharename_length; j++)
2246 sharename_offset[j]=list[i].sharename[j];
2248 sharename_offset[j]=0;
2250 sharename_offset=sharename_offset + (1+list[i].sharename_length);
2253 referal_offset=referal_offset+22;
2257 DEBUGADD(0,("call_trans2getdfsreferral:5\n"));
2259 send_trans2_replies(outbuf, bufsize, params, 0, *ppdata, bytesreq+22);
2261 /* send_trans2_replies(outbuf, bufsize, *ppdata, bytesreq, params, 0);*/
2262 DEBUGADD(0,("call_trans2getdfsreferral:6\n"));
2268 /****************************************************************************
2269 reply to a TRANS2_REPORT_DFS_INCONSISTANCY
2270 ****************************************************************************/
2271 static int call_trans2reportdfsinconsistancy(connection_struct *conn,
2272 char *inbuf, char *outbuf, int length,
2274 char **pparams, char **ppdata)
2276 char *params = *pparams;
2278 DEBUG(4,("call_trans2reportdfsinconsistancy\n"));
2279 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2284 /****************************************************************************
2285 reply to a SMBtranss2 - just ignore it!
2286 ****************************************************************************/
2287 int reply_transs2(connection_struct *conn,
2288 char *inbuf,char *outbuf,int length,int bufsize)
2290 DEBUG(4,("Ignoring transs2 of length %d\n",length));
2294 /****************************************************************************
2295 reply to a SMBtrans2
2296 ****************************************************************************/
2297 int reply_trans2(connection_struct *conn,
2298 char *inbuf,char *outbuf,int length,int bufsize)
2301 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2302 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2304 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2305 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2306 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2307 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2308 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2309 int32 timeout = IVALS(inbuf,smb_timeout);
2311 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2312 unsigned int tran_call = SVAL(inbuf, smb_setup0);
2313 char *params = NULL, *data = NULL;
2314 int num_params, num_params_sofar, num_data, num_data_sofar;
2316 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2317 /* Queue this open message as we are the process of an
2320 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2321 DEBUGADD(2,( "in oplock break state.\n"));
2323 push_oplock_pending_smb_message(inbuf, length);
2327 outsize = set_message(outbuf,0,0,True);
2329 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2330 is so as a sanity check */
2332 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2333 return(ERROR(ERRSRV,ERRerror));
2336 /* Allocate the space for the maximum needed parameters and data */
2337 if (total_params > 0)
2338 params = (char *)malloc(total_params);
2340 data = (char *)malloc(total_data);
2342 if ((total_params && !params) || (total_data && !data)) {
2343 DEBUG(2,("Out of memory in reply_trans2\n"));
2348 return(ERROR(ERRDOS,ERRnomem));
2351 /* Copy the param and data bytes sent with this request into
2352 the params buffer */
2353 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2354 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2356 if (num_params > total_params || num_data > total_data)
2357 exit_server("invalid params in reply_trans2");
2360 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2362 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2364 if(num_data_sofar < total_data || num_params_sofar < total_params) {
2365 /* We need to send an interim response then receive the rest
2366 of the parameter/data bytes */
2367 outsize = set_message(outbuf,0,0,True);
2368 send_smb(Client,outbuf);
2370 while (num_data_sofar < total_data ||
2371 num_params_sofar < total_params) {
2374 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2377 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2378 outsize = set_message(outbuf,0,0,True);
2380 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2382 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2383 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2388 return(ERROR(ERRSRV,ERRerror));
2391 /* Revise total_params and total_data in case
2392 they have changed downwards */
2393 total_params = SVAL(inbuf, smb_tpscnt);
2394 total_data = SVAL(inbuf, smb_tdscnt);
2395 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2396 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2397 if (num_params_sofar > total_params || num_data_sofar > total_data)
2398 exit_server("data overflow in trans2");
2400 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
2401 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2402 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2403 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2407 if (Protocol >= PROTOCOL_NT1) {
2408 uint16 flg2 = SVAL(outbuf,smb_flg2);
2409 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2412 /* Now we must call the relevant TRANS2 function */
2415 case TRANSACT2_OPEN:
2417 outsize = call_trans2open(conn,
2418 inbuf, outbuf, bufsize,
2422 case TRANSACT2_FINDFIRST:
2424 outsize = call_trans2findfirst(conn, inbuf, outbuf,
2425 bufsize, ¶ms, &data);
2428 case TRANSACT2_FINDNEXT:
2430 outsize = call_trans2findnext(conn, inbuf, outbuf,
2435 case TRANSACT2_QFSINFO:
2437 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
2438 length, bufsize, ¶ms,
2442 case TRANSACT2_SETFSINFO:
2444 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2449 case TRANSACT2_QPATHINFO:
2450 case TRANSACT2_QFILEINFO:
2452 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2454 ¶ms, &data, total_data);
2457 case TRANSACT2_SETPATHINFO:
2458 case TRANSACT2_SETFILEINFO:
2460 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2466 case TRANSACT2_FINDNOTIFYFIRST:
2468 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2473 case TRANSACT2_FINDNOTIFYNEXT:
2475 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2480 case TRANSACT2_MKDIR:
2482 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2483 bufsize, ¶ms, &data);
2486 case TRANSACT2_GET_DFS_REFERRAL:
2488 outsize = call_trans2getdfsreferral(conn, inbuf, outbuf,
2489 length, bufsize, ¶ms,
2493 case TRANSACT2_REPORT_DFS_INCONSISTANCY:
2495 outsize = call_trans2reportdfsinconsistancy(conn, inbuf, outbuf,
2502 /* Error in request */
2503 DEBUG(2,("Unknown request %d in trans2 call\n",
2509 return (ERROR(ERRSRV,ERRerror));
2513 /* As we do not know how many data packets will need to be
2514 returned here the various call_trans2xxxx calls
2515 must send their own. Thus a call_trans2xxx routine only
2516 returns a value other than -1 when it wants to send
2524 return outsize; /* If a correct response was needed the
2525 call_trans2xxx calls have already sent
2526 it. If outsize != -1 then it is returning */