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