ufs_vnops.c revision 9354
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.24 1995/05/30 08:15:39 rgrimes 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(tdvp, cnp); 687 error = EXDEV; 688 goto out2; 689 } 690 if (vp != tdvp && (error = VOP_LOCK(vp))) { 691 VOP_ABORTOP(tdvp, cnp); 692 goto out2; 693 } 694 ip = VTOI(vp); 695 if ((nlink_t)ip->i_nlink >= LINK_MAX) { 696 VOP_ABORTOP(tdvp, cnp); 697 error = EMLINK; 698 goto out1; 699 } 700 if (ip->i_flags & (IMMUTABLE | APPEND)) { 701 VOP_ABORTOP(tdvp, 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(vp, &tv, &tv, 1); 709 if (!error) 710 error = ufs_direnter(ip, tdvp, 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(vp); 719out2: 720 vput(tdvp); 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 IN_RENAME 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 ip->i_flag &= ~IN_RENAME; 1116 vput(fvp); 1117 } else 1118 vrele(fvp); 1119 return (error); 1120} 1121 1122/* 1123 * A virgin directory (no blushing please). 1124 */ 1125static struct dirtemplate mastertemplate = { 1126 0, 12, DT_DIR, 1, ".", 1127 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." 1128}; 1129static struct odirtemplate omastertemplate = { 1130 0, 12, 1, ".", 1131 0, DIRBLKSIZ - 12, 2, ".." 1132}; 1133 1134/* 1135 * Mkdir system call 1136 */ 1137int 1138ufs_mkdir(ap) 1139 struct vop_mkdir_args /* { 1140 struct vnode *a_dvp; 1141 struct vnode **a_vpp; 1142 struct componentname *a_cnp; 1143 struct vattr *a_vap; 1144 } */ *ap; 1145{ 1146 register struct vnode *dvp = ap->a_dvp; 1147 register struct vattr *vap = ap->a_vap; 1148 register struct componentname *cnp = ap->a_cnp; 1149 register struct inode *ip, *dp; 1150 struct vnode *tvp; 1151 struct dirtemplate dirtemplate, *dtp; 1152 struct timeval tv; 1153 int error, dmode; 1154 1155#ifdef DIAGNOSTIC 1156 if ((cnp->cn_flags & HASBUF) == 0) 1157 panic("ufs_mkdir: no name"); 1158#endif 1159 dp = VTOI(dvp); 1160 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1161 error = EMLINK; 1162 goto out; 1163 } 1164 dmode = vap->va_mode & 0777; 1165 dmode |= IFDIR; 1166 /* 1167 * Must simulate part of ufs_makeinode here to acquire the inode, 1168 * but not have it entered in the parent directory. The entry is 1169 * made later after writing "." and ".." entries. 1170 */ 1171 error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp); 1172 if (error) 1173 goto out; 1174 ip = VTOI(tvp); 1175 ip->i_uid = cnp->cn_cred->cr_uid; 1176 ip->i_gid = dp->i_gid; 1177#ifdef QUOTA 1178 if ((error = getinoquota(ip)) || 1179 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1180 free(cnp->cn_pnbuf, M_NAMEI); 1181 VOP_VFREE(tvp, ip->i_number, dmode); 1182 vput(tvp); 1183 vput(dvp); 1184 return (error); 1185 } 1186#endif 1187 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1188 ip->i_mode = dmode; 1189 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ 1190 ip->i_nlink = 2; 1191 tv = time; 1192 error = VOP_UPDATE(tvp, &tv, &tv, 1); 1193 1194 /* 1195 * Bump link count in parent directory 1196 * to reflect work done below. Should 1197 * be done before reference is created 1198 * so reparation is possible if we crash. 1199 */ 1200 dp->i_nlink++; 1201 dp->i_flag |= IN_CHANGE; 1202 error = VOP_UPDATE(dvp, &tv, &tv, 1); 1203 if (error) 1204 goto bad; 1205 1206 /* Initialize directory with "." and ".." from static template. */ 1207 if (dvp->v_mount->mnt_maxsymlinklen > 0) 1208 dtp = &mastertemplate; 1209 else 1210 dtp = (struct dirtemplate *)&omastertemplate; 1211 dirtemplate = *dtp; 1212 dirtemplate.dot_ino = ip->i_number; 1213 dirtemplate.dotdot_ino = dp->i_number; 1214 error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate, 1215 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, 1216 IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0); 1217 if (error) { 1218 dp->i_nlink--; 1219 dp->i_flag |= IN_CHANGE; 1220 goto bad; 1221 } 1222 if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 1223 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */ 1224 else { 1225 ip->i_size = DIRBLKSIZ; 1226 ip->i_flag |= IN_CHANGE; 1227 } 1228 1229 /* Directory set up, now install it's entry in the parent directory. */ 1230 error = ufs_direnter(ip, dvp, cnp); 1231 if (error) { 1232 dp->i_nlink--; 1233 dp->i_flag |= IN_CHANGE; 1234 } 1235bad: 1236 /* 1237 * No need to do an explicit VOP_TRUNCATE here, vrele will do this 1238 * for us because we set the link count to 0. 1239 */ 1240 if (error) { 1241 ip->i_nlink = 0; 1242 ip->i_flag |= IN_CHANGE; 1243 vput(tvp); 1244 } else 1245 *ap->a_vpp = tvp; 1246out: 1247 FREE(cnp->cn_pnbuf, M_NAMEI); 1248 vput(dvp); 1249 return (error); 1250} 1251 1252/* 1253 * Rmdir system call. 1254 */ 1255int 1256ufs_rmdir(ap) 1257 struct vop_rmdir_args /* { 1258 struct vnode *a_dvp; 1259 struct vnode *a_vp; 1260 struct componentname *a_cnp; 1261 } */ *ap; 1262{ 1263 register struct vnode *vp = ap->a_vp; 1264 register struct vnode *dvp = ap->a_dvp; 1265 register struct componentname *cnp = ap->a_cnp; 1266 register struct inode *ip, *dp; 1267 int error; 1268 1269 ip = VTOI(vp); 1270 dp = VTOI(dvp); 1271 /* 1272 * No rmdir "." please. 1273 */ 1274 if (dp == ip) { 1275 vrele(dvp); 1276 vput(vp); 1277 return (EINVAL); 1278 } 1279 /* 1280 * Verify the directory is empty (and valid). 1281 * (Rmdir ".." won't be valid since 1282 * ".." will contain a reference to 1283 * the current directory and thus be 1284 * non-empty.) 1285 */ 1286 error = 0; 1287 if (ip->i_nlink != 2 || 1288 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { 1289 error = ENOTEMPTY; 1290 goto out; 1291 } 1292 if ((dp->i_flags & APPEND) || (ip->i_flags & (IMMUTABLE | APPEND))) { 1293 error = EPERM; 1294 goto out; 1295 } 1296 /* 1297 * Delete reference to directory before purging 1298 * inode. If we crash in between, the directory 1299 * will be reattached to lost+found, 1300 */ 1301 error = ufs_dirremove(dvp, cnp); 1302 if (error) 1303 goto out; 1304 dp->i_nlink--; 1305 dp->i_flag |= IN_CHANGE; 1306 cache_purge(dvp); 1307 vput(dvp); 1308 dvp = NULL; 1309 /* 1310 * Truncate inode. The only stuff left 1311 * in the directory is "." and "..". The 1312 * "." reference is inconsequential since 1313 * we're quashing it. The ".." reference 1314 * has already been adjusted above. We've 1315 * removed the "." reference and the reference 1316 * in the parent directory, but there may be 1317 * other hard links so decrement by 2 and 1318 * worry about them later. 1319 */ 1320 ip->i_nlink -= 2; 1321 error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred, 1322 cnp->cn_proc); 1323 cache_purge(ITOV(ip)); 1324out: 1325 if (dvp) 1326 vput(dvp); 1327 vput(vp); 1328 return (error); 1329} 1330 1331/* 1332 * symlink -- make a symbolic link 1333 */ 1334int 1335ufs_symlink(ap) 1336 struct vop_symlink_args /* { 1337 struct vnode *a_dvp; 1338 struct vnode **a_vpp; 1339 struct componentname *a_cnp; 1340 struct vattr *a_vap; 1341 char *a_target; 1342 } */ *ap; 1343{ 1344 register struct vnode *vp, **vpp = ap->a_vpp; 1345 register struct inode *ip; 1346 int len, error; 1347 1348 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, 1349 vpp, ap->a_cnp); 1350 if (error) 1351 return (error); 1352 vp = *vpp; 1353 len = strlen(ap->a_target); 1354 if (len < vp->v_mount->mnt_maxsymlinklen) { 1355 ip = VTOI(vp); 1356 bcopy(ap->a_target, (char *)ip->i_shortlink, len); 1357 ip->i_size = len; 1358 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1359 } else 1360 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, 1361 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0, 1362 (struct proc *)0); 1363 vput(vp); 1364 return (error); 1365} 1366 1367/* 1368 * Vnode op for reading directories. 1369 * 1370 * The routine below assumes that the on-disk format of a directory 1371 * is the same as that defined by <sys/dirent.h>. If the on-disk 1372 * format changes, then it will be necessary to do a conversion 1373 * from the on-disk format that read returns to the format defined 1374 * by <sys/dirent.h>. 1375 */ 1376int 1377ufs_readdir(ap) 1378 struct vop_readdir_args /* { 1379 struct vnode *a_vp; 1380 struct uio *a_uio; 1381 struct ucred *a_cred; 1382 int *a_ncookies; 1383 u_int **cookies; 1384 } */ *ap; 1385{ 1386 register struct uio *uio = ap->a_uio; 1387 off_t off; 1388 int count, lost, error; 1389 1390 if (ap->a_ncookies != NULL) 1391 /* 1392 * Ensure that the block is aligned. The caller can use 1393 * the cookies to determine where in the block to start. 1394 */ 1395 uio->uio_offset &= ~(DIRBLKSIZ - 1); 1396 off = uio->uio_offset; 1397 count = uio->uio_resid; 1398 count &= ~(DIRBLKSIZ - 1); 1399 lost = uio->uio_resid - count; 1400 if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1))) 1401 return (EINVAL); 1402 uio->uio_resid = count; 1403 uio->uio_iov->iov_len = count; 1404# if (BYTE_ORDER == LITTLE_ENDIAN) 1405 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) { 1406 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1407 } else { 1408 struct dirent *dp, *edp; 1409 struct uio auio; 1410 struct iovec aiov; 1411 caddr_t dirbuf; 1412 int readcnt; 1413 u_char tmp; 1414 1415 auio = *uio; 1416 auio.uio_iov = &aiov; 1417 auio.uio_iovcnt = 1; 1418 auio.uio_segflg = UIO_SYSSPACE; 1419 aiov.iov_len = count; 1420 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); 1421 aiov.iov_base = dirbuf; 1422 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 1423 if (error == 0) { 1424 readcnt = count - auio.uio_resid; 1425 edp = (struct dirent *)&dirbuf[readcnt]; 1426 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1427 tmp = dp->d_namlen; 1428 dp->d_namlen = dp->d_type; 1429 dp->d_type = tmp; 1430 if (dp->d_reclen > 0) { 1431 dp = (struct dirent *) 1432 ((char *)dp + dp->d_reclen); 1433 } else { 1434 error = EIO; 1435 break; 1436 } 1437 } 1438 if (dp >= edp) 1439 error = uiomove(dirbuf, readcnt, uio); 1440 } 1441 FREE(dirbuf, M_TEMP); 1442 } 1443# else 1444 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1445# endif 1446 if (!error && ap->a_ncookies != NULL) { 1447 struct dirent* dpStart; 1448 struct dirent* dpEnd; 1449 struct dirent* dp; 1450 int ncookies; 1451 u_int *cookies; 1452 u_int *cookiep; 1453 1454 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1455 panic("ufs_readdir: unexpected uio from NFS server"); 1456 dpStart = (struct dirent *) 1457 (uio->uio_iov->iov_base - (uio->uio_offset - off)); 1458 dpEnd = (struct dirent *) uio->uio_iov->iov_base; 1459 for (dp = dpStart, ncookies = 0; 1460 dp < dpEnd; 1461 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) 1462 ncookies++; 1463 MALLOC(cookies, u_int *, ncookies * sizeof(u_int), 1464 M_TEMP, M_WAITOK); 1465 for (dp = dpStart, cookiep = cookies; 1466 dp < dpEnd; 1467 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 1468 off += dp->d_reclen; 1469 *cookiep++ = (u_int) off; 1470 } 1471 *ap->a_ncookies = ncookies; 1472 *ap->a_cookies = cookies; 1473 } 1474 if (ap->a_eofflag) 1475 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; 1476 uio->uio_resid += lost; 1477 return (error); 1478} 1479 1480/* 1481 * Return target name of a symbolic link 1482 */ 1483int 1484ufs_readlink(ap) 1485 struct vop_readlink_args /* { 1486 struct vnode *a_vp; 1487 struct uio *a_uio; 1488 struct ucred *a_cred; 1489 } */ *ap; 1490{ 1491 register struct vnode *vp = ap->a_vp; 1492 register struct inode *ip = VTOI(vp); 1493 int isize; 1494 1495 isize = ip->i_size; 1496 if ((isize < vp->v_mount->mnt_maxsymlinklen) || 1497 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */ 1498 uiomove((char *)ip->i_shortlink, isize, ap->a_uio); 1499 return (0); 1500 } 1501 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1502} 1503 1504/* 1505 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 1506 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 1507 */ 1508/* ARGSUSED */ 1509int 1510ufs_abortop(ap) 1511 struct vop_abortop_args /* { 1512 struct vnode *a_dvp; 1513 struct componentname *a_cnp; 1514 } */ *ap; 1515{ 1516 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 1517 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 1518 return (0); 1519} 1520 1521/* 1522 * Lock an inode. If its already locked, set the WANT bit and sleep. 1523 */ 1524int 1525ufs_lock(ap) 1526 struct vop_lock_args /* { 1527 struct vnode *a_vp; 1528 } */ *ap; 1529{ 1530 struct proc *p = curproc; 1531 register struct vnode *vp = ap->a_vp; 1532 register struct inode *ip; 1533 1534start: 1535 while (vp->v_flag & VXLOCK) { 1536 vp->v_flag |= VXWANT; 1537 (void) tsleep((caddr_t)vp, PINOD, "ufslk1", 0); 1538 } 1539 if (vp->v_tag == VT_NON) 1540 return (ENOENT); 1541 ip = VTOI(vp); 1542 if (ip->i_flag & IN_LOCKED) { 1543 if (p->p_pid == ip->i_lockholder) { 1544 if( (ip->i_flag & IN_RECURSE) == 0) 1545 panic("ufs_lock: recursive lock not expected, pid: %d\n", 1546 ip->i_lockholder); 1547 } else { 1548 ip->i_flag |= IN_WANTED; 1549#ifdef DIAGNOSTIC 1550 if (p) 1551 ip->i_lockwaiter = p->p_pid; 1552 else 1553 ip->i_lockwaiter = -1; 1554#endif 1555 (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0); 1556 goto start; 1557 } 1558 } 1559#ifdef DIAGNOSTIC 1560 ip->i_lockwaiter = 0; 1561 if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0)) 1562 panic("lockholder (%d) != 0", ip->i_lockholder); 1563 if (p && p->p_pid == 0) 1564 printf("locking by process 0\n"); 1565#endif 1566 1567 if ((ip->i_flag & IN_RECURSE) == 0) 1568 ip->i_lockcount = 1; 1569 else 1570 ++ip->i_lockcount; 1571 1572 if (p) 1573 ip->i_lockholder = p->p_pid; 1574 else 1575 ip->i_lockholder = -1; 1576 ip->i_flag |= IN_LOCKED; 1577 return (0); 1578} 1579 1580/* 1581 * Unlock an inode. If WANT bit is on, wakeup. 1582 */ 1583int lockcount = 90; 1584int 1585ufs_unlock(ap) 1586 struct vop_unlock_args /* { 1587 struct vnode *a_vp; 1588 } */ *ap; 1589{ 1590 register struct inode *ip = VTOI(ap->a_vp); 1591 struct proc *p = curproc; 1592 1593#ifdef DIAGNOSTIC 1594 1595 if ((ip->i_flag & IN_LOCKED) == 0) { 1596 vprint("ufs_unlock: unlocked inode", ap->a_vp); 1597 panic("ufs_unlock NOT LOCKED"); 1598 } 1599 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && 1600 ip->i_lockholder > -1 && lockcount++ < 100) 1601 panic("unlocker (%d) != lock holder (%d)", 1602 p->p_pid, ip->i_lockholder); 1603#endif 1604 if (--ip->i_lockcount > 0) { 1605 if ((ip->i_flag & IN_RECURSE) == 0) 1606 panic("ufs_unlock: recursive lock prematurely released, pid=%d\n", 1607 ip->i_lockholder); 1608 return (0); 1609 } 1610 ip->i_lockholder = 0; 1611 ip->i_flag &= ~(IN_LOCKED|IN_RECURSE); 1612 if (ip->i_flag & IN_WANTED) { 1613 ip->i_flag &= ~IN_WANTED; 1614 wakeup((caddr_t)ip); 1615 } 1616 return (0); 1617} 1618 1619/* 1620 * Check for a locked inode. 1621 */ 1622int 1623ufs_islocked(ap) 1624 struct vop_islocked_args /* { 1625 struct vnode *a_vp; 1626 } */ *ap; 1627{ 1628 1629 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 1630 return (1); 1631 return (0); 1632} 1633 1634/* 1635 * Calculate the logical to physical mapping if not done already, 1636 * then call the device strategy routine. 1637 */ 1638int 1639ufs_strategy(ap) 1640 struct vop_strategy_args /* { 1641 struct buf *a_bp; 1642 } */ *ap; 1643{ 1644 register struct buf *bp = ap->a_bp; 1645 register struct vnode *vp = bp->b_vp; 1646 register struct inode *ip; 1647 int error; 1648 1649 ip = VTOI(vp); 1650 if (vp->v_type == VBLK || vp->v_type == VCHR) 1651 panic("ufs_strategy: spec"); 1652 if (bp->b_blkno == bp->b_lblkno) { 1653 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 1654 if (error) { 1655 bp->b_error = error; 1656 bp->b_flags |= B_ERROR; 1657 biodone(bp); 1658 return (error); 1659 } 1660 if ((long)bp->b_blkno == -1) 1661 vfs_bio_clrbuf(bp); 1662 } 1663 if ((long)bp->b_blkno == -1) { 1664 biodone(bp); 1665 return (0); 1666 } 1667 vp = ip->i_devvp; 1668 bp->b_dev = vp->v_rdev; 1669 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 1670 return (0); 1671} 1672 1673/* 1674 * Print out the contents of an inode. 1675 */ 1676int 1677ufs_print(ap) 1678 struct vop_print_args /* { 1679 struct vnode *a_vp; 1680 } */ *ap; 1681{ 1682 register struct vnode *vp = ap->a_vp; 1683 register struct inode *ip = VTOI(vp); 1684 1685 printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number, 1686 major(ip->i_dev), minor(ip->i_dev)); 1687 if (vp->v_type == VFIFO) 1688 fifo_printinfo(vp); 1689 printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : ""); 1690 if (ip->i_lockholder == 0) 1691 return (0); 1692 printf("\towner pid %lu", (u_long)ip->i_lockholder); 1693 if (ip->i_lockwaiter) 1694 printf(" waiting pid %lu", (u_long)ip->i_lockwaiter); 1695 printf("\n"); 1696 return (0); 1697} 1698 1699/* 1700 * Read wrapper for special devices. 1701 */ 1702int 1703ufsspec_read(ap) 1704 struct vop_read_args /* { 1705 struct vnode *a_vp; 1706 struct uio *a_uio; 1707 int a_ioflag; 1708 struct ucred *a_cred; 1709 } */ *ap; 1710{ 1711 1712 /* 1713 * Set access flag. 1714 */ 1715 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 1716 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap)); 1717} 1718 1719/* 1720 * Write wrapper for special devices. 1721 */ 1722int 1723ufsspec_write(ap) 1724 struct vop_write_args /* { 1725 struct vnode *a_vp; 1726 struct uio *a_uio; 1727 int a_ioflag; 1728 struct ucred *a_cred; 1729 } */ *ap; 1730{ 1731 1732 /* 1733 * Set update and change flags. 1734 */ 1735 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 1736 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap)); 1737} 1738 1739/* 1740 * Close wrapper for special devices. 1741 * 1742 * Update the times on the inode then do device close. 1743 */ 1744int 1745ufsspec_close(ap) 1746 struct vop_close_args /* { 1747 struct vnode *a_vp; 1748 int a_fflag; 1749 struct ucred *a_cred; 1750 struct proc *a_p; 1751 } */ *ap; 1752{ 1753 register struct inode *ip = VTOI(ap->a_vp); 1754 1755 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) 1756 ITIMES(ip, &time, &time); 1757 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap)); 1758} 1759 1760/* 1761 * Read wrapper for fifo's 1762 */ 1763int 1764ufsfifo_read(ap) 1765 struct vop_read_args /* { 1766 struct vnode *a_vp; 1767 struct uio *a_uio; 1768 int a_ioflag; 1769 struct ucred *a_cred; 1770 } */ *ap; 1771{ 1772 /* 1773 * Set access flag. 1774 */ 1775 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 1776 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap)); 1777} 1778 1779/* 1780 * Write wrapper for fifo's. 1781 */ 1782int 1783ufsfifo_write(ap) 1784 struct vop_write_args /* { 1785 struct vnode *a_vp; 1786 struct uio *a_uio; 1787 int a_ioflag; 1788 struct ucred *a_cred; 1789 } */ *ap; 1790{ 1791 /* 1792 * Set update and change flags. 1793 */ 1794 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 1795 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap)); 1796} 1797 1798/* 1799 * Close wrapper for fifo's. 1800 * 1801 * Update the times on the inode then do device close. 1802 */ 1803int 1804ufsfifo_close(ap) 1805 struct vop_close_args /* { 1806 struct vnode *a_vp; 1807 int a_fflag; 1808 struct ucred *a_cred; 1809 struct proc *a_p; 1810 } */ *ap; 1811{ 1812 register struct inode *ip = VTOI(ap->a_vp); 1813 1814 if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) 1815 ITIMES(ip, &time, &time); 1816 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap)); 1817} 1818 1819/* 1820 * Return POSIX pathconf information applicable to ufs filesystems. 1821 */ 1822int 1823ufs_pathconf(ap) 1824 struct vop_pathconf_args /* { 1825 struct vnode *a_vp; 1826 int a_name; 1827 int *a_retval; 1828 } */ *ap; 1829{ 1830 1831 switch (ap->a_name) { 1832 case _PC_LINK_MAX: 1833 *ap->a_retval = LINK_MAX; 1834 return (0); 1835 case _PC_NAME_MAX: 1836 *ap->a_retval = NAME_MAX; 1837 return (0); 1838 case _PC_PATH_MAX: 1839 *ap->a_retval = PATH_MAX; 1840 return (0); 1841 case _PC_PIPE_BUF: 1842 *ap->a_retval = PIPE_BUF; 1843 return (0); 1844 case _PC_CHOWN_RESTRICTED: 1845 *ap->a_retval = 1; 1846 return (0); 1847 case _PC_NO_TRUNC: 1848 *ap->a_retval = 1; 1849 return (0); 1850 default: 1851 return (EINVAL); 1852 } 1853 /* NOTREACHED */ 1854} 1855 1856/* 1857 * Advisory record locking support 1858 */ 1859int 1860ufs_advlock(ap) 1861 struct vop_advlock_args /* { 1862 struct vnode *a_vp; 1863 caddr_t a_id; 1864 int a_op; 1865 struct flock *a_fl; 1866 int a_flags; 1867 } */ *ap; 1868{ 1869 register struct inode *ip = VTOI(ap->a_vp); 1870 1871 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); 1872} 1873 1874/* 1875 * Initialize the vnode associated with a new inode, handle aliased 1876 * vnodes. 1877 */ 1878int 1879ufs_vinit(mntp, specops, fifoops, vpp) 1880 struct mount *mntp; 1881 int (**specops)(); 1882 int (**fifoops)(); 1883 struct vnode **vpp; 1884{ 1885 struct inode *ip; 1886 struct vnode *vp, *nvp; 1887 1888 vp = *vpp; 1889 ip = VTOI(vp); 1890 switch(vp->v_type = IFTOVT(ip->i_mode)) { 1891 case VCHR: 1892 case VBLK: 1893 vp->v_op = specops; 1894 nvp = checkalias(vp, ip->i_rdev, mntp); 1895 if (nvp) { 1896 /* 1897 * Discard unneeded vnode, but save its inode. 1898 */ 1899 ufs_ihashrem(ip); 1900 VOP_UNLOCK(vp); 1901 nvp->v_data = vp->v_data; 1902 vp->v_data = NULL; 1903 vp->v_op = spec_vnodeop_p; 1904 vrele(vp); 1905 vgone(vp); 1906 /* 1907 * Reinitialize aliased inode. 1908 */ 1909 vp = nvp; 1910 ip->i_vnode = vp; 1911 ufs_ihashins(ip); 1912 } 1913 break; 1914 case VFIFO: 1915 vp->v_op = fifoops; 1916 break; 1917 default: 1918 break; 1919 1920 } 1921 if (ip->i_number == ROOTINO) 1922 vp->v_flag |= VROOT; 1923 /* 1924 * Initialize modrev times 1925 */ 1926 SETHIGH(ip->i_modrev, mono_time.tv_sec); 1927 SETLOW(ip->i_modrev, mono_time.tv_usec * 4294); 1928 *vpp = vp; 1929 return (0); 1930} 1931 1932/* 1933 * Allocate a new inode. 1934 */ 1935int 1936ufs_makeinode(mode, dvp, vpp, cnp) 1937 int mode; 1938 struct vnode *dvp; 1939 struct vnode **vpp; 1940 struct componentname *cnp; 1941{ 1942 register struct inode *ip, *pdir; 1943 struct timeval tv; 1944 struct vnode *tvp; 1945 int error; 1946 1947 pdir = VTOI(dvp); 1948#ifdef DIAGNOSTIC 1949 if ((cnp->cn_flags & HASBUF) == 0) 1950 panic("ufs_makeinode: no name"); 1951#endif 1952 *vpp = NULL; 1953 if ((mode & IFMT) == 0) 1954 mode |= IFREG; 1955 1956 error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp); 1957 if (error) { 1958 free(cnp->cn_pnbuf, M_NAMEI); 1959 vput(dvp); 1960 return (error); 1961 } 1962 ip = VTOI(tvp); 1963 ip->i_gid = pdir->i_gid; 1964 if ((mode & IFMT) == IFLNK) 1965 ip->i_uid = pdir->i_uid; 1966 else 1967 ip->i_uid = cnp->cn_cred->cr_uid; 1968#ifdef QUOTA 1969 if ((error = getinoquota(ip)) || 1970 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1971 free(cnp->cn_pnbuf, M_NAMEI); 1972 VOP_VFREE(tvp, ip->i_number, mode); 1973 vput(tvp); 1974 vput(dvp); 1975 return (error); 1976 } 1977#endif 1978 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1979 ip->i_mode = mode; 1980 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ 1981 ip->i_nlink = 1; 1982 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && 1983 suser(cnp->cn_cred, NULL)) 1984 ip->i_mode &= ~ISGID; 1985 1986 /* 1987 * Make sure inode goes to disk before directory entry. 1988 */ 1989 tv = time; 1990 error = VOP_UPDATE(tvp, &tv, &tv, 1); 1991 if (error) 1992 goto bad; 1993 error = ufs_direnter(ip, dvp, cnp); 1994 if (error) 1995 goto bad; 1996 if ((cnp->cn_flags & SAVESTART) == 0) 1997 FREE(cnp->cn_pnbuf, M_NAMEI); 1998 vput(dvp); 1999 *vpp = tvp; 2000 return (0); 2001 2002bad: 2003 /* 2004 * Write error occurred trying to update the inode 2005 * or the directory so must deallocate the inode. 2006 */ 2007 free(cnp->cn_pnbuf, M_NAMEI); 2008 vput(dvp); 2009 ip->i_nlink = 0; 2010 ip->i_flag |= IN_CHANGE; 2011 vput(tvp); 2012 return (error); 2013} 2014