Makefile: Added cleandir target.
[Samba.git] / source / smbd / trans2.c
blobab2fe8853645f149bc6d13ca183e2b3d43e3c606
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 useable_space */
83 total_sent_thistime = MIN(total_sent_thistime, useable_space);
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;
279 int nt_extmode; /* Used for NT connections instead of mode */
281 *fname = 0;
282 *out_of_space = False;
284 if (!Connections[cnum].dirptr)
285 return(False);
287 p = strrchr(path_mask,'/');
288 if(p != NULL)
290 if(p[1] == '\0')
291 strcpy(mask,"*.*");
292 else
293 strcpy(mask, p+1);
295 else
296 strcpy(mask, path_mask);
298 while (!found)
300 /* Needed if we run out of space */
301 prev_dirpos = TellDir(Connections[cnum].dirptr);
302 dname = ReadDirName(Connections[cnum].dirptr);
304 reskey = TellDir(Connections[cnum].dirptr);
306 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
307 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
309 if (!dname)
310 return(False);
312 matched = False;
314 strcpy(fname,dname);
316 if(mask_match(fname, mask, case_sensitive, True))
318 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
319 if (dont_descend && !isdots)
320 continue;
322 if (isrootdir && isdots)
323 continue;
325 strcpy(pathreal,Connections[cnum].dirpath);
326 strcat(pathreal,"/");
327 strcat(pathreal,fname);
328 if (sys_stat(pathreal,&sbuf) != 0)
330 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
331 continue;
334 mode = dos_mode(cnum,pathreal,&sbuf);
336 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
337 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
338 continue;
341 size = sbuf.st_size;
342 mdate = sbuf.st_mtime;
343 adate = sbuf.st_atime;
344 cdate = sbuf.st_ctime;
345 if(mode & aDIR)
346 size = 0;
348 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
350 found = True;
356 p = pdata;
357 nameptr = p;
359 name_map_mangle(fname,False,SNUM(cnum));
361 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
363 switch (info_level)
365 case 1:
366 if(requires_resume_key) {
367 SIVAL(p,0,reskey);
368 p += 4;
370 put_dos_date2(p,l1_fdateCreation,cdate);
371 put_dos_date2(p,l1_fdateLastAccess,adate);
372 put_dos_date2(p,l1_fdateLastWrite,mdate);
373 SIVAL(p,l1_cbFile,size);
374 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
375 SSVAL(p,l1_attrFile,mode);
376 SCVAL(p,l1_cchName,strlen(fname));
377 strcpy(p + l1_achName, fname);
378 nameptr = p + l1_achName;
379 p += l1_achName + strlen(fname) + 1;
380 break;
382 case 2:
383 /* info_level 2 */
384 if(requires_resume_key) {
385 SIVAL(p,0,reskey);
386 p += 4;
388 put_dos_date2(p,l2_fdateCreation,cdate);
389 put_dos_date2(p,l2_fdateLastAccess,adate);
390 put_dos_date2(p,l2_fdateLastWrite,mdate);
391 SIVAL(p,l2_cbFile,size);
392 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
393 SSVAL(p,l2_attrFile,mode);
394 SIVAL(p,l2_cbList,0); /* No extended attributes */
395 SCVAL(p,l2_cchName,strlen(fname));
396 strcpy(p + l2_achName, fname);
397 nameptr = p + l2_achName;
398 p += l2_achName + strlen(fname) + 1;
399 break;
401 case 3:
402 SIVAL(p,0,reskey);
403 put_dos_date2(p,4,cdate);
404 put_dos_date2(p,8,adate);
405 put_dos_date2(p,12,mdate);
406 SIVAL(p,16,size);
407 SIVAL(p,20,ROUNDUP(size,1024));
408 SSVAL(p,24,mode);
409 SIVAL(p,26,4);
410 CVAL(p,30) = strlen(fname);
411 strcpy(p+31, fname);
412 nameptr = p+31;
413 p += 31 + strlen(fname) + 1;
414 break;
416 case 4:
417 if(requires_resume_key) {
418 SIVAL(p,0,reskey);
419 p += 4;
421 SIVAL(p,0,33+strlen(fname)+1);
422 put_dos_date2(p,4,cdate);
423 put_dos_date2(p,8,adate);
424 put_dos_date2(p,12,mdate);
425 SIVAL(p,16,size);
426 SIVAL(p,20,ROUNDUP(size,1024));
427 SSVAL(p,24,mode);
428 CVAL(p,32) = strlen(fname);
429 strcpy(p + 33, fname);
430 nameptr = p+33;
431 p += 33 + strlen(fname) + 1;
432 break;
434 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
435 was_8_3 = is_8_3(fname, True);
436 len = 94+strlen(fname);
437 len = (len + 3) & ~3;
438 SIVAL(p,0,len); p += 4;
439 SIVAL(p,0,reskey); p += 4;
440 put_long_date(p,cdate); p += 8;
441 put_long_date(p,adate); p += 8;
442 put_long_date(p,mdate); p += 8;
443 put_long_date(p,mdate); p += 8;
444 SIVAL(p,0,size); p += 8;
445 SIVAL(p,0,size); p += 8;
446 SIVAL(p,0,nt_extmode); p += 4;
447 SIVAL(p,0,strlen(fname)); p += 4;
448 SIVAL(p,0,0); p += 4;
449 if (!was_8_3) {
450 strcpy(p+2,fname);
451 if (!name_map_mangle(p+2,True,SNUM(cnum)))
452 (p+2)[12] = 0;
453 } else
454 *(p+2) = 0;
455 strupper(p+2);
456 SSVAL(p,0,strlen(p+2));
457 p += 2 + 24;
458 /* nameptr = p; */
459 strcpy(p,fname); p += strlen(p);
460 p = pdata + len;
461 break;
463 case SMB_FIND_FILE_DIRECTORY_INFO:
464 len = 64+strlen(fname);
465 len = (len + 3) & ~3;
466 SIVAL(p,0,len); p += 4;
467 SIVAL(p,0,reskey); p += 4;
468 put_long_date(p,cdate); p += 8;
469 put_long_date(p,adate); p += 8;
470 put_long_date(p,mdate); p += 8;
471 put_long_date(p,mdate); p += 8;
472 SIVAL(p,0,size); p += 8;
473 SIVAL(p,0,size); p += 8;
474 SIVAL(p,0,nt_extmode); p += 4;
475 SIVAL(p,0,strlen(fname)); p += 4;
476 strcpy(p,fname);
477 p = pdata + len;
478 break;
481 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
482 len = 68+strlen(fname);
483 len = (len + 3) & ~3;
484 SIVAL(p,0,len); p += 4;
485 SIVAL(p,0,reskey); p += 4;
486 put_long_date(p,cdate); p += 8;
487 put_long_date(p,adate); p += 8;
488 put_long_date(p,mdate); p += 8;
489 put_long_date(p,mdate); p += 8;
490 SIVAL(p,0,size); p += 8;
491 SIVAL(p,0,size); p += 8;
492 SIVAL(p,0,nt_extmode); p += 4;
493 SIVAL(p,0,strlen(fname)); p += 4;
494 SIVAL(p,0,0); p += 4;
495 strcpy(p,fname);
496 p = pdata + len;
497 break;
499 case SMB_FIND_FILE_NAMES_INFO:
500 len = 12+strlen(fname);
501 len = (len + 3) & ~3;
502 SIVAL(p,0,len); p += 4;
503 SIVAL(p,0,reskey); p += 4;
504 SIVAL(p,0,strlen(fname)); p += 4;
505 strcpy(p,fname);
506 p = pdata + len;
507 break;
509 default:
510 return(False);
514 if (PTR_DIFF(p,pdata) > space_remaining) {
515 /* Move the dirptr back to prev_dirpos */
516 SeekDir(Connections[cnum].dirptr, prev_dirpos);
517 *out_of_space = True;
518 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
519 return False; /* Not finished - just out of space */
522 /* Setup the last_filename pointer, as an offset from base_data */
523 *last_name_off = PTR_DIFF(nameptr,base_data);
524 /* Advance the data pointer to the next slot */
525 *ppdata = p;
526 return(found);
529 /****************************************************************************
530 reply to a TRANS2_FINDFIRST
531 ****************************************************************************/
532 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
533 char **pparams, char **ppdata)
535 /* We must be careful here that we don't return more than the
536 allowed number of data bytes. If this means returning fewer than
537 maxentries then so be it. We assume that the redirector has
538 enough room for the fixed number of parameter bytes it has
539 requested. */
540 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
541 char *params = *pparams;
542 char *pdata = *ppdata;
543 int dirtype = SVAL(params,0);
544 int maxentries = SVAL(params,2);
545 BOOL close_after_first = BITSETW(params+4,0);
546 BOOL close_if_end = BITSETW(params+4,1);
547 BOOL requires_resume_key = BITSETW(params+4,2);
548 int info_level = SVAL(params,6);
549 pstring directory;
550 pstring mask;
551 char *p, *wcard;
552 int last_name_off=0;
553 int dptr_num = -1;
554 int numentries = 0;
555 int i;
556 BOOL finished = False;
557 BOOL dont_descend = False;
558 BOOL out_of_space = False;
559 int space_remaining;
561 *directory = *mask = 0;
563 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",
564 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
565 info_level, max_data_bytes));
567 switch (info_level)
569 case 1:
570 case 2:
571 case 3:
572 case 4:
573 case SMB_FIND_FILE_DIRECTORY_INFO:
574 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
575 case SMB_FIND_FILE_NAMES_INFO:
576 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
577 break;
578 default:
579 return(ERROR(ERRDOS,ERRunknownlevel));
582 strcpy(directory, params + 12); /* Complete directory path with
583 wildcard mask appended */
585 DEBUG(5,("path=%s\n",directory));
587 unix_convert(directory,cnum,0);
588 if(!check_name(directory,cnum)) {
589 return(ERROR(ERRDOS,ERRbadpath));
592 p = strrchr(directory,'/');
593 if(p == NULL) {
594 strcpy(mask,directory);
595 strcpy(directory,"./");
596 } else {
597 strcpy(mask,p+1);
598 *p = 0;
601 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
603 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
604 if(!*ppdata)
605 return(ERROR(ERRDOS,ERRnomem));
606 bzero(pdata,max_data_bytes);
608 /* Realloc the params space */
609 params = *pparams = Realloc(*pparams, 10);
610 if(params == NULL)
611 return(ERROR(ERRDOS,ERRnomem));
613 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
614 if (dptr_num < 0)
615 return(ERROR(ERRDOS,ERRbadpath));
617 /* convert the formatted masks */
619 p = mask;
620 while (*p) {
621 if (*p == '<') *p = '*';
622 if (*p == '>') *p = '?';
623 if (*p == '"') *p = '.';
624 p++;
628 /* a special case for 16 bit apps */
629 if (strequal(mask,"????????.???")) strcpy(mask,"*");
631 /* handle broken clients that send us old 8.3 format */
632 string_sub(mask,"????????","*");
633 string_sub(mask,".???",".*");
635 /* Save the wildcard match and attribs we are using on this directory -
636 needed as lanman2 assumes these are being saved between calls */
638 if(!(wcard = strdup(mask))) {
639 dptr_close(dptr_num);
640 return(ERROR(ERRDOS,ERRnomem));
643 dptr_set_wcard(dptr_num, wcard);
644 dptr_set_attr(dptr_num, dirtype);
646 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
648 /* We don't need to check for VOL here as this is returned by
649 a different TRANS2 call. */
651 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
652 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
653 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
654 dont_descend = True;
656 p = pdata;
657 space_remaining = max_data_bytes;
658 out_of_space = False;
660 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
663 /* this is a heuristic to avoid seeking the dirptr except when
664 absolutely necessary. It allows for a filename of about 40 chars */
665 if (space_remaining < DIRLEN_GUESS && numentries > 0)
667 out_of_space = True;
668 finished = False;
670 else
672 finished =
673 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
674 requires_resume_key,dont_descend,
675 &p,pdata,space_remaining, &out_of_space,
676 &last_name_off);
679 if (finished && out_of_space)
680 finished = False;
682 if (!finished && !out_of_space)
683 numentries++;
684 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
687 /* Check if we can close the dirptr */
688 if(close_after_first || (finished && close_if_end))
690 dptr_close(dptr_num);
691 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
692 dptr_num = -1;
695 /* At this point pdata points to numentries directory entries. */
697 /* Set up the return parameter block */
698 SSVAL(params,0,dptr_num);
699 SSVAL(params,2,numentries);
700 SSVAL(params,4,finished);
701 SSVAL(params,6,0); /* Never an EA error */
702 SSVAL(params,8,last_name_off);
704 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
706 if ((! *directory) && dptr_path(dptr_num))
707 sprintf(directory,"(%s)",dptr_path(dptr_num));
709 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
710 timestring(),
711 smb_fn_name(CVAL(inbuf,smb_com)),
712 mask,directory,cnum,dirtype,numentries));
714 return(-1);
718 /****************************************************************************
719 reply to a TRANS2_FINDNEXT
720 ****************************************************************************/
721 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
722 int cnum, char **pparams, char **ppdata)
724 /* We must be careful here that we don't return more than the
725 allowed number of data bytes. If this means returning fewer than
726 maxentries then so be it. We assume that the redirector has
727 enough room for the fixed number of parameter bytes it has
728 requested. */
729 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
730 char *params = *pparams;
731 char *pdata = *ppdata;
732 int16 dptr_num = SVAL(params,0);
733 int maxentries = SVAL(params,2);
734 uint16 info_level = SVAL(params,4);
735 uint32 resume_key = IVAL(params,6);
736 BOOL close_after_request = BITSETW(params+10,0);
737 BOOL close_if_end = BITSETW(params+10,1);
738 BOOL requires_resume_key = BITSETW(params+10,2);
739 BOOL continue_bit = BITSETW(params+10,3);
740 pstring mask;
741 pstring directory;
742 char *p;
743 uint16 dirtype;
744 int numentries = 0;
745 int i, last_name_off=0;
746 BOOL finished = False;
747 BOOL dont_descend = False;
748 BOOL out_of_space = False;
749 int space_remaining;
751 *mask = *directory = 0;
753 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",
754 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
755 requires_resume_key, resume_key, continue_bit, info_level));
757 switch (info_level)
759 case 1:
760 case 2:
761 case 3:
762 case 4:
763 case SMB_FIND_FILE_DIRECTORY_INFO:
764 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
765 case SMB_FIND_FILE_NAMES_INFO:
766 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
767 break;
768 default:
769 return(ERROR(ERRDOS,ERRunknownlevel));
772 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
773 if(!*ppdata)
774 return(ERROR(ERRDOS,ERRnomem));
775 bzero(pdata,max_data_bytes);
777 /* Realloc the params space */
778 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
779 if(!params)
780 return(ERROR(ERRDOS,ERRnomem));
782 /* Check that the dptr is valid */
783 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
784 return(ERROR(ERRDOS,ERRnofiles));
786 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
788 /* Get the wildcard mask from the dptr */
789 if((p = dptr_wcard(dptr_num))== NULL) {
790 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
791 return (ERROR(ERRDOS,ERRnofiles));
793 strcpy(mask, p);
794 strcpy(directory,Connections[cnum].dirpath);
796 /* Get the attr mask from the dptr */
797 dirtype = dptr_attr(dptr_num);
799 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
800 dptr_num, mask, dirtype,
801 Connections[cnum].dirptr,
802 TellDir(Connections[cnum].dirptr)));
804 /* We don't need to check for VOL here as this is returned by
805 a different TRANS2 call. */
807 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
808 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
809 dont_descend = True;
811 p = pdata;
812 space_remaining = max_data_bytes;
813 out_of_space = False;
815 /* If we have a resume key - seek to the correct position. */
816 if(requires_resume_key && !continue_bit)
817 SeekDir(Connections[cnum].dirptr, resume_key);
819 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
821 /* this is a heuristic to avoid seeking the dirptr except when
822 absolutely necessary. It allows for a filename of about 40 chars */
823 if (space_remaining < DIRLEN_GUESS && numentries > 0)
825 out_of_space = True;
826 finished = False;
828 else
830 finished =
831 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
832 requires_resume_key,dont_descend,
833 &p,pdata,space_remaining, &out_of_space,
834 &last_name_off);
837 if (finished && out_of_space)
838 finished = False;
840 if (!finished && !out_of_space)
841 numentries++;
842 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
845 /* Check if we can close the dirptr */
846 if(close_after_request || (finished && close_if_end))
848 dptr_close(dptr_num); /* This frees up the saved mask */
849 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
850 dptr_num = -1;
854 /* Set up the return parameter block */
855 SSVAL(params,0,numentries);
856 SSVAL(params,2,finished);
857 SSVAL(params,4,0); /* Never an EA error */
858 SSVAL(params,6,last_name_off);
860 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
862 if ((! *directory) && dptr_path(dptr_num))
863 sprintf(directory,"(%s)",dptr_path(dptr_num));
865 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
866 timestring(),
867 smb_fn_name(CVAL(inbuf,smb_com)),
868 mask,directory,cnum,dirtype,numentries));
870 return(-1);
873 /****************************************************************************
874 reply to a TRANS2_QFSINFO (query filesystem info)
875 ****************************************************************************/
876 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
877 int cnum, char **pparams, char **ppdata)
879 char *pdata = *ppdata;
880 char *params = *pparams;
881 uint16 info_level = SVAL(params,0);
882 int data_len;
883 struct stat st;
884 char *vname = volume_label(SNUM(cnum));
886 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
888 if(sys_stat(".",&st)!=0) {
889 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
890 return (ERROR(ERRSRV,ERRinvdevice));
893 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
895 switch (info_level)
897 case 1:
899 int dfree,dsize,bsize;
900 data_len = 18;
901 sys_disk_free(".",&bsize,&dfree,&dsize);
902 SIVAL(pdata,l1_idFileSystem,st.st_dev);
903 SIVAL(pdata,l1_cSectorUnit,bsize/512);
904 SIVAL(pdata,l1_cUnit,dsize);
905 SIVAL(pdata,l1_cUnitAvail,dfree);
906 SSVAL(pdata,l1_cbSector,512);
907 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
908 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
909 break;
911 case 2:
913 /* Return volume name */
914 int volname_len = MIN(strlen(vname),11);
915 data_len = l2_vol_szVolLabel + volname_len + 1;
916 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
917 SCVAL(pdata,l2_vol_cch,volname_len);
918 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
919 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
920 pdata+l2_vol_szVolLabel));
921 break;
923 case SMB_QUERY_FS_ATTRIBUTE_INFO:
924 data_len = 12 + 2*strlen(FSTYPE_STRING);
925 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
926 SIVAL(pdata,4,128); /* Max filename component length */
927 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
928 PutUniCode(pdata+12,FSTYPE_STRING);
929 break;
930 case SMB_QUERY_FS_LABEL_INFO:
931 data_len = 4 + strlen(vname);
932 SIVAL(pdata,0,strlen(vname));
933 strcpy(pdata+4,vname);
934 break;
935 case SMB_QUERY_FS_VOLUME_INFO:
936 data_len = 18 + 2*strlen(vname);
937 SIVAL(pdata,12,2*strlen(vname));
938 PutUniCode(pdata+18,vname);
939 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
940 vname));
941 break;
942 break;
943 case SMB_QUERY_FS_SIZE_INFO:
945 int dfree,dsize,bsize;
946 data_len = 24;
947 sys_disk_free(".",&bsize,&dfree,&dsize);
948 SIVAL(pdata,0,dsize);
949 SIVAL(pdata,8,dfree);
950 SIVAL(pdata,16,bsize/512);
951 SIVAL(pdata,20,512);
953 break;
954 case SMB_QUERY_FS_DEVICE_INFO:
955 data_len = 8;
956 SIVAL(pdata,0,0); /* dev type */
957 SIVAL(pdata,4,0); /* characteristics */
958 break;
959 default:
960 return(ERROR(ERRDOS,ERRunknownlevel));
964 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
966 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
968 return -1;
971 /****************************************************************************
972 reply to a TRANS2_SETFSINFO (set filesystem info)
973 ****************************************************************************/
974 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
975 int cnum, char **pparams, char **ppdata)
977 /* Just say yes we did it - there is nothing that
978 can be set here so it doesn't matter. */
979 int outsize;
980 DEBUG(3,("call_trans2setfsinfo\n"));
982 if (!CAN_WRITE(cnum))
983 return(ERROR(ERRSRV,ERRaccess));
985 outsize = set_message(outbuf,10,0,True);
987 return outsize;
990 /****************************************************************************
991 reply to a TRANS2_QFILEINFO (query file info by fileid)
992 ****************************************************************************/
993 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
994 int bufsize,int cnum,
995 char **pparams,char **ppdata,
996 int total_data)
998 char *params = *pparams;
999 char *pdata = *ppdata;
1000 uint16 tran_call = SVAL(inbuf, smb_setup0);
1001 uint16 info_level;
1002 int mode=0;
1003 int size=0;
1004 unsigned int data_size;
1005 struct stat sbuf;
1006 pstring fname1;
1007 char *fname;
1008 char *p;
1009 int l,pos;
1012 if (tran_call == TRANSACT2_QFILEINFO) {
1013 int16 fnum = SVALS(params,0);
1014 info_level = SVAL(params,2);
1016 CHECK_FNUM(fnum,cnum);
1017 CHECK_ERROR(fnum);
1019 fname = Files[fnum].name;
1020 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1021 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1022 return(UNIXERROR(ERRDOS,ERRbadfid));
1024 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1025 } else {
1026 /* qpathinfo */
1027 info_level = SVAL(params,0);
1028 fname = &fname1[0];
1029 strcpy(fname,&params[6]);
1030 unix_convert(fname,cnum,0);
1031 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1032 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1033 return(UNIXERROR(ERRDOS,ERRbadpath));
1035 pos = 0;
1039 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1040 fname,info_level,tran_call,total_data));
1042 p = strrchr(fname,'/');
1043 if (!p)
1044 p = fname;
1045 else
1046 p++;
1047 l = strlen(p);
1048 mode = dos_mode(cnum,fname,&sbuf);
1049 size = sbuf.st_size;
1050 if (mode & aDIR) size = 0;
1052 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1053 data_size = 1024;
1054 pdata = *ppdata = Realloc(*ppdata, data_size);
1056 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1057 /* uggh, EAs for OS2 */
1058 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1059 #if 0
1060 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1061 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1062 return(-1);
1063 #else
1064 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1065 #endif
1068 bzero(pdata,data_size);
1070 switch (info_level)
1072 case 1:
1073 case 2:
1074 data_size = (info_level==1?22:26);
1075 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
1076 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1077 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
1078 SIVAL(pdata,l1_cbFile,size);
1079 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1080 SSVAL(pdata,l1_attrFile,mode);
1081 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1082 break;
1084 case 3:
1085 data_size = 24;
1086 put_dos_date2(pdata,0,sbuf.st_ctime);
1087 put_dos_date2(pdata,4,sbuf.st_atime);
1088 put_dos_date2(pdata,8,sbuf.st_mtime);
1089 SIVAL(pdata,12,size);
1090 SIVAL(pdata,16,ROUNDUP(size,1024));
1091 SIVAL(pdata,20,mode);
1092 break;
1094 case 4:
1095 data_size = 4;
1096 SIVAL(pdata,0,data_size);
1097 break;
1099 case 6:
1100 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1102 case SMB_QUERY_FILE_BASIC_INFO:
1103 data_size = 36;
1104 put_long_date(pdata,sbuf.st_ctime);
1105 put_long_date(pdata+8,sbuf.st_atime);
1106 put_long_date(pdata+16,sbuf.st_mtime);
1107 put_long_date(pdata+24,sbuf.st_mtime);
1108 SIVAL(pdata,32,mode);
1109 break;
1111 case SMB_QUERY_FILE_STANDARD_INFO:
1112 data_size = 22;
1113 SIVAL(pdata,0,size);
1114 SIVAL(pdata,8,size);
1115 SIVAL(pdata,16,sbuf.st_nlink);
1116 CVAL(pdata,20) = 0;
1117 CVAL(pdata,21) = (mode&aDIR)?1:0;
1118 break;
1120 case SMB_QUERY_FILE_EA_INFO:
1121 data_size = 4;
1122 break;
1124 case SMB_QUERY_FILE_NAME_INFO:
1125 case SMB_QUERY_FILE_ALT_NAME_INFO:
1126 data_size = 4 + l;
1127 SIVAL(pdata,0,l);
1128 strcpy(pdata+4,fname);
1129 break;
1130 case SMB_QUERY_FILE_ALLOCATION_INFO:
1131 case SMB_QUERY_FILE_END_OF_FILEINFO:
1132 data_size = 8;
1133 SIVAL(pdata,0,size);
1134 break;
1136 case SMB_QUERY_FILE_ALL_INFO:
1137 put_long_date(pdata,sbuf.st_ctime);
1138 put_long_date(pdata+8,sbuf.st_atime);
1139 put_long_date(pdata+16,sbuf.st_mtime);
1140 put_long_date(pdata+24,sbuf.st_mtime);
1141 SIVAL(pdata,32,mode);
1142 pdata += 40;
1143 SIVAL(pdata,0,size);
1144 SIVAL(pdata,8,size);
1145 SIVAL(pdata,16,sbuf.st_nlink);
1146 CVAL(pdata,20) = 0;
1147 CVAL(pdata,21) = (mode&aDIR)?1:0;
1148 pdata += 24;
1149 pdata += 8; /* index number */
1150 pdata += 4; /* EA info */
1151 if (mode & aRONLY)
1152 SIVAL(pdata,0,0xA9);
1153 else
1154 SIVAL(pdata,0,0xd01BF);
1155 pdata += 4;
1156 SIVAL(pdata,0,pos); /* current offset */
1157 pdata += 8;
1158 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1159 pdata += 4;
1160 pdata += 4; /* alignment */
1161 SIVAL(pdata,0,l);
1162 strcpy(pdata+4,fname);
1163 pdata += 4 + l;
1164 data_size = PTR_DIFF(pdata,(*ppdata));
1165 break;
1167 case SMB_QUERY_FILE_STREAM_INFO:
1168 data_size = 24 + l;
1169 SIVAL(pdata,0,pos);
1170 SIVAL(pdata,4,size);
1171 SIVAL(pdata,12,size);
1172 SIVAL(pdata,20,l);
1173 strcpy(pdata+24,fname);
1174 break;
1175 default:
1176 return(ERROR(ERRDOS,ERRunknownlevel));
1179 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1181 return(-1);
1184 /****************************************************************************
1185 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1186 ****************************************************************************/
1187 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1188 int bufsize, int cnum, char **pparams,
1189 char **ppdata, int total_data)
1191 char *params = *pparams;
1192 char *pdata = *ppdata;
1193 uint16 tran_call = SVAL(inbuf, smb_setup0);
1194 uint16 info_level;
1195 int mode=0;
1196 int size=0;
1197 struct utimbuf tvs;
1198 struct stat st;
1199 pstring fname1;
1200 char *fname;
1201 int fd = -1;
1203 if (!CAN_WRITE(cnum))
1204 return(ERROR(ERRSRV,ERRaccess));
1206 if (tran_call == TRANSACT2_SETFILEINFO) {
1207 int16 fnum = SVALS(params,0);
1208 info_level = SVAL(params,2);
1210 CHECK_FNUM(fnum,cnum);
1211 CHECK_ERROR(fnum);
1213 fname = Files[fnum].name;
1214 fd = Files[fnum].fd_ptr->fd;
1216 if(fstat(fd,&st)!=0) {
1217 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1218 return(ERROR(ERRDOS,ERRbadpath));
1220 } else {
1221 /* set path info */
1222 info_level = SVAL(params,0);
1223 fname = fname1;
1224 strcpy(fname,&params[6]);
1225 unix_convert(fname,cnum,0);
1226 if(!check_name(fname, cnum))
1227 return(ERROR(ERRDOS,ERRbadpath));
1229 if(sys_stat(fname,&st)!=0) {
1230 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1231 return(ERROR(ERRDOS,ERRbadpath));
1235 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1236 tran_call,fname,info_level,total_data));
1238 /* Realloc the parameter and data sizes */
1239 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1240 if(params == NULL)
1241 return(ERROR(ERRDOS,ERRnomem));
1243 size = st.st_size;
1244 tvs.modtime = st.st_mtime;
1245 tvs.actime = st.st_atime;
1246 mode = dos_mode(cnum,fname,&st);
1248 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1249 /* uggh, EAs for OS2 */
1250 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1251 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1253 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1255 return(-1);
1258 switch (info_level)
1260 case 1:
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 2:
1268 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1269 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1270 mode = SVAL(pdata,l1_attrFile);
1271 size = IVAL(pdata,l1_cbFile);
1272 break;
1274 case 3:
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 4:
1282 tvs.actime = make_unix_date2(pdata+8);
1283 tvs.modtime = make_unix_date2(pdata+12);
1284 size = IVAL(pdata,16);
1285 mode = IVAL(pdata,24);
1286 break;
1288 case SMB_SET_FILE_BASIC_INFO:
1289 pdata += 8; /* create time */
1290 tvs.actime = interpret_long_date(pdata); pdata += 8;
1291 tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8));
1292 pdata += 16;
1293 mode = IVAL(pdata,0);
1294 break;
1296 case SMB_SET_FILE_END_OF_FILE_INFO:
1297 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1298 return(ERROR(ERRDOS,ERRunknownlevel));
1299 size = IVAL(pdata,0);
1300 break;
1302 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1303 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1304 default:
1305 return(ERROR(ERRDOS,ERRunknownlevel));
1309 if (!tvs.actime) tvs.actime = st.st_atime;
1310 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1311 if (!size) size = st.st_size;
1313 /* Try and set the times, size and mode of this file - if they are different
1314 from the current values */
1315 if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
1316 if(sys_utime(fname, &tvs)!=0)
1317 return(ERROR(ERRDOS,ERRnoaccess));
1319 if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) {
1320 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1321 return(ERROR(ERRDOS,ERRnoaccess));
1323 if(size != st.st_size) {
1324 if (fd == -1) {
1325 fd = sys_open(fname,O_RDWR,0);
1326 if (fd == -1)
1327 return(ERROR(ERRDOS,ERRbadpath));
1328 set_filelen(fd, size);
1329 close(fd);
1330 } else {
1331 set_filelen(fd, size);
1335 SSVAL(params,0,0);
1337 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1339 return(-1);
1342 /****************************************************************************
1343 reply to a TRANS2_MKDIR (make directory with extended attributes).
1344 ****************************************************************************/
1345 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1346 int cnum, char **pparams, char **ppdata)
1348 char *params = *pparams;
1349 pstring directory;
1350 int ret = -1;
1352 if (!CAN_WRITE(cnum))
1353 return(ERROR(ERRSRV,ERRaccess));
1355 strcpy(directory, &params[4]);
1357 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1359 unix_convert(directory,cnum,0);
1360 if (check_name(directory,cnum))
1361 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1363 if(ret < 0)
1365 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1366 return(UNIXERROR(ERRDOS,ERRnoaccess));
1369 /* Realloc the parameter and data sizes */
1370 params = *pparams = Realloc(*pparams,2);
1371 if(params == NULL)
1372 return(ERROR(ERRDOS,ERRnomem));
1374 SSVAL(params,0,0);
1376 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1378 return(-1);
1381 /****************************************************************************
1382 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1383 We don't actually do this - we just send a null response.
1384 ****************************************************************************/
1385 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1386 int cnum, char **pparams, char **ppdata)
1388 static uint16 fnf_handle = 257;
1389 char *params = *pparams;
1390 uint16 info_level = SVAL(params,4);
1392 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1394 switch (info_level)
1396 case 1:
1397 case 2:
1398 break;
1399 default:
1400 return(ERROR(ERRDOS,ERRunknownlevel));
1403 /* Realloc the parameter and data sizes */
1404 params = *pparams = Realloc(*pparams,6);
1405 if(params == NULL)
1406 return(ERROR(ERRDOS,ERRnomem));
1408 SSVAL(params,0,fnf_handle);
1409 SSVAL(params,2,0); /* No changes */
1410 SSVAL(params,4,0); /* No EA errors */
1412 fnf_handle++;
1414 if(fnf_handle == 0)
1415 fnf_handle = 257;
1417 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1419 return(-1);
1422 /****************************************************************************
1423 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1424 changes). Currently this does nothing.
1425 ****************************************************************************/
1426 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1427 int cnum, char **pparams, char **ppdata)
1429 char *params = *pparams;
1431 DEBUG(3,("call_trans2findnotifynext\n"));
1433 /* Realloc the parameter and data sizes */
1434 params = *pparams = Realloc(*pparams,4);
1435 if(params == NULL)
1436 return(ERROR(ERRDOS,ERRnomem));
1438 SSVAL(params,0,0); /* No changes */
1439 SSVAL(params,2,0); /* No EA errors */
1441 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1443 return(-1);
1446 /****************************************************************************
1447 reply to a SMBfindclose (stop trans2 directory search)
1448 ****************************************************************************/
1449 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1451 int cnum;
1452 int outsize = 0;
1453 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1455 cnum = SVAL(inbuf,smb_tid);
1457 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1459 dptr_close(dptr_num);
1461 outsize = set_message(outbuf,0,0,True);
1463 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1465 return(outsize);
1468 /****************************************************************************
1469 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1470 ****************************************************************************/
1471 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1473 int cnum;
1474 int outsize = 0;
1475 int dptr_num= -1;
1477 cnum = SVAL(inbuf,smb_tid);
1478 dptr_num = SVAL(inbuf,smb_vwv0);
1480 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1482 /* We never give out valid handles for a
1483 findnotifyfirst - so any dptr_num is ok here.
1484 Just ignore it. */
1486 outsize = set_message(outbuf,0,0,True);
1488 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1490 return(outsize);
1494 /****************************************************************************
1495 reply to a SMBtranss2 - just ignore it!
1496 ****************************************************************************/
1497 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1499 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1500 return(-1);
1503 /****************************************************************************
1504 reply to a SMBtrans2
1505 ****************************************************************************/
1506 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1508 int outsize = 0;
1509 int cnum = SVAL(inbuf,smb_tid);
1510 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1511 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1512 #if 0
1513 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1514 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1515 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1516 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1517 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1518 int32 timeout = IVALS(inbuf,smb_timeout);
1519 #endif
1520 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1521 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1522 char *params = NULL, *data = NULL;
1523 int num_params, num_params_sofar, num_data, num_data_sofar;
1525 outsize = set_message(outbuf,0,0,True);
1527 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1528 is so as a sanity check */
1529 if(suwcnt != 1 )
1531 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1532 return(ERROR(ERRSRV,ERRerror));
1535 /* Allocate the space for the maximum needed parameters and data */
1536 if (total_params > 0)
1537 params = (char *)malloc(total_params);
1538 if (total_data > 0)
1539 data = (char *)malloc(total_data);
1541 if ((total_params && !params) || (total_data && !data))
1543 DEBUG(2,("Out of memory in reply_trans2\n"));
1544 return(ERROR(ERRDOS,ERRnomem));
1547 /* Copy the param and data bytes sent with this request into
1548 the params buffer */
1549 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1550 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1552 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1553 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1555 if(num_data_sofar < total_data || num_params_sofar < total_params)
1557 /* We need to send an interim response then receive the rest
1558 of the parameter/data bytes */
1559 outsize = set_message(outbuf,0,0,True);
1560 send_smb(Client,outbuf);
1562 while( num_data_sofar < total_data || num_params_sofar < total_params)
1564 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1565 CVAL(inbuf, smb_com) != SMBtranss2)
1567 outsize = set_message(outbuf,0,0,True);
1568 DEBUG(2,("Invalid secondary trans2 packet\n"));
1569 free(params);
1570 free(data);
1571 return(ERROR(ERRSRV,ERRerror));
1574 /* Revise total_params and total_data in case they have changed downwards */
1575 total_params = SVAL(inbuf, smb_tpscnt);
1576 total_data = SVAL(inbuf, smb_tdscnt);
1577 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1578 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1579 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1580 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1581 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1582 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1586 if (Protocol >= PROTOCOL_NT1) {
1587 uint16 flg2 = SVAL(outbuf,smb_flg2);
1588 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1591 /* Now we must call the relevant TRANS2 function */
1592 switch(tran_call)
1594 case TRANSACT2_OPEN:
1595 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1596 break;
1597 case TRANSACT2_FINDFIRST:
1598 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1599 break;
1600 case TRANSACT2_FINDNEXT:
1601 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1602 break;
1603 case TRANSACT2_QFSINFO:
1604 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1605 break;
1606 case TRANSACT2_SETFSINFO:
1607 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1608 break;
1609 case TRANSACT2_QPATHINFO:
1610 case TRANSACT2_QFILEINFO:
1611 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1612 break;
1613 case TRANSACT2_SETPATHINFO:
1614 case TRANSACT2_SETFILEINFO:
1615 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1616 break;
1617 case TRANSACT2_FINDNOTIFYFIRST:
1618 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1619 break;
1620 case TRANSACT2_FINDNOTIFYNEXT:
1621 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1622 break;
1623 case TRANSACT2_MKDIR:
1624 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1625 break;
1626 default:
1627 /* Error in request */
1628 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1629 if(params)
1630 free(params);
1631 if(data)
1632 free(data);
1633 return (ERROR(ERRSRV,ERRerror));
1636 /* As we do not know how many data packets will need to be
1637 returned here the various call_trans2xxxx calls
1638 must send their own. Thus a call_trans2xxx routine only
1639 returns a value other than -1 when it wants to send
1640 an error packet.
1643 if(params)
1644 free(params);
1645 if(data)
1646 free(data);
1647 return outsize; /* If a correct response was needed the call_trans2xxx
1648 calls have already sent it. If outsize != -1 then it is
1649 returning an error packet. */