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