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