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