This is the ubiqx binary tree and linked list library.
[Samba.git] / source / smbd / trans2.c
bloba56df9cb9cc68f03a4ed6017eb289f8bf4a2c4fe
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 = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>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 oplock_request, &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 |= EXTENDED_OPLOCK_GRANTED;
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 pstrcpy(mask, p+1);
311 else
312 pstrcpy(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(8,("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 pstrcpy(fname,dname);
332 if(mask_match(fname, mask, case_sensitive, True))
334 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
335 if (dont_descend && !isdots)
336 continue;
338 if (isrootdir && isdots)
339 continue;
341 pstrcpy(pathreal,Connections[cnum].dirpath);
342 if(needslash)
343 strcat(pathreal,"/");
344 strcat(pathreal,dname);
345 if (sys_stat(pathreal,&sbuf) != 0)
347 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
348 continue;
351 mode = dos_mode(cnum,pathreal,&sbuf);
353 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
354 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
355 continue;
358 size = sbuf.st_size;
359 mdate = sbuf.st_mtime;
360 adate = sbuf.st_atime;
361 cdate = sbuf.st_ctime;
362 if(mode & aDIR)
363 size = 0;
365 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
367 found = True;
371 name_map_mangle(fname,False,SNUM(cnum));
373 p = pdata;
374 nameptr = p;
376 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
378 switch (info_level)
380 case 1:
381 if(requires_resume_key) {
382 SIVAL(p,0,reskey);
383 p += 4;
385 put_dos_date2(p,l1_fdateCreation,cdate);
386 put_dos_date2(p,l1_fdateLastAccess,adate);
387 put_dos_date2(p,l1_fdateLastWrite,mdate);
388 SIVAL(p,l1_cbFile,size);
389 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
390 SSVAL(p,l1_attrFile,mode);
391 SCVAL(p,l1_cchName,strlen(fname));
392 strcpy(p + l1_achName, fname);
393 nameptr = p + l1_achName;
394 p += l1_achName + strlen(fname) + 1;
395 break;
397 case 2:
398 /* info_level 2 */
399 if(requires_resume_key) {
400 SIVAL(p,0,reskey);
401 p += 4;
403 put_dos_date2(p,l2_fdateCreation,cdate);
404 put_dos_date2(p,l2_fdateLastAccess,adate);
405 put_dos_date2(p,l2_fdateLastWrite,mdate);
406 SIVAL(p,l2_cbFile,size);
407 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
408 SSVAL(p,l2_attrFile,mode);
409 SIVAL(p,l2_cbList,0); /* No extended attributes */
410 SCVAL(p,l2_cchName,strlen(fname));
411 strcpy(p + l2_achName, fname);
412 nameptr = p + l2_achName;
413 p += l2_achName + strlen(fname) + 1;
414 break;
416 case 3:
417 SIVAL(p,0,reskey);
418 put_dos_date2(p,4,cdate);
419 put_dos_date2(p,8,adate);
420 put_dos_date2(p,12,mdate);
421 SIVAL(p,16,size);
422 SIVAL(p,20,ROUNDUP(size,1024));
423 SSVAL(p,24,mode);
424 SIVAL(p,26,4);
425 CVAL(p,30) = strlen(fname);
426 strcpy(p+31, fname);
427 nameptr = p+31;
428 p += 31 + strlen(fname) + 1;
429 break;
431 case 4:
432 if(requires_resume_key) {
433 SIVAL(p,0,reskey);
434 p += 4;
436 SIVAL(p,0,33+strlen(fname)+1);
437 put_dos_date2(p,4,cdate);
438 put_dos_date2(p,8,adate);
439 put_dos_date2(p,12,mdate);
440 SIVAL(p,16,size);
441 SIVAL(p,20,ROUNDUP(size,1024));
442 SSVAL(p,24,mode);
443 CVAL(p,32) = strlen(fname);
444 strcpy(p + 33, fname);
445 nameptr = p+33;
446 p += 33 + strlen(fname) + 1;
447 break;
449 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
450 was_8_3 = is_8_3(fname, True);
451 len = 94+strlen(fname);
452 len = (len + 3) & ~3;
453 SIVAL(p,0,len); p += 4;
454 SIVAL(p,0,reskey); p += 4;
455 put_long_date(p,cdate); p += 8;
456 put_long_date(p,adate); p += 8;
457 put_long_date(p,mdate); p += 8;
458 put_long_date(p,mdate); p += 8;
459 SIVAL(p,0,size); p += 8;
460 SIVAL(p,0,size); p += 8;
461 SIVAL(p,0,nt_extmode); p += 4;
462 SIVAL(p,0,strlen(fname)); p += 4;
463 SIVAL(p,0,0); p += 4;
464 if (!was_8_3) {
465 strcpy(p+2,fname);
466 if (!name_map_mangle(p+2,True,SNUM(cnum)))
467 (p+2)[12] = 0;
468 } else
469 *(p+2) = 0;
470 strupper(p+2);
471 SSVAL(p,0,strlen(p+2));
472 p += 2 + 24;
473 /* nameptr = p; */
474 strcpy(p,fname); p += strlen(p);
475 p = pdata + len;
476 break;
478 case SMB_FIND_FILE_DIRECTORY_INFO:
479 len = 64+strlen(fname);
480 len = (len + 3) & ~3;
481 SIVAL(p,0,len); p += 4;
482 SIVAL(p,0,reskey); p += 4;
483 put_long_date(p,cdate); p += 8;
484 put_long_date(p,adate); p += 8;
485 put_long_date(p,mdate); p += 8;
486 put_long_date(p,mdate); p += 8;
487 SIVAL(p,0,size); p += 8;
488 SIVAL(p,0,size); p += 8;
489 SIVAL(p,0,nt_extmode); p += 4;
490 SIVAL(p,0,strlen(fname)); p += 4;
491 strcpy(p,fname);
492 p = pdata + len;
493 break;
496 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
497 len = 68+strlen(fname);
498 len = (len + 3) & ~3;
499 SIVAL(p,0,len); p += 4;
500 SIVAL(p,0,reskey); p += 4;
501 put_long_date(p,cdate); p += 8;
502 put_long_date(p,adate); p += 8;
503 put_long_date(p,mdate); p += 8;
504 put_long_date(p,mdate); p += 8;
505 SIVAL(p,0,size); p += 8;
506 SIVAL(p,0,size); p += 8;
507 SIVAL(p,0,nt_extmode); p += 4;
508 SIVAL(p,0,strlen(fname)); p += 4;
509 SIVAL(p,0,0); p += 4;
510 strcpy(p,fname);
511 p = pdata + len;
512 break;
514 case SMB_FIND_FILE_NAMES_INFO:
515 len = 12+strlen(fname);
516 len = (len + 3) & ~3;
517 SIVAL(p,0,len); p += 4;
518 SIVAL(p,0,reskey); p += 4;
519 SIVAL(p,0,strlen(fname)); p += 4;
520 strcpy(p,fname);
521 p = pdata + len;
522 break;
524 default:
525 return(False);
529 if (PTR_DIFF(p,pdata) > space_remaining) {
530 /* Move the dirptr back to prev_dirpos */
531 SeekDir(Connections[cnum].dirptr, prev_dirpos);
532 *out_of_space = True;
533 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
534 return False; /* Not finished - just out of space */
537 /* Setup the last_filename pointer, as an offset from base_data */
538 *last_name_off = PTR_DIFF(nameptr,base_data);
539 /* Advance the data pointer to the next slot */
540 *ppdata = p;
541 return(found);
544 /****************************************************************************
545 reply to a TRANS2_FINDFIRST
546 ****************************************************************************/
547 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
548 char **pparams, char **ppdata)
550 /* We must be careful here that we don't return more than the
551 allowed number of data bytes. If this means returning fewer than
552 maxentries then so be it. We assume that the redirector has
553 enough room for the fixed number of parameter bytes it has
554 requested. */
555 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
556 char *params = *pparams;
557 char *pdata = *ppdata;
558 int dirtype = SVAL(params,0);
559 int maxentries = SVAL(params,2);
560 BOOL close_after_first = BITSETW(params+4,0);
561 BOOL close_if_end = BITSETW(params+4,1);
562 BOOL requires_resume_key = BITSETW(params+4,2);
563 int info_level = SVAL(params,6);
564 pstring directory;
565 pstring mask;
566 char *p, *wcard;
567 int last_name_off=0;
568 int dptr_num = -1;
569 int numentries = 0;
570 int i;
571 BOOL finished = False;
572 BOOL dont_descend = False;
573 BOOL out_of_space = False;
574 int space_remaining;
575 BOOL bad_path = False;
577 *directory = *mask = 0;
579 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",
580 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
581 info_level, max_data_bytes));
583 switch (info_level)
585 case 1:
586 case 2:
587 case 3:
588 case 4:
589 case SMB_FIND_FILE_DIRECTORY_INFO:
590 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
591 case SMB_FIND_FILE_NAMES_INFO:
592 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
593 break;
594 default:
595 return(ERROR(ERRDOS,ERRunknownlevel));
598 pstrcpy(directory, params + 12); /* Complete directory path with
599 wildcard mask appended */
601 DEBUG(5,("path=%s\n",directory));
603 unix_convert(directory,cnum,0,&bad_path);
604 if(!check_name(directory,cnum)) {
605 if((errno == ENOENT) && bad_path)
607 unix_ERR_class = ERRDOS;
608 unix_ERR_code = ERRbadpath;
611 #if 0
612 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
613 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
614 (get_remote_arch() == RA_WINNT))
616 unix_ERR_class = ERRDOS;
617 unix_ERR_code = ERRbaddirectory;
619 #endif
621 return(ERROR(ERRDOS,ERRbadpath));
624 p = strrchr(directory,'/');
625 if(p == NULL) {
626 strcpy(mask,directory);
627 strcpy(directory,"./");
628 } else {
629 strcpy(mask,p+1);
630 *p = 0;
633 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
635 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
636 if(!*ppdata)
637 return(ERROR(ERRDOS,ERRnomem));
638 bzero(pdata,max_data_bytes);
640 /* Realloc the params space */
641 params = *pparams = Realloc(*pparams, 10);
642 if(params == NULL)
643 return(ERROR(ERRDOS,ERRnomem));
645 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
646 if (dptr_num < 0)
648 if(dptr_num == -2)
650 if((errno == ENOENT) && bad_path)
652 unix_ERR_class = ERRDOS;
653 unix_ERR_code = ERRbadpath;
656 #if 0
657 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
658 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
659 (get_remote_arch() == RA_WINNT))
661 unix_ERR_class = ERRDOS;
662 unix_ERR_code = ERRbaddirectory;
664 #endif
666 return (UNIXERROR(ERRDOS,ERRbadpath));
668 return(ERROR(ERRDOS,ERRbadpath));
671 /* convert the formatted masks */
673 p = mask;
674 while (*p) {
675 if (*p == '<') *p = '*';
676 if (*p == '>') *p = '?';
677 if (*p == '"') *p = '.';
678 p++;
682 /* a special case for 16 bit apps */
683 if (strequal(mask,"????????.???")) strcpy(mask,"*");
685 /* handle broken clients that send us old 8.3 format */
686 string_sub(mask,"????????","*");
687 string_sub(mask,".???",".*");
689 /* Save the wildcard match and attribs we are using on this directory -
690 needed as lanman2 assumes these are being saved between calls */
692 if(!(wcard = strdup(mask))) {
693 dptr_close(dptr_num);
694 return(ERROR(ERRDOS,ERRnomem));
697 dptr_set_wcard(dptr_num, wcard);
698 dptr_set_attr(dptr_num, dirtype);
700 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
702 /* We don't need to check for VOL here as this is returned by
703 a different TRANS2 call. */
705 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
706 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
707 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
708 dont_descend = True;
710 p = pdata;
711 space_remaining = max_data_bytes;
712 out_of_space = False;
714 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
717 /* this is a heuristic to avoid seeking the dirptr except when
718 absolutely necessary. It allows for a filename of about 40 chars */
719 if (space_remaining < DIRLEN_GUESS && numentries > 0)
721 out_of_space = True;
722 finished = False;
724 else
726 finished =
727 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
728 requires_resume_key,dont_descend,
729 &p,pdata,space_remaining, &out_of_space,
730 &last_name_off);
733 if (finished && out_of_space)
734 finished = False;
736 if (!finished && !out_of_space)
737 numentries++;
738 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
741 /* Check if we can close the dirptr */
742 if(close_after_first || (finished && close_if_end))
744 dptr_close(dptr_num);
745 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
746 dptr_num = -1;
749 /* At this point pdata points to numentries directory entries. */
751 /* Set up the return parameter block */
752 SSVAL(params,0,dptr_num);
753 SSVAL(params,2,numentries);
754 SSVAL(params,4,finished);
755 SSVAL(params,6,0); /* Never an EA error */
756 SSVAL(params,8,last_name_off);
758 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
760 if ((! *directory) && dptr_path(dptr_num))
761 sprintf(directory,"(%s)",dptr_path(dptr_num));
763 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
764 timestring(),
765 smb_fn_name(CVAL(inbuf,smb_com)),
766 mask,directory,cnum,dirtype,numentries));
768 return(-1);
772 /****************************************************************************
773 reply to a TRANS2_FINDNEXT
774 ****************************************************************************/
775 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
776 int cnum, char **pparams, char **ppdata)
778 /* We must be careful here that we don't return more than the
779 allowed number of data bytes. If this means returning fewer than
780 maxentries then so be it. We assume that the redirector has
781 enough room for the fixed number of parameter bytes it has
782 requested. */
783 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
784 char *params = *pparams;
785 char *pdata = *ppdata;
786 int16 dptr_num = SVAL(params,0);
787 int maxentries = SVAL(params,2);
788 uint16 info_level = SVAL(params,4);
789 uint32 resume_key = IVAL(params,6);
790 BOOL close_after_request = BITSETW(params+10,0);
791 BOOL close_if_end = BITSETW(params+10,1);
792 BOOL requires_resume_key = BITSETW(params+10,2);
793 BOOL continue_bit = BITSETW(params+10,3);
794 pstring mask;
795 pstring directory;
796 char *p;
797 uint16 dirtype;
798 int numentries = 0;
799 int i, last_name_off=0;
800 BOOL finished = False;
801 BOOL dont_descend = False;
802 BOOL out_of_space = False;
803 int space_remaining;
805 *mask = *directory = 0;
807 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",
808 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
809 requires_resume_key, resume_key, continue_bit, info_level));
811 switch (info_level)
813 case 1:
814 case 2:
815 case 3:
816 case 4:
817 case SMB_FIND_FILE_DIRECTORY_INFO:
818 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
819 case SMB_FIND_FILE_NAMES_INFO:
820 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
821 break;
822 default:
823 return(ERROR(ERRDOS,ERRunknownlevel));
826 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
827 if(!*ppdata)
828 return(ERROR(ERRDOS,ERRnomem));
829 bzero(pdata,max_data_bytes);
831 /* Realloc the params space */
832 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
833 if(!params)
834 return(ERROR(ERRDOS,ERRnomem));
836 /* Check that the dptr is valid */
837 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
838 return(ERROR(ERRDOS,ERRnofiles));
840 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
842 /* Get the wildcard mask from the dptr */
843 if((p = dptr_wcard(dptr_num))== NULL) {
844 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
845 return (ERROR(ERRDOS,ERRnofiles));
847 strcpy(mask, p);
848 strcpy(directory,Connections[cnum].dirpath);
850 /* Get the attr mask from the dptr */
851 dirtype = dptr_attr(dptr_num);
853 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
854 dptr_num, mask, dirtype,
855 Connections[cnum].dirptr,
856 TellDir(Connections[cnum].dirptr)));
858 /* We don't need to check for VOL here as this is returned by
859 a different TRANS2 call. */
861 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
862 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
863 dont_descend = True;
865 p = pdata;
866 space_remaining = max_data_bytes;
867 out_of_space = False;
869 /* If we have a resume key - seek to the correct position. */
870 if(requires_resume_key && !continue_bit)
871 SeekDir(Connections[cnum].dirptr, resume_key);
873 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
875 /* this is a heuristic to avoid seeking the dirptr except when
876 absolutely necessary. It allows for a filename of about 40 chars */
877 if (space_remaining < DIRLEN_GUESS && numentries > 0)
879 out_of_space = True;
880 finished = False;
882 else
884 finished =
885 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
886 requires_resume_key,dont_descend,
887 &p,pdata,space_remaining, &out_of_space,
888 &last_name_off);
891 if (finished && out_of_space)
892 finished = False;
894 if (!finished && !out_of_space)
895 numentries++;
896 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
899 /* Check if we can close the dirptr */
900 if(close_after_request || (finished && close_if_end))
902 dptr_close(dptr_num); /* This frees up the saved mask */
903 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
904 dptr_num = -1;
908 /* Set up the return parameter block */
909 SSVAL(params,0,numentries);
910 SSVAL(params,2,finished);
911 SSVAL(params,4,0); /* Never an EA error */
912 SSVAL(params,6,last_name_off);
914 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
916 if ((! *directory) && dptr_path(dptr_num))
917 sprintf(directory,"(%s)",dptr_path(dptr_num));
919 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
920 timestring(),
921 smb_fn_name(CVAL(inbuf,smb_com)),
922 mask,directory,cnum,dirtype,numentries));
924 return(-1);
927 /****************************************************************************
928 reply to a TRANS2_QFSINFO (query filesystem info)
929 ****************************************************************************/
930 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
931 int cnum, char **pparams, char **ppdata)
933 char *pdata = *ppdata;
934 char *params = *pparams;
935 uint16 info_level = SVAL(params,0);
936 int data_len;
937 struct stat st;
938 char *vname = volume_label(SNUM(cnum));
940 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
942 if(sys_stat(".",&st)!=0) {
943 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
944 return (ERROR(ERRSRV,ERRinvdevice));
947 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
949 switch (info_level)
951 case 1:
953 int dfree,dsize,bsize;
954 data_len = 18;
955 sys_disk_free(".",&bsize,&dfree,&dsize);
956 SIVAL(pdata,l1_idFileSystem,st.st_dev);
957 SIVAL(pdata,l1_cSectorUnit,bsize/512);
958 SIVAL(pdata,l1_cUnit,dsize);
959 SIVAL(pdata,l1_cUnitAvail,dfree);
960 SSVAL(pdata,l1_cbSector,512);
961 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
962 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
963 break;
965 case 2:
967 /* Return volume name */
968 int volname_len = MIN(strlen(vname),11);
969 data_len = l2_vol_szVolLabel + volname_len + 1;
970 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
971 SCVAL(pdata,l2_vol_cch,volname_len);
972 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
973 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
974 pdata+l2_vol_szVolLabel));
975 break;
977 case SMB_QUERY_FS_ATTRIBUTE_INFO:
978 data_len = 12 + 2*strlen(FSTYPE_STRING);
979 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
980 SIVAL(pdata,4,128); /* Max filename component length */
981 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
982 PutUniCode(pdata+12,FSTYPE_STRING);
983 break;
984 case SMB_QUERY_FS_LABEL_INFO:
985 data_len = 4 + strlen(vname);
986 SIVAL(pdata,0,strlen(vname));
987 strcpy(pdata+4,vname);
988 break;
989 case SMB_QUERY_FS_VOLUME_INFO:
990 data_len = 18 + 2*strlen(vname);
991 SIVAL(pdata,12,2*strlen(vname));
992 PutUniCode(pdata+18,vname);
993 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
994 vname));
995 break;
996 case SMB_QUERY_FS_SIZE_INFO:
998 int dfree,dsize,bsize;
999 data_len = 24;
1000 sys_disk_free(".",&bsize,&dfree,&dsize);
1001 SIVAL(pdata,0,dsize);
1002 SIVAL(pdata,8,dfree);
1003 SIVAL(pdata,16,bsize/512);
1004 SIVAL(pdata,20,512);
1006 break;
1007 case SMB_QUERY_FS_DEVICE_INFO:
1008 data_len = 8;
1009 SIVAL(pdata,0,0); /* dev type */
1010 SIVAL(pdata,4,0); /* characteristics */
1011 break;
1012 default:
1013 return(ERROR(ERRDOS,ERRunknownlevel));
1017 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1019 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1021 return -1;
1024 /****************************************************************************
1025 reply to a TRANS2_SETFSINFO (set filesystem info)
1026 ****************************************************************************/
1027 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1028 int cnum, char **pparams, char **ppdata)
1030 /* Just say yes we did it - there is nothing that
1031 can be set here so it doesn't matter. */
1032 int outsize;
1033 DEBUG(3,("call_trans2setfsinfo\n"));
1035 if (!CAN_WRITE(cnum))
1036 return(ERROR(ERRSRV,ERRaccess));
1038 outsize = set_message(outbuf,10,0,True);
1040 return outsize;
1043 /****************************************************************************
1044 reply to a TRANS2_QFILEINFO (query file info by fileid)
1045 ****************************************************************************/
1046 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
1047 int bufsize,int cnum,
1048 char **pparams,char **ppdata,
1049 int total_data)
1051 char *params = *pparams;
1052 char *pdata = *ppdata;
1053 uint16 tran_call = SVAL(inbuf, smb_setup0);
1054 uint16 info_level;
1055 int mode=0;
1056 int size=0;
1057 unsigned int data_size;
1058 struct stat sbuf;
1059 pstring fname1;
1060 char *fname;
1061 char *p;
1062 int l,pos;
1063 BOOL bad_path = False;
1065 if (tran_call == TRANSACT2_QFILEINFO) {
1066 int16 fnum = SVALS(params,0);
1067 info_level = SVAL(params,2);
1069 CHECK_FNUM(fnum,cnum);
1070 CHECK_ERROR(fnum);
1072 fname = Files[fnum].name;
1073 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1074 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1075 return(UNIXERROR(ERRDOS,ERRbadfid));
1077 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1078 } else {
1079 /* qpathinfo */
1080 info_level = SVAL(params,0);
1081 fname = &fname1[0];
1082 pstrcpy(fname,&params[6]);
1083 unix_convert(fname,cnum,0,&bad_path);
1084 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1085 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1086 if((errno == ENOENT) && bad_path)
1088 unix_ERR_class = ERRDOS;
1089 unix_ERR_code = ERRbadpath;
1091 return(UNIXERROR(ERRDOS,ERRbadpath));
1093 pos = 0;
1097 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1098 fname,info_level,tran_call,total_data));
1100 p = strrchr(fname,'/');
1101 if (!p)
1102 p = fname;
1103 else
1104 p++;
1105 l = strlen(p);
1106 mode = dos_mode(cnum,fname,&sbuf);
1107 size = sbuf.st_size;
1108 if (mode & aDIR) size = 0;
1110 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1111 data_size = 1024;
1112 pdata = *ppdata = Realloc(*ppdata, data_size);
1114 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1115 /* uggh, EAs for OS2 */
1116 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1117 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1120 bzero(pdata,data_size);
1122 switch (info_level)
1124 case SMB_INFO_STANDARD:
1125 case SMB_INFO_QUERY_EA_SIZE:
1126 data_size = (info_level==1?22:26);
1127 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1128 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1129 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1130 SIVAL(pdata,l1_cbFile,size);
1131 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1132 SSVAL(pdata,l1_attrFile,mode);
1133 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1134 break;
1136 case SMB_INFO_QUERY_EAS_FROM_LIST:
1137 data_size = 24;
1138 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1139 put_dos_date2(pdata,4,sbuf.st_atime);
1140 put_dos_date2(pdata,8,sbuf.st_mtime);
1141 SIVAL(pdata,12,size);
1142 SIVAL(pdata,16,ROUNDUP(size,1024));
1143 SIVAL(pdata,20,mode);
1144 break;
1146 case SMB_INFO_QUERY_ALL_EAS:
1147 data_size = 4;
1148 SIVAL(pdata,0,data_size);
1149 break;
1151 case 6:
1152 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1154 case SMB_QUERY_FILE_BASIC_INFO:
1155 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1156 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1157 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1158 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1159 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1160 SIVAL(pdata,32,mode);
1162 DEBUG(5,("SMB_QFBI - "));
1163 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1164 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1165 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1166 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1167 DEBUG(5,("mode: %x\n", mode));
1169 break;
1171 case SMB_QUERY_FILE_STANDARD_INFO:
1172 data_size = 22;
1173 SIVAL(pdata,0,size);
1174 SIVAL(pdata,8,size);
1175 SIVAL(pdata,16,sbuf.st_nlink);
1176 CVAL(pdata,20) = 0;
1177 CVAL(pdata,21) = (mode&aDIR)?1:0;
1178 break;
1180 case SMB_QUERY_FILE_EA_INFO:
1181 data_size = 4;
1182 break;
1184 /* Get the 8.3 name - used if NT SMB was negotiated. */
1185 case SMB_QUERY_FILE_ALT_NAME_INFO:
1187 pstring short_name;
1188 pstrcpy(short_name,fname);
1189 /* Mangle if not already 8.3 */
1190 if(!is_8_3(short_name, True))
1192 if(!name_map_mangle(short_name,True,SNUM(cnum)))
1193 *short_name = '\0';
1195 strncpy(pdata + 4,short_name,12);
1196 (pdata + 4)[12] = 0;
1197 strupper(pdata + 4);
1198 l = strlen(pdata + 4);
1199 data_size = 4 + l;
1200 SIVAL(pdata,0,l);
1202 break;
1204 case SMB_QUERY_FILE_NAME_INFO:
1205 data_size = 4 + l;
1206 SIVAL(pdata,0,l);
1207 pstrcpy(pdata+4,fname);
1208 break;
1210 case SMB_QUERY_FILE_ALLOCATION_INFO:
1211 case SMB_QUERY_FILE_END_OF_FILEINFO:
1212 data_size = 8;
1213 SIVAL(pdata,0,size);
1214 break;
1216 case SMB_QUERY_FILE_ALL_INFO:
1217 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1218 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1219 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1220 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1221 SIVAL(pdata,32,mode);
1222 pdata += 40;
1223 SIVAL(pdata,0,size);
1224 SIVAL(pdata,8,size);
1225 SIVAL(pdata,16,sbuf.st_nlink);
1226 CVAL(pdata,20) = 0;
1227 CVAL(pdata,21) = (mode&aDIR)?1:0;
1228 pdata += 24;
1229 pdata += 8; /* index number */
1230 pdata += 4; /* EA info */
1231 if (mode & aRONLY)
1232 SIVAL(pdata,0,0xA9);
1233 else
1234 SIVAL(pdata,0,0xd01BF);
1235 pdata += 4;
1236 SIVAL(pdata,0,pos); /* current offset */
1237 pdata += 8;
1238 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1239 pdata += 4;
1240 pdata += 4; /* alignment */
1241 SIVAL(pdata,0,l);
1242 pstrcpy(pdata+4,fname);
1243 pdata += 4 + l;
1244 data_size = PTR_DIFF(pdata,(*ppdata));
1245 break;
1247 case SMB_QUERY_FILE_STREAM_INFO:
1248 data_size = 24 + l;
1249 SIVAL(pdata,0,pos);
1250 SIVAL(pdata,4,size);
1251 SIVAL(pdata,12,size);
1252 SIVAL(pdata,20,l);
1253 pstrcpy(pdata+24,fname);
1254 break;
1255 default:
1256 return(ERROR(ERRDOS,ERRunknownlevel));
1259 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1261 return(-1);
1264 /****************************************************************************
1265 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1266 ****************************************************************************/
1267 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1268 int bufsize, int cnum, char **pparams,
1269 char **ppdata, int total_data)
1271 char *params = *pparams;
1272 char *pdata = *ppdata;
1273 uint16 tran_call = SVAL(inbuf, smb_setup0);
1274 uint16 info_level;
1275 int mode=0;
1276 int size=0;
1277 struct utimbuf tvs;
1278 struct stat st;
1279 pstring fname1;
1280 char *fname;
1281 int fd = -1;
1282 BOOL bad_path = False;
1284 if (!CAN_WRITE(cnum))
1285 return(ERROR(ERRSRV,ERRaccess));
1287 if (tran_call == TRANSACT2_SETFILEINFO) {
1288 int16 fnum = SVALS(params,0);
1289 info_level = SVAL(params,2);
1291 CHECK_FNUM(fnum,cnum);
1292 CHECK_ERROR(fnum);
1294 fname = Files[fnum].name;
1295 fd = Files[fnum].fd_ptr->fd;
1297 if(fstat(fd,&st)!=0) {
1298 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1299 return(ERROR(ERRDOS,ERRbadpath));
1301 } else {
1302 /* set path info */
1303 info_level = SVAL(params,0);
1304 fname = fname1;
1305 pstrcpy(fname,&params[6]);
1306 unix_convert(fname,cnum,0,&bad_path);
1307 if(!check_name(fname, cnum))
1309 if((errno == ENOENT) && bad_path)
1311 unix_ERR_class = ERRDOS;
1312 unix_ERR_code = ERRbadpath;
1314 return(UNIXERROR(ERRDOS,ERRbadpath));
1317 if(sys_stat(fname,&st)!=0) {
1318 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1319 if((errno == ENOENT) && bad_path)
1321 unix_ERR_class = ERRDOS;
1322 unix_ERR_code = ERRbadpath;
1324 return(UNIXERROR(ERRDOS,ERRbadpath));
1328 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1329 tran_call,fname,info_level,total_data));
1331 /* Realloc the parameter and data sizes */
1332 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1333 if(params == NULL)
1334 return(ERROR(ERRDOS,ERRnomem));
1336 size = st.st_size;
1337 tvs.modtime = st.st_mtime;
1338 tvs.actime = st.st_atime;
1339 mode = dos_mode(cnum,fname,&st);
1341 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1342 /* uggh, EAs for OS2 */
1343 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1344 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1347 switch (info_level)
1349 case SMB_INFO_STANDARD:
1350 case SMB_INFO_QUERY_EA_SIZE:
1352 /* access time */
1353 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1355 /* write time */
1356 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1358 mode = SVAL(pdata,l1_attrFile);
1359 size = IVAL(pdata,l1_cbFile);
1360 break;
1363 /* XXXX um, i don't think this is right.
1364 it's also not in the cifs6.txt spec.
1366 case SMB_INFO_QUERY_EAS_FROM_LIST:
1367 tvs.actime = make_unix_date2(pdata+8);
1368 tvs.modtime = make_unix_date2(pdata+12);
1369 size = IVAL(pdata,16);
1370 mode = IVAL(pdata,24);
1371 break;
1373 /* XXXX nor this. not in cifs6.txt, either. */
1374 case SMB_INFO_QUERY_ALL_EAS:
1375 tvs.actime = make_unix_date2(pdata+8);
1376 tvs.modtime = make_unix_date2(pdata+12);
1377 size = IVAL(pdata,16);
1378 mode = IVAL(pdata,24);
1379 break;
1381 case SMB_SET_FILE_BASIC_INFO:
1383 /* Ignore create time at offset pdata. */
1385 /* access time */
1386 tvs.actime = interpret_long_date(pdata+8);
1388 /* write time + changed time, combined. */
1389 tvs.modtime=MAX(interpret_long_date(pdata+16),
1390 interpret_long_date(pdata+24));
1392 #if 0 /* Needs more testing... */
1393 /* Test from Luke to prevent Win95 from
1394 setting incorrect values here.
1396 if (tvs.actime < tvs.modtime)
1397 return(ERROR(ERRDOS,ERRnoaccess));
1398 #endif /* Needs more testing... */
1400 /* attributes */
1401 mode = IVAL(pdata,32);
1402 break;
1405 case SMB_SET_FILE_END_OF_FILE_INFO:
1407 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1408 return(ERROR(ERRDOS,ERRunknownlevel));
1409 size = IVAL(pdata,0);
1410 break;
1413 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1414 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1415 default:
1417 return(ERROR(ERRDOS,ERRunknownlevel));
1421 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1422 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1423 DEBUG(6,("size: %x " , size));
1424 DEBUG(6,("mode: %x\n" , mode));
1426 /* get some defaults (no modifications) if any info is zero. */
1427 if (!tvs.actime) tvs.actime = st.st_atime;
1428 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1429 if (!size) size = st.st_size;
1431 /* Try and set the times, size and mode of this file -
1432 if they are different from the current values
1434 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1436 if(sys_utime(fname, &tvs)!=0)
1438 return(ERROR(ERRDOS,ERRnoaccess));
1442 /* check the mode isn't different, before changing it */
1443 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1445 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1446 return(ERROR(ERRDOS,ERRnoaccess));
1449 if(size != st.st_size)
1451 if (fd == -1)
1453 fd = sys_open(fname,O_RDWR,0);
1454 if (fd == -1)
1456 return(ERROR(ERRDOS,ERRbadpath));
1458 set_filelen(fd, size);
1459 close(fd);
1461 else
1463 set_filelen(fd, size);
1467 SSVAL(params,0,0);
1469 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1471 return(-1);
1474 /****************************************************************************
1475 reply to a TRANS2_MKDIR (make directory with extended attributes).
1476 ****************************************************************************/
1477 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1478 int cnum, char **pparams, char **ppdata)
1480 char *params = *pparams;
1481 pstring directory;
1482 int ret = -1;
1483 BOOL bad_path = False;
1485 if (!CAN_WRITE(cnum))
1486 return(ERROR(ERRSRV,ERRaccess));
1488 pstrcpy(directory, &params[4]);
1490 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1492 unix_convert(directory,cnum,0,&bad_path);
1493 if (check_name(directory,cnum))
1494 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1496 if(ret < 0)
1498 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1499 if((errno == ENOENT) && bad_path)
1501 unix_ERR_class = ERRDOS;
1502 unix_ERR_code = ERRbadpath;
1504 return(UNIXERROR(ERRDOS,ERRnoaccess));
1507 /* Realloc the parameter and data sizes */
1508 params = *pparams = Realloc(*pparams,2);
1509 if(params == NULL)
1510 return(ERROR(ERRDOS,ERRnomem));
1512 SSVAL(params,0,0);
1514 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1516 return(-1);
1519 /****************************************************************************
1520 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1521 We don't actually do this - we just send a null response.
1522 ****************************************************************************/
1523 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1524 int cnum, char **pparams, char **ppdata)
1526 static uint16 fnf_handle = 257;
1527 char *params = *pparams;
1528 uint16 info_level = SVAL(params,4);
1530 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1532 switch (info_level)
1534 case 1:
1535 case 2:
1536 break;
1537 default:
1538 return(ERROR(ERRDOS,ERRunknownlevel));
1541 /* Realloc the parameter and data sizes */
1542 params = *pparams = Realloc(*pparams,6);
1543 if(params == NULL)
1544 return(ERROR(ERRDOS,ERRnomem));
1546 SSVAL(params,0,fnf_handle);
1547 SSVAL(params,2,0); /* No changes */
1548 SSVAL(params,4,0); /* No EA errors */
1550 fnf_handle++;
1552 if(fnf_handle == 0)
1553 fnf_handle = 257;
1555 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1557 return(-1);
1560 /****************************************************************************
1561 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1562 changes). Currently this does nothing.
1563 ****************************************************************************/
1564 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1565 int cnum, char **pparams, char **ppdata)
1567 char *params = *pparams;
1569 DEBUG(3,("call_trans2findnotifynext\n"));
1571 /* Realloc the parameter and data sizes */
1572 params = *pparams = Realloc(*pparams,4);
1573 if(params == NULL)
1574 return(ERROR(ERRDOS,ERRnomem));
1576 SSVAL(params,0,0); /* No changes */
1577 SSVAL(params,2,0); /* No EA errors */
1579 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1581 return(-1);
1584 /****************************************************************************
1585 reply to a SMBfindclose (stop trans2 directory search)
1586 ****************************************************************************/
1587 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1589 int cnum;
1590 int outsize = 0;
1591 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1593 cnum = SVAL(inbuf,smb_tid);
1595 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1597 dptr_close(dptr_num);
1599 outsize = set_message(outbuf,0,0,True);
1601 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1603 return(outsize);
1606 /****************************************************************************
1607 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1608 ****************************************************************************/
1609 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1611 int cnum;
1612 int outsize = 0;
1613 int dptr_num= -1;
1615 cnum = SVAL(inbuf,smb_tid);
1616 dptr_num = SVAL(inbuf,smb_vwv0);
1618 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1620 /* We never give out valid handles for a
1621 findnotifyfirst - so any dptr_num is ok here.
1622 Just ignore it. */
1624 outsize = set_message(outbuf,0,0,True);
1626 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1628 return(outsize);
1632 /****************************************************************************
1633 reply to a SMBtranss2 - just ignore it!
1634 ****************************************************************************/
1635 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1637 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1638 return(-1);
1641 /****************************************************************************
1642 reply to a SMBtrans2
1643 ****************************************************************************/
1644 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1646 int outsize = 0;
1647 int cnum = SVAL(inbuf,smb_tid);
1648 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1649 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1650 #if 0
1651 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1652 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1653 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1654 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1655 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1656 int32 timeout = IVALS(inbuf,smb_timeout);
1657 #endif
1658 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1659 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1660 char *params = NULL, *data = NULL;
1661 int num_params, num_params_sofar, num_data, num_data_sofar;
1663 outsize = set_message(outbuf,0,0,True);
1665 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1666 is so as a sanity check */
1667 if(suwcnt != 1 )
1669 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1670 return(ERROR(ERRSRV,ERRerror));
1673 /* Allocate the space for the maximum needed parameters and data */
1674 if (total_params > 0)
1675 params = (char *)malloc(total_params);
1676 if (total_data > 0)
1677 data = (char *)malloc(total_data);
1679 if ((total_params && !params) || (total_data && !data))
1681 DEBUG(2,("Out of memory in reply_trans2\n"));
1682 return(ERROR(ERRDOS,ERRnomem));
1685 /* Copy the param and data bytes sent with this request into
1686 the params buffer */
1687 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1688 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1690 if (num_params > total_params || num_data > total_data)
1691 exit_server("invalid params in reply_trans2");
1693 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1694 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1696 if(num_data_sofar < total_data || num_params_sofar < total_params)
1698 /* We need to send an interim response then receive the rest
1699 of the parameter/data bytes */
1700 outsize = set_message(outbuf,0,0,True);
1701 send_smb(Client,outbuf);
1703 while( num_data_sofar < total_data || num_params_sofar < total_params)
1705 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1706 CVAL(inbuf, smb_com) != SMBtranss2)
1708 outsize = set_message(outbuf,0,0,True);
1709 DEBUG(2,("Invalid secondary trans2 packet\n"));
1710 free(params);
1711 free(data);
1712 return(ERROR(ERRSRV,ERRerror));
1715 /* Revise total_params and total_data in case they have changed downwards */
1716 total_params = SVAL(inbuf, smb_tpscnt);
1717 total_data = SVAL(inbuf, smb_tdscnt);
1718 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1719 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1720 if (num_params_sofar > total_params || num_data_sofar > total_data)
1721 exit_server("data overflow in trans2");
1723 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1724 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1725 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1726 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1730 if (Protocol >= PROTOCOL_NT1) {
1731 uint16 flg2 = SVAL(outbuf,smb_flg2);
1732 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1735 /* Now we must call the relevant TRANS2 function */
1736 switch(tran_call)
1738 case TRANSACT2_OPEN:
1739 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1740 break;
1741 case TRANSACT2_FINDFIRST:
1742 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1743 break;
1744 case TRANSACT2_FINDNEXT:
1745 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1746 break;
1747 case TRANSACT2_QFSINFO:
1748 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1749 break;
1750 case TRANSACT2_SETFSINFO:
1751 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1752 break;
1753 case TRANSACT2_QPATHINFO:
1754 case TRANSACT2_QFILEINFO:
1755 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1756 break;
1757 case TRANSACT2_SETPATHINFO:
1758 case TRANSACT2_SETFILEINFO:
1759 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1760 break;
1761 case TRANSACT2_FINDNOTIFYFIRST:
1762 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1763 break;
1764 case TRANSACT2_FINDNOTIFYNEXT:
1765 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1766 break;
1767 case TRANSACT2_MKDIR:
1768 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1769 break;
1770 default:
1771 /* Error in request */
1772 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1773 if(params)
1774 free(params);
1775 if(data)
1776 free(data);
1777 return (ERROR(ERRSRV,ERRerror));
1780 /* As we do not know how many data packets will need to be
1781 returned here the various call_trans2xxxx calls
1782 must send their own. Thus a call_trans2xxx routine only
1783 returns a value other than -1 when it wants to send
1784 an error packet.
1787 if(params)
1788 free(params);
1789 if(data)
1790 free(data);
1791 return outsize; /* If a correct response was needed the call_trans2xxx
1792 calls have already sent it. If outsize != -1 then it is
1793 returning an error packet. */