1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_syscalls.c 7.92 (Berkeley) 07/09/92 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "namei.h" 13 #include "filedesc.h" 14 #include "kernel.h" 15 #include "file.h" 16 #include "stat.h" 17 #include "vnode.h" 18 #include "mount.h" 19 #include "proc.h" 20 #include "uio.h" 21 #include "malloc.h" 22 #include "dirent.h" 23 #include <vm/vm.h> 24 25 /* 26 * Virtual File System System Calls 27 */ 28 29 /* 30 * Mount system call. 31 */ 32 /* ARGSUSED */ 33 mount(p, uap, retval) 34 struct proc *p; 35 register struct args { 36 int type; 37 char *dir; 38 int flags; 39 caddr_t data; 40 } *uap; 41 int *retval; 42 { 43 register struct vnode *vp; 44 register struct mount *mp; 45 int error, flag; 46 struct nameidata nd; 47 48 /* 49 * Must be super user 50 */ 51 if (error = suser(p->p_ucred, &p->p_acflag)) 52 return (error); 53 /* 54 * Get vnode to be covered 55 */ 56 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->dir, p); 57 if (error = namei(&nd)) 58 return (error); 59 vp = nd.ni_vp; 60 if (uap->flags & MNT_UPDATE) { 61 if ((vp->v_flag & VROOT) == 0) { 62 vput(vp); 63 return (EINVAL); 64 } 65 mp = vp->v_mount; 66 /* 67 * We allow going from read-only to read-write, 68 * but not from read-write to read-only. 69 */ 70 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 71 (uap->flags & MNT_RDONLY) != 0) { 72 vput(vp); 73 return (EOPNOTSUPP); /* Needs translation */ 74 } 75 flag = mp->mnt_flag; 76 mp->mnt_flag |= MNT_UPDATE; 77 VOP_UNLOCK(vp); 78 goto update; 79 } 80 if (vp->v_usecount != 1) { 81 vput(vp); 82 return (EBUSY); 83 } 84 if (error = vinvalbuf(vp, 1, p->p_ucred, p)) 85 return (error); 86 if (vp->v_type != VDIR) { 87 vput(vp); 88 return (ENOTDIR); 89 } 90 if ((unsigned long)uap->type > MOUNT_MAXTYPE || 91 vfssw[uap->type] == (struct vfsops *)0) { 92 vput(vp); 93 return (ENODEV); 94 } 95 96 /* 97 * Allocate and initialize the file system. 98 */ 99 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 100 M_MOUNT, M_WAITOK); 101 bzero((char *)mp, (u_long)sizeof(struct mount)); 102 mp->mnt_op = vfssw[uap->type]; 103 if (error = vfs_lock(mp)) { 104 free((caddr_t)mp, M_MOUNT); 105 vput(vp); 106 return (error); 107 } 108 if (vp->v_mountedhere != (struct mount *)0) { 109 vfs_unlock(mp); 110 free((caddr_t)mp, M_MOUNT); 111 vput(vp); 112 return (EBUSY); 113 } 114 vp->v_mountedhere = mp; 115 mp->mnt_vnodecovered = vp; 116 update: 117 /* 118 * Set the mount level flags. 119 */ 120 if (uap->flags & MNT_RDONLY) 121 mp->mnt_flag |= MNT_RDONLY; 122 else 123 mp->mnt_flag &= ~MNT_RDONLY; 124 if (uap->flags & MNT_NOSUID) 125 mp->mnt_flag |= MNT_NOSUID; 126 else 127 mp->mnt_flag &= ~MNT_NOSUID; 128 if (uap->flags & MNT_NOEXEC) 129 mp->mnt_flag |= MNT_NOEXEC; 130 else 131 mp->mnt_flag &= ~MNT_NOEXEC; 132 if (uap->flags & MNT_NODEV) 133 mp->mnt_flag |= MNT_NODEV; 134 else 135 mp->mnt_flag &= ~MNT_NODEV; 136 if (uap->flags & MNT_SYNCHRONOUS) 137 mp->mnt_flag |= MNT_SYNCHRONOUS; 138 else 139 mp->mnt_flag &= ~MNT_SYNCHRONOUS; 140 /* 141 * Mount the filesystem. 142 */ 143 error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p); 144 if (mp->mnt_flag & MNT_UPDATE) { 145 mp->mnt_flag &= ~MNT_UPDATE; 146 vrele(vp); 147 if (error) 148 mp->mnt_flag = flag; 149 return (error); 150 } 151 /* 152 * Put the new filesystem on the mount list after root. 153 */ 154 mp->mnt_next = rootfs->mnt_next; 155 mp->mnt_prev = rootfs; 156 rootfs->mnt_next = mp; 157 mp->mnt_next->mnt_prev = mp; 158 cache_purge(vp); 159 if (!error) { 160 VOP_UNLOCK(vp); 161 vfs_unlock(mp); 162 error = VFS_START(mp, 0, p); 163 } else { 164 vfs_remove(mp); 165 free((caddr_t)mp, M_MOUNT); 166 vput(vp); 167 } 168 return (error); 169 } 170 171 /* 172 * Unmount system call. 173 * 174 * Note: unmount takes a path to the vnode mounted on as argument, 175 * not special file (as before). 176 */ 177 /* ARGSUSED */ 178 unmount(p, uap, retval) 179 struct proc *p; 180 register struct args { 181 char *pathp; 182 int flags; 183 } *uap; 184 int *retval; 185 { 186 register struct vnode *vp; 187 struct mount *mp; 188 int error; 189 struct nameidata nd; 190 191 /* 192 * Must be super user 193 */ 194 if (error = suser(p->p_ucred, &p->p_acflag)) 195 return (error); 196 197 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->pathp, p); 198 if (error = namei(&nd)) 199 return (error); 200 vp = nd.ni_vp; 201 /* 202 * Must be the root of the filesystem 203 */ 204 if ((vp->v_flag & VROOT) == 0) { 205 vput(vp); 206 return (EINVAL); 207 } 208 mp = vp->v_mount; 209 vput(vp); 210 return (dounmount(mp, uap->flags, p)); 211 } 212 213 /* 214 * Do an unmount. 215 */ 216 dounmount(mp, flags, p) 217 register struct mount *mp; 218 int flags; 219 struct proc *p; 220 { 221 struct vnode *coveredvp; 222 int error; 223 224 coveredvp = mp->mnt_vnodecovered; 225 if (vfs_busy(mp)) 226 return (EBUSY); 227 mp->mnt_flag |= MNT_UNMOUNT; 228 if (error = vfs_lock(mp)) 229 return (error); 230 231 vnode_pager_umount(mp); /* release cached vnodes */ 232 cache_purgevfs(mp); /* remove cache entries for this file sys */ 233 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || 234 (flags & MNT_FORCE)) 235 error = VFS_UNMOUNT(mp, flags, p); 236 mp->mnt_flag &= ~MNT_UNMOUNT; 237 vfs_unbusy(mp); 238 if (error) { 239 vfs_unlock(mp); 240 } else { 241 vrele(coveredvp); 242 vfs_remove(mp); 243 if (mp->mnt_mounth != NULL) 244 panic("unmount: dangling vnode"); 245 free((caddr_t)mp, M_MOUNT); 246 } 247 return (error); 248 } 249 250 /* 251 * Sync system call. 252 * Sync each mounted filesystem. 253 */ 254 /* ARGSUSED */ 255 sync(p, uap, retval) 256 struct proc *p; 257 void *uap; 258 int *retval; 259 { 260 register struct mount *mp; 261 struct mount *omp; 262 263 mp = rootfs; 264 do { 265 /* 266 * The lock check below is to avoid races with mount 267 * and unmount. 268 */ 269 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 270 !vfs_busy(mp)) { 271 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 272 omp = mp; 273 mp = mp->mnt_next; 274 vfs_unbusy(omp); 275 } else 276 mp = mp->mnt_next; 277 } while (mp != rootfs); 278 return (0); 279 } 280 281 /* 282 * Operate on filesystem quotas. 283 */ 284 /* ARGSUSED */ 285 quotactl(p, uap, retval) 286 struct proc *p; 287 register struct args { 288 char *path; 289 int cmd; 290 int uid; 291 caddr_t arg; 292 } *uap; 293 int *retval; 294 { 295 register struct mount *mp; 296 int error; 297 struct nameidata nd; 298 299 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 300 if (error = namei(&nd)) 301 return (error); 302 mp = nd.ni_vp->v_mount; 303 vrele(nd.ni_vp); 304 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 305 } 306 307 /* 308 * Get filesystem statistics. 309 */ 310 /* ARGSUSED */ 311 statfs(p, uap, retval) 312 struct proc *p; 313 register struct args { 314 char *path; 315 struct statfs *buf; 316 } *uap; 317 int *retval; 318 { 319 register struct mount *mp; 320 register struct statfs *sp; 321 int error; 322 struct nameidata nd; 323 324 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 325 if (error = namei(&nd)) 326 return (error); 327 mp = nd.ni_vp->v_mount; 328 sp = &mp->mnt_stat; 329 vrele(nd.ni_vp); 330 if (error = VFS_STATFS(mp, sp, p)) 331 return (error); 332 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 333 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 334 } 335 336 /* 337 * Get filesystem statistics. 338 */ 339 /* ARGSUSED */ 340 fstatfs(p, uap, retval) 341 struct proc *p; 342 register struct args { 343 int fd; 344 struct statfs *buf; 345 } *uap; 346 int *retval; 347 { 348 struct file *fp; 349 struct mount *mp; 350 register struct statfs *sp; 351 int error; 352 353 if (error = getvnode(p->p_fd, uap->fd, &fp)) 354 return (error); 355 mp = ((struct vnode *)fp->f_data)->v_mount; 356 sp = &mp->mnt_stat; 357 if (error = VFS_STATFS(mp, sp, p)) 358 return (error); 359 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 360 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 361 } 362 363 /* 364 * Get statistics on all filesystems. 365 */ 366 getfsstat(p, uap, retval) 367 struct proc *p; 368 register struct args { 369 struct statfs *buf; 370 long bufsize; 371 int flags; 372 } *uap; 373 int *retval; 374 { 375 register struct mount *mp; 376 register struct statfs *sp; 377 caddr_t sfsp; 378 long count, maxcount, error; 379 380 maxcount = uap->bufsize / sizeof(struct statfs); 381 sfsp = (caddr_t)uap->buf; 382 mp = rootfs; 383 count = 0; 384 do { 385 if (sfsp && count < maxcount && 386 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 387 sp = &mp->mnt_stat; 388 /* 389 * If MNT_NOWAIT is specified, do not refresh the 390 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 391 */ 392 if (((uap->flags & MNT_NOWAIT) == 0 || 393 (uap->flags & MNT_WAIT)) && 394 (error = VFS_STATFS(mp, sp, p))) { 395 mp = mp->mnt_prev; 396 continue; 397 } 398 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 399 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 400 return (error); 401 sfsp += sizeof(*sp); 402 } 403 count++; 404 mp = mp->mnt_prev; 405 } while (mp != rootfs); 406 if (sfsp && count > maxcount) 407 *retval = maxcount; 408 else 409 *retval = count; 410 return (0); 411 } 412 413 /* 414 * Change current working directory to a given file descriptor. 415 */ 416 /* ARGSUSED */ 417 fchdir(p, uap, retval) 418 struct proc *p; 419 struct args { 420 int fd; 421 } *uap; 422 int *retval; 423 { 424 register struct filedesc *fdp = p->p_fd; 425 register struct vnode *vp; 426 struct file *fp; 427 int error; 428 429 if (error = getvnode(fdp, uap->fd, &fp)) 430 return (error); 431 vp = (struct vnode *)fp->f_data; 432 VOP_LOCK(vp); 433 if (vp->v_type != VDIR) 434 error = ENOTDIR; 435 else 436 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 437 VOP_UNLOCK(vp); 438 if (error) 439 return (error); 440 VREF(vp); 441 vrele(fdp->fd_cdir); 442 fdp->fd_cdir = vp; 443 return (0); 444 } 445 446 /* 447 * Change current working directory (``.''). 448 */ 449 /* ARGSUSED */ 450 chdir(p, uap, retval) 451 struct proc *p; 452 struct args { 453 char *fname; 454 } *uap; 455 int *retval; 456 { 457 register struct filedesc *fdp = p->p_fd; 458 int error; 459 struct nameidata nd; 460 461 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 462 if (error = chdirec(&nd, p)) 463 return (error); 464 vrele(fdp->fd_cdir); 465 fdp->fd_cdir = nd.ni_vp; 466 return (0); 467 } 468 469 /* 470 * Change notion of root (``/'') directory. 471 */ 472 /* ARGSUSED */ 473 chroot(p, uap, retval) 474 struct proc *p; 475 struct args { 476 char *fname; 477 } *uap; 478 int *retval; 479 { 480 register struct filedesc *fdp = p->p_fd; 481 int error; 482 struct nameidata nd; 483 484 if (error = suser(p->p_ucred, &p->p_acflag)) 485 return (error); 486 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 487 if (error = chdirec(&nd, p)) 488 return (error); 489 if (fdp->fd_rdir != NULL) 490 vrele(fdp->fd_rdir); 491 fdp->fd_rdir = nd.ni_vp; 492 return (0); 493 } 494 495 /* 496 * Common routine for chroot and chdir. 497 */ 498 chdirec(ndp, p) 499 register struct nameidata *ndp; 500 struct proc *p; 501 { 502 struct vnode *vp; 503 int error; 504 505 if (error = namei(ndp)) 506 return (error); 507 vp = ndp->ni_vp; 508 if (vp->v_type != VDIR) 509 error = ENOTDIR; 510 else 511 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 512 VOP_UNLOCK(vp); 513 if (error) 514 vrele(vp); 515 return (error); 516 } 517 518 /* 519 * Open system call. 520 * Check permissions, allocate an open file structure, 521 * and call the device open routine if any. 522 */ 523 open(p, uap, retval) 524 struct proc *p; 525 register struct args { 526 char *fname; 527 int mode; 528 int crtmode; 529 } *uap; 530 int *retval; 531 { 532 register struct filedesc *fdp = p->p_fd; 533 register struct file *fp; 534 register struct vnode *vp; 535 int fmode, cmode; 536 struct file *nfp; 537 int type, indx, error; 538 struct flock lf; 539 struct nameidata nd; 540 extern struct fileops vnops; 541 542 if (error = falloc(p, &nfp, &indx)) 543 return (error); 544 fp = nfp; 545 fmode = FFLAGS(uap->mode); 546 cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX; 547 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 548 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 549 if (error = vn_open(&nd, fmode, cmode)) { 550 ffree(fp); 551 if ((error == ENODEV || error == ENXIO) && 552 p->p_dupfd >= 0 && /* XXX from fdopen */ 553 (error = dupfdopen(fdp, indx, p->p_dupfd, 554 fmode, error)) == 0) { 555 *retval = indx; 556 return (0); 557 } 558 if (error == ERESTART) 559 error = EINTR; 560 fdp->fd_ofiles[indx] = NULL; 561 return (error); 562 } 563 p->p_dupfd = 0; 564 vp = nd.ni_vp; 565 fp->f_flag = fmode & FMASK; 566 fp->f_type = DTYPE_VNODE; 567 fp->f_ops = &vnops; 568 fp->f_data = (caddr_t)vp; 569 if (fmode & (O_EXLOCK | O_SHLOCK)) { 570 lf.l_whence = SEEK_SET; 571 lf.l_start = 0; 572 lf.l_len = 0; 573 if (fmode & O_EXLOCK) 574 lf.l_type = F_WRLCK; 575 else 576 lf.l_type = F_RDLCK; 577 type = F_FLOCK; 578 if ((fmode & FNONBLOCK) == 0) 579 type |= F_WAIT; 580 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 581 VOP_UNLOCK(vp); 582 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 583 ffree(fp); 584 fdp->fd_ofiles[indx] = NULL; 585 return (error); 586 } 587 fp->f_flag |= FHASLOCK; 588 } 589 VOP_UNLOCK(vp); 590 *retval = indx; 591 return (0); 592 } 593 594 #ifdef COMPAT_43 595 /* 596 * Creat system call. 597 */ 598 ocreat(p, uap, retval) 599 struct proc *p; 600 register struct args { 601 char *fname; 602 int fmode; 603 } *uap; 604 int *retval; 605 { 606 struct nargs { 607 char *fname; 608 int mode; 609 int crtmode; 610 } openuap; 611 612 openuap.fname = uap->fname; 613 openuap.crtmode = uap->fmode; 614 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 615 return (open(p, &openuap, retval)); 616 } 617 #endif /* COMPAT_43 */ 618 619 /* 620 * Mknod system call. 621 */ 622 /* ARGSUSED */ 623 mknod(p, uap, retval) 624 struct proc *p; 625 register struct args { 626 char *fname; 627 int fmode; 628 int dev; 629 } *uap; 630 int *retval; 631 { 632 register struct vnode *vp; 633 struct vattr vattr; 634 int error; 635 struct nameidata nd; 636 637 if (error = suser(p->p_ucred, &p->p_acflag)) 638 return (error); 639 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 640 if (error = namei(&nd)) 641 return (error); 642 vp = nd.ni_vp; 643 if (vp != NULL) { 644 error = EEXIST; 645 goto out; 646 } 647 VATTR_NULL(&vattr); 648 switch (uap->fmode & S_IFMT) { 649 650 case S_IFMT: /* used by badsect to flag bad sectors */ 651 vattr.va_type = VBAD; 652 break; 653 case S_IFCHR: 654 vattr.va_type = VCHR; 655 break; 656 case S_IFBLK: 657 vattr.va_type = VBLK; 658 break; 659 default: 660 error = EINVAL; 661 goto out; 662 } 663 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 664 vattr.va_rdev = uap->dev; 665 out: 666 if (!error) { 667 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 668 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 669 } else { 670 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 671 if (nd.ni_dvp == vp) 672 vrele(nd.ni_dvp); 673 else 674 vput(nd.ni_dvp); 675 if (vp) 676 vrele(vp); 677 } 678 return (error); 679 } 680 681 /* 682 * Mkfifo system call. 683 */ 684 /* ARGSUSED */ 685 mkfifo(p, uap, retval) 686 struct proc *p; 687 register struct args { 688 char *fname; 689 int fmode; 690 } *uap; 691 int *retval; 692 { 693 struct vattr vattr; 694 int error; 695 struct nameidata nd; 696 697 #ifndef FIFO 698 return (EOPNOTSUPP); 699 #else 700 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 701 if (error = namei(&nd)) 702 return (error); 703 if (nd.ni_vp != NULL) { 704 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 705 if (nd.ni_dvp == nd.ni_vp) 706 vrele(nd.ni_dvp); 707 else 708 vput(nd.ni_dvp); 709 vrele(nd.ni_vp); 710 return (EEXIST); 711 } 712 VATTR_NULL(&vattr); 713 vattr.va_type = VFIFO; 714 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 715 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 716 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 717 #endif /* FIFO */ 718 } 719 720 /* 721 * Link system call. 722 */ 723 /* ARGSUSED */ 724 link(p, uap, retval) 725 struct proc *p; 726 register struct args { 727 char *target; 728 char *linkname; 729 } *uap; 730 int *retval; 731 { 732 register struct vnode *vp, *xp; 733 int error; 734 struct nameidata nd; 735 736 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->target, p); 737 if (error = namei(&nd)) 738 return (error); 739 vp = nd.ni_vp; 740 if (vp->v_type == VDIR && 741 (error = suser(p->p_ucred, &p->p_acflag))) 742 goto out1; 743 nd.ni_cnd.cn_nameiop = CREATE; 744 nd.ni_cnd.cn_flags = LOCKPARENT; 745 nd.ni_dirp = (caddr_t)uap->linkname; 746 if (error = namei(&nd)) 747 goto out1; 748 xp = nd.ni_vp; 749 if (xp != NULL) { 750 error = EEXIST; 751 goto out; 752 } 753 xp = nd.ni_dvp; 754 out: 755 if (!error) { 756 LEASE_CHECK(xp, p, p->p_ucred, LEASE_WRITE); 757 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 758 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 759 } else { 760 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 761 if (nd.ni_dvp == nd.ni_vp) 762 vrele(nd.ni_dvp); 763 else 764 vput(nd.ni_dvp); 765 if (nd.ni_vp) 766 vrele(nd.ni_vp); 767 } 768 out1: 769 vrele(vp); 770 return (error); 771 } 772 773 /* 774 * Make a symbolic link. 775 */ 776 /* ARGSUSED */ 777 symlink(p, uap, retval) 778 struct proc *p; 779 register struct args { 780 char *target; 781 char *linkname; 782 } *uap; 783 int *retval; 784 { 785 struct vattr vattr; 786 char *target; 787 int error; 788 struct nameidata nd; 789 790 MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 791 if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 792 goto out; 793 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->linkname, p); 794 if (error = namei(&nd)) 795 goto out; 796 if (nd.ni_vp) { 797 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 798 if (nd.ni_dvp == nd.ni_vp) 799 vrele(nd.ni_dvp); 800 else 801 vput(nd.ni_dvp); 802 vrele(nd.ni_vp); 803 error = EEXIST; 804 goto out; 805 } 806 VATTR_NULL(&vattr); 807 vattr.va_mode = 0777 &~ p->p_fd->fd_cmask; 808 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 809 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, target); 810 out: 811 FREE(target, M_NAMEI); 812 return (error); 813 } 814 815 /* 816 * Delete a name from the filesystem. 817 */ 818 /* ARGSUSED */ 819 unlink(p, uap, retval) 820 struct proc *p; 821 struct args { 822 char *name; 823 } *uap; 824 int *retval; 825 { 826 register struct vnode *vp; 827 int error; 828 struct nameidata nd; 829 830 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 831 if (error = namei(&nd)) 832 return (error); 833 vp = nd.ni_vp; 834 if (vp->v_type == VDIR && 835 (error = suser(p->p_ucred, &p->p_acflag))) 836 goto out; 837 /* 838 * The root of a mounted filesystem cannot be deleted. 839 */ 840 if (vp->v_flag & VROOT) { 841 error = EBUSY; 842 goto out; 843 } 844 (void) vnode_pager_uncache(vp); 845 out: 846 if (!error) { 847 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 848 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 849 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 850 } else { 851 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 852 if (nd.ni_dvp == vp) 853 vrele(nd.ni_dvp); 854 else 855 vput(nd.ni_dvp); 856 vput(vp); 857 } 858 return (error); 859 } 860 861 struct args_lseek { 862 int fdes; 863 int pad; 864 off_t off; 865 int sbase; 866 }; 867 868 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 869 /* 870 * Seek system call. 871 */ 872 lseek(p, uap, retval) 873 struct proc *p; 874 register struct args { 875 int fdes; 876 long off; 877 int sbase; 878 } *uap; 879 long *retval; 880 { 881 struct args_lseek nuap; 882 off_t qret; 883 int error; 884 885 nuap.fdes = uap->fdes; 886 nuap.off = uap->off; 887 nuap.sbase = uap->sbase; 888 error = __lseek(p, &nuap, &qret); 889 *retval = qret; 890 return (error); 891 } 892 #endif /* COMPAT_43 || COMPAT_SUNOS */ 893 894 /* 895 * Seek system call. 896 */ 897 __lseek(p, uap, retval) 898 struct proc *p; 899 register struct args_lseek *uap; 900 off_t *retval; 901 { 902 struct ucred *cred = p->p_ucred; 903 register struct filedesc *fdp = p->p_fd; 904 register struct file *fp; 905 struct vattr vattr; 906 int error; 907 908 if ((unsigned)uap->fdes >= fdp->fd_nfiles || 909 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 910 return (EBADF); 911 if (fp->f_type != DTYPE_VNODE) 912 return (ESPIPE); 913 switch (uap->sbase) { 914 915 case L_INCR: 916 fp->f_offset += uap->off; 917 break; 918 919 case L_XTND: 920 if (error = VOP_GETATTR((struct vnode *)fp->f_data, 921 &vattr, cred, p)) 922 return (error); 923 fp->f_offset = uap->off + vattr.va_size; 924 break; 925 926 case L_SET: 927 fp->f_offset = uap->off; 928 break; 929 930 default: 931 return (EINVAL); 932 } 933 *retval = fp->f_offset; 934 return (0); 935 } 936 937 /* 938 * Check access permissions. 939 */ 940 /* ARGSUSED */ 941 saccess(p, uap, retval) 942 struct proc *p; 943 register struct args { 944 char *fname; 945 int fmode; 946 } *uap; 947 int *retval; 948 { 949 register struct ucred *cred = p->p_ucred; 950 register struct vnode *vp; 951 int error, mode, svuid, svgid; 952 struct nameidata nd; 953 954 svuid = cred->cr_uid; 955 svgid = cred->cr_groups[0]; 956 cred->cr_uid = p->p_cred->p_ruid; 957 cred->cr_groups[0] = p->p_cred->p_rgid; 958 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 959 if (error = namei(&nd)) 960 goto out1; 961 vp = nd.ni_vp; 962 /* 963 * fmode == 0 means only check for exist 964 */ 965 if (uap->fmode) { 966 mode = 0; 967 if (uap->fmode & R_OK) 968 mode |= VREAD; 969 if (uap->fmode & W_OK) 970 mode |= VWRITE; 971 if (uap->fmode & X_OK) 972 mode |= VEXEC; 973 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 974 error = VOP_ACCESS(vp, mode, cred, p); 975 } 976 vput(vp); 977 out1: 978 cred->cr_uid = svuid; 979 cred->cr_groups[0] = svgid; 980 return (error); 981 } 982 983 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 984 /* 985 * Stat system call. 986 * This version follows links. 987 */ 988 /* ARGSUSED */ 989 ostat(p, uap, retval) 990 struct proc *p; 991 register struct args { 992 char *fname; 993 struct ostat *ub; 994 } *uap; 995 int *retval; 996 { 997 struct stat sb; 998 struct ostat osb; 999 int error; 1000 struct nameidata nd; 1001 1002 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1003 if (error = namei(&nd)) 1004 return (error); 1005 error = vn_stat(nd.ni_vp, &sb, p); 1006 vput(nd.ni_vp); 1007 if (error) 1008 return (error); 1009 cvtstat(&sb, &osb); 1010 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1011 return (error); 1012 } 1013 1014 /* 1015 * Lstat system call. 1016 * This version does not follow links. 1017 */ 1018 /* ARGSUSED */ 1019 olstat(p, uap, retval) 1020 struct proc *p; 1021 register struct args { 1022 char *fname; 1023 struct ostat *ub; 1024 } *uap; 1025 int *retval; 1026 { 1027 struct stat sb; 1028 struct ostat osb; 1029 int error; 1030 struct nameidata nd; 1031 1032 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1033 if (error = namei(&nd)) 1034 return (error); 1035 error = vn_stat(nd.ni_vp, &sb, p); 1036 vput(nd.ni_vp); 1037 if (error) 1038 return (error); 1039 cvtstat(&sb, &osb); 1040 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1041 return (error); 1042 } 1043 1044 /* 1045 * convert from an old to a new stat structure. 1046 */ 1047 cvtstat(st, ost) 1048 struct stat *st; 1049 struct ostat *ost; 1050 { 1051 1052 ost->st_dev = st->st_dev; 1053 ost->st_ino = st->st_ino; 1054 ost->st_mode = st->st_mode; 1055 ost->st_nlink = st->st_nlink; 1056 ost->st_uid = st->st_uid; 1057 ost->st_gid = st->st_gid; 1058 ost->st_rdev = st->st_rdev; 1059 if (st->st_size < (quad_t)1 << 32) 1060 ost->st_size = st->st_size; 1061 else 1062 ost->st_size = -2; 1063 ost->st_atime = st->st_atime; 1064 ost->st_mtime = st->st_mtime; 1065 ost->st_ctime = st->st_ctime; 1066 ost->st_blksize = st->st_blksize; 1067 ost->st_blocks = st->st_blocks; 1068 ost->st_flags = st->st_flags; 1069 ost->st_gen = st->st_gen; 1070 } 1071 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1072 1073 /* 1074 * Stat system call. 1075 * This version follows links. 1076 */ 1077 /* ARGSUSED */ 1078 stat(p, uap, retval) 1079 struct proc *p; 1080 register struct args { 1081 char *fname; 1082 struct stat *ub; 1083 } *uap; 1084 int *retval; 1085 { 1086 struct stat sb; 1087 int error; 1088 struct nameidata nd; 1089 1090 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1091 if (error = namei(&nd)) 1092 return (error); 1093 error = vn_stat(nd.ni_vp, &sb, p); 1094 vput(nd.ni_vp); 1095 if (error) 1096 return (error); 1097 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1098 return (error); 1099 } 1100 1101 /* 1102 * Lstat system call. 1103 * This version does not follow links. 1104 */ 1105 /* ARGSUSED */ 1106 lstat(p, uap, retval) 1107 struct proc *p; 1108 register struct args { 1109 char *fname; 1110 struct stat *ub; 1111 } *uap; 1112 int *retval; 1113 { 1114 struct stat sb; 1115 int error; 1116 struct nameidata nd; 1117 1118 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1119 if (error = namei(&nd)) 1120 return (error); 1121 error = vn_stat(nd.ni_vp, &sb, p); 1122 vput(nd.ni_vp); 1123 if (error) 1124 return (error); 1125 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1126 return (error); 1127 } 1128 1129 /* 1130 * Return target name of a symbolic link. 1131 */ 1132 /* ARGSUSED */ 1133 readlink(p, uap, retval) 1134 struct proc *p; 1135 register struct args { 1136 char *name; 1137 char *buf; 1138 int count; 1139 } *uap; 1140 int *retval; 1141 { 1142 register struct vnode *vp; 1143 struct iovec aiov; 1144 struct uio auio; 1145 int error; 1146 struct nameidata nd; 1147 1148 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1149 if (error = namei(&nd)) 1150 return (error); 1151 vp = nd.ni_vp; 1152 if (vp->v_type != VLNK) { 1153 error = EINVAL; 1154 goto out; 1155 } 1156 aiov.iov_base = uap->buf; 1157 aiov.iov_len = uap->count; 1158 auio.uio_iov = &aiov; 1159 auio.uio_iovcnt = 1; 1160 auio.uio_offset = 0; 1161 auio.uio_rw = UIO_READ; 1162 auio.uio_segflg = UIO_USERSPACE; 1163 auio.uio_procp = p; 1164 auio.uio_resid = uap->count; 1165 error = VOP_READLINK(vp, &auio, p->p_ucred); 1166 out: 1167 vput(vp); 1168 *retval = uap->count - auio.uio_resid; 1169 return (error); 1170 } 1171 1172 /* 1173 * Change flags of a file given path name. 1174 */ 1175 /* ARGSUSED */ 1176 chflags(p, uap, retval) 1177 struct proc *p; 1178 register struct args { 1179 char *fname; 1180 int flags; 1181 } *uap; 1182 int *retval; 1183 { 1184 register struct vnode *vp; 1185 struct vattr vattr; 1186 int error; 1187 struct nameidata nd; 1188 1189 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1190 if (error = namei(&nd)) 1191 return (error); 1192 vp = nd.ni_vp; 1193 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1194 error = EROFS; 1195 goto out; 1196 } 1197 VATTR_NULL(&vattr); 1198 vattr.va_flags = uap->flags; 1199 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1200 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1201 out: 1202 vput(vp); 1203 return (error); 1204 } 1205 1206 /* 1207 * Change flags of a file given a file descriptor. 1208 */ 1209 /* ARGSUSED */ 1210 fchflags(p, uap, retval) 1211 struct proc *p; 1212 register struct args { 1213 int fd; 1214 int flags; 1215 } *uap; 1216 int *retval; 1217 { 1218 struct vattr vattr; 1219 struct vnode *vp; 1220 struct file *fp; 1221 int error; 1222 1223 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1224 return (error); 1225 vp = (struct vnode *)fp->f_data; 1226 VOP_LOCK(vp); 1227 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1228 error = EROFS; 1229 goto out; 1230 } 1231 VATTR_NULL(&vattr); 1232 vattr.va_flags = uap->flags; 1233 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1234 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1235 out: 1236 VOP_UNLOCK(vp); 1237 return (error); 1238 } 1239 1240 /* 1241 * Change mode of a file given path name. 1242 */ 1243 /* ARGSUSED */ 1244 chmod(p, uap, retval) 1245 struct proc *p; 1246 register struct args { 1247 char *fname; 1248 int fmode; 1249 } *uap; 1250 int *retval; 1251 { 1252 register struct vnode *vp; 1253 struct vattr vattr; 1254 int error; 1255 struct nameidata nd; 1256 1257 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1258 if (error = namei(&nd)) 1259 return (error); 1260 vp = nd.ni_vp; 1261 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1262 error = EROFS; 1263 goto out; 1264 } 1265 VATTR_NULL(&vattr); 1266 vattr.va_mode = uap->fmode & 07777; 1267 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1268 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1269 out: 1270 vput(vp); 1271 return (error); 1272 } 1273 1274 /* 1275 * Change mode of a file given a file descriptor. 1276 */ 1277 /* ARGSUSED */ 1278 fchmod(p, uap, retval) 1279 struct proc *p; 1280 register struct args { 1281 int fd; 1282 int fmode; 1283 } *uap; 1284 int *retval; 1285 { 1286 struct vattr vattr; 1287 struct vnode *vp; 1288 struct file *fp; 1289 int error; 1290 1291 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1292 return (error); 1293 vp = (struct vnode *)fp->f_data; 1294 VOP_LOCK(vp); 1295 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1296 error = EROFS; 1297 goto out; 1298 } 1299 VATTR_NULL(&vattr); 1300 vattr.va_mode = uap->fmode & 07777; 1301 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1302 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1303 out: 1304 VOP_UNLOCK(vp); 1305 return (error); 1306 } 1307 1308 /* 1309 * Set ownership given a path name. 1310 */ 1311 /* ARGSUSED */ 1312 chown(p, uap, retval) 1313 struct proc *p; 1314 register struct args { 1315 char *fname; 1316 int uid; 1317 int gid; 1318 } *uap; 1319 int *retval; 1320 { 1321 register struct vnode *vp; 1322 struct vattr vattr; 1323 int error; 1324 struct nameidata nd; 1325 1326 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1327 if (error = namei(&nd)) 1328 return (error); 1329 vp = nd.ni_vp; 1330 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1331 error = EROFS; 1332 goto out; 1333 } 1334 VATTR_NULL(&vattr); 1335 vattr.va_uid = uap->uid; 1336 vattr.va_gid = uap->gid; 1337 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1338 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1339 out: 1340 vput(vp); 1341 return (error); 1342 } 1343 1344 /* 1345 * Set ownership given a file descriptor. 1346 */ 1347 /* ARGSUSED */ 1348 fchown(p, uap, retval) 1349 struct proc *p; 1350 register struct args { 1351 int fd; 1352 int uid; 1353 int gid; 1354 } *uap; 1355 int *retval; 1356 { 1357 struct vattr vattr; 1358 struct vnode *vp; 1359 struct file *fp; 1360 int error; 1361 1362 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1363 return (error); 1364 vp = (struct vnode *)fp->f_data; 1365 VOP_LOCK(vp); 1366 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1367 error = EROFS; 1368 goto out; 1369 } 1370 VATTR_NULL(&vattr); 1371 vattr.va_uid = uap->uid; 1372 vattr.va_gid = uap->gid; 1373 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1374 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1375 out: 1376 VOP_UNLOCK(vp); 1377 return (error); 1378 } 1379 1380 /* 1381 * Set the access and modification times of a file. 1382 */ 1383 /* ARGSUSED */ 1384 utimes(p, uap, retval) 1385 struct proc *p; 1386 register struct args { 1387 char *fname; 1388 struct timeval *tptr; 1389 } *uap; 1390 int *retval; 1391 { 1392 register struct vnode *vp; 1393 struct timeval tv[2]; 1394 struct vattr vattr; 1395 int error; 1396 struct nameidata nd; 1397 1398 if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1399 return (error); 1400 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1401 if (error = namei(&nd)) 1402 return (error); 1403 vp = nd.ni_vp; 1404 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1405 error = EROFS; 1406 goto out; 1407 } 1408 VATTR_NULL(&vattr); 1409 vattr.va_atime.ts_sec = tv[0].tv_sec; 1410 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1411 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1412 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1413 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1414 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1415 out: 1416 vput(vp); 1417 return (error); 1418 } 1419 1420 struct args_truncate { 1421 char *fname; 1422 int pad; 1423 off_t length; 1424 }; 1425 1426 /* 1427 * Truncate a file given its path name. 1428 */ 1429 /* ARGSUSED */ 1430 __truncate(p, uap, retval) 1431 struct proc *p; 1432 register struct args_truncate *uap; 1433 int *retval; 1434 { 1435 register struct vnode *vp; 1436 struct vattr vattr; 1437 int error; 1438 struct nameidata nd; 1439 1440 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1441 if (error = namei(&nd)) 1442 return (error); 1443 vp = nd.ni_vp; 1444 if (vp->v_type == VDIR) { 1445 error = EISDIR; 1446 goto out; 1447 } 1448 if ((error = vn_writechk(vp)) || 1449 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) 1450 goto out; 1451 VATTR_NULL(&vattr); 1452 vattr.va_size = uap->length; 1453 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1454 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1455 out: 1456 vput(vp); 1457 return (error); 1458 } 1459 1460 struct args_ftruncate { 1461 int fd; 1462 int pad; 1463 off_t length; 1464 }; 1465 1466 /* 1467 * Truncate a file given a file descriptor. 1468 */ 1469 /* ARGSUSED */ 1470 __ftruncate(p, uap, retval) 1471 struct proc *p; 1472 register struct args_ftruncate *uap; 1473 int *retval; 1474 { 1475 struct vattr vattr; 1476 struct vnode *vp; 1477 struct file *fp; 1478 int error; 1479 1480 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1481 return (error); 1482 if ((fp->f_flag & FWRITE) == 0) 1483 return (EINVAL); 1484 vp = (struct vnode *)fp->f_data; 1485 VOP_LOCK(vp); 1486 if (vp->v_type == VDIR) { 1487 error = EISDIR; 1488 goto out; 1489 } 1490 if (error = vn_writechk(vp)) 1491 goto out; 1492 VATTR_NULL(&vattr); 1493 vattr.va_size = uap->length; 1494 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1495 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1496 out: 1497 VOP_UNLOCK(vp); 1498 return (error); 1499 } 1500 1501 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1502 /* 1503 * Truncate a file given its path name. 1504 */ 1505 /* ARGSUSED */ 1506 truncate(p, uap, retval) 1507 struct proc *p; 1508 register struct args { 1509 char *fname; 1510 long length; 1511 } *uap; 1512 int *retval; 1513 { 1514 struct args_truncate nuap; 1515 1516 nuap.fname = uap->fname; 1517 nuap.length = uap->length; 1518 return (__truncate(p, &nuap, retval)); 1519 } 1520 1521 /* 1522 * Truncate a file given a file descriptor. 1523 */ 1524 /* ARGSUSED */ 1525 ftruncate(p, uap, retval) 1526 struct proc *p; 1527 register struct args { 1528 int fd; 1529 long length; 1530 } *uap; 1531 int *retval; 1532 { 1533 struct args_ftruncate nuap; 1534 1535 nuap.fd = uap->fd; 1536 nuap.length = uap->length; 1537 return (__ftruncate(p, &nuap, retval)); 1538 } 1539 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1540 1541 /* 1542 * Synch an open file. 1543 */ 1544 /* ARGSUSED */ 1545 fsync(p, uap, retval) 1546 struct proc *p; 1547 struct args { 1548 int fd; 1549 } *uap; 1550 int *retval; 1551 { 1552 register struct vnode *vp; 1553 struct file *fp; 1554 int error; 1555 1556 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1557 return (error); 1558 vp = (struct vnode *)fp->f_data; 1559 VOP_LOCK(vp); 1560 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1561 VOP_UNLOCK(vp); 1562 return (error); 1563 } 1564 1565 /* 1566 * Rename system call. 1567 * 1568 * Source and destination must either both be directories, or both 1569 * not be directories. If target is a directory, it must be empty. 1570 */ 1571 /* ARGSUSED */ 1572 rename(p, uap, retval) 1573 struct proc *p; 1574 register struct args { 1575 char *from; 1576 char *to; 1577 } *uap; 1578 int *retval; 1579 { 1580 register struct vnode *tvp, *fvp, *tdvp; 1581 struct nameidata fromnd, tond; 1582 int error; 1583 1584 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1585 uap->from, p); 1586 if (error = namei(&fromnd)) 1587 return (error); 1588 fvp = fromnd.ni_vp; 1589 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1590 UIO_USERSPACE, uap->to, p); 1591 if (error = namei(&tond)) { 1592 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1593 vrele(fromnd.ni_dvp); 1594 vrele(fvp); 1595 goto out1; 1596 } 1597 tdvp = tond.ni_dvp; 1598 tvp = tond.ni_vp; 1599 if (tvp != NULL) { 1600 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1601 error = ENOTDIR; 1602 goto out; 1603 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1604 error = EISDIR; 1605 goto out; 1606 } 1607 } 1608 if (fvp == tdvp) 1609 error = EINVAL; 1610 /* 1611 * If source is the same as the destination (that is the 1612 * same inode number with the same name in the same directory), 1613 * then there is nothing to do. 1614 */ 1615 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1616 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1617 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1618 fromnd.ni_cnd.cn_namelen)) 1619 error = -1; 1620 out: 1621 if (!error) { 1622 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1623 if (fromnd.ni_dvp != tdvp) 1624 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1625 if (tvp) 1626 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1627 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1628 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1629 } else { 1630 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1631 if (tdvp == tvp) 1632 vrele(tdvp); 1633 else 1634 vput(tdvp); 1635 if (tvp) 1636 vput(tvp); 1637 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1638 vrele(fromnd.ni_dvp); 1639 vrele(fvp); 1640 } 1641 vrele(tond.ni_startdir); 1642 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1643 out1: 1644 vrele(fromnd.ni_startdir); 1645 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1646 if (error == -1) 1647 return (0); 1648 return (error); 1649 } 1650 1651 /* 1652 * Mkdir system call. 1653 */ 1654 /* ARGSUSED */ 1655 mkdir(p, uap, retval) 1656 struct proc *p; 1657 register struct args { 1658 char *name; 1659 int dmode; 1660 } *uap; 1661 int *retval; 1662 { 1663 register struct vnode *vp; 1664 struct vattr vattr; 1665 int error; 1666 struct nameidata nd; 1667 1668 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p); 1669 if (error = namei(&nd)) 1670 return (error); 1671 vp = nd.ni_vp; 1672 if (vp != NULL) { 1673 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1674 if (nd.ni_dvp == vp) 1675 vrele(nd.ni_dvp); 1676 else 1677 vput(nd.ni_dvp); 1678 vrele(vp); 1679 return (EEXIST); 1680 } 1681 VATTR_NULL(&vattr); 1682 vattr.va_type = VDIR; 1683 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; 1684 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1685 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1686 if (!error) 1687 vput(nd.ni_vp); 1688 return (error); 1689 } 1690 1691 /* 1692 * Rmdir system call. 1693 */ 1694 /* ARGSUSED */ 1695 rmdir(p, uap, retval) 1696 struct proc *p; 1697 struct args { 1698 char *name; 1699 } *uap; 1700 int *retval; 1701 { 1702 register struct vnode *vp; 1703 int error; 1704 struct nameidata nd; 1705 1706 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1707 if (error = namei(&nd)) 1708 return (error); 1709 vp = nd.ni_vp; 1710 if (vp->v_type != VDIR) { 1711 error = ENOTDIR; 1712 goto out; 1713 } 1714 /* 1715 * No rmdir "." please. 1716 */ 1717 if (nd.ni_dvp == vp) { 1718 error = EINVAL; 1719 goto out; 1720 } 1721 /* 1722 * The root of a mounted filesystem cannot be deleted. 1723 */ 1724 if (vp->v_flag & VROOT) 1725 error = EBUSY; 1726 out: 1727 if (!error) { 1728 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1729 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1730 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1731 } else { 1732 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1733 if (nd.ni_dvp == vp) 1734 vrele(nd.ni_dvp); 1735 else 1736 vput(nd.ni_dvp); 1737 vput(vp); 1738 } 1739 return (error); 1740 } 1741 1742 #ifdef COMPAT_43 1743 /* 1744 * Read a block of directory entries in a file system independent format. 1745 */ 1746 ogetdirentries(p, uap, retval) 1747 struct proc *p; 1748 register struct args { 1749 int fd; 1750 char *buf; 1751 unsigned count; 1752 long *basep; 1753 } *uap; 1754 int *retval; 1755 { 1756 register struct vnode *vp; 1757 struct file *fp; 1758 struct uio auio, kuio; 1759 struct iovec aiov, kiov; 1760 struct dirent *dp, *edp; 1761 caddr_t dirbuf; 1762 int error, readcnt; 1763 off_t off; 1764 1765 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1766 return (error); 1767 if ((fp->f_flag & FREAD) == 0) 1768 return (EBADF); 1769 vp = (struct vnode *)fp->f_data; 1770 if (vp->v_type != VDIR) 1771 return (EINVAL); 1772 aiov.iov_base = uap->buf; 1773 aiov.iov_len = uap->count; 1774 auio.uio_iov = &aiov; 1775 auio.uio_iovcnt = 1; 1776 auio.uio_rw = UIO_READ; 1777 auio.uio_segflg = UIO_USERSPACE; 1778 auio.uio_procp = p; 1779 auio.uio_resid = uap->count; 1780 VOP_LOCK(vp); 1781 auio.uio_offset = off = fp->f_offset; 1782 # if (BYTE_ORDER != LITTLE_ENDIAN) 1783 if (vp->v_mount->mnt_maxsymlinklen <= 0) 1784 error = VOP_READDIR(vp, &auio, fp->f_cred); 1785 else 1786 # endif 1787 { 1788 kuio = auio; 1789 kuio.uio_iov = &kiov; 1790 kuio.uio_segflg = UIO_SYSSPACE; 1791 kiov.iov_len = uap->count; 1792 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1793 kiov.iov_base = dirbuf; 1794 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1795 if (error == 0) { 1796 readcnt = uap->count - kuio.uio_resid; 1797 edp = (struct dirent *)&dirbuf[readcnt]; 1798 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1799 dp->d_type = 0; 1800 # if (BYTE_ORDER == LITTLE_ENDIAN) 1801 { u_char tmp = dp->d_namlen; 1802 dp->d_namlen = dp->d_type; 1803 dp->d_type = tmp; } 1804 # endif 1805 if (dp->d_reclen > 0) { 1806 dp = (struct dirent *) 1807 ((char *)dp + dp->d_reclen); 1808 } else { 1809 error = EIO; 1810 break; 1811 } 1812 } 1813 if (dp >= edp) 1814 error = uiomove(dirbuf, readcnt, &auio); 1815 } 1816 FREE(dirbuf, M_TEMP); 1817 } 1818 fp->f_offset = auio.uio_offset; 1819 VOP_UNLOCK(vp); 1820 if (error) 1821 return (error); 1822 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 1823 *retval = uap->count - auio.uio_resid; 1824 return (error); 1825 } 1826 #endif 1827 1828 /* 1829 * Read a block of directory entries in a file system independent format. 1830 */ 1831 getdirentries(p, uap, retval) 1832 struct proc *p; 1833 register struct args { 1834 int fd; 1835 char *buf; 1836 unsigned count; 1837 long *basep; 1838 } *uap; 1839 int *retval; 1840 { 1841 register struct vnode *vp; 1842 struct file *fp; 1843 struct uio auio; 1844 struct iovec aiov; 1845 off_t off; 1846 int error; 1847 1848 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1849 return (error); 1850 if ((fp->f_flag & FREAD) == 0) 1851 return (EBADF); 1852 vp = (struct vnode *)fp->f_data; 1853 if (vp->v_type != VDIR) 1854 return (EINVAL); 1855 aiov.iov_base = uap->buf; 1856 aiov.iov_len = uap->count; 1857 auio.uio_iov = &aiov; 1858 auio.uio_iovcnt = 1; 1859 auio.uio_rw = UIO_READ; 1860 auio.uio_segflg = UIO_USERSPACE; 1861 auio.uio_procp = p; 1862 auio.uio_resid = uap->count; 1863 VOP_LOCK(vp); 1864 auio.uio_offset = off = fp->f_offset; 1865 error = VOP_READDIR(vp, &auio, fp->f_cred); 1866 fp->f_offset = auio.uio_offset; 1867 VOP_UNLOCK(vp); 1868 if (error) 1869 return (error); 1870 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 1871 *retval = uap->count - auio.uio_resid; 1872 return (error); 1873 } 1874 1875 /* 1876 * Set the mode mask for creation of filesystem nodes. 1877 */ 1878 mode_t 1879 umask(p, uap, retval) 1880 struct proc *p; 1881 struct args { 1882 int mask; 1883 } *uap; 1884 int *retval; 1885 { 1886 register struct filedesc *fdp = p->p_fd; 1887 1888 *retval = fdp->fd_cmask; 1889 fdp->fd_cmask = uap->mask & 07777; 1890 return (0); 1891 } 1892 1893 /* 1894 * Void all references to file by ripping underlying filesystem 1895 * away from vnode. 1896 */ 1897 /* ARGSUSED */ 1898 revoke(p, uap, retval) 1899 struct proc *p; 1900 register struct args { 1901 char *fname; 1902 } *uap; 1903 int *retval; 1904 { 1905 register struct vnode *vp; 1906 struct vattr vattr; 1907 int error; 1908 struct nameidata nd; 1909 1910 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1911 if (error = namei(&nd)) 1912 return (error); 1913 vp = nd.ni_vp; 1914 if (vp->v_type != VCHR && vp->v_type != VBLK) { 1915 error = EINVAL; 1916 goto out; 1917 } 1918 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 1919 goto out; 1920 if (p->p_ucred->cr_uid != vattr.va_uid && 1921 (error = suser(p->p_ucred, &p->p_acflag))) 1922 goto out; 1923 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 1924 vgoneall(vp); 1925 out: 1926 vrele(vp); 1927 return (error); 1928 } 1929 1930 /* 1931 * Convert a user file descriptor to a kernel file entry. 1932 */ 1933 getvnode(fdp, fdes, fpp) 1934 struct filedesc *fdp; 1935 struct file **fpp; 1936 int fdes; 1937 { 1938 struct file *fp; 1939 1940 if ((unsigned)fdes >= fdp->fd_nfiles || 1941 (fp = fdp->fd_ofiles[fdes]) == NULL) 1942 return (EBADF); 1943 if (fp->f_type != DTYPE_VNODE) 1944 return (EINVAL); 1945 *fpp = fp; 1946 return (0); 1947 } 1948