2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2001
6 Extensively modified by Andrew Tridgell, 1995
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.
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;
32 #define get_file_size(sbuf) ((sbuf).st_size)
34 /* given a stat buffer return the allocated size on disk, taking into
35 account sparse files */
36 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
39 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
40 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
42 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
44 if (!ret && fsp && fsp->initial_allocation_size)
45 ret = fsp->initial_allocation_size;
46 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
50 /****************************************************************************
51 Send the required number of replies back.
52 We assume all fields other than the data fields are
53 set correctly for the type of call.
54 HACK ! Always assumes smb_setup field is zero.
55 ****************************************************************************/
57 static int send_trans2_replies(char *outbuf,
64 /* As we are using a protocol > LANMAN1 then the max_send
65 variable must have been set in the sessetupX call.
66 This takes precedence over the max_xmit field in the
67 global struct. These different max_xmit variables should
68 be merged as this is now too confusing */
71 int data_to_send = datasize;
72 int params_to_send = paramsize;
76 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
77 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
78 int data_alignment_offset = 0;
80 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
82 set_message(outbuf,10,0,True);
84 /* If there genuinely are no parameters or data to send just send the empty packet */
86 if(params_to_send == 0 && data_to_send == 0) {
87 if (!send_smb(smbd_server_fd(),outbuf))
88 exit_server("send_trans2_replies: send_smb failed.");
92 /* When sending params and data ensure that both are nicely aligned */
93 /* Only do this alignment when there is also data to send - else
94 can cause NT redirector problems. */
96 if (((params_to_send % 4) != 0) && (data_to_send != 0))
97 data_alignment_offset = 4 - (params_to_send % 4);
99 /* Space is bufsize minus Netbios over TCP header minus SMB header */
100 /* The alignment_offset is to align the param bytes on an even byte
101 boundary. NT 4.0 Beta needs this to work correctly. */
103 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
105 /* useable_space can never be more than max_send minus the alignment offset. */
107 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
109 while (params_to_send || data_to_send) {
110 /* Calculate whether we will totally or partially fill this packet */
112 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
114 /* We can never send more than useable_space */
116 * Note that 'useable_space' does not include the alignment offsets,
117 * but we must include the alignment offsets in the calculation of
118 * the length of the data we send over the wire, as the alignment offsets
119 * are sent here. Fix from Marc_Jacobsen@hp.com.
122 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
124 set_message(outbuf, 10, total_sent_thistime, True);
126 /* Set total params and data to be sent */
127 SSVAL(outbuf,smb_tprcnt,paramsize);
128 SSVAL(outbuf,smb_tdrcnt,datasize);
130 /* Calculate how many parameters and data we can fit into
131 * this packet. Parameters get precedence
134 params_sent_thistime = MIN(params_to_send,useable_space);
135 data_sent_thistime = useable_space - params_sent_thistime;
136 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
138 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
140 /* smb_proff is the offset from the start of the SMB header to the
141 parameter bytes, however the first 4 bytes of outbuf are
142 the Netbios over TCP header. Thus use smb_base() to subtract
143 them from the calculation */
145 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
147 if(params_sent_thistime == 0)
148 SSVAL(outbuf,smb_prdisp,0);
150 /* Absolute displacement of param bytes sent in this packet */
151 SSVAL(outbuf,smb_prdisp,pp - params);
153 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
154 if(data_sent_thistime == 0) {
155 SSVAL(outbuf,smb_droff,0);
156 SSVAL(outbuf,smb_drdisp, 0);
158 /* The offset of the data bytes is the offset of the
159 parameter bytes plus the number of parameters being sent this time */
160 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
161 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
162 SSVAL(outbuf,smb_drdisp, pd - pdata);
165 /* Copy the param bytes into the packet */
167 if(params_sent_thistime)
168 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
170 /* Copy in the data bytes */
171 if(data_sent_thistime)
172 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
173 data_alignment_offset,pd,data_sent_thistime);
175 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
176 params_sent_thistime, data_sent_thistime, useable_space));
177 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
178 params_to_send, data_to_send, paramsize, datasize));
180 /* Send the packet */
181 if (!send_smb(smbd_server_fd(),outbuf))
182 exit_server("send_trans2_replies: send_smb failed.");
184 pp += params_sent_thistime;
185 pd += data_sent_thistime;
187 params_to_send -= params_sent_thistime;
188 data_to_send -= data_sent_thistime;
191 if(params_to_send < 0 || data_to_send < 0) {
192 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
193 params_to_send, data_to_send));
201 /****************************************************************************
202 Reply to a TRANSACT2_OPEN.
203 ****************************************************************************/
205 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
206 char **pparams, int total_params, char **ppdata, int total_data)
208 char *params = *pparams;
213 BOOL return_additional_info;
223 int fmode=0,mtime=0,rmode;
225 SMB_STRUCT_STAT sbuf;
227 BOOL bad_path = False;
231 * Ensure we have enough parameters to perform the operation.
234 if (total_params < 29)
235 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
237 open_mode = SVAL(params, 2);
238 open_attr = SVAL(params,6);
239 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
241 return_additional_info = BITSETW(params,0);
242 open_sattr = SVAL(params, 4);
243 open_time = make_unix_date3(params+8);
245 open_ofun = SVAL(params,12);
246 open_size = IVAL(params,14);
249 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
251 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
252 fname,open_mode, open_attr, open_ofun, open_size));
255 return(ERROR_DOS(ERRSRV,ERRaccess));
257 /* XXXX we need to handle passed times, sattr and flags */
259 unix_convert(fname,conn,0,&bad_path,&sbuf);
261 if (!check_name(fname,conn)) {
262 set_bad_path_error(errno, bad_path);
263 return(UNIXERROR(ERRDOS,ERRnoaccess));
266 unixmode = unix_mode(conn,open_attr | aARCH, fname);
268 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
269 oplock_request, &rmode,&smb_action);
272 set_bad_path_error(errno, bad_path);
273 return(UNIXERROR(ERRDOS,ERRnoaccess));
276 size = get_file_size(sbuf);
277 fmode = dos_mode(conn,fname,&sbuf);
278 mtime = sbuf.st_mtime;
281 close_file(fsp,False);
282 return(ERROR_DOS(ERRDOS,ERRnoaccess));
285 /* Realloc the size of parameters and data we will return */
286 params = Realloc(*pparams, 28);
288 return(ERROR_DOS(ERRDOS,ERRnomem));
291 memset((char *)params,'\0',28);
292 SSVAL(params,0,fsp->fnum);
293 SSVAL(params,2,fmode);
294 put_dos_date2(params,4, mtime);
295 SIVAL(params,8, (uint32)size);
296 SSVAL(params,12,rmode);
298 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
299 smb_action |= EXTENDED_OPLOCK_GRANTED;
301 SSVAL(params,18,smb_action);
304 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
306 SIVAL(params,20,inode);
308 /* Send the required number of replies */
309 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
314 /*********************************************************
315 Routine to check if a given string matches exactly.
316 as a special case a mask of "." does NOT match. That
317 is required for correct wildcard semantics
318 Case can be significant or not.
319 **********************************************************/
321 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
323 if (mask[0] == '.' && mask[1] == 0)
326 return strcmp(str,mask)==0;
327 return strcasecmp(str,mask) == 0;
330 /****************************************************************************
331 Return the filetype for UNIX extensions.
332 ****************************************************************************/
334 static uint32 unix_filetype(mode_t mode)
337 return UNIX_TYPE_FILE;
338 else if(S_ISDIR(mode))
339 return UNIX_TYPE_DIR;
341 else if(S_ISLNK(mode))
342 return UNIX_TYPE_SYMLINK;
345 else if(S_ISCHR(mode))
346 return UNIX_TYPE_CHARDEV;
349 else if(S_ISBLK(mode))
350 return UNIX_TYPE_BLKDEV;
353 else if(S_ISFIFO(mode))
354 return UNIX_TYPE_FIFO;
357 else if(S_ISSOCK(mode))
358 return UNIX_TYPE_SOCKET;
361 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
362 return UNIX_TYPE_UNKNOWN;
365 /****************************************************************************
366 Return the major devicenumber for UNIX extensions.
367 ****************************************************************************/
369 static uint32 unix_dev_major(SMB_DEV_T dev)
371 #if defined(HAVE_DEVICE_MAJOR_FN)
372 return (uint32)major(dev);
374 return (uint32)(dev >> 8);
378 /****************************************************************************
379 Return the minor devicenumber for UNIX extensions.
380 ****************************************************************************/
382 static uint32 unix_dev_minor(SMB_DEV_T dev)
384 #if defined(HAVE_DEVICE_MINOR_FN)
385 return (uint32)minor(dev);
387 return (uint32)(dev & 0xff);
391 /****************************************************************************
392 Map wire perms onto standard UNIX permissions. Obey share restrictions.
393 ****************************************************************************/
395 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
399 if (perms == SMB_MODE_NO_CHANGE)
402 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
403 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
404 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
405 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
406 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
407 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
408 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
409 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
410 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
412 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
415 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
418 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
421 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
422 ret &= lp_dir_mask(SNUM(conn));
423 /* Add in force bits */
424 ret |= lp_force_dir_mode(SNUM(conn));
426 /* Apply mode mask */
427 ret &= lp_create_mask(SNUM(conn));
428 /* Add in force bits */
429 ret |= lp_force_create_mode(SNUM(conn));
435 /****************************************************************************
436 checks for SMB_TIME_NO_CHANGE and if not found
437 calls interpret_long_date
438 ****************************************************************************/
439 time_t interpret_long_unix_date(char *p)
441 DEBUG(1,("interpret_long_unix_date\n"));
442 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
443 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
446 return interpret_long_date(p);
450 /****************************************************************************
451 Get a level dependent lanman2 dir entry.
452 ****************************************************************************/
454 static BOOL get_lanman2_dir_entry(connection_struct *conn,
455 void *inbuf, void *outbuf,
456 char *path_mask,int dirtype,int info_level,
457 int requires_resume_key,
458 BOOL dont_descend,char **ppdata,
459 char *base_data, int space_remaining,
460 BOOL *out_of_space, BOOL *got_exact_match,
465 SMB_STRUCT_STAT sbuf;
469 char *p, *q, *pdata = *ppdata;
473 SMB_OFF_T file_size = 0;
474 SMB_BIG_UINT allocation_size = 0;
476 time_t mdate=0, adate=0, cdate=0;
479 int nt_extmode; /* Used for NT connections instead of mode */
480 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
483 *out_of_space = False;
484 *got_exact_match = False;
489 p = strrchr_m(path_mask,'/');
496 pstrcpy(mask, path_mask);
501 /* Needed if we run out of space */
502 prev_dirpos = TellDir(conn->dirptr);
503 dname = ReadDirName(conn->dirptr);
506 * Due to bugs in NT client redirectors we are not using
507 * resume keys any more - set them to zero.
508 * Check out the related comments in findfirst/findnext.
514 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
515 (long)conn->dirptr,TellDir(conn->dirptr)));
520 pstrcpy(fname,dname);
522 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
523 got_match = mask_match(fname, mask, case_sensitive);
525 if(!got_match && !mangle_is_8_3(fname, False)) {
528 * It turns out that NT matches wildcards against
529 * both long *and* short names. This may explain some
530 * of the wildcard wierdness from old DOS clients
531 * that some people have been seeing.... JRA.
535 pstrcpy( newname, fname);
536 mangle_map( newname, True, False, SNUM(conn));
537 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
538 got_match = mask_match(newname, mask, case_sensitive);
542 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
543 if (dont_descend && !isdots)
546 pstrcpy(pathreal,conn->dirpath);
548 pstrcat(pathreal,"/");
549 pstrcat(pathreal,dname);
551 if (INFO_LEVEL_IS_UNIX(info_level)) {
552 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
553 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
554 pathreal,strerror(errno)));
557 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
559 /* Needed to show the msdfs symlinks as
562 if(lp_host_msdfs() &&
563 lp_msdfs_root(SNUM(conn)) &&
564 is_msdfs_link(conn, pathreal, NULL, NULL,
567 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
568 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
572 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
573 pathreal,strerror(errno)));
578 mode = dos_mode(conn,pathreal,&sbuf);
580 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
581 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
585 file_size = get_file_size(sbuf);
586 allocation_size = get_allocation_size(NULL,&sbuf);
587 mdate = sbuf.st_mtime;
588 adate = sbuf.st_atime;
589 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
591 if (lp_dos_filetime_resolution(SNUM(conn))) {
600 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
606 mangle_map(fname,False,True,SNUM(conn));
611 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
613 switch (info_level) {
614 case SMB_INFO_STANDARD:
615 if(requires_resume_key) {
619 put_dos_date2(p,l1_fdateCreation,cdate);
620 put_dos_date2(p,l1_fdateLastAccess,adate);
621 put_dos_date2(p,l1_fdateLastWrite,mdate);
622 SIVAL(p,l1_cbFile,(uint32)file_size);
623 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
624 SSVAL(p,l1_attrFile,mode);
627 p += align_string(outbuf, p, 0);
628 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
629 SCVAL(nameptr, -1, len);
633 case SMB_INFO_QUERY_EA_SIZE:
634 if(requires_resume_key) {
638 put_dos_date2(p,l2_fdateCreation,cdate);
639 put_dos_date2(p,l2_fdateLastAccess,adate);
640 put_dos_date2(p,l2_fdateLastWrite,mdate);
641 SIVAL(p,l2_cbFile,(uint32)file_size);
642 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
643 SSVAL(p,l2_attrFile,mode);
644 SIVAL(p,l2_cbList,0); /* No extended attributes */
647 len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
650 *p++ = 0; /* craig from unisys pointed out we need this */
653 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
654 was_8_3 = mangle_is_8_3(fname, True);
656 SIVAL(p,0,reskey); p += 4;
657 put_long_date(p,cdate); p += 8;
658 put_long_date(p,adate); p += 8;
659 put_long_date(p,mdate); p += 8;
660 put_long_date(p,mdate); p += 8;
661 SOFF_T(p,0,file_size);
662 SOFF_T(p,8,allocation_size);
664 SIVAL(p,0,nt_extmode); p += 4;
666 SIVAL(p,0,0); p += 4;
667 /* Clear the short name buffer. This is
668 * IMPORTANT as not doing so will trigger
669 * a Win2k client bug. JRA.
673 pstring mangled_name;
674 pstrcpy(mangled_name, fname);
675 mangle_map(mangled_name,True,True,SNUM(conn));
676 mangled_name[12] = 0;
677 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
684 len = srvstr_push(outbuf, p, fname, -1, 0);
687 len = PTR_DIFF(p, pdata);
688 len = (len + 3) & ~3;
693 case SMB_FIND_FILE_DIRECTORY_INFO:
695 SIVAL(p,0,reskey); p += 4;
696 put_long_date(p,cdate); p += 8;
697 put_long_date(p,adate); p += 8;
698 put_long_date(p,mdate); p += 8;
699 put_long_date(p,mdate); p += 8;
700 SOFF_T(p,0,file_size);
701 SOFF_T(p,8,allocation_size);
703 SIVAL(p,0,nt_extmode); p += 4;
705 len = srvstr_push(outbuf, p, fname, -1, 0);
708 len = PTR_DIFF(p, pdata);
709 len = (len + 3) & ~3;
714 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
716 SIVAL(p,0,reskey); p += 4;
717 put_long_date(p,cdate); p += 8;
718 put_long_date(p,adate); p += 8;
719 put_long_date(p,mdate); p += 8;
720 put_long_date(p,mdate); p += 8;
721 SOFF_T(p,0,file_size);
722 SOFF_T(p,8,allocation_size);
724 SIVAL(p,0,nt_extmode); p += 4;
726 SIVAL(p,0,0); p += 4;
728 len = srvstr_push(outbuf, p, fname, -1, 0);
732 len = PTR_DIFF(p, pdata);
733 len = (len + 3) & ~3;
738 case SMB_FIND_FILE_NAMES_INFO:
740 SIVAL(p,0,reskey); p += 4;
742 /* this must *not* be null terminated or w2k gets in a loop trying to set an
743 acl on a dir (tridge) */
744 len = srvstr_push(outbuf, p, fname, -1, 0);
747 len = PTR_DIFF(p, pdata);
748 len = (len + 3) & ~3;
753 /* CIFS UNIX Extension. */
755 case SMB_FIND_FILE_UNIX:
757 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
759 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
760 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
763 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
766 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
767 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
768 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
771 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
775 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
779 SIVAL(p,0,unix_filetype(sbuf.st_mode));
782 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
786 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
790 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
793 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
797 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
801 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
804 len = PTR_DIFF(p, pdata);
805 len = (len + 3) & ~3;
806 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
808 /* End of SMB_QUERY_FILE_UNIX_BASIC */
817 if (PTR_DIFF(p,pdata) > space_remaining) {
818 /* Move the dirptr back to prev_dirpos */
819 SeekDir(conn->dirptr, prev_dirpos);
820 *out_of_space = True;
821 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
822 return False; /* Not finished - just out of space */
825 /* Setup the last_filename pointer, as an offset from base_data */
826 *last_name_off = PTR_DIFF(nameptr,base_data);
827 /* Advance the data pointer to the next slot */
833 /****************************************************************************
834 Reply to a TRANS2_FINDFIRST.
835 ****************************************************************************/
837 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
838 char **pparams, int total_params, char **ppdata, int total_data)
840 /* We must be careful here that we don't return more than the
841 allowed number of data bytes. If this means returning fewer than
842 maxentries then so be it. We assume that the redirector has
843 enough room for the fixed number of parameter bytes it has
845 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
846 char *params = *pparams;
847 char *pdata = *ppdata;
848 int dirtype = SVAL(params,0);
849 int maxentries = SVAL(params,2);
850 BOOL close_after_first = BITSETW(params+4,0);
851 BOOL close_if_end = BITSETW(params+4,1);
852 BOOL requires_resume_key = BITSETW(params+4,2);
853 int info_level = SVAL(params,6);
861 BOOL finished = False;
862 BOOL dont_descend = False;
863 BOOL out_of_space = False;
865 BOOL bad_path = False;
866 SMB_STRUCT_STAT sbuf;
868 if (total_params < 12)
869 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
871 *directory = *mask = 0;
873 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
874 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
875 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
876 info_level, max_data_bytes));
878 switch (info_level) {
879 case SMB_INFO_STANDARD:
880 case SMB_INFO_QUERY_EA_SIZE:
881 case SMB_FIND_FILE_DIRECTORY_INFO:
882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
883 case SMB_FIND_FILE_NAMES_INFO:
884 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
886 case SMB_FIND_FILE_UNIX:
887 if (!lp_unix_extensions())
888 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
891 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
894 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
896 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
898 unix_convert(directory,conn,0,&bad_path,&sbuf);
899 if(!check_name(directory,conn)) {
900 set_bad_path_error(errno, bad_path);
901 return(UNIXERROR(ERRDOS,ERRbadpath));
904 p = strrchr_m(directory,'/');
906 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
907 if((directory[0] == '.') && (directory[1] == '\0'))
910 pstrcpy(mask,directory);
911 pstrcpy(directory,"./");
917 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
919 pdata = Realloc(*ppdata, max_data_bytes + 1024);
921 return(ERROR_DOS(ERRDOS,ERRnomem));
924 memset((char *)pdata,'\0',max_data_bytes + 1024);
926 /* Realloc the params space */
927 params = Realloc(*pparams, 10);
929 return ERROR_DOS(ERRDOS,ERRnomem);
932 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
934 return(UNIXERROR(ERRDOS,ERRbadfile));
936 /* Save the wildcard match and attribs we are using on this directory -
937 needed as lanman2 assumes these are being saved between calls */
939 if(!(wcard = strdup(mask))) {
940 dptr_close(&dptr_num);
941 return ERROR_DOS(ERRDOS,ERRnomem);
944 dptr_set_wcard(dptr_num, wcard);
945 dptr_set_attr(dptr_num, dirtype);
947 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
949 /* We don't need to check for VOL here as this is returned by
950 a different TRANS2 call. */
952 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
953 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
957 space_remaining = max_data_bytes;
958 out_of_space = False;
960 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
961 BOOL got_exact_match = False;
963 /* this is a heuristic to avoid seeking the dirptr except when
964 absolutely necessary. It allows for a filename of about 40 chars */
965 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
969 finished = !get_lanman2_dir_entry(conn,
971 mask,dirtype,info_level,
972 requires_resume_key,dont_descend,
973 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
977 if (finished && out_of_space)
980 if (!finished && !out_of_space)
984 * As an optimisation if we know we aren't looking
985 * for a wildcard name (ie. the name matches the wildcard exactly)
986 * then we can finish on any (first) match.
987 * This speeds up large directory searches. JRA.
993 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
996 /* Check if we can close the dirptr */
997 if(close_after_first || (finished && close_if_end)) {
998 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
999 dptr_close(&dptr_num);
1003 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1004 * from observation of NT.
1007 if(numentries == 0) {
1008 dptr_close(&dptr_num);
1009 return ERROR_DOS(ERRDOS,ERRbadfile);
1012 /* At this point pdata points to numentries directory entries. */
1014 /* Set up the return parameter block */
1015 SSVAL(params,0,dptr_num);
1016 SSVAL(params,2,numentries);
1017 SSVAL(params,4,finished);
1018 SSVAL(params,6,0); /* Never an EA error */
1019 SSVAL(params,8,last_name_off);
1021 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1023 if ((! *directory) && dptr_path(dptr_num))
1024 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1026 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1027 smb_fn_name(CVAL(inbuf,smb_com)),
1028 mask, directory, dirtype, numentries ) );
1031 * Force a name mangle here to ensure that the
1032 * mask as an 8.3 name is top of the mangled cache.
1033 * The reasons for this are subtle. Don't remove
1034 * this code unless you know what you are doing
1035 * (see PR#13758). JRA.
1038 if(!mangle_is_8_3_wildcards( mask, False))
1039 mangle_map(mask, True, True, SNUM(conn));
1044 /****************************************************************************
1045 Reply to a TRANS2_FINDNEXT.
1046 ****************************************************************************/
1048 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1049 char **pparams, int total_params, char **ppdata, int total_data)
1051 /* We must be careful here that we don't return more than the
1052 allowed number of data bytes. If this means returning fewer than
1053 maxentries then so be it. We assume that the redirector has
1054 enough room for the fixed number of parameter bytes it has
1056 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1057 char *params = *pparams;
1058 char *pdata = *ppdata;
1059 int dptr_num = SVAL(params,0);
1060 int maxentries = SVAL(params,2);
1061 uint16 info_level = SVAL(params,4);
1062 uint32 resume_key = IVAL(params,6);
1063 BOOL close_after_request = BITSETW(params+10,0);
1064 BOOL close_if_end = BITSETW(params+10,1);
1065 BOOL requires_resume_key = BITSETW(params+10,2);
1066 BOOL continue_bit = BITSETW(params+10,3);
1067 pstring resume_name;
1073 int i, last_name_off=0;
1074 BOOL finished = False;
1075 BOOL dont_descend = False;
1076 BOOL out_of_space = False;
1077 int space_remaining;
1079 if (total_params < 12)
1080 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1082 *mask = *directory = *resume_name = 0;
1084 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1086 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1087 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1088 resume_key = %d resume name = %s continue=%d level = %d\n",
1089 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1090 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1092 switch (info_level) {
1093 case SMB_INFO_STANDARD:
1094 case SMB_INFO_QUERY_EA_SIZE:
1095 case SMB_FIND_FILE_DIRECTORY_INFO:
1096 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1097 case SMB_FIND_FILE_NAMES_INFO:
1098 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1100 case SMB_FIND_FILE_UNIX:
1101 if (!lp_unix_extensions())
1102 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1105 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1108 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1110 return ERROR_DOS(ERRDOS,ERRnomem);
1113 memset((char *)pdata,'\0',max_data_bytes + 1024);
1115 /* Realloc the params space */
1116 params = Realloc(*pparams, 6*SIZEOFWORD);
1117 if( params == NULL )
1118 return ERROR_DOS(ERRDOS,ERRnomem);
1122 /* Check that the dptr is valid */
1123 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1124 return ERROR_DOS(ERRDOS,ERRnofiles);
1126 string_set(&conn->dirpath,dptr_path(dptr_num));
1128 /* Get the wildcard mask from the dptr */
1129 if((p = dptr_wcard(dptr_num))== NULL) {
1130 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1131 return ERROR_DOS(ERRDOS,ERRnofiles);
1135 pstrcpy(directory,conn->dirpath);
1137 /* Get the attr mask from the dptr */
1138 dirtype = dptr_attr(dptr_num);
1140 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1141 dptr_num, mask, dirtype,
1143 TellDir(conn->dirptr)));
1145 /* We don't need to check for VOL here as this is returned by
1146 a different TRANS2 call. */
1148 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1149 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1150 dont_descend = True;
1153 space_remaining = max_data_bytes;
1154 out_of_space = False;
1157 * Seek to the correct position. We no longer use the resume key but
1158 * depend on the last file name instead.
1161 if(requires_resume_key && *resume_name && !continue_bit) {
1164 * Fix for NT redirector problem triggered by resume key indexes
1165 * changing between directory scans. We now return a resume key of 0
1166 * and instead look for the filename to continue from (also given
1167 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1168 * findfirst/findnext (as is usual) then the directory pointer
1169 * should already be at the correct place. Check this by scanning
1170 * backwards looking for an exact (ie. case sensitive) filename match.
1171 * If we get to the beginning of the directory and haven't found it then scan
1172 * forwards again looking for a match. JRA.
1175 int current_pos, start_pos;
1176 const char *dname = NULL;
1177 pstring dname_pstring;
1178 void *dirptr = conn->dirptr;
1179 start_pos = TellDir(dirptr);
1180 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1181 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1183 SeekDir(dirptr, current_pos);
1184 dname = ReadDirName(dirptr);
1187 * Remember, mangle_map is called by
1188 * get_lanman2_dir_entry(), so the resume name
1189 * could be mangled. Ensure we do the same
1193 /* make sure we get a copy that mangle_map can modify */
1195 pstrcpy(dname_pstring, dname);
1196 mangle_map( dname_pstring, False, True, SNUM(conn));
1198 if(strcsequal( resume_name, dname_pstring)) {
1199 SeekDir(dirptr, current_pos+1);
1200 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1207 * Scan forward from start if not found going backwards.
1210 if(current_pos < 0) {
1211 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1212 SeekDir(dirptr, start_pos);
1213 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1216 * Remember, mangle_map is called by
1217 * get_lanman2_dir_entry(), so the resume name
1218 * could be mangled. Ensure we do the same
1223 /* make sure we get a copy that mangle_map can modify */
1225 pstrcpy(dname_pstring, dname);
1226 mangle_map(dname_pstring, False, True, SNUM(conn));
1228 if(strcsequal( resume_name, dname_pstring)) {
1229 SeekDir(dirptr, current_pos+1);
1230 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1235 } /* end if current_pos */
1236 } /* end if requires_resume_key && !continue_bit */
1238 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1239 BOOL got_exact_match = False;
1241 /* this is a heuristic to avoid seeking the dirptr except when
1242 absolutely necessary. It allows for a filename of about 40 chars */
1243 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1244 out_of_space = True;
1247 finished = !get_lanman2_dir_entry(conn,
1249 mask,dirtype,info_level,
1250 requires_resume_key,dont_descend,
1251 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1255 if (finished && out_of_space)
1258 if (!finished && !out_of_space)
1262 * As an optimisation if we know we aren't looking
1263 * for a wildcard name (ie. the name matches the wildcard exactly)
1264 * then we can finish on any (first) match.
1265 * This speeds up large directory searches. JRA.
1271 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1274 /* Check if we can close the dirptr */
1275 if(close_after_request || (finished && close_if_end)) {
1276 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1277 dptr_close(&dptr_num); /* This frees up the saved mask */
1280 /* Set up the return parameter block */
1281 SSVAL(params,0,numentries);
1282 SSVAL(params,2,finished);
1283 SSVAL(params,4,0); /* Never an EA error */
1284 SSVAL(params,6,last_name_off);
1286 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1288 if ((! *directory) && dptr_path(dptr_num))
1289 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1291 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1292 smb_fn_name(CVAL(inbuf,smb_com)),
1293 mask, directory, dirtype, numentries ) );
1298 /****************************************************************************
1299 Reply to a TRANS2_QFSINFO (query filesystem info).
1300 ****************************************************************************/
1302 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1303 int length, int bufsize,
1304 char **pparams, int total_params, char **ppdata, int total_data)
1306 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1307 char *pdata = *ppdata;
1308 char *params = *pparams;
1309 uint16 info_level = SVAL(params,0);
1312 char *vname = volume_label(SNUM(conn));
1313 int snum = SNUM(conn);
1314 char *fstype = lp_fstype(SNUM(conn));
1316 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1318 if(vfs_stat(conn,".",&st)!=0) {
1319 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1320 return ERROR_DOS(ERRSRV,ERRinvdevice);
1323 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1324 if ( pdata == NULL )
1325 return ERROR_DOS(ERRDOS,ERRnomem);
1328 memset((char *)pdata,'\0',max_data_bytes + 1024);
1330 switch (info_level) {
1331 case SMB_INFO_ALLOCATION:
1333 SMB_BIG_UINT dfree,dsize,bsize;
1335 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1336 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1337 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1338 SIVAL(pdata,l1_cUnit,dsize);
1339 SIVAL(pdata,l1_cUnitAvail,dfree);
1340 SSVAL(pdata,l1_cbSector,512);
1341 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1342 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1343 (unsigned int)dfree, 512));
1347 case SMB_INFO_VOLUME:
1348 /* Return volume name */
1350 * Add volume serial number - hash of a combination of
1351 * the called hostname and the service name.
1353 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1354 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1355 SCVAL(pdata,l2_vol_cch,len);
1356 data_len = l2_vol_szVolLabel + len;
1357 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1358 (unsigned)st.st_ctime, len, vname));
1361 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1362 case SMB_FS_ATTRIBUTE_INFORMATION:
1364 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1365 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1366 SIVAL(pdata,4,255); /* Max filename component length */
1367 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1368 and will think we can't do long filenames */
1369 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1371 data_len = 12 + len;
1374 case SMB_QUERY_FS_LABEL_INFO:
1375 case SMB_FS_LABEL_INFORMATION:
1376 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1381 case SMB_QUERY_FS_VOLUME_INFO:
1382 case SMB_FS_VOLUME_INFORMATION:
1385 * Add volume serial number - hash of a combination of
1386 * the called hostname and the service name.
1388 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1389 (str_checksum(local_machine)<<16));
1391 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1392 SIVAL(pdata,12,len);
1394 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1395 (int)strlen(vname),vname, lp_servicename(snum)));
1398 case SMB_QUERY_FS_SIZE_INFO:
1399 case SMB_FS_SIZE_INFORMATION:
1401 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1403 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1404 block_size = lp_block_size(snum);
1405 if (bsize < block_size) {
1406 SMB_BIG_UINT factor = block_size/bsize;
1411 if (bsize > block_size) {
1412 SMB_BIG_UINT factor = bsize/block_size;
1417 bytes_per_sector = 512;
1418 sectors_per_unit = bsize/bytes_per_sector;
1419 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1420 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1421 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1422 SBIG_UINT(pdata,0,dsize);
1423 SBIG_UINT(pdata,8,dfree);
1424 SIVAL(pdata,16,sectors_per_unit);
1425 SIVAL(pdata,20,bytes_per_sector);
1429 case SMB_FS_FULL_SIZE_INFORMATION:
1431 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1433 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1434 block_size = lp_block_size(snum);
1435 if (bsize < block_size) {
1436 SMB_BIG_UINT factor = block_size/bsize;
1441 if (bsize > block_size) {
1442 SMB_BIG_UINT factor = bsize/block_size;
1447 bytes_per_sector = 512;
1448 sectors_per_unit = bsize/bytes_per_sector;
1449 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1450 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1451 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1452 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1453 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1454 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1455 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1456 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1460 case SMB_QUERY_FS_DEVICE_INFO:
1461 case SMB_FS_DEVICE_INFORMATION:
1463 SIVAL(pdata,0,0); /* dev type */
1464 SIVAL(pdata,4,0); /* characteristics */
1467 case SMB_FS_OBJECTID_INFORMATION:
1472 * Query the version and capabilities of the CIFS UNIX extensions
1476 case SMB_QUERY_CIFS_UNIX_INFO:
1477 if (!lp_unix_extensions())
1478 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1480 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1481 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1482 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1485 case SMB_MAC_QUERY_FS_INFO:
1487 * Thursby MAC extension... ONLY on NTFS filesystems
1488 * once we do streams then we don't need this
1490 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1492 SIVAL(pdata,84,0x100); /* Don't support mac... */
1497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1501 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1503 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1508 /****************************************************************************
1509 Reply to a TRANS2_SETFSINFO (set filesystem info).
1510 ****************************************************************************/
1512 static int call_trans2setfsinfo(connection_struct *conn,
1513 char *inbuf, char *outbuf, int length, int bufsize,
1514 char **pparams, int total_params, char **ppdata, int total_data)
1516 /* Just say yes we did it - there is nothing that
1517 can be set here so it doesn't matter. */
1519 DEBUG(3,("call_trans2setfsinfo\n"));
1521 if (!CAN_WRITE(conn))
1522 return ERROR_DOS(ERRSRV,ERRaccess);
1524 outsize = set_message(outbuf,10,0,True);
1529 /****************************************************************************
1530 * Utility function to set bad path error.
1531 ****************************************************************************/
1533 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1535 if((err == ENOENT) && bad_path) {
1536 unix_ERR_class = ERRDOS;
1537 unix_ERR_code = ERRbadpath;
1538 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1540 return NT_STATUS_OK;
1543 /****************************************************************************
1544 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1545 file name or file id).
1546 ****************************************************************************/
1548 static int call_trans2qfilepathinfo(connection_struct *conn,
1549 char *inbuf, char *outbuf, int length,
1551 char **pparams, int total_params, char **ppdata, int total_data)
1553 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1554 char *params = *pparams;
1555 char *pdata = *ppdata;
1556 uint16 tran_call = SVAL(inbuf, smb_setup0);
1559 SMB_OFF_T file_size=0;
1560 SMB_BIG_UINT allocation_size=0;
1561 unsigned int data_size;
1562 SMB_STRUCT_STAT sbuf;
1563 pstring fname, dos_fname;
1568 BOOL bad_path = False;
1569 BOOL delete_pending = False;
1572 files_struct *fsp = NULL;
1575 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1577 if (tran_call == TRANSACT2_QFILEINFO) {
1578 if (total_params < 4)
1579 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1581 fsp = file_fsp(params,0);
1582 info_level = SVAL(params,2);
1584 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1586 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1588 * This is actually a QFILEINFO on a directory
1589 * handle (returned from an NT SMB). NT5.0 seems
1590 * to do this call. JRA.
1592 pstrcpy(fname, fsp->fsp_name);
1593 unix_convert(fname,conn,0,&bad_path,&sbuf);
1594 if (!check_name(fname,conn)) {
1595 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1596 set_bad_path_error(errno, bad_path);
1597 return(UNIXERROR(ERRDOS,ERRbadpath));
1600 if (INFO_LEVEL_IS_UNIX(info_level)) {
1601 /* Always do lstat for UNIX calls. */
1602 if (vfs_lstat(conn,fname,&sbuf)) {
1603 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1604 set_bad_path_error(errno, bad_path);
1605 return(UNIXERROR(ERRDOS,ERRbadpath));
1607 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1608 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1609 set_bad_path_error(errno, bad_path);
1610 return(UNIXERROR(ERRDOS,ERRbadpath));
1613 delete_pending = fsp->directory_delete_on_close;
1616 * Original code - this is an open file.
1618 CHECK_FSP(fsp,conn);
1620 pstrcpy(fname, fsp->fsp_name);
1621 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1622 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1623 return(UNIXERROR(ERRDOS,ERRbadfid));
1625 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1626 return(UNIXERROR(ERRDOS,ERRnoaccess));
1628 delete_pending = fsp->delete_on_close;
1632 if (total_params < 6)
1633 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1635 info_level = SVAL(params,0);
1637 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1639 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
1641 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1643 unix_convert(fname,conn,0,&bad_path,&sbuf);
1644 if (!check_name(fname,conn)) {
1645 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1646 set_bad_path_error(errno, bad_path);
1647 return(UNIXERROR(ERRDOS,ERRbadpath));
1650 if (INFO_LEVEL_IS_UNIX(info_level)) {
1651 /* Always do lstat for UNIX calls. */
1652 if (vfs_lstat(conn,fname,&sbuf)) {
1653 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1654 set_bad_path_error(errno, bad_path);
1655 return(UNIXERROR(ERRDOS,ERRbadpath));
1657 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1658 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1659 set_bad_path_error(errno, bad_path);
1660 return(UNIXERROR(ERRDOS,ERRbadpath));
1664 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1665 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1667 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1668 fname,info_level,tran_call,total_data));
1670 p = strrchr_m(fname,'/');
1676 mode = dos_mode(conn,fname,&sbuf);
1677 fullpathname = fname;
1678 file_size = get_file_size(sbuf);
1679 allocation_size = get_allocation_size(fsp,&sbuf);
1683 params = Realloc(*pparams,2);
1685 return ERROR_DOS(ERRDOS,ERRnomem);
1687 memset((char *)params,'\0',2);
1688 data_size = max_data_bytes + 1024;
1689 pdata = Realloc(*ppdata, data_size);
1690 if ( pdata == NULL )
1691 return ERROR_DOS(ERRDOS,ERRnomem);
1694 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1695 /* uggh, EAs for OS2 */
1696 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1697 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1700 memset((char *)pdata,'\0',data_size);
1702 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1704 if (lp_dos_filetime_resolution(SNUM(conn))) {
1706 sbuf.st_atime &= ~1;
1707 sbuf.st_mtime &= ~1;
1708 sbuf.st_mtime &= ~1;
1711 /* NT expects the name to be in an exact form of the *full*
1712 filename. See the trans2 torture test */
1713 if (strequal(base_name,".")) {
1714 pstrcpy(dos_fname, "\\");
1716 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1717 string_replace(dos_fname, '/', '\\');
1720 switch (info_level) {
1721 case SMB_INFO_STANDARD:
1722 case SMB_INFO_QUERY_EA_SIZE:
1723 data_size = (info_level==1?22:26);
1724 put_dos_date2(pdata,l1_fdateCreation,c_time);
1725 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1726 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1727 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1728 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1729 SSVAL(pdata,l1_attrFile,mode);
1730 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1733 case SMB_INFO_QUERY_EAS_FROM_LIST:
1735 put_dos_date2(pdata,0,c_time);
1736 put_dos_date2(pdata,4,sbuf.st_atime);
1737 put_dos_date2(pdata,8,sbuf.st_mtime);
1738 SIVAL(pdata,12,(uint32)file_size);
1739 SIVAL(pdata,16,(uint32)allocation_size);
1740 SIVAL(pdata,20,mode);
1743 case SMB_INFO_QUERY_ALL_EAS:
1745 SIVAL(pdata,0,data_size);
1749 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1751 case SMB_FILE_BASIC_INFORMATION:
1752 case SMB_QUERY_FILE_BASIC_INFO:
1754 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1755 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1760 put_long_date(pdata,c_time);
1761 put_long_date(pdata+8,sbuf.st_atime);
1762 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1763 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1764 SIVAL(pdata,32,mode);
1766 DEBUG(5,("SMB_QFBI - "));
1768 time_t create_time = c_time;
1769 DEBUG(5,("create: %s ", ctime(&create_time)));
1771 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1772 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1773 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1774 DEBUG(5,("mode: %x\n", mode));
1778 case SMB_FILE_STANDARD_INFORMATION:
1779 case SMB_QUERY_FILE_STANDARD_INFO:
1782 SOFF_T(pdata,0,allocation_size);
1783 SOFF_T(pdata,8,file_size);
1784 SIVAL(pdata,16,sbuf.st_nlink);
1786 SCVAL(pdata,21,(mode&aDIR)?1:0);
1789 case SMB_FILE_EA_INFORMATION:
1790 case SMB_QUERY_FILE_EA_INFO:
1794 /* Get the 8.3 name - used if NT SMB was negotiated. */
1795 case SMB_QUERY_FILE_ALT_NAME_INFO:
1799 pstrcpy(short_name,base_name);
1800 /* Mangle if not already 8.3 */
1801 if(!mangle_is_8_3(short_name, True)) {
1802 mangle_map(short_name,True,True,SNUM(conn));
1804 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
1805 data_size = 4 + len;
1810 case SMB_QUERY_FILE_NAME_INFO:
1812 this must be *exactly* right for ACLs on mapped drives to work
1814 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1815 data_size = 4 + len;
1819 case SMB_FILE_ALLOCATION_INFORMATION:
1820 case SMB_QUERY_FILE_ALLOCATION_INFO:
1822 SOFF_T(pdata,0,allocation_size);
1825 case SMB_FILE_END_OF_FILE_INFORMATION:
1826 case SMB_QUERY_FILE_END_OF_FILEINFO:
1828 SOFF_T(pdata,0,file_size);
1831 case SMB_QUERY_FILE_ALL_INFO:
1832 put_long_date(pdata,c_time);
1833 put_long_date(pdata+8,sbuf.st_atime);
1834 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1835 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1836 SIVAL(pdata,32,mode);
1838 SOFF_T(pdata,0,allocation_size);
1839 SOFF_T(pdata,8,file_size);
1840 SIVAL(pdata,16,sbuf.st_nlink);
1841 SCVAL(pdata,20,delete_pending);
1842 SCVAL(pdata,21,(mode&aDIR)?1:0);
1844 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1845 pdata += 8; /* index number */
1846 pdata += 4; /* EA info */
1848 SIVAL(pdata,0,0xA9);
1850 SIVAL(pdata,0,0xd01BF);
1852 SOFF_T(pdata,0,pos); /* current offset */
1854 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1856 pdata += 4; /* alignment */
1857 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1860 data_size = PTR_DIFF(pdata,(*ppdata));
1863 case SMB_FILE_INTERNAL_INFORMATION:
1864 /* This should be an index number - looks like
1867 I think this causes us to fail the IFSKIT
1868 BasicFileInformationTest. -tpot */
1870 SIVAL(pdata,0,sbuf.st_dev);
1871 SIVAL(pdata,4,sbuf.st_ino);
1875 case SMB_FILE_ACCESS_INFORMATION:
1876 SIVAL(pdata,0,0x12019F); /* ??? */
1880 case SMB_FILE_NAME_INFORMATION:
1881 /* Pathname with leading '\'. */
1884 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1885 SIVAL(pdata,0,byte_len);
1886 data_size = 4 + byte_len;
1890 case SMB_FILE_DISPOSITION_INFORMATION:
1892 SCVAL(pdata,0,delete_pending);
1895 case SMB_FILE_POSITION_INFORMATION:
1897 SOFF_T(pdata,0,pos);
1900 case SMB_FILE_MODE_INFORMATION:
1901 SIVAL(pdata,0,mode);
1905 case SMB_FILE_ALIGNMENT_INFORMATION:
1906 SIVAL(pdata,0,0); /* No alignment needed. */
1911 /* Not yet finished... JRA */
1914 put_long_date(pdata,c_time);
1915 put_long_date(pdata+8,sbuf.st_atime);
1916 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1917 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1918 SIVAL(pdata,32,mode);
1919 SIVAL(pdata,36,0); /* ??? */
1920 SIVAL(pdata,40,0x20); /* ??? */
1921 SIVAL(pdata,44,0); /* ??? */
1922 SOFF_T(pdata,48,size);
1923 SIVAL(pdata,56,0x1); /* ??? */
1924 SIVAL(pdata,60,0); /* ??? */
1925 SIVAL(pdata,64,0); /* ??? */
1926 SIVAL(pdata,68,length); /* Following string length in bytes. */
1927 dos_PutUniCode(pdata+72,,False);
1932 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1933 /* Last component of pathname. */
1935 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1936 SIVAL(pdata,0,byte_len);
1937 data_size = 4 + byte_len;
1943 * NT4 server just returns "invalid query" to this - if we try to answer
1944 * it then NTws gets a BSOD! (tridge).
1945 * W2K seems to want this. JRA.
1947 case SMB_QUERY_FILE_STREAM_INFO:
1949 case SMB_FILE_STREAM_INFORMATION:
1953 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1954 SIVAL(pdata,0,0); /* ??? */
1955 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1956 SOFF_T(pdata,8,file_size);
1957 SIVAL(pdata,16,allocation_size);
1958 SIVAL(pdata,20,0); /* ??? */
1959 data_size = 24 + byte_len;
1963 case SMB_FILE_COMPRESSION_INFORMATION:
1964 SOFF_T(pdata,0,allocation_size);
1965 SIVAL(pdata,8,0); /* ??? */
1966 SIVAL(pdata,12,0); /* ??? */
1970 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1971 put_long_date(pdata,c_time);
1972 put_long_date(pdata+8,sbuf.st_atime);
1973 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1974 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1975 SIVAL(pdata,32,allocation_size);
1976 SOFF_T(pdata,40,file_size);
1977 SIVAL(pdata,48,mode);
1978 SIVAL(pdata,52,0); /* ??? */
1982 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1983 SIVAL(pdata,0,mode);
1989 * CIFS UNIX Extensions.
1992 case SMB_QUERY_FILE_UNIX_BASIC:
1994 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1996 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
1999 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2002 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2003 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2004 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2007 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2011 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2015 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2018 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2022 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2026 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2029 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2033 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2036 data_size = PTR_DIFF(pdata,(*ppdata));
2040 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2042 for (i=0; i<100; i++)
2043 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2049 case SMB_QUERY_FILE_UNIX_LINK:
2054 if(!S_ISLNK(sbuf.st_mode))
2055 return(UNIXERROR(ERRSRV,ERRbadlink));
2057 return(UNIXERROR(ERRDOS,ERRbadlink));
2059 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2061 return(UNIXERROR(ERRDOS,ERRnoaccess));
2063 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2065 data_size = PTR_DIFF(pdata,(*ppdata));
2071 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2074 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2079 /****************************************************************************
2080 Deal with the internal needs of setting the delete on close flag. Note that
2081 as the tdb locking is recursive, it is safe to call this from within
2082 open_file_shared. JRA.
2083 ****************************************************************************/
2085 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2088 * Only allow delete on close for writable shares.
2091 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2092 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2094 return NT_STATUS_ACCESS_DENIED;
2097 * Only allow delete on close for files/directories opened with delete intent.
2100 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2101 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2103 return NT_STATUS_ACCESS_DENIED;
2106 if(fsp->is_directory) {
2107 fsp->directory_delete_on_close = delete_on_close;
2108 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2109 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2111 fsp->delete_on_close = delete_on_close;
2112 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2113 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2116 return NT_STATUS_OK;
2119 /****************************************************************************
2120 Sets the delete on close flag over all share modes on this file.
2121 Modify the share mode entry for all files open
2122 on this device and inode to tell other smbds we have
2123 changed the delete on close flag. This will be noticed
2124 in the close code, the last closer will delete the file
2126 ****************************************************************************/
2128 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2130 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2131 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2133 if (fsp->is_directory || fsp->is_stat)
2134 return NT_STATUS_OK;
2136 if (lock_share_entry_fsp(fsp) == False)
2137 return NT_STATUS_ACCESS_DENIED;
2139 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2140 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2142 unlock_share_entry_fsp(fsp);
2143 return NT_STATUS_ACCESS_DENIED;
2146 unlock_share_entry_fsp(fsp);
2147 return NT_STATUS_OK;
2150 /****************************************************************************
2151 Returns true if this pathname is within the share, and thus safe.
2152 ****************************************************************************/
2154 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2157 char resolved_name[PATH_MAX+1];
2159 pstring resolved_name;
2161 fstring last_component;
2165 BOOL bad_path = False;
2166 SMB_STRUCT_STAT sbuf;
2168 pstrcpy(link_dest, link_dest_in);
2169 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2171 /* Store the UNIX converted path. */
2172 pstrcpy(link_dest_out, link_dest);
2174 p = strrchr(link_dest, '/');
2176 fstrcpy(last_component, p+1);
2179 fstrcpy(last_component, link_dest);
2180 pstrcpy(link_dest, "./");
2183 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2186 pstrcpy(link_dest, resolved_name);
2187 pstrcat(link_dest, "/");
2188 pstrcat(link_dest, last_component);
2190 if (*link_dest != '/') {
2191 /* Relative path. */
2192 pstrcpy(link_test, conn->connectpath);
2193 pstrcat(link_test, "/");
2194 pstrcat(link_test, link_dest);
2196 pstrcpy(link_test, link_dest);
2200 * Check if the link is within the share.
2203 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2210 /****************************************************************************
2211 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2212 ****************************************************************************/
2214 static int call_trans2setfilepathinfo(connection_struct *conn,
2215 char *inbuf, char *outbuf, int length, int bufsize,
2216 char **pparams, int total_params, char **ppdata, int total_data)
2218 char *params = *pparams;
2219 char *pdata = *ppdata;
2220 uint16 tran_call = SVAL(inbuf, smb_setup0);
2225 SMB_STRUCT_STAT sbuf;
2228 BOOL bad_path = False;
2229 files_struct *fsp = NULL;
2230 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2231 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2232 mode_t unixmode = 0;
2234 if (tran_call == TRANSACT2_SETFILEINFO) {
2235 fsp = file_fsp(params,0);
2236 info_level = SVAL(params,2);
2238 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2240 * This is actually a SETFILEINFO on a directory
2241 * handle (returned from an NT SMB). NT5.0 seems
2242 * to do this call. JRA.
2244 pstrcpy(fname, fsp->fsp_name);
2245 unix_convert(fname,conn,0,&bad_path,&sbuf);
2246 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2247 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2248 set_bad_path_error(errno, bad_path);
2249 return(UNIXERROR(ERRDOS,ERRbadpath));
2251 } else if (fsp && fsp->print_file) {
2253 * Doing a DELETE_ON_CLOSE should cancel a print job.
2255 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2256 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2258 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2261 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2264 return (UNIXERROR(ERRDOS,ERRbadpath));
2267 * Original code - this is an open file.
2269 CHECK_FSP(fsp,conn);
2271 pstrcpy(fname, fsp->fsp_name);
2274 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2275 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2276 return(UNIXERROR(ERRDOS,ERRbadfid));
2281 if (total_params < 6)
2282 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2284 info_level = SVAL(params,0);
2285 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2286 unix_convert(fname,conn,0,&bad_path,&sbuf);
2287 if(!check_name(fname, conn)) {
2288 set_bad_path_error(errno, bad_path);
2289 return(UNIXERROR(ERRDOS,ERRbadpath));
2293 * For CIFS UNIX extensions the target name may not exist.
2296 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2297 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2298 set_bad_path_error(errno, bad_path);
2299 return(UNIXERROR(ERRDOS,ERRbadpath));
2303 if (!CAN_WRITE(conn))
2304 return ERROR_DOS(ERRSRV,ERRaccess);
2306 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2307 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2309 if (VALID_STAT(sbuf))
2310 unixmode = sbuf.st_mode;
2312 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2313 tran_call,fname,info_level,total_data));
2315 /* Realloc the parameter and data sizes */
2316 params = Realloc(*pparams,2);
2318 return ERROR_DOS(ERRDOS,ERRnomem);
2324 /* the pending modtime overrides the current modtime */
2325 sbuf.st_mtime = fsp->pending_modtime;
2328 size = get_file_size(sbuf);
2329 tvs.modtime = sbuf.st_mtime;
2330 tvs.actime = sbuf.st_atime;
2331 dosmode = dos_mode(conn,fname,&sbuf);
2332 unixmode = sbuf.st_mode;
2334 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2335 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2337 switch (info_level) {
2338 case SMB_INFO_STANDARD:
2340 if (total_data < l1_cbFile+4)
2341 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2344 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2347 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2349 dosmode = SVAL(pdata,l1_attrFile);
2350 size = IVAL(pdata,l1_cbFile);
2355 case SMB_INFO_SET_EA:
2356 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2358 /* XXXX um, i don't think this is right.
2359 it's also not in the cifs6.txt spec.
2361 case SMB_INFO_QUERY_EAS_FROM_LIST:
2362 if (total_data < 28)
2363 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2365 tvs.actime = make_unix_date2(pdata+8);
2366 tvs.modtime = make_unix_date2(pdata+12);
2367 size = IVAL(pdata,16);
2368 dosmode = IVAL(pdata,24);
2371 /* XXXX nor this. not in cifs6.txt, either. */
2372 case SMB_INFO_QUERY_ALL_EAS:
2373 if (total_data < 28)
2374 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2376 tvs.actime = make_unix_date2(pdata+8);
2377 tvs.modtime = make_unix_date2(pdata+12);
2378 size = IVAL(pdata,16);
2379 dosmode = IVAL(pdata,24);
2382 case SMB_SET_FILE_BASIC_INFO:
2383 case SMB_FILE_BASIC_INFORMATION:
2385 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2387 time_t changed_time;
2389 if (total_data < 36)
2390 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2392 /* Ignore create time at offset pdata. */
2395 tvs.actime = interpret_long_date(pdata+8);
2397 write_time = interpret_long_date(pdata+16);
2398 changed_time = interpret_long_date(pdata+24);
2400 tvs.modtime = MIN(write_time, changed_time);
2402 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2403 tvs.modtime = write_time;
2405 /* Prefer a defined time to an undefined one. */
2406 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2407 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2408 ? changed_time : write_time);
2411 dosmode = IVAL(pdata,32);
2415 case SMB_FILE_ALLOCATION_INFORMATION:
2416 case SMB_SET_FILE_ALLOCATION_INFO:
2419 SMB_BIG_UINT allocation_size;
2422 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2424 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2425 #ifdef LARGE_SMB_OFF_T
2426 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2427 #else /* LARGE_SMB_OFF_T */
2428 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2429 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2430 #endif /* LARGE_SMB_OFF_T */
2431 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2432 fname, (double)allocation_size ));
2434 if (allocation_size)
2435 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2437 if(allocation_size != get_file_size(sbuf)) {
2438 SMB_STRUCT_STAT new_sbuf;
2440 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2441 fname, (double)allocation_size ));
2444 files_struct *new_fsp = NULL;
2445 int access_mode = 0;
2448 if(global_oplock_break) {
2449 /* Queue this file modify as we are the process of an oplock break. */
2451 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2452 DEBUGADD(2,( "in oplock break state.\n"));
2454 push_oplock_pending_smb_message(inbuf, length);
2458 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2459 SET_OPEN_MODE(DOS_OPEN_RDWR),
2460 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2461 0, 0, &access_mode, &action);
2463 if (new_fsp == NULL)
2464 return(UNIXERROR(ERRDOS,ERRbadpath));
2465 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2466 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2467 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2468 new_fsp->fnum, strerror(errno)));
2471 close_file(new_fsp,True);
2473 ret = vfs_allocate_file_space(fsp, allocation_size);
2474 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2475 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2476 fsp->fnum, strerror(errno)));
2481 return ERROR_NT(NT_STATUS_DISK_FULL);
2483 /* Allocate can truncate size... */
2484 size = get_file_size(new_sbuf);
2490 case SMB_FILE_END_OF_FILE_INFORMATION:
2491 case SMB_SET_FILE_END_OF_FILE_INFO:
2494 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2496 size = IVAL(pdata,0);
2497 #ifdef LARGE_SMB_OFF_T
2498 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2499 #else /* LARGE_SMB_OFF_T */
2500 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2501 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2502 #endif /* LARGE_SMB_OFF_T */
2503 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2507 case SMB_FILE_DISPOSITION_INFORMATION:
2508 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2510 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2514 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2516 if (tran_call != TRANSACT2_SETFILEINFO)
2517 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2520 return(UNIXERROR(ERRDOS,ERRbadfid));
2522 status = set_delete_on_close_internal(fsp, delete_on_close);
2524 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2525 return ERROR_NT(status);
2527 /* The set is across all open files on this dev/inode pair. */
2528 status =set_delete_on_close_over_all(fsp, delete_on_close);
2529 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2530 return ERROR_NT(status);
2536 * CIFS UNIX extensions.
2539 case SMB_SET_FILE_UNIX_BASIC:
2541 uint32 raw_unixmode;
2543 if (total_data < 100)
2544 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2546 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2547 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2548 size=IVAL(pdata,0); /* first 8 Bytes are size */
2549 #ifdef LARGE_SMB_OFF_T
2550 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2551 #else /* LARGE_SMB_OFF_T */
2552 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2553 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2554 #endif /* LARGE_SMB_OFF_T */
2556 pdata+=24; /* ctime & st_blocks are not changed */
2557 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2558 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2560 set_owner = (uid_t)IVAL(pdata,0);
2562 set_grp = (gid_t)IVAL(pdata,0);
2564 raw_unixmode = IVAL(pdata,28);
2565 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2566 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2568 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2569 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2570 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2572 if (!VALID_STAT(sbuf)) {
2575 * The only valid use of this is to create character and block
2576 * devices, and named pipes. This is deprecated (IMHO) and
2577 * a new info level should be used for mknod. JRA.
2580 #if !defined(HAVE_MAKEDEV_FN)
2581 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2582 #else /* HAVE_MAKEDEV_FN */
2583 uint32 file_type = IVAL(pdata,0);
2584 uint32 dev_major = IVAL(pdata,4);
2585 uint32 dev_minor = IVAL(pdata,12);
2587 uid_t myuid = geteuid();
2588 gid_t mygid = getegid();
2591 if (tran_call == TRANSACT2_SETFILEINFO)
2592 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2594 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2595 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2597 dev = makedev(dev_major, dev_minor);
2599 /* We can only create as the owner/group we are. */
2601 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2602 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2603 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2604 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2606 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2607 file_type != UNIX_TYPE_FIFO)
2608 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2610 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2611 0%o for file %s\n", (double)dev, unixmode, fname ));
2613 /* Ok - do the mknod. */
2614 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2615 return(UNIXERROR(ERRDOS,ERRnoaccess));
2617 inherit_access_acl(conn, fname, unixmode);
2620 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2622 #endif /* HAVE_MAKEDEV_FN */
2627 * Deal with the UNIX specific mode set.
2630 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2631 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2632 (unsigned int)unixmode, fname ));
2633 if (vfs_chmod(conn,fname,unixmode) != 0)
2634 return(UNIXERROR(ERRDOS,ERRnoaccess));
2638 * Deal with the UNIX specific uid set.
2641 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2642 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2643 (unsigned int)set_owner, fname ));
2644 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2645 return(UNIXERROR(ERRDOS,ERRnoaccess));
2649 * Deal with the UNIX specific gid set.
2652 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2653 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2654 (unsigned int)set_owner, fname ));
2655 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2656 return(UNIXERROR(ERRDOS,ERRnoaccess));
2661 case SMB_SET_FILE_UNIX_LINK:
2664 /* Set a symbolic link. */
2665 /* Don't allow this if follow links is false. */
2667 if (!lp_symlinks(SNUM(conn)))
2668 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2670 /* Disallow if already exists. */
2671 if (VALID_STAT(sbuf))
2672 return(ERROR_DOS(ERRDOS,ERRbadpath));
2674 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2676 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2677 return(UNIXERROR(ERRDOS,ERRnoaccess));
2679 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2680 fname, link_dest ));
2682 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2683 return(UNIXERROR(ERRDOS,ERRnoaccess));
2685 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2689 case SMB_SET_FILE_UNIX_HLINK:
2693 /* Set a hard link. */
2695 /* Disallow if already exists. */
2696 if (VALID_STAT(sbuf))
2697 return(ERROR_DOS(ERRDOS,ERRbadpath));
2699 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2701 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2702 return(UNIXERROR(ERRDOS,ERRnoaccess));
2704 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2705 fname, link_dest ));
2707 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2708 return(UNIXERROR(ERRDOS,ERRnoaccess));
2710 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2715 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2718 /* get some defaults (no modifications) if any info is zero or -1. */
2719 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2720 tvs.actime = sbuf.st_atime;
2722 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2723 tvs.modtime = sbuf.st_mtime;
2725 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2726 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2727 DEBUG(6,("size: %.0f ", (double)size));
2729 if (S_ISDIR(sbuf.st_mode))
2734 DEBUG(6,("dosmode: %x\n" , dosmode));
2736 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2737 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2738 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2739 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2742 * Only do this test if we are not explicitly
2743 * changing the size of a file.
2746 size = get_file_size(sbuf);
2750 * Try and set the times, size and mode of this file -
2751 * if they are different from the current values
2753 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2756 * This was a setfileinfo on an open file.
2757 * NT does this a lot. It's actually pointless
2758 * setting the time here, as it will be overwritten
2759 * on the next write, so we save the request
2760 * away and will set it on file close. JRA.
2763 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2764 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2765 fsp->pending_modtime = tvs.modtime;
2770 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2772 if(file_utime(conn, fname, &tvs)!=0)
2773 return(UNIXERROR(ERRDOS,ERRnoaccess));
2777 /* check the mode isn't different, before changing it */
2778 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2780 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2782 if(file_chmod(conn, fname, dosmode, NULL)) {
2783 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2784 return(UNIXERROR(ERRDOS,ERRnoaccess));
2788 if (size != get_file_size(sbuf)) {
2792 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2793 fname, (double)size ));
2796 files_struct *new_fsp = NULL;
2797 int access_mode = 0;
2800 if(global_oplock_break) {
2801 /* Queue this file modify as we are the process of an oplock break. */
2803 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2804 DEBUGADD(2,( "in oplock break state.\n"));
2806 push_oplock_pending_smb_message(inbuf, length);
2810 new_fsp = open_file_shared(conn, fname, &sbuf,
2811 SET_OPEN_MODE(DOS_OPEN_RDWR),
2812 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2813 0, 0, &access_mode, &action);
2815 if (new_fsp == NULL)
2816 return(UNIXERROR(ERRDOS,ERRbadpath));
2817 ret = vfs_set_filelen(new_fsp, size);
2818 close_file(new_fsp,True);
2820 ret = vfs_set_filelen(fsp, size);
2824 return (UNIXERROR(ERRHRD,ERRdiskfull));
2828 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2833 /****************************************************************************
2834 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2835 ****************************************************************************/
2837 static int call_trans2mkdir(connection_struct *conn,
2838 char *inbuf, char *outbuf, int length, int bufsize,
2839 char **pparams, int total_params, char **ppdata, int total_data)
2841 char *params = *pparams;
2844 SMB_STRUCT_STAT sbuf;
2845 BOOL bad_path = False;
2847 if (!CAN_WRITE(conn))
2848 return ERROR_DOS(ERRSRV,ERRaccess);
2850 if (total_params < 4)
2851 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2853 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2855 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2857 unix_convert(directory,conn,0,&bad_path,&sbuf);
2858 if (check_name(directory,conn))
2859 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2862 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2863 set_bad_path_error(errno, bad_path);
2864 return(UNIXERROR(ERRDOS,ERRnoaccess));
2867 /* Realloc the parameter and data sizes */
2868 params = Realloc(*pparams,2);
2870 return ERROR_DOS(ERRDOS,ERRnomem);
2875 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2880 /****************************************************************************
2881 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2882 We don't actually do this - we just send a null response.
2883 ****************************************************************************/
2885 static int call_trans2findnotifyfirst(connection_struct *conn,
2886 char *inbuf, char *outbuf, int length, int bufsize,
2887 char **pparams, int total_params, char **ppdata, int total_data)
2889 static uint16 fnf_handle = 257;
2890 char *params = *pparams;
2893 if (total_params < 6)
2894 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2896 info_level = SVAL(params,4);
2897 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2899 switch (info_level) {
2904 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2907 /* Realloc the parameter and data sizes */
2908 params = Realloc(*pparams,6);
2910 return ERROR_DOS(ERRDOS,ERRnomem);
2913 SSVAL(params,0,fnf_handle);
2914 SSVAL(params,2,0); /* No changes */
2915 SSVAL(params,4,0); /* No EA errors */
2922 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2927 /****************************************************************************
2928 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2929 changes). Currently this does nothing.
2930 ****************************************************************************/
2932 static int call_trans2findnotifynext(connection_struct *conn,
2933 char *inbuf, char *outbuf, int length, int bufsize,
2934 char **pparams, int total_params, char **ppdata, int total_data)
2936 char *params = *pparams;
2938 DEBUG(3,("call_trans2findnotifynext\n"));
2940 /* Realloc the parameter and data sizes */
2941 params = Realloc(*pparams,4);
2943 return ERROR_DOS(ERRDOS,ERRnomem);
2946 SSVAL(params,0,0); /* No changes */
2947 SSVAL(params,2,0); /* No EA errors */
2949 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2954 /****************************************************************************
2955 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2956 ****************************************************************************/
2958 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2959 char* outbuf, int length, int bufsize,
2960 char **pparams, int total_params, char **ppdata, int total_data)
2962 char *params = *pparams;
2965 int max_referral_level;
2967 DEBUG(10,("call_trans2getdfsreferral\n"));
2969 if (total_params < 2)
2970 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2972 max_referral_level = SVAL(params,0);
2974 if(!lp_host_msdfs())
2975 return ERROR_DOS(ERRDOS,ERRbadfunc);
2977 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2979 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2980 return ERROR_DOS(ERRDOS,ERRbadfile);
2982 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2983 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2988 #define LMCAT_SPL 0x53
2989 #define LMFUNC_GETJOBID 0x60
2991 /****************************************************************************
2992 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2993 ****************************************************************************/
2995 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2996 char* outbuf, int length, int bufsize,
2997 char **pparams, int total_params, char **ppdata, int total_data)
2999 char *pdata = *ppdata;
3000 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3002 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3003 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3004 pdata = Realloc(*ppdata, 32);
3006 return ERROR_DOS(ERRDOS,ERRnomem);
3009 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3010 CAN ACCEPT THIS IN UNICODE. JRA. */
3012 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3013 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3014 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3015 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3018 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3019 return ERROR_DOS(ERRSRV,ERRerror);
3023 /****************************************************************************
3024 Reply to a SMBfindclose (stop trans2 directory search).
3025 ****************************************************************************/
3027 int reply_findclose(connection_struct *conn,
3028 char *inbuf,char *outbuf,int length,int bufsize)
3031 int dptr_num=SVALS(inbuf,smb_vwv0);
3032 START_PROFILE(SMBfindclose);
3034 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3036 dptr_close(&dptr_num);
3038 outsize = set_message(outbuf,0,0,True);
3040 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3042 END_PROFILE(SMBfindclose);
3046 /****************************************************************************
3047 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3048 ****************************************************************************/
3050 int reply_findnclose(connection_struct *conn,
3051 char *inbuf,char *outbuf,int length,int bufsize)
3055 START_PROFILE(SMBfindnclose);
3057 dptr_num = SVAL(inbuf,smb_vwv0);
3059 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3061 /* We never give out valid handles for a
3062 findnotifyfirst - so any dptr_num is ok here.
3065 outsize = set_message(outbuf,0,0,True);
3067 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3069 END_PROFILE(SMBfindnclose);
3073 /****************************************************************************
3074 Reply to a SMBtranss2 - just ignore it!
3075 ****************************************************************************/
3077 int reply_transs2(connection_struct *conn,
3078 char *inbuf,char *outbuf,int length,int bufsize)
3080 START_PROFILE(SMBtranss2);
3081 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3082 END_PROFILE(SMBtranss2);
3086 /****************************************************************************
3087 Reply to a SMBtrans2.
3088 ****************************************************************************/
3090 int reply_trans2(connection_struct *conn,
3091 char *inbuf,char *outbuf,int length,int bufsize)
3094 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3095 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3097 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3098 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3099 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3100 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3101 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3102 int32 timeout = IVALS(inbuf,smb_timeout);
3104 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3105 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3106 char *params = NULL, *data = NULL;
3107 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3108 START_PROFILE(SMBtrans2);
3110 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3111 /* Queue this open message as we are the process of an
3114 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3115 DEBUGADD(2,( "in oplock break state.\n"));
3117 push_oplock_pending_smb_message(inbuf, length);
3118 END_PROFILE(SMBtrans2);
3122 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3123 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3124 END_PROFILE(SMBtrans2);
3125 return ERROR_DOS(ERRSRV,ERRaccess);
3128 outsize = set_message(outbuf,0,0,True);
3130 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3131 is so as a sanity check */
3134 * Need to have rc=0 for ioctl to get job id for OS/2.
3135 * Network printing will fail if function is not successful.
3136 * Similar function in reply.c will be used if protocol
3137 * is LANMAN1.0 instead of LM1.2X002.
3138 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3139 * outbuf doesn't have to be set(only job id is used).
3141 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3142 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3143 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3144 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3146 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3147 DEBUG(2,("Transaction is %d\n",tran_call));
3148 END_PROFILE(SMBtrans2);
3149 ERROR_DOS(ERRDOS,ERRinvalidparam);
3153 /* Allocate the space for the maximum needed parameters and data */
3154 if (total_params > 0)
3155 params = (char *)malloc(total_params);
3157 data = (char *)malloc(total_data);
3159 if ((total_params && !params) || (total_data && !data)) {
3160 DEBUG(2,("Out of memory in reply_trans2\n"));
3163 END_PROFILE(SMBtrans2);
3164 return ERROR_DOS(ERRDOS,ERRnomem);
3167 /* Copy the param and data bytes sent with this request into
3168 the params buffer */
3169 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3170 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3172 if (num_params > total_params || num_data > total_data)
3173 exit_server("invalid params in reply_trans2");
3176 unsigned int psoff = SVAL(inbuf, smb_psoff);
3177 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3179 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3181 memcpy( params, smb_base(inbuf) + psoff, num_params);
3184 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3185 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3187 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3189 memcpy( data, smb_base(inbuf) + 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) {
3202 unsigned int param_disp;
3203 unsigned int param_off;
3204 unsigned int data_disp;
3205 unsigned int data_off;
3207 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3210 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3211 outsize = set_message(outbuf,0,0,True);
3213 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3215 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3216 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3220 /* Revise total_params and total_data in case
3221 they have changed downwards */
3222 if (SVAL(inbuf, smb_tpscnt) < total_params)
3223 total_params = SVAL(inbuf, smb_tpscnt);
3224 if (SVAL(inbuf, smb_tdscnt) < total_data)
3225 total_data = SVAL(inbuf, smb_tdscnt);
3227 num_params = SVAL(inbuf,smb_spscnt);
3228 param_off = SVAL(inbuf, smb_spsoff);
3229 param_disp = SVAL(inbuf, smb_spsdisp);
3230 num_params_sofar += num_params;
3232 num_data = SVAL(inbuf, smb_sdscnt);
3233 data_off = SVAL(inbuf, smb_sdsoff);
3234 data_disp = SVAL(inbuf, smb_sdsdisp);
3235 num_data_sofar += num_data;
3237 if (num_params_sofar > total_params || num_data_sofar > total_data)
3241 if (param_disp + num_params >= total_params)
3243 if ((param_disp + num_params < param_disp) ||
3244 (param_disp + num_params < num_params))
3246 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3248 if (params + param_disp < params)
3251 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
3254 if (data_disp + num_data >= total_data)
3256 if ((data_disp + num_data < data_disp) ||
3257 (data_disp + num_data < num_data))
3259 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3261 if (data + data_disp < data)
3264 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3269 if (Protocol >= PROTOCOL_NT1) {
3270 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3273 /* Now we must call the relevant TRANS2 function */
3275 case TRANSACT2_OPEN:
3276 START_PROFILE_NESTED(Trans2_open);
3277 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3278 ¶ms, total_params, &data, total_data);
3279 END_PROFILE_NESTED(Trans2_open);
3282 case TRANSACT2_FINDFIRST:
3283 START_PROFILE_NESTED(Trans2_findfirst);
3284 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3285 ¶ms, total_params, &data, total_data);
3286 END_PROFILE_NESTED(Trans2_findfirst);
3289 case TRANSACT2_FINDNEXT:
3290 START_PROFILE_NESTED(Trans2_findnext);
3291 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3292 ¶ms, total_params, &data, total_data);
3293 END_PROFILE_NESTED(Trans2_findnext);
3296 case TRANSACT2_QFSINFO:
3297 START_PROFILE_NESTED(Trans2_qfsinfo);
3298 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3299 ¶ms, total_params, &data, total_data);
3300 END_PROFILE_NESTED(Trans2_qfsinfo);
3303 case TRANSACT2_SETFSINFO:
3304 START_PROFILE_NESTED(Trans2_setfsinfo);
3305 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3306 ¶ms, total_params, &data, total_data);
3307 END_PROFILE_NESTED(Trans2_setfsinfo);
3310 case TRANSACT2_QPATHINFO:
3311 case TRANSACT2_QFILEINFO:
3312 START_PROFILE_NESTED(Trans2_qpathinfo);
3313 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3314 ¶ms, total_params, &data, total_data);
3315 END_PROFILE_NESTED(Trans2_qpathinfo);
3317 case TRANSACT2_SETPATHINFO:
3318 case TRANSACT2_SETFILEINFO:
3319 START_PROFILE_NESTED(Trans2_setpathinfo);
3320 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3321 ¶ms, total_params, &data, total_data);
3322 END_PROFILE_NESTED(Trans2_setpathinfo);
3325 case TRANSACT2_FINDNOTIFYFIRST:
3326 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3327 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3328 ¶ms, total_params, &data, total_data);
3329 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3332 case TRANSACT2_FINDNOTIFYNEXT:
3333 START_PROFILE_NESTED(Trans2_findnotifynext);
3334 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3335 ¶ms, total_params, &data, total_data);
3336 END_PROFILE_NESTED(Trans2_findnotifynext);
3338 case TRANSACT2_MKDIR:
3339 START_PROFILE_NESTED(Trans2_mkdir);
3340 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3341 ¶ms, total_params, &data, total_data);
3342 END_PROFILE_NESTED(Trans2_mkdir);
3345 case TRANSACT2_GET_DFS_REFERRAL:
3346 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3347 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3348 ¶ms, total_params, &data, total_data);
3349 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3351 case TRANSACT2_IOCTL:
3352 START_PROFILE_NESTED(Trans2_ioctl);
3353 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3354 ¶ms, total_params, &data, total_data);
3355 END_PROFILE_NESTED(Trans2_ioctl);
3358 /* Error in request */
3359 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3362 END_PROFILE(SMBtrans2);
3363 return ERROR_DOS(ERRSRV,ERRerror);
3366 /* As we do not know how many data packets will need to be
3367 returned here the various call_trans2xxxx calls
3368 must send their own. Thus a call_trans2xxx routine only
3369 returns a value other than -1 when it wants to send
3375 END_PROFILE(SMBtrans2);
3376 return outsize; /* If a correct response was needed the
3377 call_trans2xxx calls have already sent
3378 it. If outsize != -1 then it is returning */
3384 END_PROFILE(SMBtrans2);
3385 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);