This commit was manufactured by cvs2svn to create tag
[Samba/gbeck.git] / source / smbd / trans2.c
blob94c4f26359eb333323eba114b983cc0c5e325cb9
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 alignment_offset 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 can never be more than maxxmit minus the
75 alignment offset. */
76 useable_space = MIN(useable_space, maxxmit - alignment_offset);
78 while( params_to_send || data_to_send)
80 /* Calculate whether we will totally or partially fill this packet */
81 total_sent_thistime = params_to_send + data_to_send + alignment_offset;
82 /* We can never send more than maxxmit */
83 total_sent_thistime = MIN(total_sent_thistime, maxxmit);
85 set_message(outbuf, 10, total_sent_thistime, True);
87 /* Set total params and data to be sent */
88 SSVAL(outbuf,smb_tprcnt,paramsize);
89 SSVAL(outbuf,smb_tdrcnt,datasize);
91 /* Calculate how many parameters and data we can fit into
92 this packet. Parameters get precedence */
94 params_sent_thistime = MIN(params_to_send,useable_space);
95 data_sent_thistime = useable_space - params_sent_thistime;
96 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
98 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
99 if(params_sent_thistime == 0)
101 SSVAL(outbuf,smb_proff,0);
102 SSVAL(outbuf,smb_prdisp,0);
103 } else {
104 /* smb_proff is the offset from the start of the SMB header to the
105 parameter bytes, however the first 4 bytes of outbuf are
106 the Netbios over TCP header. Thus use smb_base() to subtract
107 them from the calculation */
108 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
109 /* Absolute displacement of param bytes sent in this packet */
110 SSVAL(outbuf,smb_prdisp,pp - params);
113 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
114 if(data_sent_thistime == 0)
116 SSVAL(outbuf,smb_droff,0);
117 SSVAL(outbuf,smb_drdisp, 0);
118 } else {
119 /* The offset of the data bytes is the offset of the
120 parameter bytes plus the number of parameters being sent this time */
121 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
122 smb_base(outbuf)) + params_sent_thistime);
123 SSVAL(outbuf,smb_drdisp, pd - pdata);
126 /* Copy the param bytes into the packet */
127 if(params_sent_thistime)
128 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
129 /* Copy in the data bytes */
130 if(data_sent_thistime)
131 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime);
133 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
134 params_sent_thistime, data_sent_thistime, useable_space));
135 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
136 params_to_send, data_to_send, paramsize, datasize));
138 /* Send the packet */
139 send_smb(Client,outbuf);
141 pp += params_sent_thistime;
142 pd += data_sent_thistime;
144 params_to_send -= params_sent_thistime;
145 data_to_send -= data_sent_thistime;
147 /* Sanity check */
148 if(params_to_send < 0 || data_to_send < 0)
150 DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
151 params_to_send, data_to_send));
152 return -1;
156 return 0;
160 /****************************************************************************
161 reply to a TRANSACT2_OPEN
162 ****************************************************************************/
163 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
164 char **pparams, char **ppdata)
166 char *params = *pparams;
167 int16 open_mode = SVAL(params, 2);
168 int16 open_attr = SVAL(params,6);
169 BOOL oplock_request = BITSETW(params,1);
170 #if 0
171 BOOL return_additional_info = BITSETW(params,0);
172 int16 open_sattr = SVAL(params, 4);
173 time_t open_time = make_unix_date3(params+8);
174 #endif
175 int16 open_ofun = SVAL(params,12);
176 int32 open_size = IVAL(params,14);
177 char *pname = &params[28];
178 int16 namelen = strlen(pname)+1;
180 pstring fname;
181 int fnum = -1;
182 int unixmode;
183 int size=0,fmode=0,mtime=0,rmode;
184 int32 inode = 0;
185 struct stat sbuf;
186 int smb_action = 0;
188 StrnCpy(fname,pname,namelen);
190 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
191 fname,cnum,open_mode, open_attr, open_ofun, open_size));
193 /* XXXX we need to handle passed times, sattr and flags */
195 unix_convert(fname,cnum,0);
197 fnum = find_free_file();
198 if (fnum < 0)
199 return(ERROR(ERRSRV,ERRnofids));
201 if (!check_name(fname,cnum))
202 return(UNIXERROR(ERRDOS,ERRnoaccess));
204 unixmode = unix_mode(cnum,open_attr | aARCH);
207 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
208 &rmode,&smb_action);
210 if (!Files[fnum].open)
211 return(UNIXERROR(ERRDOS,ERRnoaccess));
213 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
214 close_file(fnum);
215 return(ERROR(ERRDOS,ERRnoaccess));
218 size = sbuf.st_size;
219 fmode = dos_mode(cnum,fname,&sbuf);
220 mtime = sbuf.st_mtime;
221 inode = sbuf.st_ino;
222 if (fmode & aDIR) {
223 close_file(fnum);
224 return(ERROR(ERRDOS,ERRnoaccess));
227 /* Realloc the size of parameters and data we will return */
228 params = *pparams = Realloc(*pparams, 28);
229 if(params == NULL)
230 return(ERROR(ERRDOS,ERRnomem));
232 bzero(params,28);
233 SSVAL(params,0,fnum);
234 SSVAL(params,2,fmode);
235 put_dos_date2(params,4, mtime);
236 SIVAL(params,8, size);
237 SSVAL(params,12,rmode);
239 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
240 smb_action |= (1<<15);
243 SSVAL(params,18,smb_action);
244 SIVAL(params,20,inode);
246 /* Send the required number of replies */
247 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
249 return -1;
252 /****************************************************************************
253 get a level dependent lanman2 dir entry.
254 ****************************************************************************/
255 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
256 int requires_resume_key,
257 BOOL dont_descend,char **ppdata,
258 char *base_data, int space_remaining,
259 BOOL *out_of_space,
260 int *last_name_off)
262 char *dname;
263 BOOL found = False;
264 struct stat sbuf;
265 pstring mask;
266 pstring pathreal;
267 pstring fname;
268 BOOL matched;
269 char *p, *pdata = *ppdata;
270 int reskey=0, prev_dirpos=0;
271 int mode=0;
272 uint32 size=0,len;
273 uint32 mdate=0, adate=0, cdate=0;
274 char *nameptr;
275 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
276 strequal(Connections[cnum].dirpath,".") ||
277 strequal(Connections[cnum].dirpath,"/"));
278 BOOL was_8_3;
280 *fname = 0;
281 *out_of_space = False;
283 if (!Connections[cnum].dirptr)
284 return(False);
286 p = strrchr(path_mask,'/');
287 if(p != NULL)
289 if(p[1] == '\0')
290 strcpy(mask,"*.*");
291 else
292 strcpy(mask, p+1);
294 else
295 strcpy(mask, path_mask);
297 while (!found)
299 /* Needed if we run out of space */
300 prev_dirpos = TellDir(Connections[cnum].dirptr);
301 dname = ReadDirName(Connections[cnum].dirptr);
303 reskey = TellDir(Connections[cnum].dirptr);
305 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
306 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
308 if (!dname)
309 return(False);
311 matched = False;
313 strcpy(fname,dname);
315 if(mask_match(fname, mask, case_sensitive, True))
317 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
318 if (dont_descend && !isdots)
319 continue;
321 if (isrootdir && isdots)
322 continue;
324 strcpy(pathreal,Connections[cnum].dirpath);
325 strcat(pathreal,"/");
326 strcat(pathreal,fname);
327 if (sys_stat(pathreal,&sbuf) != 0)
329 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
330 continue;
333 mode = dos_mode(cnum,pathreal,&sbuf);
335 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
336 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
337 continue;
340 size = sbuf.st_size;
341 mdate = sbuf.st_mtime;
342 adate = sbuf.st_atime;
343 cdate = sbuf.st_ctime;
344 if(mode & aDIR)
345 size = 0;
347 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
349 found = True;
355 p = pdata;
356 nameptr = p;
358 name_map_mangle(fname,False,SNUM(cnum));
360 switch (info_level)
362 case 1:
363 if(requires_resume_key) {
364 SIVAL(p,0,reskey);
365 p += 4;
367 put_dos_date2(p,l1_fdateCreation,cdate);
368 put_dos_date2(p,l1_fdateLastAccess,adate);
369 put_dos_date2(p,l1_fdateLastWrite,mdate);
370 SIVAL(p,l1_cbFile,size);
371 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
372 SSVAL(p,l1_attrFile,mode);
373 SCVAL(p,l1_cchName,strlen(fname));
374 strcpy(p + l1_achName, fname);
375 nameptr = p + l1_achName;
376 p += l1_achName + strlen(fname) + 1;
377 break;
379 case 2:
380 /* info_level 2 */
381 if(requires_resume_key) {
382 SIVAL(p,0,reskey);
383 p += 4;
385 put_dos_date2(p,l2_fdateCreation,cdate);
386 put_dos_date2(p,l2_fdateLastAccess,adate);
387 put_dos_date2(p,l2_fdateLastWrite,mdate);
388 SIVAL(p,l2_cbFile,size);
389 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
390 SSVAL(p,l2_attrFile,mode);
391 SIVAL(p,l2_cbList,0); /* No extended attributes */
392 SCVAL(p,l2_cchName,strlen(fname));
393 strcpy(p + l2_achName, fname);
394 nameptr = p + l2_achName;
395 p += l2_achName + strlen(fname) + 1;
396 break;
398 case 3:
399 SIVAL(p,0,reskey);
400 put_dos_date2(p,4,cdate);
401 put_dos_date2(p,8,adate);
402 put_dos_date2(p,12,mdate);
403 SIVAL(p,16,size);
404 SIVAL(p,20,ROUNDUP(size,1024));
405 SSVAL(p,24,mode);
406 SIVAL(p,26,4);
407 CVAL(p,30) = strlen(fname);
408 strcpy(p+31, fname);
409 nameptr = p+31;
410 p += 31 + strlen(fname) + 1;
411 break;
413 case 4:
414 if(requires_resume_key) {
415 SIVAL(p,0,reskey);
416 p += 4;
418 SIVAL(p,0,33+strlen(fname)+1);
419 put_dos_date2(p,4,cdate);
420 put_dos_date2(p,8,adate);
421 put_dos_date2(p,12,mdate);
422 SIVAL(p,16,size);
423 SIVAL(p,20,ROUNDUP(size,1024));
424 SSVAL(p,24,mode);
425 CVAL(p,32) = strlen(fname);
426 strcpy(p + 33, fname);
427 nameptr = p+33;
428 p += 33 + strlen(fname) + 1;
429 break;
431 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
432 was_8_3 = is_8_3(fname);
433 len = 94+strlen(fname);
434 len = (len + 3) & ~3;
435 SIVAL(p,0,len); p += 4;
436 SIVAL(p,0,reskey); p += 4;
437 put_long_date(p,cdate); p += 8;
438 put_long_date(p,adate); p += 8;
439 put_long_date(p,mdate); p += 8;
440 put_long_date(p,mdate); p += 8;
441 SIVAL(p,0,size); p += 8;
442 SIVAL(p,0,size); p += 8;
443 SIVAL(p,0,mode); p += 4;
444 SIVAL(p,0,strlen(fname)); p += 4;
445 SIVAL(p,0,0); p += 4;
446 if (!was_8_3) {
447 strcpy(p+2,fname);
448 if (!name_map_mangle(p+2,True,SNUM(cnum)))
449 (p+2)[12] = 0;
450 } else
451 *(p+2) = 0;
452 strupper(p+2);
453 SSVAL(p,0,strlen(p+2));
454 p += 2 + 24;
455 /* nameptr = p; */
456 strcpy(p,fname); p += strlen(p);
457 p = pdata + len;
458 break;
460 case SMB_FIND_FILE_DIRECTORY_INFO:
461 len = 64+strlen(fname);
462 len = (len + 3) & ~3;
463 SIVAL(p,0,len); p += 4;
464 SIVAL(p,0,reskey); p += 4;
465 put_long_date(p,cdate); p += 8;
466 put_long_date(p,adate); p += 8;
467 put_long_date(p,mdate); p += 8;
468 put_long_date(p,mdate); p += 8;
469 SIVAL(p,0,size); p += 8;
470 SIVAL(p,0,size); p += 8;
471 SIVAL(p,0,mode); p += 4;
472 SIVAL(p,0,strlen(fname)); p += 4;
473 strcpy(p,fname);
474 p = pdata + len;
475 break;
478 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
479 len = 68+strlen(fname);
480 len = (len + 3) & ~3;
481 SIVAL(p,0,len); p += 4;
482 SIVAL(p,0,reskey); p += 4;
483 put_long_date(p,cdate); p += 8;
484 put_long_date(p,adate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 put_long_date(p,mdate); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,size); p += 8;
489 SIVAL(p,0,mode); p += 4;
490 SIVAL(p,0,strlen(fname)); p += 4;
491 SIVAL(p,0,0); p += 4;
492 strcpy(p,fname);
493 p = pdata + len;
494 break;
496 case SMB_FIND_FILE_NAMES_INFO:
497 len = 12+strlen(fname);
498 len = (len + 3) & ~3;
499 SIVAL(p,0,len); p += 4;
500 SIVAL(p,0,reskey); p += 4;
501 SIVAL(p,0,strlen(fname)); p += 4;
502 strcpy(p,fname);
503 p = pdata + len;
504 break;
506 default:
507 return(False);
511 if (PTR_DIFF(p,pdata) > space_remaining) {
512 /* Move the dirptr back to prev_dirpos */
513 SeekDir(Connections[cnum].dirptr, prev_dirpos);
514 *out_of_space = True;
515 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
516 return False; /* Not finished - just out of space */
519 /* Setup the last_filename pointer, as an offset from base_data */
520 *last_name_off = PTR_DIFF(nameptr,base_data);
521 /* Advance the data pointer to the next slot */
522 *ppdata = p;
523 return(found);
526 /****************************************************************************
527 reply to a TRANS2_FINDFIRST
528 ****************************************************************************/
529 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
530 char **pparams, char **ppdata)
532 /* We must be careful here that we don't return more than the
533 allowed number of data bytes. If this means returning fewer than
534 maxentries then so be it. We assume that the redirector has
535 enough room for the fixed number of parameter bytes it has
536 requested. */
537 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
538 char *params = *pparams;
539 char *pdata = *ppdata;
540 int dirtype = SVAL(params,0);
541 int maxentries = SVAL(params,2);
542 BOOL close_after_first = BITSETW(params+4,0);
543 BOOL close_if_end = BITSETW(params+4,1);
544 BOOL requires_resume_key = BITSETW(params+4,2);
545 int info_level = SVAL(params,6);
546 pstring directory;
547 pstring mask;
548 char *p, *wcard;
549 int last_name_off=0;
550 int dptr_num = -1;
551 int numentries = 0;
552 int i;
553 BOOL finished = False;
554 BOOL dont_descend = False;
555 BOOL out_of_space = False;
556 int space_remaining;
558 *directory = *mask = 0;
560 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",
561 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
562 info_level, max_data_bytes));
564 switch (info_level)
566 case 1:
567 case 2:
568 case 3:
569 case 4:
570 case SMB_FIND_FILE_DIRECTORY_INFO:
571 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
572 case SMB_FIND_FILE_NAMES_INFO:
573 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
574 break;
575 default:
576 return(ERROR(ERRDOS,ERRunknownlevel));
579 strcpy(directory, params + 12); /* Complete directory path with
580 wildcard mask appended */
582 DEBUG(5,("path=%s\n",directory));
584 unix_convert(directory,cnum,0);
585 if(!check_name(directory,cnum)) {
586 return(ERROR(ERRDOS,ERRbadpath));
589 p = strrchr(directory,'/');
590 if(p == NULL) {
591 strcpy(mask,directory);
592 strcpy(directory,"./");
593 } else {
594 strcpy(mask,p+1);
595 *p = 0;
598 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
600 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
601 if(!*ppdata)
602 return(ERROR(ERRDOS,ERRnomem));
603 bzero(pdata,max_data_bytes);
605 /* Realloc the params space */
606 params = *pparams = Realloc(*pparams, 10);
607 if(params == NULL)
608 return(ERROR(ERRDOS,ERRnomem));
610 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
611 if (dptr_num < 0)
612 return(ERROR(ERRDOS,ERRbadpath));
614 /* convert the formatted masks */
616 p = mask;
617 while (*p) {
618 if (*p == '<') *p = '*';
619 if (*p == '>') *p = '?';
620 if (*p == '"') *p = '.';
621 p++;
625 /* a special case for 16 bit apps */
626 if (strequal(mask,"????????.???")) strcpy(mask,"*");
628 /* handle broken clients that send us old 8.3 format */
629 string_sub(mask,"????????","*");
630 string_sub(mask,".???",".*");
632 /* Save the wildcard match and attribs we are using on this directory -
633 needed as lanman2 assumes these are being saved between calls */
635 if(!(wcard = strdup(mask))) {
636 dptr_close(dptr_num);
637 return(ERROR(ERRDOS,ERRnomem));
640 dptr_set_wcard(dptr_num, wcard);
641 dptr_set_attr(dptr_num, dirtype);
643 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
645 /* We don't need to check for VOL here as this is returned by
646 a different TRANS2 call. */
648 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
649 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
650 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
651 dont_descend = True;
653 p = pdata;
654 space_remaining = max_data_bytes;
655 out_of_space = False;
657 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
660 /* this is a heuristic to avoid seeking the dirptr except when
661 absolutely necessary. It allows for a filename of about 40 chars */
662 if (space_remaining < DIRLEN_GUESS && numentries > 0)
664 out_of_space = True;
665 finished = False;
667 else
669 finished =
670 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
671 requires_resume_key,dont_descend,
672 &p,pdata,space_remaining, &out_of_space,
673 &last_name_off);
676 if (finished && out_of_space)
677 finished = False;
679 if (!finished && !out_of_space)
680 numentries++;
681 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
684 /* Check if we can close the dirptr */
685 if(close_after_first || (finished && close_if_end))
687 dptr_close(dptr_num);
688 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
689 dptr_num = -1;
692 /* At this point pdata points to numentries directory entries. */
694 /* Set up the return parameter block */
695 SSVAL(params,0,dptr_num);
696 SSVAL(params,2,numentries);
697 SSVAL(params,4,finished);
698 SSVAL(params,6,0); /* Never an EA error */
699 SSVAL(params,8,last_name_off);
701 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
703 if ((! *directory) && dptr_path(dptr_num))
704 sprintf(directory,"(%s)",dptr_path(dptr_num));
706 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
707 timestring(),
708 smb_fn_name(CVAL(inbuf,smb_com)),
709 mask,directory,cnum,dirtype,numentries));
711 return(-1);
715 /****************************************************************************
716 reply to a TRANS2_FINDNEXT
717 ****************************************************************************/
718 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
719 int cnum, char **pparams, char **ppdata)
721 /* We must be careful here that we don't return more than the
722 allowed number of data bytes. If this means returning fewer than
723 maxentries then so be it. We assume that the redirector has
724 enough room for the fixed number of parameter bytes it has
725 requested. */
726 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
727 char *params = *pparams;
728 char *pdata = *ppdata;
729 int16 dptr_num = SVAL(params,0);
730 int maxentries = SVAL(params,2);
731 uint16 info_level = SVAL(params,4);
732 uint32 resume_key = IVAL(params,6);
733 BOOL close_after_request = BITSETW(params+10,0);
734 BOOL close_if_end = BITSETW(params+10,1);
735 BOOL requires_resume_key = BITSETW(params+10,2);
736 BOOL continue_bit = BITSETW(params+10,3);
737 pstring mask;
738 pstring directory;
739 char *p;
740 uint16 dirtype;
741 int numentries = 0;
742 int i, last_name_off=0;
743 BOOL finished = False;
744 BOOL dont_descend = False;
745 BOOL out_of_space = False;
746 int space_remaining;
748 *mask = *directory = 0;
750 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",
751 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
752 requires_resume_key, resume_key, continue_bit, info_level));
754 switch (info_level)
756 case 1:
757 case 2:
758 case 3:
759 case 4:
760 case SMB_FIND_FILE_DIRECTORY_INFO:
761 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
762 case SMB_FIND_FILE_NAMES_INFO:
763 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
764 break;
765 default:
766 return(ERROR(ERRDOS,ERRunknownlevel));
769 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
770 if(!*ppdata)
771 return(ERROR(ERRDOS,ERRnomem));
772 bzero(pdata,max_data_bytes);
774 /* Realloc the params space */
775 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
776 if(!params)
777 return(ERROR(ERRDOS,ERRnomem));
779 /* Check that the dptr is valid */
780 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
781 return(ERROR(ERRDOS,ERRnofiles));
783 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
785 /* Get the wildcard mask from the dptr */
786 if((p = dptr_wcard(dptr_num))== NULL) {
787 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
788 return (ERROR(ERRDOS,ERRnofiles));
790 strcpy(mask, p);
791 strcpy(directory,Connections[cnum].dirpath);
793 /* Get the attr mask from the dptr */
794 dirtype = dptr_attr(dptr_num);
796 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
797 dptr_num, mask, dirtype,
798 Connections[cnum].dirptr,
799 TellDir(Connections[cnum].dirptr)));
801 /* We don't need to check for VOL here as this is returned by
802 a different TRANS2 call. */
804 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
805 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
806 dont_descend = True;
808 p = pdata;
809 space_remaining = max_data_bytes;
810 out_of_space = False;
812 /* If we have a resume key - seek to the correct position. */
813 if(requires_resume_key && !continue_bit)
814 SeekDir(Connections[cnum].dirptr, resume_key);
816 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
818 /* this is a heuristic to avoid seeking the dirptr except when
819 absolutely necessary. It allows for a filename of about 40 chars */
820 if (space_remaining < DIRLEN_GUESS && numentries > 0)
822 out_of_space = True;
823 finished = False;
825 else
827 finished =
828 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
829 requires_resume_key,dont_descend,
830 &p,pdata,space_remaining, &out_of_space,
831 &last_name_off);
834 if (finished && out_of_space)
835 finished = False;
837 if (!finished && !out_of_space)
838 numentries++;
839 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
842 /* Check if we can close the dirptr */
843 if(close_after_request || (finished && close_if_end))
845 dptr_close(dptr_num); /* This frees up the saved mask */
846 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
847 dptr_num = -1;
851 /* Set up the return parameter block */
852 SSVAL(params,0,numentries);
853 SSVAL(params,2,finished);
854 SSVAL(params,4,0); /* Never an EA error */
855 SSVAL(params,6,last_name_off);
857 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
859 if ((! *directory) && dptr_path(dptr_num))
860 sprintf(directory,"(%s)",dptr_path(dptr_num));
862 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
863 timestring(),
864 smb_fn_name(CVAL(inbuf,smb_com)),
865 mask,directory,cnum,dirtype,numentries));
867 return(-1);
870 /****************************************************************************
871 reply to a TRANS2_QFSINFO (query filesystem info)
872 ****************************************************************************/
873 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
874 int cnum, char **pparams, char **ppdata)
876 char *pdata = *ppdata;
877 char *params = *pparams;
878 uint16 info_level = SVAL(params,0);
879 int data_len;
880 struct stat st;
881 char *vname = volume_label(SNUM(cnum));
883 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
885 if(sys_stat(".",&st)!=0) {
886 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
887 return (ERROR(ERRSRV,ERRinvdevice));
890 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
892 switch (info_level)
894 case 1:
896 int dfree,dsize,bsize;
897 data_len = 18;
898 sys_disk_free(".",&bsize,&dfree,&dsize);
899 SIVAL(pdata,l1_idFileSystem,st.st_dev);
900 SIVAL(pdata,l1_cSectorUnit,bsize/512);
901 SIVAL(pdata,l1_cUnit,dsize);
902 SIVAL(pdata,l1_cUnitAvail,dfree);
903 SSVAL(pdata,l1_cbSector,512);
904 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
905 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
906 break;
908 case 2:
910 /* Return volume name */
911 int volname_len = MIN(strlen(vname),11);
912 data_len = l2_vol_szVolLabel + volname_len + 1;
913 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
914 SCVAL(pdata,l2_vol_cch,volname_len);
915 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
916 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
917 pdata+l2_vol_szVolLabel));
918 break;
920 case SMB_QUERY_FS_ATTRIBUTE_INFO:
921 data_len = 12 + 2*strlen(FSTYPE_STRING);
922 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
923 SIVAL(pdata,4,128); /* Max filename component length */
924 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
925 PutUniCode(pdata+12,FSTYPE_STRING);
926 break;
927 case SMB_QUERY_FS_LABEL_INFO:
928 data_len = 4 + strlen(vname);
929 SIVAL(pdata,0,strlen(vname));
930 strcpy(pdata+4,vname);
931 break;
932 case SMB_QUERY_FS_VOLUME_INFO:
933 data_len = 18 + 2*strlen(vname);
934 SIVAL(pdata,12,2*strlen(vname));
935 PutUniCode(pdata+18,vname);
936 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
937 vname));
938 break;
939 break;
940 case SMB_QUERY_FS_SIZE_INFO:
942 int dfree,dsize,bsize;
943 data_len = 24;
944 sys_disk_free(".",&bsize,&dfree,&dsize);
945 SIVAL(pdata,0,dsize);
946 SIVAL(pdata,8,dfree);
947 SIVAL(pdata,16,bsize/512);
948 SIVAL(pdata,20,512);
950 break;
951 case SMB_QUERY_FS_DEVICE_INFO:
952 data_len = 8;
953 SIVAL(pdata,0,0); /* dev type */
954 SIVAL(pdata,4,0); /* characteristics */
955 break;
956 default:
957 return(ERROR(ERRDOS,ERRunknownlevel));
961 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
963 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
965 return -1;
968 /****************************************************************************
969 reply to a TRANS2_SETFSINFO (set filesystem info)
970 ****************************************************************************/
971 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
972 int cnum, char **pparams, char **ppdata)
974 /* Just say yes we did it - there is nothing that
975 can be set here so it doesn't matter. */
976 int outsize;
977 DEBUG(3,("call_trans2setfsinfo\n"));
979 if (!CAN_WRITE(cnum))
980 return(ERROR(ERRSRV,ERRaccess));
982 outsize = set_message(outbuf,10,0,True);
984 return outsize;
987 /****************************************************************************
988 reply to a TRANS2_QFILEINFO (query file info by fileid)
989 ****************************************************************************/
990 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
991 int bufsize,int cnum,
992 char **pparams,char **ppdata,
993 int total_data)
995 char *params = *pparams;
996 char *pdata = *ppdata;
997 uint16 tran_call = SVAL(inbuf, smb_setup0);
998 uint16 info_level;
999 int mode=0;
1000 int size=0;
1001 unsigned int data_size;
1002 struct stat sbuf;
1003 pstring fname1;
1004 char *fname;
1005 char *p;
1006 int l,pos;
1009 if (tran_call == TRANSACT2_QFILEINFO) {
1010 int16 fnum = SVALS(params,0);
1011 info_level = SVAL(params,2);
1013 CHECK_FNUM(fnum,cnum);
1014 CHECK_ERROR(fnum);
1016 fname = Files[fnum].name;
1017 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1018 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1019 return(UNIXERROR(ERRDOS,ERRbadfid));
1021 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1022 } else {
1023 /* qpathinfo */
1024 info_level = SVAL(params,0);
1025 fname = &fname1[0];
1026 strcpy(fname,&params[6]);
1027 unix_convert(fname,cnum,0);
1028 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1029 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1030 return(UNIXERROR(ERRDOS,ERRbadpath));
1032 pos = 0;
1036 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1037 fname,info_level,tran_call,total_data));
1039 p = strrchr(fname,'/');
1040 if (!p)
1041 p = fname;
1042 else
1043 p++;
1044 l = strlen(p);
1045 mode = dos_mode(cnum,fname,&sbuf);
1046 size = sbuf.st_size;
1047 if (mode & aDIR) size = 0;
1049 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1050 data_size = 1024;
1051 pdata = *ppdata = Realloc(*ppdata, data_size);
1053 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1054 /* uggh, EAs for OS2 */
1055 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1056 #if 0
1057 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1058 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1059 return(-1);
1060 #else
1061 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1062 #endif
1065 bzero(pdata,data_size);
1067 switch (info_level)
1069 case 1:
1070 case 2:
1071 data_size = (info_level==1?22:26);
1072 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
1073 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1074 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
1075 SIVAL(pdata,l1_cbFile,size);
1076 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1077 SSVAL(pdata,l1_attrFile,mode);
1078 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1079 break;
1081 case 3:
1082 data_size = 24;
1083 put_dos_date2(pdata,0,sbuf.st_ctime);
1084 put_dos_date2(pdata,4,sbuf.st_atime);
1085 put_dos_date2(pdata,8,sbuf.st_mtime);
1086 SIVAL(pdata,12,size);
1087 SIVAL(pdata,16,ROUNDUP(size,1024));
1088 SIVAL(pdata,20,mode);
1089 break;
1091 case 4:
1092 data_size = 4;
1093 SIVAL(pdata,0,data_size);
1094 break;
1096 case 6:
1097 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1099 case SMB_QUERY_FILE_BASIC_INFO:
1100 data_size = 36;
1101 put_long_date(pdata,sbuf.st_ctime);
1102 put_long_date(pdata+8,sbuf.st_atime);
1103 put_long_date(pdata+16,sbuf.st_mtime);
1104 put_long_date(pdata+24,sbuf.st_mtime);
1105 SIVAL(pdata,32,mode);
1106 break;
1108 case SMB_QUERY_FILE_STANDARD_INFO:
1109 data_size = 22;
1110 SIVAL(pdata,0,size);
1111 SIVAL(pdata,8,size);
1112 SIVAL(pdata,16,sbuf.st_nlink);
1113 CVAL(pdata,20) = 0;
1114 CVAL(pdata,21) = (mode&aDIR)?1:0;
1115 break;
1117 case SMB_QUERY_FILE_EA_INFO:
1118 data_size = 4;
1119 break;
1121 case SMB_QUERY_FILE_NAME_INFO:
1122 case SMB_QUERY_FILE_ALT_NAME_INFO:
1123 data_size = 4 + l;
1124 SIVAL(pdata,0,l);
1125 strcpy(pdata+4,fname);
1126 break;
1127 case SMB_QUERY_FILE_ALLOCATION_INFO:
1128 case SMB_QUERY_FILE_END_OF_FILEINFO:
1129 data_size = 8;
1130 SIVAL(pdata,0,size);
1131 break;
1133 case SMB_QUERY_FILE_ALL_INFO:
1134 put_long_date(pdata,sbuf.st_ctime);
1135 put_long_date(pdata+8,sbuf.st_atime);
1136 put_long_date(pdata+16,sbuf.st_mtime);
1137 put_long_date(pdata+24,sbuf.st_mtime);
1138 SIVAL(pdata,32,mode);
1139 pdata += 40;
1140 SIVAL(pdata,0,size);
1141 SIVAL(pdata,8,size);
1142 SIVAL(pdata,16,sbuf.st_nlink);
1143 CVAL(pdata,20) = 0;
1144 CVAL(pdata,21) = (mode&aDIR)?1:0;
1145 pdata += 24;
1146 pdata += 8; /* index number */
1147 pdata += 4; /* EA info */
1148 if (mode & aRONLY)
1149 SIVAL(pdata,0,0xA9);
1150 else
1151 SIVAL(pdata,0,0xd01BF);
1152 pdata += 4;
1153 SIVAL(pdata,0,pos); /* current offset */
1154 pdata += 8;
1155 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1156 pdata += 4;
1157 pdata += 4; /* alignment */
1158 SIVAL(pdata,0,l);
1159 strcpy(pdata+4,fname);
1160 pdata += 4 + l;
1161 data_size = PTR_DIFF(pdata,(*ppdata));
1162 break;
1164 case SMB_QUERY_FILE_STREAM_INFO:
1165 data_size = 24 + l;
1166 SIVAL(pdata,0,pos);
1167 SIVAL(pdata,4,size);
1168 SIVAL(pdata,12,size);
1169 SIVAL(pdata,20,l);
1170 strcpy(pdata+24,fname);
1171 break;
1172 default:
1173 return(ERROR(ERRDOS,ERRunknownlevel));
1176 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1178 return(-1);
1181 /****************************************************************************
1182 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1183 ****************************************************************************/
1184 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1185 int bufsize, int cnum, char **pparams,
1186 char **ppdata, int total_data)
1188 char *params = *pparams;
1189 char *pdata = *ppdata;
1190 uint16 tran_call = SVAL(inbuf, smb_setup0);
1191 uint16 info_level;
1192 int mode=0;
1193 int size=0;
1194 struct utimbuf tvs;
1195 struct stat st;
1196 pstring fname1;
1197 char *fname;
1198 int fd = -1;
1200 if (!CAN_WRITE(cnum))
1201 return(ERROR(ERRSRV,ERRaccess));
1203 if (tran_call == TRANSACT2_SETFILEINFO) {
1204 int16 fnum = SVALS(params,0);
1205 info_level = SVAL(params,2);
1207 CHECK_FNUM(fnum,cnum);
1208 CHECK_ERROR(fnum);
1210 fname = Files[fnum].name;
1211 fd = Files[fnum].fd_ptr->fd;
1213 if(fstat(fd,&st)!=0) {
1214 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1215 return(ERROR(ERRDOS,ERRbadpath));
1217 } else {
1218 /* set path info */
1219 info_level = SVAL(params,0);
1220 fname = fname1;
1221 strcpy(fname,&params[6]);
1222 unix_convert(fname,cnum,0);
1223 if(!check_name(fname, cnum))
1224 return(ERROR(ERRDOS,ERRbadpath));
1226 if(sys_stat(fname,&st)!=0) {
1227 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1228 return(ERROR(ERRDOS,ERRbadpath));
1232 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1233 tran_call,fname,info_level,total_data));
1235 /* Realloc the parameter and data sizes */
1236 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1237 if(params == NULL)
1238 return(ERROR(ERRDOS,ERRnomem));
1240 size = st.st_size;
1241 tvs.modtime = st.st_mtime;
1242 tvs.actime = st.st_atime;
1243 mode = dos_mode(cnum,fname,&st);
1245 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1246 /* uggh, EAs for OS2 */
1247 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1248 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1250 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1252 return(-1);
1255 switch (info_level)
1257 case 1:
1258 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1259 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1260 mode = SVAL(pdata,l1_attrFile);
1261 size = IVAL(pdata,l1_cbFile);
1262 break;
1264 case 2:
1265 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1266 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1267 mode = SVAL(pdata,l1_attrFile);
1268 size = IVAL(pdata,l1_cbFile);
1269 break;
1271 case 3:
1272 tvs.actime = make_unix_date2(pdata+8);
1273 tvs.modtime = make_unix_date2(pdata+12);
1274 size = IVAL(pdata,16);
1275 mode = IVAL(pdata,24);
1276 break;
1278 case 4:
1279 tvs.actime = make_unix_date2(pdata+8);
1280 tvs.modtime = make_unix_date2(pdata+12);
1281 size = IVAL(pdata,16);
1282 mode = IVAL(pdata,24);
1283 break;
1285 case SMB_SET_FILE_BASIC_INFO:
1286 pdata += 8; /* create time */
1287 tvs.actime = interpret_long_date(pdata); pdata += 8;
1288 tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8));
1289 pdata += 16;
1290 mode = IVAL(pdata,0);
1291 break;
1293 case SMB_SET_FILE_END_OF_FILE_INFO:
1294 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1295 return(ERROR(ERRDOS,ERRunknownlevel));
1296 size = IVAL(pdata,0);
1297 break;
1299 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1300 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1301 default:
1302 return(ERROR(ERRDOS,ERRunknownlevel));
1306 if (!tvs.actime) tvs.actime = st.st_atime;
1307 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1308 if (!size) size = st.st_size;
1310 /* Try and set the times, size and mode of this file - if they are different
1311 from the current values */
1312 if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
1313 if(sys_utime(fname, &tvs)!=0)
1314 return(ERROR(ERRDOS,ERRnoaccess));
1316 if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) {
1317 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1318 return(ERROR(ERRDOS,ERRnoaccess));
1320 if(size != st.st_size) {
1321 if (fd == -1) {
1322 fd = sys_open(fname,O_RDWR,0);
1323 if (fd == -1)
1324 return(ERROR(ERRDOS,ERRbadpath));
1325 set_filelen(fd, size);
1326 close(fd);
1327 } else {
1328 set_filelen(fd, size);
1332 SSVAL(params,0,0);
1334 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1336 return(-1);
1339 /****************************************************************************
1340 reply to a TRANS2_MKDIR (make directory with extended attributes).
1341 ****************************************************************************/
1342 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1343 int cnum, char **pparams, char **ppdata)
1345 char *params = *pparams;
1346 pstring directory;
1347 int ret = -1;
1349 if (!CAN_WRITE(cnum))
1350 return(ERROR(ERRSRV,ERRaccess));
1352 strcpy(directory, &params[4]);
1354 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1356 unix_convert(directory,cnum,0);
1357 if (check_name(directory,cnum))
1358 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1360 if(ret < 0)
1362 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1363 return(UNIXERROR(ERRDOS,ERRnoaccess));
1366 /* Realloc the parameter and data sizes */
1367 params = *pparams = Realloc(*pparams,2);
1368 if(params == NULL)
1369 return(ERROR(ERRDOS,ERRnomem));
1371 SSVAL(params,0,0);
1373 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1375 return(-1);
1378 /****************************************************************************
1379 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1380 We don't actually do this - we just send a null response.
1381 ****************************************************************************/
1382 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1383 int cnum, char **pparams, char **ppdata)
1385 static uint16 fnf_handle = 257;
1386 char *params = *pparams;
1387 uint16 info_level = SVAL(params,4);
1389 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1391 switch (info_level)
1393 case 1:
1394 case 2:
1395 break;
1396 default:
1397 return(ERROR(ERRDOS,ERRunknownlevel));
1400 /* Realloc the parameter and data sizes */
1401 params = *pparams = Realloc(*pparams,6);
1402 if(params == NULL)
1403 return(ERROR(ERRDOS,ERRnomem));
1405 SSVAL(params,0,fnf_handle);
1406 SSVAL(params,2,0); /* No changes */
1407 SSVAL(params,4,0); /* No EA errors */
1409 fnf_handle++;
1411 if(fnf_handle == 0)
1412 fnf_handle = 257;
1414 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1416 return(-1);
1419 /****************************************************************************
1420 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1421 changes). Currently this does nothing.
1422 ****************************************************************************/
1423 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1424 int cnum, char **pparams, char **ppdata)
1426 char *params = *pparams;
1428 DEBUG(3,("call_trans2findnotifynext\n"));
1430 /* Realloc the parameter and data sizes */
1431 params = *pparams = Realloc(*pparams,4);
1432 if(params == NULL)
1433 return(ERROR(ERRDOS,ERRnomem));
1435 SSVAL(params,0,0); /* No changes */
1436 SSVAL(params,2,0); /* No EA errors */
1438 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1440 return(-1);
1443 /****************************************************************************
1444 reply to a SMBfindclose (stop trans2 directory search)
1445 ****************************************************************************/
1446 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1448 int cnum;
1449 int outsize = 0;
1450 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1452 cnum = SVAL(inbuf,smb_tid);
1454 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1456 dptr_close(dptr_num);
1458 outsize = set_message(outbuf,0,0,True);
1460 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1462 return(outsize);
1465 /****************************************************************************
1466 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1467 ****************************************************************************/
1468 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1470 int cnum;
1471 int outsize = 0;
1472 int dptr_num= -1;
1474 cnum = SVAL(inbuf,smb_tid);
1475 dptr_num = SVAL(inbuf,smb_vwv0);
1477 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1479 /* We never give out valid handles for a
1480 findnotifyfirst - so any dptr_num is ok here.
1481 Just ignore it. */
1483 outsize = set_message(outbuf,0,0,True);
1485 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1487 return(outsize);
1491 /****************************************************************************
1492 reply to a SMBtranss2 - just ignore it!
1493 ****************************************************************************/
1494 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1496 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1497 return(-1);
1500 /****************************************************************************
1501 reply to a SMBtrans2
1502 ****************************************************************************/
1503 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1505 int outsize = 0;
1506 int cnum = SVAL(inbuf,smb_tid);
1507 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1508 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1509 #if 0
1510 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1511 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1512 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1513 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1514 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1515 int32 timeout = IVALS(inbuf,smb_timeout);
1516 #endif
1517 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1518 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1519 char *params = NULL, *data = NULL;
1520 int num_params, num_params_sofar, num_data, num_data_sofar;
1522 outsize = set_message(outbuf,0,0,True);
1524 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1525 is so as a sanity check */
1526 if(suwcnt != 1 )
1528 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1529 return(ERROR(ERRSRV,ERRerror));
1532 /* Allocate the space for the maximum needed parameters and data */
1533 if (total_params > 0)
1534 params = (char *)malloc(total_params);
1535 if (total_data > 0)
1536 data = (char *)malloc(total_data);
1538 if ((total_params && !params) || (total_data && !data))
1540 DEBUG(2,("Out of memory in reply_trans2\n"));
1541 return(ERROR(ERRDOS,ERRnomem));
1544 /* Copy the param and data bytes sent with this request into
1545 the params buffer */
1546 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1547 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1549 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1550 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1552 if(num_data_sofar < total_data || num_params_sofar < total_params)
1554 /* We need to send an interim response then receive the rest
1555 of the parameter/data bytes */
1556 outsize = set_message(outbuf,0,0,True);
1557 send_smb(Client,outbuf);
1559 while( num_data_sofar < total_data || num_params_sofar < total_params)
1561 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1562 CVAL(inbuf, smb_com) != SMBtranss2)
1564 outsize = set_message(outbuf,0,0,True);
1565 DEBUG(2,("Invalid secondary trans2 packet\n"));
1566 free(params);
1567 free(data);
1568 return(ERROR(ERRSRV,ERRerror));
1571 /* Revise total_params and total_data in case they have changed downwards */
1572 total_params = SVAL(inbuf, smb_tpscnt);
1573 total_data = SVAL(inbuf, smb_tdscnt);
1574 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1575 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1576 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1577 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1578 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1579 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1583 if (Protocol >= PROTOCOL_NT1) {
1584 uint16 flg2 = SVAL(outbuf,smb_flg2);
1585 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1588 /* Now we must call the relevant TRANS2 function */
1589 switch(tran_call)
1591 case TRANSACT2_OPEN:
1592 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1593 break;
1594 case TRANSACT2_FINDFIRST:
1595 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1596 break;
1597 case TRANSACT2_FINDNEXT:
1598 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1599 break;
1600 case TRANSACT2_QFSINFO:
1601 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1602 break;
1603 case TRANSACT2_SETFSINFO:
1604 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1605 break;
1606 case TRANSACT2_QPATHINFO:
1607 case TRANSACT2_QFILEINFO:
1608 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1609 break;
1610 case TRANSACT2_SETPATHINFO:
1611 case TRANSACT2_SETFILEINFO:
1612 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1613 break;
1614 case TRANSACT2_FINDNOTIFYFIRST:
1615 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1616 break;
1617 case TRANSACT2_FINDNOTIFYNEXT:
1618 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1619 break;
1620 case TRANSACT2_MKDIR:
1621 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1622 break;
1623 default:
1624 /* Error in request */
1625 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1626 if(params)
1627 free(params);
1628 if(data)
1629 free(data);
1630 return (ERROR(ERRSRV,ERRerror));
1633 /* As we do not know how many data packets will need to be
1634 returned here the various call_trans2xxxx calls
1635 must send their own. Thus a call_trans2xxx routine only
1636 returns a value other than -1 when it wants to send
1637 an error packet.
1640 if(params)
1641 free(params);
1642 if(data)
1643 free(data);
1644 return outsize; /* If a correct response was needed the call_trans2xxx
1645 calls have already sent it. If outsize != -1 then it is
1646 returning an error packet. */