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