ufs_vnops.c revision 11644
1/* 2 * Copyright (c) 1982, 1986, 1989, 1993 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.10 (Berkeley) 4/1/94 39 * $Id: ufs_vnops.c,v 1.30 1995/10/07 10:13:41 bde Exp $ 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/namei.h> 45#include <sys/resourcevar.h> 46#include <sys/kernel.h> 47#include <sys/file.h> 48#include <sys/stat.h> 49#include <sys/buf.h> 50#include <sys/proc.h> 51#include <sys/conf.h> 52#include <sys/mount.h> 53#include <sys/vnode.h> 54#include <sys/malloc.h> 55#include <sys/dirent.h> 56#include <sys/lockf.h> 57 58#include <vm/vm.h> 59 60#include <miscfs/specfs/specdev.h> 61#include <miscfs/fifofs/fifo.h> 62 63#include <ufs/ufs/quota.h> 64#include <ufs/ufs/inode.h> 65#include <ufs/ufs/dir.h> 66#include <ufs/ufs/ufsmount.h> 67#include <ufs/ufs/ufs_extern.h> 68 69static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct proc *)); 70static int ufs_chown 71 __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *)); 72 73union _qcvt { 74 quad_t qcvt; 75 long val[2]; 76}; 77#define SETHIGH(q, h) { \ 78 union _qcvt tmp; \ 79 tmp.qcvt = (q); \ 80 tmp.val[_QUAD_HIGHWORD] = (h); \ 81 (q) = tmp.qcvt; \ 82} 83#define SETLOW(q, l) { \ 84 union _qcvt tmp; \ 85 tmp.qcvt = (q); \ 86 tmp.val[_QUAD_LOWWORD] = (l); \ 87 (q) = tmp.qcvt; \ 88} 89 90/* 91 * Create a regular file 92 */ 93int 94ufs_create(ap) 95 struct vop_create_args /* { 96 struct vnode *a_dvp; 97 struct vnode **a_vpp; 98 struct componentname *a_cnp; 99 struct vattr *a_vap; 100 } */ *ap; 101{ 102 int error; 103 104 error = 105 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), 106 ap->a_dvp, ap->a_vpp, ap->a_cnp); 107 if (error) 108 return (error); 109 return (0); 110} 111 112/* 113 * Mknod vnode call 114 */ 115/* ARGSUSED */ 116int 117ufs_mknod(ap) 118 struct vop_mknod_args /* { 119 struct vnode *a_dvp; 120 struct vnode **a_vpp; 121 struct componentname *a_cnp; 122 struct vattr *a_vap; 123 } */ *ap; 124{ 125 struct vattr *vap = ap->a_vap; 126 struct vnode **vpp = ap->a_vpp; 127 struct inode *ip; 128 int error; 129 130 error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), 131 ap->a_dvp, vpp, ap->a_cnp); 132 if (error) 133 return (error); 134 ip = VTOI(*vpp); 135 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 136 if (vap->va_rdev != VNOVAL) { 137 /* 138 * Want to be able to use this to make badblock 139 * inodes, so don't truncate the dev number. 140 */ 141 ip->i_rdev = vap->va_rdev; 142 } 143 /* 144 * Remove inode so that it will be reloaded by VFS_VGET and 145 * checked to see if it is an alias of an existing entry in 146 * the inode cache. 147 */ 148 vput(*vpp); 149 (*vpp)->v_type = VNON; 150 vgone(*vpp); 151 *vpp = 0; 152 return (0); 153} 154 155/* 156 * Open called. 157 * 158 * Nothing to do. 159 */ 160/* ARGSUSED */ 161int 162ufs_open(ap) 163 struct vop_open_args /* { 164 struct vnode *a_vp; 165 int a_mode; 166 struct ucred *a_cred; 167 struct proc *a_p; 168 } */ *ap; 169{ 170 171 /* 172 * Files marked append-only must be opened for appending. 173 */ 174 if ((VTOI(ap->a_vp)->i_flags & APPEND) && 175 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 176 return (EPERM); 177 return (0); 178} 179 180/* 181 * Close called. 182 * 183 * Update the times on the inode. 184 */ 185/* ARGSUSED */ 186int 187ufs_close(ap) 188 struct vop_close_args /* { 189 struct vnode *a_vp; 190 int a_fflag; 191 struct ucred *a_cred; 192 struct proc *a_p; 193 } */ *ap; 194{ 195 register struct vnode *vp = ap->a_vp; 196 register struct inode *ip = VTOI(vp); 197 198 if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) 199 ITIMES(ip, &time, &time); 200 return (0); 201} 202 203int 204ufs_access(ap) 205 struct vop_access_args /* { 206 struct vnode *a_vp; 207 int a_mode; 208 struct ucred *a_cred; 209 struct proc *a_p; 210 } */ *ap; 211{ 212 struct vnode *vp = ap->a_vp; 213 struct inode *ip = VTOI(vp); 214 struct ucred *cred = ap->a_cred; 215 mode_t mask, mode = ap->a_mode; 216 register gid_t *gp; 217 int i, error; 218 219 /* 220 * Disallow write attempts on read-only file systems; 221 * unless the file is a socket, fifo, or a block or 222 * character device resident on the file system. 223 */ 224 if (mode & VWRITE) { 225 switch (vp->v_type) { 226 case VDIR: 227 case VLNK: 228 case VREG: 229 if (vp->v_mount->mnt_flag & MNT_RDONLY) 230 return (EROFS); 231#ifdef QUOTA 232 if (error = getinoquota(ip)) 233 return (error); 234#endif 235 break; 236 } 237 } 238 239 /* If immutable bit set, nobody gets to write it. */ 240 if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE)) 241 return (EPERM); 242 243 /* Otherwise, user id 0 always gets access. */ 244 if (cred->cr_uid == 0) 245 return (0); 246 247 mask = 0; 248 249 /* Otherwise, check the owner. */ 250 if (cred->cr_uid == ip->i_uid) { 251 if (mode & VEXEC) 252 mask |= S_IXUSR; 253 if (mode & VREAD) 254 mask |= S_IRUSR; 255 if (mode & VWRITE) 256 mask |= S_IWUSR; 257 return ((ip->i_mode & mask) == mask ? 0 : EACCES); 258 } 259 260 /* Otherwise, check the groups. */ 261 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 262 if (ip->i_gid == *gp) { 263 if (mode & VEXEC) 264 mask |= S_IXGRP; 265 if (mode & VREAD) 266 mask |= S_IRGRP; 267 if (mode & VWRITE) 268 mask |= S_IWGRP; 269 return ((ip->i_mode & mask) == mask ? 0 : EACCES); 270 } 271 272 /* Otherwise, check everyone else. */ 273 if (mode & VEXEC) 274 mask |= S_IXOTH; 275 if (mode & VREAD) 276 mask |= S_IROTH; 277 if (mode & VWRITE) 278 mask |= S_IWOTH; 279 return ((ip->i_mode & mask) == mask ? 0 : EACCES); 280} 281 282/* ARGSUSED */ 283int 284ufs_getattr(ap) 285 struct vop_getattr_args /* { 286 struct vnode *a_vp; 287 struct vattr *a_vap; 288 struct ucred *a_cred; 289 struct proc *a_p; 290 } */ *ap; 291{ 292 register struct vnode *vp = ap->a_vp; 293 register struct inode *ip = VTOI(vp); 294 register struct vattr *vap = ap->a_vap; 295 296 ITIMES(ip, &time, &time); 297 /* 298 * Copy from inode table 299 */ 300 vap->va_fsid = ip->i_dev; 301 vap->va_fileid = ip->i_number; 302 vap->va_mode = ip->i_mode & ~IFMT; 303 vap->va_nlink = ip->i_nlink; 304 vap->va_uid = ip->i_uid; 305 vap->va_gid = ip->i_gid; 306 vap->va_rdev = (dev_t)ip->i_rdev; 307 vap->va_size = ip->i_din.di_size; 308 vap->va_atime = ip->i_atime; 309 vap->va_mtime = ip->i_mtime; 310 vap->va_ctime = ip->i_ctime; 311 vap->va_flags = ip->i_flags; 312 vap->va_gen = ip->i_gen; 313 /* this doesn't belong here */ 314 if (vp->v_type == VBLK) 315 vap->va_blocksize = BLKDEV_IOSIZE; 316 else if (vp->v_type == VCHR) 317 vap->va_blocksize = MAXBSIZE; 318 else 319 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 320 vap->va_bytes = dbtob(ip->i_blocks); 321 vap->va_type = vp->v_type; 322 vap->va_filerev = ip->i_modrev; 323 return (0); 324} 325 326/* 327 * Set attribute vnode op. called from several syscalls 328 */ 329int 330ufs_setattr(ap) 331 struct vop_setattr_args /* { 332 struct vnode *a_vp; 333 struct vattr *a_vap; 334 struct ucred *a_cred; 335 struct proc *a_p; 336 } */ *ap; 337{ 338 struct vattr *vap = ap->a_vap; 339 struct vnode *vp = ap->a_vp; 340 struct inode *ip = VTOI(vp); 341 struct ucred *cred = ap->a_cred; 342 struct proc *p = ap->a_p; 343 struct timeval atimeval, mtimeval; 344 int error; 345 346 /* 347 * Check for unsettable attributes. 348 */ 349 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 350 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 351 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 352 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 353 return (EINVAL); 354 } 355 if (vap->va_flags != VNOVAL) { 356 if (vp->v_mount->mnt_flag & MNT_RDONLY) 357 return (EROFS); 358 if (cred->cr_uid != ip->i_uid && 359 (error = suser(cred, &p->p_acflag))) 360 return (error); 361 if (cred->cr_uid == 0) { 362 if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) && 363 securelevel > 0) 364 return (EPERM); 365 ip->i_flags = vap->va_flags; 366 } else { 367 if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) 368 return (EPERM); 369 ip->i_flags &= SF_SETTABLE; 370 ip->i_flags |= (vap->va_flags & UF_SETTABLE); 371 } 372 ip->i_flag |= IN_CHANGE; 373 if (vap->va_flags & (IMMUTABLE | APPEND)) 374 return (0); 375 } 376 if (ip->i_flags & (IMMUTABLE | APPEND)) 377 return (EPERM); 378 /* 379 * Go through the fields and update iff not VNOVAL. 380 */ 381 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 382 if (vp->v_mount->mnt_flag & MNT_RDONLY) 383 return (EROFS); 384 error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p); 385 if (error) 386 return (error); 387 } 388 if (vap->va_size != VNOVAL) { 389 /* 390 * Disallow write attempts on read-only file systems; 391 * unless the file is a socket, fifo, or a block or 392 * character device resident on the file system. 393 */ 394 switch (vp->v_type) { 395 case VDIR: 396 return (EISDIR); 397 case VLNK: 398 case VREG: 399 if (vp->v_mount->mnt_flag & MNT_RDONLY) 400 return (EROFS); 401 break; 402 } 403 error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p); 404 if (error) 405 return (error); 406 } 407 ip = VTOI(vp); 408 if (vap->va_atime.ts_sec != VNOVAL || vap->va_mtime.ts_sec != VNOVAL) { 409 if (vp->v_mount->mnt_flag & MNT_RDONLY) 410 return (EROFS); 411 if (cred->cr_uid != ip->i_uid && 412 (error = suser(cred, &p->p_acflag)) && 413 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 414 (error = VOP_ACCESS(vp, VWRITE, cred, p)))) 415 return (error); 416 if (vap->va_atime.ts_sec != VNOVAL) 417 ip->i_flag |= IN_ACCESS; 418 if (vap->va_mtime.ts_sec != VNOVAL) 419 ip->i_flag |= IN_CHANGE | IN_UPDATE; 420 atimeval.tv_sec = vap->va_atime.ts_sec; 421 atimeval.tv_usec = vap->va_atime.ts_nsec / 1000; 422 mtimeval.tv_sec = vap->va_mtime.ts_sec; 423 mtimeval.tv_usec = vap->va_mtime.ts_nsec / 1000; 424 error = VOP_UPDATE(vp, &atimeval, &mtimeval, 1); 425 if (error) 426 return (error); 427 } 428 error = 0; 429 if (vap->va_mode != (mode_t)VNOVAL) { 430 if (vp->v_mount->mnt_flag & MNT_RDONLY) 431 return (EROFS); 432 error = ufs_chmod(vp, (int)vap->va_mode, cred, p); 433 } 434 return (error); 435} 436 437/* 438 * Change the mode on a file. 439 * Inode must be locked before calling. 440 */ 441static int 442ufs_chmod(vp, mode, cred, p) 443 register struct vnode *vp; 444 register int mode; 445 register struct ucred *cred; 446 struct proc *p; 447{ 448 register struct inode *ip = VTOI(vp); 449 int error; 450 451 if (cred->cr_uid != ip->i_uid) { 452 error = suser(cred, &p->p_acflag); 453 if (error) 454 return (error); 455 } 456 if (cred->cr_uid) { 457 if (vp->v_type != VDIR && (mode & S_ISTXT)) 458 return (EFTYPE); 459 if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) 460 return (EPERM); 461 } 462 ip->i_mode &= ~ALLPERMS; 463 ip->i_mode |= (mode & ALLPERMS); 464 ip->i_flag |= IN_CHANGE; 465/* 466 if ((vp->v_flag & VTEXT) && (ip->i_mode & S_ISTXT) == 0) 467 (void) vnode_pager_uncache(vp); 468*/ 469 return (0); 470} 471 472/* 473 * Perform chown operation on inode ip; 474 * inode must be locked prior to call. 475 */ 476static int 477ufs_chown(vp, uid, gid, cred, p) 478 register struct vnode *vp; 479 uid_t uid; 480 gid_t gid; 481 struct ucred *cred; 482 struct proc *p; 483{ 484 register struct inode *ip = VTOI(vp); 485 uid_t ouid; 486 gid_t ogid; 487 int error = 0; 488#ifdef QUOTA 489 register int i; 490 long change; 491#endif 492 493 if (uid == (uid_t)VNOVAL) 494 uid = ip->i_uid; 495 if (gid == (gid_t)VNOVAL) 496 gid = ip->i_gid; 497 /* 498 * If we don't own the file, are trying to change the owner 499 * of the file, or are not a member of the target group, 500 * the caller must be superuser or the call fails. 501 */ 502 if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid || 503 (gid != ip->i_gid && !groupmember((gid_t)gid, cred))) && 504 (error = suser(cred, &p->p_acflag))) 505 return (error); 506 ogid = ip->i_gid; 507 ouid = ip->i_uid; 508#ifdef QUOTA 509 if (error = getinoquota(ip)) 510 return (error); 511 if (ouid == uid) { 512 dqrele(vp, ip->i_dquot[USRQUOTA]); 513 ip->i_dquot[USRQUOTA] = NODQUOT; 514 } 515 if (ogid == gid) { 516 dqrele(vp, ip->i_dquot[GRPQUOTA]); 517 ip->i_dquot[GRPQUOTA] = NODQUOT; 518 } 519 change = ip->i_blocks; 520 (void) chkdq(ip, -change, cred, CHOWN); 521 (void) chkiq(ip, -1, cred, CHOWN); 522 for (i = 0; i < MAXQUOTAS; i++) { 523 dqrele(vp, ip->i_dquot[i]); 524 ip->i_dquot[i] = NODQUOT; 525 } 526#endif 527 ip->i_gid = gid; 528 ip->i_uid = uid; 529#ifdef QUOTA 530 if ((error = getinoquota(ip)) == 0) { 531 if (ouid == uid) { 532 dqrele(vp, ip->i_dquot[USRQUOTA]); 533 ip->i_dquot[USRQUOTA] = NODQUOT; 534 } 535 if (ogid == gid) { 536 dqrele(vp, ip->i_dquot[GRPQUOTA]); 537 ip->i_dquot[GRPQUOTA] = NODQUOT; 538 } 539 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) { 540 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0) 541 goto good; 542 else 543 (void) chkdq(ip, -change, cred, CHOWN|FORCE); 544 } 545 for (i = 0; i < MAXQUOTAS; i++) { 546 dqrele(vp, ip->i_dquot[i]); 547 ip->i_dquot[i] = NODQUOT; 548 } 549 } 550 ip->i_gid = ogid; 551 ip->i_uid = ouid; 552 if (getinoquota(ip) == 0) { 553 if (ouid == uid) { 554 dqrele(vp, ip->i_dquot[USRQUOTA]); 555 ip->i_dquot[USRQUOTA] = NODQUOT; 556 } 557 if (ogid == gid) { 558 dqrele(vp, ip->i_dquot[GRPQUOTA]); 559 ip->i_dquot[GRPQUOTA] = NODQUOT; 560 } 561 (void) chkdq(ip, change, cred, FORCE|CHOWN); 562 (void) chkiq(ip, 1, cred, FORCE|CHOWN); 563 (void) getinoquota(ip); 564 } 565 return (error); 566good: 567 if (getinoquota(ip)) 568 panic("chown: lost quota"); 569#endif /* QUOTA */ 570 if (ouid != uid || ogid != gid) 571 ip->i_flag |= IN_CHANGE; 572 if (ouid != uid && cred->cr_uid != 0) 573 ip->i_mode &= ~ISUID; 574 if (ogid != gid && cred->cr_uid != 0) 575 ip->i_mode &= ~ISGID; 576 return (0); 577} 578 579/* ARGSUSED */ 580int 581ufs_ioctl(ap) 582 struct vop_ioctl_args /* { 583 struct vnode *a_vp; 584 int a_command; 585 caddr_t a_data; 586 int a_fflag; 587 struct ucred *a_cred; 588 struct proc *a_p; 589 } */ *ap; 590{ 591 592 return (ENOTTY); 593} 594 595/* ARGSUSED */ 596int 597ufs_select(ap) 598 struct vop_select_args /* { 599 struct vnode *a_vp; 600 int a_which; 601 int a_fflags; 602 struct ucred *a_cred; 603 struct proc *a_p; 604 } */ *ap; 605{ 606 607 /* 608 * We should really check to see if I/O is possible. 609 */ 610 return (1); 611} 612 613/* 614 * Mmap a file 615 * 616 * NB Currently unsupported. 617 */ 618/* ARGSUSED */ 619int 620ufs_mmap(ap) 621 struct vop_mmap_args /* { 622 struct vnode *a_vp; 623 int a_fflags; 624 struct ucred *a_cred; 625 struct proc *a_p; 626 } */ *ap; 627{ 628 629 return (EINVAL); 630} 631 632/* 633 * Seek on a file 634 * 635 * Nothing to do, so just return. 636 */ 637/* ARGSUSED */ 638int 639ufs_seek(ap) 640 struct vop_seek_args /* { 641 struct vnode *a_vp; 642 off_t a_oldoff; 643 off_t a_newoff; 644 struct ucred *a_cred; 645 } */ *ap; 646{ 647 648 return (0); 649} 650 651int 652ufs_remove(ap) 653 struct vop_remove_args /* { 654 struct vnode *a_dvp; 655 struct vnode *a_vp; 656 struct componentname *a_cnp; 657 } */ *ap; 658{ 659 struct inode *ip; 660 struct vnode *vp = ap->a_vp; 661 struct vnode *dvp = ap->a_dvp; 662 int error; 663 664 ip = VTOI(vp); 665 if ((ip->i_flags & (IMMUTABLE | APPEND)) || 666 (VTOI(dvp)->i_flags & APPEND)) { 667 error = EPERM; 668 goto out; 669 } 670 if ((error = ufs_dirremove(dvp, ap->a_cnp)) == 0) { 671 ip->i_nlink--; 672 ip->i_flag |= IN_CHANGE; 673 } 674out: 675 if (dvp == vp) 676 vrele(vp); 677 else 678 vput(vp); 679 vput(dvp); 680 return (error); 681} 682 683/* 684 * link vnode call 685 */ 686int 687ufs_link(ap) 688 struct vop_link_args /* { 689 struct vnode *a_tdvp; 690 struct vnode *a_vp; 691 struct componentname *a_cnp; 692 } */ *ap; 693{ 694 struct vnode *vp = ap->a_vp; 695 struct vnode *tdvp = ap->a_tdvp; 696 struct componentname *cnp = ap->a_cnp; 697 struct inode *ip; 698 struct timeval tv; 699 int error; 700 701#ifdef DIAGNOSTIC 702 if ((cnp->cn_flags & HASBUF) == 0) 703 panic("ufs_link: no name"); 704#endif 705 if (vp->v_mount != tdvp->v_mount) { 706 VOP_ABORTOP(tdvp, cnp); 707 error = EXDEV; 708 goto out2; 709 } 710 if (vp != tdvp && (error = VOP_LOCK(vp))) { 711 VOP_ABORTOP(tdvp, cnp); 712 goto out2; 713 } 714 ip = VTOI(vp); 715 if ((nlink_t)ip->i_nlink >= LINK_MAX) { 716 VOP_ABORTOP(tdvp, cnp); 717 error = EMLINK; 718 goto out1; 719 } 720 if (ip->i_flags & (IMMUTABLE | APPEND)) { 721 VOP_ABORTOP(tdvp, cnp); 722 error = EPERM; 723 goto out1; 724 } 725 ip->i_nlink++; 726 ip->i_flag |= IN_CHANGE; 727 tv = time; 728 error = VOP_UPDATE(vp, &tv, &tv, 1); 729 if (!error) 730 error = ufs_direnter(ip, tdvp, cnp); 731 if (error) { 732 ip->i_nlink--; 733 ip->i_flag |= IN_CHANGE; 734 } 735 FREE(cnp->cn_pnbuf, M_NAMEI); 736out1: 737 if (vp != tdvp) 738 VOP_UNLOCK(vp); 739out2: 740 vput(tdvp); 741 return (error); 742} 743 744 745/* 746 * Rename system call. 747 * rename("foo", "bar"); 748 * is essentially 749 * unlink("bar"); 750 * link("foo", "bar"); 751 * unlink("foo"); 752 * but ``atomically''. Can't do full commit without saving state in the 753 * inode on disk which isn't feasible at this time. Best we can do is 754 * always guarantee the target exists. 755 * 756 * Basic algorithm is: 757 * 758 * 1) Bump link count on source while we're linking it to the 759 * target. This also ensure the inode won't be deleted out 760 * from underneath us while we work (it may be truncated by 761 * a concurrent `trunc' or `open' for creation). 762 * 2) Link source to destination. If destination already exists, 763 * delete it first. 764 * 3) Unlink source reference to inode if still around. If a 765 * directory was moved and the parent of the destination 766 * is different from the source, patch the ".." entry in the 767 * directory. 768 */ 769int 770ufs_rename(ap) 771 struct vop_rename_args /* { 772 struct vnode *a_fdvp; 773 struct vnode *a_fvp; 774 struct componentname *a_fcnp; 775 struct vnode *a_tdvp; 776 struct vnode *a_tvp; 777 struct componentname *a_tcnp; 778 } */ *ap; 779{ 780 struct vnode *tvp = ap->a_tvp; 781 register struct vnode *tdvp = ap->a_tdvp; 782 struct vnode *fvp = ap->a_fvp; 783 struct vnode *fdvp = ap->a_fdvp; 784 struct componentname *tcnp = ap->a_tcnp; 785 struct componentname *fcnp = ap->a_fcnp; 786 struct inode *ip, *xp, *dp; 787 struct dirtemplate dirbuf; 788 struct timeval tv; 789 int doingdirectory = 0, oldparent = 0, newparent = 0; 790 int error = 0; 791 u_char namlen; 792 793#ifdef DIAGNOSTIC 794 if ((tcnp->cn_flags & HASBUF) == 0 || 795 (fcnp->cn_flags & HASBUF) == 0) 796 panic("ufs_rename: no name"); 797#endif 798 /* 799 * Check for cross-device rename. 800 */ 801 if ((fvp->v_mount != tdvp->v_mount) || 802 (tvp && (fvp->v_mount != tvp->v_mount))) { 803 error = EXDEV; 804abortit: 805 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */ 806 if (tdvp == tvp) 807 vrele(tdvp); 808 else 809 vput(tdvp); 810 if (tvp) 811 vput(tvp); 812 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */ 813 vrele(fdvp); 814 vrele(fvp); 815 return (error); 816 } 817 818 /* 819 * Check if just deleting a link name. 820 */ 821 if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) || 822 (VTOI(tdvp)->i_flags & APPEND))) { 823 error = EPERM; 824 goto abortit; 825 } 826 if (fvp == tvp) { 827 if (fvp->v_type == VDIR) { 828 error = EINVAL; 829 goto abortit; 830 } 831 832 /* Release destination completely. */ 833 VOP_ABORTOP(tdvp, tcnp); 834 vput(tdvp); 835 vput(tvp); 836 837 /* Delete source. */ 838 vrele(fdvp); 839 vrele(fvp); 840 fcnp->cn_flags &= ~MODMASK; 841 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 842 if ((fcnp->cn_flags & SAVESTART) == 0) 843 panic("ufs_rename: lost from startdir"); 844 fcnp->cn_nameiop = DELETE; 845 (void) relookup(fdvp, &fvp, fcnp); 846 return (VOP_REMOVE(fdvp, fvp, fcnp)); 847 } 848 error = VOP_LOCK(fvp); 849 if (error) 850 goto abortit; 851 dp = VTOI(fdvp); 852 ip = VTOI(fvp); 853 if ((ip->i_flags & (IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { 854 VOP_UNLOCK(fvp); 855 error = EPERM; 856 goto abortit; 857 } 858 if ((ip->i_mode & IFMT) == IFDIR) { 859 /* 860 * Avoid ".", "..", and aliases of "." for obvious reasons. 861 */ 862 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 863 dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT || 864 (ip->i_flag & IN_RENAME)) { 865 VOP_UNLOCK(fvp); 866 error = EINVAL; 867 goto abortit; 868 } 869 ip->i_flag |= IN_RENAME; 870 oldparent = dp->i_number; 871 doingdirectory++; 872 } 873 vrele(fdvp); 874 875 /* 876 * When the target exists, both the directory 877 * and target vnodes are returned locked. 878 */ 879 dp = VTOI(tdvp); 880 xp = NULL; 881 if (tvp) 882 xp = VTOI(tvp); 883 884 /* 885 * 1) Bump link count while we're moving stuff 886 * around. If we crash somewhere before 887 * completing our work, the link count 888 * may be wrong, but correctable. 889 */ 890 ip->i_nlink++; 891 ip->i_flag |= IN_CHANGE; 892 tv = time; 893 error = VOP_UPDATE(fvp, &tv, &tv, 1); 894 if (error) { 895 VOP_UNLOCK(fvp); 896 goto bad; 897 } 898 899 /* 900 * If ".." must be changed (ie the directory gets a new 901 * parent) then the source directory must not be in the 902 * directory heirarchy above the target, as this would 903 * orphan everything below the source directory. Also 904 * the user must have write permission in the source so 905 * as to be able to change "..". We must repeat the call 906 * to namei, as the parent directory is unlocked by the 907 * call to checkpath(). 908 */ 909 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); 910 VOP_UNLOCK(fvp); 911 if (oldparent != dp->i_number) 912 newparent = dp->i_number; 913 if (doingdirectory && newparent) { 914 if (error) /* write access check above */ 915 goto bad; 916 if (xp != NULL) 917 vput(tvp); 918 error = ufs_checkpath(ip, dp, tcnp->cn_cred); 919 if (error) 920 goto out; 921 if ((tcnp->cn_flags & SAVESTART) == 0) 922 panic("ufs_rename: lost to startdir"); 923 error = relookup(tdvp, &tvp, tcnp); 924 if (error) 925 goto out; 926 dp = VTOI(tdvp); 927 xp = NULL; 928 if (tvp) 929 xp = VTOI(tvp); 930 } 931 /* 932 * 2) If target doesn't exist, link the target 933 * to the source and unlink the source. 934 * Otherwise, rewrite the target directory 935 * entry to reference the source inode and 936 * expunge the original entry's existence. 937 */ 938 if (xp == NULL) { 939 if (dp->i_dev != ip->i_dev) 940 panic("rename: EXDEV"); 941 /* 942 * Account for ".." in new directory. 943 * When source and destination have the same 944 * parent we don't fool with the link count. 945 */ 946 if (doingdirectory && newparent) { 947 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 948 error = EMLINK; 949 goto bad; 950 } 951 dp->i_nlink++; 952 dp->i_flag |= IN_CHANGE; 953 error = VOP_UPDATE(tdvp, &tv, &tv, 1); 954 if (error) 955 goto bad; 956 } 957 error = ufs_direnter(ip, tdvp, tcnp); 958 if (error) { 959 if (doingdirectory && newparent) { 960 dp->i_nlink--; 961 dp->i_flag |= IN_CHANGE; 962 (void)VOP_UPDATE(tdvp, &tv, &tv, 1); 963 } 964 goto bad; 965 } 966 vput(tdvp); 967 } else { 968 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) 969 panic("rename: EXDEV"); 970 /* 971 * Short circuit rename(foo, foo). 972 */ 973 if (xp->i_number == ip->i_number) 974 panic("rename: same file"); 975 /* 976 * If the parent directory is "sticky", then the user must 977 * own the parent directory, or the destination of the rename, 978 * otherwise the destination may not be changed (except by 979 * root). This implements append-only directories. 980 */ 981 if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 && 982 tcnp->cn_cred->cr_uid != dp->i_uid && 983 xp->i_uid != tcnp->cn_cred->cr_uid) { 984 error = EPERM; 985 goto bad; 986 } 987 /* 988 * Target must be empty if a directory and have no links 989 * to it. Also, ensure source and target are compatible 990 * (both directories, or both not directories). 991 */ 992 if ((xp->i_mode&IFMT) == IFDIR) { 993 if (!ufs_dirempty(xp, dp->i_number, tcnp->cn_cred) || 994 xp->i_nlink > 2) { 995 error = ENOTEMPTY; 996 goto bad; 997 } 998 if (!doingdirectory) { 999 error = ENOTDIR; 1000 goto bad; 1001 } 1002 cache_purge(tdvp); 1003 } else if (doingdirectory) { 1004 error = EISDIR; 1005 goto bad; 1006 } 1007 error = ufs_dirrewrite(dp, ip, tcnp); 1008 if (error) 1009 goto bad; 1010 /* 1011 * If the target directory is in the same 1012 * directory as the source directory, 1013 * decrement the link count on the parent 1014 * of the target directory. 1015 */ 1016 if (doingdirectory && !newparent) { 1017 dp->i_nlink--; 1018 dp->i_flag |= IN_CHANGE; 1019 } 1020 vput(tdvp); 1021 /* 1022 * Adjust the link count of the target to 1023 * reflect the dirrewrite above. If this is 1024 * a directory it is empty and there are 1025 * no links to it, so we can squash the inode and 1026 * any space associated with it. We disallowed 1027 * renaming over top of a directory with links to 1028 * it above, as the remaining link would point to 1029 * a directory without "." or ".." entries. 1030 */ 1031 xp->i_nlink--; 1032 if (doingdirectory) { 1033 if (--xp->i_nlink != 0) 1034 panic("rename: linked directory"); 1035 error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC, 1036 tcnp->cn_cred, tcnp->cn_proc); 1037 } 1038 xp->i_flag |= IN_CHANGE; 1039 vput(tvp); 1040 xp = NULL; 1041 } 1042 1043 /* 1044 * 3) Unlink the source. 1045 */ 1046 fcnp->cn_flags &= ~MODMASK; 1047 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1048 if ((fcnp->cn_flags & SAVESTART) == 0) 1049 panic("ufs_rename: lost from startdir"); 1050 (void) relookup(fdvp, &fvp, fcnp); 1051 if (fvp != NULL) { 1052 xp = VTOI(fvp); 1053 dp = VTOI(fdvp); 1054 } else { 1055 /* 1056 * From name has disappeared. 1057 */ 1058 if (doingdirectory) 1059 panic("rename: lost dir entry"); 1060 vrele(ap->a_fvp); 1061 return (0); 1062 } 1063 /* 1064 * Ensure that the directory entry still exists and has not 1065 * changed while the new name has been entered. If the source is 1066 * a file then the entry may have been unlinked or renamed. In 1067 * either case there is no further work to be done. If the source 1068 * is a directory then it cannot have been rmdir'ed; its link 1069 * count of three would cause a rmdir to fail with ENOTEMPTY. 1070 * The IN_RENAME flag ensures that it cannot be moved by another 1071 * rename. 1072 */ 1073 if (xp != ip) { 1074 if (doingdirectory) 1075 panic("rename: lost dir entry"); 1076 } else { 1077 /* 1078 * If the source is a directory with a 1079 * new parent, the link count of the old 1080 * parent directory must be decremented 1081 * and ".." set to point to the new parent. 1082 */ 1083 if (doingdirectory && newparent) { 1084 dp->i_nlink--; 1085 dp->i_flag |= IN_CHANGE; 1086 error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf, 1087 sizeof (struct dirtemplate), (off_t)0, 1088 UIO_SYSSPACE, IO_NODELOCKED, 1089 tcnp->cn_cred, (int *)0, (struct proc *)0); 1090 if (error == 0) { 1091# if (BYTE_ORDER == LITTLE_ENDIAN) 1092 if (fvp->v_mount->mnt_maxsymlinklen <= 0) 1093 namlen = dirbuf.dotdot_type; 1094 else 1095 namlen = dirbuf.dotdot_namlen; 1096# else 1097 namlen = dirbuf.dotdot_namlen; 1098# endif 1099 if (namlen != 2 || 1100 dirbuf.dotdot_name[0] != '.' || 1101 dirbuf.dotdot_name[1] != '.') { 1102 ufs_dirbad(xp, (doff_t)12, 1103 "rename: mangled dir"); 1104 } else { 1105 dirbuf.dotdot_ino = newparent; 1106 (void) vn_rdwr(UIO_WRITE, fvp, 1107 (caddr_t)&dirbuf, 1108 sizeof (struct dirtemplate), 1109 (off_t)0, UIO_SYSSPACE, 1110 IO_NODELOCKED|IO_SYNC, 1111 tcnp->cn_cred, (int *)0, 1112 (struct proc *)0); 1113 cache_purge(fdvp); 1114 } 1115 } 1116 } 1117 error = ufs_dirremove(fdvp, fcnp); 1118 if (!error) { 1119 xp->i_nlink--; 1120 xp->i_flag |= IN_CHANGE; 1121 } 1122 xp->i_flag &= ~IN_RENAME; 1123 } 1124 if (dp) 1125 vput(fdvp); 1126 if (xp) 1127 vput(fvp); 1128 vrele(ap->a_fvp); 1129 return (error); 1130 1131bad: 1132 if (xp) 1133 vput(ITOV(xp)); 1134 vput(ITOV(dp)); 1135out: 1136 if (VOP_LOCK(fvp) == 0) { 1137 ip->i_nlink--; 1138 ip->i_flag |= IN_CHANGE; 1139 ip->i_flag &= ~IN_RENAME; 1140 vput(fvp); 1141 } else 1142 vrele(fvp); 1143 return (error); 1144} 1145 1146/* 1147 * A virgin directory (no blushing please). 1148 */ 1149static struct dirtemplate mastertemplate = { 1150 0, 12, DT_DIR, 1, { '.', 0 }, 1151 0, DIRBLKSIZ - 12, DT_DIR, 2, { '.', '.', 0 } 1152}; 1153static struct odirtemplate omastertemplate = { 1154 0, 12, 1, { '.', 0 }, 1155 0, DIRBLKSIZ - 12, 2, { '.', '.', 0 } 1156}; 1157 1158/* 1159 * Mkdir system call 1160 */ 1161int 1162ufs_mkdir(ap) 1163 struct vop_mkdir_args /* { 1164 struct vnode *a_dvp; 1165 struct vnode **a_vpp; 1166 struct componentname *a_cnp; 1167 struct vattr *a_vap; 1168 } */ *ap; 1169{ 1170 register struct vnode *dvp = ap->a_dvp; 1171 register struct vattr *vap = ap->a_vap; 1172 register struct componentname *cnp = ap->a_cnp; 1173 register struct inode *ip, *dp; 1174 struct vnode *tvp; 1175 struct dirtemplate dirtemplate, *dtp; 1176 struct timeval tv; 1177 int error, dmode; 1178 1179#ifdef DIAGNOSTIC 1180 if ((cnp->cn_flags & HASBUF) == 0) 1181 panic("ufs_mkdir: no name"); 1182#endif 1183 dp = VTOI(dvp); 1184 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1185 error = EMLINK; 1186 goto out; 1187 } 1188 dmode = vap->va_mode & 0777; 1189 dmode |= IFDIR; 1190 /* 1191 * Must simulate part of ufs_makeinode here to acquire the inode, 1192 * but not have it entered in the parent directory. The entry is 1193 * made later after writing "." and ".." entries. 1194 */ 1195 error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp); 1196 if (error) 1197 goto out; 1198 ip = VTOI(tvp); 1199 ip->i_uid = cnp->cn_cred->cr_uid; 1200 ip->i_gid = dp->i_gid; 1201#ifdef QUOTA 1202 if ((error = getinoquota(ip)) || 1203 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1204 free(cnp->cn_pnbuf, M_NAMEI); 1205 VOP_VFREE(tvp, ip->i_number, dmode); 1206 vput(tvp); 1207 vput(dvp); 1208 return (error); 1209 } 1210#endif 1211 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1212 ip->i_mode = dmode; 1213 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ 1214 ip->i_nlink = 2; 1215 tv = time; 1216 error = VOP_UPDATE(tvp, &tv, &tv, 1); 1217 1218 /* 1219 * Bump link count in parent directory 1220 * to reflect work done below. Should 1221 * be done before reference is created 1222 * so reparation is possible if we crash. 1223 */ 1224 dp->i_nlink++; 1225 dp->i_flag |= IN_CHANGE; 1226 error = VOP_UPDATE(dvp, &tv, &tv, 1); 1227 if (error) 1228 goto bad; 1229 1230 /* Initialize directory with "." and ".." from static template. */ 1231 if (dvp->v_mount->mnt_maxsymlinklen > 0) 1232 dtp = &mastertemplate; 1233 else 1234 dtp = (struct dirtemplate *)&omastertemplate; 1235 dirtemplate = *dtp; 1236 dirtemplate.dot_ino = ip->i_number; 1237 dirtemplate.dotdot_ino = dp->i_number; 1238 error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate, 1239 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, 1240 IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0); 1241 if (error) { 1242 dp->i_nlink--; 1243 dp->i_flag |= IN_CHANGE; 1244 goto bad; 1245 } 1246 if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 1247 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */ 1248 else { 1249 ip->i_size = DIRBLKSIZ; 1250 ip->i_flag |= IN_CHANGE; 1251 } 1252 1253 /* Directory set up, now install it's entry in the parent directory. */ 1254 error = ufs_direnter(ip, dvp, cnp); 1255 if (error) { 1256 dp->i_nlink--; 1257 dp->i_flag |= IN_CHANGE; 1258 } 1259bad: 1260 /* 1261 * No need to do an explicit VOP_TRUNCATE here, vrele will do this 1262 * for us because we set the link count to 0. 1263 */ 1264 if (error) { 1265 ip->i_nlink = 0; 1266 ip->i_flag |= IN_CHANGE; 1267 vput(tvp); 1268 } else 1269 *ap->a_vpp = tvp; 1270out: 1271 FREE(cnp->cn_pnbuf, M_NAMEI); 1272 vput(dvp); 1273 return (error); 1274} 1275 1276/* 1277 * Rmdir system call. 1278 */ 1279int 1280ufs_rmdir(ap) 1281 struct vop_rmdir_args /* { 1282 struct vnode *a_dvp; 1283 struct vnode *a_vp; 1284 struct componentname *a_cnp; 1285 } */ *ap; 1286{ 1287 struct vnode *vp = ap->a_vp; 1288 struct vnode *dvp = ap->a_dvp; 1289 struct componentname *cnp = ap->a_cnp; 1290 struct inode *ip, *dp; 1291 int error; 1292 1293 ip = VTOI(vp); 1294 dp = VTOI(dvp); 1295 /* 1296 * No rmdir "." please. 1297 */ 1298 if (dp == ip) { 1299 vrele(dvp); 1300 vput(vp); 1301 return (EINVAL); 1302 } 1303 /* 1304 * Verify the directory is empty (and valid). 1305 * (Rmdir ".." won't be valid since 1306 * ".." will contain a reference to 1307 * the current directory and thus be 1308 * non-empty.) 1309 */ 1310 error = 0; 1311 if (ip->i_nlink != 2 || 1312 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { 1313 error = ENOTEMPTY; 1314 goto out; 1315 } 1316 if ((dp->i_flags & APPEND) || (ip->i_flags & (IMMUTABLE | APPEND))) { 1317 error = EPERM; 1318 goto out; 1319 } 1320 /* 1321 * Delete reference to directory before purging 1322 * inode. If we crash in between, the directory 1323 * will be reattached to lost+found, 1324 */ 1325 error = ufs_dirremove(dvp, cnp); 1326 if (error) 1327 goto out; 1328 dp->i_nlink--; 1329 dp->i_flag |= IN_CHANGE; 1330 cache_purge(dvp); 1331 vput(dvp); 1332 dvp = NULL; 1333 /* 1334 * Truncate inode. The only stuff left 1335 * in the directory is "." and "..". The 1336 * "." reference is inconsequential since 1337 * we're quashing it. The ".." reference 1338 * has already been adjusted above. We've 1339 * removed the "." reference and the reference 1340 * in the parent directory, but there may be 1341 * other hard links so decrement by 2 and 1342 * worry about them later. 1343 */ 1344 ip->i_nlink -= 2; 1345 error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred, 1346 cnp->cn_proc); 1347 cache_purge(ITOV(ip)); 1348out: 1349 if (dvp) 1350 vput(dvp); 1351 vput(vp); 1352 return (error); 1353} 1354 1355/* 1356 * symlink -- make a symbolic link 1357 */ 1358int 1359ufs_symlink(ap) 1360 struct vop_symlink_args /* { 1361 struct vnode *a_dvp; 1362 struct vnode **a_vpp; 1363 struct componentname *a_cnp; 1364 struct vattr *a_vap; 1365 char *a_target; 1366 } */ *ap; 1367{ 1368 register struct vnode *vp, **vpp = ap->a_vpp; 1369 register struct inode *ip; 1370 int len, error; 1371 1372 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, 1373 vpp, ap->a_cnp); 1374 if (error) 1375 return (error); 1376 vp = *vpp; 1377 len = strlen(ap->a_target); 1378 if (len < vp->v_mount->mnt_maxsymlinklen) { 1379 ip = VTOI(vp); 1380 bcopy(ap->a_target, (char *)ip->i_shortlink, len); 1381 ip->i_size = len; 1382 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1383 } else 1384 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, 1385 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0, 1386 (struct proc *)0); 1387 vput(vp); 1388 return (error); 1389} 1390 1391/* 1392 * Vnode op for reading directories. 1393 * 1394 * The routine below assumes that the on-disk format of a directory 1395 * is the same as that defined by <sys/dirent.h>. If the on-disk 1396 * format changes, then it will be necessary to do a conversion 1397 * from the on-disk format that read returns to the format defined 1398 * by <sys/dirent.h>. 1399 */ 1400int 1401ufs_readdir(ap) 1402 struct vop_readdir_args /* { 1403 struct vnode *a_vp; 1404 struct uio *a_uio; 1405 struct ucred *a_cred; 1406 int *a_ncookies; 1407 u_int **cookies; 1408 } */ *ap; 1409{ 1410 register struct uio *uio = ap->a_uio; 1411 off_t off; 1412 int count, lost, error; 1413 1414 if (ap->a_ncookies != NULL) 1415 /* 1416 * Ensure that the block is aligned. The caller can use 1417 * the cookies to determine where in the block to start. 1418 */ 1419 uio->uio_offset &= ~(DIRBLKSIZ - 1); 1420 off = uio->uio_offset; 1421 count = uio->uio_resid; 1422 count &= ~(DIRBLKSIZ - 1); 1423 lost = uio->uio_resid - count; 1424 if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1))) 1425 return (EINVAL); 1426 uio->uio_resid = count; 1427 uio->uio_iov->iov_len = count; 1428# if (BYTE_ORDER == LITTLE_ENDIAN) 1429 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) { 1430 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1431 } else { 1432 struct dirent *dp, *edp; 1433 struct uio auio; 1434 struct iovec aiov; 1435 caddr_t dirbuf; 1436 int readcnt; 1437 u_char tmp; 1438 1439 auio = *uio; 1440 auio.uio_iov = &aiov; 1441 auio.uio_iovcnt = 1; 1442 auio.uio_segflg = UIO_SYSSPACE; 1443 aiov.iov_len = count; 1444 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); 1445 aiov.iov_base = dirbuf; 1446 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 1447 if (error == 0) { 1448 readcnt = count - auio.uio_resid; 1449 edp = (struct dirent *)&dirbuf[readcnt]; 1450 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1451 tmp = dp->d_namlen; 1452 dp->d_namlen = dp->d_type; 1453 dp->d_type = tmp; 1454 if (dp->d_reclen > 0) { 1455 dp = (struct dirent *) 1456 ((char *)dp + dp->d_reclen); 1457 } else { 1458 error = EIO; 1459 break; 1460 } 1461 } 1462 if (dp >= edp) 1463 error = uiomove(dirbuf, readcnt, uio); 1464 } 1465 FREE(dirbuf, M_TEMP); 1466 } 1467# else 1468 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1469# endif 1470 if (!error && ap->a_ncookies != NULL) { 1471 struct dirent* dpStart; 1472 struct dirent* dpEnd; 1473 struct dirent* dp; 1474 int ncookies; 1475 u_int *cookies; 1476 u_int *cookiep; 1477 1478 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1479 panic("ufs_readdir: unexpected uio from NFS server"); 1480 dpStart = (struct dirent *) 1481 (uio->uio_iov->iov_base - (uio->uio_offset - off)); 1482 dpEnd = (struct dirent *) uio->uio_iov->iov_base; 1483 for (dp = dpStart, ncookies = 0; 1484 dp < dpEnd; 1485 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) 1486 ncookies++; 1487 MALLOC(cookies, u_int *, ncookies * sizeof(u_int), 1488 M_TEMP, M_WAITOK); 1489 for (dp = dpStart, cookiep = cookies; 1490 dp < dpEnd; 1491 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 1492 off += dp->d_reclen; 1493 *cookiep++ = (u_int) off; 1494 } 1495 *ap->a_ncookies = ncookies; 1496 *ap->a_cookies = cookies; 1497 } 1498 if (ap->a_eofflag) 1499 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; 1500 uio->uio_resid += lost; 1501 return (error); 1502} 1503 1504/* 1505 * Return target name of a symbolic link 1506 */ 1507int 1508ufs_readlink(ap) 1509 struct vop_readlink_args /* { 1510 struct vnode *a_vp; 1511 struct uio *a_uio; 1512 struct ucred *a_cred; 1513 } */ *ap; 1514{ 1515 register struct vnode *vp = ap->a_vp; 1516 register struct inode *ip = VTOI(vp); 1517 int isize; 1518 1519 isize = ip->i_size; 1520 if ((isize < vp->v_mount->mnt_maxsymlinklen) || 1521 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */ 1522 uiomove((char *)ip->i_shortlink, isize, ap->a_uio); 1523 return (0); 1524 } 1525 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1526} 1527 1528/* 1529 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 1530 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 1531 */ 1532/* ARGSUSED */ 1533int 1534ufs_abortop(ap) 1535 struct vop_abortop_args /* { 1536 struct vnode *a_dvp; 1537 struct componentname *a_cnp; 1538 } */ *ap; 1539{ 1540 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 1541 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 1542 return (0); 1543} 1544 1545/* 1546 * Lock an inode. If its already locked, set the WANT bit and sleep. 1547 */ 1548int 1549ufs_lock(ap) 1550 struct vop_lock_args /* { 1551 struct vnode *a_vp; 1552 } */ *ap; 1553{ 1554 struct proc *p = curproc; 1555 register struct vnode *vp = ap->a_vp; 1556 register struct inode *ip; 1557 1558start: 1559 while (vp->v_flag & VXLOCK) { 1560 vp->v_flag |= VXWANT; 1561 (void) tsleep((caddr_t)vp, PINOD, "ufslk1", 0); 1562 } 1563 if (vp->v_tag == VT_NON) 1564 return (ENOENT); 1565 ip = VTOI(vp); 1566 if (ip->i_flag & IN_LOCKED) { 1567 if (p->p_pid == ip->i_lockholder) { 1568 if( (ip->i_flag & IN_RECURSE) == 0) 1569 panic("ufs_lock: recursive lock not expected, pid: %d\n", 1570 ip->i_lockholder); 1571 } else { 1572 ip->i_flag |= IN_WANTED; 1573#ifdef DIAGNOSTIC 1574 if (p) 1575 ip->i_lockwaiter = p->p_pid; 1576 else 1577 ip->i_lockwaiter = -1; 1578#endif 1579 (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0); 1580 goto start; 1581 } 1582 } 1583#ifdef DIAGNOSTIC 1584 ip->i_lockwaiter = 0; 1585 if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0)) 1586 panic("lockholder (%d) != 0", ip->i_lockholder); 1587 if (p && p->p_pid == 0) 1588 printf("locking by process 0\n"); 1589#endif 1590 1591 if ((ip->i_flag & IN_RECURSE) == 0) 1592 ip->i_lockcount = 1; 1593 else 1594 ++ip->i_lockcount; 1595 1596 if (p) 1597 ip->i_lockholder = p->p_pid; 1598 else 1599 ip->i_lockholder = -1; 1600 ip->i_flag |= IN_LOCKED; 1601 return (0); 1602} 1603 1604/* 1605 * Unlock an inode. If WANT bit is on, wakeup. 1606 */ 1607int lockcount = 90; 1608int 1609ufs_unlock(ap) 1610 struct vop_unlock_args /* { 1611 struct vnode *a_vp; 1612 } */ *ap; 1613{ 1614 register struct inode *ip = VTOI(ap->a_vp); 1615 struct proc *p = curproc; 1616 1617#ifdef DIAGNOSTIC 1618 1619 if ((ip->i_flag & IN_LOCKED) == 0) { 1620 vprint("ufs_unlock: unlocked inode", ap->a_vp); 1621 panic("ufs_unlock NOT LOCKED"); 1622 } 1623 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && 1624 ip->i_lockholder > -1 && lockcount++ < 100) 1625 panic("unlocker (%d) != lock holder (%d)", 1626 p->p_pid, ip->i_lockholder); 1627#endif 1628 if (--ip->i_lockcount > 0) { 1629 if ((ip->i_flag & IN_RECURSE) == 0) 1630 panic("ufs_unlock: recursive lock prematurely released, pid=%d\n", 1631 ip->i_lockholder); 1632 return (0); 1633 } 1634 ip->i_lockholder = 0; 1635 ip->i_flag &= ~(IN_LOCKED|IN_RECURSE); 1636 if (ip->i_flag & IN_WANTED) { 1637 ip->i_flag &= ~IN_WANTED; 1638 wakeup((caddr_t)ip); 1639 } 1640 return (0); 1641} 1642 1643/* 1644 * Check for a locked inode. 1645 */ 1646int 1647ufs_islocked(ap) 1648 struct vop_islocked_args /* { 1649 struct vnode *a_vp; 1650 } */ *ap; 1651{ 1652 1653 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 1654 return (1); 1655 return (0); 1656} 1657 1658/* 1659 * Calculate the logical to physical mapping if not done already, 1660 * then call the device strategy routine. 1661 */ 1662int 1663ufs_strategy(ap) 1664 struct vop_strategy_args /* { 1665 struct buf *a_bp; 1666 } */ *ap; 1667{ 1668 register struct buf *bp = ap->a_bp; 1669 register struct vnode *vp = bp->b_vp; 1670 register struct inode *ip; 1671 int error; 1672 1673 ip = VTOI(vp); 1674 if (vp->v_type == VBLK || vp->v_type == VCHR) 1675 panic("ufs_strategy: spec"); 1676 if (bp->b_blkno == bp->b_lblkno) { 1677 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL); 1678 if (error) { 1679 bp->b_error = error; 1680 bp->b_flags |= B_ERROR; 1681 biodone(bp); 1682 return (error); 1683 } 1684 if ((long)bp->b_blkno == -1) 1685 vfs_bio_clrbuf(bp); 1686 } 1687 if ((long)bp->b_blkno == -1) { 1688 biodone(bp); 1689 return (0); 1690 } 1691 vp = ip->i_devvp; 1692 bp->b_dev = vp->v_rdev; 1693 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 1694 return (0); 1695} 1696 1697/* 1698 * Print out the contents of an inode. 1699 */ 1700int 1701ufs_print(ap) 1702 struct vop_print_args /* { 1703 struct vnode *a_vp; 1704 } */ *ap; 1705{ 1706 register struct vnode *vp = ap->a_vp; 1707 register struct inode *ip = VTOI(vp); 1708 1709 printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number, 1710 major(ip->i_dev), minor(ip->i_dev)); 1711 if (vp->v_type == VFIFO) 1712 fifo_printinfo(vp); 1713 printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : ""); 1714 if (ip->i_lockholder == 0) 1715 return (0); 1716 printf("\towner pid %lu", (u_long)ip->i_lockholder); 1717 if (ip->i_lockwaiter) 1718 printf(" waiting pid %lu", (u_long)ip->i_lockwaiter); 1719 printf("\n"); 1720 return (0); 1721} 1722 1723/* 1724 * Read wrapper for special devices. 1725 */ 1726int 1727ufsspec_read(ap) 1728 struct vop_read_args /* { 1729 struct vnode *a_vp; 1730 struct uio *a_uio; 1731 int a_ioflag; 1732 struct ucred *a_cred; 1733 } */ *ap; 1734{ 1735 1736 /* 1737 * Set access flag. 1738 */ 1739 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 1740 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap)); 1741} 1742 1743/* 1744 * Write wrapper for special devices. 1745 */ 1746int 1747ufsspec_write(ap) 1748 struct vop_write_args /* { 1749 struct vnode *a_vp; 1750 struct uio *a_uio; 1751 int a_ioflag; 1752 struct ucred *a_cred; 1753 } */ *ap; 1754{ 1755 1756 /* 1757 * Set update and change flags. 1758 */ 1759 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 1760 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap)); 1761} 1762 1763/* 1764 * Close wrapper for special devices. 1765 * 1766 * Update the times on the inode then do device close. 1767 */ 1768int 1769ufsspec_close(ap) 1770 struct vop_close_args /* { 1771 struct vnode *a_vp; 1772 int a_fflag; 1773 struct ucred *a_cred; 1774 struct proc *a_p; 1775 } */ *ap; 1776{ 1777 register struct inode *ip = VTOI(ap->a_vp); 1778 1779 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) 1780 ITIMES(ip, &time, &time); 1781 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap)); 1782} 1783 1784/* 1785 * Read wrapper for fifo's 1786 */ 1787int 1788ufsfifo_read(ap) 1789 struct vop_read_args /* { 1790 struct vnode *a_vp; 1791 struct uio *a_uio; 1792 int a_ioflag; 1793 struct ucred *a_cred; 1794 } */ *ap; 1795{ 1796 /* 1797 * Set access flag. 1798 */ 1799 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 1800 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap)); 1801} 1802 1803/* 1804 * Write wrapper for fifo's. 1805 */ 1806int 1807ufsfifo_write(ap) 1808 struct vop_write_args /* { 1809 struct vnode *a_vp; 1810 struct uio *a_uio; 1811 int a_ioflag; 1812 struct ucred *a_cred; 1813 } */ *ap; 1814{ 1815 /* 1816 * Set update and change flags. 1817 */ 1818 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 1819 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap)); 1820} 1821 1822/* 1823 * Close wrapper for fifo's. 1824 * 1825 * Update the times on the inode then do device close. 1826 */ 1827int 1828ufsfifo_close(ap) 1829 struct vop_close_args /* { 1830 struct vnode *a_vp; 1831 int a_fflag; 1832 struct ucred *a_cred; 1833 struct proc *a_p; 1834 } */ *ap; 1835{ 1836 register struct inode *ip = VTOI(ap->a_vp); 1837 1838 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) 1839 ITIMES(ip, &time, &time); 1840 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap)); 1841} 1842 1843/* 1844 * Return POSIX pathconf information applicable to ufs filesystems. 1845 */ 1846int 1847ufs_pathconf(ap) 1848 struct vop_pathconf_args /* { 1849 struct vnode *a_vp; 1850 int a_name; 1851 int *a_retval; 1852 } */ *ap; 1853{ 1854 1855 switch (ap->a_name) { 1856 case _PC_LINK_MAX: 1857 *ap->a_retval = LINK_MAX; 1858 return (0); 1859 case _PC_NAME_MAX: 1860 *ap->a_retval = NAME_MAX; 1861 return (0); 1862 case _PC_PATH_MAX: 1863 *ap->a_retval = PATH_MAX; 1864 return (0); 1865 case _PC_PIPE_BUF: 1866 *ap->a_retval = PIPE_BUF; 1867 return (0); 1868 case _PC_CHOWN_RESTRICTED: 1869 *ap->a_retval = 1; 1870 return (0); 1871 case _PC_NO_TRUNC: 1872 *ap->a_retval = 1; 1873 return (0); 1874 default: 1875 return (EINVAL); 1876 } 1877 /* NOTREACHED */ 1878} 1879 1880/* 1881 * Advisory record locking support 1882 */ 1883int 1884ufs_advlock(ap) 1885 struct vop_advlock_args /* { 1886 struct vnode *a_vp; 1887 caddr_t a_id; 1888 int a_op; 1889 struct flock *a_fl; 1890 int a_flags; 1891 } */ *ap; 1892{ 1893 register struct inode *ip = VTOI(ap->a_vp); 1894 1895 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); 1896} 1897 1898/* 1899 * Initialize the vnode associated with a new inode, handle aliased 1900 * vnodes. 1901 */ 1902int 1903ufs_vinit(mntp, specops, fifoops, vpp) 1904 struct mount *mntp; 1905 int (**specops)(); 1906 int (**fifoops)(); 1907 struct vnode **vpp; 1908{ 1909 struct inode *ip; 1910 struct vnode *vp, *nvp; 1911 1912 vp = *vpp; 1913 ip = VTOI(vp); 1914 switch(vp->v_type = IFTOVT(ip->i_mode)) { 1915 case VCHR: 1916 case VBLK: 1917 vp->v_op = specops; 1918 nvp = checkalias(vp, ip->i_rdev, mntp); 1919 if (nvp) { 1920 /* 1921 * Discard unneeded vnode, but save its inode. 1922 */ 1923 ufs_ihashrem(ip); 1924 VOP_UNLOCK(vp); 1925 nvp->v_data = vp->v_data; 1926 vp->v_data = NULL; 1927 vp->v_op = spec_vnodeop_p; 1928 vrele(vp); 1929 vgone(vp); 1930 /* 1931 * Reinitialize aliased inode. 1932 */ 1933 vp = nvp; 1934 ip->i_vnode = vp; 1935 ufs_ihashins(ip); 1936 } 1937 break; 1938 case VFIFO: 1939 vp->v_op = fifoops; 1940 break; 1941 default: 1942 break; 1943 1944 } 1945 if (ip->i_number == ROOTINO) 1946 vp->v_flag |= VROOT; 1947 /* 1948 * Initialize modrev times 1949 */ 1950 SETHIGH(ip->i_modrev, mono_time.tv_sec); 1951 SETLOW(ip->i_modrev, mono_time.tv_usec * 4294); 1952 *vpp = vp; 1953 return (0); 1954} 1955 1956/* 1957 * Allocate a new inode. 1958 */ 1959int 1960ufs_makeinode(mode, dvp, vpp, cnp) 1961 int mode; 1962 struct vnode *dvp; 1963 struct vnode **vpp; 1964 struct componentname *cnp; 1965{ 1966 register struct inode *ip, *pdir; 1967 struct timeval tv; 1968 struct vnode *tvp; 1969 int error; 1970 1971 pdir = VTOI(dvp); 1972#ifdef DIAGNOSTIC 1973 if ((cnp->cn_flags & HASBUF) == 0) 1974 panic("ufs_makeinode: no name"); 1975#endif 1976 *vpp = NULL; 1977 if ((mode & IFMT) == 0) 1978 mode |= IFREG; 1979 1980 error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp); 1981 if (error) { 1982 free(cnp->cn_pnbuf, M_NAMEI); 1983 vput(dvp); 1984 return (error); 1985 } 1986 ip = VTOI(tvp); 1987 ip->i_gid = pdir->i_gid; 1988 if ((mode & IFMT) == IFLNK) 1989 ip->i_uid = pdir->i_uid; 1990 else 1991 ip->i_uid = cnp->cn_cred->cr_uid; 1992#ifdef QUOTA 1993 if ((error = getinoquota(ip)) || 1994 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1995 free(cnp->cn_pnbuf, M_NAMEI); 1996 VOP_VFREE(tvp, ip->i_number, mode); 1997 vput(tvp); 1998 vput(dvp); 1999 return (error); 2000 } 2001#endif 2002 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 2003 ip->i_mode = mode; 2004 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ 2005 ip->i_nlink = 1; 2006 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && 2007 suser(cnp->cn_cred, NULL)) 2008 ip->i_mode &= ~ISGID; 2009 2010 /* 2011 * Make sure inode goes to disk before directory entry. 2012 */ 2013 tv = time; 2014 error = VOP_UPDATE(tvp, &tv, &tv, 1); 2015 if (error) 2016 goto bad; 2017 error = ufs_direnter(ip, dvp, cnp); 2018 if (error) 2019 goto bad; 2020 if ((cnp->cn_flags & SAVESTART) == 0) 2021 FREE(cnp->cn_pnbuf, M_NAMEI); 2022 vput(dvp); 2023 *vpp = tvp; 2024 return (0); 2025 2026bad: 2027 /* 2028 * Write error occurred trying to update the inode 2029 * or the directory so must deallocate the inode. 2030 */ 2031 free(cnp->cn_pnbuf, M_NAMEI); 2032 vput(dvp); 2033 ip->i_nlink = 0; 2034 ip->i_flag |= IN_CHANGE; 2035 vput(tvp); 2036 return (error); 2037} 2038