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