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;
1177 void *dirptr = conn->dirptr;
1178 start_pos = TellDir(dirptr);
1179 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1180 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1182 SeekDir(dirptr, current_pos);
1183 dname = ReadDirName(dirptr);
1186 * Remember, mangle_map is called by
1187 * get_lanman2_dir_entry(), so the resume name
1188 * could be mangled. Ensure we do the same
1193 mangle_map( dname, False, True, SNUM(conn));
1195 if(dname && strcsequal( resume_name, dname)) {
1196 SeekDir(dirptr, current_pos+1);
1197 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1203 * Scan forward from start if not found going backwards.
1206 if(current_pos < 0) {
1207 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1208 SeekDir(dirptr, start_pos);
1209 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1212 * Remember, mangle_map is called by
1213 * get_lanman2_dir_entry(), so the resume name
1214 * could be mangled. Ensure we do the same
1219 mangle_map( dname, False, True, SNUM(conn));
1221 if(dname && strcsequal( resume_name, dname)) {
1222 SeekDir(dirptr, current_pos+1);
1223 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1227 } /* end if current_pos */
1228 } /* end if requires_resume_key && !continue_bit */
1230 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1231 BOOL got_exact_match = False;
1233 /* this is a heuristic to avoid seeking the dirptr except when
1234 absolutely necessary. It allows for a filename of about 40 chars */
1235 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1236 out_of_space = True;
1239 finished = !get_lanman2_dir_entry(conn,
1241 mask,dirtype,info_level,
1242 requires_resume_key,dont_descend,
1243 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1247 if (finished && out_of_space)
1250 if (!finished && !out_of_space)
1254 * As an optimisation if we know we aren't looking
1255 * for a wildcard name (ie. the name matches the wildcard exactly)
1256 * then we can finish on any (first) match.
1257 * This speeds up large directory searches. JRA.
1263 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1266 /* Check if we can close the dirptr */
1267 if(close_after_request || (finished && close_if_end)) {
1268 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1269 dptr_close(&dptr_num); /* This frees up the saved mask */
1273 /* Set up the return parameter block */
1274 SSVAL(params,0,numentries);
1275 SSVAL(params,2,finished);
1276 SSVAL(params,4,0); /* Never an EA error */
1277 SSVAL(params,6,last_name_off);
1279 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1281 if ((! *directory) && dptr_path(dptr_num))
1282 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1284 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1285 smb_fn_name(CVAL(inbuf,smb_com)),
1286 mask, directory, dirtype, numentries ) );
1291 /****************************************************************************
1292 Reply to a TRANS2_QFSINFO (query filesystem info).
1293 ****************************************************************************/
1295 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1296 int length, int bufsize,
1297 char **pparams, int total_params, char **ppdata, int total_data)
1299 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1300 char *pdata = *ppdata;
1301 char *params = *pparams;
1302 uint16 info_level = SVAL(params,0);
1305 char *vname = volume_label(SNUM(conn));
1306 int snum = SNUM(conn);
1307 char *fstype = lp_fstype(SNUM(conn));
1309 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1311 if(vfs_stat(conn,".",&st)!=0) {
1312 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1313 return ERROR_DOS(ERRSRV,ERRinvdevice);
1316 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1317 if ( pdata == NULL )
1318 return ERROR_DOS(ERRDOS,ERRnomem);
1321 memset((char *)pdata,'\0',max_data_bytes + 1024);
1323 switch (info_level) {
1324 case SMB_INFO_ALLOCATION:
1326 SMB_BIG_UINT dfree,dsize,bsize;
1328 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1329 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1330 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1331 SIVAL(pdata,l1_cUnit,dsize);
1332 SIVAL(pdata,l1_cUnitAvail,dfree);
1333 SSVAL(pdata,l1_cbSector,512);
1334 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1335 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1336 (unsigned int)dfree, 512));
1340 case SMB_INFO_VOLUME:
1341 /* Return volume name */
1343 * Add volume serial number - hash of a combination of
1344 * the called hostname and the service name.
1346 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1347 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1348 SCVAL(pdata,l2_vol_cch,len);
1349 data_len = l2_vol_szVolLabel + len;
1350 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1351 (unsigned)st.st_ctime, len, vname));
1354 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1355 case SMB_FS_ATTRIBUTE_INFORMATION:
1357 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1358 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1359 SIVAL(pdata,4,255); /* Max filename component length */
1360 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1361 and will think we can't do long filenames */
1362 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1364 data_len = 12 + len;
1367 case SMB_QUERY_FS_LABEL_INFO:
1368 case SMB_FS_LABEL_INFORMATION:
1369 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1374 case SMB_QUERY_FS_VOLUME_INFO:
1375 case SMB_FS_VOLUME_INFORMATION:
1378 * Add volume serial number - hash of a combination of
1379 * the called hostname and the service name.
1381 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1382 (str_checksum(local_machine)<<16));
1384 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1385 SIVAL(pdata,12,len);
1387 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1388 (int)strlen(vname),vname, lp_servicename(snum)));
1391 case SMB_QUERY_FS_SIZE_INFO:
1392 case SMB_FS_SIZE_INFORMATION:
1394 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1396 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1397 block_size = lp_block_size(snum);
1398 if (bsize < block_size) {
1399 SMB_BIG_UINT factor = block_size/bsize;
1404 if (bsize > block_size) {
1405 SMB_BIG_UINT factor = bsize/block_size;
1410 bytes_per_sector = 512;
1411 sectors_per_unit = bsize/bytes_per_sector;
1412 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1413 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1414 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1415 SBIG_UINT(pdata,0,dsize);
1416 SBIG_UINT(pdata,8,dfree);
1417 SIVAL(pdata,16,sectors_per_unit);
1418 SIVAL(pdata,20,bytes_per_sector);
1422 case SMB_FS_FULL_SIZE_INFORMATION:
1424 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1426 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1427 block_size = lp_block_size(snum);
1428 if (bsize < block_size) {
1429 SMB_BIG_UINT factor = block_size/bsize;
1434 if (bsize > block_size) {
1435 SMB_BIG_UINT factor = bsize/block_size;
1440 bytes_per_sector = 512;
1441 sectors_per_unit = bsize/bytes_per_sector;
1442 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1443 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1444 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1445 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1446 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1447 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1448 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1449 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1453 case SMB_QUERY_FS_DEVICE_INFO:
1454 case SMB_FS_DEVICE_INFORMATION:
1456 SIVAL(pdata,0,0); /* dev type */
1457 SIVAL(pdata,4,0); /* characteristics */
1460 case SMB_FS_OBJECTID_INFORMATION:
1465 * Query the version and capabilities of the CIFS UNIX extensions
1469 case SMB_QUERY_CIFS_UNIX_INFO:
1470 if (!lp_unix_extensions())
1471 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1473 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1474 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1475 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1478 case SMB_MAC_QUERY_FS_INFO:
1480 * Thursby MAC extension... ONLY on NTFS filesystems
1481 * once we do streams then we don't need this
1483 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1485 SIVAL(pdata,84,0x100); /* Don't support mac... */
1490 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1494 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1496 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1501 /****************************************************************************
1502 Reply to a TRANS2_SETFSINFO (set filesystem info).
1503 ****************************************************************************/
1505 static int call_trans2setfsinfo(connection_struct *conn,
1506 char *inbuf, char *outbuf, int length, int bufsize,
1507 char **pparams, int total_params, char **ppdata, int total_data)
1509 /* Just say yes we did it - there is nothing that
1510 can be set here so it doesn't matter. */
1512 DEBUG(3,("call_trans2setfsinfo\n"));
1514 if (!CAN_WRITE(conn))
1515 return ERROR_DOS(ERRSRV,ERRaccess);
1517 outsize = set_message(outbuf,10,0,True);
1522 /****************************************************************************
1523 * Utility function to set bad path error.
1524 ****************************************************************************/
1526 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1528 if((err == ENOENT) && bad_path) {
1529 unix_ERR_class = ERRDOS;
1530 unix_ERR_code = ERRbadpath;
1531 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1533 return NT_STATUS_OK;
1536 /****************************************************************************
1537 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1538 file name or file id).
1539 ****************************************************************************/
1541 static int call_trans2qfilepathinfo(connection_struct *conn,
1542 char *inbuf, char *outbuf, int length,
1544 char **pparams, int total_params, char **ppdata, int total_data)
1546 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1547 char *params = *pparams;
1548 char *pdata = *ppdata;
1549 uint16 tran_call = SVAL(inbuf, smb_setup0);
1552 SMB_OFF_T file_size=0;
1553 SMB_BIG_UINT allocation_size=0;
1554 unsigned int data_size;
1555 SMB_STRUCT_STAT sbuf;
1556 pstring fname, dos_fname;
1561 BOOL bad_path = False;
1562 BOOL delete_pending = False;
1565 files_struct *fsp = NULL;
1568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1570 if (tran_call == TRANSACT2_QFILEINFO) {
1571 if (total_params < 4)
1572 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1574 fsp = file_fsp(params,0);
1575 info_level = SVAL(params,2);
1577 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1579 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1581 * This is actually a QFILEINFO on a directory
1582 * handle (returned from an NT SMB). NT5.0 seems
1583 * to do this call. JRA.
1585 pstrcpy(fname, fsp->fsp_name);
1586 unix_convert(fname,conn,0,&bad_path,&sbuf);
1587 if (!check_name(fname,conn)) {
1588 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1589 set_bad_path_error(errno, bad_path);
1590 return(UNIXERROR(ERRDOS,ERRbadpath));
1593 if (INFO_LEVEL_IS_UNIX(info_level)) {
1594 /* Always do lstat for UNIX calls. */
1595 if (vfs_lstat(conn,fname,&sbuf)) {
1596 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1597 set_bad_path_error(errno, bad_path);
1598 return(UNIXERROR(ERRDOS,ERRbadpath));
1600 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1601 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1602 set_bad_path_error(errno, bad_path);
1603 return(UNIXERROR(ERRDOS,ERRbadpath));
1606 delete_pending = fsp->directory_delete_on_close;
1609 * Original code - this is an open file.
1611 CHECK_FSP(fsp,conn);
1613 pstrcpy(fname, fsp->fsp_name);
1614 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1615 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1616 return(UNIXERROR(ERRDOS,ERRbadfid));
1618 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1619 return(UNIXERROR(ERRDOS,ERRnoaccess));
1621 delete_pending = fsp->delete_on_close;
1625 if (total_params < 6)
1626 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1628 info_level = SVAL(params,0);
1630 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1632 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
1634 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1636 unix_convert(fname,conn,0,&bad_path,&sbuf);
1637 if (!check_name(fname,conn)) {
1638 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1639 set_bad_path_error(errno, bad_path);
1640 return(UNIXERROR(ERRDOS,ERRbadpath));
1643 if (INFO_LEVEL_IS_UNIX(info_level)) {
1644 /* Always do lstat for UNIX calls. */
1645 if (vfs_lstat(conn,fname,&sbuf)) {
1646 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1647 set_bad_path_error(errno, bad_path);
1648 return(UNIXERROR(ERRDOS,ERRbadpath));
1650 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1651 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1652 set_bad_path_error(errno, bad_path);
1653 return(UNIXERROR(ERRDOS,ERRbadpath));
1657 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1658 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1660 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1661 fname,info_level,tran_call,total_data));
1663 p = strrchr_m(fname,'/');
1669 mode = dos_mode(conn,fname,&sbuf);
1670 fullpathname = fname;
1671 file_size = get_file_size(sbuf);
1672 allocation_size = get_allocation_size(fsp,&sbuf);
1676 params = Realloc(*pparams,2);
1678 return ERROR_DOS(ERRDOS,ERRnomem);
1680 memset((char *)params,'\0',2);
1681 data_size = max_data_bytes + 1024;
1682 pdata = Realloc(*ppdata, data_size);
1683 if ( pdata == NULL )
1684 return ERROR_DOS(ERRDOS,ERRnomem);
1687 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1688 /* uggh, EAs for OS2 */
1689 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1690 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1693 memset((char *)pdata,'\0',data_size);
1695 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1697 if (lp_dos_filetime_resolution(SNUM(conn))) {
1699 sbuf.st_atime &= ~1;
1700 sbuf.st_mtime &= ~1;
1701 sbuf.st_mtime &= ~1;
1704 /* NT expects the name to be in an exact form of the *full*
1705 filename. See the trans2 torture test */
1706 if (strequal(base_name,".")) {
1707 pstrcpy(dos_fname, "\\");
1709 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1710 string_replace(dos_fname, '/', '\\');
1713 switch (info_level) {
1714 case SMB_INFO_STANDARD:
1715 case SMB_INFO_QUERY_EA_SIZE:
1716 data_size = (info_level==1?22:26);
1717 put_dos_date2(pdata,l1_fdateCreation,c_time);
1718 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1719 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1720 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1721 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1722 SSVAL(pdata,l1_attrFile,mode);
1723 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1726 case SMB_INFO_QUERY_EAS_FROM_LIST:
1728 put_dos_date2(pdata,0,c_time);
1729 put_dos_date2(pdata,4,sbuf.st_atime);
1730 put_dos_date2(pdata,8,sbuf.st_mtime);
1731 SIVAL(pdata,12,(uint32)file_size);
1732 SIVAL(pdata,16,(uint32)allocation_size);
1733 SIVAL(pdata,20,mode);
1736 case SMB_INFO_QUERY_ALL_EAS:
1738 SIVAL(pdata,0,data_size);
1742 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1744 case SMB_FILE_BASIC_INFORMATION:
1745 case SMB_QUERY_FILE_BASIC_INFO:
1747 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1748 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1753 put_long_date(pdata,c_time);
1754 put_long_date(pdata+8,sbuf.st_atime);
1755 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1756 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1757 SIVAL(pdata,32,mode);
1759 DEBUG(5,("SMB_QFBI - "));
1761 time_t create_time = c_time;
1762 DEBUG(5,("create: %s ", ctime(&create_time)));
1764 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1765 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1766 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1767 DEBUG(5,("mode: %x\n", mode));
1771 case SMB_FILE_STANDARD_INFORMATION:
1772 case SMB_QUERY_FILE_STANDARD_INFO:
1775 SOFF_T(pdata,0,allocation_size);
1776 SOFF_T(pdata,8,file_size);
1777 SIVAL(pdata,16,sbuf.st_nlink);
1779 SCVAL(pdata,21,(mode&aDIR)?1:0);
1782 case SMB_FILE_EA_INFORMATION:
1783 case SMB_QUERY_FILE_EA_INFO:
1787 /* Get the 8.3 name - used if NT SMB was negotiated. */
1788 case SMB_QUERY_FILE_ALT_NAME_INFO:
1792 pstrcpy(short_name,base_name);
1793 /* Mangle if not already 8.3 */
1794 if(!mangle_is_8_3(short_name, True)) {
1795 mangle_map(short_name,True,True,SNUM(conn));
1797 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
1798 data_size = 4 + len;
1803 case SMB_QUERY_FILE_NAME_INFO:
1805 this must be *exactly* right for ACLs on mapped drives to work
1807 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1808 data_size = 4 + len;
1812 case SMB_FILE_ALLOCATION_INFORMATION:
1813 case SMB_QUERY_FILE_ALLOCATION_INFO:
1815 SOFF_T(pdata,0,allocation_size);
1818 case SMB_FILE_END_OF_FILE_INFORMATION:
1819 case SMB_QUERY_FILE_END_OF_FILEINFO:
1821 SOFF_T(pdata,0,file_size);
1824 case SMB_QUERY_FILE_ALL_INFO:
1825 put_long_date(pdata,c_time);
1826 put_long_date(pdata+8,sbuf.st_atime);
1827 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1828 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1829 SIVAL(pdata,32,mode);
1831 SOFF_T(pdata,0,allocation_size);
1832 SOFF_T(pdata,8,file_size);
1833 SIVAL(pdata,16,sbuf.st_nlink);
1834 SCVAL(pdata,20,delete_pending);
1835 SCVAL(pdata,21,(mode&aDIR)?1:0);
1837 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1838 pdata += 8; /* index number */
1839 pdata += 4; /* EA info */
1841 SIVAL(pdata,0,0xA9);
1843 SIVAL(pdata,0,0xd01BF);
1845 SOFF_T(pdata,0,pos); /* current offset */
1847 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1849 pdata += 4; /* alignment */
1850 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1853 data_size = PTR_DIFF(pdata,(*ppdata));
1856 case SMB_FILE_INTERNAL_INFORMATION:
1857 /* This should be an index number - looks like
1860 I think this causes us to fail the IFSKIT
1861 BasicFileInformationTest. -tpot */
1863 SIVAL(pdata,0,sbuf.st_dev);
1864 SIVAL(pdata,4,sbuf.st_ino);
1868 case SMB_FILE_ACCESS_INFORMATION:
1869 SIVAL(pdata,0,0x12019F); /* ??? */
1873 case SMB_FILE_NAME_INFORMATION:
1874 /* Pathname with leading '\'. */
1877 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1878 SIVAL(pdata,0,byte_len);
1879 data_size = 4 + byte_len;
1883 case SMB_FILE_DISPOSITION_INFORMATION:
1885 SCVAL(pdata,0,delete_pending);
1888 case SMB_FILE_POSITION_INFORMATION:
1890 SOFF_T(pdata,0,pos);
1893 case SMB_FILE_MODE_INFORMATION:
1894 SIVAL(pdata,0,mode);
1898 case SMB_FILE_ALIGNMENT_INFORMATION:
1899 SIVAL(pdata,0,0); /* No alignment needed. */
1904 /* Not yet finished... JRA */
1907 put_long_date(pdata,c_time);
1908 put_long_date(pdata+8,sbuf.st_atime);
1909 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1910 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1911 SIVAL(pdata,32,mode);
1912 SIVAL(pdata,36,0); /* ??? */
1913 SIVAL(pdata,40,0x20); /* ??? */
1914 SIVAL(pdata,44,0); /* ??? */
1915 SOFF_T(pdata,48,size);
1916 SIVAL(pdata,56,0x1); /* ??? */
1917 SIVAL(pdata,60,0); /* ??? */
1918 SIVAL(pdata,64,0); /* ??? */
1919 SIVAL(pdata,68,length); /* Following string length in bytes. */
1920 dos_PutUniCode(pdata+72,,False);
1925 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1926 /* Last component of pathname. */
1928 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1929 SIVAL(pdata,0,byte_len);
1930 data_size = 4 + byte_len;
1936 * NT4 server just returns "invalid query" to this - if we try to answer
1937 * it then NTws gets a BSOD! (tridge).
1938 * W2K seems to want this. JRA.
1940 case SMB_QUERY_FILE_STREAM_INFO:
1942 case SMB_FILE_STREAM_INFORMATION:
1946 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1947 SIVAL(pdata,0,0); /* ??? */
1948 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1949 SOFF_T(pdata,8,file_size);
1950 SIVAL(pdata,16,allocation_size);
1951 SIVAL(pdata,20,0); /* ??? */
1952 data_size = 24 + byte_len;
1956 case SMB_FILE_COMPRESSION_INFORMATION:
1957 SOFF_T(pdata,0,allocation_size);
1958 SIVAL(pdata,8,0); /* ??? */
1959 SIVAL(pdata,12,0); /* ??? */
1963 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1964 put_long_date(pdata,c_time);
1965 put_long_date(pdata+8,sbuf.st_atime);
1966 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1967 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1968 SIVAL(pdata,32,allocation_size);
1969 SOFF_T(pdata,40,file_size);
1970 SIVAL(pdata,48,mode);
1971 SIVAL(pdata,52,0); /* ??? */
1975 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1976 SIVAL(pdata,0,mode);
1982 * CIFS UNIX Extensions.
1985 case SMB_QUERY_FILE_UNIX_BASIC:
1987 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1989 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
1992 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1995 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
1996 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
1997 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2000 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2004 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2008 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2011 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2015 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2019 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2022 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2026 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2029 data_size = PTR_DIFF(pdata,(*ppdata));
2033 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2035 for (i=0; i<100; i++)
2036 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2042 case SMB_QUERY_FILE_UNIX_LINK:
2047 if(!S_ISLNK(sbuf.st_mode))
2048 return(UNIXERROR(ERRSRV,ERRbadlink));
2050 return(UNIXERROR(ERRDOS,ERRbadlink));
2052 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2054 return(UNIXERROR(ERRDOS,ERRnoaccess));
2056 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2058 data_size = PTR_DIFF(pdata,(*ppdata));
2064 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2067 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2072 /****************************************************************************
2073 Deal with the internal needs of setting the delete on close flag. Note that
2074 as the tdb locking is recursive, it is safe to call this from within
2075 open_file_shared. JRA.
2076 ****************************************************************************/
2078 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2081 * Only allow delete on close for writable shares.
2084 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2085 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2087 return NT_STATUS_ACCESS_DENIED;
2090 * Only allow delete on close for files/directories opened with delete intent.
2093 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2094 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2096 return NT_STATUS_ACCESS_DENIED;
2099 if(fsp->is_directory) {
2100 fsp->directory_delete_on_close = delete_on_close;
2101 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2102 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2104 fsp->delete_on_close = delete_on_close;
2105 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2106 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2109 return NT_STATUS_OK;
2112 /****************************************************************************
2113 Sets the delete on close flag over all share modes on this file.
2114 Modify the share mode entry for all files open
2115 on this device and inode to tell other smbds we have
2116 changed the delete on close flag. This will be noticed
2117 in the close code, the last closer will delete the file
2119 ****************************************************************************/
2121 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2123 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2124 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2126 if (lock_share_entry_fsp(fsp) == False)
2127 return NT_STATUS_ACCESS_DENIED;
2129 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2130 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2132 unlock_share_entry_fsp(fsp);
2133 return NT_STATUS_ACCESS_DENIED;
2136 unlock_share_entry_fsp(fsp);
2137 return NT_STATUS_OK;
2140 /****************************************************************************
2141 Returns true if this pathname is within the share, and thus safe.
2142 ****************************************************************************/
2144 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2147 char resolved_name[PATH_MAX+1];
2149 pstring resolved_name;
2151 fstring last_component;
2155 BOOL bad_path = False;
2156 SMB_STRUCT_STAT sbuf;
2158 pstrcpy(link_dest, link_dest_in);
2159 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2161 /* Store the UNIX converted path. */
2162 pstrcpy(link_dest_out, link_dest);
2164 p = strrchr(link_dest, '/');
2166 fstrcpy(last_component, p+1);
2169 fstrcpy(last_component, link_dest);
2170 pstrcpy(link_dest, "./");
2173 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2176 pstrcpy(link_dest, resolved_name);
2177 pstrcat(link_dest, "/");
2178 pstrcat(link_dest, last_component);
2180 if (*link_dest != '/') {
2181 /* Relative path. */
2182 pstrcpy(link_test, conn->connectpath);
2183 pstrcat(link_test, "/");
2184 pstrcat(link_test, link_dest);
2186 pstrcpy(link_test, link_dest);
2190 * Check if the link is within the share.
2193 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2200 /****************************************************************************
2201 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2202 ****************************************************************************/
2204 static int call_trans2setfilepathinfo(connection_struct *conn,
2205 char *inbuf, char *outbuf, int length, int bufsize,
2206 char **pparams, int total_params, char **ppdata, int total_data)
2208 char *params = *pparams;
2209 char *pdata = *ppdata;
2210 uint16 tran_call = SVAL(inbuf, smb_setup0);
2215 SMB_STRUCT_STAT sbuf;
2218 BOOL bad_path = False;
2219 files_struct *fsp = NULL;
2220 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2221 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2222 mode_t unixmode = 0;
2224 if (tran_call == TRANSACT2_SETFILEINFO) {
2225 fsp = file_fsp(params,0);
2226 info_level = SVAL(params,2);
2228 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2230 * This is actually a SETFILEINFO on a directory
2231 * handle (returned from an NT SMB). NT5.0 seems
2232 * to do this call. JRA.
2234 pstrcpy(fname, fsp->fsp_name);
2235 unix_convert(fname,conn,0,&bad_path,&sbuf);
2236 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2237 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2238 set_bad_path_error(errno, bad_path);
2239 return(UNIXERROR(ERRDOS,ERRbadpath));
2241 } else if (fsp && fsp->print_file) {
2243 * Doing a DELETE_ON_CLOSE should cancel a print job.
2245 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2246 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2248 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2251 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2254 return (UNIXERROR(ERRDOS,ERRbadpath));
2257 * Original code - this is an open file.
2259 CHECK_FSP(fsp,conn);
2261 pstrcpy(fname, fsp->fsp_name);
2264 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2265 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2266 return(UNIXERROR(ERRDOS,ERRbadfid));
2271 if (total_params < 6)
2272 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2274 info_level = SVAL(params,0);
2275 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2276 unix_convert(fname,conn,0,&bad_path,&sbuf);
2277 if(!check_name(fname, conn)) {
2278 set_bad_path_error(errno, bad_path);
2279 return(UNIXERROR(ERRDOS,ERRbadpath));
2283 * For CIFS UNIX extensions the target name may not exist.
2286 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2287 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2288 set_bad_path_error(errno, bad_path);
2289 return(UNIXERROR(ERRDOS,ERRbadpath));
2293 if (!CAN_WRITE(conn))
2294 return ERROR_DOS(ERRSRV,ERRaccess);
2296 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2297 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2299 if (VALID_STAT(sbuf))
2300 unixmode = sbuf.st_mode;
2302 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2303 tran_call,fname,info_level,total_data));
2305 /* Realloc the parameter and data sizes */
2306 params = Realloc(*pparams,2);
2308 return ERROR_DOS(ERRDOS,ERRnomem);
2314 /* the pending modtime overrides the current modtime */
2315 sbuf.st_mtime = fsp->pending_modtime;
2318 size = get_file_size(sbuf);
2319 tvs.modtime = sbuf.st_mtime;
2320 tvs.actime = sbuf.st_atime;
2321 dosmode = dos_mode(conn,fname,&sbuf);
2322 unixmode = sbuf.st_mode;
2324 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2325 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2327 switch (info_level) {
2328 case SMB_INFO_STANDARD:
2330 if (total_data < l1_cbFile+4)
2331 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2334 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2337 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2339 dosmode = SVAL(pdata,l1_attrFile);
2340 size = IVAL(pdata,l1_cbFile);
2345 case SMB_INFO_SET_EA:
2346 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2348 /* XXXX um, i don't think this is right.
2349 it's also not in the cifs6.txt spec.
2351 case SMB_INFO_QUERY_EAS_FROM_LIST:
2352 if (total_data < 28)
2353 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2355 tvs.actime = make_unix_date2(pdata+8);
2356 tvs.modtime = make_unix_date2(pdata+12);
2357 size = IVAL(pdata,16);
2358 dosmode = IVAL(pdata,24);
2361 /* XXXX nor this. not in cifs6.txt, either. */
2362 case SMB_INFO_QUERY_ALL_EAS:
2363 if (total_data < 28)
2364 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2366 tvs.actime = make_unix_date2(pdata+8);
2367 tvs.modtime = make_unix_date2(pdata+12);
2368 size = IVAL(pdata,16);
2369 dosmode = IVAL(pdata,24);
2372 case SMB_SET_FILE_BASIC_INFO:
2373 case SMB_FILE_BASIC_INFORMATION:
2375 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2377 time_t changed_time;
2379 if (total_data < 36)
2380 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2382 /* Ignore create time at offset pdata. */
2385 tvs.actime = interpret_long_date(pdata+8);
2387 write_time = interpret_long_date(pdata+16);
2388 changed_time = interpret_long_date(pdata+24);
2390 tvs.modtime = MIN(write_time, changed_time);
2392 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2393 tvs.modtime = write_time;
2395 /* Prefer a defined time to an undefined one. */
2396 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2397 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2398 ? changed_time : write_time);
2401 dosmode = IVAL(pdata,32);
2405 case SMB_FILE_ALLOCATION_INFORMATION:
2406 case SMB_SET_FILE_ALLOCATION_INFO:
2409 SMB_BIG_UINT allocation_size;
2412 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2414 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2415 #ifdef LARGE_SMB_OFF_T
2416 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2417 #else /* LARGE_SMB_OFF_T */
2418 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2419 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2420 #endif /* LARGE_SMB_OFF_T */
2421 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2422 fname, (double)allocation_size ));
2424 if (allocation_size)
2425 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2427 if(allocation_size != get_file_size(sbuf)) {
2428 SMB_STRUCT_STAT new_sbuf;
2430 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2431 fname, (double)allocation_size ));
2434 files_struct *new_fsp = NULL;
2435 int access_mode = 0;
2438 if(global_oplock_break) {
2439 /* Queue this file modify as we are the process of an oplock break. */
2441 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2442 DEBUGADD(2,( "in oplock break state.\n"));
2444 push_oplock_pending_smb_message(inbuf, length);
2448 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2449 SET_OPEN_MODE(DOS_OPEN_RDWR),
2450 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2451 0, 0, &access_mode, &action);
2453 if (new_fsp == NULL)
2454 return(UNIXERROR(ERRDOS,ERRbadpath));
2455 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2456 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2457 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2458 new_fsp->fnum, strerror(errno)));
2461 close_file(new_fsp,True);
2463 ret = vfs_allocate_file_space(fsp, allocation_size);
2464 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2465 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2466 fsp->fnum, strerror(errno)));
2471 return ERROR_NT(NT_STATUS_DISK_FULL);
2473 /* Allocate can truncate size... */
2474 size = get_file_size(new_sbuf);
2480 case SMB_FILE_END_OF_FILE_INFORMATION:
2481 case SMB_SET_FILE_END_OF_FILE_INFO:
2484 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2486 size = IVAL(pdata,0);
2487 #ifdef LARGE_SMB_OFF_T
2488 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2489 #else /* LARGE_SMB_OFF_T */
2490 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2491 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2492 #endif /* LARGE_SMB_OFF_T */
2493 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2497 case SMB_FILE_DISPOSITION_INFORMATION:
2498 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2500 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2504 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2506 if (tran_call != TRANSACT2_SETFILEINFO)
2507 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2510 return(UNIXERROR(ERRDOS,ERRbadfid));
2512 status = set_delete_on_close_internal(fsp, delete_on_close);
2514 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2515 return ERROR_NT(status);
2517 /* The set is across all open files on this dev/inode pair. */
2518 status =set_delete_on_close_over_all(fsp, delete_on_close);
2519 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2520 return ERROR_NT(status);
2526 * CIFS UNIX extensions.
2529 case SMB_SET_FILE_UNIX_BASIC:
2531 uint32 raw_unixmode;
2533 if (total_data < 100)
2534 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2536 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2537 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2538 size=IVAL(pdata,0); /* first 8 Bytes are size */
2539 #ifdef LARGE_SMB_OFF_T
2540 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2541 #else /* LARGE_SMB_OFF_T */
2542 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2543 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2544 #endif /* LARGE_SMB_OFF_T */
2546 pdata+=24; /* ctime & st_blocks are not changed */
2547 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2548 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2550 set_owner = (uid_t)IVAL(pdata,0);
2552 set_grp = (gid_t)IVAL(pdata,0);
2554 raw_unixmode = IVAL(pdata,28);
2555 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2556 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2558 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2559 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2560 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2562 if (!VALID_STAT(sbuf)) {
2565 * The only valid use of this is to create character and block
2566 * devices, and named pipes. This is deprecated (IMHO) and
2567 * a new info level should be used for mknod. JRA.
2570 #if !defined(HAVE_MAKEDEV_FN)
2571 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2572 #else /* HAVE_MAKEDEV_FN */
2573 uint32 file_type = IVAL(pdata,0);
2574 uint32 dev_major = IVAL(pdata,4);
2575 uint32 dev_minor = IVAL(pdata,12);
2577 uid_t myuid = geteuid();
2578 gid_t mygid = getegid();
2581 if (tran_call == TRANSACT2_SETFILEINFO)
2582 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2584 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2585 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2587 dev = makedev(dev_major, dev_minor);
2589 /* We can only create as the owner/group we are. */
2591 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2592 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2593 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2594 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2596 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2597 file_type != UNIX_TYPE_FIFO)
2598 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2600 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2601 0%o for file %s\n", (double)dev, unixmode, fname ));
2603 /* Ok - do the mknod. */
2604 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2605 return(UNIXERROR(ERRDOS,ERRnoaccess));
2607 inherit_access_acl(conn, fname, unixmode);
2610 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2612 #endif /* HAVE_MAKEDEV_FN */
2617 * Deal with the UNIX specific mode set.
2620 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2621 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2622 (unsigned int)unixmode, fname ));
2623 if (vfs_chmod(conn,fname,unixmode) != 0)
2624 return(UNIXERROR(ERRDOS,ERRnoaccess));
2628 * Deal with the UNIX specific uid set.
2631 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2632 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2633 (unsigned int)set_owner, fname ));
2634 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2635 return(UNIXERROR(ERRDOS,ERRnoaccess));
2639 * Deal with the UNIX specific gid set.
2642 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2643 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2644 (unsigned int)set_owner, fname ));
2645 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2646 return(UNIXERROR(ERRDOS,ERRnoaccess));
2651 case SMB_SET_FILE_UNIX_LINK:
2654 /* Set a symbolic link. */
2655 /* Don't allow this if follow links is false. */
2657 if (!lp_symlinks(SNUM(conn)))
2658 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2660 /* Disallow if already exists. */
2661 if (VALID_STAT(sbuf))
2662 return(ERROR_DOS(ERRDOS,ERRbadpath));
2664 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2666 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2667 return(UNIXERROR(ERRDOS,ERRnoaccess));
2669 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2670 fname, link_dest ));
2672 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2673 return(UNIXERROR(ERRDOS,ERRnoaccess));
2675 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2679 case SMB_SET_FILE_UNIX_HLINK:
2683 /* Set a hard link. */
2685 /* Disallow if already exists. */
2686 if (VALID_STAT(sbuf))
2687 return(ERROR_DOS(ERRDOS,ERRbadpath));
2689 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2691 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2692 return(UNIXERROR(ERRDOS,ERRnoaccess));
2694 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2695 fname, link_dest ));
2697 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2698 return(UNIXERROR(ERRDOS,ERRnoaccess));
2700 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2705 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2708 /* get some defaults (no modifications) if any info is zero or -1. */
2709 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2710 tvs.actime = sbuf.st_atime;
2712 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2713 tvs.modtime = sbuf.st_mtime;
2715 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2716 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2717 DEBUG(6,("size: %.0f ", (double)size));
2719 if (S_ISDIR(sbuf.st_mode))
2724 DEBUG(6,("dosmode: %x\n" , dosmode));
2726 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2727 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2728 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2729 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2732 * Only do this test if we are not explicitly
2733 * changing the size of a file.
2736 size = get_file_size(sbuf);
2740 * Try and set the times, size and mode of this file -
2741 * if they are different from the current values
2743 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2746 * This was a setfileinfo on an open file.
2747 * NT does this a lot. It's actually pointless
2748 * setting the time here, as it will be overwritten
2749 * on the next write, so we save the request
2750 * away and will set it on file close. JRA.
2753 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2754 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2755 fsp->pending_modtime = tvs.modtime;
2760 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2762 if(file_utime(conn, fname, &tvs)!=0)
2763 return(UNIXERROR(ERRDOS,ERRnoaccess));
2767 /* check the mode isn't different, before changing it */
2768 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2770 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2772 if(file_chmod(conn, fname, dosmode, NULL)) {
2773 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2774 return(UNIXERROR(ERRDOS,ERRnoaccess));
2778 if (size != get_file_size(sbuf)) {
2782 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2783 fname, (double)size ));
2786 files_struct *new_fsp = NULL;
2787 int access_mode = 0;
2790 if(global_oplock_break) {
2791 /* Queue this file modify as we are the process of an oplock break. */
2793 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2794 DEBUGADD(2,( "in oplock break state.\n"));
2796 push_oplock_pending_smb_message(inbuf, length);
2800 new_fsp = open_file_shared(conn, fname, &sbuf,
2801 SET_OPEN_MODE(DOS_OPEN_RDWR),
2802 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2803 0, 0, &access_mode, &action);
2805 if (new_fsp == NULL)
2806 return(UNIXERROR(ERRDOS,ERRbadpath));
2807 ret = vfs_set_filelen(new_fsp, size);
2808 close_file(new_fsp,True);
2810 ret = vfs_set_filelen(fsp, size);
2814 return (UNIXERROR(ERRHRD,ERRdiskfull));
2818 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2823 /****************************************************************************
2824 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2825 ****************************************************************************/
2827 static int call_trans2mkdir(connection_struct *conn,
2828 char *inbuf, char *outbuf, int length, int bufsize,
2829 char **pparams, int total_params, char **ppdata, int total_data)
2831 char *params = *pparams;
2834 SMB_STRUCT_STAT sbuf;
2835 BOOL bad_path = False;
2837 if (!CAN_WRITE(conn))
2838 return ERROR_DOS(ERRSRV,ERRaccess);
2840 if (total_params < 4)
2841 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2843 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2845 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2847 unix_convert(directory,conn,0,&bad_path,&sbuf);
2848 if (check_name(directory,conn))
2849 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2852 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2853 set_bad_path_error(errno, bad_path);
2854 return(UNIXERROR(ERRDOS,ERRnoaccess));
2857 /* Realloc the parameter and data sizes */
2858 params = Realloc(*pparams,2);
2860 return ERROR_DOS(ERRDOS,ERRnomem);
2865 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2870 /****************************************************************************
2871 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2872 We don't actually do this - we just send a null response.
2873 ****************************************************************************/
2875 static int call_trans2findnotifyfirst(connection_struct *conn,
2876 char *inbuf, char *outbuf, int length, int bufsize,
2877 char **pparams, int total_params, char **ppdata, int total_data)
2879 static uint16 fnf_handle = 257;
2880 char *params = *pparams;
2883 if (total_params < 6)
2884 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2886 info_level = SVAL(params,4);
2887 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2889 switch (info_level) {
2894 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2897 /* Realloc the parameter and data sizes */
2898 params = Realloc(*pparams,6);
2900 return ERROR_DOS(ERRDOS,ERRnomem);
2903 SSVAL(params,0,fnf_handle);
2904 SSVAL(params,2,0); /* No changes */
2905 SSVAL(params,4,0); /* No EA errors */
2912 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2917 /****************************************************************************
2918 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2919 changes). Currently this does nothing.
2920 ****************************************************************************/
2922 static int call_trans2findnotifynext(connection_struct *conn,
2923 char *inbuf, char *outbuf, int length, int bufsize,
2924 char **pparams, int total_params, char **ppdata, int total_data)
2926 char *params = *pparams;
2928 DEBUG(3,("call_trans2findnotifynext\n"));
2930 /* Realloc the parameter and data sizes */
2931 params = Realloc(*pparams,4);
2933 return ERROR_DOS(ERRDOS,ERRnomem);
2936 SSVAL(params,0,0); /* No changes */
2937 SSVAL(params,2,0); /* No EA errors */
2939 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2944 /****************************************************************************
2945 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2946 ****************************************************************************/
2948 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2949 char* outbuf, int length, int bufsize,
2950 char **pparams, int total_params, char **ppdata, int total_data)
2952 char *params = *pparams;
2955 int max_referral_level;
2957 DEBUG(10,("call_trans2getdfsreferral\n"));
2959 if (total_params < 2)
2960 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2962 max_referral_level = SVAL(params,0);
2964 if(!lp_host_msdfs())
2965 return ERROR_DOS(ERRDOS,ERRbadfunc);
2967 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2969 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2970 return ERROR_DOS(ERRDOS,ERRbadfile);
2972 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2973 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2978 #define LMCAT_SPL 0x53
2979 #define LMFUNC_GETJOBID 0x60
2981 /****************************************************************************
2982 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2983 ****************************************************************************/
2985 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2986 char* outbuf, int length, int bufsize,
2987 char **pparams, int total_params, char **ppdata, int total_data)
2989 char *pdata = *ppdata;
2990 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2992 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2993 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2994 pdata = Realloc(*ppdata, 32);
2996 return ERROR_DOS(ERRDOS,ERRnomem);
2999 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3000 CAN ACCEPT THIS IN UNICODE. JRA. */
3002 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3003 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3004 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3005 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3008 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3009 return ERROR_DOS(ERRSRV,ERRerror);
3013 /****************************************************************************
3014 Reply to a SMBfindclose (stop trans2 directory search).
3015 ****************************************************************************/
3017 int reply_findclose(connection_struct *conn,
3018 char *inbuf,char *outbuf,int length,int bufsize)
3021 int dptr_num=SVALS(inbuf,smb_vwv0);
3022 START_PROFILE(SMBfindclose);
3024 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3026 dptr_close(&dptr_num);
3028 outsize = set_message(outbuf,0,0,True);
3030 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3032 END_PROFILE(SMBfindclose);
3036 /****************************************************************************
3037 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3038 ****************************************************************************/
3040 int reply_findnclose(connection_struct *conn,
3041 char *inbuf,char *outbuf,int length,int bufsize)
3045 START_PROFILE(SMBfindnclose);
3047 dptr_num = SVAL(inbuf,smb_vwv0);
3049 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3051 /* We never give out valid handles for a
3052 findnotifyfirst - so any dptr_num is ok here.
3055 outsize = set_message(outbuf,0,0,True);
3057 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3059 END_PROFILE(SMBfindnclose);
3063 /****************************************************************************
3064 Reply to a SMBtranss2 - just ignore it!
3065 ****************************************************************************/
3067 int reply_transs2(connection_struct *conn,
3068 char *inbuf,char *outbuf,int length,int bufsize)
3070 START_PROFILE(SMBtranss2);
3071 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3072 END_PROFILE(SMBtranss2);
3076 /****************************************************************************
3077 Reply to a SMBtrans2.
3078 ****************************************************************************/
3080 int reply_trans2(connection_struct *conn,
3081 char *inbuf,char *outbuf,int length,int bufsize)
3084 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3085 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3087 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3088 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3089 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3090 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3091 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3092 int32 timeout = IVALS(inbuf,smb_timeout);
3094 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3095 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3096 char *params = NULL, *data = NULL;
3097 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3098 START_PROFILE(SMBtrans2);
3100 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3101 /* Queue this open message as we are the process of an
3104 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3105 DEBUGADD(2,( "in oplock break state.\n"));
3107 push_oplock_pending_smb_message(inbuf, length);
3108 END_PROFILE(SMBtrans2);
3112 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3113 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3114 END_PROFILE(SMBtrans2);
3115 return ERROR_DOS(ERRSRV,ERRaccess);
3118 outsize = set_message(outbuf,0,0,True);
3120 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3121 is so as a sanity check */
3124 * Need to have rc=0 for ioctl to get job id for OS/2.
3125 * Network printing will fail if function is not successful.
3126 * Similar function in reply.c will be used if protocol
3127 * is LANMAN1.0 instead of LM1.2X002.
3128 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3129 * outbuf doesn't have to be set(only job id is used).
3131 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3132 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3133 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3134 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3136 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3137 DEBUG(2,("Transaction is %d\n",tran_call));
3138 END_PROFILE(SMBtrans2);
3139 ERROR_DOS(ERRDOS,ERRinvalidparam);
3143 /* Allocate the space for the maximum needed parameters and data */
3144 if (total_params > 0)
3145 params = (char *)malloc(total_params);
3147 data = (char *)malloc(total_data);
3149 if ((total_params && !params) || (total_data && !data)) {
3150 DEBUG(2,("Out of memory in reply_trans2\n"));
3153 END_PROFILE(SMBtrans2);
3154 return ERROR_DOS(ERRDOS,ERRnomem);
3157 /* Copy the param and data bytes sent with this request into
3158 the params buffer */
3159 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3160 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3162 if (num_params > total_params || num_data > total_data)
3163 exit_server("invalid params in reply_trans2");
3166 unsigned int psoff = SVAL(inbuf, smb_psoff);
3167 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3169 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3171 memcpy( params, smb_base(inbuf) + psoff, num_params);
3174 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3175 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3177 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3179 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3182 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3183 /* We need to send an interim response then receive the rest
3184 of the parameter/data bytes */
3185 outsize = set_message(outbuf,0,0,True);
3186 if (!send_smb(smbd_server_fd(),outbuf))
3187 exit_server("reply_trans2: send_smb failed.");
3189 while (num_data_sofar < total_data ||
3190 num_params_sofar < total_params) {
3192 unsigned int param_disp;
3193 unsigned int param_off;
3194 unsigned int data_disp;
3195 unsigned int data_off;
3197 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3200 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3201 outsize = set_message(outbuf,0,0,True);
3203 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3205 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3206 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3210 /* Revise total_params and total_data in case
3211 they have changed downwards */
3212 if (SVAL(inbuf, smb_tpscnt) < total_params)
3213 total_params = SVAL(inbuf, smb_tpscnt);
3214 if (SVAL(inbuf, smb_tdscnt) < total_data)
3215 total_data = SVAL(inbuf, smb_tdscnt);
3217 num_params = SVAL(inbuf,smb_spscnt);
3218 param_off = SVAL(inbuf, smb_spsoff);
3219 param_disp = SVAL(inbuf, smb_spsdisp);
3220 num_params_sofar += num_params;
3222 num_data = SVAL(inbuf, smb_sdscnt);
3223 data_off = SVAL(inbuf, smb_sdsoff);
3224 data_disp = SVAL(inbuf, smb_sdsdisp);
3225 num_data_sofar += num_data;
3227 if (num_params_sofar > total_params || num_data_sofar > total_data)
3231 if (param_disp + num_params >= total_params)
3233 if ((param_disp + num_params < param_disp) ||
3234 (param_disp + num_params < num_params))
3236 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3238 if (params + param_disp < params)
3241 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
3244 if (data_disp + num_data >= total_data)
3246 if ((data_disp + num_data < data_disp) ||
3247 (data_disp + num_data < num_data))
3249 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3251 if (data + data_disp < data)
3254 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3259 if (Protocol >= PROTOCOL_NT1) {
3260 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3263 /* Now we must call the relevant TRANS2 function */
3265 case TRANSACT2_OPEN:
3266 START_PROFILE_NESTED(Trans2_open);
3267 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3268 ¶ms, total_params, &data, total_data);
3269 END_PROFILE_NESTED(Trans2_open);
3272 case TRANSACT2_FINDFIRST:
3273 START_PROFILE_NESTED(Trans2_findfirst);
3274 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3275 ¶ms, total_params, &data, total_data);
3276 END_PROFILE_NESTED(Trans2_findfirst);
3279 case TRANSACT2_FINDNEXT:
3280 START_PROFILE_NESTED(Trans2_findnext);
3281 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3282 ¶ms, total_params, &data, total_data);
3283 END_PROFILE_NESTED(Trans2_findnext);
3286 case TRANSACT2_QFSINFO:
3287 START_PROFILE_NESTED(Trans2_qfsinfo);
3288 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3289 ¶ms, total_params, &data, total_data);
3290 END_PROFILE_NESTED(Trans2_qfsinfo);
3293 case TRANSACT2_SETFSINFO:
3294 START_PROFILE_NESTED(Trans2_setfsinfo);
3295 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3296 ¶ms, total_params, &data, total_data);
3297 END_PROFILE_NESTED(Trans2_setfsinfo);
3300 case TRANSACT2_QPATHINFO:
3301 case TRANSACT2_QFILEINFO:
3302 START_PROFILE_NESTED(Trans2_qpathinfo);
3303 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3304 ¶ms, total_params, &data, total_data);
3305 END_PROFILE_NESTED(Trans2_qpathinfo);
3307 case TRANSACT2_SETPATHINFO:
3308 case TRANSACT2_SETFILEINFO:
3309 START_PROFILE_NESTED(Trans2_setpathinfo);
3310 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3311 ¶ms, total_params, &data, total_data);
3312 END_PROFILE_NESTED(Trans2_setpathinfo);
3315 case TRANSACT2_FINDNOTIFYFIRST:
3316 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3317 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3318 ¶ms, total_params, &data, total_data);
3319 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3322 case TRANSACT2_FINDNOTIFYNEXT:
3323 START_PROFILE_NESTED(Trans2_findnotifynext);
3324 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3325 ¶ms, total_params, &data, total_data);
3326 END_PROFILE_NESTED(Trans2_findnotifynext);
3328 case TRANSACT2_MKDIR:
3329 START_PROFILE_NESTED(Trans2_mkdir);
3330 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3331 ¶ms, total_params, &data, total_data);
3332 END_PROFILE_NESTED(Trans2_mkdir);
3335 case TRANSACT2_GET_DFS_REFERRAL:
3336 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3337 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3338 ¶ms, total_params, &data, total_data);
3339 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3341 case TRANSACT2_IOCTL:
3342 START_PROFILE_NESTED(Trans2_ioctl);
3343 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3344 ¶ms, total_params, &data, total_data);
3345 END_PROFILE_NESTED(Trans2_ioctl);
3348 /* Error in request */
3349 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3352 END_PROFILE(SMBtrans2);
3353 return ERROR_DOS(ERRSRV,ERRerror);
3356 /* As we do not know how many data packets will need to be
3357 returned here the various call_trans2xxxx calls
3358 must send their own. Thus a call_trans2xxx routine only
3359 returns a value other than -1 when it wants to send
3365 END_PROFILE(SMBtrans2);
3366 return outsize; /* If a correct response was needed the
3367 call_trans2xxx calls have already sent
3368 it. If outsize != -1 then it is returning */
3374 END_PROFILE(SMBtrans2);
3375 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);