This commit was manufactured by cvs2svn to create tag
[Samba.git] / source / smbd / trans2.c
blob9b5419010e2d68a5a09089c4e8b07ff11df6feb0
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994
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.
24 #include "includes.h"
25 #include "trans2.h"
27 extern int DEBUGLEVEL;
28 extern int Protocol;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
32 extern int Client;
34 /****************************************************************************
35 Send the required number of replies back.
36 We assume all fields other than the data fields are
37 set correctly for the type of call.
38 HACK ! Always assumes smb_setup field is zero.
39 ****************************************************************************/
40 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
41 int paramsize, char *pdata, int datasize)
43 /* As we are using a protocol > LANMAN1 then the maxxmit
44 variable must have been set in the sessetupX call.
45 This takes precedence over the max_xmit field in the
46 global struct. These different max_xmit variables should
47 be merged as this is now too confusing */
49 extern int maxxmit;
50 int data_to_send = datasize;
51 int params_to_send = paramsize;
52 int useable_space;
53 char *pp = params;
54 char *pd = pdata;
55 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
56 int alignment_offset = 1;
58 /* Initially set the wcnt area to be 10 - this is true for all
59 trans2 replies */
60 set_message(outbuf,10,0,True);
62 /* If there genuinely are no parameters or data to send just send
63 the empty packet */
64 if(params_to_send == 0 && data_to_send == 0)
66 send_smb(Client,outbuf);
67 return 0;
70 /* Space is bufsize minus Netbios over TCP header minus SMB header */
71 /* The + 1 is to align the param and data bytes on an even byte
72 boundary. NT 4.0 Beta needs this to work correctly. */
73 useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf);
74 useable_space = MIN(useable_space, maxxmit); /* XXX is this needed? correct? */
76 while( params_to_send || data_to_send)
78 /* Calculate whether we will totally or partially fill this packet */
79 total_sent_thistime = params_to_send + data_to_send + alignment_offset;
80 total_sent_thistime = MIN(total_sent_thistime, useable_space);
82 set_message(outbuf, 10, total_sent_thistime, True);
84 /* Set total params and data to be sent */
85 SSVAL(outbuf,smb_tprcnt,paramsize);
86 SSVAL(outbuf,smb_tdrcnt,datasize);
88 /* Calculate how many parameters and data we can fit into
89 this packet. Parameters get precedence */
91 params_sent_thistime = MIN(params_to_send,useable_space);
92 data_sent_thistime = useable_space - params_sent_thistime;
93 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
95 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
96 if(params_sent_thistime == 0)
98 SSVAL(outbuf,smb_proff,0);
99 SSVAL(outbuf,smb_prdisp,0);
100 } else {
101 /* smb_proff is the offset from the start of the SMB header to the
102 parameter bytes, however the first 4 bytes of outbuf are
103 the Netbios over TCP header. Thus use smb_base() to subtract
104 them from the calculation */
105 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
106 /* Absolute displacement of param bytes sent in this packet */
107 SSVAL(outbuf,smb_prdisp,pp - params);
110 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
111 if(data_sent_thistime == 0)
113 SSVAL(outbuf,smb_droff,0);
114 SSVAL(outbuf,smb_drdisp, 0);
115 } else {
116 /* The offset of the data bytes is the offset of the
117 parameter bytes plus the number of parameters being sent this time */
118 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
119 smb_base(outbuf)) + params_sent_thistime);
120 SSVAL(outbuf,smb_drdisp, pd - pdata);
123 /* Copy the param bytes into the packet */
124 if(params_sent_thistime)
125 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
126 /* Copy in the data bytes */
127 if(data_sent_thistime)
128 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime);
130 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
131 params_sent_thistime, data_sent_thistime, useable_space));
132 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
133 params_to_send, data_to_send, paramsize, datasize));
135 /* Send the packet */
136 send_smb(Client,outbuf);
138 pp += params_sent_thistime;
139 pd += data_sent_thistime;
141 params_to_send -= params_sent_thistime;
142 data_to_send -= data_sent_thistime;
144 /* Sanity check */
145 if(params_to_send < 0 || data_to_send < 0)
147 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
148 params_to_send, data_to_send));
149 return -1;
153 return 0;
157 /****************************************************************************
158 reply to a TRANSACT2_OPEN
159 ****************************************************************************/
160 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
161 char **pparams, char **ppdata)
163 char *params = *pparams;
164 int16 open_mode = SVAL(params, 2);
165 int16 open_attr = SVAL(params,6);
166 #if 0
167 BOOL return_additional_info = BITSETW(params,0);
168 int16 open_sattr = SVAL(params, 4);
169 time_t open_time = make_unix_date3(params+8);
170 #endif
171 int16 open_ofun = SVAL(params,12);
172 int32 open_size = IVAL(params,14);
173 char *pname = &params[28];
174 int16 namelen = strlen(pname)+1;
176 pstring fname;
177 int fnum = -1;
178 int unixmode;
179 int size=0,fmode=0,mtime=0,rmode;
180 int32 inode = 0;
181 struct stat sbuf;
182 int smb_action = 0;
184 StrnCpy(fname,pname,namelen);
186 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
187 fname,cnum,open_mode, open_attr, open_ofun, open_size));
189 /* XXXX we need to handle passed times, sattr and flags */
191 unix_convert(fname,cnum);
193 fnum = find_free_file();
194 if (fnum < 0)
195 return(ERROR(ERRSRV,ERRnofids));
197 if (!check_name(fname,cnum))
198 return(UNIXERROR(ERRDOS,ERRnoaccess));
200 unixmode = unix_mode(cnum,open_attr | aARCH);
203 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
204 &rmode,&smb_action);
206 if (!Files[fnum].open)
207 return(UNIXERROR(ERRDOS,ERRnoaccess));
209 if (fstat(Files[fnum].fd,&sbuf) != 0) {
210 close_file(fnum);
211 return(ERROR(ERRDOS,ERRnoaccess));
214 size = sbuf.st_size;
215 fmode = dos_mode(cnum,fname,&sbuf);
216 mtime = sbuf.st_mtime;
217 inode = sbuf.st_ino;
218 if (fmode & aDIR) {
219 close_file(fnum);
220 return(ERROR(ERRDOS,ERRnoaccess));
223 /* Realloc the size of parameters and data we will return */
224 params = *pparams = Realloc(*pparams, 28);
225 if(params == NULL)
226 return(ERROR(ERRDOS,ERRnomem));
228 bzero(params,28);
229 SSVAL(params,0,fnum);
230 SSVAL(params,2,fmode);
231 put_dos_date2(params,4, mtime);
232 SIVAL(params,8, size);
233 SSVAL(params,12,rmode);
235 SSVAL(params,18,smb_action);
236 SIVAL(params,20,inode);
238 /* Send the required number of replies */
239 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
241 return -1;
244 /****************************************************************************
245 get a level dependent lanman2 dir entry.
246 ****************************************************************************/
247 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
248 int requires_resume_key,
249 BOOL dont_descend,char **ppdata,
250 char *base_data, int space_remaining,
251 BOOL *out_of_space,
252 int *last_name_off)
254 char *dname;
255 BOOL found = False;
256 struct stat sbuf;
257 pstring mask;
258 pstring pathreal;
259 pstring fname;
260 BOOL matched;
261 char *p, *pdata = *ppdata;
262 int reskey=0, prev_dirpos=0;
263 int mode=0;
264 uint32 size=0,len;
265 uint32 mdate=0, adate=0, cdate=0;
266 char *nameptr;
267 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
268 strequal(Connections[cnum].dirpath,".") ||
269 strequal(Connections[cnum].dirpath,"/"));
270 BOOL was_8_3;
272 *fname = 0;
273 *out_of_space = False;
275 if (!Connections[cnum].dirptr)
276 return(False);
278 p = strrchr(path_mask,'/');
279 if(p != NULL)
281 if(p[1] == '\0')
282 strcpy(mask,"*.*");
283 else
284 strcpy(mask, p+1);
286 else
287 strcpy(mask, path_mask);
289 while (!found)
291 /* Needed if we run out of space */
292 prev_dirpos = TellDir(Connections[cnum].dirptr);
293 dname = ReadDirName(Connections[cnum].dirptr);
295 reskey = TellDir(Connections[cnum].dirptr);
297 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
298 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
300 if (!dname)
301 return(False);
303 matched = False;
305 strcpy(fname,dname);
307 if(mask_match(fname, mask, case_sensitive, True))
309 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
310 if (dont_descend && !isdots)
311 continue;
313 if (isrootdir && isdots)
314 continue;
316 strcpy(pathreal,Connections[cnum].dirpath);
317 strcat(pathreal,"/");
318 strcat(pathreal,fname);
319 if (sys_stat(pathreal,&sbuf) != 0)
321 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
322 continue;
325 mode = dos_mode(cnum,pathreal,&sbuf);
327 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
328 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
329 continue;
332 size = sbuf.st_size;
333 mdate = sbuf.st_mtime;
334 adate = sbuf.st_atime;
335 cdate = sbuf.st_ctime;
336 if(mode & aDIR)
337 size = 0;
339 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
341 found = True;
346 #ifndef KANJI
347 unix2dos_format(fname, True);
348 #endif
350 p = pdata;
351 nameptr = p;
353 name_map_mangle(fname,False,SNUM(cnum));
355 switch (info_level)
357 case 1:
358 if(requires_resume_key) {
359 SIVAL(p,0,reskey);
360 p += 4;
362 put_dos_date2(p,l1_fdateCreation,cdate);
363 put_dos_date2(p,l1_fdateLastAccess,adate);
364 put_dos_date2(p,l1_fdateLastWrite,mdate);
365 SIVAL(p,l1_cbFile,size);
366 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
367 SSVAL(p,l1_attrFile,mode);
368 SCVAL(p,l1_cchName,strlen(fname));
369 strcpy(p + l1_achName, fname);
370 nameptr = p + l1_achName;
371 p += l1_achName + strlen(fname) + 1;
372 break;
374 case 2:
375 /* info_level 2 */
376 if(requires_resume_key) {
377 SIVAL(p,0,reskey);
378 p += 4;
380 put_dos_date2(p,l2_fdateCreation,cdate);
381 put_dos_date2(p,l2_fdateLastAccess,adate);
382 put_dos_date2(p,l2_fdateLastWrite,mdate);
383 SIVAL(p,l2_cbFile,size);
384 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
385 SSVAL(p,l2_attrFile,mode);
386 SIVAL(p,l2_cbList,0); /* No extended attributes */
387 SCVAL(p,l2_cchName,strlen(fname));
388 strcpy(p + l2_achName, fname);
389 nameptr = p + l2_achName;
390 p += l2_achName + strlen(fname) + 1;
391 break;
393 case 3:
394 SIVAL(p,0,reskey);
395 put_dos_date2(p,4,cdate);
396 put_dos_date2(p,8,adate);
397 put_dos_date2(p,12,mdate);
398 SIVAL(p,16,size);
399 SIVAL(p,20,ROUNDUP(size,1024));
400 SSVAL(p,24,mode);
401 SIVAL(p,26,4);
402 CVAL(p,30) = strlen(fname);
403 strcpy(p+31, fname);
404 nameptr = p+31;
405 p += 31 + strlen(fname) + 1;
406 break;
408 case 4:
409 if(requires_resume_key) {
410 SIVAL(p,0,reskey);
411 p += 4;
413 SIVAL(p,0,33+strlen(fname)+1);
414 put_dos_date2(p,4,cdate);
415 put_dos_date2(p,8,adate);
416 put_dos_date2(p,12,mdate);
417 SIVAL(p,16,size);
418 SIVAL(p,20,ROUNDUP(size,1024));
419 SSVAL(p,24,mode);
420 CVAL(p,32) = strlen(fname);
421 strcpy(p + 33, fname);
422 nameptr = p+33;
423 p += 33 + strlen(fname) + 1;
424 break;
426 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
427 was_8_3 = is_8_3(fname);
428 len = 94+strlen(fname);
429 len = (len + 3) & ~3;
430 SIVAL(p,0,len); p += 4;
431 SIVAL(p,0,reskey); p += 4;
432 put_long_date(p,cdate); p += 8;
433 put_long_date(p,adate); p += 8;
434 put_long_date(p,mdate); p += 8;
435 put_long_date(p,mdate); p += 8;
436 SIVAL(p,0,size); p += 8;
437 SIVAL(p,0,size); p += 8;
438 SIVAL(p,0,mode); p += 4;
439 SIVAL(p,0,strlen(fname)); p += 4;
440 SIVAL(p,0,0); p += 4;
441 if (!was_8_3) {
442 #ifndef KANJI
443 strcpy(p+2,unix2dos_format(fname,False));
444 #else
445 strcpy(p+2,fname);
446 #endif
447 if (!name_map_mangle(p+2,True,SNUM(cnum)))
448 (p+2)[12] = 0;
449 } else
450 *(p+2) = 0;
451 strupper(p+2);
452 SSVAL(p,0,strlen(p+2));
453 p += 2 + 24;
454 /* nameptr = p; */
455 strcpy(p,fname); p += strlen(p);
456 p = pdata + len;
457 break;
459 case SMB_FIND_FILE_DIRECTORY_INFO:
460 len = 64+strlen(fname);
461 len = (len + 3) & ~3;
462 SIVAL(p,0,len); p += 4;
463 SIVAL(p,0,reskey); p += 4;
464 put_long_date(p,cdate); p += 8;
465 put_long_date(p,adate); p += 8;
466 put_long_date(p,mdate); p += 8;
467 put_long_date(p,mdate); p += 8;
468 SIVAL(p,0,size); p += 8;
469 SIVAL(p,0,size); p += 8;
470 SIVAL(p,0,mode); p += 4;
471 SIVAL(p,0,strlen(fname)); p += 4;
472 strcpy(p,fname);
473 p = pdata + len;
474 break;
477 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
478 len = 68+strlen(fname);
479 len = (len + 3) & ~3;
480 SIVAL(p,0,len); p += 4;
481 SIVAL(p,0,reskey); p += 4;
482 put_long_date(p,cdate); p += 8;
483 put_long_date(p,adate); p += 8;
484 put_long_date(p,mdate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 SIVAL(p,0,size); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,mode); p += 4;
489 SIVAL(p,0,strlen(fname)); p += 4;
490 SIVAL(p,0,0); p += 4;
491 strcpy(p,fname);
492 p = pdata + len;
493 break;
495 case SMB_FIND_FILE_NAMES_INFO:
496 len = 12+strlen(fname);
497 len = (len + 3) & ~3;
498 SIVAL(p,0,len); p += 4;
499 SIVAL(p,0,reskey); p += 4;
500 SIVAL(p,0,strlen(fname)); p += 4;
501 strcpy(p,fname);
502 p = pdata + len;
503 break;
505 default:
506 return(False);
510 if (PTR_DIFF(p,pdata) > space_remaining) {
511 /* Move the dirptr back to prev_dirpos */
512 SeekDir(Connections[cnum].dirptr, prev_dirpos);
513 *out_of_space = True;
514 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
515 return False; /* Not finished - just out of space */
518 /* Setup the last_filename pointer, as an offset from base_data */
519 *last_name_off = PTR_DIFF(nameptr,base_data);
520 /* Advance the data pointer to the next slot */
521 *ppdata = p;
522 return(found);
525 /****************************************************************************
526 reply to a TRANS2_FINDFIRST
527 ****************************************************************************/
528 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
529 char **pparams, char **ppdata)
531 /* We must be careful here that we don't return more than the
532 allowed number of data bytes. If this means returning fewer than
533 maxentries then so be it. We assume that the redirector has
534 enough room for the fixed number of parameter bytes it has
535 requested. */
536 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
537 char *params = *pparams;
538 char *pdata = *ppdata;
539 int dirtype = SVAL(params,0);
540 int maxentries = SVAL(params,2);
541 BOOL close_after_first = BITSETW(params+4,0);
542 BOOL close_if_end = BITSETW(params+4,1);
543 BOOL requires_resume_key = BITSETW(params+4,2);
544 int info_level = SVAL(params,6);
545 pstring directory;
546 pstring mask;
547 char *p, *wcard;
548 int last_name_off=0;
549 int dptr_num = -1;
550 int numentries = 0;
551 int i;
552 BOOL finished = False;
553 BOOL dont_descend = False;
554 BOOL out_of_space = False;
555 int space_remaining;
557 *directory = *mask = 0;
559 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",
560 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
561 info_level, max_data_bytes));
563 switch (info_level)
565 case 1:
566 case 2:
567 case 3:
568 case 4:
569 case SMB_FIND_FILE_DIRECTORY_INFO:
570 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
571 case SMB_FIND_FILE_NAMES_INFO:
572 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
573 break;
574 default:
575 return(ERROR(ERRDOS,ERRunknownlevel));
578 strcpy(directory, params + 12); /* Complete directory path with
579 wildcard mask appended */
581 DEBUG(5,("path=%s\n",directory));
583 unix_convert(directory,cnum);
584 if(!check_name(directory,cnum)) {
585 return(ERROR(ERRDOS,ERRbadpath));
588 p = strrchr(directory,'/');
589 if(p == NULL) {
590 strcpy(mask,directory);
591 strcpy(directory,"./");
592 } else {
593 strcpy(mask,p+1);
594 *p = 0;
597 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
599 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
600 if(!*ppdata)
601 return(ERROR(ERRDOS,ERRnomem));
602 bzero(pdata,max_data_bytes);
604 /* Realloc the params space */
605 params = *pparams = Realloc(*pparams, 10);
606 if(params == NULL)
607 return(ERROR(ERRDOS,ERRnomem));
609 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
610 if (dptr_num < 0)
611 return(ERROR(ERRDOS,ERRbadpath));
613 /* convert the formatted masks */
615 p = mask;
616 while (*p) {
617 if (*p == '<') *p = '*';
618 if (*p == '>') *p = '?';
619 if (*p == '"') *p = '.';
620 p++;
624 /* a special case for 16 bit apps */
625 if (strequal(mask,"????????.???")) strcpy(mask,"*");
627 /* handle broken clients that send us old 8.3 format */
628 string_sub(mask,"????????","*");
629 string_sub(mask,".???",".*");
631 /* Save the wildcard match and attribs we are using on this directory -
632 needed as lanman2 assumes these are being saved between calls */
634 if(!(wcard = strdup(mask))) {
635 dptr_close(dptr_num);
636 return(ERROR(ERRDOS,ERRnomem));
639 dptr_set_wcard(dptr_num, wcard);
640 dptr_set_attr(dptr_num, dirtype);
642 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
644 /* We don't need to check for VOL here as this is returned by
645 a different TRANS2 call. */
647 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
648 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
649 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
650 dont_descend = True;
652 p = pdata;
653 space_remaining = max_data_bytes;
654 out_of_space = False;
656 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
659 /* this is a heuristic to avoid seeking the dirptr except when
660 absolutely necessary. It allows for a filename of about 40 chars */
661 if (space_remaining < DIRLEN_GUESS && numentries > 0)
663 out_of_space = True;
664 finished = False;
666 else
668 finished =
669 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
670 requires_resume_key,dont_descend,
671 &p,pdata,space_remaining, &out_of_space,
672 &last_name_off);
675 if (finished && out_of_space)
676 finished = False;
678 if (!finished && !out_of_space)
679 numentries++;
680 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
683 /* Check if we can close the dirptr */
684 if(close_after_first || (finished && close_if_end))
686 dptr_close(dptr_num);
687 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
688 dptr_num = -1;
691 /* At this point pdata points to numentries directory entries. */
693 /* Set up the return parameter block */
694 SSVAL(params,0,dptr_num);
695 SSVAL(params,2,numentries);
696 SSVAL(params,4,finished);
697 SSVAL(params,6,0); /* Never an EA error */
698 SSVAL(params,8,last_name_off);
700 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
702 if ((! *directory) && dptr_path(dptr_num))
703 sprintf(directory,"(%s)",dptr_path(dptr_num));
705 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
706 timestring(),
707 smb_fn_name(CVAL(inbuf,smb_com)),
708 mask,directory,cnum,dirtype,numentries));
710 return(-1);
714 /****************************************************************************
715 reply to a TRANS2_FINDNEXT
716 ****************************************************************************/
717 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
718 int cnum, char **pparams, char **ppdata)
720 /* We must be careful here that we don't return more than the
721 allowed number of data bytes. If this means returning fewer than
722 maxentries then so be it. We assume that the redirector has
723 enough room for the fixed number of parameter bytes it has
724 requested. */
725 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
726 char *params = *pparams;
727 char *pdata = *ppdata;
728 int16 dptr_num = SVAL(params,0);
729 int maxentries = SVAL(params,2);
730 uint16 info_level = SVAL(params,4);
731 uint32 resume_key = IVAL(params,6);
732 BOOL close_after_request = BITSETW(params+10,0);
733 BOOL close_if_end = BITSETW(params+10,1);
734 BOOL requires_resume_key = BITSETW(params+10,2);
735 BOOL continue_bit = BITSETW(params+10,3);
736 pstring mask;
737 pstring directory;
738 char *p;
739 uint16 dirtype;
740 int numentries = 0;
741 int i, last_name_off=0;
742 BOOL finished = False;
743 BOOL dont_descend = False;
744 BOOL out_of_space = False;
745 int space_remaining;
747 *mask = *directory = 0;
749 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",
750 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
751 requires_resume_key, resume_key, continue_bit, info_level));
753 switch (info_level)
755 case 1:
756 case 2:
757 case 3:
758 case 4:
759 case SMB_FIND_FILE_DIRECTORY_INFO:
760 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
761 case SMB_FIND_FILE_NAMES_INFO:
762 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
763 break;
764 default:
765 return(ERROR(ERRDOS,ERRunknownlevel));
768 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
769 if(!*ppdata)
770 return(ERROR(ERRDOS,ERRnomem));
771 bzero(pdata,max_data_bytes);
773 /* Realloc the params space */
774 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
775 if(!params)
776 return(ERROR(ERRDOS,ERRnomem));
778 /* Check that the dptr is valid */
779 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
780 return(ERROR(ERRDOS,ERRnofiles));
782 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
784 /* Get the wildcard mask from the dptr */
785 if((p = dptr_wcard(dptr_num))== NULL) {
786 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
787 return (ERROR(ERRDOS,ERRnofiles));
789 strcpy(mask, p);
790 strcpy(directory,Connections[cnum].dirpath);
792 /* Get the attr mask from the dptr */
793 dirtype = dptr_attr(dptr_num);
795 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
796 dptr_num, mask, dirtype,
797 Connections[cnum].dirptr,
798 TellDir(Connections[cnum].dirptr)));
800 /* We don't need to check for VOL here as this is returned by
801 a different TRANS2 call. */
803 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
804 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
805 dont_descend = True;
807 p = pdata;
808 space_remaining = max_data_bytes;
809 out_of_space = False;
811 /* If we have a resume key - seek to the correct position. */
812 if(requires_resume_key && !continue_bit)
813 SeekDir(Connections[cnum].dirptr, resume_key);
815 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
817 /* this is a heuristic to avoid seeking the dirptr except when
818 absolutely necessary. It allows for a filename of about 40 chars */
819 if (space_remaining < DIRLEN_GUESS && numentries > 0)
821 out_of_space = True;
822 finished = False;
824 else
826 finished =
827 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
828 requires_resume_key,dont_descend,
829 &p,pdata,space_remaining, &out_of_space,
830 &last_name_off);
833 if (finished && out_of_space)
834 finished = False;
836 if (!finished && !out_of_space)
837 numentries++;
838 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
841 /* Check if we can close the dirptr */
842 if(close_after_request || (finished && close_if_end))
844 dptr_close(dptr_num); /* This frees up the saved mask */
845 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
846 dptr_num = -1;
850 /* Set up the return parameter block */
851 SSVAL(params,0,numentries);
852 SSVAL(params,2,finished);
853 SSVAL(params,4,0); /* Never an EA error */
854 SSVAL(params,6,last_name_off);
856 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
858 if ((! *directory) && dptr_path(dptr_num))
859 sprintf(directory,"(%s)",dptr_path(dptr_num));
861 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
862 timestring(),
863 smb_fn_name(CVAL(inbuf,smb_com)),
864 mask,directory,cnum,dirtype,numentries));
866 return(-1);
869 /****************************************************************************
870 reply to a TRANS2_QFSINFO (query filesystem info)
871 ****************************************************************************/
872 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
873 int cnum, char **pparams, char **ppdata)
875 char *pdata = *ppdata;
876 char *params = *pparams;
877 uint16 info_level = SVAL(params,0);
878 int data_len;
879 struct stat st;
880 char *vname = volume_label(SNUM(cnum));
882 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
884 if(sys_stat(".",&st)!=0) {
885 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
886 return (ERROR(ERRSRV,ERRinvdevice));
889 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
891 switch (info_level)
893 case 1:
895 int dfree,dsize,bsize;
896 data_len = 18;
897 sys_disk_free(".",&bsize,&dfree,&dsize);
898 SIVAL(pdata,l1_idFileSystem,st.st_dev);
899 SIVAL(pdata,l1_cSectorUnit,bsize/512);
900 SIVAL(pdata,l1_cUnit,dsize);
901 SIVAL(pdata,l1_cUnitAvail,dfree);
902 SSVAL(pdata,l1_cbSector,512);
903 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
904 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
905 break;
907 case 2:
909 /* Return volume name */
910 int volname_len = MIN(strlen(vname),11);
911 data_len = l2_vol_szVolLabel + volname_len + 1;
912 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
913 SCVAL(pdata,l2_vol_cch,volname_len);
914 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
915 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
916 pdata+l2_vol_szVolLabel));
917 break;
919 case SMB_QUERY_FS_ATTRIBUTE_INFO:
920 data_len = 12 + 2*strlen(FSTYPE_STRING);
921 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
922 SIVAL(pdata,4,128); /* Max filename component length */
923 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
924 PutUniCode(pdata+12,FSTYPE_STRING);
925 break;
926 case SMB_QUERY_FS_LABEL_INFO:
927 data_len = 4 + strlen(vname);
928 SIVAL(pdata,0,strlen(vname));
929 strcpy(pdata+4,vname);
930 break;
931 case SMB_QUERY_FS_VOLUME_INFO:
932 data_len = 17 + strlen(vname);
933 SIVAL(pdata,12,strlen(vname));
934 strcpy(pdata+17,vname);
935 break;
936 case SMB_QUERY_FS_SIZE_INFO:
938 int dfree,dsize,bsize;
939 data_len = 24;
940 sys_disk_free(".",&bsize,&dfree,&dsize);
941 SIVAL(pdata,0,dsize);
942 SIVAL(pdata,8,dfree);
943 SIVAL(pdata,16,bsize/512);
944 SIVAL(pdata,20,512);
946 break;
947 case SMB_QUERY_FS_DEVICE_INFO:
948 data_len = 8;
949 SIVAL(pdata,0,0); /* dev type */
950 SIVAL(pdata,4,0); /* characteristics */
951 break;
952 default:
953 return(ERROR(ERRDOS,ERRunknownlevel));
957 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
959 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
961 return -1;
964 /****************************************************************************
965 reply to a TRANS2_SETFSINFO (set filesystem info)
966 ****************************************************************************/
967 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
968 int cnum, char **pparams, char **ppdata)
970 /* Just say yes we did it - there is nothing that
971 can be set here so it doesn't matter. */
972 int outsize;
973 DEBUG(3,("call_trans2setfsinfo\n"));
975 if (!CAN_WRITE(cnum))
976 return(ERROR(ERRSRV,ERRaccess));
978 outsize = set_message(outbuf,10,0,True);
980 return outsize;
983 /****************************************************************************
984 reply to a TRANS2_QFILEINFO (query file info by fileid)
985 ****************************************************************************/
986 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
987 int bufsize,int cnum,
988 char **pparams,char **ppdata,
989 int total_data)
991 char *params = *pparams;
992 char *pdata = *ppdata;
993 uint16 tran_call = SVAL(inbuf, smb_setup0);
994 uint16 info_level;
995 int mode=0;
996 int size=0;
997 unsigned int data_size;
998 struct stat sbuf;
999 pstring fname1;
1000 char *fname;
1001 char *p;
1002 int l,pos;
1005 if (tran_call == TRANSACT2_QFILEINFO) {
1006 int16 fnum = SVALS(params,0);
1007 info_level = SVAL(params,2);
1009 CHECK_FNUM(fnum,cnum);
1010 CHECK_ERROR(fnum);
1012 fname = Files[fnum].name;
1013 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1014 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1015 return(UNIXERROR(ERRDOS,ERRbadfid));
1017 pos = lseek(Files[fnum].fd,0,SEEK_CUR);
1018 } else {
1019 /* qpathinfo */
1020 info_level = SVAL(params,0);
1021 fname = &fname1[0];
1022 strcpy(fname,&params[6]);
1023 unix_convert(fname,cnum);
1024 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1025 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1026 return(UNIXERROR(ERRDOS,ERRbadpath));
1028 pos = 0;
1032 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1033 fname,info_level,tran_call,total_data));
1035 p = strrchr(fname,'/');
1036 if (!p)
1037 p = fname;
1038 else
1039 p++;
1040 l = strlen(p);
1041 mode = dos_mode(cnum,fname,&sbuf);
1042 size = sbuf.st_size;
1043 if (mode & aDIR) size = 0;
1045 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1046 data_size = 1024;
1047 pdata = *ppdata = Realloc(*ppdata, data_size);
1049 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1050 /* uggh, EAs for OS2 */
1051 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1052 #if 0
1053 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1054 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1055 return(-1);
1056 #else
1057 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1058 #endif
1061 bzero(pdata,data_size);
1063 switch (info_level)
1065 case 1:
1066 case 2:
1067 data_size = (info_level==1?22:26);
1068 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
1069 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1070 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
1071 SIVAL(pdata,l1_cbFile,size);
1072 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1073 SSVAL(pdata,l1_attrFile,mode);
1074 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1075 break;
1077 case 3:
1078 data_size = 24;
1079 put_dos_date2(pdata,0,sbuf.st_ctime);
1080 put_dos_date2(pdata,4,sbuf.st_atime);
1081 put_dos_date2(pdata,8,sbuf.st_mtime);
1082 SIVAL(pdata,12,size);
1083 SIVAL(pdata,16,ROUNDUP(size,1024));
1084 SIVAL(pdata,20,mode);
1085 break;
1087 case 4:
1088 data_size = 4;
1089 SIVAL(pdata,0,data_size);
1090 break;
1092 case 6:
1093 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1095 case SMB_QUERY_FILE_BASIC_INFO:
1096 data_size = 36;
1097 put_long_date(pdata,sbuf.st_ctime);
1098 put_long_date(pdata+8,sbuf.st_atime);
1099 put_long_date(pdata+16,sbuf.st_mtime);
1100 put_long_date(pdata+24,sbuf.st_mtime);
1101 SIVAL(pdata,32,mode);
1102 break;
1104 case SMB_QUERY_FILE_STANDARD_INFO:
1105 data_size = 22;
1106 SIVAL(pdata,0,size);
1107 SIVAL(pdata,8,size);
1108 SIVAL(pdata,16,sbuf.st_nlink);
1109 CVAL(pdata,20) = 0;
1110 CVAL(pdata,21) = (mode&aDIR)?1:0;
1111 break;
1113 case SMB_QUERY_FILE_EA_INFO:
1114 data_size = 4;
1115 break;
1117 case SMB_QUERY_FILE_NAME_INFO:
1118 case SMB_QUERY_FILE_ALT_NAME_INFO:
1119 data_size = 4 + l;
1120 SIVAL(pdata,0,l);
1121 strcpy(pdata+4,fname);
1122 break;
1123 case SMB_QUERY_FILE_ALLOCATION_INFO:
1124 case SMB_QUERY_FILE_END_OF_FILEINFO:
1125 data_size = 8;
1126 SIVAL(pdata,0,size);
1127 break;
1129 case SMB_QUERY_FILE_ALL_INFO:
1130 put_long_date(pdata,sbuf.st_ctime);
1131 put_long_date(pdata+8,sbuf.st_atime);
1132 put_long_date(pdata+16,sbuf.st_mtime);
1133 put_long_date(pdata+24,sbuf.st_mtime);
1134 SIVAL(pdata,32,mode);
1135 pdata += 40;
1136 SIVAL(pdata,0,size);
1137 SIVAL(pdata,8,size);
1138 SIVAL(pdata,16,sbuf.st_nlink);
1139 CVAL(pdata,20) = 0;
1140 CVAL(pdata,21) = (mode&aDIR)?1:0;
1141 pdata += 24;
1142 pdata += 8; /* index number */
1143 pdata += 4; /* EA info */
1144 if (mode & aRONLY)
1145 SIVAL(pdata,0,0xA9);
1146 else
1147 SIVAL(pdata,0,0xd01BF);
1148 pdata += 4;
1149 SIVAL(pdata,0,pos); /* current offset */
1150 pdata += 8;
1151 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1152 pdata += 4;
1153 pdata += 4; /* alignment */
1154 SIVAL(pdata,0,l);
1155 strcpy(pdata+4,fname);
1156 pdata += 4 + l;
1157 data_size = PTR_DIFF(pdata,(*ppdata));
1158 break;
1160 case SMB_QUERY_FILE_STREAM_INFO:
1161 data_size = 24 + l;
1162 SIVAL(pdata,0,pos);
1163 SIVAL(pdata,4,size);
1164 SIVAL(pdata,12,size);
1165 SIVAL(pdata,20,l);
1166 strcpy(pdata+24,fname);
1167 break;
1168 default:
1169 return(ERROR(ERRDOS,ERRunknownlevel));
1172 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1174 return(-1);
1177 /****************************************************************************
1178 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1179 ****************************************************************************/
1180 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1181 int bufsize, int cnum, char **pparams,
1182 char **ppdata, int total_data)
1184 char *params = *pparams;
1185 char *pdata = *ppdata;
1186 uint16 tran_call = SVAL(inbuf, smb_setup0);
1187 uint16 info_level;
1188 int mode=0;
1189 int size=0;
1190 struct utimbuf tvs;
1191 struct stat st;
1192 pstring fname1;
1193 char *fname;
1194 int fd = -1;
1196 if (!CAN_WRITE(cnum))
1197 return(ERROR(ERRSRV,ERRaccess));
1199 if (tran_call == TRANSACT2_SETFILEINFO) {
1200 int16 fnum = SVALS(params,0);
1201 info_level = SVAL(params,2);
1203 CHECK_FNUM(fnum,cnum);
1204 CHECK_ERROR(fnum);
1206 fname = Files[fnum].name;
1207 fd = Files[fnum].fd;
1209 if(fstat(fd,&st)!=0) {
1210 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1211 return(ERROR(ERRDOS,ERRbadpath));
1213 } else {
1214 /* set path info */
1215 info_level = SVAL(params,0);
1216 fname = fname1;
1217 strcpy(fname,&params[6]);
1218 unix_convert(fname,cnum);
1219 if(!check_name(fname, cnum))
1220 return(ERROR(ERRDOS,ERRbadpath));
1222 if(sys_stat(fname,&st)!=0) {
1223 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1224 return(ERROR(ERRDOS,ERRbadpath));
1228 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1229 tran_call,fname,info_level,total_data));
1231 /* Realloc the parameter and data sizes */
1232 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1233 if(params == NULL)
1234 return(ERROR(ERRDOS,ERRnomem));
1236 size = st.st_size;
1237 tvs.modtime = st.st_mtime;
1238 tvs.actime = st.st_atime;
1239 mode = dos_mode(cnum,fname,&st);
1241 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1242 /* uggh, EAs for OS2 */
1243 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1244 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1246 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1248 return(-1);
1251 switch (info_level)
1253 case 1:
1254 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1255 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1256 mode = SVAL(pdata,l1_attrFile);
1257 size = IVAL(pdata,l1_cbFile);
1258 break;
1260 case 2:
1261 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1262 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1263 mode = SVAL(pdata,l1_attrFile);
1264 size = IVAL(pdata,l1_cbFile);
1265 break;
1267 case 3:
1268 tvs.actime = make_unix_date2(pdata+8);
1269 tvs.modtime = make_unix_date2(pdata+12);
1270 size = IVAL(pdata,16);
1271 mode = IVAL(pdata,24);
1272 break;
1274 case 4:
1275 tvs.actime = make_unix_date2(pdata+8);
1276 tvs.modtime = make_unix_date2(pdata+12);
1277 size = IVAL(pdata,16);
1278 mode = IVAL(pdata,24);
1279 break;
1281 case SMB_SET_FILE_BASIC_INFO:
1282 pdata += 8; /* create time */
1283 tvs.actime = interpret_long_date(pdata); pdata += 8;
1284 tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8));
1285 pdata += 16;
1286 mode = IVAL(pdata,0);
1287 break;
1289 case SMB_SET_FILE_END_OF_FILE_INFO:
1290 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1291 return(ERROR(ERRDOS,ERRunknownlevel));
1292 size = IVAL(pdata,0);
1293 break;
1295 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1296 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1297 default:
1298 return(ERROR(ERRDOS,ERRunknownlevel));
1302 if (!tvs.actime) tvs.actime = st.st_atime;
1303 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1304 if (!size) size = st.st_size;
1306 /* Try and set the times, size and mode of this file - if they are different
1307 from the current values */
1308 if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
1309 if(sys_utime(fname, &tvs)!=0)
1310 return(ERROR(ERRDOS,ERRnoaccess));
1312 if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) {
1313 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1314 return(ERROR(ERRDOS,ERRnoaccess));
1316 if(size != st.st_size) {
1317 if (fd == -1) {
1318 fd = sys_open(fname,O_RDWR,0);
1319 if (fd == -1)
1320 return(ERROR(ERRDOS,ERRbadpath));
1321 set_filelen(fd, size);
1322 close(fd);
1323 } else {
1324 set_filelen(fd, size);
1328 SSVAL(params,0,0);
1330 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1332 return(-1);
1335 /****************************************************************************
1336 reply to a TRANS2_MKDIR (make directory with extended attributes).
1337 ****************************************************************************/
1338 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1339 int cnum, char **pparams, char **ppdata)
1341 char *params = *pparams;
1342 pstring directory;
1343 int ret = -1;
1345 if (!CAN_WRITE(cnum))
1346 return(ERROR(ERRSRV,ERRaccess));
1348 strcpy(directory, &params[4]);
1350 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1352 unix_convert(directory,cnum);
1353 if (check_name(directory,cnum))
1354 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1356 if(ret < 0)
1358 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1359 return(UNIXERROR(ERRDOS,ERRnoaccess));
1362 /* Realloc the parameter and data sizes */
1363 params = *pparams = Realloc(*pparams,2);
1364 if(params == NULL)
1365 return(ERROR(ERRDOS,ERRnomem));
1367 SSVAL(params,0,0);
1369 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1371 return(-1);
1374 /****************************************************************************
1375 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1376 We don't actually do this - we just send a null response.
1377 ****************************************************************************/
1378 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1379 int cnum, char **pparams, char **ppdata)
1381 static uint16 fnf_handle = 257;
1382 char *params = *pparams;
1383 uint16 info_level = SVAL(params,4);
1385 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1387 switch (info_level)
1389 case 1:
1390 case 2:
1391 break;
1392 default:
1393 return(ERROR(ERRDOS,ERRunknownlevel));
1396 /* Realloc the parameter and data sizes */
1397 params = *pparams = Realloc(*pparams,6);
1398 if(params == NULL)
1399 return(ERROR(ERRDOS,ERRnomem));
1401 SSVAL(params,0,fnf_handle);
1402 SSVAL(params,2,0); /* No changes */
1403 SSVAL(params,4,0); /* No EA errors */
1405 fnf_handle++;
1407 if(fnf_handle == 0)
1408 fnf_handle = 257;
1410 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1412 return(-1);
1415 /****************************************************************************
1416 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1417 changes). Currently this does nothing.
1418 ****************************************************************************/
1419 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1420 int cnum, char **pparams, char **ppdata)
1422 char *params = *pparams;
1424 DEBUG(3,("call_trans2findnotifynext\n"));
1426 /* Realloc the parameter and data sizes */
1427 params = *pparams = Realloc(*pparams,4);
1428 if(params == NULL)
1429 return(ERROR(ERRDOS,ERRnomem));
1431 SSVAL(params,0,0); /* No changes */
1432 SSVAL(params,2,0); /* No EA errors */
1434 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1436 return(-1);
1439 /****************************************************************************
1440 reply to a SMBfindclose (stop trans2 directory search)
1441 ****************************************************************************/
1442 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1444 int cnum;
1445 int outsize = 0;
1446 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1448 cnum = SVAL(inbuf,smb_tid);
1450 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1452 dptr_close(dptr_num);
1454 outsize = set_message(outbuf,0,0,True);
1456 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1458 return(outsize);
1461 /****************************************************************************
1462 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1463 ****************************************************************************/
1464 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1466 int cnum;
1467 int outsize = 0;
1468 int dptr_num= -1;
1470 cnum = SVAL(inbuf,smb_tid);
1471 dptr_num = SVAL(inbuf,smb_vwv0);
1473 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1475 /* We never give out valid handles for a
1476 findnotifyfirst - so any dptr_num is ok here.
1477 Just ignore it. */
1479 outsize = set_message(outbuf,0,0,True);
1481 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1483 return(outsize);
1487 /****************************************************************************
1488 reply to a SMBtranss2 - just ignore it!
1489 ****************************************************************************/
1490 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1492 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1493 return(-1);
1496 /****************************************************************************
1497 reply to a SMBtrans2
1498 ****************************************************************************/
1499 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1501 int outsize = 0;
1502 int cnum = SVAL(inbuf,smb_tid);
1503 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1504 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1505 #if 0
1506 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1507 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1508 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1509 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1510 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1511 int32 timeout = IVALS(inbuf,smb_timeout);
1512 #endif
1513 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1514 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1515 char *params = NULL, *data = NULL;
1516 int num_params, num_params_sofar, num_data, num_data_sofar;
1518 outsize = set_message(outbuf,0,0,True);
1520 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1521 is so as a sanity check */
1522 if(suwcnt != 1 )
1524 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1525 return(ERROR(ERRSRV,ERRerror));
1528 /* Allocate the space for the maximum needed parameters and data */
1529 if (total_params > 0)
1530 params = (char *)malloc(total_params);
1531 if (total_data > 0)
1532 data = (char *)malloc(total_data);
1534 if ((total_params && !params) || (total_data && !data))
1536 DEBUG(2,("Out of memory in reply_trans2\n"));
1537 return(ERROR(ERRDOS,ERRnomem));
1540 /* Copy the param and data bytes sent with this request into
1541 the params buffer */
1542 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1543 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1545 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1546 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1548 if(num_data_sofar < total_data || num_params_sofar < total_params)
1550 /* We need to send an interim response then receive the rest
1551 of the parameter/data bytes */
1552 outsize = set_message(outbuf,0,0,True);
1553 send_smb(Client,outbuf);
1555 while( num_data_sofar < total_data || num_params_sofar < total_params)
1557 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1558 CVAL(inbuf, smb_com) != SMBtranss2)
1560 outsize = set_message(outbuf,0,0,True);
1561 DEBUG(2,("Invalid secondary trans2 packet\n"));
1562 free(params);
1563 free(data);
1564 return(ERROR(ERRSRV,ERRerror));
1567 /* Revise total_params and total_data in case they have changed downwards */
1568 total_params = SVAL(inbuf, smb_tpscnt);
1569 total_data = SVAL(inbuf, smb_tdscnt);
1570 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1571 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1572 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1573 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1574 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1575 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1579 if (Protocol >= PROTOCOL_NT1) {
1580 uint16 flg2 = SVAL(outbuf,smb_flg2);
1581 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1584 /* Now we must call the relevant TRANS2 function */
1585 switch(tran_call)
1587 case TRANSACT2_OPEN:
1588 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1589 break;
1590 case TRANSACT2_FINDFIRST:
1591 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1592 break;
1593 case TRANSACT2_FINDNEXT:
1594 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1595 break;
1596 case TRANSACT2_QFSINFO:
1597 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1598 break;
1599 case TRANSACT2_SETFSINFO:
1600 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1601 break;
1602 case TRANSACT2_QPATHINFO:
1603 case TRANSACT2_QFILEINFO:
1604 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1605 break;
1606 case TRANSACT2_SETPATHINFO:
1607 case TRANSACT2_SETFILEINFO:
1608 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1609 break;
1610 case TRANSACT2_FINDNOTIFYFIRST:
1611 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1612 break;
1613 case TRANSACT2_FINDNOTIFYNEXT:
1614 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1615 break;
1616 case TRANSACT2_MKDIR:
1617 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1618 break;
1619 default:
1620 /* Error in request */
1621 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1622 if(params)
1623 free(params);
1624 if(data)
1625 free(data);
1626 return (ERROR(ERRSRV,ERRerror));
1629 /* As we do not know how many data packets will need to be
1630 returned here the various call_trans2xxxx calls
1631 must send their own. Thus a call_trans2xxx routine only
1632 returns a value other than -1 when it wants to send
1633 an error packet.
1636 if(params)
1637 free(params);
1638 if(data)
1639 free(data);
1640 return outsize; /* If a correct response was needed the call_trans2xxx
1641 calls have already sent it. If outsize != -1 then it is
1642 returning an error packet. */