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