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