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