local.h: Removed ununsed SHARE_MODES_XXX defines. Upped SMBD_RELOAD_CHECK
[Samba.git] / source / smbd / trans2.c
blob1b199f01ba920e42452eff986ae0b49189893255
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;
188 StrnCpy(fname,pname,namelen);
190 DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
191 fname,cnum,open_mode, open_attr, open_ofun, open_size));
193 /* XXXX we need to handle passed times, sattr and flags */
195 unix_convert(fname,cnum,0);
197 fnum = find_free_file();
198 if (fnum < 0)
199 return(ERROR(ERRSRV,ERRnofids));
201 if (!check_name(fname,cnum))
202 return(UNIXERROR(ERRDOS,ERRnoaccess));
204 unixmode = unix_mode(cnum,open_attr | aARCH);
207 open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
208 &rmode,&smb_action);
210 if (!Files[fnum].open)
211 return(UNIXERROR(ERRDOS,ERRnoaccess));
213 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
214 close_file(fnum);
215 return(ERROR(ERRDOS,ERRnoaccess));
218 size = sbuf.st_size;
219 fmode = dos_mode(cnum,fname,&sbuf);
220 mtime = sbuf.st_mtime;
221 inode = sbuf.st_ino;
222 if (fmode & aDIR) {
223 close_file(fnum);
224 return(ERROR(ERRDOS,ERRnoaccess));
227 /* Realloc the size of parameters and data we will return */
228 params = *pparams = Realloc(*pparams, 28);
229 if(params == NULL)
230 return(ERROR(ERRDOS,ERRnomem));
232 bzero(params,28);
233 SSVAL(params,0,fnum);
234 SSVAL(params,2,fmode);
235 put_dos_date2(params,4, mtime);
236 SIVAL(params,8, size);
237 SSVAL(params,12,rmode);
239 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
240 smb_action |= (1<<15);
243 SSVAL(params,18,smb_action);
244 SIVAL(params,20,inode);
246 /* Send the required number of replies */
247 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
249 return -1;
252 /****************************************************************************
253 get a level dependent lanman2 dir entry.
254 ****************************************************************************/
255 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
256 int requires_resume_key,
257 BOOL dont_descend,char **ppdata,
258 char *base_data, int space_remaining,
259 BOOL *out_of_space,
260 int *last_name_off)
262 char *dname;
263 BOOL found = False;
264 struct stat sbuf;
265 pstring mask;
266 pstring pathreal;
267 pstring fname;
268 BOOL matched;
269 char *p, *pdata = *ppdata;
270 int reskey=0, prev_dirpos=0;
271 int mode=0;
272 uint32 size=0,len;
273 uint32 mdate=0, adate=0, cdate=0;
274 char *nameptr;
275 BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
276 strequal(Connections[cnum].dirpath,".") ||
277 strequal(Connections[cnum].dirpath,"/"));
278 BOOL was_8_3;
279 int nt_extmode; /* Used for NT connections instead of mode */
280 BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
282 *fname = 0;
283 *out_of_space = False;
285 if (!Connections[cnum].dirptr)
286 return(False);
288 p = strrchr(path_mask,'/');
289 if(p != NULL)
291 if(p[1] == '\0')
292 strcpy(mask,"*.*");
293 else
294 strcpy(mask, p+1);
296 else
297 strcpy(mask, path_mask);
299 while (!found)
301 /* Needed if we run out of space */
302 prev_dirpos = TellDir(Connections[cnum].dirptr);
303 dname = ReadDirName(Connections[cnum].dirptr);
305 reskey = TellDir(Connections[cnum].dirptr);
307 DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
308 Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
310 if (!dname)
311 return(False);
313 matched = False;
315 strcpy(fname,dname);
317 if(mask_match(fname, mask, case_sensitive, True))
319 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
320 if (dont_descend && !isdots)
321 continue;
323 if (isrootdir && isdots)
324 continue;
326 strcpy(pathreal,Connections[cnum].dirpath);
327 if(needslash)
328 strcat(pathreal,"/");
329 strcat(pathreal,fname);
330 if (sys_stat(pathreal,&sbuf) != 0)
332 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
333 continue;
336 mode = dos_mode(cnum,pathreal,&sbuf);
338 if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
339 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
340 continue;
343 size = sbuf.st_size;
344 mdate = sbuf.st_mtime;
345 adate = sbuf.st_atime;
346 cdate = sbuf.st_ctime;
347 if(mode & aDIR)
348 size = 0;
350 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
352 found = True;
358 p = pdata;
359 nameptr = p;
361 name_map_mangle(fname,False,SNUM(cnum));
363 nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
365 switch (info_level)
367 case 1:
368 if(requires_resume_key) {
369 SIVAL(p,0,reskey);
370 p += 4;
372 put_dos_date2(p,l1_fdateCreation,cdate);
373 put_dos_date2(p,l1_fdateLastAccess,adate);
374 put_dos_date2(p,l1_fdateLastWrite,mdate);
375 SIVAL(p,l1_cbFile,size);
376 SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
377 SSVAL(p,l1_attrFile,mode);
378 SCVAL(p,l1_cchName,strlen(fname));
379 strcpy(p + l1_achName, fname);
380 nameptr = p + l1_achName;
381 p += l1_achName + strlen(fname) + 1;
382 break;
384 case 2:
385 /* info_level 2 */
386 if(requires_resume_key) {
387 SIVAL(p,0,reskey);
388 p += 4;
390 put_dos_date2(p,l2_fdateCreation,cdate);
391 put_dos_date2(p,l2_fdateLastAccess,adate);
392 put_dos_date2(p,l2_fdateLastWrite,mdate);
393 SIVAL(p,l2_cbFile,size);
394 SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
395 SSVAL(p,l2_attrFile,mode);
396 SIVAL(p,l2_cbList,0); /* No extended attributes */
397 SCVAL(p,l2_cchName,strlen(fname));
398 strcpy(p + l2_achName, fname);
399 nameptr = p + l2_achName;
400 p += l2_achName + strlen(fname) + 1;
401 break;
403 case 3:
404 SIVAL(p,0,reskey);
405 put_dos_date2(p,4,cdate);
406 put_dos_date2(p,8,adate);
407 put_dos_date2(p,12,mdate);
408 SIVAL(p,16,size);
409 SIVAL(p,20,ROUNDUP(size,1024));
410 SSVAL(p,24,mode);
411 SIVAL(p,26,4);
412 CVAL(p,30) = strlen(fname);
413 strcpy(p+31, fname);
414 nameptr = p+31;
415 p += 31 + strlen(fname) + 1;
416 break;
418 case 4:
419 if(requires_resume_key) {
420 SIVAL(p,0,reskey);
421 p += 4;
423 SIVAL(p,0,33+strlen(fname)+1);
424 put_dos_date2(p,4,cdate);
425 put_dos_date2(p,8,adate);
426 put_dos_date2(p,12,mdate);
427 SIVAL(p,16,size);
428 SIVAL(p,20,ROUNDUP(size,1024));
429 SSVAL(p,24,mode);
430 CVAL(p,32) = strlen(fname);
431 strcpy(p + 33, fname);
432 nameptr = p+33;
433 p += 33 + strlen(fname) + 1;
434 break;
436 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
437 was_8_3 = is_8_3(fname, True);
438 len = 94+strlen(fname);
439 len = (len + 3) & ~3;
440 SIVAL(p,0,len); p += 4;
441 SIVAL(p,0,reskey); p += 4;
442 put_long_date(p,cdate); p += 8;
443 put_long_date(p,adate); p += 8;
444 put_long_date(p,mdate); p += 8;
445 put_long_date(p,mdate); p += 8;
446 SIVAL(p,0,size); p += 8;
447 SIVAL(p,0,size); p += 8;
448 SIVAL(p,0,nt_extmode); p += 4;
449 SIVAL(p,0,strlen(fname)); p += 4;
450 SIVAL(p,0,0); p += 4;
451 if (!was_8_3) {
452 strcpy(p+2,fname);
453 if (!name_map_mangle(p+2,True,SNUM(cnum)))
454 (p+2)[12] = 0;
455 } else
456 *(p+2) = 0;
457 strupper(p+2);
458 SSVAL(p,0,strlen(p+2));
459 p += 2 + 24;
460 /* nameptr = p; */
461 strcpy(p,fname); p += strlen(p);
462 p = pdata + len;
463 break;
465 case SMB_FIND_FILE_DIRECTORY_INFO:
466 len = 64+strlen(fname);
467 len = (len + 3) & ~3;
468 SIVAL(p,0,len); p += 4;
469 SIVAL(p,0,reskey); p += 4;
470 put_long_date(p,cdate); p += 8;
471 put_long_date(p,adate); p += 8;
472 put_long_date(p,mdate); p += 8;
473 put_long_date(p,mdate); p += 8;
474 SIVAL(p,0,size); p += 8;
475 SIVAL(p,0,size); p += 8;
476 SIVAL(p,0,nt_extmode); p += 4;
477 SIVAL(p,0,strlen(fname)); p += 4;
478 strcpy(p,fname);
479 p = pdata + len;
480 break;
483 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
484 len = 68+strlen(fname);
485 len = (len + 3) & ~3;
486 SIVAL(p,0,len); p += 4;
487 SIVAL(p,0,reskey); p += 4;
488 put_long_date(p,cdate); p += 8;
489 put_long_date(p,adate); p += 8;
490 put_long_date(p,mdate); p += 8;
491 put_long_date(p,mdate); p += 8;
492 SIVAL(p,0,size); p += 8;
493 SIVAL(p,0,size); p += 8;
494 SIVAL(p,0,nt_extmode); p += 4;
495 SIVAL(p,0,strlen(fname)); p += 4;
496 SIVAL(p,0,0); p += 4;
497 strcpy(p,fname);
498 p = pdata + len;
499 break;
501 case SMB_FIND_FILE_NAMES_INFO:
502 len = 12+strlen(fname);
503 len = (len + 3) & ~3;
504 SIVAL(p,0,len); p += 4;
505 SIVAL(p,0,reskey); p += 4;
506 SIVAL(p,0,strlen(fname)); p += 4;
507 strcpy(p,fname);
508 p = pdata + len;
509 break;
511 default:
512 return(False);
516 if (PTR_DIFF(p,pdata) > space_remaining) {
517 /* Move the dirptr back to prev_dirpos */
518 SeekDir(Connections[cnum].dirptr, prev_dirpos);
519 *out_of_space = True;
520 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
521 return False; /* Not finished - just out of space */
524 /* Setup the last_filename pointer, as an offset from base_data */
525 *last_name_off = PTR_DIFF(nameptr,base_data);
526 /* Advance the data pointer to the next slot */
527 *ppdata = p;
528 return(found);
531 /****************************************************************************
532 reply to a TRANS2_FINDFIRST
533 ****************************************************************************/
534 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum,
535 char **pparams, char **ppdata)
537 /* We must be careful here that we don't return more than the
538 allowed number of data bytes. If this means returning fewer than
539 maxentries then so be it. We assume that the redirector has
540 enough room for the fixed number of parameter bytes it has
541 requested. */
542 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
543 char *params = *pparams;
544 char *pdata = *ppdata;
545 int dirtype = SVAL(params,0);
546 int maxentries = SVAL(params,2);
547 BOOL close_after_first = BITSETW(params+4,0);
548 BOOL close_if_end = BITSETW(params+4,1);
549 BOOL requires_resume_key = BITSETW(params+4,2);
550 int info_level = SVAL(params,6);
551 pstring directory;
552 pstring mask;
553 char *p, *wcard;
554 int last_name_off=0;
555 int dptr_num = -1;
556 int numentries = 0;
557 int i;
558 BOOL finished = False;
559 BOOL dont_descend = False;
560 BOOL out_of_space = False;
561 int space_remaining;
563 *directory = *mask = 0;
565 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",
566 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
567 info_level, max_data_bytes));
569 switch (info_level)
571 case 1:
572 case 2:
573 case 3:
574 case 4:
575 case SMB_FIND_FILE_DIRECTORY_INFO:
576 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
577 case SMB_FIND_FILE_NAMES_INFO:
578 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
579 break;
580 default:
581 return(ERROR(ERRDOS,ERRunknownlevel));
584 strcpy(directory, params + 12); /* Complete directory path with
585 wildcard mask appended */
587 DEBUG(5,("path=%s\n",directory));
589 unix_convert(directory,cnum,0);
590 if(!check_name(directory,cnum)) {
591 return(ERROR(ERRDOS,ERRbadpath));
594 p = strrchr(directory,'/');
595 if(p == NULL) {
596 strcpy(mask,directory);
597 strcpy(directory,"./");
598 } else {
599 strcpy(mask,p+1);
600 *p = 0;
603 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
605 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
606 if(!*ppdata)
607 return(ERROR(ERRDOS,ERRnomem));
608 bzero(pdata,max_data_bytes);
610 /* Realloc the params space */
611 params = *pparams = Realloc(*pparams, 10);
612 if(params == NULL)
613 return(ERROR(ERRDOS,ERRnomem));
615 dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
616 if (dptr_num < 0)
617 return(ERROR(ERRDOS,ERRbadpath));
619 /* convert the formatted masks */
621 p = mask;
622 while (*p) {
623 if (*p == '<') *p = '*';
624 if (*p == '>') *p = '?';
625 if (*p == '"') *p = '.';
626 p++;
630 /* a special case for 16 bit apps */
631 if (strequal(mask,"????????.???")) strcpy(mask,"*");
633 /* handle broken clients that send us old 8.3 format */
634 string_sub(mask,"????????","*");
635 string_sub(mask,".???",".*");
637 /* Save the wildcard match and attribs we are using on this directory -
638 needed as lanman2 assumes these are being saved between calls */
640 if(!(wcard = strdup(mask))) {
641 dptr_close(dptr_num);
642 return(ERROR(ERRDOS,ERRnomem));
645 dptr_set_wcard(dptr_num, wcard);
646 dptr_set_attr(dptr_num, dirtype);
648 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
650 /* We don't need to check for VOL here as this is returned by
651 a different TRANS2 call. */
653 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
654 Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
655 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
656 dont_descend = True;
658 p = pdata;
659 space_remaining = max_data_bytes;
660 out_of_space = False;
662 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
665 /* this is a heuristic to avoid seeking the dirptr except when
666 absolutely necessary. It allows for a filename of about 40 chars */
667 if (space_remaining < DIRLEN_GUESS && numentries > 0)
669 out_of_space = True;
670 finished = False;
672 else
674 finished =
675 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
676 requires_resume_key,dont_descend,
677 &p,pdata,space_remaining, &out_of_space,
678 &last_name_off);
681 if (finished && out_of_space)
682 finished = False;
684 if (!finished && !out_of_space)
685 numentries++;
686 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
689 /* Check if we can close the dirptr */
690 if(close_after_first || (finished && close_if_end))
692 dptr_close(dptr_num);
693 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
694 dptr_num = -1;
697 /* At this point pdata points to numentries directory entries. */
699 /* Set up the return parameter block */
700 SSVAL(params,0,dptr_num);
701 SSVAL(params,2,numentries);
702 SSVAL(params,4,finished);
703 SSVAL(params,6,0); /* Never an EA error */
704 SSVAL(params,8,last_name_off);
706 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
708 if ((! *directory) && dptr_path(dptr_num))
709 sprintf(directory,"(%s)",dptr_path(dptr_num));
711 DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
712 timestring(),
713 smb_fn_name(CVAL(inbuf,smb_com)),
714 mask,directory,cnum,dirtype,numentries));
716 return(-1);
720 /****************************************************************************
721 reply to a TRANS2_FINDNEXT
722 ****************************************************************************/
723 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
724 int cnum, char **pparams, char **ppdata)
726 /* We must be careful here that we don't return more than the
727 allowed number of data bytes. If this means returning fewer than
728 maxentries then so be it. We assume that the redirector has
729 enough room for the fixed number of parameter bytes it has
730 requested. */
731 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
732 char *params = *pparams;
733 char *pdata = *ppdata;
734 int16 dptr_num = SVAL(params,0);
735 int maxentries = SVAL(params,2);
736 uint16 info_level = SVAL(params,4);
737 uint32 resume_key = IVAL(params,6);
738 BOOL close_after_request = BITSETW(params+10,0);
739 BOOL close_if_end = BITSETW(params+10,1);
740 BOOL requires_resume_key = BITSETW(params+10,2);
741 BOOL continue_bit = BITSETW(params+10,3);
742 pstring mask;
743 pstring directory;
744 char *p;
745 uint16 dirtype;
746 int numentries = 0;
747 int i, last_name_off=0;
748 BOOL finished = False;
749 BOOL dont_descend = False;
750 BOOL out_of_space = False;
751 int space_remaining;
753 *mask = *directory = 0;
755 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",
756 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
757 requires_resume_key, resume_key, continue_bit, info_level));
759 switch (info_level)
761 case 1:
762 case 2:
763 case 3:
764 case 4:
765 case SMB_FIND_FILE_DIRECTORY_INFO:
766 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
767 case SMB_FIND_FILE_NAMES_INFO:
768 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
769 break;
770 default:
771 return(ERROR(ERRDOS,ERRunknownlevel));
774 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
775 if(!*ppdata)
776 return(ERROR(ERRDOS,ERRnomem));
777 bzero(pdata,max_data_bytes);
779 /* Realloc the params space */
780 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
781 if(!params)
782 return(ERROR(ERRDOS,ERRnomem));
784 /* Check that the dptr is valid */
785 if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(SNUM(cnum), params, dptr_num)))
786 return(ERROR(ERRDOS,ERRnofiles));
788 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
790 /* Get the wildcard mask from the dptr */
791 if((p = dptr_wcard(dptr_num))== NULL) {
792 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
793 return (ERROR(ERRDOS,ERRnofiles));
795 strcpy(mask, p);
796 strcpy(directory,Connections[cnum].dirpath);
798 /* Get the attr mask from the dptr */
799 dirtype = dptr_attr(dptr_num);
801 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
802 dptr_num, mask, dirtype,
803 Connections[cnum].dirptr,
804 TellDir(Connections[cnum].dirptr)));
806 /* We don't need to check for VOL here as this is returned by
807 a different TRANS2 call. */
809 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
810 if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
811 dont_descend = True;
813 p = pdata;
814 space_remaining = max_data_bytes;
815 out_of_space = False;
817 /* If we have a resume key - seek to the correct position. */
818 if(requires_resume_key && !continue_bit)
819 SeekDir(Connections[cnum].dirptr, resume_key);
821 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
823 /* this is a heuristic to avoid seeking the dirptr except when
824 absolutely necessary. It allows for a filename of about 40 chars */
825 if (space_remaining < DIRLEN_GUESS && numentries > 0)
827 out_of_space = True;
828 finished = False;
830 else
832 finished =
833 !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
834 requires_resume_key,dont_descend,
835 &p,pdata,space_remaining, &out_of_space,
836 &last_name_off);
839 if (finished && out_of_space)
840 finished = False;
842 if (!finished && !out_of_space)
843 numentries++;
844 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
847 /* Check if we can close the dirptr */
848 if(close_after_request || (finished && close_if_end))
850 dptr_close(dptr_num); /* This frees up the saved mask */
851 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
852 dptr_num = -1;
856 /* Set up the return parameter block */
857 SSVAL(params,0,numentries);
858 SSVAL(params,2,finished);
859 SSVAL(params,4,0); /* Never an EA error */
860 SSVAL(params,6,last_name_off);
862 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
864 if ((! *directory) && dptr_path(dptr_num))
865 sprintf(directory,"(%s)",dptr_path(dptr_num));
867 DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
868 timestring(),
869 smb_fn_name(CVAL(inbuf,smb_com)),
870 mask,directory,cnum,dirtype,numentries));
872 return(-1);
875 /****************************************************************************
876 reply to a TRANS2_QFSINFO (query filesystem info)
877 ****************************************************************************/
878 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
879 int cnum, char **pparams, char **ppdata)
881 char *pdata = *ppdata;
882 char *params = *pparams;
883 uint16 info_level = SVAL(params,0);
884 int data_len;
885 struct stat st;
886 char *vname = volume_label(SNUM(cnum));
888 DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
890 if(sys_stat(".",&st)!=0) {
891 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
892 return (ERROR(ERRSRV,ERRinvdevice));
895 pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
897 switch (info_level)
899 case 1:
901 int dfree,dsize,bsize;
902 data_len = 18;
903 sys_disk_free(".",&bsize,&dfree,&dsize);
904 SIVAL(pdata,l1_idFileSystem,st.st_dev);
905 SIVAL(pdata,l1_cSectorUnit,bsize/512);
906 SIVAL(pdata,l1_cUnit,dsize);
907 SIVAL(pdata,l1_cUnitAvail,dfree);
908 SSVAL(pdata,l1_cbSector,512);
909 DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
910 bsize, st.st_dev, bsize/512, dsize, dfree, 512));
911 break;
913 case 2:
915 /* Return volume name */
916 int volname_len = MIN(strlen(vname),11);
917 data_len = l2_vol_szVolLabel + volname_len + 1;
918 put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
919 SCVAL(pdata,l2_vol_cch,volname_len);
920 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
921 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
922 pdata+l2_vol_szVolLabel));
923 break;
925 case SMB_QUERY_FS_ATTRIBUTE_INFO:
926 data_len = 12 + 2*strlen(FSTYPE_STRING);
927 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
928 SIVAL(pdata,4,128); /* Max filename component length */
929 SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
930 PutUniCode(pdata+12,FSTYPE_STRING);
931 break;
932 case SMB_QUERY_FS_LABEL_INFO:
933 data_len = 4 + strlen(vname);
934 SIVAL(pdata,0,strlen(vname));
935 strcpy(pdata+4,vname);
936 break;
937 case SMB_QUERY_FS_VOLUME_INFO:
938 data_len = 18 + 2*strlen(vname);
939 SIVAL(pdata,12,2*strlen(vname));
940 PutUniCode(pdata+18,vname);
941 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
942 vname));
943 break;
944 case SMB_QUERY_FS_SIZE_INFO:
946 int dfree,dsize,bsize;
947 data_len = 24;
948 sys_disk_free(".",&bsize,&dfree,&dsize);
949 SIVAL(pdata,0,dsize);
950 SIVAL(pdata,8,dfree);
951 SIVAL(pdata,16,bsize/512);
952 SIVAL(pdata,20,512);
954 break;
955 case SMB_QUERY_FS_DEVICE_INFO:
956 data_len = 8;
957 SIVAL(pdata,0,0); /* dev type */
958 SIVAL(pdata,4,0); /* characteristics */
959 break;
960 default:
961 return(ERROR(ERRDOS,ERRunknownlevel));
965 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
967 DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
969 return -1;
972 /****************************************************************************
973 reply to a TRANS2_SETFSINFO (set filesystem info)
974 ****************************************************************************/
975 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
976 int cnum, char **pparams, char **ppdata)
978 /* Just say yes we did it - there is nothing that
979 can be set here so it doesn't matter. */
980 int outsize;
981 DEBUG(3,("call_trans2setfsinfo\n"));
983 if (!CAN_WRITE(cnum))
984 return(ERROR(ERRSRV,ERRaccess));
986 outsize = set_message(outbuf,10,0,True);
988 return outsize;
991 /****************************************************************************
992 reply to a TRANS2_QFILEINFO (query file info by fileid)
993 ****************************************************************************/
994 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
995 int bufsize,int cnum,
996 char **pparams,char **ppdata,
997 int total_data)
999 char *params = *pparams;
1000 char *pdata = *ppdata;
1001 uint16 tran_call = SVAL(inbuf, smb_setup0);
1002 uint16 info_level;
1003 int mode=0;
1004 int size=0;
1005 unsigned int data_size;
1006 struct stat sbuf;
1007 pstring fname1;
1008 char *fname;
1009 char *p;
1010 int l,pos;
1013 if (tran_call == TRANSACT2_QFILEINFO) {
1014 int16 fnum = SVALS(params,0);
1015 info_level = SVAL(params,2);
1017 CHECK_FNUM(fnum,cnum);
1018 CHECK_ERROR(fnum);
1020 fname = Files[fnum].name;
1021 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1022 DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1023 return(UNIXERROR(ERRDOS,ERRbadfid));
1025 pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1026 } else {
1027 /* qpathinfo */
1028 info_level = SVAL(params,0);
1029 fname = &fname1[0];
1030 strcpy(fname,&params[6]);
1031 unix_convert(fname,cnum,0);
1032 if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1033 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1034 return(UNIXERROR(ERRDOS,ERRbadpath));
1036 pos = 0;
1040 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1041 fname,info_level,tran_call,total_data));
1043 p = strrchr(fname,'/');
1044 if (!p)
1045 p = fname;
1046 else
1047 p++;
1048 l = strlen(p);
1049 mode = dos_mode(cnum,fname,&sbuf);
1050 size = sbuf.st_size;
1051 if (mode & aDIR) size = 0;
1053 params = *pparams = Realloc(*pparams,2); bzero(params,2);
1054 data_size = 1024;
1055 pdata = *ppdata = Realloc(*ppdata, data_size);
1057 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1058 /* uggh, EAs for OS2 */
1059 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1060 #if 0
1061 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1062 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1063 return(-1);
1064 #else
1065 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1066 #endif
1069 bzero(pdata,data_size);
1071 switch (info_level)
1073 case SMB_INFO_STANDARD:
1074 case SMB_INFO_QUERY_EA_SIZE:
1075 data_size = (info_level==1?22:26);
1076 put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1077 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1078 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1079 SIVAL(pdata,l1_cbFile,size);
1080 SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1081 SSVAL(pdata,l1_attrFile,mode);
1082 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1083 break;
1085 case SMB_INFO_QUERY_EAS_FROM_LIST:
1086 data_size = 24;
1087 put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1088 put_dos_date2(pdata,4,sbuf.st_atime);
1089 put_dos_date2(pdata,8,sbuf.st_mtime);
1090 SIVAL(pdata,12,size);
1091 SIVAL(pdata,16,ROUNDUP(size,1024));
1092 SIVAL(pdata,20,mode);
1093 break;
1095 case SMB_INFO_QUERY_ALL_EAS:
1096 data_size = 4;
1097 SIVAL(pdata,0,data_size);
1098 break;
1100 case 6:
1101 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1103 case SMB_QUERY_FILE_BASIC_INFO:
1104 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1105 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1106 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1107 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1108 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1109 SIVAL(pdata,32,mode);
1111 DEBUG(5,("SMB_QFBI - "));
1112 DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1113 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1114 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1115 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1116 DEBUG(5,("mode: %x\n", mode));
1118 break;
1120 case SMB_QUERY_FILE_STANDARD_INFO:
1121 data_size = 22;
1122 SIVAL(pdata,0,size);
1123 SIVAL(pdata,8,size);
1124 SIVAL(pdata,16,sbuf.st_nlink);
1125 CVAL(pdata,20) = 0;
1126 CVAL(pdata,21) = (mode&aDIR)?1:0;
1127 break;
1129 case SMB_QUERY_FILE_EA_INFO:
1130 data_size = 4;
1131 break;
1133 case SMB_QUERY_FILE_NAME_INFO:
1134 case SMB_QUERY_FILE_ALT_NAME_INFO:
1135 data_size = 4 + l;
1136 SIVAL(pdata,0,l);
1137 strcpy(pdata+4,fname);
1138 break;
1139 case SMB_QUERY_FILE_ALLOCATION_INFO:
1140 case SMB_QUERY_FILE_END_OF_FILEINFO:
1141 data_size = 8;
1142 SIVAL(pdata,0,size);
1143 break;
1145 case SMB_QUERY_FILE_ALL_INFO:
1146 put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1147 put_long_date(pdata+8,sbuf.st_atime); /* access time */
1148 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1149 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1150 SIVAL(pdata,32,mode);
1151 pdata += 40;
1152 SIVAL(pdata,0,size);
1153 SIVAL(pdata,8,size);
1154 SIVAL(pdata,16,sbuf.st_nlink);
1155 CVAL(pdata,20) = 0;
1156 CVAL(pdata,21) = (mode&aDIR)?1:0;
1157 pdata += 24;
1158 pdata += 8; /* index number */
1159 pdata += 4; /* EA info */
1160 if (mode & aRONLY)
1161 SIVAL(pdata,0,0xA9);
1162 else
1163 SIVAL(pdata,0,0xd01BF);
1164 pdata += 4;
1165 SIVAL(pdata,0,pos); /* current offset */
1166 pdata += 8;
1167 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1168 pdata += 4;
1169 pdata += 4; /* alignment */
1170 SIVAL(pdata,0,l);
1171 strcpy(pdata+4,fname);
1172 pdata += 4 + l;
1173 data_size = PTR_DIFF(pdata,(*ppdata));
1174 break;
1176 case SMB_QUERY_FILE_STREAM_INFO:
1177 data_size = 24 + l;
1178 SIVAL(pdata,0,pos);
1179 SIVAL(pdata,4,size);
1180 SIVAL(pdata,12,size);
1181 SIVAL(pdata,20,l);
1182 strcpy(pdata+24,fname);
1183 break;
1184 default:
1185 return(ERROR(ERRDOS,ERRunknownlevel));
1188 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1190 return(-1);
1193 /****************************************************************************
1194 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1195 ****************************************************************************/
1196 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
1197 int bufsize, int cnum, char **pparams,
1198 char **ppdata, int total_data)
1200 char *params = *pparams;
1201 char *pdata = *ppdata;
1202 uint16 tran_call = SVAL(inbuf, smb_setup0);
1203 uint16 info_level;
1204 int mode=0;
1205 int size=0;
1206 struct utimbuf tvs;
1207 struct stat st;
1208 pstring fname1;
1209 char *fname;
1210 int fd = -1;
1212 if (!CAN_WRITE(cnum))
1213 return(ERROR(ERRSRV,ERRaccess));
1215 if (tran_call == TRANSACT2_SETFILEINFO) {
1216 int16 fnum = SVALS(params,0);
1217 info_level = SVAL(params,2);
1219 CHECK_FNUM(fnum,cnum);
1220 CHECK_ERROR(fnum);
1222 fname = Files[fnum].name;
1223 fd = Files[fnum].fd_ptr->fd;
1225 if(fstat(fd,&st)!=0) {
1226 DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1227 return(ERROR(ERRDOS,ERRbadpath));
1229 } else {
1230 /* set path info */
1231 info_level = SVAL(params,0);
1232 fname = fname1;
1233 strcpy(fname,&params[6]);
1234 unix_convert(fname,cnum,0);
1235 if(!check_name(fname, cnum))
1236 return(ERROR(ERRDOS,ERRbadpath));
1238 if(sys_stat(fname,&st)!=0) {
1239 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1240 return(ERROR(ERRDOS,ERRbadpath));
1244 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1245 tran_call,fname,info_level,total_data));
1247 /* Realloc the parameter and data sizes */
1248 params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1249 if(params == NULL)
1250 return(ERROR(ERRDOS,ERRnomem));
1252 size = st.st_size;
1253 tvs.modtime = st.st_mtime;
1254 tvs.actime = st.st_atime;
1255 mode = dos_mode(cnum,fname,&st);
1257 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1258 /* uggh, EAs for OS2 */
1259 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1260 SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
1262 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1264 return(-1);
1267 switch (info_level)
1269 case SMB_INFO_STANDARD:
1270 case SMB_INFO_QUERY_EA_SIZE:
1272 /* access time */
1273 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1275 /* write time */
1276 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1278 mode = SVAL(pdata,l1_attrFile);
1279 size = IVAL(pdata,l1_cbFile);
1280 break;
1283 /* XXXX um, i don't think this is right.
1284 it's also not in the cifs6.txt spec.
1286 case SMB_INFO_QUERY_EAS_FROM_LIST:
1287 tvs.actime = make_unix_date2(pdata+8);
1288 tvs.modtime = make_unix_date2(pdata+12);
1289 size = IVAL(pdata,16);
1290 mode = IVAL(pdata,24);
1291 break;
1293 /* XXXX nor this. not in cifs6.txt, either. */
1294 case SMB_INFO_QUERY_ALL_EAS:
1295 tvs.actime = make_unix_date2(pdata+8);
1296 tvs.modtime = make_unix_date2(pdata+12);
1297 size = IVAL(pdata,16);
1298 mode = IVAL(pdata,24);
1299 break;
1301 case SMB_SET_FILE_BASIC_INFO:
1303 /* Ignore create time at offset pdata. */
1305 /* access time */
1306 tvs.actime = interpret_long_date(pdata+8);
1308 /* write time + changed time, combined. */
1309 tvs.modtime=MAX(interpret_long_date(pdata+16),
1310 interpret_long_date(pdata+24));
1312 /* attributes */
1313 mode = IVAL(pdata,32);
1314 break;
1317 case SMB_SET_FILE_END_OF_FILE_INFO:
1319 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1320 return(ERROR(ERRDOS,ERRunknownlevel));
1321 size = IVAL(pdata,0);
1322 break;
1325 case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1326 case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1327 default:
1329 return(ERROR(ERRDOS,ERRunknownlevel));
1333 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1334 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1335 DEBUG(6,("size: %x " , size));
1336 DEBUG(6,("mode: %x\n" , mode));
1338 /* get some defaults (no modifications) if any info is zero. */
1339 if (!tvs.actime) tvs.actime = st.st_atime;
1340 if (!tvs.modtime) tvs.modtime = st.st_mtime;
1341 if (!size) size = st.st_size;
1343 /* Try and set the times, size and mode of this file -
1344 if they are different from the current values
1346 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1348 if(sys_utime(fname, &tvs)!=0)
1350 return(ERROR(ERRDOS,ERRnoaccess));
1354 /* check the mode isn't different, before changing it */
1355 if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1357 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1358 return(ERROR(ERRDOS,ERRnoaccess));
1361 if(size != st.st_size)
1363 if (fd == -1)
1365 fd = sys_open(fname,O_RDWR,0);
1366 if (fd == -1)
1368 return(ERROR(ERRDOS,ERRbadpath));
1370 set_filelen(fd, size);
1371 close(fd);
1373 else
1375 set_filelen(fd, size);
1379 SSVAL(params,0,0);
1381 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1383 return(-1);
1386 /****************************************************************************
1387 reply to a TRANS2_MKDIR (make directory with extended attributes).
1388 ****************************************************************************/
1389 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1390 int cnum, char **pparams, char **ppdata)
1392 char *params = *pparams;
1393 pstring directory;
1394 int ret = -1;
1396 if (!CAN_WRITE(cnum))
1397 return(ERROR(ERRSRV,ERRaccess));
1399 strcpy(directory, &params[4]);
1401 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1403 unix_convert(directory,cnum,0);
1404 if (check_name(directory,cnum))
1405 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1407 if(ret < 0)
1409 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1410 return(UNIXERROR(ERRDOS,ERRnoaccess));
1413 /* Realloc the parameter and data sizes */
1414 params = *pparams = Realloc(*pparams,2);
1415 if(params == NULL)
1416 return(ERROR(ERRDOS,ERRnomem));
1418 SSVAL(params,0,0);
1420 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1422 return(-1);
1425 /****************************************************************************
1426 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1427 We don't actually do this - we just send a null response.
1428 ****************************************************************************/
1429 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1430 int cnum, char **pparams, char **ppdata)
1432 static uint16 fnf_handle = 257;
1433 char *params = *pparams;
1434 uint16 info_level = SVAL(params,4);
1436 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1438 switch (info_level)
1440 case 1:
1441 case 2:
1442 break;
1443 default:
1444 return(ERROR(ERRDOS,ERRunknownlevel));
1447 /* Realloc the parameter and data sizes */
1448 params = *pparams = Realloc(*pparams,6);
1449 if(params == NULL)
1450 return(ERROR(ERRDOS,ERRnomem));
1452 SSVAL(params,0,fnf_handle);
1453 SSVAL(params,2,0); /* No changes */
1454 SSVAL(params,4,0); /* No EA errors */
1456 fnf_handle++;
1458 if(fnf_handle == 0)
1459 fnf_handle = 257;
1461 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1463 return(-1);
1466 /****************************************************************************
1467 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
1468 changes). Currently this does nothing.
1469 ****************************************************************************/
1470 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1471 int cnum, char **pparams, char **ppdata)
1473 char *params = *pparams;
1475 DEBUG(3,("call_trans2findnotifynext\n"));
1477 /* Realloc the parameter and data sizes */
1478 params = *pparams = Realloc(*pparams,4);
1479 if(params == NULL)
1480 return(ERROR(ERRDOS,ERRnomem));
1482 SSVAL(params,0,0); /* No changes */
1483 SSVAL(params,2,0); /* No EA errors */
1485 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1487 return(-1);
1490 /****************************************************************************
1491 reply to a SMBfindclose (stop trans2 directory search)
1492 ****************************************************************************/
1493 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1495 int cnum;
1496 int outsize = 0;
1497 int16 dptr_num=SVALS(inbuf,smb_vwv0);
1499 cnum = SVAL(inbuf,smb_tid);
1501 DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1503 dptr_close(dptr_num);
1505 outsize = set_message(outbuf,0,0,True);
1507 DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1509 return(outsize);
1512 /****************************************************************************
1513 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1514 ****************************************************************************/
1515 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1517 int cnum;
1518 int outsize = 0;
1519 int dptr_num= -1;
1521 cnum = SVAL(inbuf,smb_tid);
1522 dptr_num = SVAL(inbuf,smb_vwv0);
1524 DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1526 /* We never give out valid handles for a
1527 findnotifyfirst - so any dptr_num is ok here.
1528 Just ignore it. */
1530 outsize = set_message(outbuf,0,0,True);
1532 DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1534 return(outsize);
1538 /****************************************************************************
1539 reply to a SMBtranss2 - just ignore it!
1540 ****************************************************************************/
1541 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1543 DEBUG(4,("Ignoring transs2 of length %d\n",length));
1544 return(-1);
1547 /****************************************************************************
1548 reply to a SMBtrans2
1549 ****************************************************************************/
1550 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1552 int outsize = 0;
1553 int cnum = SVAL(inbuf,smb_tid);
1554 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1555 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1556 #if 0
1557 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1558 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1559 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1560 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1561 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1562 int32 timeout = IVALS(inbuf,smb_timeout);
1563 #endif
1564 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1565 unsigned int tran_call = SVAL(inbuf, smb_setup0);
1566 char *params = NULL, *data = NULL;
1567 int num_params, num_params_sofar, num_data, num_data_sofar;
1569 outsize = set_message(outbuf,0,0,True);
1571 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1572 is so as a sanity check */
1573 if(suwcnt != 1 )
1575 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1576 return(ERROR(ERRSRV,ERRerror));
1579 /* Allocate the space for the maximum needed parameters and data */
1580 if (total_params > 0)
1581 params = (char *)malloc(total_params);
1582 if (total_data > 0)
1583 data = (char *)malloc(total_data);
1585 if ((total_params && !params) || (total_data && !data))
1587 DEBUG(2,("Out of memory in reply_trans2\n"));
1588 return(ERROR(ERRDOS,ERRnomem));
1591 /* Copy the param and data bytes sent with this request into
1592 the params buffer */
1593 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1594 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1596 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1597 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1599 if(num_data_sofar < total_data || num_params_sofar < total_params)
1601 /* We need to send an interim response then receive the rest
1602 of the parameter/data bytes */
1603 outsize = set_message(outbuf,0,0,True);
1604 send_smb(Client,outbuf);
1606 while( num_data_sofar < total_data || num_params_sofar < total_params)
1608 if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1609 CVAL(inbuf, smb_com) != SMBtranss2)
1611 outsize = set_message(outbuf,0,0,True);
1612 DEBUG(2,("Invalid secondary trans2 packet\n"));
1613 free(params);
1614 free(data);
1615 return(ERROR(ERRSRV,ERRerror));
1618 /* Revise total_params and total_data in case they have changed downwards */
1619 total_params = SVAL(inbuf, smb_tpscnt);
1620 total_data = SVAL(inbuf, smb_tdscnt);
1621 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1622 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1623 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
1624 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1625 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1626 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1630 if (Protocol >= PROTOCOL_NT1) {
1631 uint16 flg2 = SVAL(outbuf,smb_flg2);
1632 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1635 /* Now we must call the relevant TRANS2 function */
1636 switch(tran_call)
1638 case TRANSACT2_OPEN:
1639 outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1640 break;
1641 case TRANSACT2_FINDFIRST:
1642 outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1643 break;
1644 case TRANSACT2_FINDNEXT:
1645 outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1646 break;
1647 case TRANSACT2_QFSINFO:
1648 outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1649 break;
1650 case TRANSACT2_SETFSINFO:
1651 outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1652 break;
1653 case TRANSACT2_QPATHINFO:
1654 case TRANSACT2_QFILEINFO:
1655 outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1656 break;
1657 case TRANSACT2_SETPATHINFO:
1658 case TRANSACT2_SETFILEINFO:
1659 outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1660 break;
1661 case TRANSACT2_FINDNOTIFYFIRST:
1662 outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1663 break;
1664 case TRANSACT2_FINDNOTIFYNEXT:
1665 outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1666 break;
1667 case TRANSACT2_MKDIR:
1668 outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1669 break;
1670 default:
1671 /* Error in request */
1672 DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1673 if(params)
1674 free(params);
1675 if(data)
1676 free(data);
1677 return (ERROR(ERRSRV,ERRerror));
1680 /* As we do not know how many data packets will need to be
1681 returned here the various call_trans2xxxx calls
1682 must send their own. Thus a call_trans2xxx routine only
1683 returns a value other than -1 when it wants to send
1684 an error packet.
1687 if(params)
1688 free(params);
1689 if(data)
1690 free(data);
1691 return outsize; /* If a correct response was needed the call_trans2xxx
1692 calls have already sent it. If outsize != -1 then it is
1693 returning an error packet. */