Restructuring of vfs layer to include a "this" pointer - can be an fsp or
[Samba.git] / source / smbd / trans2.c
blob7df1c09fa006de1c41eeca1b312f35f83f817416
1 #define OLD_NTDOMAIN 1
3 /*
4 Unix SMB/Netbios implementation.
5 Version 1.9.
6 SMB transaction2 handling
7 Copyright (C) Jeremy Allison 1994-1998
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 extern int DEBUGLEVEL;
29 extern int Protocol;
30 extern BOOL case_sensitive;
31 extern int smb_read_error;
32 extern fstring local_machine;
33 extern int global_oplock_break;
34 extern uint32 global_client_caps;
36 /****************************************************************************
37 Send the required number of replies back.
38 We assume all fields other than the data fields are
39 set correctly for the type of call.
40 HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params,
43 int paramsize, char *pdata, int datasize)
45 /* As we are using a protocol > LANMAN1 then the max_send
46 variable must have been set in the sessetupX call.
47 This takes precedence over the max_xmit field in the
48 global struct. These different max_xmit variables should
49 be merged as this is now too confusing */
51 extern int max_send;
52 int data_to_send = datasize;
53 int params_to_send = paramsize;
54 int useable_space;
55 char *pp = params;
56 char *pd = pdata;
57 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58 int alignment_offset = 3;
59 int data_alignment_offset = 0;
61 /* Initially set the wcnt area to be 10 - this is true for all
62 trans2 replies */
63 set_message(outbuf,10,0,True);
65 /* If there genuinely are no parameters or data to send just send
66 the empty packet */
67 if(params_to_send == 0 && data_to_send == 0)
69 send_smb(smbd_server_fd(),outbuf);
70 return 0;
73 /* When sending params and data ensure that both are nicely aligned */
74 /* Only do this alignment when there is also data to send - else
75 can cause NT redirector problems. */
76 if (((params_to_send % 4) != 0) && (data_to_send != 0))
77 data_alignment_offset = 4 - (params_to_send % 4);
79 /* Space is bufsize minus Netbios over TCP header minus SMB header */
80 /* The alignment_offset is to align the param bytes on an even byte
81 boundary. NT 4.0 Beta needs this to work correctly. */
82 useable_space = bufsize - ((smb_buf(outbuf)+
83 alignment_offset+data_alignment_offset) -
84 outbuf);
86 /* useable_space can never be more than max_send minus the
87 alignment offset. */
88 useable_space = MIN(useable_space,
89 max_send - (alignment_offset+data_alignment_offset));
92 while (params_to_send || data_to_send)
94 /* Calculate whether we will totally or partially fill this packet */
95 total_sent_thistime = params_to_send + data_to_send +
96 alignment_offset + data_alignment_offset;
97 /* We can never send more than useable_space */
99 * Note that 'useable_space' does not include the alignment offsets,
100 * but we must include the alignment offsets in the calculation of
101 * the length of the data we send over the wire, as the alignment offsets
102 * are sent here. Fix from Marc_Jacobsen@hp.com.
104 total_sent_thistime = MIN(total_sent_thistime, useable_space+
105 alignment_offset + data_alignment_offset);
107 set_message(outbuf, 10, total_sent_thistime, True);
109 /* Set total params and data to be sent */
110 SSVAL(outbuf,smb_tprcnt,paramsize);
111 SSVAL(outbuf,smb_tdrcnt,datasize);
113 /* Calculate how many parameters and data we can fit into
114 this packet. Parameters get precedence */
116 params_sent_thistime = MIN(params_to_send,useable_space);
117 data_sent_thistime = useable_space - params_sent_thistime;
118 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
120 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
122 /* smb_proff is the offset from the start of the SMB header to the
123 parameter bytes, however the first 4 bytes of outbuf are
124 the Netbios over TCP header. Thus use smb_base() to subtract
125 them from the calculation */
127 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
129 if(params_sent_thistime == 0)
130 SSVAL(outbuf,smb_prdisp,0);
131 else
132 /* Absolute displacement of param bytes sent in this packet */
133 SSVAL(outbuf,smb_prdisp,pp - params);
135 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
136 if(data_sent_thistime == 0)
138 SSVAL(outbuf,smb_droff,0);
139 SSVAL(outbuf,smb_drdisp, 0);
141 else
143 /* The offset of the data bytes is the offset of the
144 parameter bytes plus the number of parameters being sent this time */
145 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
146 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
147 SSVAL(outbuf,smb_drdisp, pd - pdata);
150 /* Copy the param bytes into the packet */
151 if(params_sent_thistime)
152 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
153 /* Copy in the data bytes */
154 if(data_sent_thistime)
155 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
156 data_alignment_offset,pd,data_sent_thistime);
158 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
159 params_sent_thistime, data_sent_thistime, useable_space));
160 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
161 params_to_send, data_to_send, paramsize, datasize));
163 /* Send the packet */
164 send_smb(smbd_server_fd(),outbuf);
166 pp += params_sent_thistime;
167 pd += data_sent_thistime;
169 params_to_send -= params_sent_thistime;
170 data_to_send -= data_sent_thistime;
172 /* Sanity check */
173 if(params_to_send < 0 || data_to_send < 0)
175 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
176 params_to_send, data_to_send));
177 return -1;
181 return 0;
185 /****************************************************************************
186 reply to a TRANSACT2_OPEN
187 ****************************************************************************/
188 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
189 int bufsize,
190 char **pparams, char **ppdata)
192 char *params = *pparams;
193 int16 open_mode = SVAL(params, 2);
194 int16 open_attr = SVAL(params,6);
195 BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
196 #if 0
197 BOOL return_additional_info = BITSETW(params,0);
198 int16 open_sattr = SVAL(params, 4);
199 time_t open_time = make_unix_date3(params+8);
200 #endif
201 int16 open_ofun = SVAL(params,12);
202 int32 open_size = IVAL(params,14);
203 char *pname = &params[28];
204 int16 namelen = strlen(pname)+1;
206 pstring fname;
207 mode_t unixmode;
208 SMB_OFF_T size=0;
209 int fmode=0,mtime=0,rmode;
210 SMB_INO_T inode = 0;
211 SMB_STRUCT_STAT sbuf;
212 int smb_action = 0;
213 BOOL bad_path = False;
214 files_struct *fsp;
216 StrnCpy(fname,pname,namelen);
218 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
219 fname,open_mode, open_attr, open_ofun, open_size));
221 if (IS_IPC(conn)) {
222 return(ERROR(ERRSRV,ERRaccess));
225 /* XXXX we need to handle passed times, sattr and flags */
227 unix_convert(fname,conn,0,&bad_path,NULL);
229 if (!check_name(fname,conn))
231 if((errno == ENOENT) && bad_path)
233 unix_ERR_class = ERRDOS;
234 unix_ERR_code = ERRbadpath;
236 return(UNIXERROR(ERRDOS,ERRnoaccess));
239 unixmode = unix_mode(conn,open_attr | aARCH, fname);
241 fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode,
242 oplock_request, &rmode,&smb_action);
244 if (!fsp)
246 if((errno == ENOENT) && bad_path)
248 unix_ERR_class = ERRDOS;
249 unix_ERR_code = ERRbadpath;
251 return(UNIXERROR(ERRDOS,ERRnoaccess));
254 if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) {
255 close_file(fsp,False);
256 return(UNIXERROR(ERRDOS,ERRnoaccess));
259 size = sbuf.st_size;
260 fmode = dos_mode(conn,fname,&sbuf);
261 mtime = sbuf.st_mtime;
262 inode = sbuf.st_ino;
263 if (fmode & aDIR) {
264 close_file(fsp,False);
265 return(ERROR(ERRDOS,ERRnoaccess));
268 /* Realloc the size of parameters and data we will return */
269 params = *pparams = Realloc(*pparams, 28);
270 if(params == NULL)
271 return(ERROR(ERRDOS,ERRnomem));
273 memset((char *)params,'\0',28);
274 SSVAL(params,0,fsp->fnum);
275 SSVAL(params,2,fmode);
276 put_dos_date2(params,4, mtime);
277 SIVAL(params,8, (uint32)size);
278 SSVAL(params,12,rmode);
280 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
281 smb_action |= EXTENDED_OPLOCK_GRANTED;
284 SSVAL(params,18,smb_action);
286 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
288 SIVAL(params,20,inode);
290 /* Send the required number of replies */
291 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
293 return -1;
296 /*********************************************************
297 * Routine to check if a given string matches exactly.
298 * as a special case a mask of "." does NOT match. That
299 * is required for correct wildcard semantics
300 * Case can be significant or not.
301 **********************************************************/
302 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
304 if (mask[0] == '.' && mask[1] == 0) return False;
305 if (case_sig) return strcmp(str,mask)==0;
306 return strcasecmp(str,mask) == 0;
309 /****************************************************************************
310 get a level dependent lanman2 dir entry.
311 ****************************************************************************/
312 static BOOL get_lanman2_dir_entry(connection_struct *conn,
313 char *path_mask,int dirtype,int info_level,
314 int requires_resume_key,
315 BOOL dont_descend,char **ppdata,
316 char *base_data, int space_remaining,
317 BOOL *out_of_space, BOOL *got_exact_match,
318 int *last_name_off)
320 char *dname;
321 BOOL found = False;
322 SMB_STRUCT_STAT sbuf;
323 pstring mask;
324 pstring pathreal;
325 pstring fname;
326 char *p, *pdata = *ppdata;
327 uint32 reskey=0;
328 int prev_dirpos=0;
329 int mode=0;
330 SMB_OFF_T size = 0;
331 uint32 len;
332 time_t mdate=0, adate=0, cdate=0;
333 char *nameptr;
334 BOOL was_8_3;
335 int nt_extmode; /* Used for NT connections instead of mode */
336 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
338 *fname = 0;
339 *out_of_space = False;
340 *got_exact_match = False;
342 if (!conn->dirptr)
343 return(False);
345 p = strrchr(path_mask,'/');
346 if(p != NULL)
348 if(p[1] == '\0')
349 pstrcpy(mask,"*.*");
350 else
351 pstrcpy(mask, p+1);
353 else
354 pstrcpy(mask, path_mask);
356 while (!found)
358 BOOL got_match;
360 /* Needed if we run out of space */
361 prev_dirpos = TellDir(conn->dirptr);
362 dname = ReadDirName(conn->dirptr);
365 * Due to bugs in NT client redirectors we are not using
366 * resume keys any more - set them to zero.
367 * Check out the related comments in findfirst/findnext.
368 * JRA.
371 reskey = 0;
373 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
374 (long)conn->dirptr,TellDir(conn->dirptr)));
376 if (!dname)
377 return(False);
379 pstrcpy(fname,dname);
381 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
382 got_match = mask_match(fname, mask, case_sensitive);
384 if(!got_match && !is_8_3(fname, False)) {
387 * It turns out that NT matches wildcards against
388 * both long *and* short names. This may explain some
389 * of the wildcard wierdness from old DOS clients
390 * that some people have been seeing.... JRA.
393 pstring newname;
394 pstrcpy( newname, fname);
395 name_map_mangle( newname, True, False, SNUM(conn));
396 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
397 got_match = mask_match(newname, mask, case_sensitive);
400 if(got_match)
402 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
403 if (dont_descend && !isdots)
404 continue;
406 pstrcpy(pathreal,conn->dirpath);
407 if(needslash)
408 pstrcat(pathreal,"/");
409 pstrcat(pathreal,dname);
410 if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal,False),&sbuf) != 0)
412 /* Needed to show the msdfs symlinks as directories */
413 if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn))
414 || !is_msdfs_link(conn, pathreal))
416 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
417 pathreal,strerror(errno)));
418 continue;
420 else
422 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
423 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
427 mode = dos_mode(conn,pathreal,&sbuf);
429 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
430 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
431 continue;
434 size = sbuf.st_size;
435 mdate = sbuf.st_mtime;
436 adate = sbuf.st_atime;
437 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
438 if(mode & aDIR)
439 size = 0;
441 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
443 found = True;
447 name_map_mangle(fname,False,True,SNUM(conn));
449 p = pdata;
450 nameptr = p;
452 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
454 switch (info_level)
456 case 1:
457 if(requires_resume_key) {
458 SIVAL(p,0,reskey);
459 p += 4;
461 put_dos_date2(p,l1_fdateCreation,cdate);
462 put_dos_date2(p,l1_fdateLastAccess,adate);
463 put_dos_date2(p,l1_fdateLastWrite,mdate);
464 SIVAL(p,l1_cbFile,(uint32)size);
465 SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
466 SSVAL(p,l1_attrFile,mode);
467 SCVAL(p,l1_cchName,strlen(fname));
468 pstrcpy(p + l1_achName, fname);
469 nameptr = p + l1_achName;
470 p += l1_achName + strlen(fname) + 1;
471 break;
473 case 2:
474 /* info_level 2 */
475 if(requires_resume_key) {
476 SIVAL(p,0,reskey);
477 p += 4;
479 put_dos_date2(p,l2_fdateCreation,cdate);
480 put_dos_date2(p,l2_fdateLastAccess,adate);
481 put_dos_date2(p,l2_fdateLastWrite,mdate);
482 SIVAL(p,l2_cbFile,(uint32)size);
483 SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
484 SSVAL(p,l2_attrFile,mode);
485 SIVAL(p,l2_cbList,0); /* No extended attributes */
486 SCVAL(p,l2_cchName,strlen(fname));
487 pstrcpy(p + l2_achName, fname);
488 nameptr = p + l2_achName;
489 p += l2_achName + strlen(fname) + 1;
490 break;
492 case 3:
493 SIVAL(p,0,reskey);
494 put_dos_date2(p,4,cdate);
495 put_dos_date2(p,8,adate);
496 put_dos_date2(p,12,mdate);
497 SIVAL(p,16,(uint32)size);
498 SIVAL(p,20,SMB_ROUNDUP(size,1024));
499 SSVAL(p,24,mode);
500 SIVAL(p,26,4);
501 CVAL(p,30) = strlen(fname);
502 pstrcpy(p+31, fname);
503 nameptr = p+31;
504 p += 31 + strlen(fname) + 1;
505 break;
507 case 4:
508 if(requires_resume_key) {
509 SIVAL(p,0,reskey);
510 p += 4;
512 SIVAL(p,0,33+strlen(fname)+1);
513 put_dos_date2(p,4,cdate);
514 put_dos_date2(p,8,adate);
515 put_dos_date2(p,12,mdate);
516 SIVAL(p,16,(uint32)size);
517 SIVAL(p,20,SMB_ROUNDUP(size,1024));
518 SSVAL(p,24,mode);
519 CVAL(p,32) = strlen(fname);
520 pstrcpy(p + 33, fname);
521 nameptr = p+33;
522 p += 33 + strlen(fname) + 1;
523 break;
525 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
526 was_8_3 = is_8_3(fname, True);
527 len = 94+strlen(fname);
528 len = (len + 3) & ~3;
529 SIVAL(p,0,len); p += 4;
530 SIVAL(p,0,reskey); p += 4;
531 put_long_date(p,cdate); p += 8;
532 put_long_date(p,adate); p += 8;
533 put_long_date(p,mdate); p += 8;
534 put_long_date(p,mdate); p += 8;
535 SOFF_T(p,0,size);
536 SOFF_T(p,8,size);
537 p += 16;
538 SIVAL(p,0,nt_extmode); p += 4;
539 SIVAL(p,0,strlen(fname)); p += 4;
540 SIVAL(p,0,0); p += 4;
541 if (!was_8_3) {
542 fstrcpy(p+2,fname);
543 name_map_mangle(p+2,True,True,SNUM(conn));
544 strupper(p+2);
545 SSVAL(p, 0, strlen(p+2));
546 } else {
547 SSVAL(p,0,0);
548 *(p+2) = 0;
550 p += 2 + 24;
551 /* nameptr = p; */
552 pstrcpy(p,fname); p += strlen(p);
553 p = pdata + len;
554 break;
556 case SMB_FIND_FILE_DIRECTORY_INFO:
557 len = 64+strlen(fname);
558 len = (len + 3) & ~3;
559 SIVAL(p,0,len); p += 4;
560 SIVAL(p,0,reskey); p += 4;
561 put_long_date(p,cdate); p += 8;
562 put_long_date(p,adate); p += 8;
563 put_long_date(p,mdate); p += 8;
564 put_long_date(p,mdate); p += 8;
565 SOFF_T(p,0,size);
566 SOFF_T(p,8,size);
567 p += 16;
568 SIVAL(p,0,nt_extmode); p += 4;
569 SIVAL(p,0,strlen(fname)); p += 4;
570 pstrcpy(p,fname);
571 p = pdata + len;
572 break;
575 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
576 len = 68+strlen(fname);
577 len = (len + 3) & ~3;
578 SIVAL(p,0,len); p += 4;
579 SIVAL(p,0,reskey); p += 4;
580 put_long_date(p,cdate); p += 8;
581 put_long_date(p,adate); p += 8;
582 put_long_date(p,mdate); p += 8;
583 put_long_date(p,mdate); p += 8;
584 SOFF_T(p,0,size);
585 SOFF_T(p,8,size);
586 p += 16;
587 SIVAL(p,0,nt_extmode); p += 4;
588 SIVAL(p,0,strlen(fname)); p += 4;
589 SIVAL(p,0,0); p += 4;
590 pstrcpy(p,fname);
591 p = pdata + len;
592 break;
594 case SMB_FIND_FILE_NAMES_INFO:
595 len = 12+strlen(fname);
596 len = (len + 3) & ~3;
597 SIVAL(p,0,len); p += 4;
598 SIVAL(p,0,reskey); p += 4;
599 SIVAL(p,0,strlen(fname)); p += 4;
600 pstrcpy(p,fname);
601 p = pdata + len;
602 break;
604 default:
605 return(False);
609 if (PTR_DIFF(p,pdata) > space_remaining) {
610 /* Move the dirptr back to prev_dirpos */
611 SeekDir(conn->dirptr, prev_dirpos);
612 *out_of_space = True;
613 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
614 return False; /* Not finished - just out of space */
617 /* Setup the last_filename pointer, as an offset from base_data */
618 *last_name_off = PTR_DIFF(nameptr,base_data);
619 /* Advance the data pointer to the next slot */
620 *ppdata = p;
622 return(found);
626 /****************************************************************************
627 Reply to a TRANS2_FINDFIRST.
628 ****************************************************************************/
630 static int call_trans2findfirst(connection_struct *conn,
631 char *inbuf, char *outbuf, int bufsize,
632 char **pparams, char **ppdata)
634 /* We must be careful here that we don't return more than the
635 allowed number of data bytes. If this means returning fewer than
636 maxentries then so be it. We assume that the redirector has
637 enough room for the fixed number of parameter bytes it has
638 requested. */
639 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
640 char *params = *pparams;
641 char *pdata = *ppdata;
642 int dirtype = SVAL(params,0);
643 int maxentries = SVAL(params,2);
644 BOOL close_after_first = BITSETW(params+4,0);
645 BOOL close_if_end = BITSETW(params+4,1);
646 BOOL requires_resume_key = BITSETW(params+4,2);
647 int info_level = SVAL(params,6);
648 pstring directory;
649 pstring mask;
650 char *p, *wcard;
651 int last_name_off=0;
652 int dptr_num = -1;
653 int numentries = 0;
654 int i;
655 BOOL finished = False;
656 BOOL dont_descend = False;
657 BOOL out_of_space = False;
658 int space_remaining;
659 BOOL bad_path = False;
661 *directory = *mask = 0;
663 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",
664 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
665 info_level, max_data_bytes));
667 switch (info_level)
669 case 1:
670 case 2:
671 case 3:
672 case 4:
673 case SMB_FIND_FILE_DIRECTORY_INFO:
674 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
675 case SMB_FIND_FILE_NAMES_INFO:
676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
677 break;
678 default:
679 return(ERROR(ERRDOS,ERRunknownlevel));
682 pstrcpy(directory, params + 12); /* Complete directory path with
683 wildcard mask appended */
685 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
687 DEBUG(5,("path=%s\n",directory));
689 unix_convert(directory,conn,0,&bad_path,NULL);
690 if(!check_name(directory,conn)) {
691 if((errno == ENOENT) && bad_path)
693 unix_ERR_class = ERRDOS;
694 unix_ERR_code = ERRbadpath;
697 #if 0
698 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
699 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
700 (get_remote_arch() == RA_WINNT))
702 unix_ERR_class = ERRDOS;
703 unix_ERR_code = ERRbaddirectory;
705 #endif
707 return(UNIXERROR(ERRDOS,ERRbadpath));
710 p = strrchr(directory,'/');
711 if(p == NULL) {
712 pstrcpy(mask,directory);
713 pstrcpy(directory,"./");
714 } else {
715 pstrcpy(mask,p+1);
716 *p = 0;
719 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
721 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
722 if(!*ppdata)
723 return(ERROR(ERRDOS,ERRnomem));
724 memset((char *)pdata,'\0',max_data_bytes + 1024);
726 /* Realloc the params space */
727 params = *pparams = Realloc(*pparams, 10);
728 if(params == NULL)
729 return(ERROR(ERRDOS,ERRnomem));
731 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
732 if (dptr_num < 0)
733 return(UNIXERROR(ERRDOS,ERRbadfile));
735 /* Save the wildcard match and attribs we are using on this directory -
736 needed as lanman2 assumes these are being saved between calls */
738 if(!(wcard = strdup(mask))) {
739 dptr_close(&dptr_num);
740 return(ERROR(ERRDOS,ERRnomem));
743 dptr_set_wcard(dptr_num, wcard);
744 dptr_set_attr(dptr_num, dirtype);
746 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
748 /* We don't need to check for VOL here as this is returned by
749 a different TRANS2 call. */
751 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
752 conn->dirpath,lp_dontdescend(SNUM(conn))));
753 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
754 dont_descend = True;
756 p = pdata;
757 space_remaining = max_data_bytes;
758 out_of_space = False;
760 for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
762 BOOL got_exact_match = False;
764 /* this is a heuristic to avoid seeking the dirptr except when
765 absolutely necessary. It allows for a filename of about 40 chars */
766 if (space_remaining < DIRLEN_GUESS && numentries > 0)
768 out_of_space = True;
769 finished = False;
771 else
773 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
774 requires_resume_key,dont_descend,
775 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
776 &last_name_off);
779 if (finished && out_of_space)
780 finished = False;
782 if (!finished && !out_of_space)
783 numentries++;
786 * As an optimisation if we know we aren't looking
787 * for a wildcard name (ie. the name matches the wildcard exactly)
788 * then we can finish on any (first) match.
789 * This speeds up large directory searches. JRA.
792 if(got_exact_match)
793 finished = True;
795 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
798 /* Check if we can close the dirptr */
799 if(close_after_first || (finished && close_if_end))
801 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
802 dptr_close(&dptr_num);
806 * If there are no matching entries we must return ERRDOS/ERRbadfile -
807 * from observation of NT.
810 if(numentries == 0)
812 dptr_close(&dptr_num);
813 return(ERROR(ERRDOS,ERRbadfile));
816 /* At this point pdata points to numentries directory entries. */
818 /* Set up the return parameter block */
819 SSVAL(params,0,dptr_num);
820 SSVAL(params,2,numentries);
821 SSVAL(params,4,finished);
822 SSVAL(params,6,0); /* Never an EA error */
823 SSVAL(params,8,last_name_off);
825 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
827 if ((! *directory) && dptr_path(dptr_num))
828 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
830 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
831 smb_fn_name(CVAL(inbuf,smb_com)),
832 mask, directory, dirtype, numentries ) );
835 * Force a name mangle here to ensure that the
836 * mask as an 8.3 name is top of the mangled cache.
837 * The reasons for this are subtle. Don't remove
838 * this code unless you know what you are doing
839 * (see PR#13758). JRA.
842 if(!is_8_3( mask, False))
843 name_map_mangle(mask, True, True, SNUM(conn));
845 return(-1);
849 /****************************************************************************
850 reply to a TRANS2_FINDNEXT
851 ****************************************************************************/
852 static int call_trans2findnext(connection_struct *conn,
853 char *inbuf, char *outbuf,
854 int length, int bufsize,
855 char **pparams, char **ppdata)
857 /* We must be careful here that we don't return more than the
858 allowed number of data bytes. If this means returning fewer than
859 maxentries then so be it. We assume that the redirector has
860 enough room for the fixed number of parameter bytes it has
861 requested. */
862 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
863 char *params = *pparams;
864 char *pdata = *ppdata;
865 int dptr_num = SVAL(params,0);
866 int maxentries = SVAL(params,2);
867 uint16 info_level = SVAL(params,4);
868 uint32 resume_key = IVAL(params,6);
869 BOOL close_after_request = BITSETW(params+10,0);
870 BOOL close_if_end = BITSETW(params+10,1);
871 BOOL requires_resume_key = BITSETW(params+10,2);
872 BOOL continue_bit = BITSETW(params+10,3);
873 pstring resume_name;
874 pstring mask;
875 pstring directory;
876 char *p;
877 uint16 dirtype;
878 int numentries = 0;
879 int i, last_name_off=0;
880 BOOL finished = False;
881 BOOL dont_descend = False;
882 BOOL out_of_space = False;
883 int space_remaining;
885 *mask = *directory = *resume_name = 0;
887 pstrcpy( resume_name, params+12);
889 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
890 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
891 resume_key = %d resume name = %s continue=%d level = %d\n",
892 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
893 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
895 switch (info_level)
897 case 1:
898 case 2:
899 case 3:
900 case 4:
901 case SMB_FIND_FILE_DIRECTORY_INFO:
902 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
903 case SMB_FIND_FILE_NAMES_INFO:
904 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
905 break;
906 default:
907 return(ERROR(ERRDOS,ERRunknownlevel));
910 pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
911 if(!*ppdata)
912 return(ERROR(ERRDOS,ERRnomem));
913 memset((char *)pdata,'\0',max_data_bytes + 1024);
915 /* Realloc the params space */
916 params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
917 if(!params)
918 return(ERROR(ERRDOS,ERRnomem));
920 /* Check that the dptr is valid */
921 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
922 return(ERROR(ERRDOS,ERRnofiles));
924 string_set(&conn->dirpath,dptr_path(dptr_num));
926 /* Get the wildcard mask from the dptr */
927 if((p = dptr_wcard(dptr_num))== NULL) {
928 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
929 return (ERROR(ERRDOS,ERRnofiles));
931 pstrcpy(mask, p);
932 pstrcpy(directory,conn->dirpath);
934 /* Get the attr mask from the dptr */
935 dirtype = dptr_attr(dptr_num);
937 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
938 dptr_num, mask, dirtype,
939 (long)conn->dirptr,
940 TellDir(conn->dirptr)));
942 /* We don't need to check for VOL here as this is returned by
943 a different TRANS2 call. */
945 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
946 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
947 dont_descend = True;
949 p = pdata;
950 space_remaining = max_data_bytes;
951 out_of_space = False;
954 * Seek to the correct position. We no longer use the resume key but
955 * depend on the last file name instead.
957 if(requires_resume_key && *resume_name && !continue_bit)
960 * Fix for NT redirector problem triggered by resume key indexes
961 * changing between directory scans. We now return a resume key of 0
962 * and instead look for the filename to continue from (also given
963 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
964 * findfirst/findnext (as is usual) then the directory pointer
965 * should already be at the correct place. Check this by scanning
966 * backwards looking for an exact (ie. case sensitive) filename match.
967 * If we get to the beginning of the directory and haven't found it then scan
968 * forwards again looking for a match. JRA.
971 int current_pos, start_pos;
972 char *dname = NULL;
973 void *dirptr = conn->dirptr;
974 start_pos = TellDir(dirptr);
975 for(current_pos = start_pos; current_pos >= 0; current_pos--)
977 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
979 SeekDir(dirptr, current_pos);
980 dname = ReadDirName(dirptr);
983 * Remember, name_map_mangle is called by
984 * get_lanman2_dir_entry(), so the resume name
985 * could be mangled. Ensure we do the same
986 * here.
989 if(dname != NULL)
990 name_map_mangle( dname, False, True, SNUM(conn));
992 if(dname && strcsequal( resume_name, dname))
994 SeekDir(dirptr, current_pos+1);
995 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
996 break;
1001 * Scan forward from start if not found going backwards.
1004 if(current_pos < 0)
1006 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1007 SeekDir(dirptr, start_pos);
1008 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
1011 * Remember, name_map_mangle is called by
1012 * get_lanman2_dir_entry(), so the resume name
1013 * could be mangled. Ensure we do the same
1014 * here.
1017 if(dname != NULL)
1018 name_map_mangle( dname, False, True, SNUM(conn));
1020 if(dname && strcsequal( resume_name, dname))
1022 SeekDir(dirptr, current_pos+1);
1023 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1024 break;
1026 } /* end for */
1027 } /* end if current_pos */
1028 } /* end if requires_resume_key && !continue_bit */
1030 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1032 BOOL got_exact_match = False;
1034 /* this is a heuristic to avoid seeking the dirptr except when
1035 absolutely necessary. It allows for a filename of about 40 chars */
1036 if (space_remaining < DIRLEN_GUESS && numentries > 0)
1038 out_of_space = True;
1039 finished = False;
1041 else
1043 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1044 requires_resume_key,dont_descend,
1045 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1046 &last_name_off);
1049 if (finished && out_of_space)
1050 finished = False;
1052 if (!finished && !out_of_space)
1053 numentries++;
1056 * As an optimisation if we know we aren't looking
1057 * for a wildcard name (ie. the name matches the wildcard exactly)
1058 * then we can finish on any (first) match.
1059 * This speeds up large directory searches. JRA.
1062 if(got_exact_match)
1063 finished = True;
1065 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1068 /* Check if we can close the dirptr */
1069 if(close_after_request || (finished && close_if_end))
1071 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1072 dptr_close(&dptr_num); /* This frees up the saved mask */
1076 /* Set up the return parameter block */
1077 SSVAL(params,0,numentries);
1078 SSVAL(params,2,finished);
1079 SSVAL(params,4,0); /* Never an EA error */
1080 SSVAL(params,6,last_name_off);
1082 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1084 if ((! *directory) && dptr_path(dptr_num))
1085 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1087 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1088 smb_fn_name(CVAL(inbuf,smb_com)),
1089 mask, directory, dirtype, numentries ) );
1091 return(-1);
1094 /****************************************************************************
1095 reply to a TRANS2_QFSINFO (query filesystem info)
1096 ****************************************************************************/
1098 static int call_trans2qfsinfo(connection_struct *conn,
1099 char *inbuf, char *outbuf,
1100 int length, int bufsize,
1101 char **pparams, char **ppdata)
1103 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1104 char *pdata = *ppdata;
1105 char *params = *pparams;
1106 uint16 info_level = SVAL(params,0);
1107 int data_len;
1108 SMB_STRUCT_STAT st;
1109 char *vname = volume_label(SNUM(conn));
1110 int snum = SNUM(conn);
1111 char *fstype = lp_fstype(SNUM(conn));
1113 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1115 if(conn->vfs_ops.stat(conn,".",&st)!=0) {
1116 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1117 return (ERROR(ERRSRV,ERRinvdevice));
1120 pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
1121 memset((char *)pdata,'\0',max_data_bytes + 1024);
1123 switch (info_level)
1125 case 1:
1127 SMB_BIG_UINT dfree,dsize,bsize;
1128 data_len = 18;
1129 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1130 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1131 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1132 SIVAL(pdata,l1_cUnit,dsize);
1133 SIVAL(pdata,l1_cUnitAvail,dfree);
1134 SSVAL(pdata,l1_cbSector,512);
1135 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1136 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1137 (unsigned int)dfree, 512));
1138 break;
1140 case 2:
1142 /* Return volume name */
1143 int volname_len = MIN(strlen(vname),11);
1144 data_len = l2_vol_szVolLabel + volname_len + 1;
1146 * Add volume serial number - hash of a combination of
1147 * the called hostname and the service name.
1149 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1150 SCVAL(pdata,l2_vol_cch,volname_len);
1151 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1152 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1153 (unsigned)st.st_ctime, volname_len,
1154 pdata+l2_vol_szVolLabel));
1155 break;
1157 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1159 int fstype_len;
1160 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1161 FILE_DEVICE_IS_MOUNTED|
1162 (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1163 #if 0 /* Old code. JRA. */
1164 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1165 #endif /* Old code. */
1167 SIVAL(pdata,4,128); /* Max filename component length */
1168 fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False);
1169 SIVAL(pdata,8,fstype_len);
1170 data_len = 12 + fstype_len;
1171 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1172 break;
1174 case SMB_QUERY_FS_LABEL_INFO:
1175 data_len = 4 + strlen(vname);
1176 SIVAL(pdata,0,strlen(vname));
1177 pstrcpy(pdata+4,vname);
1178 break;
1179 case SMB_QUERY_FS_VOLUME_INFO:
1182 * Add volume serial number - hash of a combination of
1183 * the called hostname and the service name.
1185 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1186 (str_checksum(local_machine)<<16));
1188 /* NT4 always serves this up as unicode but expects it to be
1189 * delivered as ascii! (tridge && JRA)
1191 if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
1192 data_len = 18 + strlen(vname);
1193 SIVAL(pdata,12,strlen(vname));
1194 pstrcpy(pdata+18,vname);
1195 } else {
1196 int vnamelen;
1198 vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False);
1199 data_len = 18 + vnamelen;
1200 SIVAL(pdata,12,vnamelen);
1201 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1204 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1205 (int)strlen(vname),vname));
1206 break;
1207 case SMB_QUERY_FS_SIZE_INFO:
1209 SMB_BIG_UINT dfree,dsize,bsize;
1210 data_len = 24;
1211 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1212 SBIG_UINT(pdata,0,dsize);
1213 SBIG_UINT(pdata,8,dfree);
1214 SIVAL(pdata,16,bsize/512);
1215 SIVAL(pdata,20,512);
1216 break;
1218 case SMB_QUERY_FS_DEVICE_INFO:
1219 data_len = 8;
1220 SIVAL(pdata,0,0); /* dev type */
1221 SIVAL(pdata,4,0); /* characteristics */
1222 break;
1223 case SMB_MAC_QUERY_FS_INFO:
1225 * Thursby MAC extension... ONLY on NTFS filesystems
1226 * once we do streams then we don't need this
1228 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1229 data_len = 88;
1230 SIVAL(pdata,84,0x100); /* Don't support mac... */
1231 break;
1233 /* drop through */
1234 default:
1235 return(ERROR(ERRDOS,ERRunknownlevel));
1239 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1241 DEBUG( 4, ( "%s info_level = %d\n",
1242 smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1244 return -1;
1247 /****************************************************************************
1248 reply to a TRANS2_SETFSINFO (set filesystem info)
1249 ****************************************************************************/
1250 static int call_trans2setfsinfo(connection_struct *conn,
1251 char *inbuf, char *outbuf, int length,
1252 int bufsize,
1253 char **pparams, char **ppdata)
1255 /* Just say yes we did it - there is nothing that
1256 can be set here so it doesn't matter. */
1257 int outsize;
1258 DEBUG(3,("call_trans2setfsinfo\n"));
1260 if (!CAN_WRITE(conn))
1261 return(ERROR(ERRSRV,ERRaccess));
1263 outsize = set_message(outbuf,10,0,True);
1265 return outsize;
1268 /****************************************************************************
1269 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1270 file name or file id).
1271 ****************************************************************************/
1273 static int call_trans2qfilepathinfo(connection_struct *conn,
1274 char *inbuf, char *outbuf, int length,
1275 int bufsize,
1276 char **pparams,char **ppdata,
1277 int total_data)
1279 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1280 char *params = *pparams;
1281 char *pdata = *ppdata;
1282 uint16 tran_call = SVAL(inbuf, smb_setup0);
1283 uint16 info_level;
1284 int mode=0;
1285 SMB_OFF_T size=0;
1286 unsigned int data_size;
1287 SMB_STRUCT_STAT sbuf;
1288 pstring fname1;
1289 char *fname;
1290 char *p;
1291 int l;
1292 SMB_OFF_T pos = 0;
1293 BOOL bad_path = False;
1294 BOOL delete_pending = False;
1296 if (tran_call == TRANSACT2_QFILEINFO) {
1297 files_struct *fsp = file_fsp(params,0);
1298 info_level = SVAL(params,2);
1300 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1302 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1304 * This is actually a QFILEINFO on a directory
1305 * handle (returned from an NT SMB). NT5.0 seems
1306 * to do this call. JRA.
1308 fname = fsp->fsp_name;
1309 unix_convert(fname,conn,0,&bad_path,&sbuf);
1310 if (!check_name(fname,conn) ||
1311 (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) {
1312 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1313 if((errno == ENOENT) && bad_path)
1315 unix_ERR_class = ERRDOS;
1316 unix_ERR_code = ERRbadpath;
1318 return(UNIXERROR(ERRDOS,ERRbadpath));
1321 delete_pending = fsp->directory_delete_on_close;
1323 } else {
1325 * Original code - this is an open file.
1327 CHECK_FSP(fsp,conn);
1328 CHECK_ERROR(fsp);
1330 fname = fsp->fsp_name;
1331 if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) {
1332 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1333 return(UNIXERROR(ERRDOS,ERRbadfid));
1335 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1336 return(UNIXERROR(ERRDOS,ERRnoaccess));
1338 delete_pending = fsp->delete_on_close;
1340 } else {
1341 /* qpathinfo */
1342 info_level = SVAL(params,0);
1344 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1346 fname = &fname1[0];
1347 pstrcpy(fname,&params[6]);
1349 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1351 unix_convert(fname,conn,0,&bad_path,&sbuf);
1352 if (!check_name(fname,conn) ||
1353 (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) {
1354 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1355 if((errno == ENOENT) && bad_path)
1357 unix_ERR_class = ERRDOS;
1358 unix_ERR_code = ERRbadpath;
1360 return(UNIXERROR(ERRDOS,ERRbadpath));
1365 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1366 fname,info_level,tran_call,total_data));
1368 p = strrchr(fname,'/');
1369 if (!p)
1370 p = fname;
1371 else
1372 p++;
1373 l = strlen(p);
1374 mode = dos_mode(conn,fname,&sbuf);
1375 size = sbuf.st_size;
1376 if (mode & aDIR) size = 0;
1378 /* from now on we only want the part after the / */
1379 fname = p;
1381 params = *pparams = Realloc(*pparams,2);
1382 memset((char *)params,'\0',2);
1383 data_size = max_data_bytes + 1024;
1384 pdata = *ppdata = Realloc(*ppdata, data_size);
1386 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1387 /* uggh, EAs for OS2 */
1388 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1389 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1392 memset((char *)pdata,'\0',data_size);
1394 switch (info_level)
1396 case SMB_INFO_STANDARD:
1397 case SMB_INFO_QUERY_EA_SIZE:
1398 data_size = (info_level==1?22:26);
1399 put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1400 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1401 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1402 SIVAL(pdata,l1_cbFile,(uint32)size);
1403 SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1404 SSVAL(pdata,l1_attrFile,mode);
1405 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1406 break;
1408 case SMB_INFO_QUERY_EAS_FROM_LIST:
1409 data_size = 24;
1410 put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1411 put_dos_date2(pdata,4,sbuf.st_atime);
1412 put_dos_date2(pdata,8,sbuf.st_mtime);
1413 SIVAL(pdata,12,(uint32)size);
1414 SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1415 SIVAL(pdata,20,mode);
1416 break;
1418 case SMB_INFO_QUERY_ALL_EAS:
1419 data_size = 4;
1420 SIVAL(pdata,0,data_size);
1421 break;
1423 case 6:
1424 return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */
1426 case SMB_QUERY_FILE_BASIC_INFO:
1427 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1428 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1429 put_long_date(pdata+8,sbuf.st_atime);
1430 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1431 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1432 SIVAL(pdata,32,mode);
1434 DEBUG(5,("SMB_QFBI - "));
1436 time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1437 DEBUG(5,("create: %s ", ctime(&create_time)));
1439 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1440 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1441 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1442 DEBUG(5,("mode: %x\n", mode));
1444 break;
1446 case SMB_QUERY_FILE_STANDARD_INFO:
1447 data_size = 22;
1448 SOFF_T(pdata,0,size);
1449 SOFF_T(pdata,8,size);
1450 SIVAL(pdata,16,sbuf.st_nlink);
1451 CVAL(pdata,20) = 0;
1452 CVAL(pdata,21) = (mode&aDIR)?1:0;
1453 break;
1455 case SMB_QUERY_FILE_EA_INFO:
1456 data_size = 4;
1457 break;
1459 /* Get the 8.3 name - used if NT SMB was negotiated. */
1460 case SMB_QUERY_FILE_ALT_NAME_INFO:
1462 pstring short_name;
1463 pstrcpy(short_name,p);
1464 /* Mangle if not already 8.3 */
1465 if(!is_8_3(short_name, True))
1467 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1468 *short_name = '\0';
1470 strupper(short_name);
1471 l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False);
1472 data_size = 4 + l;
1473 SIVAL(pdata,0,l);
1475 break;
1477 case SMB_QUERY_FILE_NAME_INFO:
1479 * The first part of this code is essential
1480 * to get security descriptors to work on mapped
1481 * drives. Don't ask how I discovered this unless
1482 * you like hearing about me suffering.... :-). JRA.
1484 if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) {
1485 l = l*2;
1486 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1487 dos_PutUniCode(pdata + 4, "\\",sizeof(pstring), False);
1488 } else {
1489 pstrcpy(pdata+4,fname);
1491 data_size = 4 + l;
1492 SIVAL(pdata,0,l);
1493 break;
1495 case SMB_QUERY_FILE_ALLOCATION_INFO:
1496 case SMB_QUERY_FILE_END_OF_FILEINFO:
1497 data_size = 8;
1498 SOFF_T(pdata,0,size);
1499 break;
1501 case SMB_QUERY_FILE_ALL_INFO:
1502 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1503 put_long_date(pdata+8,sbuf.st_atime);
1504 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1505 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1506 SIVAL(pdata,32,mode);
1507 pdata += 40;
1508 SOFF_T(pdata,0,size);
1509 SOFF_T(pdata,8,size);
1510 SIVAL(pdata,16,sbuf.st_nlink);
1511 CVAL(pdata,20) = delete_pending;
1512 CVAL(pdata,21) = (mode&aDIR)?1:0;
1513 pdata += 24;
1514 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1515 pdata += 8; /* index number */
1516 pdata += 4; /* EA info */
1517 if (mode & aRONLY)
1518 SIVAL(pdata,0,0xA9);
1519 else
1520 SIVAL(pdata,0,0xd01BF);
1521 pdata += 4;
1522 SOFF_T(pdata,0,pos); /* current offset */
1523 pdata += 8;
1524 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1525 pdata += 4;
1526 pdata += 4; /* alignment */
1527 SIVAL(pdata,0,l);
1528 pstrcpy(pdata+4,fname);
1529 pdata += 4 + l;
1530 data_size = PTR_DIFF(pdata,(*ppdata));
1531 break;
1533 #if 0
1534 /* NT4 server just returns "invalid query" to this - if we try to answer
1535 it then NTws gets a BSOD! (tridge) */
1536 case SMB_QUERY_FILE_STREAM_INFO:
1537 data_size = 24 + l;
1538 SIVAL(pdata,0,pos);
1539 SIVAL(pdata,4,size);
1540 SIVAL(pdata,12,size);
1541 SIVAL(pdata,20,l);
1542 pstrcpy(pdata+24,fname);
1543 break;
1544 #endif
1546 default:
1547 return(ERROR(ERRDOS,ERRunknownlevel));
1550 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1552 return(-1);
1555 /****************************************************************************
1556 reply to a TRANS2_SETFILEINFO (set file info by fileid)
1557 ****************************************************************************/
1558 static int call_trans2setfilepathinfo(connection_struct *conn,
1559 char *inbuf, char *outbuf, int length,
1560 int bufsize, char **pparams,
1561 char **ppdata, int total_data)
1563 char *params = *pparams;
1564 char *pdata = *ppdata;
1565 uint16 tran_call = SVAL(inbuf, smb_setup0);
1566 uint16 info_level;
1567 int mode=0;
1568 SMB_OFF_T size=0;
1569 struct utimbuf tvs;
1570 SMB_STRUCT_STAT st;
1571 pstring fname1;
1572 char *fname;
1573 int fd = -1;
1574 BOOL bad_path = False;
1575 files_struct *fsp = NULL;
1577 if (!CAN_WRITE(conn))
1578 return(ERROR(ERRSRV,ERRaccess));
1580 if (tran_call == TRANSACT2_SETFILEINFO) {
1581 fsp = file_fsp(params,0);
1582 info_level = SVAL(params,2);
1584 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1586 * This is actually a SETFILEINFO on a directory
1587 * handle (returned from an NT SMB). NT5.0 seems
1588 * to do this call. JRA.
1590 fname = fsp->fsp_name;
1591 unix_convert(fname,conn,0,&bad_path,&st);
1592 if (!check_name(fname,conn) ||
1593 (!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st))) {
1594 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1595 if((errno == ENOENT) && bad_path)
1597 unix_ERR_class = ERRDOS;
1598 unix_ERR_code = ERRbadpath;
1600 return(UNIXERROR(ERRDOS,ERRbadpath));
1602 } else {
1604 * Original code - this is an open file.
1606 CHECK_FSP(fsp,conn);
1607 CHECK_ERROR(fsp);
1609 fname = fsp->fsp_name;
1610 fd = fsp->fd;
1612 if (fsp->conn->vfs_ops.fstat(fsp,fd,&st) != 0) {
1613 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1614 return(UNIXERROR(ERRDOS,ERRbadfid));
1617 } else {
1618 /* set path info */
1619 info_level = SVAL(params,0);
1620 fname = fname1;
1621 pstrcpy(fname,&params[6]);
1622 unix_convert(fname,conn,0,&bad_path,&st);
1623 if(!check_name(fname, conn))
1625 if((errno == ENOENT) && bad_path)
1627 unix_ERR_class = ERRDOS;
1628 unix_ERR_code = ERRbadpath;
1630 return(UNIXERROR(ERRDOS,ERRbadpath));
1633 if(!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st)!=0) {
1634 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1635 if((errno == ENOENT) && bad_path)
1637 unix_ERR_class = ERRDOS;
1638 unix_ERR_code = ERRbadpath;
1640 return(UNIXERROR(ERRDOS,ERRbadpath));
1644 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1645 tran_call,fname,info_level,total_data));
1647 /* Realloc the parameter and data sizes */
1648 params = *pparams = Realloc(*pparams,2);
1649 if(params == NULL)
1650 return(ERROR(ERRDOS,ERRnomem));
1652 SSVAL(params,0,0);
1654 size = st.st_size;
1655 tvs.modtime = st.st_mtime;
1656 tvs.actime = st.st_atime;
1657 mode = dos_mode(conn,fname,&st);
1659 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1660 /* uggh, EAs for OS2 */
1661 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1662 return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1665 switch (info_level)
1667 case SMB_INFO_STANDARD:
1668 case SMB_INFO_QUERY_EA_SIZE:
1670 /* access time */
1671 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1673 /* write time */
1674 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1676 mode = SVAL(pdata,l1_attrFile);
1677 size = IVAL(pdata,l1_cbFile);
1678 break;
1681 /* XXXX um, i don't think this is right.
1682 it's also not in the cifs6.txt spec.
1684 case SMB_INFO_QUERY_EAS_FROM_LIST:
1685 tvs.actime = make_unix_date2(pdata+8);
1686 tvs.modtime = make_unix_date2(pdata+12);
1687 size = IVAL(pdata,16);
1688 mode = IVAL(pdata,24);
1689 break;
1691 /* XXXX nor this. not in cifs6.txt, either. */
1692 case SMB_INFO_QUERY_ALL_EAS:
1693 tvs.actime = make_unix_date2(pdata+8);
1694 tvs.modtime = make_unix_date2(pdata+12);
1695 size = IVAL(pdata,16);
1696 mode = IVAL(pdata,24);
1697 break;
1699 case SMB_SET_FILE_BASIC_INFO:
1701 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
1702 time_t write_time;
1703 time_t changed_time;
1705 /* Ignore create time at offset pdata. */
1707 /* access time */
1708 tvs.actime = interpret_long_date(pdata+8);
1710 write_time = interpret_long_date(pdata+16);
1711 changed_time = interpret_long_date(pdata+24);
1713 tvs.modtime = MIN(write_time, changed_time);
1715 /* Prefer a defined time to an undefined one. */
1716 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
1717 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
1718 ? changed_time
1719 : write_time);
1721 #if 0 /* Needs more testing... */
1722 /* Test from Luke to prevent Win95 from
1723 setting incorrect values here.
1725 if (tvs.actime < tvs.modtime)
1726 return(ERROR(ERRDOS,ERRnoaccess));
1727 #endif /* Needs more testing... */
1729 /* attributes */
1730 mode = IVAL(pdata,32);
1731 break;
1735 * NT seems to use this call with a size of zero
1736 * to mean truncate the file. JRA.
1739 case SMB_SET_FILE_ALLOCATION_INFO:
1741 SMB_OFF_T newsize = IVAL(pdata,0);
1742 #ifdef LARGE_SMB_OFF_T
1743 newsize |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1744 #else /* LARGE_SMB_OFF_T */
1745 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1746 return(ERROR(ERRDOS,ERRunknownlevel));
1747 #endif /* LARGE_SMB_OFF_T */
1748 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)newsize ));
1749 if(newsize == 0)
1750 size = 0;
1751 break;
1754 case SMB_SET_FILE_END_OF_FILE_INFO:
1756 size = IVAL(pdata,0);
1757 #ifdef LARGE_SMB_OFF_T
1758 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1759 #else /* LARGE_SMB_OFF_T */
1760 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1761 return(ERROR(ERRDOS,ERRunknownlevel));
1762 #endif /* LARGE_SMB_OFF_T */
1763 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
1764 break;
1767 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1769 if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1771 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1773 if(fsp->is_directory)
1775 fsp->directory_delete_on_close = delete_on_close;
1776 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n",
1777 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1780 else if(fsp->stat_open)
1782 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n",
1783 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1785 else
1789 * We can only set the delete on close flag if
1790 * the share mode contained ALLOW_SHARE_DELETE
1793 if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1794 return(ERROR(ERRDOS,ERRnoaccess));
1797 * If the flag has been set then
1798 * modify the share mode entry for all files we have open
1799 * on this device and inode to tell other smbds we have
1800 * changed the delete on close flag.
1803 if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1805 int i;
1806 files_struct *iterate_fsp;
1807 SMB_DEV_T dev = fsp->dev;
1808 SMB_INO_T inode = fsp->inode;
1809 int num_share_modes;
1810 share_mode_entry *current_shares = NULL;
1812 if (lock_share_entry_fsp(fsp) == False)
1813 return(ERROR(ERRDOS,ERRnoaccess));
1816 * Before we allow this we need to ensure that all current opens
1817 * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1818 * do not then we deny this (as we are essentially deleting the
1819 * file at this point.
1822 num_share_modes = get_share_modes(conn, dev, inode, &current_shares);
1823 for(i = 0; i < num_share_modes; i++)
1825 if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1827 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1828 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1829 fsp->fnum, fsp->fsp_name ));
1831 * Release the lock.
1834 unlock_share_entry_fsp(fsp);
1837 * current_shares was malloced by get_share_modes - free it here.
1840 free((char *)current_shares);
1843 * Even though share violation would be more appropriate here,
1844 * return ERRnoaccess as that's what NT does.
1847 return(ERROR(ERRDOS,ERRnoaccess));
1852 * current_shares was malloced by get_share_modes - free it here.
1855 free((char *)current_shares);
1857 DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1858 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1861 * Go through all files we have open on the same device and
1862 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1863 * Other smbd's that have this file open will have to fend for themselves. We
1864 * take care of this (rare) case in close_file(). See the comment there.
1867 for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1868 iterate_fsp = file_find_di_next(iterate_fsp))
1870 int new_share_mode = (delete_on_close ?
1871 (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1872 (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1874 DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1875 dev = %x, inode = %.0f from %x to %x\n",
1876 iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
1877 (double)inode, iterate_fsp->share_mode, new_share_mode ));
1879 if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False)
1880 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1881 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1885 * Set the delete on close flag in the reference
1886 * counted struct. Delete when the last reference
1887 * goes away.
1889 fsp->delete_on_close = delete_on_close;
1891 unlock_share_entry_fsp(fsp);
1893 DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1894 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1896 } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1897 } /* end if is_directory. */
1898 } else
1899 return(ERROR(ERRDOS,ERRunknownlevel));
1900 break;
1903 default:
1905 return(ERROR(ERRDOS,ERRunknownlevel));
1909 /* get some defaults (no modifications) if any info is zero or -1. */
1910 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
1911 tvs.actime = st.st_atime;
1913 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
1914 tvs.modtime = st.st_mtime;
1916 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1917 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1918 DEBUG(6,("size: %.0f ", (double)size));
1919 DEBUG(6,("mode: %x\n" , mode));
1921 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
1922 (info_level == SMB_SET_FILE_ALLOCATION_INFO))) {
1924 * Only do this test if we are not explicitly
1925 * changing the size of a file.
1927 if (!size)
1928 size = st.st_size;
1931 /* Try and set the times, size and mode of this file -
1932 if they are different from the current values
1934 if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
1935 if(fsp != NULL) {
1937 * This was a setfileinfo on an open file.
1938 * NT does this a lot. It's actually pointless
1939 * setting the time here, as it will be overwritten
1940 * on the next write, so we save the request
1941 * away and will set it on file code. JRA.
1944 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
1945 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
1946 ctime(&tvs.modtime) ));
1947 fsp->pending_modtime = tvs.modtime;
1950 } else {
1952 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
1954 if(file_utime(conn, fname, &tvs)!=0)
1955 return(UNIXERROR(ERRDOS,ERRnoaccess));
1959 /* check the mode isn't different, before changing it */
1960 if ((mode != 0) && (mode != dos_mode(conn, fname, &st))) {
1962 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
1963 fname, mode ));
1965 if(file_chmod(conn, fname, mode, NULL)) {
1966 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1967 return(UNIXERROR(ERRDOS,ERRnoaccess));
1971 if(size != st.st_size) {
1973 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
1974 fname, (double)size ));
1976 if (fd == -1) {
1977 fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),O_RDWR,0);
1978 if (fd == -1)
1979 return(UNIXERROR(ERRDOS,ERRbadpath));
1980 set_filelen(fd, size); /* tpot vfs */
1981 conn->vfs_ops.close(fsp,fd);
1982 } else {
1983 set_filelen(fd, size); /* tpot vfs */
1986 if(fsp)
1987 set_filelen_write_cache(fsp, size);
1990 SSVAL(params,0,0);
1992 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1994 return(-1);
1997 /****************************************************************************
1998 reply to a TRANS2_MKDIR (make directory with extended attributes).
1999 ****************************************************************************/
2000 static int call_trans2mkdir(connection_struct *conn,
2001 char *inbuf, char *outbuf, int length, int bufsize,
2002 char **pparams, char **ppdata)
2004 char *params = *pparams;
2005 pstring directory;
2006 int ret = -1;
2007 BOOL bad_path = False;
2009 if (!CAN_WRITE(conn))
2010 return(ERROR(ERRSRV,ERRaccess));
2012 pstrcpy(directory, &params[4]);
2014 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2016 unix_convert(directory,conn,0,&bad_path,NULL);
2017 if (check_name(directory,conn))
2018 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2020 if(ret < 0)
2022 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2023 if((errno == ENOENT) && bad_path)
2025 unix_ERR_class = ERRDOS;
2026 unix_ERR_code = ERRbadpath;
2028 return(UNIXERROR(ERRDOS,ERRnoaccess));
2031 /* Realloc the parameter and data sizes */
2032 params = *pparams = Realloc(*pparams,2);
2033 if(params == NULL)
2034 return(ERROR(ERRDOS,ERRnomem));
2036 SSVAL(params,0,0);
2038 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2040 return(-1);
2043 /****************************************************************************
2044 reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
2045 We don't actually do this - we just send a null response.
2046 ****************************************************************************/
2047 static int call_trans2findnotifyfirst(connection_struct *conn,
2048 char *inbuf, char *outbuf,
2049 int length, int bufsize,
2050 char **pparams, char **ppdata)
2052 static uint16 fnf_handle = 257;
2053 char *params = *pparams;
2054 uint16 info_level = SVAL(params,4);
2056 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2058 switch (info_level)
2060 case 1:
2061 case 2:
2062 break;
2063 default:
2064 return(ERROR(ERRDOS,ERRunknownlevel));
2067 /* Realloc the parameter and data sizes */
2068 params = *pparams = Realloc(*pparams,6);
2069 if(params == NULL)
2070 return(ERROR(ERRDOS,ERRnomem));
2072 SSVAL(params,0,fnf_handle);
2073 SSVAL(params,2,0); /* No changes */
2074 SSVAL(params,4,0); /* No EA errors */
2076 fnf_handle++;
2078 if(fnf_handle == 0)
2079 fnf_handle = 257;
2081 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2083 return(-1);
2086 /****************************************************************************
2087 reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2088 changes). Currently this does nothing.
2089 ****************************************************************************/
2090 static int call_trans2findnotifynext(connection_struct *conn,
2091 char *inbuf, char *outbuf,
2092 int length, int bufsize,
2093 char **pparams, char **ppdata)
2095 char *params = *pparams;
2097 DEBUG(3,("call_trans2findnotifynext\n"));
2099 /* Realloc the parameter and data sizes */
2100 params = *pparams = Realloc(*pparams,4);
2101 if(params == NULL)
2102 return(ERROR(ERRDOS,ERRnomem));
2104 SSVAL(params,0,0); /* No changes */
2105 SSVAL(params,2,0); /* No EA errors */
2107 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2109 return(-1);
2112 /****************************************************************************
2113 reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>
2114 ****************************************************************************/
2115 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2116 char* outbuf, int length, int bufsize,
2117 char** pparams, char** ppdata)
2119 char *params = *pparams;
2120 enum remote_arch_types ra_type = get_remote_arch();
2121 BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
2122 pstring pathname;
2123 int reply_size = 0;
2124 int max_referral_level = SVAL(params,0);
2127 DEBUG(10,("call_trans2getdfsreferral\n"));
2129 if(!lp_host_msdfs())
2130 return(ERROR(ERRDOS,ERRbadfunc));
2132 /* if pathname is in UNICODE, convert to DOS */
2133 /* NT always sends in UNICODE, may not set UNICODE flag */
2134 if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS))
2136 unistr_to_dos(pathname, &params[2], sizeof(pathname));
2137 DEBUG(10,("UNICODE referral for %s\n",pathname));
2139 else
2140 pstrcpy(pathname,&params[2]);
2142 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2143 return(ERROR(ERRDOS,ERRbadfile));
2145 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS |
2146 FLAGS2_DFS_PATHNAMES);
2147 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2149 return(-1);
2153 /****************************************************************************
2154 reply to a SMBfindclose (stop trans2 directory search)
2155 ****************************************************************************/
2156 int reply_findclose(connection_struct *conn,
2157 char *inbuf,char *outbuf,int length,int bufsize)
2159 int outsize = 0;
2160 int dptr_num=SVALS(inbuf,smb_vwv0);
2162 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2164 dptr_close(&dptr_num);
2166 outsize = set_message(outbuf,0,0,True);
2168 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2170 return(outsize);
2173 /****************************************************************************
2174 reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2175 ****************************************************************************/
2176 int reply_findnclose(connection_struct *conn,
2177 char *inbuf,char *outbuf,int length,int bufsize)
2179 int outsize = 0;
2180 int dptr_num= -1;
2182 dptr_num = SVAL(inbuf,smb_vwv0);
2184 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2186 /* We never give out valid handles for a
2187 findnotifyfirst - so any dptr_num is ok here.
2188 Just ignore it. */
2190 outsize = set_message(outbuf,0,0,True);
2192 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2194 return(outsize);
2198 /****************************************************************************
2199 reply to a SMBtranss2 - just ignore it!
2200 ****************************************************************************/
2201 int reply_transs2(connection_struct *conn,
2202 char *inbuf,char *outbuf,int length,int bufsize)
2204 DEBUG(4,("Ignoring transs2 of length %d\n",length));
2205 return(-1);
2208 /****************************************************************************
2209 reply to a SMBtrans2
2210 ****************************************************************************/
2211 int reply_trans2(connection_struct *conn,
2212 char *inbuf,char *outbuf,int length,int bufsize)
2214 int outsize = 0;
2215 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2216 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2217 #if 0
2218 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2219 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2220 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2221 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2222 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2223 int32 timeout = IVALS(inbuf,smb_timeout);
2224 #endif
2225 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2226 unsigned int tran_call = SVAL(inbuf, smb_setup0);
2227 char *params = NULL, *data = NULL;
2228 int num_params, num_params_sofar, num_data, num_data_sofar;
2230 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2231 /* Queue this open message as we are the process of an
2232 * oplock break. */
2234 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2235 DEBUGADD(2,( "in oplock break state.\n"));
2237 push_oplock_pending_smb_message(inbuf, length);
2238 return -1;
2241 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2242 && (tran_call != TRANSACT2_GET_DFS_REFERRAL))
2243 return(ERROR(ERRSRV,ERRaccess));
2245 outsize = set_message(outbuf,0,0,True);
2247 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2248 is so as a sanity check */
2249 if (suwcnt != 1) {
2250 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2251 return(ERROR(ERRSRV,ERRerror));
2254 /* Allocate the space for the maximum needed parameters and data */
2255 if (total_params > 0)
2256 params = (char *)malloc(total_params);
2257 if (total_data > 0)
2258 data = (char *)malloc(total_data);
2260 if ((total_params && !params) || (total_data && !data)) {
2261 DEBUG(2,("Out of memory in reply_trans2\n"));
2262 if(params)
2263 free(params);
2264 if(data)
2265 free(data);
2266 return(ERROR(ERRDOS,ERRnomem));
2269 /* Copy the param and data bytes sent with this request into
2270 the params buffer */
2271 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2272 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2274 if (num_params > total_params || num_data > total_data)
2275 exit_server("invalid params in reply_trans2");
2277 if(params)
2278 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2279 if(data)
2280 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2282 if(num_data_sofar < total_data || num_params_sofar < total_params) {
2283 /* We need to send an interim response then receive the rest
2284 of the parameter/data bytes */
2285 outsize = set_message(outbuf,0,0,True);
2286 send_smb(smbd_server_fd(),outbuf);
2288 while (num_data_sofar < total_data ||
2289 num_params_sofar < total_params) {
2290 BOOL ret;
2292 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2294 if ((ret &&
2295 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2296 outsize = set_message(outbuf,0,0,True);
2297 if(ret)
2298 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2299 else
2300 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2301 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2302 if(params)
2303 free(params);
2304 if(data)
2305 free(data);
2306 return(ERROR(ERRSRV,ERRerror));
2309 /* Revise total_params and total_data in case
2310 they have changed downwards */
2311 total_params = SVAL(inbuf, smb_tpscnt);
2312 total_data = SVAL(inbuf, smb_tdscnt);
2313 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2314 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2315 if (num_params_sofar > total_params || num_data_sofar > total_data)
2316 exit_server("data overflow in trans2");
2318 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
2319 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2320 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2321 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2325 if (Protocol >= PROTOCOL_NT1) {
2326 uint16 flg2 = SVAL(outbuf,smb_flg2);
2327 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2330 /* Now we must call the relevant TRANS2 function */
2331 switch(tran_call) {
2332 case TRANSACT2_OPEN:
2333 outsize = call_trans2open(conn,
2334 inbuf, outbuf, bufsize,
2335 &params, &data);
2336 break;
2338 case TRANSACT2_FINDFIRST:
2339 outsize = call_trans2findfirst(conn, inbuf, outbuf,
2340 bufsize, &params, &data);
2341 break;
2343 case TRANSACT2_FINDNEXT:
2344 outsize = call_trans2findnext(conn, inbuf, outbuf,
2345 length, bufsize,
2346 &params, &data);
2347 break;
2349 case TRANSACT2_QFSINFO:
2350 outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
2351 length, bufsize, &params,
2352 &data);
2353 break;
2355 case TRANSACT2_SETFSINFO:
2356 outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
2357 length, bufsize,
2358 &params, &data);
2359 break;
2361 case TRANSACT2_QPATHINFO:
2362 case TRANSACT2_QFILEINFO:
2363 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
2364 length, bufsize,
2365 &params, &data, total_data);
2366 break;
2367 case TRANSACT2_SETPATHINFO:
2368 case TRANSACT2_SETFILEINFO:
2369 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
2370 length, bufsize,
2371 &params, &data,
2372 total_data);
2373 break;
2375 case TRANSACT2_FINDNOTIFYFIRST:
2376 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
2377 length, bufsize,
2378 &params, &data);
2379 break;
2381 case TRANSACT2_FINDNOTIFYNEXT:
2382 outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
2383 length, bufsize,
2384 &params, &data);
2385 break;
2386 case TRANSACT2_MKDIR:
2387 outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
2388 bufsize, &params, &data);
2389 break;
2391 case TRANSACT2_GET_DFS_REFERRAL:
2392 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2393 bufsize, &params, &data);
2394 break;
2395 default:
2396 /* Error in request */
2397 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2398 if(params)
2399 free(params);
2400 if(data)
2401 free(data);
2402 return (ERROR(ERRSRV,ERRerror));
2405 /* As we do not know how many data packets will need to be
2406 returned here the various call_trans2xxxx calls
2407 must send their own. Thus a call_trans2xxx routine only
2408 returns a value other than -1 when it wants to send
2409 an error packet.
2412 if(params)
2413 free(params);
2414 if(data)
2415 free(data);
2416 return outsize; /* If a correct response was needed the
2417 call_trans2xxx calls have already sent
2418 it. If outsize != -1 then it is returning */
2421 #undef OLD_NTDOMAIN