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 (lock_share_entry_fsp(fsp) == False)
2134 return NT_STATUS_ACCESS_DENIED;
2136 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2137 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2139 unlock_share_entry_fsp(fsp);
2140 return NT_STATUS_ACCESS_DENIED;
2143 unlock_share_entry_fsp(fsp);
2144 return NT_STATUS_OK;
2147 /****************************************************************************
2148 Returns true if this pathname is within the share, and thus safe.
2149 ****************************************************************************/
2151 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2154 char resolved_name[PATH_MAX+1];
2156 pstring resolved_name;
2158 fstring last_component;
2162 BOOL bad_path = False;
2163 SMB_STRUCT_STAT sbuf;
2165 pstrcpy(link_dest, link_dest_in);
2166 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2168 /* Store the UNIX converted path. */
2169 pstrcpy(link_dest_out, link_dest);
2171 p = strrchr(link_dest, '/');
2173 fstrcpy(last_component, p+1);
2176 fstrcpy(last_component, link_dest);
2177 pstrcpy(link_dest, "./");
2180 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2183 pstrcpy(link_dest, resolved_name);
2184 pstrcat(link_dest, "/");
2185 pstrcat(link_dest, last_component);
2187 if (*link_dest != '/') {
2188 /* Relative path. */
2189 pstrcpy(link_test, conn->connectpath);
2190 pstrcat(link_test, "/");
2191 pstrcat(link_test, link_dest);
2193 pstrcpy(link_test, link_dest);
2197 * Check if the link is within the share.
2200 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2207 /****************************************************************************
2208 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2209 ****************************************************************************/
2211 static int call_trans2setfilepathinfo(connection_struct *conn,
2212 char *inbuf, char *outbuf, int length, int bufsize,
2213 char **pparams, int total_params, char **ppdata, int total_data)
2215 char *params = *pparams;
2216 char *pdata = *ppdata;
2217 uint16 tran_call = SVAL(inbuf, smb_setup0);
2222 SMB_STRUCT_STAT sbuf;
2225 BOOL bad_path = False;
2226 files_struct *fsp = NULL;
2227 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2228 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2229 mode_t unixmode = 0;
2231 if (tran_call == TRANSACT2_SETFILEINFO) {
2232 fsp = file_fsp(params,0);
2233 info_level = SVAL(params,2);
2235 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2237 * This is actually a SETFILEINFO on a directory
2238 * handle (returned from an NT SMB). NT5.0 seems
2239 * to do this call. JRA.
2241 pstrcpy(fname, fsp->fsp_name);
2242 unix_convert(fname,conn,0,&bad_path,&sbuf);
2243 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2244 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2245 set_bad_path_error(errno, bad_path);
2246 return(UNIXERROR(ERRDOS,ERRbadpath));
2248 } else if (fsp && fsp->print_file) {
2250 * Doing a DELETE_ON_CLOSE should cancel a print job.
2252 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2253 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2255 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2258 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2261 return (UNIXERROR(ERRDOS,ERRbadpath));
2264 * Original code - this is an open file.
2266 CHECK_FSP(fsp,conn);
2268 pstrcpy(fname, fsp->fsp_name);
2271 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2272 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2273 return(UNIXERROR(ERRDOS,ERRbadfid));
2278 if (total_params < 6)
2279 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2281 info_level = SVAL(params,0);
2282 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2283 unix_convert(fname,conn,0,&bad_path,&sbuf);
2284 if(!check_name(fname, conn)) {
2285 set_bad_path_error(errno, bad_path);
2286 return(UNIXERROR(ERRDOS,ERRbadpath));
2290 * For CIFS UNIX extensions the target name may not exist.
2293 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2294 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2295 set_bad_path_error(errno, bad_path);
2296 return(UNIXERROR(ERRDOS,ERRbadpath));
2300 if (!CAN_WRITE(conn))
2301 return ERROR_DOS(ERRSRV,ERRaccess);
2303 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2304 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2306 if (VALID_STAT(sbuf))
2307 unixmode = sbuf.st_mode;
2309 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2310 tran_call,fname,info_level,total_data));
2312 /* Realloc the parameter and data sizes */
2313 params = Realloc(*pparams,2);
2315 return ERROR_DOS(ERRDOS,ERRnomem);
2321 /* the pending modtime overrides the current modtime */
2322 sbuf.st_mtime = fsp->pending_modtime;
2325 size = get_file_size(sbuf);
2326 tvs.modtime = sbuf.st_mtime;
2327 tvs.actime = sbuf.st_atime;
2328 dosmode = dos_mode(conn,fname,&sbuf);
2329 unixmode = sbuf.st_mode;
2331 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2332 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2334 switch (info_level) {
2335 case SMB_INFO_STANDARD:
2337 if (total_data < l1_cbFile+4)
2338 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2341 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2344 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2346 dosmode = SVAL(pdata,l1_attrFile);
2347 size = IVAL(pdata,l1_cbFile);
2352 case SMB_INFO_SET_EA:
2353 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2355 /* XXXX um, i don't think this is right.
2356 it's also not in the cifs6.txt spec.
2358 case SMB_INFO_QUERY_EAS_FROM_LIST:
2359 if (total_data < 28)
2360 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2362 tvs.actime = make_unix_date2(pdata+8);
2363 tvs.modtime = make_unix_date2(pdata+12);
2364 size = IVAL(pdata,16);
2365 dosmode = IVAL(pdata,24);
2368 /* XXXX nor this. not in cifs6.txt, either. */
2369 case SMB_INFO_QUERY_ALL_EAS:
2370 if (total_data < 28)
2371 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2373 tvs.actime = make_unix_date2(pdata+8);
2374 tvs.modtime = make_unix_date2(pdata+12);
2375 size = IVAL(pdata,16);
2376 dosmode = IVAL(pdata,24);
2379 case SMB_SET_FILE_BASIC_INFO:
2380 case SMB_FILE_BASIC_INFORMATION:
2382 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2384 time_t changed_time;
2386 if (total_data < 36)
2387 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2389 /* Ignore create time at offset pdata. */
2392 tvs.actime = interpret_long_date(pdata+8);
2394 write_time = interpret_long_date(pdata+16);
2395 changed_time = interpret_long_date(pdata+24);
2397 tvs.modtime = MIN(write_time, changed_time);
2399 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2400 tvs.modtime = write_time;
2402 /* Prefer a defined time to an undefined one. */
2403 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2404 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2405 ? changed_time : write_time);
2408 dosmode = IVAL(pdata,32);
2412 case SMB_FILE_ALLOCATION_INFORMATION:
2413 case SMB_SET_FILE_ALLOCATION_INFO:
2416 SMB_BIG_UINT allocation_size;
2419 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2421 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2422 #ifdef LARGE_SMB_OFF_T
2423 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2424 #else /* LARGE_SMB_OFF_T */
2425 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2426 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2427 #endif /* LARGE_SMB_OFF_T */
2428 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2429 fname, (double)allocation_size ));
2431 if (allocation_size)
2432 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2434 if(allocation_size != get_file_size(sbuf)) {
2435 SMB_STRUCT_STAT new_sbuf;
2437 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2438 fname, (double)allocation_size ));
2441 files_struct *new_fsp = NULL;
2442 int access_mode = 0;
2445 if(global_oplock_break) {
2446 /* Queue this file modify as we are the process of an oplock break. */
2448 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2449 DEBUGADD(2,( "in oplock break state.\n"));
2451 push_oplock_pending_smb_message(inbuf, length);
2455 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2456 SET_OPEN_MODE(DOS_OPEN_RDWR),
2457 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2458 0, 0, &access_mode, &action);
2460 if (new_fsp == NULL)
2461 return(UNIXERROR(ERRDOS,ERRbadpath));
2462 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2463 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2464 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2465 new_fsp->fnum, strerror(errno)));
2468 close_file(new_fsp,True);
2470 ret = vfs_allocate_file_space(fsp, allocation_size);
2471 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2472 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2473 fsp->fnum, strerror(errno)));
2478 return ERROR_NT(NT_STATUS_DISK_FULL);
2480 /* Allocate can truncate size... */
2481 size = get_file_size(new_sbuf);
2487 case SMB_FILE_END_OF_FILE_INFORMATION:
2488 case SMB_SET_FILE_END_OF_FILE_INFO:
2491 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2493 size = IVAL(pdata,0);
2494 #ifdef LARGE_SMB_OFF_T
2495 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2496 #else /* LARGE_SMB_OFF_T */
2497 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2498 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499 #endif /* LARGE_SMB_OFF_T */
2500 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2504 case SMB_FILE_DISPOSITION_INFORMATION:
2505 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2507 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2511 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2513 if (tran_call != TRANSACT2_SETFILEINFO)
2514 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2517 return(UNIXERROR(ERRDOS,ERRbadfid));
2519 status = set_delete_on_close_internal(fsp, delete_on_close);
2521 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2522 return ERROR_NT(status);
2524 /* The set is across all open files on this dev/inode pair. */
2525 status =set_delete_on_close_over_all(fsp, delete_on_close);
2526 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2527 return ERROR_NT(status);
2533 * CIFS UNIX extensions.
2536 case SMB_SET_FILE_UNIX_BASIC:
2538 uint32 raw_unixmode;
2540 if (total_data < 100)
2541 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2543 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2544 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2545 size=IVAL(pdata,0); /* first 8 Bytes are size */
2546 #ifdef LARGE_SMB_OFF_T
2547 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2548 #else /* LARGE_SMB_OFF_T */
2549 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2550 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2551 #endif /* LARGE_SMB_OFF_T */
2553 pdata+=24; /* ctime & st_blocks are not changed */
2554 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2555 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2557 set_owner = (uid_t)IVAL(pdata,0);
2559 set_grp = (gid_t)IVAL(pdata,0);
2561 raw_unixmode = IVAL(pdata,28);
2562 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2563 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2565 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2566 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2567 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2569 if (!VALID_STAT(sbuf)) {
2572 * The only valid use of this is to create character and block
2573 * devices, and named pipes. This is deprecated (IMHO) and
2574 * a new info level should be used for mknod. JRA.
2577 #if !defined(HAVE_MAKEDEV_FN)
2578 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2579 #else /* HAVE_MAKEDEV_FN */
2580 uint32 file_type = IVAL(pdata,0);
2581 uint32 dev_major = IVAL(pdata,4);
2582 uint32 dev_minor = IVAL(pdata,12);
2584 uid_t myuid = geteuid();
2585 gid_t mygid = getegid();
2588 if (tran_call == TRANSACT2_SETFILEINFO)
2589 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2591 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2592 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2594 dev = makedev(dev_major, dev_minor);
2596 /* We can only create as the owner/group we are. */
2598 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2599 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2600 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2601 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2603 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2604 file_type != UNIX_TYPE_FIFO)
2605 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2607 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2608 0%o for file %s\n", (double)dev, unixmode, fname ));
2610 /* Ok - do the mknod. */
2611 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2612 return(UNIXERROR(ERRDOS,ERRnoaccess));
2614 inherit_access_acl(conn, fname, unixmode);
2617 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2619 #endif /* HAVE_MAKEDEV_FN */
2624 * Deal with the UNIX specific mode set.
2627 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2628 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2629 (unsigned int)unixmode, fname ));
2630 if (vfs_chmod(conn,fname,unixmode) != 0)
2631 return(UNIXERROR(ERRDOS,ERRnoaccess));
2635 * Deal with the UNIX specific uid set.
2638 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2639 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2640 (unsigned int)set_owner, fname ));
2641 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2642 return(UNIXERROR(ERRDOS,ERRnoaccess));
2646 * Deal with the UNIX specific gid set.
2649 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2650 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2651 (unsigned int)set_owner, fname ));
2652 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2653 return(UNIXERROR(ERRDOS,ERRnoaccess));
2658 case SMB_SET_FILE_UNIX_LINK:
2661 /* Set a symbolic link. */
2662 /* Don't allow this if follow links is false. */
2664 if (!lp_symlinks(SNUM(conn)))
2665 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2667 /* Disallow if already exists. */
2668 if (VALID_STAT(sbuf))
2669 return(ERROR_DOS(ERRDOS,ERRbadpath));
2671 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2673 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2674 return(UNIXERROR(ERRDOS,ERRnoaccess));
2676 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2677 fname, link_dest ));
2679 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2680 return(UNIXERROR(ERRDOS,ERRnoaccess));
2682 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2686 case SMB_SET_FILE_UNIX_HLINK:
2690 /* Set a hard link. */
2692 /* Disallow if already exists. */
2693 if (VALID_STAT(sbuf))
2694 return(ERROR_DOS(ERRDOS,ERRbadpath));
2696 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2698 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2699 return(UNIXERROR(ERRDOS,ERRnoaccess));
2701 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2702 fname, link_dest ));
2704 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2705 return(UNIXERROR(ERRDOS,ERRnoaccess));
2707 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2712 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2715 /* get some defaults (no modifications) if any info is zero or -1. */
2716 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2717 tvs.actime = sbuf.st_atime;
2719 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2720 tvs.modtime = sbuf.st_mtime;
2722 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2723 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2724 DEBUG(6,("size: %.0f ", (double)size));
2726 if (S_ISDIR(sbuf.st_mode))
2731 DEBUG(6,("dosmode: %x\n" , dosmode));
2733 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2734 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2735 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2736 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2739 * Only do this test if we are not explicitly
2740 * changing the size of a file.
2743 size = get_file_size(sbuf);
2747 * Try and set the times, size and mode of this file -
2748 * if they are different from the current values
2750 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2753 * This was a setfileinfo on an open file.
2754 * NT does this a lot. It's actually pointless
2755 * setting the time here, as it will be overwritten
2756 * on the next write, so we save the request
2757 * away and will set it on file close. JRA.
2760 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2761 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2762 fsp->pending_modtime = tvs.modtime;
2767 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2769 if(file_utime(conn, fname, &tvs)!=0)
2770 return(UNIXERROR(ERRDOS,ERRnoaccess));
2774 /* check the mode isn't different, before changing it */
2775 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2777 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2779 if(file_chmod(conn, fname, dosmode, NULL)) {
2780 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2781 return(UNIXERROR(ERRDOS,ERRnoaccess));
2785 if (size != get_file_size(sbuf)) {
2789 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2790 fname, (double)size ));
2793 files_struct *new_fsp = NULL;
2794 int access_mode = 0;
2797 if(global_oplock_break) {
2798 /* Queue this file modify as we are the process of an oplock break. */
2800 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2801 DEBUGADD(2,( "in oplock break state.\n"));
2803 push_oplock_pending_smb_message(inbuf, length);
2807 new_fsp = open_file_shared(conn, fname, &sbuf,
2808 SET_OPEN_MODE(DOS_OPEN_RDWR),
2809 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2810 0, 0, &access_mode, &action);
2812 if (new_fsp == NULL)
2813 return(UNIXERROR(ERRDOS,ERRbadpath));
2814 ret = vfs_set_filelen(new_fsp, size);
2815 close_file(new_fsp,True);
2817 ret = vfs_set_filelen(fsp, size);
2821 return (UNIXERROR(ERRHRD,ERRdiskfull));
2825 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2830 /****************************************************************************
2831 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2832 ****************************************************************************/
2834 static int call_trans2mkdir(connection_struct *conn,
2835 char *inbuf, char *outbuf, int length, int bufsize,
2836 char **pparams, int total_params, char **ppdata, int total_data)
2838 char *params = *pparams;
2841 SMB_STRUCT_STAT sbuf;
2842 BOOL bad_path = False;
2844 if (!CAN_WRITE(conn))
2845 return ERROR_DOS(ERRSRV,ERRaccess);
2847 if (total_params < 4)
2848 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2850 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2852 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2854 unix_convert(directory,conn,0,&bad_path,&sbuf);
2855 if (check_name(directory,conn))
2856 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2859 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2860 set_bad_path_error(errno, bad_path);
2861 return(UNIXERROR(ERRDOS,ERRnoaccess));
2864 /* Realloc the parameter and data sizes */
2865 params = Realloc(*pparams,2);
2867 return ERROR_DOS(ERRDOS,ERRnomem);
2872 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2877 /****************************************************************************
2878 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2879 We don't actually do this - we just send a null response.
2880 ****************************************************************************/
2882 static int call_trans2findnotifyfirst(connection_struct *conn,
2883 char *inbuf, char *outbuf, int length, int bufsize,
2884 char **pparams, int total_params, char **ppdata, int total_data)
2886 static uint16 fnf_handle = 257;
2887 char *params = *pparams;
2890 if (total_params < 6)
2891 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2893 info_level = SVAL(params,4);
2894 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2896 switch (info_level) {
2901 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2904 /* Realloc the parameter and data sizes */
2905 params = Realloc(*pparams,6);
2907 return ERROR_DOS(ERRDOS,ERRnomem);
2910 SSVAL(params,0,fnf_handle);
2911 SSVAL(params,2,0); /* No changes */
2912 SSVAL(params,4,0); /* No EA errors */
2919 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2924 /****************************************************************************
2925 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2926 changes). Currently this does nothing.
2927 ****************************************************************************/
2929 static int call_trans2findnotifynext(connection_struct *conn,
2930 char *inbuf, char *outbuf, int length, int bufsize,
2931 char **pparams, int total_params, char **ppdata, int total_data)
2933 char *params = *pparams;
2935 DEBUG(3,("call_trans2findnotifynext\n"));
2937 /* Realloc the parameter and data sizes */
2938 params = Realloc(*pparams,4);
2940 return ERROR_DOS(ERRDOS,ERRnomem);
2943 SSVAL(params,0,0); /* No changes */
2944 SSVAL(params,2,0); /* No EA errors */
2946 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2951 /****************************************************************************
2952 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2953 ****************************************************************************/
2955 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2956 char* outbuf, int length, int bufsize,
2957 char **pparams, int total_params, char **ppdata, int total_data)
2959 char *params = *pparams;
2962 int max_referral_level;
2964 DEBUG(10,("call_trans2getdfsreferral\n"));
2966 if (total_params < 2)
2967 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2969 max_referral_level = SVAL(params,0);
2971 if(!lp_host_msdfs())
2972 return ERROR_DOS(ERRDOS,ERRbadfunc);
2974 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2976 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2977 return ERROR_DOS(ERRDOS,ERRbadfile);
2979 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2980 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2985 #define LMCAT_SPL 0x53
2986 #define LMFUNC_GETJOBID 0x60
2988 /****************************************************************************
2989 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2990 ****************************************************************************/
2992 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2993 char* outbuf, int length, int bufsize,
2994 char **pparams, int total_params, char **ppdata, int total_data)
2996 char *pdata = *ppdata;
2997 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2999 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3000 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3001 pdata = Realloc(*ppdata, 32);
3003 return ERROR_DOS(ERRDOS,ERRnomem);
3006 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3007 CAN ACCEPT THIS IN UNICODE. JRA. */
3009 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3010 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3011 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3012 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3015 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3016 return ERROR_DOS(ERRSRV,ERRerror);
3020 /****************************************************************************
3021 Reply to a SMBfindclose (stop trans2 directory search).
3022 ****************************************************************************/
3024 int reply_findclose(connection_struct *conn,
3025 char *inbuf,char *outbuf,int length,int bufsize)
3028 int dptr_num=SVALS(inbuf,smb_vwv0);
3029 START_PROFILE(SMBfindclose);
3031 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3033 dptr_close(&dptr_num);
3035 outsize = set_message(outbuf,0,0,True);
3037 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3039 END_PROFILE(SMBfindclose);
3043 /****************************************************************************
3044 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3045 ****************************************************************************/
3047 int reply_findnclose(connection_struct *conn,
3048 char *inbuf,char *outbuf,int length,int bufsize)
3052 START_PROFILE(SMBfindnclose);
3054 dptr_num = SVAL(inbuf,smb_vwv0);
3056 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3058 /* We never give out valid handles for a
3059 findnotifyfirst - so any dptr_num is ok here.
3062 outsize = set_message(outbuf,0,0,True);
3064 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3066 END_PROFILE(SMBfindnclose);
3070 /****************************************************************************
3071 Reply to a SMBtranss2 - just ignore it!
3072 ****************************************************************************/
3074 int reply_transs2(connection_struct *conn,
3075 char *inbuf,char *outbuf,int length,int bufsize)
3077 START_PROFILE(SMBtranss2);
3078 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3079 END_PROFILE(SMBtranss2);
3083 /****************************************************************************
3084 Reply to a SMBtrans2.
3085 ****************************************************************************/
3087 int reply_trans2(connection_struct *conn,
3088 char *inbuf,char *outbuf,int length,int bufsize)
3091 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3092 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3094 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3095 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3096 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3097 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3098 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3099 int32 timeout = IVALS(inbuf,smb_timeout);
3101 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3102 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3103 char *params = NULL, *data = NULL;
3104 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3105 START_PROFILE(SMBtrans2);
3107 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3108 /* Queue this open message as we are the process of an
3111 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3112 DEBUGADD(2,( "in oplock break state.\n"));
3114 push_oplock_pending_smb_message(inbuf, length);
3115 END_PROFILE(SMBtrans2);
3119 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3120 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3121 END_PROFILE(SMBtrans2);
3122 return ERROR_DOS(ERRSRV,ERRaccess);
3125 outsize = set_message(outbuf,0,0,True);
3127 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3128 is so as a sanity check */
3131 * Need to have rc=0 for ioctl to get job id for OS/2.
3132 * Network printing will fail if function is not successful.
3133 * Similar function in reply.c will be used if protocol
3134 * is LANMAN1.0 instead of LM1.2X002.
3135 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3136 * outbuf doesn't have to be set(only job id is used).
3138 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3139 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3140 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3141 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3143 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3144 DEBUG(2,("Transaction is %d\n",tran_call));
3145 END_PROFILE(SMBtrans2);
3146 ERROR_DOS(ERRDOS,ERRinvalidparam);
3150 /* Allocate the space for the maximum needed parameters and data */
3151 if (total_params > 0)
3152 params = (char *)malloc(total_params);
3154 data = (char *)malloc(total_data);
3156 if ((total_params && !params) || (total_data && !data)) {
3157 DEBUG(2,("Out of memory in reply_trans2\n"));
3160 END_PROFILE(SMBtrans2);
3161 return ERROR_DOS(ERRDOS,ERRnomem);
3164 /* Copy the param and data bytes sent with this request into
3165 the params buffer */
3166 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3167 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3169 if (num_params > total_params || num_data > total_data)
3170 exit_server("invalid params in reply_trans2");
3173 unsigned int psoff = SVAL(inbuf, smb_psoff);
3174 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3176 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3178 memcpy( params, smb_base(inbuf) + psoff, num_params);
3181 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3182 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3184 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3186 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3189 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3190 /* We need to send an interim response then receive the rest
3191 of the parameter/data bytes */
3192 outsize = set_message(outbuf,0,0,True);
3193 if (!send_smb(smbd_server_fd(),outbuf))
3194 exit_server("reply_trans2: send_smb failed.");
3196 while (num_data_sofar < total_data ||
3197 num_params_sofar < total_params) {
3199 unsigned int param_disp;
3200 unsigned int param_off;
3201 unsigned int data_disp;
3202 unsigned int data_off;
3204 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3207 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3208 outsize = set_message(outbuf,0,0,True);
3210 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3212 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3213 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3217 /* Revise total_params and total_data in case
3218 they have changed downwards */
3219 if (SVAL(inbuf, smb_tpscnt) < total_params)
3220 total_params = SVAL(inbuf, smb_tpscnt);
3221 if (SVAL(inbuf, smb_tdscnt) < total_data)
3222 total_data = SVAL(inbuf, smb_tdscnt);
3224 num_params = SVAL(inbuf,smb_spscnt);
3225 param_off = SVAL(inbuf, smb_spsoff);
3226 param_disp = SVAL(inbuf, smb_spsdisp);
3227 num_params_sofar += num_params;
3229 num_data = SVAL(inbuf, smb_sdscnt);
3230 data_off = SVAL(inbuf, smb_sdsoff);
3231 data_disp = SVAL(inbuf, smb_sdsdisp);
3232 num_data_sofar += num_data;
3234 if (num_params_sofar > total_params || num_data_sofar > total_data)
3238 if (param_disp + num_params >= total_params)
3240 if ((param_disp + num_params < param_disp) ||
3241 (param_disp + num_params < num_params))
3243 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3245 if (params + param_disp < params)
3248 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
3251 if (data_disp + num_data >= total_data)
3253 if ((data_disp + num_data < data_disp) ||
3254 (data_disp + num_data < num_data))
3256 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3258 if (data + data_disp < data)
3261 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3266 if (Protocol >= PROTOCOL_NT1) {
3267 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3270 /* Now we must call the relevant TRANS2 function */
3272 case TRANSACT2_OPEN:
3273 START_PROFILE_NESTED(Trans2_open);
3274 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3275 ¶ms, total_params, &data, total_data);
3276 END_PROFILE_NESTED(Trans2_open);
3279 case TRANSACT2_FINDFIRST:
3280 START_PROFILE_NESTED(Trans2_findfirst);
3281 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3282 ¶ms, total_params, &data, total_data);
3283 END_PROFILE_NESTED(Trans2_findfirst);
3286 case TRANSACT2_FINDNEXT:
3287 START_PROFILE_NESTED(Trans2_findnext);
3288 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3289 ¶ms, total_params, &data, total_data);
3290 END_PROFILE_NESTED(Trans2_findnext);
3293 case TRANSACT2_QFSINFO:
3294 START_PROFILE_NESTED(Trans2_qfsinfo);
3295 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3296 ¶ms, total_params, &data, total_data);
3297 END_PROFILE_NESTED(Trans2_qfsinfo);
3300 case TRANSACT2_SETFSINFO:
3301 START_PROFILE_NESTED(Trans2_setfsinfo);
3302 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3303 ¶ms, total_params, &data, total_data);
3304 END_PROFILE_NESTED(Trans2_setfsinfo);
3307 case TRANSACT2_QPATHINFO:
3308 case TRANSACT2_QFILEINFO:
3309 START_PROFILE_NESTED(Trans2_qpathinfo);
3310 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3311 ¶ms, total_params, &data, total_data);
3312 END_PROFILE_NESTED(Trans2_qpathinfo);
3314 case TRANSACT2_SETPATHINFO:
3315 case TRANSACT2_SETFILEINFO:
3316 START_PROFILE_NESTED(Trans2_setpathinfo);
3317 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3318 ¶ms, total_params, &data, total_data);
3319 END_PROFILE_NESTED(Trans2_setpathinfo);
3322 case TRANSACT2_FINDNOTIFYFIRST:
3323 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3324 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3325 ¶ms, total_params, &data, total_data);
3326 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3329 case TRANSACT2_FINDNOTIFYNEXT:
3330 START_PROFILE_NESTED(Trans2_findnotifynext);
3331 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3332 ¶ms, total_params, &data, total_data);
3333 END_PROFILE_NESTED(Trans2_findnotifynext);
3335 case TRANSACT2_MKDIR:
3336 START_PROFILE_NESTED(Trans2_mkdir);
3337 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3338 ¶ms, total_params, &data, total_data);
3339 END_PROFILE_NESTED(Trans2_mkdir);
3342 case TRANSACT2_GET_DFS_REFERRAL:
3343 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3344 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3345 ¶ms, total_params, &data, total_data);
3346 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3348 case TRANSACT2_IOCTL:
3349 START_PROFILE_NESTED(Trans2_ioctl);
3350 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3351 ¶ms, total_params, &data, total_data);
3352 END_PROFILE_NESTED(Trans2_ioctl);
3355 /* Error in request */
3356 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3359 END_PROFILE(SMBtrans2);
3360 return ERROR_DOS(ERRSRV,ERRerror);
3363 /* As we do not know how many data packets will need to be
3364 returned here the various call_trans2xxxx calls
3365 must send their own. Thus a call_trans2xxx routine only
3366 returns a value other than -1 when it wants to send
3372 END_PROFILE(SMBtrans2);
3373 return outsize; /* If a correct response was needed the
3374 call_trans2xxx calls have already sent
3375 it. If outsize != -1 then it is returning */
3381 END_PROFILE(SMBtrans2);
3382 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);