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