ufs_vnops.c revision 92462
1/* 2 * Copyright (c) 1982, 1986, 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 39 * $FreeBSD: head/sys/ufs/ufs/ufs_vnops.c 92462 2002-03-17 01:25:47Z mckusick $ 40 */ 41 42#include "opt_quota.h" 43#include "opt_suiddir.h" 44#include "opt_ufs.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/namei.h> 49#include <sys/kernel.h> 50#include <sys/fcntl.h> 51#include <sys/stat.h> 52#include <sys/bio.h> 53#include <sys/buf.h> 54#include <sys/mount.h> 55#include <sys/unistd.h> 56#include <sys/malloc.h> 57#include <sys/vnode.h> 58#include <sys/dirent.h> 59#include <sys/lockf.h> 60#include <sys/event.h> 61#include <sys/conf.h> 62#include <sys/acl.h> 63 64#include <machine/mutex.h> 65 66#include <sys/file.h> /* XXX */ 67 68#include <vm/vm.h> 69#include <vm/vm_extern.h> 70 71#include <fs/fifofs/fifo.h> 72 73#include <ufs/ufs/acl.h> 74#include <ufs/ufs/extattr.h> 75#include <ufs/ufs/quota.h> 76#include <ufs/ufs/inode.h> 77#include <ufs/ufs/dir.h> 78#include <ufs/ufs/ufsmount.h> 79#include <ufs/ufs/ufs_extern.h> 80#ifdef UFS_DIRHASH 81#include <ufs/ufs/dirhash.h> 82#endif 83 84static int ufs_access __P((struct vop_access_args *)); 85static int ufs_advlock __P((struct vop_advlock_args *)); 86static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct thread *)); 87static int ufs_chown __P((struct vnode *, uid_t, gid_t, struct ucred *, struct thread *)); 88static int ufs_close __P((struct vop_close_args *)); 89static int ufs_create __P((struct vop_create_args *)); 90static int ufs_getattr __P((struct vop_getattr_args *)); 91static int ufs_link __P((struct vop_link_args *)); 92static int ufs_makeinode __P((int mode, struct vnode *, struct vnode **, struct componentname *)); 93static int ufs_missingop __P((struct vop_generic_args *ap)); 94static int ufs_mkdir __P((struct vop_mkdir_args *)); 95static int ufs_mknod __P((struct vop_mknod_args *)); 96static int ufs_open __P((struct vop_open_args *)); 97static int ufs_pathconf __P((struct vop_pathconf_args *)); 98static int ufs_print __P((struct vop_print_args *)); 99static int ufs_readlink __P((struct vop_readlink_args *)); 100static int ufs_remove __P((struct vop_remove_args *)); 101static int ufs_rename __P((struct vop_rename_args *)); 102static int ufs_rmdir __P((struct vop_rmdir_args *)); 103static int ufs_setattr __P((struct vop_setattr_args *)); 104static int ufs_strategy __P((struct vop_strategy_args *)); 105static int ufs_symlink __P((struct vop_symlink_args *)); 106static int ufs_whiteout __P((struct vop_whiteout_args *)); 107static int ufsfifo_close __P((struct vop_close_args *)); 108static int ufsfifo_kqfilter __P((struct vop_kqfilter_args *)); 109static int ufsfifo_read __P((struct vop_read_args *)); 110static int ufsfifo_write __P((struct vop_write_args *)); 111static int ufsspec_close __P((struct vop_close_args *)); 112static int ufsspec_read __P((struct vop_read_args *)); 113static int ufsspec_write __P((struct vop_write_args *)); 114static int filt_ufsread __P((struct knote *kn, long hint)); 115static int filt_ufswrite __P((struct knote *kn, long hint)); 116static int filt_ufsvnode __P((struct knote *kn, long hint)); 117static void filt_ufsdetach __P((struct knote *kn)); 118static int ufs_kqfilter __P((struct vop_kqfilter_args *ap)); 119 120union _qcvt { 121 int64_t qcvt; 122 int32_t val[2]; 123}; 124#define SETHIGH(q, h) { \ 125 union _qcvt tmp; \ 126 tmp.qcvt = (q); \ 127 tmp.val[_QUAD_HIGHWORD] = (h); \ 128 (q) = tmp.qcvt; \ 129} 130#define SETLOW(q, l) { \ 131 union _qcvt tmp; \ 132 tmp.qcvt = (q); \ 133 tmp.val[_QUAD_LOWWORD] = (l); \ 134 (q) = tmp.qcvt; \ 135} 136 137/* 138 * A virgin directory (no blushing please). 139 */ 140static struct dirtemplate mastertemplate = { 141 0, 12, DT_DIR, 1, ".", 142 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." 143}; 144static struct odirtemplate omastertemplate = { 145 0, 12, 1, ".", 146 0, DIRBLKSIZ - 12, 2, ".." 147}; 148 149void 150ufs_itimes(vp) 151 struct vnode *vp; 152{ 153 struct inode *ip; 154 struct timespec ts; 155 156 ip = VTOI(vp); 157 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) 158 return; 159 if ((vp->v_type == VBLK || vp->v_type == VCHR) && !DOINGSOFTDEP(vp)) 160 ip->i_flag |= IN_LAZYMOD; 161 else 162 ip->i_flag |= IN_MODIFIED; 163 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 164 vfs_timestamp(&ts); 165 if (ip->i_flag & IN_ACCESS) { 166 ip->i_atime = ts.tv_sec; 167 ip->i_atimensec = ts.tv_nsec; 168 } 169 if (ip->i_flag & IN_UPDATE) { 170 ip->i_mtime = ts.tv_sec; 171 ip->i_mtimensec = ts.tv_nsec; 172 ip->i_modrev++; 173 } 174 if (ip->i_flag & IN_CHANGE) { 175 ip->i_ctime = ts.tv_sec; 176 ip->i_ctimensec = ts.tv_nsec; 177 } 178 } 179 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); 180} 181 182/* 183 * Create a regular file 184 */ 185int 186ufs_create(ap) 187 struct vop_create_args /* { 188 struct vnode *a_dvp; 189 struct vnode **a_vpp; 190 struct componentname *a_cnp; 191 struct vattr *a_vap; 192 } */ *ap; 193{ 194 int error; 195 196 error = 197 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), 198 ap->a_dvp, ap->a_vpp, ap->a_cnp); 199 if (error) 200 return (error); 201 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 202 return (0); 203} 204 205/* 206 * Mknod vnode call 207 */ 208/* ARGSUSED */ 209int 210ufs_mknod(ap) 211 struct vop_mknod_args /* { 212 struct vnode *a_dvp; 213 struct vnode **a_vpp; 214 struct componentname *a_cnp; 215 struct vattr *a_vap; 216 } */ *ap; 217{ 218 struct vattr *vap = ap->a_vap; 219 struct vnode **vpp = ap->a_vpp; 220 struct inode *ip; 221 ino_t ino; 222 int error; 223 224 error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), 225 ap->a_dvp, vpp, ap->a_cnp); 226 if (error) 227 return (error); 228 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 229 ip = VTOI(*vpp); 230 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 231 if (vap->va_rdev != VNOVAL) { 232 /* 233 * Want to be able to use this to make badblock 234 * inodes, so don't truncate the dev number. 235 */ 236 ip->i_rdev = vap->va_rdev; 237 } 238 /* 239 * Remove inode, then reload it through VFS_VGET so it is 240 * checked to see if it is an alias of an existing entry in 241 * the inode cache. 242 */ 243 vput(*vpp); 244 (*vpp)->v_type = VNON; 245 ino = ip->i_number; /* Save this before vgone() invalidates ip. */ 246 vgone(*vpp); 247 error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp); 248 if (error) { 249 *vpp = NULL; 250 return (error); 251 } 252 return (0); 253} 254 255/* 256 * Open called. 257 * 258 * Nothing to do. 259 */ 260/* ARGSUSED */ 261int 262ufs_open(ap) 263 struct vop_open_args /* { 264 struct vnode *a_vp; 265 int a_mode; 266 struct ucred *a_cred; 267 struct thread *a_td; 268 } */ *ap; 269{ 270 271 /* 272 * Files marked append-only must be opened for appending. 273 */ 274 if ((VTOI(ap->a_vp)->i_flags & APPEND) && 275 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 276 return (EPERM); 277 return (0); 278} 279 280/* 281 * Close called. 282 * 283 * Update the times on the inode. 284 */ 285/* ARGSUSED */ 286int 287ufs_close(ap) 288 struct vop_close_args /* { 289 struct vnode *a_vp; 290 int a_fflag; 291 struct ucred *a_cred; 292 struct thread *a_td; 293 } */ *ap; 294{ 295 struct vnode *vp = ap->a_vp; 296 struct mount *mp; 297 298 mtx_lock(&vp->v_interlock); 299 if (vp->v_usecount > 1) { 300 ufs_itimes(vp); 301 mtx_unlock(&vp->v_interlock); 302 } else { 303 mtx_unlock(&vp->v_interlock); 304 /* 305 * If we are closing the last reference to an unlinked 306 * file, then it will be freed by the inactive routine. 307 * Because the freeing causes a the filesystem to be 308 * modified, it must be held up during periods when the 309 * filesystem is suspended. 310 * 311 * XXX - EAGAIN is returned to prevent vn_close from 312 * repeating the vrele operation. 313 */ 314 if (vp->v_type == VREG && 315 (VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ? 316 VTOI(vp)->i_effnlink : VTOI(vp)->i_nlink) == 0) { 317 (void) vn_start_write(vp, &mp, V_WAIT); 318 vrele(vp); 319 vn_finished_write(mp); 320 return (EAGAIN); 321 } 322 } 323 return (0); 324} 325 326int 327ufs_access(ap) 328 struct vop_access_args /* { 329 struct vnode *a_vp; 330 int a_mode; 331 struct ucred *a_cred; 332 struct thread *a_td; 333 } */ *ap; 334{ 335 struct vnode *vp = ap->a_vp; 336 struct inode *ip = VTOI(vp); 337 mode_t mode = ap->a_mode; 338 int error; 339#ifdef UFS_ACL 340 struct acl *acl; 341 int len; 342#endif 343 344 /* 345 * Disallow write attempts on read-only file systems; 346 * unless the file is a socket, fifo, or a block or 347 * character device resident on the file system. 348 */ 349 if (mode & VWRITE) { 350 switch (vp->v_type) { 351 case VDIR: 352 case VLNK: 353 case VREG: 354 if (vp->v_mount->mnt_flag & MNT_RDONLY) 355 return (EROFS); 356#ifdef QUOTA 357 if ((error = getinoquota(ip)) != 0) 358 return (error); 359#endif 360 break; 361 default: 362 break; 363 } 364 } 365 366 /* If immutable bit set, nobody gets to write it. */ 367 if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) 368 return (EPERM); 369 370#ifdef UFS_ACL 371 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 372 len = sizeof(*acl); 373 error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred, ap->a_td); 374 switch (error) { 375 case EOPNOTSUPP: 376 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 377 ap->a_mode, ap->a_cred, NULL); 378 break; 379 case 0: 380 error = vaccess_acl_posix1e(vp->v_type, ip->i_uid, ip->i_gid, 381 acl, ap->a_mode, ap->a_cred, NULL); 382 break; 383 default: 384 printf("ufs_access(): Error retrieving ACL on object (%d).\n", 385 error); 386 /* 387 * XXX: Fall back until debugged. Should eventually 388 * possibly log an error, and return EPERM for safety. 389 */ 390 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 391 ap->a_mode, ap->a_cred, NULL); 392 } 393 FREE(acl, M_ACL); 394#else 395 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 396 ap->a_mode, ap->a_cred, NULL); 397#endif 398 return (error); 399} 400 401/* ARGSUSED */ 402int 403ufs_getattr(ap) 404 struct vop_getattr_args /* { 405 struct vnode *a_vp; 406 struct vattr *a_vap; 407 struct ucred *a_cred; 408 struct thread *a_td; 409 } */ *ap; 410{ 411 register struct vnode *vp = ap->a_vp; 412 register struct inode *ip = VTOI(vp); 413 register struct vattr *vap = ap->a_vap; 414 415 ufs_itimes(vp); 416 /* 417 * Copy from inode table 418 */ 419 vap->va_fsid = dev2udev(ip->i_dev); 420 vap->va_fileid = ip->i_number; 421 vap->va_mode = ip->i_mode & ~IFMT; 422 vap->va_nlink = VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ? 423 ip->i_effnlink : ip->i_nlink; 424 vap->va_uid = ip->i_uid; 425 vap->va_gid = ip->i_gid; 426 vap->va_rdev = ip->i_rdev; 427 vap->va_size = ip->i_din.di_size; 428 vap->va_atime.tv_sec = ip->i_atime; 429 vap->va_atime.tv_nsec = ip->i_atimensec; 430 vap->va_mtime.tv_sec = ip->i_mtime; 431 vap->va_mtime.tv_nsec = ip->i_mtimensec; 432 vap->va_ctime.tv_sec = ip->i_ctime; 433 vap->va_ctime.tv_nsec = ip->i_ctimensec; 434 vap->va_flags = ip->i_flags; 435 vap->va_gen = ip->i_gen; 436 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 437 vap->va_bytes = dbtob((u_quad_t)ip->i_blocks); 438 vap->va_type = IFTOVT(ip->i_mode); 439 vap->va_filerev = ip->i_modrev; 440 return (0); 441} 442 443/* 444 * Set attribute vnode op. called from several syscalls 445 */ 446int 447ufs_setattr(ap) 448 struct vop_setattr_args /* { 449 struct vnode *a_vp; 450 struct vattr *a_vap; 451 struct ucred *a_cred; 452 struct thread *a_td; 453 } */ *ap; 454{ 455 struct vattr *vap = ap->a_vap; 456 struct vnode *vp = ap->a_vp; 457 struct inode *ip = VTOI(vp); 458 struct ucred *cred = ap->a_cred; 459 struct thread *td = ap->a_td; 460 int error; 461 462 /* 463 * Check for unsettable attributes. 464 */ 465 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 466 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 467 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 468 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 469 return (EINVAL); 470 } 471 if (vap->va_flags != VNOVAL) { 472 if (vp->v_mount->mnt_flag & MNT_RDONLY) 473 return (EROFS); 474 /* 475 * Callers may only modify the file flags on objects they 476 * have VADMIN rights for. 477 */ 478 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 479 return (error); 480 /* 481 * Unprivileged processes and privileged processes in 482 * jail() are not permitted to unset system flags, or 483 * modify flags if any system flags are set. 484 * Privileged non-jail processes may not modify system flags 485 * if securelevel > 0 and any existing system flags are set. 486 */ 487 if (!suser_xxx(cred, NULL, PRISON_ROOT)) { 488 if (ip->i_flags 489 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { 490 error = securelevel_gt(cred, 0); 491 if (error) 492 return (error); 493 } 494 /* Snapshot flag cannot be set or cleared */ 495 if (((vap->va_flags & SF_SNAPSHOT) != 0 && 496 (ip->i_flags & SF_SNAPSHOT) == 0) || 497 ((vap->va_flags & SF_SNAPSHOT) == 0 && 498 (ip->i_flags & SF_SNAPSHOT) != 0)) 499 return (EPERM); 500 ip->i_flags = vap->va_flags; 501 } else { 502 if (ip->i_flags 503 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || 504 (vap->va_flags & UF_SETTABLE) != vap->va_flags) 505 return (EPERM); 506 ip->i_flags &= SF_SETTABLE; 507 ip->i_flags |= (vap->va_flags & UF_SETTABLE); 508 } 509 ip->i_flag |= IN_CHANGE; 510 if (vap->va_flags & (IMMUTABLE | APPEND)) 511 return (0); 512 } 513 if (ip->i_flags & (IMMUTABLE | APPEND)) 514 return (EPERM); 515 /* 516 * Go through the fields and update iff not VNOVAL. 517 */ 518 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 519 if (vp->v_mount->mnt_flag & MNT_RDONLY) 520 return (EROFS); 521 if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, 522 td)) != 0) 523 return (error); 524 } 525 if (vap->va_size != VNOVAL) { 526 /* 527 * Disallow write attempts on read-only file systems; 528 * unless the file is a socket, fifo, or a block or 529 * character device resident on the file system. 530 */ 531 switch (vp->v_type) { 532 case VDIR: 533 return (EISDIR); 534 case VLNK: 535 case VREG: 536 if (vp->v_mount->mnt_flag & MNT_RDONLY) 537 return (EROFS); 538 if ((ip->i_flags & SF_SNAPSHOT) != 0) 539 return (EPERM); 540 break; 541 default: 542 break; 543 } 544 if ((error = UFS_TRUNCATE(vp, vap->va_size, 0, cred, td)) != 0) 545 return (error); 546 } 547 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 548 if (vp->v_mount->mnt_flag & MNT_RDONLY) 549 return (EROFS); 550 if ((ip->i_flags & SF_SNAPSHOT) != 0) 551 return (EPERM); 552 /* 553 * From utimes(2): 554 * If times is NULL, ... The caller must be the owner of 555 * the file, have permission to write the file, or be the 556 * super-user. 557 * If times is non-NULL, ... The caller must be the owner of 558 * the file or be the super-user. 559 */ 560 if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) && 561 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 562 (error = VOP_ACCESS(vp, VWRITE, cred, td)))) 563 return (error); 564 if (vap->va_atime.tv_sec != VNOVAL) 565 ip->i_flag |= IN_ACCESS; 566 if (vap->va_mtime.tv_sec != VNOVAL) 567 ip->i_flag |= IN_CHANGE | IN_UPDATE; 568 ufs_itimes(vp); 569 if (vap->va_atime.tv_sec != VNOVAL) { 570 ip->i_atime = vap->va_atime.tv_sec; 571 ip->i_atimensec = vap->va_atime.tv_nsec; 572 } 573 if (vap->va_mtime.tv_sec != VNOVAL) { 574 ip->i_mtime = vap->va_mtime.tv_sec; 575 ip->i_mtimensec = vap->va_mtime.tv_nsec; 576 } 577 error = UFS_UPDATE(vp, 0); 578 if (error) 579 return (error); 580 } 581 error = 0; 582 if (vap->va_mode != (mode_t)VNOVAL) { 583 if (vp->v_mount->mnt_flag & MNT_RDONLY) 584 return (EROFS); 585 if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode & 586 (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH))) 587 return (EPERM); 588 error = ufs_chmod(vp, (int)vap->va_mode, cred, td); 589 } 590 VN_KNOTE(vp, NOTE_ATTRIB); 591 return (error); 592} 593 594/* 595 * Change the mode on a file. 596 * Inode must be locked before calling. 597 */ 598static int 599ufs_chmod(vp, mode, cred, td) 600 register struct vnode *vp; 601 register int mode; 602 register struct ucred *cred; 603 struct thread *td; 604{ 605 register struct inode *ip = VTOI(vp); 606 int error; 607 608 /* 609 * To modify the permissions on a file, must possess VADMIN 610 * for that file. 611 */ 612 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 613 return (error); 614 /* 615 * Privileged processes may set the sticky bit on non-directories, 616 * as well as set the setgid bit on a file with a group that the 617 * process is not a member of. 618 */ 619 if (suser_xxx(cred, NULL, PRISON_ROOT)) { 620 if (vp->v_type != VDIR && (mode & S_ISTXT)) 621 return (EFTYPE); 622 if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) 623 return (EPERM); 624 } 625 ip->i_mode &= ~ALLPERMS; 626 ip->i_mode |= (mode & ALLPERMS); 627 ip->i_flag |= IN_CHANGE; 628 return (0); 629} 630 631/* 632 * Perform chown operation on inode ip; 633 * inode must be locked prior to call. 634 */ 635static int 636ufs_chown(vp, uid, gid, cred, td) 637 register struct vnode *vp; 638 uid_t uid; 639 gid_t gid; 640 struct ucred *cred; 641 struct thread *td; 642{ 643 register struct inode *ip = VTOI(vp); 644 uid_t ouid; 645 gid_t ogid; 646 int error = 0; 647#ifdef QUOTA 648 register int i; 649 long change; 650#endif 651 652 if (uid == (uid_t)VNOVAL) 653 uid = ip->i_uid; 654 if (gid == (gid_t)VNOVAL) 655 gid = ip->i_gid; 656 /* 657 * To modify the ownership of a file, must possess VADMIN 658 * for that file. 659 */ 660 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 661 return (error); 662 /* 663 * To change the owner of a file, or change the group of a file 664 * to a group of which we are not a member, the caller must 665 * have privilege. 666 */ 667 if ((uid != ip->i_uid || 668 (gid != ip->i_gid && !groupmember(gid, cred))) && 669 (error = suser_xxx(cred, td->td_proc, PRISON_ROOT))) 670 return (error); 671 ogid = ip->i_gid; 672 ouid = ip->i_uid; 673#ifdef QUOTA 674 if ((error = getinoquota(ip)) != 0) 675 return (error); 676 if (ouid == uid) { 677 dqrele(vp, ip->i_dquot[USRQUOTA]); 678 ip->i_dquot[USRQUOTA] = NODQUOT; 679 } 680 if (ogid == gid) { 681 dqrele(vp, ip->i_dquot[GRPQUOTA]); 682 ip->i_dquot[GRPQUOTA] = NODQUOT; 683 } 684 change = ip->i_blocks; 685 (void) chkdq(ip, -change, cred, CHOWN); 686 (void) chkiq(ip, -1, cred, CHOWN); 687 for (i = 0; i < MAXQUOTAS; i++) { 688 dqrele(vp, ip->i_dquot[i]); 689 ip->i_dquot[i] = NODQUOT; 690 } 691#endif 692 ip->i_gid = gid; 693 ip->i_uid = uid; 694#ifdef QUOTA 695 if ((error = getinoquota(ip)) == 0) { 696 if (ouid == uid) { 697 dqrele(vp, ip->i_dquot[USRQUOTA]); 698 ip->i_dquot[USRQUOTA] = NODQUOT; 699 } 700 if (ogid == gid) { 701 dqrele(vp, ip->i_dquot[GRPQUOTA]); 702 ip->i_dquot[GRPQUOTA] = NODQUOT; 703 } 704 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) { 705 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0) 706 goto good; 707 else 708 (void) chkdq(ip, -change, cred, CHOWN|FORCE); 709 } 710 for (i = 0; i < MAXQUOTAS; i++) { 711 dqrele(vp, ip->i_dquot[i]); 712 ip->i_dquot[i] = NODQUOT; 713 } 714 } 715 ip->i_gid = ogid; 716 ip->i_uid = ouid; 717 if (getinoquota(ip) == 0) { 718 if (ouid == uid) { 719 dqrele(vp, ip->i_dquot[USRQUOTA]); 720 ip->i_dquot[USRQUOTA] = NODQUOT; 721 } 722 if (ogid == gid) { 723 dqrele(vp, ip->i_dquot[GRPQUOTA]); 724 ip->i_dquot[GRPQUOTA] = NODQUOT; 725 } 726 (void) chkdq(ip, change, cred, FORCE|CHOWN); 727 (void) chkiq(ip, 1, cred, FORCE|CHOWN); 728 (void) getinoquota(ip); 729 } 730 return (error); 731good: 732 if (getinoquota(ip)) 733 panic("ufs_chown: lost quota"); 734#endif /* QUOTA */ 735 ip->i_flag |= IN_CHANGE; 736 if (suser_xxx(cred, NULL, PRISON_ROOT) && (ouid != uid || ogid != gid)) 737 ip->i_mode &= ~(ISUID | ISGID); 738 return (0); 739} 740 741int 742ufs_remove(ap) 743 struct vop_remove_args /* { 744 struct vnode *a_dvp; 745 struct vnode *a_vp; 746 struct componentname *a_cnp; 747 } */ *ap; 748{ 749 struct inode *ip; 750 struct vnode *vp = ap->a_vp; 751 struct vnode *dvp = ap->a_dvp; 752 int error; 753 754 ip = VTOI(vp); 755 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 756 (VTOI(dvp)->i_flags & APPEND)) { 757 error = EPERM; 758 goto out; 759 } 760 error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); 761 if (ip->i_nlink <= 0) 762 vp->v_flag |= VNOSYNC; 763 VN_KNOTE(vp, NOTE_DELETE); 764 VN_KNOTE(dvp, NOTE_WRITE); 765out: 766 return (error); 767} 768 769/* 770 * link vnode call 771 */ 772int 773ufs_link(ap) 774 struct vop_link_args /* { 775 struct vnode *a_tdvp; 776 struct vnode *a_vp; 777 struct componentname *a_cnp; 778 } */ *ap; 779{ 780 struct vnode *vp = ap->a_vp; 781 struct vnode *tdvp = ap->a_tdvp; 782 struct componentname *cnp = ap->a_cnp; 783 struct thread *td = cnp->cn_thread; 784 struct inode *ip; 785 struct direct newdir; 786 int error; 787 788#ifdef DIAGNOSTIC 789 if ((cnp->cn_flags & HASBUF) == 0) 790 panic("ufs_link: no name"); 791#endif 792 if (tdvp->v_mount != vp->v_mount) { 793 error = EXDEV; 794 goto out2; 795 } 796 if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { 797 goto out2; 798 } 799 ip = VTOI(vp); 800 if ((nlink_t)ip->i_nlink >= LINK_MAX) { 801 error = EMLINK; 802 goto out1; 803 } 804 if (ip->i_flags & (IMMUTABLE | APPEND)) { 805 error = EPERM; 806 goto out1; 807 } 808 ip->i_effnlink++; 809 ip->i_nlink++; 810 ip->i_flag |= IN_CHANGE; 811 if (DOINGSOFTDEP(vp)) 812 softdep_change_linkcnt(ip); 813 error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp))); 814 if (!error) { 815 ufs_makedirentry(ip, cnp, &newdir); 816 error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL); 817 } 818 819 if (error) { 820 ip->i_effnlink--; 821 ip->i_nlink--; 822 ip->i_flag |= IN_CHANGE; 823 if (DOINGSOFTDEP(vp)) 824 softdep_change_linkcnt(ip); 825 } 826out1: 827 if (tdvp != vp) 828 VOP_UNLOCK(vp, 0, td); 829out2: 830 VN_KNOTE(vp, NOTE_LINK); 831 VN_KNOTE(tdvp, NOTE_WRITE); 832 return (error); 833} 834 835/* 836 * whiteout vnode call 837 */ 838int 839ufs_whiteout(ap) 840 struct vop_whiteout_args /* { 841 struct vnode *a_dvp; 842 struct componentname *a_cnp; 843 int a_flags; 844 } */ *ap; 845{ 846 struct vnode *dvp = ap->a_dvp; 847 struct componentname *cnp = ap->a_cnp; 848 struct direct newdir; 849 int error = 0; 850 851 switch (ap->a_flags) { 852 case LOOKUP: 853 /* 4.4 format directories support whiteout operations */ 854 if (dvp->v_mount->mnt_maxsymlinklen > 0) 855 return (0); 856 return (EOPNOTSUPP); 857 858 case CREATE: 859 /* create a new directory whiteout */ 860#ifdef DIAGNOSTIC 861 if ((cnp->cn_flags & SAVENAME) == 0) 862 panic("ufs_whiteout: missing name"); 863 if (dvp->v_mount->mnt_maxsymlinklen <= 0) 864 panic("ufs_whiteout: old format filesystem"); 865#endif 866 867 newdir.d_ino = WINO; 868 newdir.d_namlen = cnp->cn_namelen; 869 bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1); 870 newdir.d_type = DT_WHT; 871 error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL); 872 break; 873 874 case DELETE: 875 /* remove an existing directory whiteout */ 876#ifdef DIAGNOSTIC 877 if (dvp->v_mount->mnt_maxsymlinklen <= 0) 878 panic("ufs_whiteout: old format filesystem"); 879#endif 880 881 cnp->cn_flags &= ~DOWHITEOUT; 882 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0); 883 break; 884 default: 885 panic("ufs_whiteout: unknown op"); 886 } 887 return (error); 888} 889 890/* 891 * Rename system call. 892 * rename("foo", "bar"); 893 * is essentially 894 * unlink("bar"); 895 * link("foo", "bar"); 896 * unlink("foo"); 897 * but ``atomically''. Can't do full commit without saving state in the 898 * inode on disk which isn't feasible at this time. Best we can do is 899 * always guarantee the target exists. 900 * 901 * Basic algorithm is: 902 * 903 * 1) Bump link count on source while we're linking it to the 904 * target. This also ensure the inode won't be deleted out 905 * from underneath us while we work (it may be truncated by 906 * a concurrent `trunc' or `open' for creation). 907 * 2) Link source to destination. If destination already exists, 908 * delete it first. 909 * 3) Unlink source reference to inode if still around. If a 910 * directory was moved and the parent of the destination 911 * is different from the source, patch the ".." entry in the 912 * directory. 913 */ 914int 915ufs_rename(ap) 916 struct vop_rename_args /* { 917 struct vnode *a_fdvp; 918 struct vnode *a_fvp; 919 struct componentname *a_fcnp; 920 struct vnode *a_tdvp; 921 struct vnode *a_tvp; 922 struct componentname *a_tcnp; 923 } */ *ap; 924{ 925 struct vnode *tvp = ap->a_tvp; 926 register struct vnode *tdvp = ap->a_tdvp; 927 struct vnode *fvp = ap->a_fvp; 928 struct vnode *fdvp = ap->a_fdvp; 929 struct componentname *tcnp = ap->a_tcnp; 930 struct componentname *fcnp = ap->a_fcnp; 931 struct thread *td = fcnp->cn_thread; 932 struct inode *ip, *xp, *dp; 933 struct direct newdir; 934 int doingdirectory = 0, oldparent = 0, newparent = 0; 935 int error = 0, ioflag; 936 937#ifdef DIAGNOSTIC 938 if ((tcnp->cn_flags & HASBUF) == 0 || 939 (fcnp->cn_flags & HASBUF) == 0) 940 panic("ufs_rename: no name"); 941#endif 942 /* 943 * Check for cross-device rename. 944 */ 945 if ((fvp->v_mount != tdvp->v_mount) || 946 (tvp && (fvp->v_mount != tvp->v_mount))) { 947 error = EXDEV; 948abortit: 949 if (tdvp == tvp) 950 vrele(tdvp); 951 else 952 vput(tdvp); 953 if (tvp) 954 vput(tvp); 955 vrele(fdvp); 956 vrele(fvp); 957 return (error); 958 } 959 960 if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 961 (VTOI(tdvp)->i_flags & APPEND))) { 962 error = EPERM; 963 goto abortit; 964 } 965 966 /* 967 * Check if just deleting a link name or if we've lost a race. 968 * If another process completes the same rename after we've looked 969 * up the source and have blocked looking up the target, then the 970 * source and target inodes may be identical now although the 971 * names were never linked. 972 */ 973 if (fvp == tvp) { 974 if (fvp->v_type == VDIR) { 975 /* 976 * Linked directories are impossible, so we must 977 * have lost the race. Pretend that the rename 978 * completed before the lookup. 979 */ 980#ifdef UFS_RENAME_DEBUG 981 printf("ufs_rename: fvp == tvp for directories\n"); 982#endif 983 error = ENOENT; 984 goto abortit; 985 } 986 987 /* Release destination completely. */ 988 vput(tdvp); 989 vput(tvp); 990 991 /* 992 * Delete source. There is another race now that everything 993 * is unlocked, but this doesn't cause any new complications. 994 * Relookup() may find a file that is unrelated to the 995 * original one, or it may fail. Too bad. 996 */ 997 vrele(fdvp); 998 vrele(fvp); 999 fcnp->cn_flags &= ~MODMASK; 1000 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1001 if ((fcnp->cn_flags & SAVESTART) == 0) 1002 panic("ufs_rename: lost from startdir"); 1003 fcnp->cn_nameiop = DELETE; 1004 VREF(fdvp); 1005 error = relookup(fdvp, &fvp, fcnp); 1006 if (error == 0) 1007 vrele(fdvp); 1008 if (fvp == NULL) { 1009#ifdef UFS_RENAME_DEBUG 1010 printf("ufs_rename: from name disappeared\n"); 1011#endif 1012 return (ENOENT); 1013 } 1014 error = VOP_REMOVE(fdvp, fvp, fcnp); 1015 if (fdvp == fvp) 1016 vrele(fdvp); 1017 else 1018 vput(fdvp); 1019 vput(fvp); 1020 return (error); 1021 } 1022 if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0) 1023 goto abortit; 1024 dp = VTOI(fdvp); 1025 ip = VTOI(fvp); 1026 if (ip->i_nlink >= LINK_MAX) { 1027 VOP_UNLOCK(fvp, 0, td); 1028 error = EMLINK; 1029 goto abortit; 1030 } 1031 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) 1032 || (dp->i_flags & APPEND)) { 1033 VOP_UNLOCK(fvp, 0, td); 1034 error = EPERM; 1035 goto abortit; 1036 } 1037 if ((ip->i_mode & IFMT) == IFDIR) { 1038 /* 1039 * Avoid ".", "..", and aliases of "." for obvious reasons. 1040 */ 1041 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1042 dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT || 1043 (ip->i_flag & IN_RENAME)) { 1044 VOP_UNLOCK(fvp, 0, td); 1045 error = EINVAL; 1046 goto abortit; 1047 } 1048 ip->i_flag |= IN_RENAME; 1049 oldparent = dp->i_number; 1050 doingdirectory = 1; 1051 } 1052 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ 1053 vrele(fdvp); 1054 1055 /* 1056 * When the target exists, both the directory 1057 * and target vnodes are returned locked. 1058 */ 1059 dp = VTOI(tdvp); 1060 xp = NULL; 1061 if (tvp) 1062 xp = VTOI(tvp); 1063 1064 /* 1065 * 1) Bump link count while we're moving stuff 1066 * around. If we crash somewhere before 1067 * completing our work, the link count 1068 * may be wrong, but correctable. 1069 */ 1070 ip->i_effnlink++; 1071 ip->i_nlink++; 1072 ip->i_flag |= IN_CHANGE; 1073 if (DOINGSOFTDEP(fvp)) 1074 softdep_change_linkcnt(ip); 1075 if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) | 1076 DOINGASYNC(fvp)))) != 0) { 1077 VOP_UNLOCK(fvp, 0, td); 1078 goto bad; 1079 } 1080 1081 /* 1082 * If ".." must be changed (ie the directory gets a new 1083 * parent) then the source directory must not be in the 1084 * directory heirarchy above the target, as this would 1085 * orphan everything below the source directory. Also 1086 * the user must have write permission in the source so 1087 * as to be able to change "..". We must repeat the call 1088 * to namei, as the parent directory is unlocked by the 1089 * call to checkpath(). 1090 */ 1091 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread); 1092 VOP_UNLOCK(fvp, 0, td); 1093 if (oldparent != dp->i_number) 1094 newparent = dp->i_number; 1095 if (doingdirectory && newparent) { 1096 if (error) /* write access check above */ 1097 goto bad; 1098 if (xp != NULL) 1099 vput(tvp); 1100 error = ufs_checkpath(ip, dp, tcnp->cn_cred); 1101 if (error) 1102 goto out; 1103 if ((tcnp->cn_flags & SAVESTART) == 0) 1104 panic("ufs_rename: lost to startdir"); 1105 VREF(tdvp); 1106 error = relookup(tdvp, &tvp, tcnp); 1107 if (error) 1108 goto out; 1109 vrele(tdvp); 1110 dp = VTOI(tdvp); 1111 xp = NULL; 1112 if (tvp) 1113 xp = VTOI(tvp); 1114 } 1115 /* 1116 * 2) If target doesn't exist, link the target 1117 * to the source and unlink the source. 1118 * Otherwise, rewrite the target directory 1119 * entry to reference the source inode and 1120 * expunge the original entry's existence. 1121 */ 1122 if (xp == NULL) { 1123 if (dp->i_dev != ip->i_dev) 1124 panic("ufs_rename: EXDEV"); 1125 /* 1126 * Account for ".." in new directory. 1127 * When source and destination have the same 1128 * parent we don't fool with the link count. 1129 */ 1130 if (doingdirectory && newparent) { 1131 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1132 error = EMLINK; 1133 goto bad; 1134 } 1135 dp->i_effnlink++; 1136 dp->i_nlink++; 1137 dp->i_flag |= IN_CHANGE; 1138 if (DOINGSOFTDEP(tdvp)) 1139 softdep_change_linkcnt(dp); 1140 error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) | 1141 DOINGASYNC(tdvp))); 1142 if (error) 1143 goto bad; 1144 } 1145 ufs_makedirentry(ip, tcnp, &newdir); 1146 error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL); 1147 if (error) { 1148 if (doingdirectory && newparent) { 1149 dp->i_effnlink--; 1150 dp->i_nlink--; 1151 dp->i_flag |= IN_CHANGE; 1152 if (DOINGSOFTDEP(tdvp)) 1153 softdep_change_linkcnt(dp); 1154 (void)UFS_UPDATE(tdvp, 1); 1155 } 1156 goto bad; 1157 } 1158 VN_KNOTE(tdvp, NOTE_WRITE); 1159 vput(tdvp); 1160 } else { 1161 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) 1162 panic("ufs_rename: EXDEV"); 1163 /* 1164 * Short circuit rename(foo, foo). 1165 */ 1166 if (xp->i_number == ip->i_number) 1167 panic("ufs_rename: same file"); 1168 /* 1169 * If the parent directory is "sticky", then the caller 1170 * must possess VADMIN for the parent directory, or the 1171 * destination of the rename. This implements append-only 1172 * directories. 1173 */ 1174 if ((dp->i_mode & S_ISTXT) && 1175 VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, td) && 1176 VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, td)) { 1177 error = EPERM; 1178 goto bad; 1179 } 1180 /* 1181 * Target must be empty if a directory and have no links 1182 * to it. Also, ensure source and target are compatible 1183 * (both directories, or both not directories). 1184 */ 1185 if ((xp->i_mode&IFMT) == IFDIR) { 1186 if ((xp->i_effnlink > 2) || 1187 !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) { 1188 error = ENOTEMPTY; 1189 goto bad; 1190 } 1191 if (!doingdirectory) { 1192 error = ENOTDIR; 1193 goto bad; 1194 } 1195 cache_purge(tdvp); 1196 } else if (doingdirectory) { 1197 error = EISDIR; 1198 goto bad; 1199 } 1200 error = ufs_dirrewrite(dp, xp, ip->i_number, 1201 IFTODT(ip->i_mode), 1202 (doingdirectory && newparent) ? newparent : doingdirectory); 1203 if (error) 1204 goto bad; 1205 if (doingdirectory) { 1206 if (!newparent) { 1207 dp->i_effnlink--; 1208 if (DOINGSOFTDEP(tdvp)) 1209 softdep_change_linkcnt(dp); 1210 } 1211 xp->i_effnlink--; 1212 if (DOINGSOFTDEP(tvp)) 1213 softdep_change_linkcnt(xp); 1214 } 1215 if (doingdirectory && !DOINGSOFTDEP(tvp)) { 1216 /* 1217 * Truncate inode. The only stuff left in the directory 1218 * is "." and "..". The "." reference is inconsequential 1219 * since we are quashing it. We have removed the "." 1220 * reference and the reference in the parent directory, 1221 * but there may be other hard links. The soft 1222 * dependency code will arrange to do these operations 1223 * after the parent directory entry has been deleted on 1224 * disk, so when running with that code we avoid doing 1225 * them now. 1226 */ 1227 if (!newparent) { 1228 dp->i_nlink--; 1229 dp->i_flag |= IN_CHANGE; 1230 } 1231 xp->i_nlink--; 1232 xp->i_flag |= IN_CHANGE; 1233 ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC; 1234 if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag, 1235 tcnp->cn_cred, tcnp->cn_thread)) != 0) 1236 goto bad; 1237 } 1238 VN_KNOTE(tdvp, NOTE_WRITE); 1239 vput(tdvp); 1240 VN_KNOTE(tvp, NOTE_DELETE); 1241 vput(tvp); 1242 xp = NULL; 1243 } 1244 1245 /* 1246 * 3) Unlink the source. 1247 */ 1248 fcnp->cn_flags &= ~MODMASK; 1249 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1250 if ((fcnp->cn_flags & SAVESTART) == 0) 1251 panic("ufs_rename: lost from startdir"); 1252 VREF(fdvp); 1253 error = relookup(fdvp, &fvp, fcnp); 1254 if (error == 0) 1255 vrele(fdvp); 1256 if (fvp != NULL) { 1257 xp = VTOI(fvp); 1258 dp = VTOI(fdvp); 1259 } else { 1260 /* 1261 * From name has disappeared. IN_RENAME is not sufficient 1262 * to protect against directory races due to timing windows, 1263 * so we have to remove the panic. XXX the only real way 1264 * to solve this issue is at a much higher level. By the 1265 * time we hit ufs_rename() it's too late. 1266 */ 1267#if 0 1268 if (doingdirectory) 1269 panic("ufs_rename: lost dir entry"); 1270#endif 1271 vrele(ap->a_fvp); 1272 return (0); 1273 } 1274 /* 1275 * Ensure that the directory entry still exists and has not 1276 * changed while the new name has been entered. If the source is 1277 * a file then the entry may have been unlinked or renamed. In 1278 * either case there is no further work to be done. If the source 1279 * is a directory then it cannot have been rmdir'ed; the IN_RENAME 1280 * flag ensures that it cannot be moved by another rename or removed 1281 * by a rmdir. 1282 */ 1283 if (xp != ip) { 1284 /* 1285 * From name resolves to a different inode. IN_RENAME is 1286 * not sufficient protection against timing window races 1287 * so we can't panic here. XXX the only real way 1288 * to solve this issue is at a much higher level. By the 1289 * time we hit ufs_rename() it's too late. 1290 */ 1291#if 0 1292 if (doingdirectory) 1293 panic("ufs_rename: lost dir entry"); 1294#endif 1295 } else { 1296 /* 1297 * If the source is a directory with a 1298 * new parent, the link count of the old 1299 * parent directory must be decremented 1300 * and ".." set to point to the new parent. 1301 */ 1302 if (doingdirectory && newparent) { 1303 xp->i_offset = mastertemplate.dot_reclen; 1304 ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0); 1305 cache_purge(fdvp); 1306 } 1307 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); 1308 xp->i_flag &= ~IN_RENAME; 1309 } 1310 VN_KNOTE(fvp, NOTE_RENAME); 1311 if (dp) 1312 vput(fdvp); 1313 if (xp) 1314 vput(fvp); 1315 vrele(ap->a_fvp); 1316 return (error); 1317 1318bad: 1319 if (xp) 1320 vput(ITOV(xp)); 1321 vput(ITOV(dp)); 1322out: 1323 if (doingdirectory) 1324 ip->i_flag &= ~IN_RENAME; 1325 if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) { 1326 ip->i_effnlink--; 1327 ip->i_nlink--; 1328 ip->i_flag |= IN_CHANGE; 1329 ip->i_flag &= ~IN_RENAME; 1330 if (DOINGSOFTDEP(fvp)) 1331 softdep_change_linkcnt(ip); 1332 vput(fvp); 1333 } else 1334 vrele(fvp); 1335 return (error); 1336} 1337 1338/* 1339 * Mkdir system call 1340 */ 1341int 1342ufs_mkdir(ap) 1343 struct vop_mkdir_args /* { 1344 struct vnode *a_dvp; 1345 struct vnode **a_vpp; 1346 struct componentname *a_cnp; 1347 struct vattr *a_vap; 1348 } */ *ap; 1349{ 1350 register struct vnode *dvp = ap->a_dvp; 1351 register struct vattr *vap = ap->a_vap; 1352 register struct componentname *cnp = ap->a_cnp; 1353 register struct inode *ip, *dp; 1354 struct vnode *tvp; 1355 struct buf *bp; 1356 struct dirtemplate dirtemplate, *dtp; 1357 struct direct newdir; 1358#ifdef UFS_ACL 1359 struct acl *acl, *dacl; 1360#endif 1361 int error, dmode; 1362 long blkoff; 1363 1364#ifdef DIAGNOSTIC 1365 if ((cnp->cn_flags & HASBUF) == 0) 1366 panic("ufs_mkdir: no name"); 1367#endif 1368 dp = VTOI(dvp); 1369 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1370 error = EMLINK; 1371 goto out; 1372 } 1373 dmode = vap->va_mode & 0777; 1374 dmode |= IFDIR; 1375 /* 1376 * Must simulate part of ufs_makeinode here to acquire the inode, 1377 * but not have it entered in the parent directory. The entry is 1378 * made later after writing "." and ".." entries. 1379 */ 1380 error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp); 1381 if (error) 1382 goto out; 1383 ip = VTOI(tvp); 1384 ip->i_gid = dp->i_gid; 1385#ifdef SUIDDIR 1386 { 1387#ifdef QUOTA 1388 struct ucred ucred, *ucp; 1389 ucp = cnp->cn_cred; 1390#endif 1391 /* 1392 * If we are hacking owners here, (only do this where told to) 1393 * and we are not giving it TO root, (would subvert quotas) 1394 * then go ahead and give it to the other user. 1395 * The new directory also inherits the SUID bit. 1396 * If user's UID and dir UID are the same, 1397 * 'give it away' so that the SUID is still forced on. 1398 */ 1399 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && 1400 (dp->i_mode & ISUID) && dp->i_uid) { 1401 dmode |= ISUID; 1402 ip->i_uid = dp->i_uid; 1403#ifdef QUOTA 1404 if (dp->i_uid != cnp->cn_cred->cr_uid) { 1405 /* 1406 * Make sure the correct user gets charged 1407 * for the space. 1408 * Make a dummy credential for the victim. 1409 * XXX This seems to never be accessed out of 1410 * our context so a stack variable is ok. 1411 */ 1412 ucred.cr_ref = 1; 1413 ucred.cr_uid = ip->i_uid; 1414 ucred.cr_ngroups = 1; 1415 ucred.cr_groups[0] = dp->i_gid; 1416 ucp = &ucred; 1417 } 1418#endif 1419 } else 1420 ip->i_uid = cnp->cn_cred->cr_uid; 1421#ifdef QUOTA 1422 if ((error = getinoquota(ip)) || 1423 (error = chkiq(ip, 1, ucp, 0))) { 1424 UFS_VFREE(tvp, ip->i_number, dmode); 1425 vput(tvp); 1426 return (error); 1427 } 1428#endif 1429 } 1430#else /* !SUIDDIR */ 1431 ip->i_uid = cnp->cn_cred->cr_uid; 1432#ifdef QUOTA 1433 if ((error = getinoquota(ip)) || 1434 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1435 UFS_VFREE(tvp, ip->i_number, dmode); 1436 vput(tvp); 1437 return (error); 1438 } 1439#endif 1440#endif /* !SUIDDIR */ 1441 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1442#ifdef UFS_ACL 1443 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 1444 MALLOC(dacl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 1445 1446 /* 1447 * Retrieve default ACL from parent, if any. 1448 */ 1449 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred, 1450 cnp->cn_thread); 1451 switch (error) { 1452 case 0: 1453 /* 1454 * Retrieved a default ACL, so merge mode and ACL if 1455 * necessary. 1456 */ 1457 if (acl->acl_cnt != 0) { 1458 /* 1459 * Two possible ways for default ACL to not be 1460 * present. First, the EA can be undefined, 1461 * or second, the default ACL can be blank. 1462 * If it's blank, fall through to the it's 1463 * not defined case. 1464 */ 1465 ip->i_mode = dmode; 1466 *dacl = *acl; 1467 ufs_sync_acl_from_inode(ip, acl); 1468 break; 1469 } 1470 /* FALLTHROUGH */ 1471 1472 case EOPNOTSUPP: 1473 /* 1474 * Just use the mode as-is. 1475 */ 1476 ip->i_mode = dmode; 1477 FREE(acl, M_ACL); 1478 FREE(dacl, M_ACL); 1479 dacl = acl = NULL; 1480 break; 1481 1482 default: 1483 UFS_VFREE(tvp, ip->i_number, dmode); 1484 vput(tvp); 1485 return (error); 1486 } 1487#else /* !UFS_ACL */ 1488 ip->i_mode = dmode; 1489#endif /* !UFS_ACL */ 1490 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ 1491 ip->i_effnlink = 2; 1492 ip->i_nlink = 2; 1493 if (DOINGSOFTDEP(tvp)) 1494 softdep_change_linkcnt(ip); 1495 if (cnp->cn_flags & ISWHITEOUT) 1496 ip->i_flags |= UF_OPAQUE; 1497 1498 /* 1499 * Bump link count in parent directory to reflect work done below. 1500 * Should be done before reference is created so cleanup is 1501 * possible if we crash. 1502 */ 1503 dp->i_effnlink++; 1504 dp->i_nlink++; 1505 dp->i_flag |= IN_CHANGE; 1506 if (DOINGSOFTDEP(dvp)) 1507 softdep_change_linkcnt(dp); 1508 error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp))); 1509 if (error) 1510 goto bad; 1511#ifdef UFS_ACL 1512 if (acl != NULL) { 1513 /* 1514 * XXX: If we abort now, will Soft Updates notify the extattr 1515 * code that the EAs for the file need to be released? 1516 */ 1517 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred, 1518 cnp->cn_thread); 1519 if (error == 0) 1520 error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl, 1521 cnp->cn_cred, cnp->cn_thread); 1522 switch (error) { 1523 case 0: 1524 break; 1525 1526 case EOPNOTSUPP: 1527 /* 1528 * XXX: This should not happen, as EOPNOTSUPP above 1529 * was supposed to free acl. 1530 */ 1531 printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n"); 1532 /* 1533 panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()"); 1534 */ 1535 break; 1536 1537 default: 1538 FREE(acl, M_ACL); 1539 FREE(dacl, M_ACL); 1540 goto bad; 1541 } 1542 FREE(acl, M_ACL); 1543 FREE(dacl, M_ACL); 1544 } 1545#endif /* !UFS_ACL */ 1546 1547 /* 1548 * Initialize directory with "." and ".." from static template. 1549 */ 1550 if (dvp->v_mount->mnt_maxsymlinklen > 0 1551 ) 1552 dtp = &mastertemplate; 1553 else 1554 dtp = (struct dirtemplate *)&omastertemplate; 1555 dirtemplate = *dtp; 1556 dirtemplate.dot_ino = ip->i_number; 1557 dirtemplate.dotdot_ino = dp->i_number; 1558 if ((error = UFS_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred, 1559 B_CLRBUF, &bp)) != 0) 1560 goto bad; 1561 ip->i_size = DIRBLKSIZ; 1562 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1563 vnode_pager_setsize(tvp, (u_long)ip->i_size); 1564 bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate); 1565 if (DOINGSOFTDEP(tvp)) { 1566 /* 1567 * Ensure that the entire newly allocated block is a 1568 * valid directory so that future growth within the 1569 * block does not have to ensure that the block is 1570 * written before the inode. 1571 */ 1572 blkoff = DIRBLKSIZ; 1573 while (blkoff < bp->b_bcount) { 1574 ((struct direct *) 1575 (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ; 1576 blkoff += DIRBLKSIZ; 1577 } 1578 } 1579 if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | 1580 DOINGASYNC(tvp)))) != 0) { 1581 (void)BUF_WRITE(bp); 1582 goto bad; 1583 } 1584 /* 1585 * Directory set up, now install its entry in the parent directory. 1586 * 1587 * If we are not doing soft dependencies, then we must write out the 1588 * buffer containing the new directory body before entering the new 1589 * name in the parent. If we are doing soft dependencies, then the 1590 * buffer containing the new directory body will be passed to and 1591 * released in the soft dependency code after the code has attached 1592 * an appropriate ordering dependency to the buffer which ensures that 1593 * the buffer is written before the new name is written in the parent. 1594 */ 1595 if (DOINGASYNC(dvp)) 1596 bdwrite(bp); 1597 else if (!DOINGSOFTDEP(dvp) && ((error = BUF_WRITE(bp)))) 1598 goto bad; 1599 ufs_makedirentry(ip, cnp, &newdir); 1600 error = ufs_direnter(dvp, tvp, &newdir, cnp, bp); 1601 1602bad: 1603 if (error == 0) { 1604 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1605 *ap->a_vpp = tvp; 1606 } else { 1607 dp->i_effnlink--; 1608 dp->i_nlink--; 1609 dp->i_flag |= IN_CHANGE; 1610 if (DOINGSOFTDEP(dvp)) 1611 softdep_change_linkcnt(dp); 1612 /* 1613 * No need to do an explicit VOP_TRUNCATE here, vrele will 1614 * do this for us because we set the link count to 0. 1615 */ 1616 ip->i_effnlink = 0; 1617 ip->i_nlink = 0; 1618 ip->i_flag |= IN_CHANGE; 1619 if (DOINGSOFTDEP(tvp)) 1620 softdep_change_linkcnt(ip); 1621 vput(tvp); 1622 } 1623out: 1624 return (error); 1625} 1626 1627/* 1628 * Rmdir system call. 1629 */ 1630int 1631ufs_rmdir(ap) 1632 struct vop_rmdir_args /* { 1633 struct vnode *a_dvp; 1634 struct vnode *a_vp; 1635 struct componentname *a_cnp; 1636 } */ *ap; 1637{ 1638 struct vnode *vp = ap->a_vp; 1639 struct vnode *dvp = ap->a_dvp; 1640 struct componentname *cnp = ap->a_cnp; 1641 struct inode *ip, *dp; 1642 int error, ioflag; 1643 1644 ip = VTOI(vp); 1645 dp = VTOI(dvp); 1646 1647 /* 1648 * Do not remove a directory that is in the process of being renamed. 1649 * Verify the directory is empty (and valid). Rmdir ".." will not be 1650 * valid since ".." will contain a reference to the current directory 1651 * and thus be non-empty. Do not allow the removal of mounted on 1652 * directories (this can happen when an NFS exported filesystem 1653 * tries to remove a locally mounted on directory). 1654 */ 1655 error = 0; 1656 if (ip->i_flag & IN_RENAME) { 1657 error = EINVAL; 1658 goto out; 1659 } 1660 if (ip->i_effnlink != 2 || 1661 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { 1662 error = ENOTEMPTY; 1663 goto out; 1664 } 1665 if ((dp->i_flags & APPEND) 1666 || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) { 1667 error = EPERM; 1668 goto out; 1669 } 1670 if (vp->v_mountedhere != 0) { 1671 error = EINVAL; 1672 goto out; 1673 } 1674 /* 1675 * Delete reference to directory before purging 1676 * inode. If we crash in between, the directory 1677 * will be reattached to lost+found, 1678 */ 1679 dp->i_effnlink--; 1680 ip->i_effnlink--; 1681 if (DOINGSOFTDEP(vp)) { 1682 softdep_change_linkcnt(dp); 1683 softdep_change_linkcnt(ip); 1684 } 1685 error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1); 1686 if (error) { 1687 dp->i_effnlink++; 1688 ip->i_effnlink++; 1689 if (DOINGSOFTDEP(vp)) { 1690 softdep_change_linkcnt(dp); 1691 softdep_change_linkcnt(ip); 1692 } 1693 goto out; 1694 } 1695 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1696 cache_purge(dvp); 1697 /* 1698 * Truncate inode. The only stuff left in the directory is "." and 1699 * "..". The "." reference is inconsequential since we are quashing 1700 * it. The soft dependency code will arrange to do these operations 1701 * after the parent directory entry has been deleted on disk, so 1702 * when running with that code we avoid doing them now. 1703 */ 1704 if (!DOINGSOFTDEP(vp)) { 1705 dp->i_nlink--; 1706 dp->i_flag |= IN_CHANGE; 1707 ip->i_nlink--; 1708 ip->i_flag |= IN_CHANGE; 1709 ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC; 1710 error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred, 1711 cnp->cn_thread); 1712 } 1713 cache_purge(vp); 1714#ifdef UFS_DIRHASH 1715 /* Kill any active hash; i_effnlink == 0, so it will not come back. */ 1716 if (ip->i_dirhash != NULL) 1717 ufsdirhash_free(ip); 1718#endif 1719out: 1720 VN_KNOTE(vp, NOTE_DELETE); 1721 return (error); 1722} 1723 1724/* 1725 * symlink -- make a symbolic link 1726 */ 1727int 1728ufs_symlink(ap) 1729 struct vop_symlink_args /* { 1730 struct vnode *a_dvp; 1731 struct vnode **a_vpp; 1732 struct componentname *a_cnp; 1733 struct vattr *a_vap; 1734 char *a_target; 1735 } */ *ap; 1736{ 1737 register struct vnode *vp, **vpp = ap->a_vpp; 1738 register struct inode *ip; 1739 int len, error; 1740 1741 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, 1742 vpp, ap->a_cnp); 1743 if (error) 1744 return (error); 1745 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1746 vp = *vpp; 1747 len = strlen(ap->a_target); 1748 if (len < vp->v_mount->mnt_maxsymlinklen) { 1749 ip = VTOI(vp); 1750 bcopy(ap->a_target, (char *)ip->i_shortlink, len); 1751 ip->i_size = len; 1752 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1753 } else 1754 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, 1755 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0, 1756 (struct thread *)0); 1757 if (error) 1758 vput(vp); 1759 return (error); 1760} 1761 1762/* 1763 * Vnode op for reading directories. 1764 * 1765 * The routine below assumes that the on-disk format of a directory 1766 * is the same as that defined by <sys/dirent.h>. If the on-disk 1767 * format changes, then it will be necessary to do a conversion 1768 * from the on-disk format that read returns to the format defined 1769 * by <sys/dirent.h>. 1770 */ 1771int 1772ufs_readdir(ap) 1773 struct vop_readdir_args /* { 1774 struct vnode *a_vp; 1775 struct uio *a_uio; 1776 struct ucred *a_cred; 1777 int *a_eofflag; 1778 int *ncookies; 1779 u_long **a_cookies; 1780 } */ *ap; 1781{ 1782 register struct uio *uio = ap->a_uio; 1783 int error; 1784 size_t count, lost; 1785 off_t off; 1786 1787 if (ap->a_ncookies != NULL) 1788 /* 1789 * Ensure that the block is aligned. The caller can use 1790 * the cookies to determine where in the block to start. 1791 */ 1792 uio->uio_offset &= ~(DIRBLKSIZ - 1); 1793 off = uio->uio_offset; 1794 count = uio->uio_resid; 1795 /* Make sure we don't return partial entries. */ 1796 if (count <= ((uio->uio_offset + count) & (DIRBLKSIZ -1))) 1797 return (EINVAL); 1798 count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); 1799 lost = uio->uio_resid - count; 1800 uio->uio_resid = count; 1801 uio->uio_iov->iov_len = count; 1802# if (BYTE_ORDER == LITTLE_ENDIAN) 1803 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) { 1804 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1805 } else { 1806 struct dirent *dp, *edp; 1807 struct uio auio; 1808 struct iovec aiov; 1809 caddr_t dirbuf; 1810 int readcnt; 1811 u_char tmp; 1812 1813 auio = *uio; 1814 auio.uio_iov = &aiov; 1815 auio.uio_iovcnt = 1; 1816 auio.uio_segflg = UIO_SYSSPACE; 1817 aiov.iov_len = count; 1818 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); 1819 aiov.iov_base = dirbuf; 1820 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 1821 if (error == 0) { 1822 readcnt = count - auio.uio_resid; 1823 edp = (struct dirent *)&dirbuf[readcnt]; 1824 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1825 tmp = dp->d_namlen; 1826 dp->d_namlen = dp->d_type; 1827 dp->d_type = tmp; 1828 if (dp->d_reclen > 0) { 1829 dp = (struct dirent *) 1830 ((char *)dp + dp->d_reclen); 1831 } else { 1832 error = EIO; 1833 break; 1834 } 1835 } 1836 if (dp >= edp) 1837 error = uiomove(dirbuf, readcnt, uio); 1838 } 1839 FREE(dirbuf, M_TEMP); 1840 } 1841# else 1842 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1843# endif 1844 if (!error && ap->a_ncookies != NULL) { 1845 struct dirent* dpStart; 1846 struct dirent* dpEnd; 1847 struct dirent* dp; 1848 int ncookies; 1849 u_long *cookies; 1850 u_long *cookiep; 1851 1852 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1853 panic("ufs_readdir: unexpected uio from NFS server"); 1854 dpStart = (struct dirent *) 1855 (uio->uio_iov->iov_base - (uio->uio_offset - off)); 1856 dpEnd = (struct dirent *) uio->uio_iov->iov_base; 1857 for (dp = dpStart, ncookies = 0; 1858 dp < dpEnd; 1859 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) 1860 ncookies++; 1861 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, 1862 M_WAITOK); 1863 for (dp = dpStart, cookiep = cookies; 1864 dp < dpEnd; 1865 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 1866 off += dp->d_reclen; 1867 *cookiep++ = (u_long) off; 1868 } 1869 *ap->a_ncookies = ncookies; 1870 *ap->a_cookies = cookies; 1871 } 1872 uio->uio_resid += lost; 1873 if (ap->a_eofflag) 1874 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; 1875 return (error); 1876} 1877 1878/* 1879 * Return target name of a symbolic link 1880 */ 1881int 1882ufs_readlink(ap) 1883 struct vop_readlink_args /* { 1884 struct vnode *a_vp; 1885 struct uio *a_uio; 1886 struct ucred *a_cred; 1887 } */ *ap; 1888{ 1889 register struct vnode *vp = ap->a_vp; 1890 register struct inode *ip = VTOI(vp); 1891 int isize; 1892 1893 isize = ip->i_size; 1894 if ((isize < vp->v_mount->mnt_maxsymlinklen) || 1895 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */ 1896 uiomove((char *)ip->i_shortlink, isize, ap->a_uio); 1897 return (0); 1898 } 1899 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1900} 1901 1902/* 1903 * Calculate the logical to physical mapping if not done already, 1904 * then call the device strategy routine. 1905 * 1906 * In order to be able to swap to a file, the ufs_bmaparray() operation may not 1907 * deadlock on memory. See ufs_bmap() for details. 1908 */ 1909int 1910ufs_strategy(ap) 1911 struct vop_strategy_args /* { 1912 struct vnode *a_vp; 1913 struct buf *a_bp; 1914 } */ *ap; 1915{ 1916 register struct buf *bp = ap->a_bp; 1917 register struct vnode *vp = ap->a_vp; 1918 register struct inode *ip; 1919 daddr_t blkno; 1920 int error; 1921 1922 ip = VTOI(vp); 1923 if (vp->v_type == VBLK || vp->v_type == VCHR) 1924 panic("ufs_strategy: spec"); 1925 if (bp->b_blkno == bp->b_lblkno) { 1926 error = ufs_bmaparray(vp, bp->b_lblkno, &blkno, NULL, NULL); 1927 bp->b_blkno = blkno; 1928 if (error) { 1929 bp->b_error = error; 1930 bp->b_ioflags |= BIO_ERROR; 1931 bufdone(bp); 1932 return (error); 1933 } 1934 if ((long)bp->b_blkno == -1) 1935 vfs_bio_clrbuf(bp); 1936 } 1937 if ((long)bp->b_blkno == -1) { 1938 bufdone(bp); 1939 return (0); 1940 } 1941 vp = ip->i_devvp; 1942 bp->b_dev = vp->v_rdev; 1943 VOP_STRATEGY(vp, bp); 1944 return (0); 1945} 1946 1947/* 1948 * Print out the contents of an inode. 1949 */ 1950int 1951ufs_print(ap) 1952 struct vop_print_args /* { 1953 struct vnode *a_vp; 1954 } */ *ap; 1955{ 1956 register struct vnode *vp = ap->a_vp; 1957 register struct inode *ip = VTOI(vp); 1958 1959 printf("tag VT_UFS, ino %lu, on dev %s (%d, %d)", 1960 (u_long)ip->i_number, devtoname(ip->i_dev), major(ip->i_dev), 1961 minor(ip->i_dev)); 1962 if (vp->v_type == VFIFO) 1963 fifo_printinfo(vp); 1964 lockmgr_printinfo(&vp->v_lock); 1965 printf("\n"); 1966 return (0); 1967} 1968 1969/* 1970 * Read wrapper for special devices. 1971 */ 1972int 1973ufsspec_read(ap) 1974 struct vop_read_args /* { 1975 struct vnode *a_vp; 1976 struct uio *a_uio; 1977 int a_ioflag; 1978 struct ucred *a_cred; 1979 } */ *ap; 1980{ 1981 int error, resid; 1982 struct inode *ip; 1983 struct uio *uio; 1984 1985 uio = ap->a_uio; 1986 resid = uio->uio_resid; 1987 error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap); 1988 /* 1989 * The inode may have been revoked during the call, so it must not 1990 * be accessed blindly here or in the other wrapper functions. 1991 */ 1992 ip = VTOI(ap->a_vp); 1993 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 1994 ip->i_flag |= IN_ACCESS; 1995 return (error); 1996} 1997 1998/* 1999 * Write wrapper for special devices. 2000 */ 2001int 2002ufsspec_write(ap) 2003 struct vop_write_args /* { 2004 struct vnode *a_vp; 2005 struct uio *a_uio; 2006 int a_ioflag; 2007 struct ucred *a_cred; 2008 } */ *ap; 2009{ 2010 int error, resid; 2011 struct inode *ip; 2012 struct uio *uio; 2013 2014 uio = ap->a_uio; 2015 resid = uio->uio_resid; 2016 error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap); 2017 ip = VTOI(ap->a_vp); 2018 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 2019 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 2020 return (error); 2021} 2022 2023/* 2024 * Close wrapper for special devices. 2025 * 2026 * Update the times on the inode then do device close. 2027 */ 2028int 2029ufsspec_close(ap) 2030 struct vop_close_args /* { 2031 struct vnode *a_vp; 2032 int a_fflag; 2033 struct ucred *a_cred; 2034 struct thread *a_td; 2035 } */ *ap; 2036{ 2037 struct vnode *vp = ap->a_vp; 2038 2039 mtx_lock(&vp->v_interlock); 2040 if (vp->v_usecount > 1) 2041 ufs_itimes(vp); 2042 mtx_unlock(&vp->v_interlock); 2043 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2044} 2045 2046/* 2047 * Read wrapper for fifos. 2048 */ 2049int 2050ufsfifo_read(ap) 2051 struct vop_read_args /* { 2052 struct vnode *a_vp; 2053 struct uio *a_uio; 2054 int a_ioflag; 2055 struct ucred *a_cred; 2056 } */ *ap; 2057{ 2058 int error, resid; 2059 struct inode *ip; 2060 struct uio *uio; 2061 2062 uio = ap->a_uio; 2063 resid = uio->uio_resid; 2064 error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap); 2065 ip = VTOI(ap->a_vp); 2066 if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL && 2067 (uio->uio_resid != resid || (error == 0 && resid != 0))) 2068 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 2069 return (error); 2070} 2071 2072/* 2073 * Write wrapper for fifos. 2074 */ 2075int 2076ufsfifo_write(ap) 2077 struct vop_write_args /* { 2078 struct vnode *a_vp; 2079 struct uio *a_uio; 2080 int a_ioflag; 2081 struct ucred *a_cred; 2082 } */ *ap; 2083{ 2084 int error, resid; 2085 struct inode *ip; 2086 struct uio *uio; 2087 2088 uio = ap->a_uio; 2089 resid = uio->uio_resid; 2090 error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap); 2091 ip = VTOI(ap->a_vp); 2092 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 2093 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 2094 return (error); 2095} 2096 2097/* 2098 * Close wrapper for fifos. 2099 * 2100 * Update the times on the inode then do device close. 2101 */ 2102int 2103ufsfifo_close(ap) 2104 struct vop_close_args /* { 2105 struct vnode *a_vp; 2106 int a_fflag; 2107 struct ucred *a_cred; 2108 struct thread *a_td; 2109 } */ *ap; 2110{ 2111 struct vnode *vp = ap->a_vp; 2112 2113 mtx_lock(&vp->v_interlock); 2114 if (vp->v_usecount > 1) 2115 ufs_itimes(vp); 2116 mtx_unlock(&vp->v_interlock); 2117 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2118} 2119 2120/* 2121 * Kqfilter wrapper for fifos. 2122 * 2123 * Fall through to ufs kqfilter routines if needed 2124 */ 2125int 2126ufsfifo_kqfilter(ap) 2127 struct vop_kqfilter_args *ap; 2128{ 2129 int error; 2130 2131 error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_kqfilter), ap); 2132 if (error) 2133 error = ufs_kqfilter(ap); 2134 return (error); 2135} 2136 2137/* 2138 * Return POSIX pathconf information applicable to ufs filesystems. 2139 */ 2140int 2141ufs_pathconf(ap) 2142 struct vop_pathconf_args /* { 2143 struct vnode *a_vp; 2144 int a_name; 2145 int *a_retval; 2146 } */ *ap; 2147{ 2148 2149 switch (ap->a_name) { 2150 case _PC_LINK_MAX: 2151 *ap->a_retval = LINK_MAX; 2152 return (0); 2153 case _PC_NAME_MAX: 2154 *ap->a_retval = NAME_MAX; 2155 return (0); 2156 case _PC_PATH_MAX: 2157 *ap->a_retval = PATH_MAX; 2158 return (0); 2159 case _PC_PIPE_BUF: 2160 *ap->a_retval = PIPE_BUF; 2161 return (0); 2162 case _PC_CHOWN_RESTRICTED: 2163 *ap->a_retval = 1; 2164 return (0); 2165 case _PC_NO_TRUNC: 2166 *ap->a_retval = 1; 2167 return (0); 2168 default: 2169 return (EINVAL); 2170 } 2171 /* NOTREACHED */ 2172} 2173 2174/* 2175 * Advisory record locking support 2176 */ 2177int 2178ufs_advlock(ap) 2179 struct vop_advlock_args /* { 2180 struct vnode *a_vp; 2181 caddr_t a_id; 2182 int a_op; 2183 struct flock *a_fl; 2184 int a_flags; 2185 } */ *ap; 2186{ 2187 register struct inode *ip = VTOI(ap->a_vp); 2188 2189 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); 2190} 2191 2192/* 2193 * Initialize the vnode associated with a new inode, handle aliased 2194 * vnodes. 2195 */ 2196int 2197ufs_vinit(mntp, specops, fifoops, vpp) 2198 struct mount *mntp; 2199 vop_t **specops; 2200 vop_t **fifoops; 2201 struct vnode **vpp; 2202{ 2203 struct inode *ip; 2204 struct vnode *vp; 2205 struct timeval tv; 2206 2207 vp = *vpp; 2208 ip = VTOI(vp); 2209 switch(vp->v_type = IFTOVT(ip->i_mode)) { 2210 case VCHR: 2211 case VBLK: 2212 vp->v_op = specops; 2213 vp = addaliasu(vp, ip->i_rdev); 2214 ip->i_vnode = vp; 2215 break; 2216 case VFIFO: 2217 vp->v_op = fifoops; 2218 break; 2219 default: 2220 break; 2221 2222 } 2223 if (ip->i_number == ROOTINO) 2224 vp->v_flag |= VROOT; 2225 /* 2226 * Initialize modrev times 2227 */ 2228 getmicrouptime(&tv); 2229 SETHIGH(ip->i_modrev, tv.tv_sec); 2230 SETLOW(ip->i_modrev, tv.tv_usec * 4294); 2231 *vpp = vp; 2232 return (0); 2233} 2234 2235/* 2236 * Allocate a new inode. 2237 * Vnode dvp must be locked. 2238 */ 2239int 2240ufs_makeinode(mode, dvp, vpp, cnp) 2241 int mode; 2242 struct vnode *dvp; 2243 struct vnode **vpp; 2244 struct componentname *cnp; 2245{ 2246 register struct inode *ip, *pdir; 2247 struct direct newdir; 2248 struct vnode *tvp; 2249#ifdef UFS_ACL 2250 struct acl *acl; 2251#endif 2252 int error; 2253 2254 pdir = VTOI(dvp); 2255#ifdef DIAGNOSTIC 2256 if ((cnp->cn_flags & HASBUF) == 0) 2257 panic("ufs_makeinode: no name"); 2258#endif 2259 *vpp = NULL; 2260 if ((mode & IFMT) == 0) 2261 mode |= IFREG; 2262 2263 error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp); 2264 if (error) 2265 return (error); 2266 ip = VTOI(tvp); 2267 ip->i_gid = pdir->i_gid; 2268#ifdef SUIDDIR 2269 { 2270#ifdef QUOTA 2271 struct ucred ucred, *ucp; 2272 ucp = cnp->cn_cred; 2273#endif 2274 /* 2275 * If we are not the owner of the directory, 2276 * and we are hacking owners here, (only do this where told to) 2277 * and we are not giving it TO root, (would subvert quotas) 2278 * then go ahead and give it to the other user. 2279 * Note that this drops off the execute bits for security. 2280 */ 2281 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && 2282 (pdir->i_mode & ISUID) && 2283 (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) { 2284 ip->i_uid = pdir->i_uid; 2285 mode &= ~07111; 2286#ifdef QUOTA 2287 /* 2288 * Make sure the correct user gets charged 2289 * for the space. 2290 * Quickly knock up a dummy credential for the victim. 2291 * XXX This seems to never be accessed out of our 2292 * context so a stack variable is ok. 2293 */ 2294 ucred.cr_ref = 1; 2295 ucred.cr_uid = ip->i_uid; 2296 ucred.cr_ngroups = 1; 2297 ucred.cr_groups[0] = pdir->i_gid; 2298 ucp = &ucred; 2299#endif 2300 } else 2301 ip->i_uid = cnp->cn_cred->cr_uid; 2302 2303#ifdef QUOTA 2304 if ((error = getinoquota(ip)) || 2305 (error = chkiq(ip, 1, ucp, 0))) { 2306 UFS_VFREE(tvp, ip->i_number, mode); 2307 vput(tvp); 2308 return (error); 2309 } 2310#endif 2311 } 2312#else /* !SUIDDIR */ 2313 ip->i_uid = cnp->cn_cred->cr_uid; 2314#ifdef QUOTA 2315 if ((error = getinoquota(ip)) || 2316 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 2317 UFS_VFREE(tvp, ip->i_number, mode); 2318 vput(tvp); 2319 return (error); 2320 } 2321#endif 2322#endif /* !SUIDDIR */ 2323 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 2324#ifdef UFS_ACL 2325 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 2326 /* 2327 * Retrieve default ACL for parent, if any. 2328 */ 2329 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred, 2330 cnp->cn_thread); 2331 switch (error) { 2332 case 0: 2333 /* 2334 * Retrieved a default ACL, so merge mode and ACL if 2335 * necessary. 2336 */ 2337 if (acl->acl_cnt != 0) { 2338 /* 2339 * Two possible ways for default ACL to not be 2340 * present. First, the EA can be undefined, 2341 * or second, the default ACL can be blank. 2342 * If it's blank, fall through to the it's 2343 * not defined case. 2344 */ 2345 ip->i_mode = mode; 2346 ufs_sync_acl_from_inode(ip, acl); 2347 break; 2348 } 2349 2350 case EOPNOTSUPP: 2351 /* 2352 * Just use the mode as-is. 2353 */ 2354 ip->i_mode = mode; 2355 FREE(acl, M_ACL); 2356 acl = NULL; 2357 break; 2358 2359 default: 2360 UFS_VFREE(tvp, ip->i_number, mode); 2361 vput(tvp); 2362 return (error); 2363 } 2364#else /* !UFS_ACL */ 2365 ip->i_mode = mode; 2366#endif /* !UFS_ACL */ 2367 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ 2368 ip->i_effnlink = 1; 2369 ip->i_nlink = 1; 2370 if (DOINGSOFTDEP(tvp)) 2371 softdep_change_linkcnt(ip); 2372 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && 2373 suser_xxx(cnp->cn_cred, NULL, PRISON_ROOT)) 2374 ip->i_mode &= ~ISGID; 2375 2376 if (cnp->cn_flags & ISWHITEOUT) 2377 ip->i_flags |= UF_OPAQUE; 2378 2379 /* 2380 * Make sure inode goes to disk before directory entry. 2381 */ 2382 error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp))); 2383 if (error) 2384 goto bad; 2385#ifdef UFS_ACL 2386 if (acl != NULL) { 2387 /* 2388 * XXX: If we abort now, will Soft Updates notify the extattr 2389 * code that the EAs for the file need to be released? 2390 */ 2391 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred, 2392 cnp->cn_thread); 2393 switch (error) { 2394 case 0: 2395 break; 2396 2397 case EOPNOTSUPP: 2398 /* 2399 * XXX: This should not happen, as EOPNOTSUPP above was 2400 * supposed to free acl. 2401 */ 2402 printf("ufs_makeinode: VOP_GETACL() but no " 2403 "VOP_SETACL()\n"); 2404 /* panic("ufs_makeinode: VOP_GETACL() but no " 2405 "VOP_SETACL()"); */ 2406 break; 2407 2408 default: 2409 FREE(acl, M_ACL); 2410 goto bad; 2411 } 2412 FREE(acl, M_ACL); 2413 } 2414#endif /* !UFS_ACL */ 2415 ufs_makedirentry(ip, cnp, &newdir); 2416 error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL); 2417 if (error) 2418 goto bad; 2419 *vpp = tvp; 2420 return (0); 2421 2422bad: 2423 /* 2424 * Write error occurred trying to update the inode 2425 * or the directory so must deallocate the inode. 2426 */ 2427 ip->i_effnlink = 0; 2428 ip->i_nlink = 0; 2429 ip->i_flag |= IN_CHANGE; 2430 if (DOINGSOFTDEP(tvp)) 2431 softdep_change_linkcnt(ip); 2432 vput(tvp); 2433 return (error); 2434} 2435 2436static int 2437ufs_missingop(ap) 2438 struct vop_generic_args *ap; 2439{ 2440 2441 panic("no vop function for %s in ufs child", ap->a_desc->vdesc_name); 2442 return (EOPNOTSUPP); 2443} 2444 2445static struct filterops ufsread_filtops = 2446 { 1, NULL, filt_ufsdetach, filt_ufsread }; 2447static struct filterops ufswrite_filtops = 2448 { 1, NULL, filt_ufsdetach, filt_ufswrite }; 2449static struct filterops ufsvnode_filtops = 2450 { 1, NULL, filt_ufsdetach, filt_ufsvnode }; 2451 2452static int 2453ufs_kqfilter(ap) 2454 struct vop_kqfilter_args /* { 2455 struct vnode *a_vp; 2456 struct knote *a_kn; 2457 } */ *ap; 2458{ 2459 struct vnode *vp = ap->a_vp; 2460 struct knote *kn = ap->a_kn; 2461 2462 switch (kn->kn_filter) { 2463 case EVFILT_READ: 2464 kn->kn_fop = &ufsread_filtops; 2465 break; 2466 case EVFILT_WRITE: 2467 kn->kn_fop = &ufswrite_filtops; 2468 break; 2469 case EVFILT_VNODE: 2470 kn->kn_fop = &ufsvnode_filtops; 2471 break; 2472 default: 2473 return (1); 2474 } 2475 2476 kn->kn_hook = (caddr_t)vp; 2477 2478 if (vp->v_pollinfo == NULL) 2479 v_addpollinfo(vp); 2480 mtx_lock(&vp->v_pollinfo->vpi_lock); 2481 SLIST_INSERT_HEAD(&vp->v_pollinfo->vpi_selinfo.si_note, kn, kn_selnext); 2482 mtx_unlock(&vp->v_pollinfo->vpi_lock); 2483 2484 return (0); 2485} 2486 2487static void 2488filt_ufsdetach(struct knote *kn) 2489{ 2490 struct vnode *vp = (struct vnode *)kn->kn_hook; 2491 2492 KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo")); 2493 mtx_lock(&vp->v_pollinfo->vpi_lock); 2494 SLIST_REMOVE(&vp->v_pollinfo->vpi_selinfo.si_note, 2495 kn, knote, kn_selnext); 2496 mtx_unlock(&vp->v_pollinfo->vpi_lock); 2497} 2498 2499/*ARGSUSED*/ 2500static int 2501filt_ufsread(struct knote *kn, long hint) 2502{ 2503 struct vnode *vp = (struct vnode *)kn->kn_hook; 2504 struct inode *ip = VTOI(vp); 2505 2506 /* 2507 * filesystem is gone, so set the EOF flag and schedule 2508 * the knote for deletion. 2509 */ 2510 if (hint == NOTE_REVOKE) { 2511 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2512 return (1); 2513 } 2514 2515 kn->kn_data = ip->i_size - kn->kn_fp->f_offset; 2516 return (kn->kn_data != 0); 2517} 2518 2519/*ARGSUSED*/ 2520static int 2521filt_ufswrite(struct knote *kn, long hint) 2522{ 2523 2524 /* 2525 * filesystem is gone, so set the EOF flag and schedule 2526 * the knote for deletion. 2527 */ 2528 if (hint == NOTE_REVOKE) 2529 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2530 2531 kn->kn_data = 0; 2532 return (1); 2533} 2534 2535static int 2536filt_ufsvnode(struct knote *kn, long hint) 2537{ 2538 2539 if (kn->kn_sfflags & hint) 2540 kn->kn_fflags |= hint; 2541 if (hint == NOTE_REVOKE) { 2542 kn->kn_flags |= EV_EOF; 2543 return (1); 2544 } 2545 return (kn->kn_fflags != 0); 2546} 2547 2548/* Global vfs data structures for ufs. */ 2549static vop_t **ufs_vnodeop_p; 2550static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = { 2551 { &vop_default_desc, (vop_t *) vop_defaultop }, 2552 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2553 { &vop_read_desc, (vop_t *) ufs_missingop }, 2554 { &vop_reallocblks_desc, (vop_t *) ufs_missingop }, 2555 { &vop_write_desc, (vop_t *) ufs_missingop }, 2556 { &vop_access_desc, (vop_t *) ufs_access }, 2557 { &vop_advlock_desc, (vop_t *) ufs_advlock }, 2558 { &vop_bmap_desc, (vop_t *) ufs_bmap }, 2559 { &vop_cachedlookup_desc, (vop_t *) ufs_lookup }, 2560 { &vop_close_desc, (vop_t *) ufs_close }, 2561 { &vop_create_desc, (vop_t *) ufs_create }, 2562 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2563 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2564 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2565 { &vop_link_desc, (vop_t *) ufs_link }, 2566 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2567 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 2568 { &vop_mkdir_desc, (vop_t *) ufs_mkdir }, 2569 { &vop_mknod_desc, (vop_t *) ufs_mknod }, 2570 { &vop_open_desc, (vop_t *) ufs_open }, 2571 { &vop_pathconf_desc, (vop_t *) ufs_pathconf }, 2572 { &vop_poll_desc, (vop_t *) vop_stdpoll }, 2573 { &vop_kqfilter_desc, (vop_t *) ufs_kqfilter }, 2574 { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount }, 2575 { &vop_print_desc, (vop_t *) ufs_print }, 2576 { &vop_readdir_desc, (vop_t *) ufs_readdir }, 2577 { &vop_readlink_desc, (vop_t *) ufs_readlink }, 2578 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2579 { &vop_remove_desc, (vop_t *) ufs_remove }, 2580 { &vop_rename_desc, (vop_t *) ufs_rename }, 2581 { &vop_rmdir_desc, (vop_t *) ufs_rmdir }, 2582 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2583 { &vop_strategy_desc, (vop_t *) ufs_strategy }, 2584 { &vop_symlink_desc, (vop_t *) ufs_symlink }, 2585 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2586 { &vop_whiteout_desc, (vop_t *) ufs_whiteout }, 2587#ifdef UFS_ACL 2588 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2589 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2590 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2591#endif 2592 { NULL, NULL } 2593}; 2594static struct vnodeopv_desc ufs_vnodeop_opv_desc = 2595 { &ufs_vnodeop_p, ufs_vnodeop_entries }; 2596 2597static vop_t **ufs_specop_p; 2598static struct vnodeopv_entry_desc ufs_specop_entries[] = { 2599 { &vop_default_desc, (vop_t *) spec_vnoperate }, 2600 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2601 { &vop_access_desc, (vop_t *) ufs_access }, 2602 { &vop_close_desc, (vop_t *) ufsspec_close }, 2603 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2604 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2605 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2606 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2607 { &vop_print_desc, (vop_t *) ufs_print }, 2608 { &vop_read_desc, (vop_t *) ufsspec_read }, 2609 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2610 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2611 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2612 { &vop_write_desc, (vop_t *) ufsspec_write }, 2613#ifdef UFS_ACL 2614 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2615 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2616 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2617#endif 2618 {NULL, NULL} 2619}; 2620static struct vnodeopv_desc ufs_specop_opv_desc = 2621 { &ufs_specop_p, ufs_specop_entries }; 2622 2623static vop_t **ufs_fifoop_p; 2624static struct vnodeopv_entry_desc ufs_fifoop_entries[] = { 2625 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 2626 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2627 { &vop_access_desc, (vop_t *) ufs_access }, 2628 { &vop_close_desc, (vop_t *) ufsfifo_close }, 2629 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2630 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2631 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2632 { &vop_kqfilter_desc, (vop_t *) ufsfifo_kqfilter }, 2633 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2634 { &vop_print_desc, (vop_t *) ufs_print }, 2635 { &vop_read_desc, (vop_t *) ufsfifo_read }, 2636 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2637 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2638 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2639 { &vop_write_desc, (vop_t *) ufsfifo_write }, 2640#ifdef UFS_ACL 2641 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2642 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2643 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2644#endif 2645 { NULL, NULL } 2646}; 2647static struct vnodeopv_desc ufs_fifoop_opv_desc = 2648 { &ufs_fifoop_p, ufs_fifoop_entries }; 2649 2650VNODEOP_SET(ufs_vnodeop_opv_desc); 2651VNODEOP_SET(ufs_specop_opv_desc); 2652VNODEOP_SET(ufs_fifoop_opv_desc); 2653 2654int 2655ufs_vnoperate(ap) 2656 struct vop_generic_args /* { 2657 struct vnodeop_desc *a_desc; 2658 } */ *ap; 2659{ 2660 return (VOCALL(ufs_vnodeop_p, ap->a_desc->vdesc_offset, ap)); 2661} 2662 2663int 2664ufs_vnoperatefifo(ap) 2665 struct vop_generic_args /* { 2666 struct vnodeop_desc *a_desc; 2667 } */ *ap; 2668{ 2669 return (VOCALL(ufs_fifoop_p, ap->a_desc->vdesc_offset, ap)); 2670} 2671 2672int 2673ufs_vnoperatespec(ap) 2674 struct vop_generic_args /* { 2675 struct vnodeop_desc *a_desc; 2676 } */ *ap; 2677{ 2678 return (VOCALL(ufs_specop_p, ap->a_desc->vdesc_offset, ap)); 2679} 2680