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