2 Unix SMB/Netbios implementation.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1998
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
33 extern int oplock_sock;
34 extern int smb_read_error;
35 extern fstring local_machine;
37 /****************************************************************************
38 Send the required number of replies back.
39 We assume all fields other than the data fields are
40 set correctly for the type of call.
41 HACK ! Always assumes smb_setup field is zero.
42 ****************************************************************************/
43 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
44 int paramsize, char *pdata, int datasize)
46 /* As we are using a protocol > LANMAN1 then the max_send
47 variable must have been set in the sessetupX call.
48 This takes precedence over the max_xmit field in the
49 global struct. These different max_xmit variables should
50 be merged as this is now too confusing */
53 int data_to_send = datasize;
54 int params_to_send = paramsize;
58 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
59 int alignment_offset = 3;
60 int data_alignment_offset = 0;
62 /* Initially set the wcnt area to be 10 - this is true for all
64 set_message(outbuf,10,0,True);
66 /* If there genuinely are no parameters or data to send just send
68 if(params_to_send == 0 && data_to_send == 0)
70 send_smb(Client,outbuf);
74 /* When sending params and data ensure that both are nicely aligned */
75 /* Only do this alignment when there is also data to send - else
76 can cause NT redirector problems. */
77 if (((params_to_send % 4) != 0) && (data_to_send != 0))
78 data_alignment_offset = 4 - (params_to_send % 4);
80 /* Space is bufsize minus Netbios over TCP header minus SMB header */
81 /* The alignment_offset is to align the param bytes on an even byte
82 boundary. NT 4.0 Beta needs this to work correctly. */
83 useable_space = bufsize - ((smb_buf(outbuf)+
84 alignment_offset+data_alignment_offset) -
87 /* useable_space can never be more than max_send minus the
89 useable_space = MIN(useable_space,
90 max_send - (alignment_offset+data_alignment_offset));
93 while (params_to_send || data_to_send)
95 /* Calculate whether we will totally or partially fill this packet */
96 total_sent_thistime = params_to_send + data_to_send +
97 alignment_offset + data_alignment_offset;
98 /* We can never send more than useable_space */
99 total_sent_thistime = MIN(total_sent_thistime, useable_space);
101 set_message(outbuf, 10, total_sent_thistime, True);
103 /* Set total params and data to be sent */
104 SSVAL(outbuf,smb_tprcnt,paramsize);
105 SSVAL(outbuf,smb_tdrcnt,datasize);
107 /* Calculate how many parameters and data we can fit into
108 this packet. Parameters get precedence */
110 params_sent_thistime = MIN(params_to_send,useable_space);
111 data_sent_thistime = useable_space - params_sent_thistime;
112 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
114 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
115 if(params_sent_thistime == 0)
117 SSVAL(outbuf,smb_proff,0);
118 SSVAL(outbuf,smb_prdisp,0);
120 /* smb_proff is the offset from the start of the SMB header to the
121 parameter bytes, however the first 4 bytes of outbuf are
122 the Netbios over TCP header. Thus use smb_base() to subtract
123 them from the calculation */
124 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
125 /* Absolute displacement of param bytes sent in this packet */
126 SSVAL(outbuf,smb_prdisp,pp - params);
129 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
130 if(data_sent_thistime == 0)
132 SSVAL(outbuf,smb_droff,0);
133 SSVAL(outbuf,smb_drdisp, 0);
135 /* The offset of the data bytes is the offset of the
136 parameter bytes plus the number of parameters being sent this time */
137 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
139 params_sent_thistime + data_alignment_offset);
140 SSVAL(outbuf,smb_drdisp, pd - pdata);
143 /* Copy the param bytes into the packet */
144 if(params_sent_thistime)
145 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
146 /* Copy in the data bytes */
147 if(data_sent_thistime)
148 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime);
150 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
151 params_sent_thistime, data_sent_thistime, useable_space));
152 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
153 params_to_send, data_to_send, paramsize, datasize));
155 /* Send the packet */
156 send_smb(Client,outbuf);
158 pp += params_sent_thistime;
159 pd += data_sent_thistime;
161 params_to_send -= params_sent_thistime;
162 data_to_send -= data_sent_thistime;
165 if(params_to_send < 0 || data_to_send < 0)
167 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
168 params_to_send, data_to_send));
177 /****************************************************************************
178 reply to a TRANSACT2_OPEN
179 ****************************************************************************/
180 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
181 char **pparams, char **ppdata)
183 char *params = *pparams;
184 int16 open_mode = SVAL(params, 2);
185 int16 open_attr = SVAL(params,6);
186 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
188 BOOL return_additional_info = BITSETW(params,0);
189 int16 open_sattr = SVAL(params, 4);
190 time_t open_time = make_unix_date3(params+8);
192 int16 open_ofun = SVAL(params,12);
193 int32 open_size = IVAL(params,14);
194 char *pname = ¶ms[28];
195 int16 namelen = strlen(pname)+1;
200 int size=0,fmode=0,mtime=0,rmode;
204 BOOL bad_path = False;
206 StrnCpy(fname,pname,namelen);
208 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
209 fname,cnum,open_mode, open_attr, open_ofun, open_size));
211 /* XXXX we need to handle passed times, sattr and flags */
213 unix_convert(fname,cnum,0,&bad_path);
215 fnum = find_free_file();
217 return(ERROR(ERRSRV,ERRnofids));
219 if (!check_name(fname,cnum))
221 if((errno == ENOENT) && bad_path)
223 unix_ERR_class = ERRDOS;
224 unix_ERR_code = ERRbadpath;
226 Files[fnum].reserved = False;
227 return(UNIXERROR(ERRDOS,ERRnoaccess));
230 unixmode = unix_mode(cnum,open_attr | aARCH);
233 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
234 oplock_request, &rmode,&smb_action);
236 if (!Files[fnum].open)
238 if((errno == ENOENT) && bad_path)
240 unix_ERR_class = ERRDOS;
241 unix_ERR_code = ERRbadpath;
243 Files[fnum].reserved = False;
244 return(UNIXERROR(ERRDOS,ERRnoaccess));
247 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
248 close_file(fnum,False);
249 return(ERROR(ERRDOS,ERRnoaccess));
253 fmode = dos_mode(cnum,fname,&sbuf);
254 mtime = sbuf.st_mtime;
257 close_file(fnum,False);
258 return(ERROR(ERRDOS,ERRnoaccess));
261 /* Realloc the size of parameters and data we will return */
262 params = *pparams = Realloc(*pparams, 28);
264 return(ERROR(ERRDOS,ERRnomem));
267 SSVAL(params,0,fnum);
268 SSVAL(params,2,fmode);
269 put_dos_date2(params,4, mtime);
270 SIVAL(params,8, size);
271 SSVAL(params,12,rmode);
273 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
274 smb_action |= EXTENDED_OPLOCK_GRANTED;
277 SSVAL(params,18,smb_action);
278 SIVAL(params,20,inode);
280 /* Send the required number of replies */
281 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
286 /****************************************************************************
287 get a level dependent lanman2 dir entry.
288 ****************************************************************************/
289 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
290 int requires_resume_key,
291 BOOL dont_descend,char **ppdata,
292 char *base_data, int space_remaining,
303 char *p, *pdata = *ppdata;
304 int reskey=0, prev_dirpos=0;
307 uint32 mdate=0, adate=0, cdate=0;
309 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
310 strequal(Connections[cnum].dirpath,".") ||
311 strequal(Connections[cnum].dirpath,"/"));
313 int nt_extmode; /* Used for NT connections instead of mode */
314 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
317 *out_of_space = False;
319 if (!Connections[cnum].dirptr)
322 p = strrchr(path_mask,'/');
331 pstrcpy(mask, path_mask);
335 /* Needed if we run out of space */
336 prev_dirpos = TellDir(Connections[cnum].dirptr);
337 dname = ReadDirName(Connections[cnum].dirptr);
339 reskey = TellDir(Connections[cnum].dirptr);
341 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
342 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
349 pstrcpy(fname,dname);
351 if(mask_match(fname, mask, case_sensitive, True))
353 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
354 if (dont_descend && !isdots)
357 if (isrootdir && isdots)
360 pstrcpy(pathreal,Connections[cnum].dirpath);
362 strcat(pathreal,"/");
363 strcat(pathreal,dname);
364 if (sys_stat(pathreal,&sbuf) != 0)
366 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
370 mode = dos_mode(cnum,pathreal,&sbuf);
372 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
373 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
378 mdate = sbuf.st_mtime;
379 adate = get_access_time(&sbuf);
380 cdate = get_create_time(&sbuf);
384 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
390 name_map_mangle(fname,False,SNUM(cnum));
395 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
400 if(requires_resume_key) {
404 put_dos_date2(p,l1_fdateCreation,cdate);
405 put_dos_date2(p,l1_fdateLastAccess,adate);
406 put_dos_date2(p,l1_fdateLastWrite,mdate);
407 SIVAL(p,l1_cbFile,size);
408 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
409 SSVAL(p,l1_attrFile,mode);
410 SCVAL(p,l1_cchName,strlen(fname));
411 strcpy(p + l1_achName, fname);
412 nameptr = p + l1_achName;
413 p += l1_achName + strlen(fname) + 1;
418 if(requires_resume_key) {
422 put_dos_date2(p,l2_fdateCreation,cdate);
423 put_dos_date2(p,l2_fdateLastAccess,adate);
424 put_dos_date2(p,l2_fdateLastWrite,mdate);
425 SIVAL(p,l2_cbFile,size);
426 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
427 SSVAL(p,l2_attrFile,mode);
428 SIVAL(p,l2_cbList,0); /* No extended attributes */
429 SCVAL(p,l2_cchName,strlen(fname));
430 strcpy(p + l2_achName, fname);
431 nameptr = p + l2_achName;
432 p += l2_achName + strlen(fname) + 1;
437 put_dos_date2(p,4,cdate);
438 put_dos_date2(p,8,adate);
439 put_dos_date2(p,12,mdate);
441 SIVAL(p,20,ROUNDUP(size,1024));
444 CVAL(p,30) = strlen(fname);
447 p += 31 + strlen(fname) + 1;
451 if(requires_resume_key) {
455 SIVAL(p,0,33+strlen(fname)+1);
456 put_dos_date2(p,4,cdate);
457 put_dos_date2(p,8,adate);
458 put_dos_date2(p,12,mdate);
460 SIVAL(p,20,ROUNDUP(size,1024));
462 CVAL(p,32) = strlen(fname);
463 strcpy(p + 33, fname);
465 p += 33 + strlen(fname) + 1;
468 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
469 was_8_3 = is_8_3(fname, True);
470 len = 94+strlen(fname);
471 len = (len + 3) & ~3;
472 SIVAL(p,0,len); p += 4;
473 SIVAL(p,0,reskey); p += 4;
474 put_long_date(p,cdate); p += 8;
475 put_long_date(p,adate); p += 8;
476 put_long_date(p,mdate); p += 8;
477 put_long_date(p,mdate); p += 8;
478 SIVAL(p,0,size); p += 8;
479 SIVAL(p,0,size); p += 8;
480 SIVAL(p,0,nt_extmode); p += 4;
481 SIVAL(p,0,strlen(fname)); p += 4;
482 SIVAL(p,0,0); p += 4;
485 if (!name_map_mangle(p+2,True,SNUM(cnum)))
490 SSVAL(p,0,strlen(p+2));
493 strcpy(p,fname); p += strlen(p);
497 case SMB_FIND_FILE_DIRECTORY_INFO:
498 len = 64+strlen(fname);
499 len = (len + 3) & ~3;
500 SIVAL(p,0,len); p += 4;
501 SIVAL(p,0,reskey); p += 4;
502 put_long_date(p,cdate); p += 8;
503 put_long_date(p,adate); p += 8;
504 put_long_date(p,mdate); p += 8;
505 put_long_date(p,mdate); p += 8;
506 SIVAL(p,0,size); p += 8;
507 SIVAL(p,0,size); p += 8;
508 SIVAL(p,0,nt_extmode); p += 4;
509 SIVAL(p,0,strlen(fname)); p += 4;
515 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
516 len = 68+strlen(fname);
517 len = (len + 3) & ~3;
518 SIVAL(p,0,len); p += 4;
519 SIVAL(p,0,reskey); p += 4;
520 put_long_date(p,cdate); p += 8;
521 put_long_date(p,adate); p += 8;
522 put_long_date(p,mdate); p += 8;
523 put_long_date(p,mdate); p += 8;
524 SIVAL(p,0,size); p += 8;
525 SIVAL(p,0,size); p += 8;
526 SIVAL(p,0,nt_extmode); p += 4;
527 SIVAL(p,0,strlen(fname)); p += 4;
528 SIVAL(p,0,0); p += 4;
533 case SMB_FIND_FILE_NAMES_INFO:
534 len = 12+strlen(fname);
535 len = (len + 3) & ~3;
536 SIVAL(p,0,len); p += 4;
537 SIVAL(p,0,reskey); p += 4;
538 SIVAL(p,0,strlen(fname)); p += 4;
548 if (PTR_DIFF(p,pdata) > space_remaining) {
549 /* Move the dirptr back to prev_dirpos */
550 SeekDir(Connections[cnum].dirptr, prev_dirpos);
551 *out_of_space = True;
552 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
553 return False; /* Not finished - just out of space */
556 /* Setup the last_filename pointer, as an offset from base_data */
557 *last_name_off = PTR_DIFF(nameptr,base_data);
558 /* Advance the data pointer to the next slot */
563 /****************************************************************************
564 reply to a TRANS2_FINDFIRST
565 ****************************************************************************/
566 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
567 char **pparams, char **ppdata)
569 /* We must be careful here that we don't return more than the
570 allowed number of data bytes. If this means returning fewer than
571 maxentries then so be it. We assume that the redirector has
572 enough room for the fixed number of parameter bytes it has
574 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
575 char *params = *pparams;
576 char *pdata = *ppdata;
577 int dirtype = SVAL(params,0);
578 int maxentries = SVAL(params,2);
579 BOOL close_after_first = BITSETW(params+4,0);
580 BOOL close_if_end = BITSETW(params+4,1);
581 BOOL requires_resume_key = BITSETW(params+4,2);
582 int info_level = SVAL(params,6);
590 BOOL finished = False;
591 BOOL dont_descend = False;
592 BOOL out_of_space = False;
594 BOOL bad_path = False;
596 *directory = *mask = 0;
598 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",
599 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
600 info_level, max_data_bytes));
608 case SMB_FIND_FILE_DIRECTORY_INFO:
609 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
610 case SMB_FIND_FILE_NAMES_INFO:
611 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
614 return(ERROR(ERRDOS,ERRunknownlevel));
617 pstrcpy(directory, params + 12); /* Complete directory path with
618 wildcard mask appended */
620 DEBUG(5,("path=%s\n",directory));
622 unix_convert(directory,cnum,0,&bad_path);
623 if(!check_name(directory,cnum)) {
624 if((errno == ENOENT) && bad_path)
626 unix_ERR_class = ERRDOS;
627 unix_ERR_code = ERRbadpath;
631 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
632 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
633 (get_remote_arch() == RA_WINNT))
635 unix_ERR_class = ERRDOS;
636 unix_ERR_code = ERRbaddirectory;
640 return(ERROR(ERRDOS,ERRbadpath));
643 p = strrchr(directory,'/');
645 strcpy(mask,directory);
646 strcpy(directory,"./");
652 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
654 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
656 return(ERROR(ERRDOS,ERRnomem));
657 bzero(pdata,max_data_bytes);
659 /* Realloc the params space */
660 params = *pparams = Realloc(*pparams, 10);
662 return(ERROR(ERRDOS,ERRnomem));
664 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
666 return(ERROR(ERRDOS,ERRbadfile));
668 /* convert the formatted masks */
672 if (*p == '<') *p = '*';
673 if (*p == '>') *p = '?';
674 if (*p == '"') *p = '.';
679 /* a special case for 16 bit apps */
680 if (strequal(mask,"????????.???")) strcpy(mask,"*");
682 /* handle broken clients that send us old 8.3 format */
683 string_sub(mask,"????????","*");
684 string_sub(mask,".???",".*");
686 /* Save the wildcard match and attribs we are using on this directory -
687 needed as lanman2 assumes these are being saved between calls */
689 if(!(wcard = strdup(mask))) {
690 dptr_close(dptr_num);
691 return(ERROR(ERRDOS,ERRnomem));
694 dptr_set_wcard(dptr_num, wcard);
695 dptr_set_attr(dptr_num, dirtype);
697 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
699 /* We don't need to check for VOL here as this is returned by
700 a different TRANS2 call. */
702 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
703 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
704 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
708 space_remaining = max_data_bytes;
709 out_of_space = False;
711 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
714 /* this is a heuristic to avoid seeking the dirptr except when
715 absolutely necessary. It allows for a filename of about 40 chars */
716 if (space_remaining < DIRLEN_GUESS && numentries > 0)
724 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
725 requires_resume_key,dont_descend,
726 &p,pdata,space_remaining, &out_of_space,
730 if (finished && out_of_space)
733 if (!finished && !out_of_space)
735 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
738 /* Check if we can close the dirptr */
739 if(close_after_first || (finished && close_if_end))
741 dptr_close(dptr_num);
742 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
747 * If there are no matching entries we must return ERRDOS/ERRbadfile -
748 * from observation of NT.
752 return(ERROR(ERRDOS,ERRbadfile));
754 /* At this point pdata points to numentries directory entries. */
756 /* Set up the return parameter block */
757 SSVAL(params,0,dptr_num);
758 SSVAL(params,2,numentries);
759 SSVAL(params,4,finished);
760 SSVAL(params,6,0); /* Never an EA error */
761 SSVAL(params,8,last_name_off);
763 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
765 if ((! *directory) && dptr_path(dptr_num))
766 sprintf(directory,"(%s)",dptr_path(dptr_num));
768 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
770 smb_fn_name(CVAL(inbuf,smb_com)),
771 mask,directory,cnum,dirtype,numentries));
777 /****************************************************************************
778 reply to a TRANS2_FINDNEXT
779 ****************************************************************************/
780 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
781 int cnum, char **pparams, char **ppdata)
783 /* We must be careful here that we don't return more than the
784 allowed number of data bytes. If this means returning fewer than
785 maxentries then so be it. We assume that the redirector has
786 enough room for the fixed number of parameter bytes it has
788 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
789 char *params = *pparams;
790 char *pdata = *ppdata;
791 int16 dptr_num = SVAL(params,0);
792 int maxentries = SVAL(params,2);
793 uint16 info_level = SVAL(params,4);
794 uint32 resume_key = IVAL(params,6);
795 BOOL close_after_request = BITSETW(params+10,0);
796 BOOL close_if_end = BITSETW(params+10,1);
797 BOOL requires_resume_key = BITSETW(params+10,2);
798 BOOL continue_bit = BITSETW(params+10,3);
804 int i, last_name_off=0;
805 BOOL finished = False;
806 BOOL dont_descend = False;
807 BOOL out_of_space = False;
810 *mask = *directory = 0;
812 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n",
813 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
814 requires_resume_key, resume_key, continue_bit, info_level));
822 case SMB_FIND_FILE_DIRECTORY_INFO:
823 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
824 case SMB_FIND_FILE_NAMES_INFO:
825 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
828 return(ERROR(ERRDOS,ERRunknownlevel));
831 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
833 return(ERROR(ERRDOS,ERRnomem));
834 bzero(pdata,max_data_bytes);
836 /* Realloc the params space */
837 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
839 return(ERROR(ERRDOS,ERRnomem));
841 /* Check that the dptr is valid */
842 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
843 return(ERROR(ERRDOS,ERRnofiles));
845 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
847 /* Get the wildcard mask from the dptr */
848 if((p = dptr_wcard(dptr_num))== NULL) {
849 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
850 return (ERROR(ERRDOS,ERRnofiles));
853 strcpy(directory,Connections[cnum].dirpath);
855 /* Get the attr mask from the dptr */
856 dirtype = dptr_attr(dptr_num);
858 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
859 dptr_num, mask, dirtype,
860 Connections[cnum].dirptr,
861 TellDir(Connections[cnum].dirptr)));
863 /* We don't need to check for VOL here as this is returned by
864 a different TRANS2 call. */
866 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
867 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
871 space_remaining = max_data_bytes;
872 out_of_space = False;
874 /* If we have a resume key - seek to the correct position. */
875 if(requires_resume_key && !continue_bit)
876 SeekDir(Connections[cnum].dirptr, resume_key);
878 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
880 /* this is a heuristic to avoid seeking the dirptr except when
881 absolutely necessary. It allows for a filename of about 40 chars */
882 if (space_remaining < DIRLEN_GUESS && numentries > 0)
890 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
891 requires_resume_key,dont_descend,
892 &p,pdata,space_remaining, &out_of_space,
896 if (finished && out_of_space)
899 if (!finished && !out_of_space)
901 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
904 /* Check if we can close the dirptr */
905 if(close_after_request || (finished && close_if_end))
907 dptr_close(dptr_num); /* This frees up the saved mask */
908 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
913 /* Set up the return parameter block */
914 SSVAL(params,0,numentries);
915 SSVAL(params,2,finished);
916 SSVAL(params,4,0); /* Never an EA error */
917 SSVAL(params,6,last_name_off);
919 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
921 if ((! *directory) && dptr_path(dptr_num))
922 sprintf(directory,"(%s)",dptr_path(dptr_num));
924 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
926 smb_fn_name(CVAL(inbuf,smb_com)),
927 mask,directory,cnum,dirtype,numentries));
932 /****************************************************************************
933 reply to a TRANS2_QFSINFO (query filesystem info)
934 ****************************************************************************/
935 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
936 int cnum, char **pparams, char **ppdata)
938 char *pdata = *ppdata;
939 char *params = *pparams;
940 uint16 info_level = SVAL(params,0);
943 char *vname = volume_label(SNUM(cnum));
944 int snum = SNUM(cnum);
946 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
948 if(sys_stat(".",&st)!=0) {
949 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
950 return (ERROR(ERRSRV,ERRinvdevice));
953 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
959 int dfree,dsize,bsize;
961 sys_disk_free(".",&bsize,&dfree,&dsize);
962 SIVAL(pdata,l1_idFileSystem,st.st_dev);
963 SIVAL(pdata,l1_cSectorUnit,bsize/512);
964 SIVAL(pdata,l1_cUnit,dsize);
965 SIVAL(pdata,l1_cUnitAvail,dfree);
966 SSVAL(pdata,l1_cbSector,512);
967 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
968 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
973 /* Return volume name */
974 int volname_len = MIN(strlen(vname),11);
975 data_len = l2_vol_szVolLabel + volname_len + 1;
977 * Add volume serial number - hash of a combination of
978 * the called hostname and the service name.
980 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) );
981 SCVAL(pdata,l2_vol_cch,volname_len);
982 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
983 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
984 pdata+l2_vol_szVolLabel));
987 case SMB_QUERY_FS_ATTRIBUTE_INFO:
988 data_len = 12 + 2*strlen(FSTYPE_STRING);
989 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
990 SIVAL(pdata,4,128); /* Max filename component length */
991 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
992 PutUniCode(pdata+12,FSTYPE_STRING);
994 case SMB_QUERY_FS_LABEL_INFO:
995 data_len = 4 + strlen(vname);
996 SIVAL(pdata,0,strlen(vname));
997 strcpy(pdata+4,vname);
999 case SMB_QUERY_FS_VOLUME_INFO:
1000 data_len = 18 + 2*strlen(vname);
1002 * Add volume serial number - hash of a combination of
1003 * the called hostname and the service name.
1005 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) );
1006 SIVAL(pdata,12,2*strlen(vname));
1007 PutUniCode(pdata+18,vname);
1008 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1011 case SMB_QUERY_FS_SIZE_INFO:
1013 int dfree,dsize,bsize;
1015 sys_disk_free(".",&bsize,&dfree,&dsize);
1016 SIVAL(pdata,0,dsize);
1017 SIVAL(pdata,8,dfree);
1018 SIVAL(pdata,16,bsize/512);
1019 SIVAL(pdata,20,512);
1022 case SMB_QUERY_FS_DEVICE_INFO:
1024 SIVAL(pdata,0,0); /* dev type */
1025 SIVAL(pdata,4,0); /* characteristics */
1028 return(ERROR(ERRDOS,ERRunknownlevel));
1032 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1034 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1039 /****************************************************************************
1040 reply to a TRANS2_SETFSINFO (set filesystem info)
1041 ****************************************************************************/
1042 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1043 int cnum, char **pparams, char **ppdata)
1045 /* Just say yes we did it - there is nothing that
1046 can be set here so it doesn't matter. */
1048 DEBUG(3,("call_trans2setfsinfo\n"));
1050 if (!CAN_WRITE(cnum))
1051 return(ERROR(ERRSRV,ERRaccess));
1053 outsize = set_message(outbuf,10,0,True);
1058 /****************************************************************************
1059 reply to a TRANS2_QFILEINFO (query file info by fileid)
1060 ****************************************************************************/
1061 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1062 int bufsize,int cnum,
1063 char **pparams,char **ppdata,
1066 char *params = *pparams;
1067 char *pdata = *ppdata;
1068 uint16 tran_call = SVAL(inbuf, smb_setup0);
1072 unsigned int data_size;
1078 BOOL bad_path = False;
1080 if (tran_call == TRANSACT2_QFILEINFO) {
1081 int16 fnum = SVALS(params,0);
1082 info_level = SVAL(params,2);
1084 CHECK_FNUM(fnum,cnum);
1087 fname = Files[fnum].name;
1088 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1089 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1090 return(UNIXERROR(ERRDOS,ERRbadfid));
1092 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1095 info_level = SVAL(params,0);
1097 pstrcpy(fname,¶ms[6]);
1098 unix_convert(fname,cnum,0,&bad_path);
1099 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1100 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1101 if((errno == ENOENT) && bad_path)
1103 unix_ERR_class = ERRDOS;
1104 unix_ERR_code = ERRbadpath;
1106 return(UNIXERROR(ERRDOS,ERRbadpath));
1112 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1113 fname,info_level,tran_call,total_data));
1115 p = strrchr(fname,'/');
1121 mode = dos_mode(cnum,fname,&sbuf);
1122 size = sbuf.st_size;
1123 if (mode & aDIR) size = 0;
1125 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1127 pdata = *ppdata = Realloc(*ppdata, data_size);
1129 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1130 /* uggh, EAs for OS2 */
1131 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1132 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1135 bzero(pdata,data_size);
1139 case SMB_INFO_STANDARD:
1140 case SMB_INFO_QUERY_EA_SIZE:
1141 data_size = (info_level==1?22:26);
1142 if( lp_win95_bug_compatibility())
1144 put_dos_date(pdata,l1_fdateCreation,get_create_time(&sbuf));
1145 put_dos_date(pdata,l1_fdateLastAccess,get_access_time(&sbuf));
1146 put_dos_date(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1150 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf));
1151 put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf));
1152 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1154 SIVAL(pdata,l1_cbFile,size);
1155 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1156 SSVAL(pdata,l1_attrFile,mode);
1157 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1160 case SMB_INFO_QUERY_EAS_FROM_LIST:
1162 put_dos_date2(pdata,0,get_create_time(&sbuf));
1163 put_dos_date2(pdata,4,get_access_time(&sbuf));
1164 put_dos_date2(pdata,8,sbuf.st_mtime);
1165 SIVAL(pdata,12,size);
1166 SIVAL(pdata,16,ROUNDUP(size,1024));
1167 SIVAL(pdata,20,mode);
1170 case SMB_INFO_QUERY_ALL_EAS:
1172 SIVAL(pdata,0,data_size);
1176 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1178 case SMB_QUERY_FILE_BASIC_INFO:
1179 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1180 put_long_date(pdata,get_create_time(&sbuf));
1181 put_long_date(pdata+8,get_access_time(&sbuf));
1182 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1183 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1184 SIVAL(pdata,32,mode);
1186 DEBUG(5,("SMB_QFBI - "));
1188 time_t create_time = get_create_time(&sbuf);
1189 DEBUG(5,("create: %s ", ctime(&create_time)));
1190 create_time = get_access_time(&sbuf);
1191 DEBUG(5,("access: %s ", ctime(&create_time)));
1193 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1194 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1195 DEBUG(5,("mode: %x\n", mode));
1199 case SMB_QUERY_FILE_STANDARD_INFO:
1201 SIVAL(pdata,0,size);
1202 SIVAL(pdata,8,size);
1203 SIVAL(pdata,16,sbuf.st_nlink);
1205 CVAL(pdata,21) = (mode&aDIR)?1:0;
1208 case SMB_QUERY_FILE_EA_INFO:
1212 /* Get the 8.3 name - used if NT SMB was negotiated. */
1213 case SMB_QUERY_FILE_ALT_NAME_INFO:
1216 pstrcpy(short_name,fname);
1217 /* Mangle if not already 8.3 */
1218 if(!is_8_3(short_name, True))
1220 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1223 strncpy(pdata + 4,short_name,12);
1224 (pdata + 4)[12] = 0;
1225 strupper(pdata + 4);
1226 l = strlen(pdata + 4);
1232 case SMB_QUERY_FILE_NAME_INFO:
1235 pstrcpy(pdata+4,fname);
1238 case SMB_QUERY_FILE_ALLOCATION_INFO:
1239 case SMB_QUERY_FILE_END_OF_FILEINFO:
1241 SIVAL(pdata,0,size);
1244 case SMB_QUERY_FILE_ALL_INFO:
1245 put_long_date(pdata,get_create_time(&sbuf));
1246 put_long_date(pdata+8,get_access_time(&sbuf));
1247 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1248 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1249 SIVAL(pdata,32,mode);
1251 SIVAL(pdata,0,size);
1252 SIVAL(pdata,8,size);
1253 SIVAL(pdata,16,sbuf.st_nlink);
1255 CVAL(pdata,21) = (mode&aDIR)?1:0;
1257 pdata += 8; /* index number */
1258 pdata += 4; /* EA info */
1260 SIVAL(pdata,0,0xA9);
1262 SIVAL(pdata,0,0xd01BF);
1264 SIVAL(pdata,0,pos); /* current offset */
1266 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1268 pdata += 4; /* alignment */
1270 pstrcpy(pdata+4,fname);
1272 data_size = PTR_DIFF(pdata,(*ppdata));
1275 case SMB_QUERY_FILE_STREAM_INFO:
1278 SIVAL(pdata,4,size);
1279 SIVAL(pdata,12,size);
1281 pstrcpy(pdata+24,fname);
1284 return(ERROR(ERRDOS,ERRunknownlevel));
1287 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1292 /****************************************************************************
1293 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1294 ****************************************************************************/
1295 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1296 int bufsize, int cnum, char **pparams,
1297 char **ppdata, int total_data)
1299 char *params = *pparams;
1300 char *pdata = *ppdata;
1301 uint16 tran_call = SVAL(inbuf, smb_setup0);
1310 BOOL bad_path = False;
1312 if (!CAN_WRITE(cnum))
1313 return(ERROR(ERRSRV,ERRaccess));
1315 if (tran_call == TRANSACT2_SETFILEINFO) {
1316 int16 fnum = SVALS(params,0);
1317 info_level = SVAL(params,2);
1319 CHECK_FNUM(fnum,cnum);
1322 fname = Files[fnum].name;
1323 fd = Files[fnum].fd_ptr->fd;
1325 if(fstat(fd,&st)!=0) {
1326 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1327 return(ERROR(ERRDOS,ERRbadpath));
1331 info_level = SVAL(params,0);
1333 pstrcpy(fname,¶ms[6]);
1334 unix_convert(fname,cnum,0,&bad_path);
1335 if(!check_name(fname, cnum))
1337 if((errno == ENOENT) && bad_path)
1339 unix_ERR_class = ERRDOS;
1340 unix_ERR_code = ERRbadpath;
1342 return(UNIXERROR(ERRDOS,ERRbadpath));
1345 if(sys_stat(fname,&st)!=0) {
1346 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1347 if((errno == ENOENT) && bad_path)
1349 unix_ERR_class = ERRDOS;
1350 unix_ERR_code = ERRbadpath;
1352 return(UNIXERROR(ERRDOS,ERRbadpath));
1356 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1357 tran_call,fname,info_level,total_data));
1359 /* Realloc the parameter and data sizes */
1360 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1362 return(ERROR(ERRDOS,ERRnomem));
1365 tvs.modtime = st.st_mtime;
1366 tvs.actime = st.st_atime;
1367 mode = dos_mode(cnum,fname,&st);
1369 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1370 /* uggh, EAs for OS2 */
1371 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1372 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1377 case SMB_INFO_STANDARD:
1378 case SMB_INFO_QUERY_EA_SIZE:
1381 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1384 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1386 mode = SVAL(pdata,l1_attrFile);
1387 size = IVAL(pdata,l1_cbFile);
1391 /* XXXX um, i don't think this is right.
1392 it's also not in the cifs6.txt spec.
1394 case SMB_INFO_QUERY_EAS_FROM_LIST:
1395 tvs.actime = make_unix_date2(pdata+8);
1396 tvs.modtime = make_unix_date2(pdata+12);
1397 size = IVAL(pdata,16);
1398 mode = IVAL(pdata,24);
1401 /* XXXX nor this. not in cifs6.txt, either. */
1402 case SMB_INFO_QUERY_ALL_EAS:
1403 tvs.actime = make_unix_date2(pdata+8);
1404 tvs.modtime = make_unix_date2(pdata+12);
1405 size = IVAL(pdata,16);
1406 mode = IVAL(pdata,24);
1409 case SMB_SET_FILE_BASIC_INFO:
1411 /* Ignore create time at offset pdata. */
1414 tvs.actime = interpret_long_date(pdata+8);
1416 /* write time + changed time, combined. */
1417 tvs.modtime=MAX(interpret_long_date(pdata+16),
1418 interpret_long_date(pdata+24));
1420 #if 0 /* Needs more testing... */
1421 /* Test from Luke to prevent Win95 from
1422 setting incorrect values here.
1424 if (tvs.actime < tvs.modtime)
1425 return(ERROR(ERRDOS,ERRnoaccess));
1426 #endif /* Needs more testing... */
1429 mode = IVAL(pdata,32);
1433 case SMB_SET_FILE_END_OF_FILE_INFO:
1435 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1436 return(ERROR(ERRDOS,ERRunknownlevel));
1437 size = IVAL(pdata,0);
1441 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1442 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1445 return(ERROR(ERRDOS,ERRunknownlevel));
1449 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1450 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1451 DEBUG(6,("size: %x " , size));
1452 DEBUG(6,("mode: %x\n" , mode));
1454 /* get some defaults (no modifications) if any info is zero. */
1455 if (!tvs.actime) tvs.actime = st.st_atime;
1456 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1457 if (!size) size = st.st_size;
1459 /* Try and set the times, size and mode of this file -
1460 if they are different from the current values
1462 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1464 if(file_utime(cnum, fname, &tvs)!=0)
1466 return(ERROR(ERRDOS,ERRnoaccess));
1470 /* check the mode isn't different, before changing it */
1471 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1473 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1474 return(ERROR(ERRDOS,ERRnoaccess));
1477 if(size != st.st_size)
1481 fd = sys_open(fname,O_RDWR,0);
1484 return(ERROR(ERRDOS,ERRbadpath));
1486 set_filelen(fd, size);
1491 set_filelen(fd, size);
1497 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1502 /****************************************************************************
1503 reply to a TRANS2_MKDIR (make directory with extended attributes).
1504 ****************************************************************************/
1505 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1506 int cnum, char **pparams, char **ppdata)
1508 char *params = *pparams;
1511 BOOL bad_path = False;
1513 if (!CAN_WRITE(cnum))
1514 return(ERROR(ERRSRV,ERRaccess));
1516 pstrcpy(directory, ¶ms[4]);
1518 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1520 unix_convert(directory,cnum,0,&bad_path);
1521 if (check_name(directory,cnum))
1522 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1526 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1527 if((errno == ENOENT) && bad_path)
1529 unix_ERR_class = ERRDOS;
1530 unix_ERR_code = ERRbadpath;
1532 return(UNIXERROR(ERRDOS,ERRnoaccess));
1535 /* Realloc the parameter and data sizes */
1536 params = *pparams = Realloc(*pparams,2);
1538 return(ERROR(ERRDOS,ERRnomem));
1542 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1547 /****************************************************************************
1548 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1549 We don't actually do this - we just send a null response.
1550 ****************************************************************************/
1551 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1552 int cnum, char **pparams, char **ppdata)
1554 static uint16 fnf_handle = 257;
1555 char *params = *pparams;
1556 uint16 info_level = SVAL(params,4);
1558 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1566 return(ERROR(ERRDOS,ERRunknownlevel));
1569 /* Realloc the parameter and data sizes */
1570 params = *pparams = Realloc(*pparams,6);
1572 return(ERROR(ERRDOS,ERRnomem));
1574 SSVAL(params,0,fnf_handle);
1575 SSVAL(params,2,0); /* No changes */
1576 SSVAL(params,4,0); /* No EA errors */
1583 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1588 /****************************************************************************
1589 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1590 changes). Currently this does nothing.
1591 ****************************************************************************/
1592 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1593 int cnum, char **pparams, char **ppdata)
1595 char *params = *pparams;
1597 DEBUG(3,("call_trans2findnotifynext\n"));
1599 /* Realloc the parameter and data sizes */
1600 params = *pparams = Realloc(*pparams,4);
1602 return(ERROR(ERRDOS,ERRnomem));
1604 SSVAL(params,0,0); /* No changes */
1605 SSVAL(params,2,0); /* No EA errors */
1607 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1612 /****************************************************************************
1613 reply to a SMBfindclose (stop trans2 directory search)
1614 ****************************************************************************/
1615 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1619 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1621 cnum = SVAL(inbuf,smb_tid);
1623 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1625 dptr_close(dptr_num);
1627 outsize = set_message(outbuf,0,0,True);
1629 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1634 /****************************************************************************
1635 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1636 ****************************************************************************/
1637 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1643 cnum = SVAL(inbuf,smb_tid);
1644 dptr_num = SVAL(inbuf,smb_vwv0);
1646 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1648 /* We never give out valid handles for a
1649 findnotifyfirst - so any dptr_num is ok here.
1652 outsize = set_message(outbuf,0,0,True);
1654 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1660 /****************************************************************************
1661 reply to a SMBtranss2 - just ignore it!
1662 ****************************************************************************/
1663 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1665 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1669 /****************************************************************************
1670 reply to a SMBtrans2
1671 ****************************************************************************/
1672 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1675 int cnum = SVAL(inbuf,smb_tid);
1676 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1677 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1679 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1680 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1681 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1682 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1683 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1684 int32 timeout = IVALS(inbuf,smb_timeout);
1686 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1687 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1688 char *params = NULL, *data = NULL;
1689 int num_params, num_params_sofar, num_data, num_data_sofar;
1691 outsize = set_message(outbuf,0,0,True);
1693 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1694 is so as a sanity check */
1697 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1698 return(ERROR(ERRSRV,ERRerror));
1701 /* Allocate the space for the maximum needed parameters and data */
1702 if (total_params > 0)
1703 params = (char *)malloc(total_params);
1705 data = (char *)malloc(total_data);
1707 if ((total_params && !params) || (total_data && !data))
1709 DEBUG(2,("Out of memory in reply_trans2\n"));
1710 return(ERROR(ERRDOS,ERRnomem));
1713 /* Copy the param and data bytes sent with this request into
1714 the params buffer */
1715 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1716 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1718 if (num_params > total_params || num_data > total_data)
1719 exit_server("invalid params in reply_trans2");
1721 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1722 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1724 if(num_data_sofar < total_data || num_params_sofar < total_params)
1726 /* We need to send an interim response then receive the rest
1727 of the parameter/data bytes */
1728 outsize = set_message(outbuf,0,0,True);
1729 send_smb(Client,outbuf);
1731 while( num_data_sofar < total_data || num_params_sofar < total_params)
1735 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1736 SMB_SECONDARY_WAIT);
1738 if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1740 outsize = set_message(outbuf,0,0,True);
1742 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1744 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1745 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1748 return(ERROR(ERRSRV,ERRerror));
1751 /* Revise total_params and total_data in case they have changed downwards */
1752 total_params = SVAL(inbuf, smb_tpscnt);
1753 total_data = SVAL(inbuf, smb_tdscnt);
1754 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1755 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1756 if (num_params_sofar > total_params || num_data_sofar > total_data)
1757 exit_server("data overflow in trans2");
1759 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
1760 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1761 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1762 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1766 if (Protocol >= PROTOCOL_NT1) {
1767 uint16 flg2 = SVAL(outbuf,smb_flg2);
1768 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1771 /* Now we must call the relevant TRANS2 function */
1774 case TRANSACT2_OPEN:
1775 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1777 case TRANSACT2_FINDFIRST:
1778 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
1780 case TRANSACT2_FINDNEXT:
1781 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1783 case TRANSACT2_QFSINFO:
1784 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1786 case TRANSACT2_SETFSINFO:
1787 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1789 case TRANSACT2_QPATHINFO:
1790 case TRANSACT2_QFILEINFO:
1791 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1793 case TRANSACT2_SETPATHINFO:
1794 case TRANSACT2_SETFILEINFO:
1795 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data);
1797 case TRANSACT2_FINDNOTIFYFIRST:
1798 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1800 case TRANSACT2_FINDNOTIFYNEXT:
1801 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1803 case TRANSACT2_MKDIR:
1804 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
1807 /* Error in request */
1808 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1813 return (ERROR(ERRSRV,ERRerror));
1816 /* As we do not know how many data packets will need to be
1817 returned here the various call_trans2xxxx calls
1818 must send their own. Thus a call_trans2xxx routine only
1819 returns a value other than -1 when it wants to send
1827 return outsize; /* If a correct response was needed the call_trans2xxx
1828 calls have already sent it. If outsize != -1 then it is
1829 returning an error packet. */