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