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