mangle.c: Fixed bug that caused string to run off the end of the mangled map.
[Samba.git] / source / smbd / trans2.c
blob28bff0884377d1f2bb60cff1c786b1cd3b8b3af2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB transaction2 handling
5 Copyright (C) Jeremy Allison 1994-1997
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 max_send
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 max_send;
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 max_send minus the
75 alignment offset. */
76 useable_space = MIN(useable_space, max_send - 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;
187 BOOL bad_path = False;
189 StrnCpy(fname,pname,namelen);
191 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
192 fname,cnum,open_mode, open_attr, open_ofun, open_size));
194 /* XXXX we need to handle passed times, sattr and flags */
196 unix_convert(fname,cnum,0,&bad_path);
198 fnum = find_free_file();
199 if (fnum < 0)
200 return(ERROR(ERRSRV,ERRnofids));
202 if (!check_name(fname,cnum))
204 if((errno == ENOENT) && bad_path)
206 unix_ERR_class = ERRDOS;
207 unix_ERR_code = ERRbadpath;
209 return(UNIXERROR(ERRDOS,ERRnoaccess));
212 unixmode = unix_mode(cnum,open_attr | aARCH);
215 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
216 &rmode,&smb_action);
218 if (!Files[fnum].open)
220 if((errno == ENOENT) && bad_path)
222 unix_ERR_class = ERRDOS;
223 unix_ERR_code = ERRbadpath;
225 return(UNIXERROR(ERRDOS,ERRnoaccess));
228 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
229 close_file(fnum);
230 return(ERROR(ERRDOS,ERRnoaccess));
233 size = sbuf.st_size;
234 fmode = dos_mode(cnum,fname,&sbuf);
235 mtime = sbuf.st_mtime;
236 inode = sbuf.st_ino;
237 if (fmode & aDIR) {
238 close_file(fnum);
239 return(ERROR(ERRDOS,ERRnoaccess));
242 /* Realloc the size of parameters and data we will return */
243 params = *pparams = Realloc(*pparams, 28);
244 if(params == NULL)
245 return(ERROR(ERRDOS,ERRnomem));
247 bzero(params,28);
248 SSVAL(params,0,fnum);
249 SSVAL(params,2,fmode);
250 put_dos_date2(params,4, mtime);
251 SIVAL(params,8, size);
252 SSVAL(params,12,rmode);
254 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
255 smb_action |= (1<<15);
258 SSVAL(params,18,smb_action);
259 SIVAL(params,20,inode);
261 /* Send the required number of replies */
262 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
264 return -1;
267 /****************************************************************************
268 get a level dependent lanman2 dir entry.
269 ****************************************************************************/
270 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
271 int requires_resume_key,
272 BOOL dont_descend,char **ppdata,
273 char *base_data, int space_remaining,
274 BOOL *out_of_space,
275 int *last_name_off)
277 char *dname;
278 BOOL found = False;
279 struct stat sbuf;
280 pstring mask;
281 pstring pathreal;
282 pstring fname;
283 BOOL matched;
284 char *p, *pdata = *ppdata;
285 int reskey=0, prev_dirpos=0;
286 int mode=0;
287 uint32 size=0,len;
288 uint32 mdate=0, adate=0, cdate=0;
289 char *nameptr;
290 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
291 strequal(Connections[cnum].dirpath,".") ||
292 strequal(Connections[cnum].dirpath,"/"));
293 BOOL was_8_3;
294 int nt_extmode; /* Used for NT connections instead of mode */
295 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
297 *fname = 0;
298 *out_of_space = False;
300 if (!Connections[cnum].dirptr)
301 return(False);
303 p = strrchr(path_mask,'/');
304 if(p != NULL)
306 if(p[1] == '\0')
307 strcpy(mask,"*.*");
308 else
309 strcpy(mask, p+1);
311 else
312 strcpy(mask, path_mask);
314 while (!found)
316 /* Needed if we run out of space */
317 prev_dirpos = TellDir(Connections[cnum].dirptr);
318 dname = ReadDirName(Connections[cnum].dirptr);
320 reskey = TellDir(Connections[cnum].dirptr);
322 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
323 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
325 if (!dname)
326 return(False);
328 matched = False;
330 strcpy(fname,dname);
332 if(name_map_mangle(fname,False,SNUM(cnum)) &&
333 mask_match(fname, mask, case_sensitive, True))
335 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
336 if (dont_descend && !isdots)
337 continue;
339 if (isrootdir && isdots)
340 continue;
342 strcpy(pathreal,Connections[cnum].dirpath);
343 if(needslash)
344 strcat(pathreal,"/");
345 strcat(pathreal,dname);
346 if (sys_stat(pathreal,&sbuf) != 0)
348 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
349 continue;
352 mode = dos_mode(cnum,pathreal,&sbuf);
354 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
355 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
356 continue;
359 size = sbuf.st_size;
360 mdate = sbuf.st_mtime;
361 adate = sbuf.st_atime;
362 cdate = sbuf.st_ctime;
363 if(mode & aDIR)
364 size = 0;
366 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
368 found = True;
372 p = pdata;
373 nameptr = p;
375 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
377 switch (info_level)
379 case 1:
380 if(requires_resume_key) {
381 SIVAL(p,0,reskey);
382 p += 4;
384 put_dos_date2(p,l1_fdateCreation,cdate);
385 put_dos_date2(p,l1_fdateLastAccess,adate);
386 put_dos_date2(p,l1_fdateLastWrite,mdate);
387 SIVAL(p,l1_cbFile,size);
388 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
389 SSVAL(p,l1_attrFile,mode);
390 SCVAL(p,l1_cchName,strlen(fname));
391 strcpy(p + l1_achName, fname);
392 nameptr = p + l1_achName;
393 p += l1_achName + strlen(fname) + 1;
394 break;
396 case 2:
397 /* info_level 2 */
398 if(requires_resume_key) {
399 SIVAL(p,0,reskey);
400 p += 4;
402 put_dos_date2(p,l2_fdateCreation,cdate);
403 put_dos_date2(p,l2_fdateLastAccess,adate);
404 put_dos_date2(p,l2_fdateLastWrite,mdate);
405 SIVAL(p,l2_cbFile,size);
406 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
407 SSVAL(p,l2_attrFile,mode);
408 SIVAL(p,l2_cbList,0); /* No extended attributes */
409 SCVAL(p,l2_cchName,strlen(fname));
410 strcpy(p + l2_achName, fname);
411 nameptr = p + l2_achName;
412 p += l2_achName + strlen(fname) + 1;
413 break;
415 case 3:
416 SIVAL(p,0,reskey);
417 put_dos_date2(p,4,cdate);
418 put_dos_date2(p,8,adate);
419 put_dos_date2(p,12,mdate);
420 SIVAL(p,16,size);
421 SIVAL(p,20,ROUNDUP(size,1024));
422 SSVAL(p,24,mode);
423 SIVAL(p,26,4);
424 CVAL(p,30) = strlen(fname);
425 strcpy(p+31, fname);
426 nameptr = p+31;
427 p += 31 + strlen(fname) + 1;
428 break;
430 case 4:
431 if(requires_resume_key) {
432 SIVAL(p,0,reskey);
433 p += 4;
435 SIVAL(p,0,33+strlen(fname)+1);
436 put_dos_date2(p,4,cdate);
437 put_dos_date2(p,8,adate);
438 put_dos_date2(p,12,mdate);
439 SIVAL(p,16,size);
440 SIVAL(p,20,ROUNDUP(size,1024));
441 SSVAL(p,24,mode);
442 CVAL(p,32) = strlen(fname);
443 strcpy(p + 33, fname);
444 nameptr = p+33;
445 p += 33 + strlen(fname) + 1;
446 break;
448 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
449 was_8_3 = is_8_3(fname, True);
450 len = 94+strlen(fname);
451 len = (len + 3) & ~3;
452 SIVAL(p,0,len); p += 4;
453 SIVAL(p,0,reskey); p += 4;
454 put_long_date(p,cdate); p += 8;
455 put_long_date(p,adate); p += 8;
456 put_long_date(p,mdate); p += 8;
457 put_long_date(p,mdate); p += 8;
458 SIVAL(p,0,size); p += 8;
459 SIVAL(p,0,size); p += 8;
460 SIVAL(p,0,nt_extmode); p += 4;
461 SIVAL(p,0,strlen(fname)); p += 4;
462 SIVAL(p,0,0); p += 4;
463 if (!was_8_3) {
464 strcpy(p+2,fname);
465 if (!name_map_mangle(p+2,True,SNUM(cnum)))
466 (p+2)[12] = 0;
467 } else
468 *(p+2) = 0;
469 strupper(p+2);
470 SSVAL(p,0,strlen(p+2));
471 p += 2 + 24;
472 /* nameptr = p; */
473 strcpy(p,fname); p += strlen(p);
474 p = pdata + len;
475 break;
477 case SMB_FIND_FILE_DIRECTORY_INFO:
478 len = 64+strlen(fname);
479 len = (len + 3) & ~3;
480 SIVAL(p,0,len); p += 4;
481 SIVAL(p,0,reskey); p += 4;
482 put_long_date(p,cdate); p += 8;
483 put_long_date(p,adate); p += 8;
484 put_long_date(p,mdate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 SIVAL(p,0,size); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,nt_extmode); p += 4;
489 SIVAL(p,0,strlen(fname)); p += 4;
490 strcpy(p,fname);
491 p = pdata + len;
492 break;
495 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
496 len = 68+strlen(fname);
497 len = (len + 3) & ~3;
498 SIVAL(p,0,len); p += 4;
499 SIVAL(p,0,reskey); p += 4;
500 put_long_date(p,cdate); p += 8;
501 put_long_date(p,adate); p += 8;
502 put_long_date(p,mdate); p += 8;
503 put_long_date(p,mdate); p += 8;
504 SIVAL(p,0,size); p += 8;
505 SIVAL(p,0,size); p += 8;
506 SIVAL(p,0,nt_extmode); p += 4;
507 SIVAL(p,0,strlen(fname)); p += 4;
508 SIVAL(p,0,0); p += 4;
509 strcpy(p,fname);
510 p = pdata + len;
511 break;
513 case SMB_FIND_FILE_NAMES_INFO:
514 len = 12+strlen(fname);
515 len = (len + 3) & ~3;
516 SIVAL(p,0,len); p += 4;
517 SIVAL(p,0,reskey); p += 4;
518 SIVAL(p,0,strlen(fname)); p += 4;
519 strcpy(p,fname);
520 p = pdata + len;
521 break;
523 default:
524 return(False);
528 if (PTR_DIFF(p,pdata) > space_remaining) {
529 /* Move the dirptr back to prev_dirpos */
530 SeekDir(Connections[cnum].dirptr, prev_dirpos);
531 *out_of_space = True;
532 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
533 return False; /* Not finished - just out of space */
536 /* Setup the last_filename pointer, as an offset from base_data */
537 *last_name_off = PTR_DIFF(nameptr,base_data);
538 /* Advance the data pointer to the next slot */
539 *ppdata = p;
540 return(found);
543 /****************************************************************************
544 reply to a TRANS2_FINDFIRST
545 ****************************************************************************/
546 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
547 char **pparams, char **ppdata)
549 /* We must be careful here that we don't return more than the
550 allowed number of data bytes. If this means returning fewer than
551 maxentries then so be it. We assume that the redirector has
552 enough room for the fixed number of parameter bytes it has
553 requested. */
554 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
555 char *params = *pparams;
556 char *pdata = *ppdata;
557 int dirtype = SVAL(params,0);
558 int maxentries = SVAL(params,2);
559 BOOL close_after_first = BITSETW(params+4,0);
560 BOOL close_if_end = BITSETW(params+4,1);
561 BOOL requires_resume_key = BITSETW(params+4,2);
562 int info_level = SVAL(params,6);
563 pstring directory;
564 pstring mask;
565 char *p, *wcard;
566 int last_name_off=0;
567 int dptr_num = -1;
568 int numentries = 0;
569 int i;
570 BOOL finished = False;
571 BOOL dont_descend = False;
572 BOOL out_of_space = False;
573 int space_remaining;
574 BOOL bad_path = False;
576 *directory = *mask = 0;
578 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",
579 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
580 info_level, max_data_bytes));
582 switch (info_level)
584 case 1:
585 case 2:
586 case 3:
587 case 4:
588 case SMB_FIND_FILE_DIRECTORY_INFO:
589 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
590 case SMB_FIND_FILE_NAMES_INFO:
591 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
592 break;
593 default:
594 return(ERROR(ERRDOS,ERRunknownlevel));
597 strcpy(directory, params + 12); /* Complete directory path with
598 wildcard mask appended */
600 DEBUG(5,("path=%s\n",directory));
602 unix_convert(directory,cnum,0,&bad_path);
603 if(!check_name(directory,cnum)) {
604 if((errno == ENOENT) && bad_path)
606 unix_ERR_class = ERRDOS;
607 unix_ERR_code = ERRbadpath;
609 return(ERROR(ERRDOS,ERRbadpath));
612 p = strrchr(directory,'/');
613 if(p == NULL) {
614 strcpy(mask,directory);
615 strcpy(directory,"./");
616 } else {
617 strcpy(mask,p+1);
618 *p = 0;
621 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
623 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
624 if(!*ppdata)
625 return(ERROR(ERRDOS,ERRnomem));
626 bzero(pdata,max_data_bytes);
628 /* Realloc the params space */
629 params = *pparams = Realloc(*pparams, 10);
630 if(params == NULL)
631 return(ERROR(ERRDOS,ERRnomem));
633 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
634 if (dptr_num < 0)
636 if(dptr_num == -2)
638 if((errno == ENOENT) && bad_path)
640 unix_ERR_class = ERRDOS;
641 unix_ERR_code = ERRbadpath;
643 return (UNIXERROR(ERRDOS,ERRbadpath));
645 return(ERROR(ERRDOS,ERRbadpath));
648 /* convert the formatted masks */
650 p = mask;
651 while (*p) {
652 if (*p == '<') *p = '*';
653 if (*p == '>') *p = '?';
654 if (*p == '"') *p = '.';
655 p++;
659 /* a special case for 16 bit apps */
660 if (strequal(mask,"????????.???")) strcpy(mask,"*");
662 /* handle broken clients that send us old 8.3 format */
663 string_sub(mask,"????????","*");
664 string_sub(mask,".???",".*");
666 /* Save the wildcard match and attribs we are using on this directory -
667 needed as lanman2 assumes these are being saved between calls */
669 if(!(wcard = strdup(mask))) {
670 dptr_close(dptr_num);
671 return(ERROR(ERRDOS,ERRnomem));
674 dptr_set_wcard(dptr_num, wcard);
675 dptr_set_attr(dptr_num, dirtype);
677 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
679 /* We don't need to check for VOL here as this is returned by
680 a different TRANS2 call. */
682 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
683 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
684 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
685 dont_descend = True;
687 p = pdata;
688 space_remaining = max_data_bytes;
689 out_of_space = False;
691 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
694 /* this is a heuristic to avoid seeking the dirptr except when
695 absolutely necessary. It allows for a filename of about 40 chars */
696 if (space_remaining < DIRLEN_GUESS && numentries > 0)
698 out_of_space = True;
699 finished = False;
701 else
703 finished =
704 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
705 requires_resume_key,dont_descend,
706 &p,pdata,space_remaining, &out_of_space,
707 &last_name_off);
710 if (finished && out_of_space)
711 finished = False;
713 if (!finished && !out_of_space)
714 numentries++;
715 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
718 /* Check if we can close the dirptr */
719 if(close_after_first || (finished && close_if_end))
721 dptr_close(dptr_num);
722 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
723 dptr_num = -1;
726 /* At this point pdata points to numentries directory entries. */
728 /* Set up the return parameter block */
729 SSVAL(params,0,dptr_num);
730 SSVAL(params,2,numentries);
731 SSVAL(params,4,finished);
732 SSVAL(params,6,0); /* Never an EA error */
733 SSVAL(params,8,last_name_off);
735 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
737 if ((! *directory) && dptr_path(dptr_num))
738 sprintf(directory,"(%s)",dptr_path(dptr_num));
740 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
741 timestring(),
742 smb_fn_name(CVAL(inbuf,smb_com)),
743 mask,directory,cnum,dirtype,numentries));
745 return(-1);
749 /****************************************************************************
750 reply to a TRANS2_FINDNEXT
751 ****************************************************************************/
752 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
753 int cnum, char **pparams, char **ppdata)
755 /* We must be careful here that we don't return more than the
756 allowed number of data bytes. If this means returning fewer than
757 maxentries then so be it. We assume that the redirector has
758 enough room for the fixed number of parameter bytes it has
759 requested. */
760 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
761 char *params = *pparams;
762 char *pdata = *ppdata;
763 int16 dptr_num = SVAL(params,0);
764 int maxentries = SVAL(params,2);
765 uint16 info_level = SVAL(params,4);
766 uint32 resume_key = IVAL(params,6);
767 BOOL close_after_request = BITSETW(params+10,0);
768 BOOL close_if_end = BITSETW(params+10,1);
769 BOOL requires_resume_key = BITSETW(params+10,2);
770 BOOL continue_bit = BITSETW(params+10,3);
771 pstring mask;
772 pstring directory;
773 char *p;
774 uint16 dirtype;
775 int numentries = 0;
776 int i, last_name_off=0;
777 BOOL finished = False;
778 BOOL dont_descend = False;
779 BOOL out_of_space = False;
780 int space_remaining;
782 *mask = *directory = 0;
784 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",
785 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
786 requires_resume_key, resume_key, continue_bit, info_level));
788 switch (info_level)
790 case 1:
791 case 2:
792 case 3:
793 case 4:
794 case SMB_FIND_FILE_DIRECTORY_INFO:
795 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
796 case SMB_FIND_FILE_NAMES_INFO:
797 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
798 break;
799 default:
800 return(ERROR(ERRDOS,ERRunknownlevel));
803 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
804 if(!*ppdata)
805 return(ERROR(ERRDOS,ERRnomem));
806 bzero(pdata,max_data_bytes);
808 /* Realloc the params space */
809 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
810 if(!params)
811 return(ERROR(ERRDOS,ERRnomem));
813 /* Check that the dptr is valid */
814 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
815 return(ERROR(ERRDOS,ERRnofiles));
817 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
819 /* Get the wildcard mask from the dptr */
820 if((p = dptr_wcard(dptr_num))== NULL) {
821 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
822 return (ERROR(ERRDOS,ERRnofiles));
824 strcpy(mask, p);
825 strcpy(directory,Connections[cnum].dirpath);
827 /* Get the attr mask from the dptr */
828 dirtype = dptr_attr(dptr_num);
830 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
831 dptr_num, mask, dirtype,
832 Connections[cnum].dirptr,
833 TellDir(Connections[cnum].dirptr)));
835 /* We don't need to check for VOL here as this is returned by
836 a different TRANS2 call. */
838 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
839 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
840 dont_descend = True;
842 p = pdata;
843 space_remaining = max_data_bytes;
844 out_of_space = False;
846 /* If we have a resume key - seek to the correct position. */
847 if(requires_resume_key && !continue_bit)
848 SeekDir(Connections[cnum].dirptr, resume_key);
850 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
852 /* this is a heuristic to avoid seeking the dirptr except when
853 absolutely necessary. It allows for a filename of about 40 chars */
854 if (space_remaining < DIRLEN_GUESS && numentries > 0)
856 out_of_space = True;
857 finished = False;
859 else
861 finished =
862 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
863 requires_resume_key,dont_descend,
864 &p,pdata,space_remaining, &out_of_space,
865 &last_name_off);
868 if (finished && out_of_space)
869 finished = False;
871 if (!finished && !out_of_space)
872 numentries++;
873 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
876 /* Check if we can close the dirptr */
877 if(close_after_request || (finished && close_if_end))
879 dptr_close(dptr_num); /* This frees up the saved mask */
880 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
881 dptr_num = -1;
885 /* Set up the return parameter block */
886 SSVAL(params,0,numentries);
887 SSVAL(params,2,finished);
888 SSVAL(params,4,0); /* Never an EA error */
889 SSVAL(params,6,last_name_off);
891 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
893 if ((! *directory) && dptr_path(dptr_num))
894 sprintf(directory,"(%s)",dptr_path(dptr_num));
896 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
897 timestring(),
898 smb_fn_name(CVAL(inbuf,smb_com)),
899 mask,directory,cnum,dirtype,numentries));
901 return(-1);
904 /****************************************************************************
905 reply to a TRANS2_QFSINFO (query filesystem info)
906 ****************************************************************************/
907 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
908 int cnum, char **pparams, char **ppdata)
910 char *pdata = *ppdata;
911 char *params = *pparams;
912 uint16 info_level = SVAL(params,0);
913 int data_len;
914 struct stat st;
915 char *vname = volume_label(SNUM(cnum));
917 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
919 if(sys_stat(".",&st)!=0) {
920 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
921 return (ERROR(ERRSRV,ERRinvdevice));
924 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
926 switch (info_level)
928 case 1:
930 int dfree,dsize,bsize;
931 data_len = 18;
932 sys_disk_free(".",&bsize,&dfree,&dsize);
933 SIVAL(pdata,l1_idFileSystem,st.st_dev);
934 SIVAL(pdata,l1_cSectorUnit,bsize/512);
935 SIVAL(pdata,l1_cUnit,dsize);
936 SIVAL(pdata,l1_cUnitAvail,dfree);
937 SSVAL(pdata,l1_cbSector,512);
938 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
939 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
940 break;
942 case 2:
944 /* Return volume name */
945 int volname_len = MIN(strlen(vname),11);
946 data_len = l2_vol_szVolLabel + volname_len + 1;
947 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
948 SCVAL(pdata,l2_vol_cch,volname_len);
949 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
950 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
951 pdata+l2_vol_szVolLabel));
952 break;
954 case SMB_QUERY_FS_ATTRIBUTE_INFO:
955 data_len = 12 + 2*strlen(FSTYPE_STRING);
956 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
957 SIVAL(pdata,4,128); /* Max filename component length */
958 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
959 PutUniCode(pdata+12,FSTYPE_STRING);
960 break;
961 case SMB_QUERY_FS_LABEL_INFO:
962 data_len = 4 + strlen(vname);
963 SIVAL(pdata,0,strlen(vname));
964 strcpy(pdata+4,vname);
965 break;
966 case SMB_QUERY_FS_VOLUME_INFO:
967 data_len = 18 + 2*strlen(vname);
968 SIVAL(pdata,12,2*strlen(vname));
969 PutUniCode(pdata+18,vname);
970 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
971 vname));
972 break;
973 case SMB_QUERY_FS_SIZE_INFO:
975 int dfree,dsize,bsize;
976 data_len = 24;
977 sys_disk_free(".",&bsize,&dfree,&dsize);
978 SIVAL(pdata,0,dsize);
979 SIVAL(pdata,8,dfree);
980 SIVAL(pdata,16,bsize/512);
981 SIVAL(pdata,20,512);
983 break;
984 case SMB_QUERY_FS_DEVICE_INFO:
985 data_len = 8;
986 SIVAL(pdata,0,0); /* dev type */
987 SIVAL(pdata,4,0); /* characteristics */
988 break;
989 default:
990 return(ERROR(ERRDOS,ERRunknownlevel));
994 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
996 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
998 return -1;
1001 /****************************************************************************
1002 reply to a TRANS2_SETFSINFO (set filesystem info)
1003 ****************************************************************************/
1004 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1005 int cnum, char **pparams, char **ppdata)
1007 /* Just say yes we did it - there is nothing that
1008 can be set here so it doesn't matter. */
1009 int outsize;
1010 DEBUG(3,("call_trans2setfsinfo\n"));
1012 if (!CAN_WRITE(cnum))
1013 return(ERROR(ERRSRV,ERRaccess));
1015 outsize = set_message(outbuf,10,0,True);
1017 return outsize;
1020 /****************************************************************************
1021 reply to a TRANS2_QFILEINFO (query file info by fileid)
1022 ****************************************************************************/
1023 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1024 int bufsize,int cnum,
1025 char **pparams,char **ppdata,
1026 int total_data)
1028 char *params = *pparams;
1029 char *pdata = *ppdata;
1030 uint16 tran_call = SVAL(inbuf, smb_setup0);
1031 uint16 info_level;
1032 int mode=0;
1033 int size=0;
1034 unsigned int data_size;
1035 struct stat sbuf;
1036 pstring fname1;
1037 char *fname;
1038 char *p;
1039 int l,pos;
1040 BOOL bad_path = False;
1042 if (tran_call == TRANSACT2_QFILEINFO) {
1043 int16 fnum = SVALS(params,0);
1044 info_level = SVAL(params,2);
1046 CHECK_FNUM(fnum,cnum);
1047 CHECK_ERROR(fnum);
1049 fname = Files[fnum].name;
1050 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1051 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1052 return(UNIXERROR(ERRDOS,ERRbadfid));
1054 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1055 } else {
1056 /* qpathinfo */
1057 info_level = SVAL(params,0);
1058 fname = &fname1[0];
1059 strcpy(fname,&params[6]);
1060 unix_convert(fname,cnum,0,&bad_path);
1061 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1062 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1063 if((errno == ENOENT) && bad_path)
1065 unix_ERR_class = ERRDOS;
1066 unix_ERR_code = ERRbadpath;
1068 return(UNIXERROR(ERRDOS,ERRbadpath));
1070 pos = 0;
1074 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1075 fname,info_level,tran_call,total_data));
1077 p = strrchr(fname,'/');
1078 if (!p)
1079 p = fname;
1080 else
1081 p++;
1082 l = strlen(p);
1083 mode = dos_mode(cnum,fname,&sbuf);
1084 size = sbuf.st_size;
1085 if (mode & aDIR) size = 0;
1087 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1088 data_size = 1024;
1089 pdata = *ppdata = Realloc(*ppdata, data_size);
1091 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1092 /* uggh, EAs for OS2 */
1093 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1094 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1097 bzero(pdata,data_size);
1099 switch (info_level)
1101 case SMB_INFO_STANDARD:
1102 case SMB_INFO_QUERY_EA_SIZE:
1103 data_size = (info_level==1?22:26);
1104 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1105 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1106 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1107 SIVAL(pdata,l1_cbFile,size);
1108 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1109 SSVAL(pdata,l1_attrFile,mode);
1110 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1111 break;
1113 case SMB_INFO_QUERY_EAS_FROM_LIST:
1114 data_size = 24;
1115 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1116 put_dos_date2(pdata,4,sbuf.st_atime);
1117 put_dos_date2(pdata,8,sbuf.st_mtime);
1118 SIVAL(pdata,12,size);
1119 SIVAL(pdata,16,ROUNDUP(size,1024));
1120 SIVAL(pdata,20,mode);
1121 break;
1123 case SMB_INFO_QUERY_ALL_EAS:
1124 data_size = 4;
1125 SIVAL(pdata,0,data_size);
1126 break;
1128 case 6:
1129 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1131 case SMB_QUERY_FILE_BASIC_INFO:
1132 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1133 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1134 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1135 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1136 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1137 SIVAL(pdata,32,mode);
1139 DEBUG(5,("SMB_QFBI - "));
1140 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1141 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1142 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1143 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1144 DEBUG(5,("mode: %x\n", mode));
1146 break;
1148 case SMB_QUERY_FILE_STANDARD_INFO:
1149 data_size = 22;
1150 SIVAL(pdata,0,size);
1151 SIVAL(pdata,8,size);
1152 SIVAL(pdata,16,sbuf.st_nlink);
1153 CVAL(pdata,20) = 0;
1154 CVAL(pdata,21) = (mode&aDIR)?1:0;
1155 break;
1157 case SMB_QUERY_FILE_EA_INFO:
1158 data_size = 4;
1159 break;
1161 case SMB_QUERY_FILE_NAME_INFO:
1162 case SMB_QUERY_FILE_ALT_NAME_INFO:
1163 data_size = 4 + l;
1164 SIVAL(pdata,0,l);
1165 strcpy(pdata+4,fname);
1166 break;
1167 case SMB_QUERY_FILE_ALLOCATION_INFO:
1168 case SMB_QUERY_FILE_END_OF_FILEINFO:
1169 data_size = 8;
1170 SIVAL(pdata,0,size);
1171 break;
1173 case SMB_QUERY_FILE_ALL_INFO:
1174 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1175 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1176 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1177 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1178 SIVAL(pdata,32,mode);
1179 pdata += 40;
1180 SIVAL(pdata,0,size);
1181 SIVAL(pdata,8,size);
1182 SIVAL(pdata,16,sbuf.st_nlink);
1183 CVAL(pdata,20) = 0;
1184 CVAL(pdata,21) = (mode&aDIR)?1:0;
1185 pdata += 24;
1186 pdata += 8; /* index number */
1187 pdata += 4; /* EA info */
1188 if (mode & aRONLY)
1189 SIVAL(pdata,0,0xA9);
1190 else
1191 SIVAL(pdata,0,0xd01BF);
1192 pdata += 4;
1193 SIVAL(pdata,0,pos); /* current offset */
1194 pdata += 8;
1195 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1196 pdata += 4;
1197 pdata += 4; /* alignment */
1198 SIVAL(pdata,0,l);
1199 strcpy(pdata+4,fname);
1200 pdata += 4 + l;
1201 data_size = PTR_DIFF(pdata,(*ppdata));
1202 break;
1204 case SMB_QUERY_FILE_STREAM_INFO:
1205 data_size = 24 + l;
1206 SIVAL(pdata,0,pos);
1207 SIVAL(pdata,4,size);
1208 SIVAL(pdata,12,size);
1209 SIVAL(pdata,20,l);
1210 strcpy(pdata+24,fname);
1211 break;
1212 default:
1213 return(ERROR(ERRDOS,ERRunknownlevel));
1216 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1218 return(-1);
1221 /****************************************************************************
1222 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1223 ****************************************************************************/
1224 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1225 int bufsize, int cnum, char **pparams,
1226 char **ppdata, int total_data)
1228 char *params = *pparams;
1229 char *pdata = *ppdata;
1230 uint16 tran_call = SVAL(inbuf, smb_setup0);
1231 uint16 info_level;
1232 int mode=0;
1233 int size=0;
1234 struct utimbuf tvs;
1235 struct stat st;
1236 pstring fname1;
1237 char *fname;
1238 int fd = -1;
1239 BOOL bad_path = False;
1241 if (!CAN_WRITE(cnum))
1242 return(ERROR(ERRSRV,ERRaccess));
1244 if (tran_call == TRANSACT2_SETFILEINFO) {
1245 int16 fnum = SVALS(params,0);
1246 info_level = SVAL(params,2);
1248 CHECK_FNUM(fnum,cnum);
1249 CHECK_ERROR(fnum);
1251 fname = Files[fnum].name;
1252 fd = Files[fnum].fd_ptr->fd;
1254 if(fstat(fd,&st)!=0) {
1255 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1256 return(ERROR(ERRDOS,ERRbadpath));
1258 } else {
1259 /* set path info */
1260 info_level = SVAL(params,0);
1261 fname = fname1;
1262 strcpy(fname,&params[6]);
1263 unix_convert(fname,cnum,0,&bad_path);
1264 if(!check_name(fname, cnum))
1266 if((errno == ENOENT) && bad_path)
1268 unix_ERR_class = ERRDOS;
1269 unix_ERR_code = ERRbadpath;
1271 return(UNIXERROR(ERRDOS,ERRbadpath));
1274 if(sys_stat(fname,&st)!=0) {
1275 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1276 if((errno == ENOENT) && bad_path)
1278 unix_ERR_class = ERRDOS;
1279 unix_ERR_code = ERRbadpath;
1281 return(UNIXERROR(ERRDOS,ERRbadpath));
1285 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1286 tran_call,fname,info_level,total_data));
1288 /* Realloc the parameter and data sizes */
1289 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1290 if(params == NULL)
1291 return(ERROR(ERRDOS,ERRnomem));
1293 size = st.st_size;
1294 tvs.modtime = st.st_mtime;
1295 tvs.actime = st.st_atime;
1296 mode = dos_mode(cnum,fname,&st);
1298 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1299 /* uggh, EAs for OS2 */
1300 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1301 #ifdef OS2_WPS_FIX /* This may become the main code stream in a later release */
1302 return(ERROR(ERRDOS,ERRcannotopen));
1303 #else /* OS2_WPS_FIX */
1304 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1305 #endif /* OS2_WPS_FIX */
1308 switch (info_level)
1310 case SMB_INFO_STANDARD:
1311 case SMB_INFO_QUERY_EA_SIZE:
1313 /* access time */
1314 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1316 /* write time */
1317 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1319 mode = SVAL(pdata,l1_attrFile);
1320 size = IVAL(pdata,l1_cbFile);
1321 break;
1324 /* XXXX um, i don't think this is right.
1325 it's also not in the cifs6.txt spec.
1327 case SMB_INFO_QUERY_EAS_FROM_LIST:
1328 tvs.actime = make_unix_date2(pdata+8);
1329 tvs.modtime = make_unix_date2(pdata+12);
1330 size = IVAL(pdata,16);
1331 mode = IVAL(pdata,24);
1332 break;
1334 /* XXXX nor this. not in cifs6.txt, either. */
1335 case SMB_INFO_QUERY_ALL_EAS:
1336 tvs.actime = make_unix_date2(pdata+8);
1337 tvs.modtime = make_unix_date2(pdata+12);
1338 size = IVAL(pdata,16);
1339 mode = IVAL(pdata,24);
1340 break;
1342 case SMB_SET_FILE_BASIC_INFO:
1344 /* Ignore create time at offset pdata. */
1346 /* access time */
1347 tvs.actime = interpret_long_date(pdata+8);
1349 /* write time + changed time, combined. */
1350 tvs.modtime=MAX(interpret_long_date(pdata+16),
1351 interpret_long_date(pdata+24));
1353 /* attributes */
1354 mode = IVAL(pdata,32);
1355 break;
1358 case SMB_SET_FILE_END_OF_FILE_INFO:
1360 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1361 return(ERROR(ERRDOS,ERRunknownlevel));
1362 size = IVAL(pdata,0);
1363 break;
1366 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1367 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1368 default:
1370 return(ERROR(ERRDOS,ERRunknownlevel));
1374 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1375 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1376 DEBUG(6,("size: %x " , size));
1377 DEBUG(6,("mode: %x\n" , mode));
1379 /* get some defaults (no modifications) if any info is zero. */
1380 if (!tvs.actime) tvs.actime = st.st_atime;
1381 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1382 if (!size) size = st.st_size;
1384 /* Try and set the times, size and mode of this file -
1385 if they are different from the current values
1387 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1389 if(sys_utime(fname, &tvs)!=0)
1391 return(ERROR(ERRDOS,ERRnoaccess));
1395 /* check the mode isn't different, before changing it */
1396 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1398 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1399 return(ERROR(ERRDOS,ERRnoaccess));
1402 if(size != st.st_size)
1404 if (fd == -1)
1406 fd = sys_open(fname,O_RDWR,0);
1407 if (fd == -1)
1409 return(ERROR(ERRDOS,ERRbadpath));
1411 set_filelen(fd, size);
1412 close(fd);
1414 else
1416 set_filelen(fd, size);
1420 SSVAL(params,0,0);
1422 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1424 return(-1);
1427 /****************************************************************************
1428 reply to a TRANS2_MKDIR (make directory with extended attributes).
1429 ****************************************************************************/
1430 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1431 int cnum, char **pparams, char **ppdata)
1433 char *params = *pparams;
1434 pstring directory;
1435 int ret = -1;
1436 BOOL bad_path = False;
1438 if (!CAN_WRITE(cnum))
1439 return(ERROR(ERRSRV,ERRaccess));
1441 strcpy(directory, &params[4]);
1443 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1445 unix_convert(directory,cnum,0,&bad_path);
1446 if (check_name(directory,cnum))
1447 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1449 if(ret < 0)
1451 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1452 if((errno == ENOENT) && bad_path)
1454 unix_ERR_class = ERRDOS;
1455 unix_ERR_code = ERRbadpath;
1457 return(UNIXERROR(ERRDOS,ERRnoaccess));
1460 /* Realloc the parameter and data sizes */
1461 params = *pparams = Realloc(*pparams,2);
1462 if(params == NULL)
1463 return(ERROR(ERRDOS,ERRnomem));
1465 SSVAL(params,0,0);
1467 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1469 return(-1);
1472 /****************************************************************************
1473 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1474 We don't actually do this - we just send a null response.
1475 ****************************************************************************/
1476 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1477 int cnum, char **pparams, char **ppdata)
1479 static uint16 fnf_handle = 257;
1480 char *params = *pparams;
1481 uint16 info_level = SVAL(params,4);
1483 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1485 switch (info_level)
1487 case 1:
1488 case 2:
1489 break;
1490 default:
1491 return(ERROR(ERRDOS,ERRunknownlevel));
1494 /* Realloc the parameter and data sizes */
1495 params = *pparams = Realloc(*pparams,6);
1496 if(params == NULL)
1497 return(ERROR(ERRDOS,ERRnomem));
1499 SSVAL(params,0,fnf_handle);
1500 SSVAL(params,2,0); /* No changes */
1501 SSVAL(params,4,0); /* No EA errors */
1503 fnf_handle++;
1505 if(fnf_handle == 0)
1506 fnf_handle = 257;
1508 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1510 return(-1);
1513 /****************************************************************************
1514 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1515 changes). Currently this does nothing.
1516 ****************************************************************************/
1517 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1518 int cnum, char **pparams, char **ppdata)
1520 char *params = *pparams;
1522 DEBUG(3,("call_trans2findnotifynext\n"));
1524 /* Realloc the parameter and data sizes */
1525 params = *pparams = Realloc(*pparams,4);
1526 if(params == NULL)
1527 return(ERROR(ERRDOS,ERRnomem));
1529 SSVAL(params,0,0); /* No changes */
1530 SSVAL(params,2,0); /* No EA errors */
1532 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1534 return(-1);
1537 /****************************************************************************
1538 reply to a SMBfindclose (stop trans2 directory search)
1539 ****************************************************************************/
1540 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1542 int cnum;
1543 int outsize = 0;
1544 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1546 cnum = SVAL(inbuf,smb_tid);
1548 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1550 dptr_close(dptr_num);
1552 outsize = set_message(outbuf,0,0,True);
1554 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1556 return(outsize);
1559 /****************************************************************************
1560 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1561 ****************************************************************************/
1562 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1564 int cnum;
1565 int outsize = 0;
1566 int dptr_num= -1;
1568 cnum = SVAL(inbuf,smb_tid);
1569 dptr_num = SVAL(inbuf,smb_vwv0);
1571 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1573 /* We never give out valid handles for a
1574 findnotifyfirst - so any dptr_num is ok here.
1575 Just ignore it. */
1577 outsize = set_message(outbuf,0,0,True);
1579 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1581 return(outsize);
1585 /****************************************************************************
1586 reply to a SMBtranss2 - just ignore it!
1587 ****************************************************************************/
1588 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1590 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1591 return(-1);
1594 /****************************************************************************
1595 reply to a SMBtrans2
1596 ****************************************************************************/
1597 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1599 int outsize = 0;
1600 int cnum = SVAL(inbuf,smb_tid);
1601 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1602 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1603 #if 0
1604 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1605 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1606 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1607 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1608 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1609 int32 timeout = IVALS(inbuf,smb_timeout);
1610 #endif
1611 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1612 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1613 char *params = NULL, *data = NULL;
1614 int num_params, num_params_sofar, num_data, num_data_sofar;
1616 outsize = set_message(outbuf,0,0,True);
1618 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1619 is so as a sanity check */
1620 if(suwcnt != 1 )
1622 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1623 return(ERROR(ERRSRV,ERRerror));
1626 /* Allocate the space for the maximum needed parameters and data */
1627 if (total_params > 0)
1628 params = (char *)malloc(total_params);
1629 if (total_data > 0)
1630 data = (char *)malloc(total_data);
1632 if ((total_params && !params) || (total_data && !data))
1634 DEBUG(2,("Out of memory in reply_trans2\n"));
1635 return(ERROR(ERRDOS,ERRnomem));
1638 /* Copy the param and data bytes sent with this request into
1639 the params buffer */
1640 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1641 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1643 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1644 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1646 if(num_data_sofar < total_data || num_params_sofar < total_params)
1648 /* We need to send an interim response then receive the rest
1649 of the parameter/data bytes */
1650 outsize = set_message(outbuf,0,0,True);
1651 send_smb(Client,outbuf);
1653 while( num_data_sofar < total_data || num_params_sofar < total_params)
1655 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1656 CVAL(inbuf, smb_com) != SMBtranss2)
1658 outsize = set_message(outbuf,0,0,True);
1659 DEBUG(2,("Invalid secondary trans2 packet\n"));
1660 free(params);
1661 free(data);
1662 return(ERROR(ERRSRV,ERRerror));
1665 /* Revise total_params and total_data in case they have changed downwards */
1666 total_params = SVAL(inbuf, smb_tpscnt);
1667 total_data = SVAL(inbuf, smb_tdscnt);
1668 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1669 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1670 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1671 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1672 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1673 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1677 if (Protocol >= PROTOCOL_NT1) {
1678 uint16 flg2 = SVAL(outbuf,smb_flg2);
1679 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1682 /* Now we must call the relevant TRANS2 function */
1683 switch(tran_call)
1685 case TRANSACT2_OPEN:
1686 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1687 break;
1688 case TRANSACT2_FINDFIRST:
1689 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1690 break;
1691 case TRANSACT2_FINDNEXT:
1692 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1693 break;
1694 case TRANSACT2_QFSINFO:
1695 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1696 break;
1697 case TRANSACT2_SETFSINFO:
1698 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1699 break;
1700 case TRANSACT2_QPATHINFO:
1701 case TRANSACT2_QFILEINFO:
1702 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1703 break;
1704 case TRANSACT2_SETPATHINFO:
1705 case TRANSACT2_SETFILEINFO:
1706 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1707 break;
1708 case TRANSACT2_FINDNOTIFYFIRST:
1709 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1710 break;
1711 case TRANSACT2_FINDNOTIFYNEXT:
1712 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1713 break;
1714 case TRANSACT2_MKDIR:
1715 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1716 break;
1717 default:
1718 /* Error in request */
1719 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1720 if(params)
1721 free(params);
1722 if(data)
1723 free(data);
1724 return (ERROR(ERRSRV,ERRerror));
1727 /* As we do not know how many data packets will need to be
1728 returned here the various call_trans2xxxx calls
1729 must send their own. Thus a call_trans2xxx routine only
1730 returns a value other than -1 when it wants to send
1731 an error packet.
1734 if(params)
1735 free(params);
1736 if(data)
1737 free(data);
1738 return outsize; /* If a correct response was needed the call_trans2xxx
1739 calls have already sent it. If outsize != -1 then it is
1740 returning an error packet. */