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.107 (Berkeley) 04/27/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, UIO_USERSPACE, uap->name, p); 847 if (error = namei(&nd)) 848 return (error); 849 vp = nd.ni_vp; 850 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 851 VOP_LOCK(vp); 852 if (vp->v_type == VDIR && 853 (error = suser(p->p_ucred, &p->p_acflag))) 854 goto out; 855 /* 856 * The root of a mounted filesystem cannot be deleted. 857 */ 858 if (vp->v_flag & VROOT) { 859 error = EBUSY; 860 goto out; 861 } 862 (void) vnode_pager_uncache(vp); 863 out: 864 if (!error) { 865 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 866 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 867 } else { 868 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 869 if (nd.ni_dvp == vp) 870 vrele(nd.ni_dvp); 871 else 872 vput(nd.ni_dvp); 873 vput(vp); 874 } 875 return (error); 876 } 877 878 struct __lseek_args { 879 int fdes; 880 int pad; 881 off_t off; 882 int sbase; 883 }; 884 885 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 886 /* 887 * Seek system call. 888 */ 889 struct lseek_args { 890 int fdes; 891 long off; 892 int sbase; 893 }; 894 lseek(p, uap, retval) 895 struct proc *p; 896 register struct lseek_args *uap; 897 int *retval; 898 { 899 struct __lseek_args nuap; 900 off_t qret; 901 int error; 902 903 nuap.fdes = uap->fdes; 904 nuap.off = uap->off; 905 nuap.sbase = uap->sbase; 906 error = __lseek(p, &nuap, &qret); 907 *(long *)retval = qret; 908 return (error); 909 } 910 #endif /* COMPAT_43 || COMPAT_SUNOS */ 911 912 /* 913 * Seek system call. 914 */ 915 __lseek(p, uap, retval) 916 struct proc *p; 917 register struct __lseek_args *uap; 918 int *retval; 919 { 920 struct ucred *cred = p->p_ucred; 921 register struct filedesc *fdp = p->p_fd; 922 register struct file *fp; 923 struct vattr vattr; 924 int error; 925 926 if ((unsigned)uap->fdes >= fdp->fd_nfiles || 927 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 928 return (EBADF); 929 if (fp->f_type != DTYPE_VNODE) 930 return (ESPIPE); 931 switch (uap->sbase) { 932 933 case L_INCR: 934 fp->f_offset += uap->off; 935 break; 936 937 case L_XTND: 938 if (error = VOP_GETATTR((struct vnode *)fp->f_data, 939 &vattr, cred, p)) 940 return (error); 941 fp->f_offset = uap->off + vattr.va_size; 942 break; 943 944 case L_SET: 945 fp->f_offset = uap->off; 946 break; 947 948 default: 949 return (EINVAL); 950 } 951 *(off_t *)retval = fp->f_offset; 952 return (0); 953 } 954 955 /* 956 * Check access permissions. 957 */ 958 struct saccess_args { 959 char *fname; 960 int fmode; 961 }; 962 /* ARGSUSED */ 963 saccess(p, uap, retval) 964 struct proc *p; 965 register struct saccess_args *uap; 966 int *retval; 967 { 968 register struct ucred *cred = p->p_ucred; 969 register struct vnode *vp; 970 int error, mode, svuid, svgid; 971 struct nameidata nd; 972 973 svuid = cred->cr_uid; 974 svgid = cred->cr_groups[0]; 975 cred->cr_uid = p->p_cred->p_ruid; 976 cred->cr_groups[0] = p->p_cred->p_rgid; 977 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 978 if (error = namei(&nd)) 979 goto out1; 980 vp = nd.ni_vp; 981 /* 982 * fmode == 0 means only check for exist 983 */ 984 if (uap->fmode) { 985 mode = 0; 986 if (uap->fmode & R_OK) 987 mode |= VREAD; 988 if (uap->fmode & W_OK) 989 mode |= VWRITE; 990 if (uap->fmode & X_OK) 991 mode |= VEXEC; 992 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 993 error = VOP_ACCESS(vp, mode, cred, p); 994 } 995 vput(vp); 996 out1: 997 cred->cr_uid = svuid; 998 cred->cr_groups[0] = svgid; 999 return (error); 1000 } 1001 1002 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1003 /* 1004 * Stat system call. 1005 * This version follows links. 1006 */ 1007 struct ostat_args { 1008 char *fname; 1009 struct ostat *ub; 1010 }; 1011 /* ARGSUSED */ 1012 ostat(p, uap, retval) 1013 struct proc *p; 1014 register struct ostat_args *uap; 1015 int *retval; 1016 { 1017 struct stat sb; 1018 struct ostat osb; 1019 int error; 1020 struct nameidata nd; 1021 1022 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1023 if (error = namei(&nd)) 1024 return (error); 1025 error = vn_stat(nd.ni_vp, &sb, p); 1026 vput(nd.ni_vp); 1027 if (error) 1028 return (error); 1029 cvtstat(&sb, &osb); 1030 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1031 return (error); 1032 } 1033 1034 /* 1035 * Lstat system call. 1036 * This version does not follow links. 1037 */ 1038 struct olstat_args { 1039 char *fname; 1040 struct ostat *ub; 1041 }; 1042 /* ARGSUSED */ 1043 olstat(p, uap, retval) 1044 struct proc *p; 1045 register struct olstat_args *uap; 1046 int *retval; 1047 { 1048 struct stat sb; 1049 struct ostat osb; 1050 int error; 1051 struct nameidata nd; 1052 1053 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1054 if (error = namei(&nd)) 1055 return (error); 1056 error = vn_stat(nd.ni_vp, &sb, p); 1057 vput(nd.ni_vp); 1058 if (error) 1059 return (error); 1060 cvtstat(&sb, &osb); 1061 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1062 return (error); 1063 } 1064 1065 /* 1066 * convert from an old to a new stat structure. 1067 */ 1068 cvtstat(st, ost) 1069 struct stat *st; 1070 struct ostat *ost; 1071 { 1072 1073 ost->st_dev = st->st_dev; 1074 ost->st_ino = st->st_ino; 1075 ost->st_mode = st->st_mode; 1076 ost->st_nlink = st->st_nlink; 1077 ost->st_uid = st->st_uid; 1078 ost->st_gid = st->st_gid; 1079 ost->st_rdev = st->st_rdev; 1080 if (st->st_size < (quad_t)1 << 32) 1081 ost->st_size = st->st_size; 1082 else 1083 ost->st_size = -2; 1084 ost->st_atime = st->st_atime; 1085 ost->st_mtime = st->st_mtime; 1086 ost->st_ctime = st->st_ctime; 1087 ost->st_blksize = st->st_blksize; 1088 ost->st_blocks = st->st_blocks; 1089 ost->st_flags = st->st_flags; 1090 ost->st_gen = st->st_gen; 1091 } 1092 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1093 1094 /* 1095 * Stat system call. 1096 * This version follows links. 1097 */ 1098 struct stat_args { 1099 char *fname; 1100 struct stat *ub; 1101 }; 1102 /* ARGSUSED */ 1103 stat(p, uap, retval) 1104 struct proc *p; 1105 register struct stat_args *uap; 1106 int *retval; 1107 { 1108 struct stat sb; 1109 int error; 1110 struct nameidata nd; 1111 1112 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1113 if (error = namei(&nd)) 1114 return (error); 1115 error = vn_stat(nd.ni_vp, &sb, p); 1116 vput(nd.ni_vp); 1117 if (error) 1118 return (error); 1119 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1120 return (error); 1121 } 1122 1123 /* 1124 * Lstat system call. 1125 * This version does not follow links. 1126 */ 1127 struct lstat_args { 1128 char *fname; 1129 struct stat *ub; 1130 }; 1131 /* ARGSUSED */ 1132 lstat(p, uap, retval) 1133 struct proc *p; 1134 register struct lstat_args *uap; 1135 int *retval; 1136 { 1137 int error; 1138 struct vnode *vp, *dvp; 1139 struct stat sb, sb1; 1140 struct nameidata nd; 1141 1142 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1143 uap->fname, p); 1144 if (error = namei(&nd)) 1145 return (error); 1146 /* 1147 * For symbolic links, always return the attributes of its 1148 * containing directory, except for mode, size, and links. 1149 */ 1150 vp = nd.ni_vp; 1151 dvp = nd.ni_dvp; 1152 if (vp->v_type != VLNK) { 1153 if (dvp == vp) 1154 vrele(dvp); 1155 else 1156 vput(dvp); 1157 error = vn_stat(vp, &sb, p); 1158 vput(vp); 1159 if (error) 1160 return (error); 1161 } else { 1162 error = vn_stat(dvp, &sb, p); 1163 vput(dvp); 1164 if (error) { 1165 vput(vp); 1166 return (error); 1167 } 1168 error = vn_stat(vp, &sb1, p); 1169 vput(vp); 1170 if (error) 1171 return (error); 1172 sb.st_mode &= ~S_IFDIR; 1173 sb.st_mode |= S_IFLNK; 1174 sb.st_nlink = sb1.st_nlink; 1175 sb.st_size = sb1.st_size; 1176 sb.st_blocks = sb1.st_blocks; 1177 } 1178 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1179 return (error); 1180 } 1181 1182 /* 1183 * Return target name of a symbolic link. 1184 */ 1185 struct readlink_args { 1186 char *name; 1187 char *buf; 1188 int count; 1189 }; 1190 /* ARGSUSED */ 1191 readlink(p, uap, retval) 1192 struct proc *p; 1193 register struct readlink_args *uap; 1194 int *retval; 1195 { 1196 register struct vnode *vp; 1197 struct iovec aiov; 1198 struct uio auio; 1199 int error; 1200 struct nameidata nd; 1201 1202 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1203 if (error = namei(&nd)) 1204 return (error); 1205 vp = nd.ni_vp; 1206 if (vp->v_type != VLNK) { 1207 error = EINVAL; 1208 goto out; 1209 } 1210 aiov.iov_base = uap->buf; 1211 aiov.iov_len = uap->count; 1212 auio.uio_iov = &aiov; 1213 auio.uio_iovcnt = 1; 1214 auio.uio_offset = 0; 1215 auio.uio_rw = UIO_READ; 1216 auio.uio_segflg = UIO_USERSPACE; 1217 auio.uio_procp = p; 1218 auio.uio_resid = uap->count; 1219 error = VOP_READLINK(vp, &auio, p->p_ucred); 1220 out: 1221 vput(vp); 1222 *retval = uap->count - auio.uio_resid; 1223 return (error); 1224 } 1225 1226 /* 1227 * Change flags of a file given path name. 1228 */ 1229 struct chflags_args { 1230 char *fname; 1231 int flags; 1232 }; 1233 /* ARGSUSED */ 1234 chflags(p, uap, retval) 1235 struct proc *p; 1236 register struct chflags_args *uap; 1237 int *retval; 1238 { 1239 register struct vnode *vp; 1240 struct vattr vattr; 1241 int error; 1242 struct nameidata nd; 1243 1244 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1245 if (error = namei(&nd)) 1246 return (error); 1247 vp = nd.ni_vp; 1248 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1249 VOP_LOCK(vp); 1250 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1251 error = EROFS; 1252 goto out; 1253 } 1254 VATTR_NULL(&vattr); 1255 vattr.va_flags = uap->flags; 1256 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1257 out: 1258 vput(vp); 1259 return (error); 1260 } 1261 1262 /* 1263 * Change flags of a file given a file descriptor. 1264 */ 1265 struct fchflags_args { 1266 int fd; 1267 int flags; 1268 }; 1269 /* ARGSUSED */ 1270 fchflags(p, uap, retval) 1271 struct proc *p; 1272 register struct fchflags_args *uap; 1273 int *retval; 1274 { 1275 struct vattr vattr; 1276 struct vnode *vp; 1277 struct file *fp; 1278 int error; 1279 1280 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1281 return (error); 1282 vp = (struct vnode *)fp->f_data; 1283 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1284 VOP_LOCK(vp); 1285 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1286 error = EROFS; 1287 goto out; 1288 } 1289 VATTR_NULL(&vattr); 1290 vattr.va_flags = uap->flags; 1291 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1292 out: 1293 VOP_UNLOCK(vp); 1294 return (error); 1295 } 1296 1297 /* 1298 * Change mode of a file given path name. 1299 */ 1300 struct chmod_args { 1301 char *fname; 1302 int fmode; 1303 }; 1304 /* ARGSUSED */ 1305 chmod(p, uap, retval) 1306 struct proc *p; 1307 register struct chmod_args *uap; 1308 int *retval; 1309 { 1310 register struct vnode *vp; 1311 struct vattr vattr; 1312 int error; 1313 struct nameidata nd; 1314 1315 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1316 if (error = namei(&nd)) 1317 return (error); 1318 vp = nd.ni_vp; 1319 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1320 VOP_LOCK(vp); 1321 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1322 error = EROFS; 1323 goto out; 1324 } 1325 VATTR_NULL(&vattr); 1326 vattr.va_mode = uap->fmode & 07777; 1327 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1328 out: 1329 vput(vp); 1330 return (error); 1331 } 1332 1333 /* 1334 * Change mode of a file given a file descriptor. 1335 */ 1336 struct fchmod_args { 1337 int fd; 1338 int fmode; 1339 }; 1340 /* ARGSUSED */ 1341 fchmod(p, uap, retval) 1342 struct proc *p; 1343 register struct fchmod_args *uap; 1344 int *retval; 1345 { 1346 struct vattr vattr; 1347 struct vnode *vp; 1348 struct file *fp; 1349 int error; 1350 1351 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1352 return (error); 1353 vp = (struct vnode *)fp->f_data; 1354 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1355 VOP_LOCK(vp); 1356 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1357 error = EROFS; 1358 goto out; 1359 } 1360 VATTR_NULL(&vattr); 1361 vattr.va_mode = uap->fmode & 07777; 1362 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1363 out: 1364 VOP_UNLOCK(vp); 1365 return (error); 1366 } 1367 1368 /* 1369 * Set ownership given a path name. 1370 */ 1371 struct chown_args { 1372 char *fname; 1373 int uid; 1374 int gid; 1375 }; 1376 /* ARGSUSED */ 1377 chown(p, uap, retval) 1378 struct proc *p; 1379 register struct chown_args *uap; 1380 int *retval; 1381 { 1382 register struct vnode *vp; 1383 struct vattr vattr; 1384 int error; 1385 struct nameidata nd; 1386 1387 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, p); 1388 if (error = namei(&nd)) 1389 return (error); 1390 vp = nd.ni_vp; 1391 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1392 VOP_LOCK(vp); 1393 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1394 error = EROFS; 1395 goto out; 1396 } 1397 VATTR_NULL(&vattr); 1398 vattr.va_uid = uap->uid; 1399 vattr.va_gid = uap->gid; 1400 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1401 out: 1402 vput(vp); 1403 return (error); 1404 } 1405 1406 /* 1407 * Set ownership given a file descriptor. 1408 */ 1409 struct fchown_args { 1410 int fd; 1411 int uid; 1412 int gid; 1413 }; 1414 /* ARGSUSED */ 1415 fchown(p, uap, retval) 1416 struct proc *p; 1417 register struct fchown_args *uap; 1418 int *retval; 1419 { 1420 struct vattr vattr; 1421 struct vnode *vp; 1422 struct file *fp; 1423 int error; 1424 1425 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1426 return (error); 1427 vp = (struct vnode *)fp->f_data; 1428 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1429 VOP_LOCK(vp); 1430 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1431 error = EROFS; 1432 goto out; 1433 } 1434 VATTR_NULL(&vattr); 1435 vattr.va_uid = uap->uid; 1436 vattr.va_gid = uap->gid; 1437 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1438 out: 1439 VOP_UNLOCK(vp); 1440 return (error); 1441 } 1442 1443 /* 1444 * Set the access and modification times of a file. 1445 */ 1446 struct utimes_args { 1447 char *fname; 1448 struct timeval *tptr; 1449 }; 1450 /* ARGSUSED */ 1451 utimes(p, uap, retval) 1452 struct proc *p; 1453 register struct utimes_args *uap; 1454 int *retval; 1455 { 1456 register struct vnode *vp; 1457 struct timeval tv[2]; 1458 struct vattr vattr; 1459 int error; 1460 struct nameidata nd; 1461 1462 VATTR_NULL(&vattr); 1463 if (uap->tptr == NULL) { 1464 microtime(&tv[0]); 1465 tv[1] = tv[0]; 1466 vattr.va_vaflags |= VA_UTIMES_NULL; 1467 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1468 return (error); 1469 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1470 if (error = namei(&nd)) 1471 return (error); 1472 vp = nd.ni_vp; 1473 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1474 VOP_LOCK(vp); 1475 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1476 error = EROFS; 1477 goto out; 1478 } 1479 vattr.va_atime.ts_sec = tv[0].tv_sec; 1480 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1481 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1482 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1483 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1484 out: 1485 vput(vp); 1486 return (error); 1487 } 1488 1489 struct __truncate_args { 1490 char *fname; 1491 int pad; 1492 off_t length; 1493 }; 1494 1495 /* 1496 * Truncate a file given its path name. 1497 */ 1498 /* ARGSUSED */ 1499 __truncate(p, uap, retval) 1500 struct proc *p; 1501 register struct __truncate_args *uap; 1502 int *retval; 1503 { 1504 register struct vnode *vp; 1505 struct vattr vattr; 1506 int error; 1507 struct nameidata nd; 1508 1509 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1510 if (error = namei(&nd)) 1511 return (error); 1512 vp = nd.ni_vp; 1513 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1514 VOP_LOCK(vp); 1515 if (vp->v_type == VDIR) { 1516 error = EISDIR; 1517 goto out; 1518 } 1519 if ((error = vn_writechk(vp)) || 1520 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) 1521 goto out; 1522 VATTR_NULL(&vattr); 1523 vattr.va_size = uap->length; 1524 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1525 out: 1526 vput(vp); 1527 return (error); 1528 } 1529 1530 struct __ftruncate_args { 1531 int fd; 1532 int pad; 1533 off_t length; 1534 }; 1535 1536 /* 1537 * Truncate a file given a file descriptor. 1538 */ 1539 /* ARGSUSED */ 1540 __ftruncate(p, uap, retval) 1541 struct proc *p; 1542 register struct __ftruncate_args *uap; 1543 int *retval; 1544 { 1545 struct vattr vattr; 1546 struct vnode *vp; 1547 struct file *fp; 1548 int error; 1549 1550 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1551 return (error); 1552 if ((fp->f_flag & FWRITE) == 0) 1553 return (EINVAL); 1554 vp = (struct vnode *)fp->f_data; 1555 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1556 VOP_LOCK(vp); 1557 if (vp->v_type == VDIR) { 1558 error = EISDIR; 1559 goto out; 1560 } 1561 if (error = vn_writechk(vp)) 1562 goto out; 1563 VATTR_NULL(&vattr); 1564 vattr.va_size = uap->length; 1565 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1566 out: 1567 VOP_UNLOCK(vp); 1568 return (error); 1569 } 1570 1571 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1572 /* 1573 * Truncate a file given its path name. 1574 */ 1575 struct truncate_args { 1576 char *fname; 1577 long length; 1578 }; 1579 /* ARGSUSED */ 1580 truncate(p, uap, retval) 1581 struct proc *p; 1582 register struct truncate_args *uap; 1583 int *retval; 1584 { 1585 struct __truncate_args nuap; 1586 1587 nuap.fname = uap->fname; 1588 nuap.length = uap->length; 1589 return (__truncate(p, &nuap, retval)); 1590 } 1591 1592 /* 1593 * Truncate a file given a file descriptor. 1594 */ 1595 struct ftruncate_args { 1596 int fd; 1597 long length; 1598 }; 1599 /* ARGSUSED */ 1600 ftruncate(p, uap, retval) 1601 struct proc *p; 1602 register struct ftruncate_args *uap; 1603 int *retval; 1604 { 1605 struct __ftruncate_args nuap; 1606 1607 nuap.fd = uap->fd; 1608 nuap.length = uap->length; 1609 return (__ftruncate(p, &nuap, retval)); 1610 } 1611 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1612 1613 /* 1614 * Synch an open file. 1615 */ 1616 struct fsync_args { 1617 int fd; 1618 }; 1619 /* ARGSUSED */ 1620 fsync(p, uap, retval) 1621 struct proc *p; 1622 struct fsync_args *uap; 1623 int *retval; 1624 { 1625 register struct vnode *vp; 1626 struct file *fp; 1627 int error; 1628 1629 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1630 return (error); 1631 vp = (struct vnode *)fp->f_data; 1632 VOP_LOCK(vp); 1633 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1634 VOP_UNLOCK(vp); 1635 return (error); 1636 } 1637 1638 /* 1639 * Rename system call. 1640 * 1641 * Source and destination must either both be directories, or both 1642 * not be directories. If target is a directory, it must be empty. 1643 */ 1644 struct rename_args { 1645 char *from; 1646 char *to; 1647 }; 1648 /* ARGSUSED */ 1649 rename(p, uap, retval) 1650 struct proc *p; 1651 register struct rename_args *uap; 1652 int *retval; 1653 { 1654 register struct vnode *tvp, *fvp, *tdvp; 1655 struct nameidata fromnd, tond; 1656 int error; 1657 1658 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1659 uap->from, p); 1660 if (error = namei(&fromnd)) 1661 return (error); 1662 fvp = fromnd.ni_vp; 1663 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1664 UIO_USERSPACE, uap->to, p); 1665 if (error = namei(&tond)) { 1666 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1667 vrele(fromnd.ni_dvp); 1668 vrele(fvp); 1669 goto out1; 1670 } 1671 tdvp = tond.ni_dvp; 1672 tvp = tond.ni_vp; 1673 if (tvp != NULL) { 1674 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1675 error = ENOTDIR; 1676 goto out; 1677 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1678 error = EISDIR; 1679 goto out; 1680 } 1681 } 1682 if (fvp == tdvp) 1683 error = EINVAL; 1684 /* 1685 * If source is the same as the destination (that is the 1686 * same inode number with the same name in the same directory), 1687 * then there is nothing to do. 1688 */ 1689 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1690 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1691 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1692 fromnd.ni_cnd.cn_namelen)) 1693 error = -1; 1694 out: 1695 if (!error) { 1696 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1697 if (fromnd.ni_dvp != tdvp) 1698 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1699 if (tvp) 1700 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1701 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1702 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1703 } else { 1704 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1705 if (tdvp == tvp) 1706 vrele(tdvp); 1707 else 1708 vput(tdvp); 1709 if (tvp) 1710 vput(tvp); 1711 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1712 vrele(fromnd.ni_dvp); 1713 vrele(fvp); 1714 } 1715 vrele(tond.ni_startdir); 1716 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1717 out1: 1718 vrele(fromnd.ni_startdir); 1719 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1720 if (error == -1) 1721 return (0); 1722 return (error); 1723 } 1724 1725 /* 1726 * Mkdir system call. 1727 */ 1728 struct mkdir_args { 1729 char *name; 1730 int dmode; 1731 }; 1732 /* ARGSUSED */ 1733 mkdir(p, uap, retval) 1734 struct proc *p; 1735 register struct mkdir_args *uap; 1736 int *retval; 1737 { 1738 register struct vnode *vp; 1739 struct vattr vattr; 1740 int error; 1741 struct nameidata nd; 1742 1743 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p); 1744 if (error = namei(&nd)) 1745 return (error); 1746 vp = nd.ni_vp; 1747 if (vp != NULL) { 1748 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1749 if (nd.ni_dvp == vp) 1750 vrele(nd.ni_dvp); 1751 else 1752 vput(nd.ni_dvp); 1753 vrele(vp); 1754 return (EEXIST); 1755 } 1756 VATTR_NULL(&vattr); 1757 vattr.va_type = VDIR; 1758 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; 1759 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1760 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1761 if (!error) 1762 vput(nd.ni_vp); 1763 return (error); 1764 } 1765 1766 /* 1767 * Rmdir system call. 1768 */ 1769 struct rmdir_args { 1770 char *name; 1771 }; 1772 /* ARGSUSED */ 1773 rmdir(p, uap, retval) 1774 struct proc *p; 1775 struct rmdir_args *uap; 1776 int *retval; 1777 { 1778 register struct vnode *vp; 1779 int error; 1780 struct nameidata nd; 1781 1782 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1783 if (error = namei(&nd)) 1784 return (error); 1785 vp = nd.ni_vp; 1786 if (vp->v_type != VDIR) { 1787 error = ENOTDIR; 1788 goto out; 1789 } 1790 /* 1791 * No rmdir "." please. 1792 */ 1793 if (nd.ni_dvp == vp) { 1794 error = EINVAL; 1795 goto out; 1796 } 1797 /* 1798 * The root of a mounted filesystem cannot be deleted. 1799 */ 1800 if (vp->v_flag & VROOT) 1801 error = EBUSY; 1802 out: 1803 if (!error) { 1804 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1805 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1806 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1807 } else { 1808 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1809 if (nd.ni_dvp == vp) 1810 vrele(nd.ni_dvp); 1811 else 1812 vput(nd.ni_dvp); 1813 vput(vp); 1814 } 1815 return (error); 1816 } 1817 1818 #ifdef COMPAT_43 1819 /* 1820 * Read a block of directory entries in a file system independent format. 1821 */ 1822 struct ogetdirentries_args { 1823 int fd; 1824 char *buf; 1825 unsigned count; 1826 long *basep; 1827 }; 1828 ogetdirentries(p, uap, retval) 1829 struct proc *p; 1830 register struct ogetdirentries_args *uap; 1831 int *retval; 1832 { 1833 register struct vnode *vp; 1834 struct file *fp; 1835 struct uio auio, kuio; 1836 struct iovec aiov, kiov; 1837 struct dirent *dp, *edp; 1838 caddr_t dirbuf; 1839 int error, readcnt; 1840 long loff; 1841 1842 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1843 return (error); 1844 if ((fp->f_flag & FREAD) == 0) 1845 return (EBADF); 1846 vp = (struct vnode *)fp->f_data; 1847 if (vp->v_type != VDIR) 1848 return (EINVAL); 1849 aiov.iov_base = uap->buf; 1850 aiov.iov_len = uap->count; 1851 auio.uio_iov = &aiov; 1852 auio.uio_iovcnt = 1; 1853 auio.uio_rw = UIO_READ; 1854 auio.uio_segflg = UIO_USERSPACE; 1855 auio.uio_procp = p; 1856 auio.uio_resid = uap->count; 1857 VOP_LOCK(vp); 1858 loff = auio.uio_offset = fp->f_offset; 1859 # if (BYTE_ORDER != LITTLE_ENDIAN) 1860 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 1861 error = VOP_READDIR(vp, &auio, fp->f_cred); 1862 fp->f_offset = auio.uio_offset; 1863 } else 1864 # endif 1865 { 1866 kuio = auio; 1867 kuio.uio_iov = &kiov; 1868 kuio.uio_segflg = UIO_SYSSPACE; 1869 kiov.iov_len = uap->count; 1870 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1871 kiov.iov_base = dirbuf; 1872 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1873 fp->f_offset = kuio.uio_offset; 1874 if (error == 0) { 1875 readcnt = uap->count - kuio.uio_resid; 1876 edp = (struct dirent *)&dirbuf[readcnt]; 1877 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1878 # if (BYTE_ORDER == LITTLE_ENDIAN) 1879 /* 1880 * The expected low byte of 1881 * dp->d_namlen is our dp->d_type. 1882 * The high MBZ byte of dp->d_namlen 1883 * is our dp->d_namlen. 1884 */ 1885 dp->d_type = dp->d_namlen; 1886 dp->d_namlen = 0; 1887 # else 1888 /* 1889 * The dp->d_type is the high byte 1890 * of the expected dp->d_namlen, 1891 * so must be zero'ed. 1892 */ 1893 dp->d_type = 0; 1894 # endif 1895 if (dp->d_reclen > 0) { 1896 dp = (struct dirent *) 1897 ((char *)dp + dp->d_reclen); 1898 } else { 1899 error = EIO; 1900 break; 1901 } 1902 } 1903 if (dp >= edp) 1904 error = uiomove(dirbuf, readcnt, &auio); 1905 } 1906 FREE(dirbuf, M_TEMP); 1907 } 1908 VOP_UNLOCK(vp); 1909 if (error) 1910 return (error); 1911 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 1912 *retval = uap->count - auio.uio_resid; 1913 return (error); 1914 } 1915 #endif 1916 1917 /* 1918 * Read a block of directory entries in a file system independent format. 1919 */ 1920 struct getdirentries_args { 1921 int fd; 1922 char *buf; 1923 unsigned count; 1924 long *basep; 1925 }; 1926 getdirentries(p, uap, retval) 1927 struct proc *p; 1928 register struct getdirentries_args *uap; 1929 int *retval; 1930 { 1931 register struct vnode *vp; 1932 struct file *fp; 1933 struct uio auio; 1934 struct iovec aiov; 1935 long loff; 1936 int error; 1937 1938 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1939 return (error); 1940 if ((fp->f_flag & FREAD) == 0) 1941 return (EBADF); 1942 vp = (struct vnode *)fp->f_data; 1943 unionread: 1944 if (vp->v_type != VDIR) 1945 return (EINVAL); 1946 aiov.iov_base = uap->buf; 1947 aiov.iov_len = uap->count; 1948 auio.uio_iov = &aiov; 1949 auio.uio_iovcnt = 1; 1950 auio.uio_rw = UIO_READ; 1951 auio.uio_segflg = UIO_USERSPACE; 1952 auio.uio_procp = p; 1953 auio.uio_resid = uap->count; 1954 VOP_LOCK(vp); 1955 loff = auio.uio_offset = fp->f_offset; 1956 error = VOP_READDIR(vp, &auio, fp->f_cred); 1957 fp->f_offset = auio.uio_offset; 1958 VOP_UNLOCK(vp); 1959 if (error) 1960 return (error); 1961 if ((uap->count == auio.uio_resid) && 1962 (vp->v_flag & VROOT) && 1963 (vp->v_mount->mnt_flag & MNT_UNION)) { 1964 struct vnode *tvp = vp; 1965 vp = vp->v_mount->mnt_vnodecovered; 1966 VREF(vp); 1967 fp->f_data = (caddr_t) vp; 1968 fp->f_offset = 0; 1969 vrele(tvp); 1970 goto unionread; 1971 } 1972 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); 1973 *retval = uap->count - auio.uio_resid; 1974 return (error); 1975 } 1976 1977 /* 1978 * Set the mode mask for creation of filesystem nodes. 1979 */ 1980 struct umask_args { 1981 int mask; 1982 }; 1983 mode_t /* XXX */ 1984 umask(p, uap, retval) 1985 struct proc *p; 1986 struct umask_args *uap; 1987 int *retval; 1988 { 1989 register struct filedesc *fdp = p->p_fd; 1990 1991 *retval = fdp->fd_cmask; 1992 fdp->fd_cmask = uap->mask & 07777; 1993 return (0); 1994 } 1995 1996 /* 1997 * Void all references to file by ripping underlying filesystem 1998 * away from vnode. 1999 */ 2000 struct revoke_args { 2001 char *fname; 2002 }; 2003 /* ARGSUSED */ 2004 revoke(p, uap, retval) 2005 struct proc *p; 2006 register struct revoke_args *uap; 2007 int *retval; 2008 { 2009 register struct vnode *vp; 2010 struct vattr vattr; 2011 int error; 2012 struct nameidata nd; 2013 2014 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 2015 if (error = namei(&nd)) 2016 return (error); 2017 vp = nd.ni_vp; 2018 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2019 error = EINVAL; 2020 goto out; 2021 } 2022 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2023 goto out; 2024 if (p->p_ucred->cr_uid != vattr.va_uid && 2025 (error = suser(p->p_ucred, &p->p_acflag))) 2026 goto out; 2027 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2028 vgoneall(vp); 2029 out: 2030 vrele(vp); 2031 return (error); 2032 } 2033 2034 /* 2035 * Convert a user file descriptor to a kernel file entry. 2036 */ 2037 getvnode(fdp, fdes, fpp) 2038 struct filedesc *fdp; 2039 struct file **fpp; 2040 int fdes; 2041 { 2042 struct file *fp; 2043 2044 if ((unsigned)fdes >= fdp->fd_nfiles || 2045 (fp = fdp->fd_ofiles[fdes]) == NULL) 2046 return (EBADF); 2047 if (fp->f_type != DTYPE_VNODE) 2048 return (EINVAL); 2049 *fpp = fp; 2050 return (0); 2051 } 2052