preparing for release of 2.2.3a
[Samba.git] / source / smbd / trans2.c
blob4168edf7705fb047e5b9de1ea22af7f941ea9aef
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB transaction2 handling
5 Extensively modified by Andrew Tridgell, 1995
6 Copyright (C) Jeremy Allison 1994-2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern int Protocol;
26 extern BOOL case_sensitive;
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern pstring global_myname;
33 /****************************************************************************
34 Send the required number of replies back.
35 We assume all fields other than the data fields are
36 set correctly for the type of call.
37 HACK ! Always assumes smb_setup field is zero.
38 ****************************************************************************/
40 static int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize)
42 /* As we are using a protocol > LANMAN1 then the max_send
43 variable must have been set in the sessetupX call.
44 This takes precedence over the max_xmit field in the
45 global struct. These different max_xmit variables should
46 be merged as this is now too confusing */
48 extern int max_send;
49 int data_to_send = datasize;
50 int params_to_send = paramsize;
51 int useable_space;
52 char *pp = params;
53 char *pd = pdata;
54 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
55 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
56 int data_alignment_offset = 0;
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 */
65 if(params_to_send == 0 && data_to_send == 0) {
66 if (!send_smb(smbd_server_fd(),outbuf))
67 exit_server("send_trans2_replies: send_smb failed.");
68 return 0;
71 /* When sending params and data ensure that both are nicely aligned */
72 /* Only do this alignment when there is also data to send - else
73 can cause NT redirector problems. */
75 if (((params_to_send % 4) != 0) && (data_to_send != 0))
76 data_alignment_offset = 4 - (params_to_send % 4);
78 /* Space is bufsize minus Netbios over TCP header minus SMB header */
79 /* The alignment_offset is to align the param bytes on an even byte
80 boundary. NT 4.0 Beta needs this to work correctly. */
82 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
84 /* useable_space can never be more than max_send minus the alignment offset. */
86 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
89 while (params_to_send || data_to_send) {
90 /* Calculate whether we will totally or partially fill this packet */
92 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
94 /* We can never send more than useable_space */
96 * Note that 'useable_space' does not include the alignment offsets,
97 * but we must include the alignment offsets in the calculation of
98 * the length of the data we send over the wire, as the alignment offsets
99 * are sent here. Fix from Marc_Jacobsen@hp.com.
102 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
104 set_message(outbuf, 10, total_sent_thistime, True);
106 /* Set total params and data to be sent */
107 SSVAL(outbuf,smb_tprcnt,paramsize);
108 SSVAL(outbuf,smb_tdrcnt,datasize);
110 /* Calculate how many parameters and data we can fit into
111 this packet. Parameters get precedence */
113 params_sent_thistime = MIN(params_to_send,useable_space);
114 data_sent_thistime = useable_space - params_sent_thistime;
115 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
117 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
119 /* smb_proff is the offset from the start of the SMB header to the
120 parameter bytes, however the first 4 bytes of outbuf are
121 the Netbios over TCP header. Thus use smb_base() to subtract
122 them from the calculation */
124 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
126 if(params_sent_thistime == 0)
127 SSVAL(outbuf,smb_prdisp,0);
128 else
129 /* Absolute displacement of param bytes sent in this packet */
130 SSVAL(outbuf,smb_prdisp,pp - params);
132 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
133 if(data_sent_thistime == 0) {
134 SSVAL(outbuf,smb_droff,0);
135 SSVAL(outbuf,smb_drdisp, 0);
136 } else {
137 /* The offset of the data bytes is the offset of the
138 parameter bytes plus the number of parameters being sent this time */
139 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
140 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
141 SSVAL(outbuf,smb_drdisp, pd - pdata);
144 /* Copy the param bytes into the packet */
146 if(params_sent_thistime)
147 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
149 /* Copy in the data bytes */
151 if(data_sent_thistime)
152 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
153 data_alignment_offset,pd,data_sent_thistime);
155 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
156 params_sent_thistime, data_sent_thistime, useable_space));
157 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
158 params_to_send, data_to_send, paramsize, datasize));
160 /* Send the packet */
161 if (!send_smb(smbd_server_fd(),outbuf))
162 exit_server("send_trans2_replies: send_smb failed.");
164 pp += params_sent_thistime;
165 pd += data_sent_thistime;
167 params_to_send -= params_sent_thistime;
168 data_to_send -= data_sent_thistime;
170 /* Sanity check */
172 if(params_to_send < 0 || data_to_send < 0) {
173 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
174 params_to_send, data_to_send));
175 return -1;
179 return 0;
182 /****************************************************************************
183 Reply to a TRANSACT2_OPEN.
184 ****************************************************************************/
186 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
187 char **pparams, int total_params, char **ppdata, int total_data)
189 char *params = *pparams;
190 int16 open_mode;
191 int16 open_attr;
192 BOOL oplock_request;
193 #if 0
194 BOOL return_additional_info;
195 int16 open_sattr;
196 time_t open_time;
197 #endif
198 int16 open_ofun;
199 int32 open_size;
200 char *pname;
201 int16 namelen;
203 pstring fname;
204 mode_t unixmode;
205 SMB_OFF_T size=0;
206 int fmode=0,mtime=0,rmode;
207 SMB_INO_T inode = 0;
208 SMB_STRUCT_STAT sbuf;
209 int smb_action = 0;
210 BOOL bad_path = False;
211 files_struct *fsp;
214 * Ensure we have enough parameters to perform the operation.
217 if (total_params < 29)
218 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
220 open_mode = SVAL(params, 2);
221 open_attr = SVAL(params,6);
222 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
223 #if 0
224 return_additional_info = BITSETW(params,0);
225 open_sattr = SVAL(params, 4);
226 open_time = make_unix_date3(params+8);
227 #endif
228 open_ofun = SVAL(params,12);
229 open_size = IVAL(params,14);
230 pname = &params[28];
231 namelen = strlen(pname)+1;
233 StrnCpy(fname,pname,namelen);
235 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
236 fname,open_mode, open_attr, open_ofun, open_size));
238 if (IS_IPC(conn))
239 return(ERROR_DOS(ERRSRV,ERRaccess));
241 /* XXXX we need to handle passed times, sattr and flags */
243 unix_convert(fname,conn,0,&bad_path,&sbuf);
245 if (!check_name(fname,conn)) {
246 set_bad_path_error(errno, bad_path);
247 return(UNIXERROR(ERRDOS,ERRnoaccess));
250 unixmode = unix_mode(conn,open_attr | aARCH, fname);
252 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
253 oplock_request, &rmode,&smb_action);
255 if (!fsp) {
256 set_bad_path_error(errno, bad_path);
257 return(UNIXERROR(ERRDOS,ERRnoaccess));
260 size = sbuf.st_size;
261 fmode = dos_mode(conn,fname,&sbuf);
262 mtime = sbuf.st_mtime;
263 inode = sbuf.st_ino;
264 if (fmode & aDIR) {
265 close_file(fsp,False);
266 return(ERROR_DOS(ERRDOS,ERRnoaccess));
269 /* Realloc the size of parameters and data we will return */
270 params = Realloc(*pparams, 28);
271 if( params == NULL )
272 return(ERROR_DOS(ERRDOS,ERRnomem));
273 *pparams = params;
275 memset((char *)params,'\0',28);
276 SSVAL(params,0,fsp->fnum);
277 SSVAL(params,2,fmode);
278 put_dos_date2(params,4, mtime);
279 SIVAL(params,8, (uint32)size);
280 SSVAL(params,12,rmode);
282 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
283 smb_action |= EXTENDED_OPLOCK_GRANTED;
285 SSVAL(params,18,smb_action);
288 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
290 SIVAL(params,20,inode);
292 /* Send the required number of replies */
293 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
295 return -1;
298 /*********************************************************
299 Routine to check if a given string matches exactly.
300 as a special case a mask of "." does NOT match. That
301 is required for correct wildcard semantics
302 Case can be significant or not.
303 **********************************************************/
305 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
307 if (mask[0] == '.' && mask[1] == 0)
308 return False;
309 if (case_sig)
310 return strcmp(str,mask)==0;
311 return strcasecmp(str,mask) == 0;
314 /****************************************************************************
315 Return the filetype for UNIX extensions.
316 ****************************************************************************/
318 static uint32 unix_filetype(mode_t mode)
320 if(S_ISREG(mode))
321 return UNIX_TYPE_FILE;
322 else if(S_ISDIR(mode))
323 return UNIX_TYPE_DIR;
324 #ifdef S_ISLNK
325 else if(S_ISLNK(mode))
326 return UNIX_TYPE_SYMLINK;
327 #endif
328 #ifdef S_ISCHR
329 else if(S_ISCHR(mode))
330 return UNIX_TYPE_CHARDEV;
331 #endif
332 #ifdef S_ISBLK
333 else if(S_ISBLK(mode))
334 return UNIX_TYPE_BLKDEV;
335 #endif
336 #ifdef S_ISFIFO
337 else if(S_ISFIFO(mode))
338 return UNIX_TYPE_FIFO;
339 #endif
340 #ifdef S_ISSOCK
341 else if(S_ISSOCK(mode))
342 return UNIX_TYPE_SOCKET;
343 #endif
345 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
346 return UNIX_TYPE_UNKNOWN;
349 /****************************************************************************
350 Return the major devicenumber for UNIX extensions.
351 ****************************************************************************/
353 static uint32 unix_dev_major(SMB_DEV_T dev)
355 #if defined(HAVE_DEVICE_MAJOR_FN)
356 return (uint32)major(dev);
357 #else
358 return (uint32)(dev >> 8);
359 #endif
362 /****************************************************************************
363 Return the minor devicenumber for UNIX extensions.
364 ****************************************************************************/
366 static uint32 unix_dev_minor(SMB_DEV_T dev)
368 #if defined(HAVE_DEVICE_MINOR_FN)
369 return (uint32)minor(dev);
370 #else
371 return (uint32)(dev & 0xff);
372 #endif
375 /****************************************************************************
376 Map wire perms onto standard UNIX permissions. Obey share restrictions.
377 ****************************************************************************/
379 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
381 mode_t ret = 0;
383 if (perms == SMB_MODE_NO_CHANGE)
384 return pst->st_mode;
386 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
387 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
388 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
389 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
390 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
391 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
392 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
393 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
394 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
395 #ifdef S_ISVTX
396 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
397 #endif
398 #ifdef S_ISGID
399 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
400 #endif
401 #ifdef S_ISUID
402 ret |= ((perms & UNIX_SET_UID ) ? S_ISVTX : 0);
403 #endif
405 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
406 ret &= lp_dir_mask(SNUM(conn));
407 /* Add in force bits */
408 ret |= lp_force_dir_mode(SNUM(conn));
409 } else {
410 /* Apply mode mask */
411 ret &= lp_create_mask(SNUM(conn));
412 /* Add in force bits */
413 ret |= lp_force_create_mode(SNUM(conn));
416 return ret;
419 /****************************************************************************
420 Get a level dependent lanman2 dir entry.
421 ****************************************************************************/
423 static BOOL get_lanman2_dir_entry(connection_struct *conn,
424 char *path_mask,int dirtype,int info_level,
425 int requires_resume_key,
426 BOOL dont_descend,char **ppdata,
427 char *base_data, int space_remaining,
428 BOOL *out_of_space, BOOL *got_exact_match,
429 int *last_name_off)
431 char *dname;
432 BOOL found = False;
433 SMB_STRUCT_STAT sbuf;
434 pstring mask;
435 pstring pathreal;
436 pstring fname;
437 char *p, *pdata = *ppdata;
438 uint32 reskey=0;
439 int prev_dirpos=0;
440 int mode=0;
441 SMB_OFF_T size = 0;
442 SMB_OFF_T allocation_size = 0;
443 uint32 len;
444 time_t mdate=0, adate=0, cdate=0;
445 char *nameptr;
446 BOOL was_8_3;
447 int nt_extmode; /* Used for NT connections instead of mode */
448 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
450 *fname = 0;
451 *out_of_space = False;
452 *got_exact_match = False;
454 if (!conn->dirptr)
455 return(False);
457 p = strrchr(path_mask,'/');
458 if(p != NULL) {
459 if(p[1] == '\0')
460 pstrcpy(mask,"*.*");
461 else
462 pstrcpy(mask, p+1);
463 } else
464 pstrcpy(mask, path_mask);
466 while (!found) {
467 BOOL got_match;
469 /* Needed if we run out of space */
470 prev_dirpos = TellDir(conn->dirptr);
471 dname = ReadDirName(conn->dirptr);
474 * Due to bugs in NT client redirectors we are not using
475 * resume keys any more - set them to zero.
476 * Check out the related comments in findfirst/findnext.
477 * JRA.
480 reskey = 0;
482 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
483 (long)conn->dirptr,TellDir(conn->dirptr)));
485 if (!dname)
486 return(False);
488 pstrcpy(fname,dname);
490 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
491 got_match = mask_match(fname, mask, case_sensitive);
493 if(!got_match && !is_8_3(fname, False)) {
496 * It turns out that NT matches wildcards against
497 * both long *and* short names. This may explain some
498 * of the wildcard wierdness from old DOS clients
499 * that some people have been seeing.... JRA.
502 pstring newname;
503 pstrcpy( newname, fname);
504 name_map_mangle( newname, True, False, SNUM(conn));
505 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
506 got_match = mask_match(newname, mask, case_sensitive);
509 if(got_match) {
510 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
511 if (dont_descend && !isdots)
512 continue;
514 pstrcpy(pathreal,conn->dirpath);
515 if(needslash)
516 pstrcat(pathreal,"/");
517 pstrcat(pathreal,dname);
519 if (INFO_LEVEL_IS_UNIX(info_level)) {
520 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
521 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
522 pathreal,strerror(errno)));
523 continue;
525 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
526 /* Needed to show the msdfs symlinks as directories */
527 if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn))
528 || !is_msdfs_link(conn, pathreal, NULL, NULL)) {
529 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
530 pathreal,strerror(errno)));
531 continue;
532 } else {
533 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
534 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
538 mode = dos_mode(conn,pathreal,&sbuf);
540 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
541 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
542 continue;
545 size = sbuf.st_size;
546 allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
547 mdate = sbuf.st_mtime;
548 adate = sbuf.st_atime;
549 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
551 if (lp_dos_filetime_resolution(SNUM(conn))) {
552 cdate &= ~1;
553 mdate &= ~1;
554 adate &= ~1;
557 if(mode & aDIR)
558 size = 0;
560 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
562 found = True;
566 name_map_mangle(fname,False,True,SNUM(conn));
568 p = pdata;
569 nameptr = p;
571 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
573 switch (info_level) {
574 case 1:
575 if(requires_resume_key) {
576 SIVAL(p,0,reskey);
577 p += 4;
579 put_dos_date2(p,l1_fdateCreation,cdate);
580 put_dos_date2(p,l1_fdateLastAccess,adate);
581 put_dos_date2(p,l1_fdateLastWrite,mdate);
582 SIVAL(p,l1_cbFile,(uint32)size);
583 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
584 SSVAL(p,l1_attrFile,mode);
585 SCVAL(p,l1_cchName,strlen(fname));
586 pstrcpy(p + l1_achName, fname);
587 nameptr = p + l1_achName;
588 p += l1_achName + strlen(fname) + 1;
589 break;
591 case 2:
592 if(requires_resume_key) {
593 SIVAL(p,0,reskey);
594 p += 4;
596 put_dos_date2(p,l2_fdateCreation,cdate);
597 put_dos_date2(p,l2_fdateLastAccess,adate);
598 put_dos_date2(p,l2_fdateLastWrite,mdate);
599 SIVAL(p,l2_cbFile,(uint32)size);
600 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
601 SSVAL(p,l2_attrFile,mode);
602 SIVAL(p,l2_cbList,0); /* No extended attributes */
603 SCVAL(p,l2_cchName,strlen(fname));
604 pstrcpy(p + l2_achName, fname);
605 nameptr = p + l2_achName;
606 p += l2_achName + strlen(fname) + 1;
607 break;
609 case 3:
610 SIVAL(p,0,reskey);
611 put_dos_date2(p,4,cdate);
612 put_dos_date2(p,8,adate);
613 put_dos_date2(p,12,mdate);
614 SIVAL(p,16,(uint32)size);
615 SIVAL(p,20,(uint32)allocation_size);
616 SSVAL(p,24,mode);
617 SIVAL(p,26,4);
618 SCVAL(p,30,strlen(fname));
619 pstrcpy(p+31, fname);
620 nameptr = p+31;
621 p += 31 + strlen(fname) + 1;
622 break;
624 case 4:
625 if(requires_resume_key) {
626 SIVAL(p,0,reskey);
627 p += 4;
629 SIVAL(p,0,33+strlen(fname)+1);
630 put_dos_date2(p,4,cdate);
631 put_dos_date2(p,8,adate);
632 put_dos_date2(p,12,mdate);
633 SIVAL(p,16,(uint32)size);
634 SIVAL(p,20,(uint32)allocation_size);
635 SSVAL(p,24,mode);
636 SCVAL(p,32,strlen(fname));
637 pstrcpy(p + 33, fname);
638 nameptr = p+33;
639 p += 33 + strlen(fname) + 1;
640 break;
642 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
643 was_8_3 = is_8_3(fname, True);
644 len = 94+strlen(fname);
645 len = (len + 3) & ~3;
646 SIVAL(p,0,len); p += 4;
647 SIVAL(p,0,reskey); p += 4;
648 put_long_date(p,cdate); p += 8;
649 put_long_date(p,adate); p += 8;
650 put_long_date(p,mdate); p += 8;
651 put_long_date(p,mdate); p += 8;
652 SOFF_T(p,0,size);
653 SOFF_T(p,8,allocation_size);
654 p += 16;
655 SIVAL(p,0,nt_extmode); p += 4;
656 SIVAL(p,0,strlen(fname)); p += 4;
657 SIVAL(p,0,0); p += 4;
658 if (!was_8_3) {
659 fstrcpy(p+2,fname);
660 if(!name_map_mangle(p+2,True,True,SNUM(conn)))
661 (p+2)[12] = 0;
662 strupper(p+2);
663 SSVAL(p, 0, strlen(p+2));
664 } else {
665 SSVAL(p,0,0);
666 *(p+2) = 0;
668 p += 2 + 24;
669 /* nameptr = p; */
670 pstrcpy(p,fname); p += strlen(p);
671 p = pdata + len;
672 break;
674 case SMB_FIND_FILE_DIRECTORY_INFO:
675 len = 64+strlen(fname);
676 len = (len + 3) & ~3;
677 SIVAL(p,0,len); p += 4;
678 SIVAL(p,0,reskey); p += 4;
679 put_long_date(p,cdate); p += 8;
680 put_long_date(p,adate); p += 8;
681 put_long_date(p,mdate); p += 8;
682 put_long_date(p,mdate); p += 8;
683 SOFF_T(p,0,size);
684 SOFF_T(p,8,allocation_size);
685 p += 16;
686 SIVAL(p,0,nt_extmode); p += 4;
687 SIVAL(p,0,strlen(fname)); p += 4;
688 pstrcpy(p,fname);
689 p = pdata + len;
690 break;
692 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
693 len = 68+strlen(fname);
694 len = (len + 3) & ~3;
695 SIVAL(p,0,len); p += 4;
696 SIVAL(p,0,reskey); p += 4;
697 put_long_date(p,cdate); p += 8;
698 put_long_date(p,adate); p += 8;
699 put_long_date(p,mdate); p += 8;
700 put_long_date(p,mdate); p += 8;
701 SOFF_T(p,0,size);
702 SOFF_T(p,8,allocation_size);
703 p += 16;
704 SIVAL(p,0,nt_extmode); p += 4;
705 SIVAL(p,0,strlen(fname)); p += 4;
706 SIVAL(p,0,0); p += 4;
707 pstrcpy(p,fname);
708 p = pdata + len;
709 break;
711 case SMB_FIND_FILE_NAMES_INFO:
712 len = 12+strlen(fname);
713 len = (len + 3) & ~3;
714 SIVAL(p,0,len); p += 4;
715 SIVAL(p,0,reskey); p += 4;
716 SIVAL(p,0,strlen(fname)); p += 4;
717 pstrcpy(p,fname);
718 p = pdata + len;
719 break;
721 /* CIFS UNIX Extension. */
723 case SMB_FIND_FILE_UNIX:
724 len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
725 /* +1 to be sure to transmit the termination of fname */
726 len = (len + 3) & ~3;
728 SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */
729 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
731 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
732 SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */
733 p+= 8;
735 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
736 SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
737 #else
738 /* Can't get the value - fake it using size. */
739 SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
740 #endif
741 p+= 8;
743 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
744 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
745 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
746 p+= 24;
748 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
749 SIVAL(p,4,0);
750 p+= 8;
752 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
753 SIVAL(p,4,0);
754 p+= 8;
756 SIVAL(p,0,unix_filetype(sbuf.st_mode));
757 p+= 4;
759 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
760 SIVAL(p,4,0);
761 p+= 8;
763 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
764 SIVAL(p,4,0);
765 p+= 8;
767 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
768 p+= 8;
770 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
771 SIVAL(p,4,0);
772 p+= 8;
774 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
775 SIVAL(p,4,0);
776 p+= 8;
778 /* End of SMB_QUERY_FILE_UNIX_BASIC */
779 pstrcpy(p,fname);
780 p=pdata+len;
782 break;
784 default:
785 return(False);
789 if (PTR_DIFF(p,pdata) > space_remaining) {
790 /* Move the dirptr back to prev_dirpos */
791 SeekDir(conn->dirptr, prev_dirpos);
792 *out_of_space = True;
793 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
794 return False; /* Not finished - just out of space */
797 /* Setup the last_filename pointer, as an offset from base_data */
798 *last_name_off = PTR_DIFF(nameptr,base_data);
799 /* Advance the data pointer to the next slot */
800 *ppdata = p;
802 return(found);
805 /****************************************************************************
806 Reply to a TRANS2_FINDFIRST.
807 ****************************************************************************/
809 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
810 char **pparams, int total_params, char **ppdata, int total_data)
812 /* We must be careful here that we don't return more than the
813 allowed number of data bytes. If this means returning fewer than
814 maxentries then so be it. We assume that the redirector has
815 enough room for the fixed number of parameter bytes it has
816 requested. */
817 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
818 char *params = *pparams;
819 char *pdata = *ppdata;
820 int dirtype;
821 int maxentries;
822 BOOL close_after_first;
823 BOOL close_if_end;
824 BOOL requires_resume_key;
825 int info_level;
826 pstring directory;
827 pstring mask;
828 char *p, *wcard;
829 int last_name_off=0;
830 int dptr_num = -1;
831 int numentries = 0;
832 int i;
833 BOOL finished = False;
834 BOOL dont_descend = False;
835 BOOL out_of_space = False;
836 int space_remaining;
837 BOOL bad_path = False;
838 SMB_STRUCT_STAT sbuf;
840 if (total_params < 12)
841 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
843 *directory = *mask = 0;
845 dirtype = SVAL(params,0);
846 maxentries = SVAL(params,2);
847 close_after_first = BITSETW(params+4,0);
848 close_if_end = BITSETW(params+4,1);
849 requires_resume_key = BITSETW(params+4,2);
850 info_level = SVAL(params,6);
852 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
853 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
854 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
855 info_level, max_data_bytes));
857 switch (info_level) {
858 case 1:
859 case 2:
860 case 3:
861 case 4:
862 case SMB_FIND_FILE_DIRECTORY_INFO:
863 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
864 case SMB_FIND_FILE_NAMES_INFO:
865 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
866 break;
867 case SMB_FIND_FILE_UNIX:
868 if (!lp_unix_extensions())
869 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
870 break;
871 default:
872 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
875 pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */
877 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
879 DEBUG(5,("path=%s\n",directory));
881 unix_convert(directory,conn,0,&bad_path,&sbuf);
882 if(!check_name(directory,conn)) {
883 set_bad_path_error(errno, bad_path);
885 #if 0
886 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
887 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) {
888 unix_ERR_class = ERRDOS;
889 unix_ERR_code = ERRbaddirectory;
891 #endif
893 return(UNIXERROR(ERRDOS,ERRbadpath));
896 p = strrchr(directory,'/');
897 if(p == NULL) {
898 pstrcpy(mask,directory);
899 pstrcpy(directory,"./");
900 } else {
901 pstrcpy(mask,p+1);
902 *p = 0;
905 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
907 pdata = Realloc(*ppdata, max_data_bytes + 1024);
908 if( pdata == NULL )
909 return(ERROR_DOS(ERRDOS,ERRnomem));
910 *ppdata = pdata;
911 memset((char *)pdata,'\0',max_data_bytes + 1024);
913 /* Realloc the params space */
914 params = Realloc(*pparams, 10);
915 if( params == NULL )
916 return ERROR_DOS(ERRDOS,ERRnomem);
917 *pparams = params;
919 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
920 if (dptr_num < 0)
921 return(UNIXERROR(ERRDOS,ERRbadfile));
923 /* Save the wildcard match and attribs we are using on this directory -
924 needed as lanman2 assumes these are being saved between calls */
926 if(!(wcard = strdup(mask))) {
927 dptr_close(&dptr_num);
928 return ERROR_DOS(ERRDOS,ERRnomem);
931 dptr_set_wcard(dptr_num, wcard);
932 dptr_set_attr(dptr_num, dirtype);
934 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
936 /* We don't need to check for VOL here as this is returned by
937 a different TRANS2 call. */
939 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
941 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
942 dont_descend = True;
944 p = pdata;
945 space_remaining = max_data_bytes;
946 out_of_space = False;
948 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
949 BOOL got_exact_match = False;
951 /* this is a heuristic to avoid seeking the dirptr except when
952 absolutely necessary. It allows for a filename of about 40 chars */
954 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
955 out_of_space = True;
956 finished = False;
957 } else {
958 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
959 requires_resume_key,dont_descend,
960 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
961 &last_name_off);
964 if (finished && out_of_space)
965 finished = False;
967 if (!finished && !out_of_space)
968 numentries++;
971 * As an optimisation if we know we aren't looking
972 * for a wildcard name (ie. the name matches the wildcard exactly)
973 * then we can finish on any (first) match.
974 * This speeds up large directory searches. JRA.
977 if(got_exact_match)
978 finished = True;
980 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
983 /* Check if we can close the dirptr */
985 if(close_after_first || (finished && close_if_end)) {
986 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
987 dptr_close(&dptr_num);
991 * If there are no matching entries we must return ERRDOS/ERRbadfile -
992 * from observation of NT.
995 if(numentries == 0) {
996 dptr_close(&dptr_num);
997 return ERROR_DOS(ERRDOS,ERRbadfile);
1000 /* At this point pdata points to numentries directory entries. */
1002 /* Set up the return parameter block */
1003 SSVAL(params,0,dptr_num);
1004 SSVAL(params,2,numentries);
1005 SSVAL(params,4,finished);
1006 SSVAL(params,6,0); /* Never an EA error */
1007 SSVAL(params,8,last_name_off);
1009 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1011 if ((! *directory) && dptr_path(dptr_num))
1012 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1014 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1015 smb_fn_name(CVAL(inbuf,smb_com)),
1016 mask, directory, dirtype, numentries ) );
1019 * Force a name mangle here to ensure that the
1020 * mask as an 8.3 name is top of the mangled cache.
1021 * The reasons for this are subtle. Don't remove
1022 * this code unless you know what you are doing
1023 * (see PR#13758). JRA.
1026 if(!is_8_3( mask, False))
1027 name_map_mangle(mask, True, True, SNUM(conn));
1029 return(-1);
1032 /****************************************************************************
1033 Reply to a TRANS2_FINDNEXT.
1034 ****************************************************************************/
1036 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1037 char **pparams, int total_params, char **ppdata, int total_data)
1039 /* We must be careful here that we don't return more than the
1040 allowed number of data bytes. If this means returning fewer than
1041 maxentries then so be it. We assume that the redirector has
1042 enough room for the fixed number of parameter bytes it has
1043 requested. */
1044 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1045 char *params = *pparams;
1046 char *pdata = *ppdata;
1047 int dptr_num;
1048 int maxentries;
1049 uint16 info_level;
1050 uint32 resume_key;
1051 BOOL close_after_request;
1052 BOOL close_if_end;
1053 BOOL requires_resume_key;
1054 BOOL continue_bit;
1055 pstring resume_name;
1056 pstring mask;
1057 pstring directory;
1058 char *p;
1059 uint16 dirtype;
1060 int numentries = 0;
1061 int i, last_name_off=0;
1062 BOOL finished = False;
1063 BOOL dont_descend = False;
1064 BOOL out_of_space = False;
1065 int space_remaining;
1067 if (total_params < 12)
1068 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1070 dptr_num = SVAL(params,0);
1071 maxentries = SVAL(params,2);
1072 info_level = SVAL(params,4);
1073 resume_key = IVAL(params,6);
1074 close_after_request = BITSETW(params+10,0);
1075 close_if_end = BITSETW(params+10,1);
1076 requires_resume_key = BITSETW(params+10,2);
1077 continue_bit = BITSETW(params+10,3);
1079 *mask = *directory = *resume_name = 0;
1081 pstrcpy( resume_name, params+12);
1083 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1084 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1085 resume_key = %d resume name = %s continue=%d level = %d\n",
1086 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1087 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1089 switch (info_level) {
1090 case 1:
1091 case 2:
1092 case 3:
1093 case 4:
1094 case SMB_FIND_FILE_DIRECTORY_INFO:
1095 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1096 case SMB_FIND_FILE_NAMES_INFO:
1097 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1098 break;
1099 case SMB_FIND_FILE_UNIX:
1100 if (!lp_unix_extensions())
1101 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1102 break;
1103 default:
1104 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1107 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1108 if(pdata == NULL)
1109 return ERROR_DOS(ERRDOS,ERRnomem);
1111 *ppdata = pdata;
1112 memset((char *)pdata,'\0',max_data_bytes + 1024);
1114 /* Realloc the params space */
1115 params = Realloc(*pparams, 6*SIZEOFWORD);
1116 if( params == NULL )
1117 return ERROR_DOS(ERRDOS,ERRnomem);
1118 *pparams = params;
1120 /* Check that the dptr is valid */
1121 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1122 return ERROR_DOS(ERRDOS,ERRnofiles);
1124 string_set(&conn->dirpath,dptr_path(dptr_num));
1126 /* Get the wildcard mask from the dptr */
1127 if((p = dptr_wcard(dptr_num))== NULL) {
1128 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1129 return ERROR_DOS(ERRDOS,ERRnofiles);
1131 pstrcpy(mask, p);
1132 pstrcpy(directory,conn->dirpath);
1134 /* Get the attr mask from the dptr */
1135 dirtype = dptr_attr(dptr_num);
1137 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1138 dptr_num, mask, dirtype, (long)conn->dirptr, TellDir(conn->dirptr)));
1140 /* We don't need to check for VOL here as this is returned by
1141 a different TRANS2 call. */
1143 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1144 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1145 dont_descend = True;
1147 p = pdata;
1148 space_remaining = max_data_bytes;
1149 out_of_space = False;
1152 * Seek to the correct position. We no longer use the resume key but
1153 * depend on the last file name instead.
1156 if(requires_resume_key && *resume_name && !continue_bit) {
1159 * Fix for NT redirector problem triggered by resume key indexes
1160 * changing between directory scans. We now return a resume key of 0
1161 * and instead look for the filename to continue from (also given
1162 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1163 * findfirst/findnext (as is usual) then the directory pointer
1164 * should already be at the correct place. Check this by scanning
1165 * backwards looking for an exact (ie. case sensitive) filename match.
1166 * If we get to the beginning of the directory and haven't found it then scan
1167 * forwards again looking for a match. JRA.
1170 int current_pos, start_pos;
1171 char *dname = NULL;
1172 void *dirptr = conn->dirptr;
1173 start_pos = TellDir(dirptr);
1175 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1176 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1178 SeekDir(dirptr, current_pos);
1179 dname = ReadDirName(dirptr);
1182 * Remember, name_map_mangle is called by
1183 * get_lanman2_dir_entry(), so the resume name
1184 * could be mangled. Ensure we do the same
1185 * here.
1188 if(dname != NULL)
1189 name_map_mangle( dname, False, True, SNUM(conn));
1191 if(dname && strcsequal( resume_name, dname)) {
1192 SeekDir(dirptr, current_pos+1);
1193 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1194 break;
1199 * Scan forward from start if not found going backwards.
1202 if(current_pos < 0) {
1203 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1204 SeekDir(dirptr, start_pos);
1205 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1208 * Remember, name_map_mangle is called by
1209 * get_lanman2_dir_entry(), so the resume name
1210 * could be mangled. Ensure we do the same
1211 * here.
1214 if(dname != NULL)
1215 name_map_mangle( dname, False, True, SNUM(conn));
1217 if(dname && strcsequal( resume_name, dname)) {
1218 SeekDir(dirptr, current_pos+1);
1219 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1220 break;
1222 } /* end for */
1223 } /* end if current_pos */
1224 } /* end if requires_resume_key && !continue_bit */
1226 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1227 BOOL got_exact_match = False;
1229 /* this is a heuristic to avoid seeking the dirptr except when
1230 absolutely necessary. It allows for a filename of about 40 chars */
1232 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1233 out_of_space = True;
1234 finished = False;
1235 } else {
1236 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1237 requires_resume_key,dont_descend,
1238 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1239 &last_name_off);
1242 if (finished && out_of_space)
1243 finished = False;
1245 if (!finished && !out_of_space)
1246 numentries++;
1249 * As an optimisation if we know we aren't looking
1250 * for a wildcard name (ie. the name matches the wildcard exactly)
1251 * then we can finish on any (first) match.
1252 * This speeds up large directory searches. JRA.
1255 if(got_exact_match)
1256 finished = True;
1258 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1261 /* Check if we can close the dirptr */
1262 if(close_after_request || (finished && close_if_end)) {
1263 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1264 dptr_close(&dptr_num); /* This frees up the saved mask */
1268 /* Set up the return parameter block */
1269 SSVAL(params,0,numentries);
1270 SSVAL(params,2,finished);
1271 SSVAL(params,4,0); /* Never an EA error */
1272 SSVAL(params,6,last_name_off);
1274 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1276 if ((! *directory) && dptr_path(dptr_num))
1277 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1279 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1280 smb_fn_name(CVAL(inbuf,smb_com)),
1281 mask, directory, dirtype, numentries ) );
1283 return(-1);
1286 /****************************************************************************
1287 Reply to a TRANS2_QFSINFO (query filesystem info).
1288 ****************************************************************************/
1290 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1291 char **pparams, int total_params, char **ppdata, int total_data)
1293 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1294 char *pdata = *ppdata;
1295 char *params = *pparams;
1296 uint16 info_level;
1297 int data_len;
1298 SMB_STRUCT_STAT st;
1299 char *vname = volume_label(SNUM(conn));
1300 int snum = SNUM(conn);
1301 char *fstype = lp_fstype(SNUM(conn));
1303 if (total_params < 2)
1304 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1306 info_level = SVAL(params,0);
1307 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1309 if(vfs_stat(conn,".",&st)!=0) {
1310 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1311 return ERROR_DOS(ERRSRV,ERRinvdevice);
1314 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1315 if ( pdata == NULL )
1316 return ERROR_DOS(ERRDOS,ERRnomem);
1318 *ppdata = pdata;
1319 memset((char *)pdata,'\0',max_data_bytes + 1024);
1321 switch (info_level) {
1322 case 1:
1324 SMB_BIG_UINT dfree,dsize,bsize;
1325 data_len = 18;
1326 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1327 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1328 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1329 SIVAL(pdata,l1_cUnit,dsize);
1330 SIVAL(pdata,l1_cUnitAvail,dfree);
1331 SSVAL(pdata,l1_cbSector,512);
1332 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1333 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1334 (unsigned int)dfree, 512));
1335 break;
1338 case 2:
1340 /* Return volume name */
1341 int volname_len = MIN(strlen(vname),11);
1342 data_len = l2_vol_szVolLabel + volname_len + 1;
1344 * Add volume serial number - hash of a combination of
1345 * the called hostname and the service name.
1347 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1348 SCVAL(pdata,l2_vol_cch,volname_len);
1349 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1350 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1351 (unsigned)st.st_ctime, volname_len,
1352 pdata+l2_vol_szVolLabel));
1353 break;
1356 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1357 case SMB_FS_ATTRIBUTE_INFORMATION:
1359 int fstype_len;
1360 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1361 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1362 #if 0 /* Old code. JRA. */
1363 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1364 SIVAL(pdata,0,0x700FF);
1365 #endif /* Old code. */
1367 SIVAL(pdata,4,255); /* Max filename component length */
1368 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1369 and will think we can't do long filenames */
1370 fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False);
1371 SIVAL(pdata,8,fstype_len);
1372 data_len = 12 + fstype_len;
1373 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1374 break;
1377 case SMB_QUERY_FS_LABEL_INFO:
1378 case SMB_FS_LABEL_INFORMATION:
1379 data_len = 4 + strlen(vname);
1380 SIVAL(pdata,0,strlen(vname));
1381 pstrcpy(pdata+4,vname);
1382 break;
1384 case SMB_QUERY_FS_VOLUME_INFO:
1385 case SMB_FS_VOLUME_INFORMATION:
1387 * Add volume serial number - hash of a combination of
1388 * the called hostname and the service name.
1390 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1391 (str_checksum(local_machine)<<16));
1393 /* NT4 always serves this up as unicode but expects it to be
1394 * delivered as ascii! (tridge && JRA)
1396 if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
1397 data_len = 18 + strlen(vname);
1398 SIVAL(pdata,12,strlen(vname));
1399 pstrcpy(pdata+18,vname);
1400 } else {
1401 int vnamelen;
1403 vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False);
1404 data_len = 18 + vnamelen;
1405 SIVAL(pdata,12,vnamelen);
1406 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1409 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1410 (int)strlen(vname),vname));
1411 break;
1413 case SMB_QUERY_FS_SIZE_INFO:
1414 case SMB_FS_SIZE_INFORMATION:
1416 SMB_BIG_UINT dfree,dsize,bsize;
1417 data_len = 24;
1418 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1419 SBIG_UINT(pdata,0,dsize);
1420 SBIG_UINT(pdata,8,dfree);
1421 SIVAL(pdata,16,bsize/512);
1422 SIVAL(pdata,20,512);
1423 break;
1426 case SMB_FS_FULL_SIZE_INFORMATION:
1428 SMB_BIG_UINT dfree,dsize,bsize;
1429 data_len = 32;
1430 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1431 SBIG_UINT(pdata,0,dsize);
1432 SBIG_UINT(pdata,8,dsize);
1433 SBIG_UINT(pdata,16,dfree);
1434 SIVAL(pdata,24,bsize/512);
1435 SIVAL(pdata,28,512);
1436 break;
1439 case SMB_QUERY_FS_DEVICE_INFO:
1440 case SMB_FS_DEVICE_INFORMATION:
1441 data_len = 8;
1442 SIVAL(pdata,0,0); /* dev type */
1443 SIVAL(pdata,4,0); /* characteristics */
1444 break;
1446 case SMB_FS_OBJECTID_INFORMATION:
1447 data_len = 64;
1448 break;
1451 * Query the version and capabilities of the CIFS UNIX extensions
1452 * in use.
1455 case SMB_QUERY_CIFS_UNIX_INFO:
1457 if (!lp_unix_extensions())
1458 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1460 data_len = 12;
1461 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1462 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1463 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1464 break;
1466 case SMB_MAC_QUERY_FS_INFO:
1468 * Thursby MAC extension... ONLY on NTFS filesystems
1469 * once we do streams then we don't need this
1471 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1472 data_len = 88;
1473 SIVAL(pdata,84,0x100); /* Don't support mac... */
1474 break;
1476 /* drop through */
1477 default:
1478 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1481 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1483 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1485 return -1;
1488 /****************************************************************************
1489 Reply to a TRANS2_SETFSINFO (set filesystem info).
1490 ****************************************************************************/
1492 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1493 char **pparams, int total_params, char **ppdata, int total_data)
1495 /* Just say yes we did it - there is nothing that
1496 can be set here so it doesn't matter. */
1497 int outsize;
1498 DEBUG(3,("call_trans2setfsinfo\n"));
1500 if (!CAN_WRITE(conn))
1501 return(ERROR_DOS(ERRSRV,ERRaccess));
1503 outsize = set_message(outbuf,10,0,True);
1505 return outsize;
1508 /****************************************************************************
1509 Utility function to set bad path error.
1510 ****************************************************************************/
1512 void set_bad_path_error(int err, BOOL bad_path)
1514 if((err == ENOENT) && bad_path) {
1515 unix_ERR_class = ERRDOS;
1516 unix_ERR_code = ERRbadpath;
1520 /****************************************************************************
1521 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1522 file name or file id).
1523 ****************************************************************************/
1525 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1526 char **pparams, int total_params, char **ppdata, int total_data)
1528 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1529 char *params = *pparams;
1530 char *pdata = *ppdata;
1531 uint16 tran_call = SVAL(inbuf, smb_setup0);
1532 uint16 info_level;
1533 int mode=0;
1534 SMB_OFF_T size=0;
1535 SMB_OFF_T allocation_size=0;
1536 unsigned int data_size;
1537 SMB_STRUCT_STAT sbuf;
1538 pstring fname1;
1539 char *fname;
1540 char *fullpathname;
1541 char *p;
1542 int l;
1543 SMB_OFF_T pos = 0;
1544 BOOL bad_path = False;
1545 BOOL delete_pending = False;
1546 time_t c_time;
1548 if (!params)
1549 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1551 if (tran_call == TRANSACT2_QFILEINFO) {
1552 files_struct *fsp;
1554 if (total_params < 4)
1555 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1557 fsp = file_fsp(params,0);
1558 info_level = SVAL(params,2);
1560 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1562 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1564 * This is actually a QFILEINFO on a directory
1565 * handle (returned from an NT SMB). NT5.0 seems
1566 * to do this call. JRA.
1568 fname = fsp->fsp_name;
1569 unix_convert(fname,conn,0,&bad_path,&sbuf);
1570 if (!check_name(fname,conn)) {
1571 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1572 set_bad_path_error(errno, bad_path);
1573 return(UNIXERROR(ERRDOS,ERRbadpath));
1576 if (INFO_LEVEL_IS_UNIX(info_level)) {
1577 /* Always do lstat for UNIX calls. */
1578 if (vfs_lstat(conn,fname,&sbuf)) {
1579 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1580 set_bad_path_error(errno, bad_path);
1581 return(UNIXERROR(ERRDOS,ERRbadpath));
1583 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1584 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1585 set_bad_path_error(errno, bad_path);
1586 return(UNIXERROR(ERRDOS,ERRbadpath));
1589 delete_pending = fsp->directory_delete_on_close;
1591 } else {
1593 * Original code - this is an open file.
1595 CHECK_FSP(fsp,conn);
1597 fname = fsp->fsp_name;
1598 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1599 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1600 return(UNIXERROR(ERRDOS,ERRbadfid));
1603 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1604 return(UNIXERROR(ERRDOS,ERRnoaccess));
1606 delete_pending = fsp->delete_on_close;
1608 } else {
1609 /* qpathinfo */
1610 if (total_params < 6)
1611 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1613 info_level = SVAL(params,0);
1615 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1617 fname = &fname1[0];
1618 pstrcpy(fname,&params[6]);
1620 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1622 unix_convert(fname,conn,0,&bad_path,&sbuf);
1623 if (!check_name(fname,conn)) {
1624 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1625 set_bad_path_error(errno, bad_path);
1626 return(UNIXERROR(ERRDOS,ERRbadpath));
1628 if (INFO_LEVEL_IS_UNIX(info_level)) {
1629 /* Always do lstat for UNIX calls. */
1630 if (vfs_lstat(conn,fname,&sbuf)) {
1631 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1632 set_bad_path_error(errno, bad_path);
1633 return(UNIXERROR(ERRDOS,ERRbadpath));
1635 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1636 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1637 set_bad_path_error(errno, bad_path);
1638 return(UNIXERROR(ERRDOS,ERRbadpath));
1643 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1644 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1646 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1647 fname,info_level,tran_call,total_data));
1649 p = strrchr(fname,'/');
1650 if (!p)
1651 p = fname;
1652 else
1653 p++;
1654 l = strlen(p);
1655 mode = dos_mode(conn,fname,&sbuf);
1656 fullpathname = fname;
1657 size = sbuf.st_size;
1658 allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1659 if (mode & aDIR)
1660 size = 0;
1662 /* from now on we only want the part after the / */
1663 fname = p;
1665 params = Realloc(*pparams,2);
1666 if ( params == NULL )
1667 return ERROR_DOS(ERRDOS,ERRnomem);
1668 *pparams = params;
1669 memset((char *)params,'\0',2);
1670 data_size = max_data_bytes + 1024;
1671 pdata = Realloc(*ppdata, data_size);
1672 if ( pdata == NULL )
1673 return ERROR_DOS(ERRDOS,ERRnomem);
1674 *ppdata = pdata;
1676 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1677 /* uggh, EAs for OS2 */
1678 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1679 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1682 memset((char *)pdata,'\0',data_size);
1684 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1686 if (lp_dos_filetime_resolution(SNUM(conn))) {
1687 c_time &= ~1;
1688 sbuf.st_atime &= ~1;
1689 sbuf.st_mtime &= ~1;
1690 sbuf.st_mtime &= ~1;
1693 switch (info_level) {
1694 case SMB_INFO_STANDARD:
1695 case SMB_INFO_QUERY_EA_SIZE:
1696 data_size = (info_level==1?22:26);
1697 put_dos_date2(pdata,l1_fdateCreation,c_time);
1698 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1699 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1700 SIVAL(pdata,l1_cbFile,(uint32)size);
1701 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1702 SSVAL(pdata,l1_attrFile,mode);
1703 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1704 break;
1706 case SMB_INFO_QUERY_EAS_FROM_LIST:
1707 data_size = 24;
1708 put_dos_date2(pdata,0,c_time);
1709 put_dos_date2(pdata,4,sbuf.st_atime);
1710 put_dos_date2(pdata,8,sbuf.st_mtime);
1711 SIVAL(pdata,12,(uint32)size);
1712 SIVAL(pdata,16,(uint32)allocation_size);
1713 SIVAL(pdata,20,mode);
1714 break;
1716 case SMB_INFO_QUERY_ALL_EAS:
1717 data_size = 4;
1718 SIVAL(pdata,0,data_size);
1719 break;
1721 case 6:
1722 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1724 case SMB_FILE_BASIC_INFORMATION:
1725 case SMB_QUERY_FILE_BASIC_INFO:
1727 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1728 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1729 else {
1730 data_size = 40;
1731 SIVAL(pdata,36,0);
1733 put_long_date(pdata,c_time);
1734 put_long_date(pdata+8,sbuf.st_atime);
1735 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1736 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1737 SIVAL(pdata,32,mode);
1739 DEBUG(5,("SMB_QFBI - "));
1742 time_t create_time = c_time;
1743 DEBUG(5,("create: %s ", ctime(&create_time)));
1746 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1747 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1748 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1749 DEBUG(5,("mode: %x\n", mode));
1751 break;
1753 case SMB_FILE_STANDARD_INFORMATION:
1754 case SMB_QUERY_FILE_STANDARD_INFO:
1756 data_size = 24;
1757 /* Fake up allocation size. */
1758 SOFF_T(pdata,0,allocation_size);
1759 SOFF_T(pdata,8,size);
1760 SIVAL(pdata,16,sbuf.st_nlink);
1761 SCVAL(pdata,20,0);
1762 SCVAL(pdata,21,(mode&aDIR)?1:0);
1763 break;
1765 case SMB_FILE_EA_INFORMATION:
1766 case SMB_QUERY_FILE_EA_INFO:
1767 data_size = 4;
1768 SIVAL(pdata,0,0);
1769 break;
1771 /* Get the 8.3 name - used if NT SMB was negotiated. */
1773 case SMB_QUERY_FILE_ALT_NAME_INFO:
1775 pstring short_name;
1776 pstrcpy(short_name,p);
1777 /* Mangle if not already 8.3 */
1778 if(!is_8_3(short_name, True)) {
1779 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1780 *short_name = '\0';
1782 strupper(short_name);
1783 l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False);
1784 data_size = 4 + l;
1785 SIVAL(pdata,0,l);
1786 break;
1789 case SMB_QUERY_FILE_NAME_INFO:
1791 * The first part of this code is essential
1792 * to get security descriptors to work on mapped
1793 * drives. Don't ask how I discovered this unless
1794 * you like hearing about me suffering.... :-). JRA.
1797 if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) {
1798 l = l*2;
1799 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1800 dos_PutUniCode(pdata + 4, "\\",sizeof(pstring), False);
1801 } else {
1802 pstrcpy(pdata+4,fname);
1804 data_size = 4 + l;
1805 SIVAL(pdata,0,l);
1806 break;
1808 case SMB_FILE_ALLOCATION_INFORMATION:
1809 case SMB_QUERY_FILE_ALLOCATION_INFO:
1810 data_size = 8;
1811 SOFF_T(pdata,0,allocation_size);
1812 break;
1814 case SMB_QUERY_FILE_END_OF_FILEINFO:
1815 case SMB_FILE_END_OF_FILE_INFORMATION:
1816 data_size = 8;
1817 SOFF_T(pdata,0,size);
1818 break;
1820 case SMB_QUERY_FILE_ALL_INFO:
1821 put_long_date(pdata,c_time);
1822 put_long_date(pdata+8,sbuf.st_atime);
1823 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1824 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1825 SIVAL(pdata,32,mode);
1826 pdata += 40;
1827 SOFF_T(pdata,0,allocation_size);
1828 SOFF_T(pdata,8,size);
1829 SIVAL(pdata,16,sbuf.st_nlink);
1830 SCVAL(pdata,20,delete_pending);
1831 SCVAL(pdata,21,(mode&aDIR)?1:0);
1832 pdata += 24;
1833 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1834 pdata += 8; /* index number */
1835 pdata += 4; /* EA info */
1836 if (mode & aRONLY)
1837 SIVAL(pdata,0,0xA9);
1838 else
1839 SIVAL(pdata,0,0xd01BF);
1840 pdata += 4;
1841 SOFF_T(pdata,0,pos); /* current offset */
1842 pdata += 8;
1843 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1844 pdata += 4;
1845 pdata += 4; /* alignment */
1846 SIVAL(pdata,0,l);
1847 pstrcpy(pdata+4,fname);
1848 pdata += 4 + l;
1849 data_size = PTR_DIFF(pdata,(*ppdata));
1850 break;
1852 case SMB_FILE_INTERNAL_INFORMATION:
1853 /* This should be an index number - looks like dev/ino to me :-) */
1854 SIVAL(pdata,0,sbuf.st_dev);
1855 SIVAL(pdata,4,sbuf.st_ino);
1856 data_size = 8;
1857 break;
1859 case SMB_FILE_ACCESS_INFORMATION:
1860 SIVAL(pdata,0,0x12019F); /* ??? */
1861 data_size = 4;
1862 break;
1864 case SMB_FILE_NAME_INFORMATION:
1865 /* Pathname with leading '\'. */
1867 pstring new_fname;
1868 size_t byte_len;
1870 pstrcpy(new_fname, "\\");
1871 pstrcat(new_fname, fname);
1872 byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False);
1873 SIVAL(pdata,0,byte_len);
1874 data_size = 4 + byte_len;
1875 break;
1878 case SMB_FILE_DISPOSITION_INFORMATION:
1879 data_size = 1;
1880 SCVAL(pdata,0,delete_pending);
1881 break;
1883 case SMB_FILE_POSITION_INFORMATION:
1884 data_size = 8;
1885 SOFF_T(pdata,0,pos);
1886 break;
1888 case SMB_FILE_MODE_INFORMATION:
1889 SIVAL(pdata,0,mode);
1890 data_size = 4;
1891 break;
1893 case SMB_FILE_ALIGNMENT_INFORMATION:
1894 SIVAL(pdata,0,0); /* No alignment needed. */
1895 data_size = 4;
1896 break;
1898 #if 0
1899 /* Not yet finished... JRA */
1900 case 1018:
1902 pstring new_fname;
1903 size_t byte_len;
1905 put_long_date(pdata,c_time);
1906 put_long_date(pdata+8,sbuf.st_atime);
1907 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1908 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1909 SIVAL(pdata,32,mode);
1910 SIVAL(pdata,36,0); /* ??? */
1911 SIVAL(pdata,40,0x20); /* ??? */
1912 SIVAL(pdata,44,0); /* ??? */
1913 SOFF_T(pdata,48,size);
1914 SIVAL(pdata,56,0x1); /* ??? */
1915 SIVAL(pdata,60,0); /* ??? */
1916 SIVAL(pdata,64,0); /* ??? */
1917 SIVAL(pdata,68,length); /* Following string length in bytes. */
1918 dos_PutUniCode(pdata+72,,False);
1919 break;
1921 #endif
1923 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1924 /* Last component of pathname. */
1926 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1927 SIVAL(pdata,0,byte_len);
1928 data_size = 4 + byte_len;
1929 break;
1932 case SMB_FILE_STREAM_INFORMATION:
1933 if (mode & aDIR) {
1934 data_size = 0;
1935 } else {
1936 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1937 SIVAL(pdata,0,0); /* ??? */
1938 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1939 SOFF_T(pdata,8,size);
1940 SIVAL(pdata,16,allocation_size);
1941 SIVAL(pdata,20,0); /* ??? */
1942 data_size = 24 + byte_len;
1944 break;
1946 case SMB_FILE_COMPRESSION_INFORMATION:
1947 SOFF_T(pdata,0,size);
1948 SIVAL(pdata,8,0); /* ??? */
1949 SIVAL(pdata,12,0); /* ??? */
1950 data_size = 16;
1951 break;
1953 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1954 put_long_date(pdata,c_time);
1955 put_long_date(pdata+8,sbuf.st_atime);
1956 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1957 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1958 SOFF_T(pdata,32,allocation_size); /* Allocation size. */
1959 SOFF_T(pdata,40,size);
1960 SIVAL(pdata,48,mode);
1961 SIVAL(pdata,52,0); /* ??? */
1962 data_size = 56;
1963 break;
1965 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1966 SIVAL(pdata,0,mode);
1967 SIVAL(pdata,4,0);
1968 data_size = 8;
1969 break;
1971 #if 0
1973 * NT4 server just returns "invalid query" to this - if we try to answer
1974 * it then NTws gets a BSOD! (tridge).
1975 * W2K seems to want this. JRA.
1978 case SMB_QUERY_FILE_STREAM_INFO:
1979 if (get_remote_arch() != RA_WIN2K)
1980 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1981 data_size = 24 + l;
1982 SIVAL(pdata,0,pos);
1983 SIVAL(pdata,4,size);
1984 SIVAL(pdata,12,allocation_size);
1985 SIVAL(pdata,20,l);
1986 pstrcpy(pdata+24,fname);
1987 break;
1988 #endif
1991 * CIFS UNIX Extensions.
1994 case SMB_QUERY_FILE_UNIX_BASIC:
1996 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1998 SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */
1999 pdata += 8;
2001 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2002 SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
2003 #else
2004 /* Can't get the value - fake it using size. */
2005 SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
2006 #endif
2007 pdata += 8;
2009 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2010 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2011 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2012 pdata += 24;
2014 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2015 SIVAL(pdata,4,0);
2016 pdata += 8;
2018 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2019 SIVAL(pdata,4,0);
2020 pdata += 8;
2022 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2023 pdata += 4;
2025 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2026 SIVAL(pdata,4,0);
2027 pdata += 8;
2029 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2030 SIVAL(pdata,4,0);
2031 pdata += 8;
2033 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2034 pdata += 8;
2036 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2037 SIVAL(pdata,4,0);
2038 pdata += 8;
2040 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2041 SIVAL(pdata,4,0);
2042 pdata += 8+1;
2043 data_size = PTR_DIFF(pdata,(*ppdata));
2046 int i;
2047 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2049 for (i=0; i<100; i++)
2050 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2051 DEBUG(4,("\n"));
2054 break;
2056 case SMB_QUERY_FILE_UNIX_LINK:
2058 pstring buffer;
2059 int len;
2061 #ifdef S_ISLNK
2062 if(!S_ISLNK(sbuf.st_mode))
2063 return(UNIXERROR(ERRSRV,ERRbadlink));
2064 #else
2065 return(UNIXERROR(ERRDOS,ErrNotALink));
2066 #endif
2067 len = conn->vfs_ops.readlink(conn,dos_to_unix(fullpathname,False), buffer, sizeof(pstring)-1); /* read link */
2068 if (len == -1)
2069 return(UNIXERROR(ERRDOS,ERRnoaccess));
2070 buffer[len] = 0;
2071 unix_to_dos(buffer,True);
2072 pstrcpy(pdata,buffer); /* write '\0' terminated string */
2073 pdata += strlen(buffer)+1;
2074 data_size = PTR_DIFF(pdata,(*ppdata));
2076 break;
2079 default:
2080 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2083 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
2085 return(-1);
2088 /****************************************************************************
2089 Deal with the internal needs of setting the delete on close flag. Note that
2090 as the tdb locking is recursive, it is safe to call this from within
2091 open_file_shared. JRA.
2092 ****************************************************************************/
2094 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2097 * Only allow delete on close for writable shares.
2100 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2101 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2102 fsp->fsp_name ));
2103 return NT_STATUS_ACCESS_DENIED;
2106 * Only allow delete on close for files/directories opened with delete intent.
2109 if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
2110 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2111 fsp->fsp_name ));
2112 return NT_STATUS_ACCESS_DENIED;
2115 if(fsp->is_directory) {
2116 fsp->directory_delete_on_close = delete_on_close;
2117 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2118 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2119 } else if(fsp->stat_open) {
2121 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, stat open %s\n",
2122 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2124 } else {
2126 files_struct *iterate_fsp;
2129 * Modify the share mode entry for all files open
2130 * on this device and inode to tell other smbds we have
2131 * changed the delete on close flag. This will be noticed
2132 * in the close code, the last closer will delete the file
2133 * if flag is set.
2136 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2137 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2139 if (lock_share_entry_fsp(fsp) == False)
2140 return NT_STATUS_ACCESS_DENIED;
2142 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2143 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2144 fsp->fsp_name ));
2145 unlock_share_entry_fsp(fsp);
2146 return NT_STATUS_ACCESS_DENIED;
2150 * Release the lock.
2153 unlock_share_entry_fsp(fsp);
2156 * Go through all files we have open on the same device and
2157 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2158 * Other smbd's that have this file open will look in the share_mode on close.
2159 * take care of this (rare) case in close_file(). See the comment there.
2160 * NB. JRA. We don't really need to do this anymore - all should be taken
2161 * care of in the share_mode changes in the tdb.
2164 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2165 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2166 fsp->delete_on_close = delete_on_close;
2169 * Set the delete on close flag in the fsp.
2171 fsp->delete_on_close = delete_on_close;
2173 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2174 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2178 return NT_STATUS_OK;
2181 /****************************************************************************
2182 Returns true if this pathname is within the share, and thus safe.
2183 ****************************************************************************/
2185 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2187 #ifdef PATH_MAX
2188 char resolved_name[PATH_MAX+1];
2189 #else
2190 pstring resolved_name;
2191 #endif
2192 fstring last_component;
2193 pstring link_dest;
2194 pstring link_test;
2195 char *p;
2196 BOOL bad_path = False;
2197 SMB_STRUCT_STAT sbuf;
2199 pstrcpy(link_dest, link_dest_in);
2200 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2202 /* Store the UNIX converted path. */
2203 pstrcpy(link_dest_out, link_dest);
2205 p = strrchr(link_dest, '/');
2206 if (p) {
2207 fstrcpy(last_component, p+1);
2208 *p = '\0';
2209 } else {
2210 fstrcpy(last_component, link_dest);
2211 pstrcpy(link_dest, "./");
2214 if (conn->vfs_ops.realpath(conn,dos_to_unix(link_dest,False),resolved_name) == NULL)
2215 return -1;
2217 pstrcpy(link_dest, unix_to_dos(resolved_name,False));
2218 pstrcat(link_dest, "/");
2219 pstrcat(link_dest, last_component);
2221 if (*link_dest != '/') {
2222 /* Relative path. */
2223 pstrcpy(link_test, conn->connectpath);
2224 pstrcat(link_test, "/");
2225 pstrcat(link_test, link_dest);
2226 } else {
2227 pstrcpy(link_test, link_dest);
2231 * Check if the link is within the share.
2234 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2235 errno = EACCES;
2236 return -1;
2238 return 0;
2241 /****************************************************************************
2242 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2243 ****************************************************************************/
2245 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2246 char **pparams, int total_params, char **ppdata, int total_data)
2248 char *params = *pparams;
2249 char *pdata = *ppdata;
2250 uint16 tran_call = SVAL(inbuf, smb_setup0);
2251 uint16 info_level;
2252 int dosmode = 0;
2253 SMB_OFF_T size=0;
2254 struct utimbuf tvs;
2255 SMB_STRUCT_STAT sbuf;
2256 pstring fname1;
2257 char *fname = NULL;
2258 int fd = -1;
2259 BOOL bad_path = False;
2260 files_struct *fsp = NULL;
2261 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2262 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2263 mode_t unixmode = 0;
2265 if (tran_call == TRANSACT2_SETFILEINFO) {
2267 if (total_params < 4)
2268 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2270 fsp = file_fsp(params,0);
2271 info_level = SVAL(params,2);
2273 if(fsp && (fsp->is_directory || fsp->stat_open)) {
2275 * This is actually a SETFILEINFO on a directory
2276 * handle (returned from an NT SMB). NT5.0 seems
2277 * to do this call. JRA.
2279 fname = fsp->fsp_name;
2280 unix_convert(fname,conn,0,&bad_path,&sbuf);
2281 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2282 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2283 set_bad_path_error(errno, bad_path);
2284 return(UNIXERROR(ERRDOS,ERRbadpath));
2286 } else if (fsp && fsp->print_file) {
2288 * Doing a DELETE_ON_CLOSE should cancel a print job.
2290 if (((info_level == SMB_SET_FILE_DISPOSITION_INFO)||(info_level == SMB_FILE_DISPOSITION_INFORMATION)) &&
2291 CVAL(pdata,0)) {
2292 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2294 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
2295 fsp->fsp_name ));
2297 SSVAL(params,0,0);
2298 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2299 return(-1);
2301 } else {
2303 * Original code - this is an open file.
2305 CHECK_FSP(fsp,conn);
2307 fname = fsp->fsp_name;
2308 fd = fsp->fd;
2310 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2311 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2312 return(UNIXERROR(ERRDOS,ERRbadfid));
2315 } else {
2316 /* set path info */
2317 if (total_params < 6)
2318 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2320 info_level = SVAL(params,0);
2321 fname = fname1;
2322 pstrcpy(fname,&params[6]);
2323 unix_convert(fname,conn,0,&bad_path,&sbuf);
2324 if(!check_name(fname, conn)) {
2325 set_bad_path_error(errno, bad_path);
2326 return(UNIXERROR(ERRDOS,ERRbadpath));
2330 * For CIFS UNIX extensions the target name may not exist.
2333 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2335 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2336 set_bad_path_error(errno, bad_path);
2337 return(UNIXERROR(ERRDOS,ERRbadpath));
2341 if (!CAN_WRITE(conn))
2342 return ERROR_DOS(ERRSRV,ERRaccess);
2344 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2345 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2347 if (VALID_STAT(sbuf))
2348 unixmode = sbuf.st_mode;
2350 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2351 tran_call,fname,info_level,total_data));
2353 /* Realloc the parameter and data sizes */
2354 params = Realloc(*pparams,2);
2355 if(params == NULL)
2356 return ERROR_DOS(ERRDOS,ERRnomem);
2357 *pparams = params;
2359 SSVAL(params,0,0);
2361 size = sbuf.st_size;
2362 tvs.modtime = sbuf.st_mtime;
2363 tvs.actime = sbuf.st_atime;
2364 dosmode = dos_mode(conn,fname,&sbuf);
2365 unixmode = sbuf.st_mode;
2367 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2368 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2370 if (total_data > 4 && IVAL(pdata,0) == total_data) {
2371 /* uggh, EAs for OS2 */
2372 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2373 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2376 switch (info_level) {
2377 case SMB_INFO_STANDARD:
2378 case SMB_INFO_QUERY_EA_SIZE:
2380 if (total_data < l1_cbFile+4)
2381 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2383 /* access time */
2384 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2386 /* write time */
2387 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2389 dosmode = SVAL(pdata,l1_attrFile);
2390 size = IVAL(pdata,l1_cbFile);
2391 break;
2394 /* XXXX um, i don't think this is right.
2395 it's also not in the cifs6.txt spec.
2397 case SMB_INFO_QUERY_EAS_FROM_LIST:
2398 if (total_data < 28)
2399 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2401 tvs.actime = make_unix_date2(pdata+8);
2402 tvs.modtime = make_unix_date2(pdata+12);
2403 size = IVAL(pdata,16);
2404 dosmode = IVAL(pdata,24);
2405 break;
2407 /* XXXX nor this. not in cifs6.txt, either. */
2408 case SMB_INFO_QUERY_ALL_EAS:
2409 if (total_data < 28)
2410 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2412 tvs.actime = make_unix_date2(pdata+8);
2413 tvs.modtime = make_unix_date2(pdata+12);
2414 size = IVAL(pdata,16);
2415 dosmode = IVAL(pdata,24);
2416 break;
2418 case SMB_SET_FILE_BASIC_INFO:
2419 case SMB_FILE_BASIC_INFORMATION:
2421 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2422 time_t write_time;
2423 time_t changed_time;
2425 if (total_data < 36)
2426 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2428 /* Ignore create time at offset pdata. */
2430 /* access time */
2431 tvs.actime = interpret_long_date(pdata+8);
2433 write_time = interpret_long_date(pdata+16);
2434 changed_time = interpret_long_date(pdata+24);
2436 tvs.modtime = MIN(write_time, changed_time);
2438 /* Prefer a defined time to an undefined one. */
2439 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2440 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2441 ? changed_time
2442 : write_time);
2444 /* attributes */
2445 dosmode = IVAL(pdata,32);
2446 break;
2449 case SMB_FILE_ALLOCATION_INFORMATION:
2450 case SMB_SET_FILE_ALLOCATION_INFO:
2452 int ret = -1;
2453 SMB_OFF_T allocation_size;
2455 if (total_data < 8)
2456 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2458 allocation_size = IVAL(pdata,0);
2459 #ifdef LARGE_SMB_OFF_T
2460 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2461 #else /* LARGE_SMB_OFF_T */
2462 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2463 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2464 #endif /* LARGE_SMB_OFF_T */
2465 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2466 fname, (double)allocation_size ));
2468 if(allocation_size != sbuf.st_size) {
2469 SMB_STRUCT_STAT new_sbuf;
2471 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2472 fname, (double)allocation_size ));
2474 if (fd == -1) {
2475 files_struct *new_fsp = NULL;
2476 int access_mode = 0;
2477 int action = 0;
2479 if(global_oplock_break) {
2480 /* Queue this file modify as we are the process of an oplock break. */
2482 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2483 DEBUGADD(2,( "in oplock break state.\n"));
2485 push_oplock_pending_smb_message(inbuf, length);
2486 return -1;
2489 new_fsp = open_file_shared(conn, fname, &sbuf,
2490 SET_OPEN_MODE(DOS_OPEN_RDWR),
2491 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2492 0, 0, &access_mode, &action);
2494 if (new_fsp == NULL)
2495 return(UNIXERROR(ERRDOS,ERRbadpath));
2496 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2497 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2498 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2499 ret = -1;
2501 close_file(new_fsp,True);
2502 } else {
2503 ret = vfs_allocate_file_space(fsp, allocation_size);
2504 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2505 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2506 ret = -1;
2509 if (ret == -1)
2510 return ERROR_NT(NT_STATUS_DISK_FULL);
2512 /* Allocate can trucate size... */
2513 size = new_sbuf.st_size;
2516 break;
2519 case SMB_FILE_END_OF_FILE_INFORMATION:
2520 case SMB_SET_FILE_END_OF_FILE_INFO:
2522 if (total_data < 8)
2523 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2525 size = IVAL(pdata,0);
2526 #ifdef LARGE_SMB_OFF_T
2527 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2528 #else /* LARGE_SMB_OFF_T */
2529 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2530 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2531 #endif /* LARGE_SMB_OFF_T */
2532 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2533 break;
2536 case SMB_FILE_DISPOSITION_INFORMATION:
2537 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2539 BOOL delete_on_close;
2540 NTSTATUS status;
2542 if (total_data < 1)
2543 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2545 delete_on_close = (CVAL(pdata,0) ? True : False);
2547 if (tran_call != TRANSACT2_SETFILEINFO)
2548 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
2550 if (fsp == NULL)
2551 return(UNIXERROR(ERRDOS,ERRbadfid));
2553 status = set_delete_on_close_internal(fsp, delete_on_close);
2555 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2556 return ERROR_NT(status);
2558 break;
2562 * CIFS UNIX extensions.
2565 case SMB_SET_FILE_UNIX_BASIC:
2567 uint32 raw_unixmode;
2569 if (total_data < 100)
2570 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2572 size=IVAL(pdata,0); /* first 8 Bytes are size */
2573 #ifdef LARGE_SMB_OFF_T
2574 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2575 #else /* LARGE_SMB_OFF_T */
2576 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2577 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2578 #endif /* LARGE_SMB_OFF_T */
2579 pdata+=24; /* ctime & st_blocks are not changed */
2580 tvs.actime = interpret_long_date(pdata); /* access_time */
2581 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
2582 pdata+=16;
2583 set_owner = (uid_t)IVAL(pdata,0);
2584 pdata += 8;
2585 set_grp = (gid_t)IVAL(pdata,0);
2586 pdata += 8;
2587 raw_unixmode = IVAL(pdata,28);
2588 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2589 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2591 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2592 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2593 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2595 if (!VALID_STAT(sbuf)) {
2598 * The only valid use of this is to create character and block
2599 * devices, and named pipes. This is deprecated (IMHO) and
2600 * a new info level should be used for mknod. JRA.
2603 #if !defined(HAVE_MAKEDEV_FN)
2604 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2605 #else /* HAVE_MAKEDEV_FN */
2606 uint32 file_type = IVAL(pdata,0);
2607 uint32 dev_major = IVAL(pdata,4);
2608 uint32 dev_minor = IVAL(pdata,12);
2610 uid_t myuid = geteuid();
2611 gid_t mygid = getegid();
2612 SMB_DEV_T dev;
2614 if (tran_call == TRANSACT2_SETFILEINFO)
2615 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2617 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2618 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2620 dev = makedev(dev_major, dev_minor);
2622 /* We can only create as the owner/group we are. */
2624 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2625 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2626 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2627 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2629 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2630 file_type != UNIX_TYPE_FIFO)
2631 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2633 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2634 0%o for file %s\n", (double)dev, unixmode, fname ));
2636 /* Ok - do the mknod. */
2637 if (conn->vfs_ops.mknod(conn,dos_to_unix(fname,False), unixmode, dev) != 0)
2638 return(UNIXERROR(ERRDOS,ERRnoaccess));
2640 SSVAL(params,0,0);
2641 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2642 return(-1);
2643 #endif /* HAVE_MAKEDEV_FN */
2648 * Deal with the UNIX specific mode set.
2651 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2652 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2653 unixmode, fname ));
2654 if (vfs_chmod(conn,fname,unixmode) != 0)
2655 return(UNIXERROR(ERRDOS,ERRnoaccess));
2659 * Deal with the UNIX specific uid set.
2662 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2663 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2664 (unsigned int)set_owner, fname ));
2665 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2666 return(UNIXERROR(ERRDOS,ERRnoaccess));
2670 * Deal with the UNIX specific gid set.
2673 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2674 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2675 (unsigned int)set_owner, fname ));
2676 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2677 return(UNIXERROR(ERRDOS,ERRnoaccess));
2679 break;
2682 case SMB_SET_FILE_UNIX_LINK:
2684 pstring link_dest;
2685 /* Set a symbolic link. */
2686 /* Don't allow this if follow links is false. */
2688 if (!lp_symlinks(SNUM(conn)))
2689 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2691 /* Disallow if already exists. */
2692 if (VALID_STAT(sbuf))
2693 return(ERROR_DOS(ERRDOS,ERRbadpath));
2695 pstrcpy(link_dest, pdata);
2697 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2698 return(UNIXERROR(ERRDOS,ERRnoaccess));
2699 dos_to_unix(link_dest, True);
2700 dos_to_unix(fname, True);
2702 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2703 fname, link_dest ));
2705 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2706 return(UNIXERROR(ERRDOS,ERRnoaccess));
2707 SSVAL(params,0,0);
2708 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2709 return(-1);
2712 case SMB_SET_FILE_UNIX_HLINK:
2714 pstring link_dest;
2716 /* Set a hard link. */
2718 /* Disallow if already exists. */
2719 if (VALID_STAT(sbuf))
2720 return(ERROR_DOS(ERRDOS,ERRbadpath));
2722 pstrcpy(link_dest, pdata);
2724 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2725 return(UNIXERROR(ERRDOS,ERRnoaccess));
2727 dos_to_unix(link_dest, True);
2728 dos_to_unix(fname, True);
2730 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2731 fname, link_dest ));
2733 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2734 return(UNIXERROR(ERRDOS,ERRnoaccess));
2735 SSVAL(params,0,0);
2736 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2737 return(-1);
2740 default:
2741 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2744 /* get some defaults (no modifications) if any info is zero or -1. */
2745 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2746 tvs.actime = sbuf.st_atime;
2748 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2749 tvs.modtime = sbuf.st_mtime;
2751 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2752 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2753 DEBUG(6,("size: %.0f ", (double)size));
2754 DEBUG(6,("dosmode: %x\n" , dosmode));
2756 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2757 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2758 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2759 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2761 * Only do this test if we are not explicitly
2762 * changing the size of a file.
2764 if (!size)
2765 size = sbuf.st_size;
2769 * Try and set the times, size and mode of this file -
2770 * if they are different from the current values
2773 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2774 if(fsp != NULL) {
2776 * This was a setfileinfo on an open file.
2777 * NT does this a lot. It's actually pointless
2778 * setting the time here, as it will be overwritten
2779 * on the next write, so we save the request
2780 * away and will set it on file code. JRA.
2783 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2784 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2785 ctime(&tvs.modtime) ));
2786 fsp->pending_modtime = tvs.modtime;
2789 } else {
2791 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2793 if(file_utime(conn, fname, &tvs)!=0)
2794 return(UNIXERROR(ERRDOS,ERRnoaccess));
2798 /* check the mode isn't different, before changing it */
2799 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2801 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2802 fname, dosmode ));
2804 if(file_chmod(conn, fname, dosmode, NULL)) {
2805 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2806 return(UNIXERROR(ERRDOS,ERRnoaccess));
2810 if(size != sbuf.st_size) {
2812 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2813 fname, (double)size ));
2815 if (fd == -1) {
2816 files_struct *new_fsp = NULL;
2817 int access_mode = 0;
2818 int action = 0;
2820 if(global_oplock_break) {
2821 /* Queue this file modify as we are the process of an oplock break. */
2823 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2824 DEBUGADD(2,( "in oplock break state.\n"));
2826 push_oplock_pending_smb_message(inbuf, length);
2827 return -1;
2830 new_fsp = open_file_shared(conn, fname, &sbuf,
2831 SET_OPEN_MODE(DOS_OPEN_RDWR),
2832 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2833 0, 0, &access_mode, &action);
2835 if (new_fsp == NULL)
2836 return(UNIXERROR(ERRDOS,ERRbadpath));
2837 vfs_set_filelen(new_fsp, size);
2838 close_file(new_fsp,True);
2839 } else {
2840 vfs_set_filelen(fsp, size);
2844 SSVAL(params,0,0);
2845 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2846 return(-1);
2849 /****************************************************************************
2850 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2851 ****************************************************************************/
2853 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2854 char **pparams, int total_params, char **ppdata, int total_data)
2856 char *params = *pparams;
2857 pstring directory;
2858 int ret = -1;
2859 SMB_STRUCT_STAT sbuf;
2860 BOOL bad_path = False;
2862 if (!CAN_WRITE(conn))
2863 return ERROR_DOS(ERRSRV,ERRaccess);
2865 if (total_params < 4)
2866 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2868 pstrcpy(directory, &params[4]);
2870 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2872 unix_convert(directory,conn,0,&bad_path,&sbuf);
2873 if (check_name(directory,conn))
2874 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2876 if(ret < 0) {
2877 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2878 set_bad_path_error(errno, bad_path);
2879 return(UNIXERROR(ERRDOS,ERRnoaccess));
2882 /* Realloc the parameter and data sizes */
2883 params = Realloc(*pparams,2);
2884 if(params == NULL)
2885 return ERROR_DOS(ERRDOS,ERRnomem);
2886 *pparams = params;
2888 SSVAL(params,0,0);
2890 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2892 return(-1);
2895 /****************************************************************************
2896 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2897 We don't actually do this - we just send a null response.
2898 ****************************************************************************/
2900 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2901 char **pparams, int total_params, char **ppdata, int total_data)
2903 static uint16 fnf_handle = 257;
2904 char *params = *pparams;
2905 uint16 info_level;
2907 if (total_params < 6)
2908 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2910 info_level = SVAL(params,4);
2911 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2913 switch (info_level) {
2914 case 1:
2915 case 2:
2916 break;
2917 default:
2918 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2921 /* Realloc the parameter and data sizes */
2922 params = Realloc(*pparams,6);
2923 if(params == NULL)
2924 return ERROR_DOS(ERRDOS,ERRnomem);
2925 *pparams = params;
2927 SSVAL(params,0,fnf_handle);
2928 SSVAL(params,2,0); /* No changes */
2929 SSVAL(params,4,0); /* No EA errors */
2931 fnf_handle++;
2933 if(fnf_handle == 0)
2934 fnf_handle = 257;
2936 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2938 return(-1);
2941 /****************************************************************************
2942 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2943 changes). Currently this does nothing.
2944 ****************************************************************************/
2946 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2947 char **pparams, int total_params, char **ppdata, int total_data)
2949 char *params = *pparams;
2951 DEBUG(3,("call_trans2findnotifynext\n"));
2953 /* Realloc the parameter and data sizes */
2954 params = Realloc(*pparams,4);
2955 if(params == NULL)
2956 return ERROR_DOS(ERRDOS,ERRnomem);
2957 *pparams = params;
2959 SSVAL(params,0,0); /* No changes */
2960 SSVAL(params,2,0); /* No EA errors */
2962 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2964 return(-1);
2967 /****************************************************************************
2968 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2969 ****************************************************************************/
2971 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
2972 char **pparams, int total_params, char **ppdata, int total_data)
2974 char *params = *pparams;
2975 enum remote_arch_types ra_type = get_remote_arch();
2976 BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
2977 pstring pathname;
2978 int reply_size = 0;
2979 int max_referral_level;
2981 DEBUG(10,("call_trans2getdfsreferral\n"));
2983 if (total_params < 2)
2984 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2986 max_referral_level = SVAL(params,0);
2988 if(!lp_host_msdfs())
2989 return ERROR_DOS(ERRDOS,ERRbadfunc);
2991 /* if pathname is in UNICODE, convert to DOS */
2992 /* NT always sends in UNICODE, may not set UNICODE flag */
2993 if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) {
2994 unistr_to_dos(pathname, &params[2], sizeof(pathname));
2995 DEBUG(10,("UNICODE referral for %s\n",pathname));
2996 } else
2997 pstrcpy(pathname,&params[2]);
2999 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3000 return ERROR_DOS(ERRDOS,ERRbadfile);
3002 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES);
3003 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3005 return(-1);
3008 #define LMCAT_SPL 0x53
3009 #define LMFUNC_GETJOBID 0x60
3011 /****************************************************************************
3012 reply to a TRANS2_IOCTL - used for OS/2 printing.
3013 ****************************************************************************/
3015 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3016 char **pparams, int total_params, char **ppdata, int total_data)
3018 char *pdata = *ppdata;
3019 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3021 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3022 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3023 pdata = Realloc(*ppdata, 32);
3024 if(pdata == NULL)
3025 return ERROR_DOS(ERRDOS,ERRnomem);
3026 *ppdata = pdata;
3028 SSVAL(pdata,0,fsp->print_jobid); /* Job number */
3029 StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */
3030 StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */
3031 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3032 return(-1);
3033 } else {
3034 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3035 return ERROR_DOS(ERRSRV,ERRerror);
3039 /****************************************************************************
3040 Reply to a SMBfindclose (stop trans2 directory search).
3041 ****************************************************************************/
3043 int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3045 int outsize = 0;
3046 int dptr_num=SVALS(inbuf,smb_vwv0);
3047 START_PROFILE(SMBfindclose);
3049 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3051 dptr_close(&dptr_num);
3053 outsize = set_message(outbuf,0,0,True);
3055 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3057 END_PROFILE(SMBfindclose);
3058 return(outsize);
3061 /****************************************************************************
3062 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3063 ****************************************************************************/
3065 int reply_findnclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3067 int outsize = 0;
3068 int dptr_num= -1;
3069 START_PROFILE(SMBfindnclose);
3071 dptr_num = SVAL(inbuf,smb_vwv0);
3073 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3075 /* We never give out valid handles for a
3076 findnotifyfirst - so any dptr_num is ok here.
3077 Just ignore it. */
3079 outsize = set_message(outbuf,0,0,True);
3081 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3083 END_PROFILE(SMBfindnclose);
3084 return(outsize);
3087 /****************************************************************************
3088 Reply to a SMBtranss2 - just ignore it!
3089 ****************************************************************************/
3091 int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3093 START_PROFILE(SMBtranss2);
3094 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3095 END_PROFILE(SMBtranss2);
3096 return(-1);
3099 /****************************************************************************
3100 Reply to a SMBtrans2.
3101 ****************************************************************************/
3103 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3105 int outsize = 0;
3106 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3107 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3108 #if 0
3109 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3110 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3111 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3112 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3113 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3114 int32 timeout = IVALS(inbuf,smb_timeout);
3115 #endif
3116 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3117 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3118 char *params = NULL, *data = NULL;
3119 int num_params, num_params_sofar, num_data, num_data_sofar;
3120 START_PROFILE(SMBtrans2);
3122 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3123 /* Queue this open message as we are the process of an
3124 * oplock break. */
3126 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3127 DEBUGADD(2,( "in oplock break state.\n"));
3129 push_oplock_pending_smb_message(inbuf, length);
3130 END_PROFILE(SMBtrans2);
3131 return -1;
3134 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3135 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3136 END_PROFILE(SMBtrans2);
3137 return ERROR_DOS(ERRSRV,ERRaccess);
3140 outsize = set_message(outbuf,0,0,True);
3142 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3143 is so as a sanity check */
3144 if (suwcnt != 1) {
3146 * Need to have rc=0 for ioctl to get job id for OS/2.
3147 * Network printing will fail if function is not successful.
3148 * Similar function in reply.c will be used if protocol
3149 * is LANMAN1.0 instead of LM1.2X002.
3150 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3151 * outbuf doesn't have to be set(only job id is used).
3153 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3154 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3155 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3156 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3157 } else {
3158 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3159 DEBUG(2,("Transaction is %d\n",tran_call));
3160 END_PROFILE(SMBtrans2);
3161 return ERROR_DOS(ERRSRV,ERRerror);
3165 /* Allocate the space for the maximum needed parameters and data */
3166 if (total_params > 0)
3167 params = (char *)malloc(total_params);
3168 if (total_data > 0)
3169 data = (char *)malloc(total_data);
3171 if ((total_params && !params) || (total_data && !data)) {
3172 DEBUG(2,("Out of memory in reply_trans2\n"));
3173 SAFE_FREE(params);
3174 SAFE_FREE(data);
3175 END_PROFILE(SMBtrans2);
3176 return ERROR_DOS(ERRDOS,ERRnomem);
3179 /* Copy the param and data bytes sent with this request into
3180 the params buffer */
3181 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3182 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3184 if (num_params > total_params || num_data > total_data)
3185 exit_server("invalid params in reply_trans2");
3187 if(params)
3188 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3189 if(data)
3190 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3192 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3193 /* We need to send an interim response then receive the rest
3194 of the parameter/data bytes */
3195 outsize = set_message(outbuf,0,0,True);
3196 if (!send_smb(smbd_server_fd(),outbuf))
3197 exit_server("reply_trans2: send_smb failed.");
3199 while (num_data_sofar < total_data ||
3200 num_params_sofar < total_params) {
3201 BOOL ret;
3203 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3205 if ((ret &&
3206 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3207 outsize = set_message(outbuf,0,0,True);
3208 if(ret)
3209 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3210 else
3211 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3212 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3213 SAFE_FREE(params);
3214 SAFE_FREE(data);
3215 END_PROFILE(SMBtrans2);
3216 return ERROR_DOS(ERRSRV,ERRerror);
3219 /* Revise total_params and total_data in case
3220 they have changed downwards */
3221 total_params = SVAL(inbuf, smb_tpscnt);
3222 total_data = SVAL(inbuf, smb_tdscnt);
3223 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3224 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3225 if (num_params_sofar > total_params || num_data_sofar > total_data)
3226 exit_server("data overflow in trans2");
3228 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
3229 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3230 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3231 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3235 if (Protocol >= PROTOCOL_NT1) {
3236 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3239 /* Now we must call the relevant TRANS2 function */
3240 switch(tran_call) {
3241 case TRANSACT2_OPEN:
3242 START_PROFILE_NESTED(Trans2_open);
3243 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3244 &params, total_params, &data, total_data);
3245 END_PROFILE_NESTED(Trans2_open);
3246 break;
3248 case TRANSACT2_FINDFIRST:
3249 START_PROFILE_NESTED(Trans2_findfirst);
3250 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3251 &params, total_params, &data, total_data);
3252 END_PROFILE_NESTED(Trans2_findfirst);
3253 break;
3255 case TRANSACT2_FINDNEXT:
3256 START_PROFILE_NESTED(Trans2_findnext);
3257 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3258 &params, total_params, &data, total_data);
3259 END_PROFILE_NESTED(Trans2_findnext);
3260 break;
3262 case TRANSACT2_QFSINFO:
3263 START_PROFILE_NESTED(Trans2_qfsinfo);
3264 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3265 &params, total_params, &data, total_data);
3266 END_PROFILE_NESTED(Trans2_qfsinfo);
3267 break;
3269 case TRANSACT2_SETFSINFO:
3270 START_PROFILE_NESTED(Trans2_setfsinfo);
3271 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3272 &params, total_params, &data, total_data);
3273 END_PROFILE_NESTED(Trans2_setfsinfo);
3274 break;
3276 case TRANSACT2_QPATHINFO:
3277 case TRANSACT2_QFILEINFO:
3278 START_PROFILE_NESTED(Trans2_qpathinfo);
3279 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3280 &params, total_params, &data, total_data);
3281 END_PROFILE_NESTED(Trans2_qpathinfo);
3282 break;
3283 case TRANSACT2_SETPATHINFO:
3284 case TRANSACT2_SETFILEINFO:
3285 START_PROFILE_NESTED(Trans2_setpathinfo);
3286 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3287 &params, total_params, &data, total_data);
3288 END_PROFILE_NESTED(Trans2_setpathinfo);
3289 break;
3291 case TRANSACT2_FINDNOTIFYFIRST:
3292 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3293 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3294 &params, total_params, &data, total_data);
3295 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3296 break;
3298 case TRANSACT2_FINDNOTIFYNEXT:
3299 START_PROFILE_NESTED(Trans2_findnotifynext);
3300 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3301 &params, total_params, &data, total_data);
3302 END_PROFILE_NESTED(Trans2_findnotifynext);
3303 break;
3304 case TRANSACT2_MKDIR:
3305 START_PROFILE_NESTED(Trans2_mkdir);
3306 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3307 &params, total_params, &data, total_data);
3308 END_PROFILE_NESTED(Trans2_mkdir);
3309 break;
3311 case TRANSACT2_GET_DFS_REFERRAL:
3312 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3313 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3314 &params, total_params, &data, total_data);
3315 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3316 break;
3317 case TRANSACT2_IOCTL:
3318 START_PROFILE_NESTED(Trans2_ioctl);
3319 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3320 &params, total_params, &data, total_data);
3321 END_PROFILE_NESTED(Trans2_ioctl);
3322 break;
3323 default:
3324 /* Error in request */
3325 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3326 SAFE_FREE(params);
3327 SAFE_FREE(data);
3328 END_PROFILE(SMBtrans2);
3329 return ERROR_DOS(ERRSRV,ERRerror);
3332 /* As we do not know how many data packets will need to be
3333 returned here the various call_trans2xxxx calls
3334 must send their own. Thus a call_trans2xxx routine only
3335 returns a value other than -1 when it wants to send
3336 an error packet.
3339 SAFE_FREE(params);
3340 SAFE_FREE(data);
3341 END_PROFILE(SMBtrans2);
3342 return outsize; /* If a correct response was needed the
3343 call_trans2xxx calls have already sent
3344 it. If outsize != -1 then it is returning */