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