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