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.29 (Berkeley) 02/14/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(nd.ni_dvp, vp, &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 1340 * containing directory, except for mode, size, 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 } 1370 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1371 return (error); 1372 } 1373 1374 /* 1375 * Get configurable pathname variables. 1376 */ 1377 /* ARGSUSED */ 1378 int 1379 pathconf(p, uap, retval) 1380 struct proc *p; 1381 register struct pathconf_args /* { 1382 syscallarg(char *) path; 1383 syscallarg(int) name; 1384 } */ *uap; 1385 register_t *retval; 1386 { 1387 int error; 1388 struct nameidata nd; 1389 1390 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1391 SCARG(uap, path), p); 1392 if (error = namei(&nd)) 1393 return (error); 1394 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 1395 vput(nd.ni_vp); 1396 return (error); 1397 } 1398 1399 /* 1400 * Return target name of a symbolic link. 1401 */ 1402 /* ARGSUSED */ 1403 int 1404 readlink(p, uap, retval) 1405 struct proc *p; 1406 register struct readlink_args /* { 1407 syscallarg(char *) path; 1408 syscallarg(char *) buf; 1409 syscallarg(int) count; 1410 } */ *uap; 1411 register_t *retval; 1412 { 1413 register struct vnode *vp; 1414 struct iovec aiov; 1415 struct uio auio; 1416 int error; 1417 struct nameidata nd; 1418 1419 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1420 SCARG(uap, path), p); 1421 if (error = namei(&nd)) 1422 return (error); 1423 vp = nd.ni_vp; 1424 if (vp->v_type != VLNK) 1425 error = EINVAL; 1426 else { 1427 aiov.iov_base = SCARG(uap, buf); 1428 aiov.iov_len = SCARG(uap, count); 1429 auio.uio_iov = &aiov; 1430 auio.uio_iovcnt = 1; 1431 auio.uio_offset = 0; 1432 auio.uio_rw = UIO_READ; 1433 auio.uio_segflg = UIO_USERSPACE; 1434 auio.uio_procp = p; 1435 auio.uio_resid = SCARG(uap, count); 1436 error = VOP_READLINK(vp, &auio, p->p_ucred); 1437 } 1438 vput(vp); 1439 *retval = SCARG(uap, count) - auio.uio_resid; 1440 return (error); 1441 } 1442 1443 /* 1444 * Change flags of a file given a path name. 1445 */ 1446 /* ARGSUSED */ 1447 int 1448 chflags(p, uap, retval) 1449 struct proc *p; 1450 register struct chflags_args /* { 1451 syscallarg(char *) path; 1452 syscallarg(int) flags; 1453 } */ *uap; 1454 register_t *retval; 1455 { 1456 register struct vnode *vp; 1457 struct vattr vattr; 1458 int error; 1459 struct nameidata nd; 1460 1461 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1462 if (error = namei(&nd)) 1463 return (error); 1464 vp = nd.ni_vp; 1465 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1466 VOP_LOCK(vp); 1467 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1468 error = EROFS; 1469 else { 1470 VATTR_NULL(&vattr); 1471 vattr.va_flags = SCARG(uap, flags); 1472 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1473 } 1474 vput(vp); 1475 return (error); 1476 } 1477 1478 /* 1479 * Change flags of a file given a file descriptor. 1480 */ 1481 /* ARGSUSED */ 1482 int 1483 fchflags(p, uap, retval) 1484 struct proc *p; 1485 register struct fchflags_args /* { 1486 syscallarg(int) fd; 1487 syscallarg(int) flags; 1488 } */ *uap; 1489 register_t *retval; 1490 { 1491 struct vattr vattr; 1492 struct vnode *vp; 1493 struct file *fp; 1494 int error; 1495 1496 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1497 return (error); 1498 vp = (struct vnode *)fp->f_data; 1499 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1500 VOP_LOCK(vp); 1501 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1502 error = EROFS; 1503 else { 1504 VATTR_NULL(&vattr); 1505 vattr.va_flags = SCARG(uap, flags); 1506 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1507 } 1508 VOP_UNLOCK(vp); 1509 return (error); 1510 } 1511 1512 /* 1513 * Change mode of a file given path name. 1514 */ 1515 /* ARGSUSED */ 1516 int 1517 chmod(p, uap, retval) 1518 struct proc *p; 1519 register struct chmod_args /* { 1520 syscallarg(char *) path; 1521 syscallarg(int) mode; 1522 } */ *uap; 1523 register_t *retval; 1524 { 1525 register struct vnode *vp; 1526 struct vattr vattr; 1527 int error; 1528 struct nameidata nd; 1529 1530 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1531 if (error = namei(&nd)) 1532 return (error); 1533 vp = nd.ni_vp; 1534 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1535 VOP_LOCK(vp); 1536 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1537 error = EROFS; 1538 else { 1539 VATTR_NULL(&vattr); 1540 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1541 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1542 } 1543 vput(vp); 1544 return (error); 1545 } 1546 1547 /* 1548 * Change mode of a file given a file descriptor. 1549 */ 1550 /* ARGSUSED */ 1551 int 1552 fchmod(p, uap, retval) 1553 struct proc *p; 1554 register struct fchmod_args /* { 1555 syscallarg(int) fd; 1556 syscallarg(int) mode; 1557 } */ *uap; 1558 register_t *retval; 1559 { 1560 struct vattr vattr; 1561 struct vnode *vp; 1562 struct file *fp; 1563 int error; 1564 1565 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1566 return (error); 1567 vp = (struct vnode *)fp->f_data; 1568 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1569 VOP_LOCK(vp); 1570 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1571 error = EROFS; 1572 else { 1573 VATTR_NULL(&vattr); 1574 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1575 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1576 } 1577 VOP_UNLOCK(vp); 1578 return (error); 1579 } 1580 1581 /* 1582 * Set ownership given a path name. 1583 */ 1584 /* ARGSUSED */ 1585 int 1586 chown(p, uap, retval) 1587 struct proc *p; 1588 register struct chown_args /* { 1589 syscallarg(char *) path; 1590 syscallarg(int) uid; 1591 syscallarg(int) gid; 1592 } */ *uap; 1593 register_t *retval; 1594 { 1595 register struct vnode *vp; 1596 struct vattr vattr; 1597 int error; 1598 struct nameidata nd; 1599 1600 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1601 if (error = namei(&nd)) 1602 return (error); 1603 vp = nd.ni_vp; 1604 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1605 VOP_LOCK(vp); 1606 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1607 error = EROFS; 1608 else { 1609 VATTR_NULL(&vattr); 1610 vattr.va_uid = SCARG(uap, uid); 1611 vattr.va_gid = SCARG(uap, gid); 1612 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1613 } 1614 vput(vp); 1615 return (error); 1616 } 1617 1618 /* 1619 * Set ownership given a file descriptor. 1620 */ 1621 /* ARGSUSED */ 1622 int 1623 fchown(p, uap, retval) 1624 struct proc *p; 1625 register struct fchown_args /* { 1626 syscallarg(int) fd; 1627 syscallarg(int) uid; 1628 syscallarg(int) gid; 1629 } */ *uap; 1630 register_t *retval; 1631 { 1632 struct vattr vattr; 1633 struct vnode *vp; 1634 struct file *fp; 1635 int error; 1636 1637 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1638 return (error); 1639 vp = (struct vnode *)fp->f_data; 1640 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1641 VOP_LOCK(vp); 1642 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1643 error = EROFS; 1644 else { 1645 VATTR_NULL(&vattr); 1646 vattr.va_uid = SCARG(uap, uid); 1647 vattr.va_gid = SCARG(uap, gid); 1648 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1649 } 1650 VOP_UNLOCK(vp); 1651 return (error); 1652 } 1653 1654 /* 1655 * Set the access and modification times of a file. 1656 */ 1657 /* ARGSUSED */ 1658 int 1659 utimes(p, uap, retval) 1660 struct proc *p; 1661 register struct utimes_args /* { 1662 syscallarg(char *) path; 1663 syscallarg(struct timeval *) tptr; 1664 } */ *uap; 1665 register_t *retval; 1666 { 1667 register struct vnode *vp; 1668 struct timeval tv[2]; 1669 struct vattr vattr; 1670 int error; 1671 struct nameidata nd; 1672 1673 VATTR_NULL(&vattr); 1674 if (SCARG(uap, tptr) == NULL) { 1675 microtime(&tv[0]); 1676 tv[1] = tv[0]; 1677 vattr.va_vaflags |= VA_UTIMES_NULL; 1678 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1679 sizeof (tv))) 1680 return (error); 1681 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1682 if (error = namei(&nd)) 1683 return (error); 1684 vp = nd.ni_vp; 1685 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1686 VOP_LOCK(vp); 1687 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1688 error = EROFS; 1689 else { 1690 vattr.va_atime.ts_sec = tv[0].tv_sec; 1691 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1692 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1693 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1694 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1695 } 1696 vput(vp); 1697 return (error); 1698 } 1699 1700 /* 1701 * Truncate a file given its path name. 1702 */ 1703 /* ARGSUSED */ 1704 int 1705 truncate(p, uap, retval) 1706 struct proc *p; 1707 register struct truncate_args /* { 1708 syscallarg(char *) path; 1709 syscallarg(int) pad; 1710 syscallarg(off_t) length; 1711 } */ *uap; 1712 register_t *retval; 1713 { 1714 register struct vnode *vp; 1715 struct vattr vattr; 1716 int error; 1717 struct nameidata nd; 1718 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_type == VDIR) 1726 error = EISDIR; 1727 else if ((error = vn_writechk(vp)) == 0 && 1728 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1729 VATTR_NULL(&vattr); 1730 vattr.va_size = SCARG(uap, length); 1731 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1732 } 1733 vput(vp); 1734 return (error); 1735 } 1736 1737 /* 1738 * Truncate a file given a file descriptor. 1739 */ 1740 /* ARGSUSED */ 1741 int 1742 ftruncate(p, uap, retval) 1743 struct proc *p; 1744 register struct ftruncate_args /* { 1745 syscallarg(int) fd; 1746 syscallarg(int) pad; 1747 syscallarg(off_t) length; 1748 } */ *uap; 1749 register_t *retval; 1750 { 1751 struct vattr vattr; 1752 struct vnode *vp; 1753 struct file *fp; 1754 int error; 1755 1756 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1757 return (error); 1758 if ((fp->f_flag & FWRITE) == 0) 1759 return (EINVAL); 1760 vp = (struct vnode *)fp->f_data; 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 VATTR_NULL(&vattr); 1767 vattr.va_size = SCARG(uap, length); 1768 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1769 } 1770 VOP_UNLOCK(vp); 1771 return (error); 1772 } 1773 1774 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1775 /* 1776 * Truncate a file given its path name. 1777 */ 1778 /* ARGSUSED */ 1779 int 1780 compat_43_truncate(p, uap, retval) 1781 struct proc *p; 1782 register struct compat_43_truncate_args /* { 1783 syscallarg(char *) path; 1784 syscallarg(long) length; 1785 } */ *uap; 1786 register_t *retval; 1787 { 1788 struct truncate_args /* { 1789 syscallarg(char *) path; 1790 syscallarg(int) pad; 1791 syscallarg(off_t) length; 1792 } */ nuap; 1793 1794 SCARG(&nuap, path) = SCARG(uap, path); 1795 SCARG(&nuap, length) = SCARG(uap, length); 1796 return (truncate(p, &nuap, retval)); 1797 } 1798 1799 /* 1800 * Truncate a file given a file descriptor. 1801 */ 1802 /* ARGSUSED */ 1803 int 1804 compat_43_ftruncate(p, uap, retval) 1805 struct proc *p; 1806 register struct compat_43_ftruncate_args /* { 1807 syscallarg(int) fd; 1808 syscallarg(long) length; 1809 } */ *uap; 1810 register_t *retval; 1811 { 1812 struct ftruncate_args /* { 1813 syscallarg(int) fd; 1814 syscallarg(int) pad; 1815 syscallarg(off_t) length; 1816 } */ nuap; 1817 1818 SCARG(&nuap, fd) = SCARG(uap, fd); 1819 SCARG(&nuap, length) = SCARG(uap, length); 1820 return (ftruncate(p, &nuap, retval)); 1821 } 1822 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1823 1824 /* 1825 * Sync an open file. 1826 */ 1827 /* ARGSUSED */ 1828 int 1829 fsync(p, uap, retval) 1830 struct proc *p; 1831 struct fsync_args /* { 1832 syscallarg(int) fd; 1833 } */ *uap; 1834 register_t *retval; 1835 { 1836 register struct vnode *vp; 1837 struct file *fp; 1838 int error; 1839 1840 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1841 return (error); 1842 vp = (struct vnode *)fp->f_data; 1843 VOP_LOCK(vp); 1844 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1845 VOP_UNLOCK(vp); 1846 return (error); 1847 } 1848 1849 /* 1850 * Rename files. Source and destination must either both be directories, 1851 * or both not be directories. If target is a directory, it must be empty. 1852 */ 1853 /* ARGSUSED */ 1854 int 1855 rename(p, uap, retval) 1856 struct proc *p; 1857 register struct rename_args /* { 1858 syscallarg(char *) from; 1859 syscallarg(char *) to; 1860 } */ *uap; 1861 register_t *retval; 1862 { 1863 register struct vnode *tvp, *fvp, *tdvp; 1864 struct nameidata fromnd, tond; 1865 int error; 1866 1867 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1868 SCARG(uap, from), p); 1869 if (error = namei(&fromnd)) 1870 return (error); 1871 fvp = fromnd.ni_vp; 1872 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1873 UIO_USERSPACE, SCARG(uap, to), p); 1874 if (error = namei(&tond)) { 1875 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1876 vrele(fromnd.ni_dvp); 1877 vrele(fvp); 1878 goto out1; 1879 } 1880 tdvp = tond.ni_dvp; 1881 tvp = tond.ni_vp; 1882 if (tvp != NULL) { 1883 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1884 error = ENOTDIR; 1885 goto out; 1886 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1887 error = EISDIR; 1888 goto out; 1889 } 1890 } 1891 if (fvp == tdvp) 1892 error = EINVAL; 1893 /* 1894 * If source is the same as the destination (that is the 1895 * same inode number with the same name in the same directory), 1896 * then there is nothing to do. 1897 */ 1898 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1899 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1900 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1901 fromnd.ni_cnd.cn_namelen)) 1902 error = -1; 1903 out: 1904 if (!error) { 1905 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 1906 if (fromnd.ni_dvp != tdvp) 1907 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1908 if (tvp) 1909 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 1910 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1911 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1912 } else { 1913 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1914 if (tdvp == tvp) 1915 vrele(tdvp); 1916 else 1917 vput(tdvp); 1918 if (tvp) 1919 vput(tvp); 1920 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1921 vrele(fromnd.ni_dvp); 1922 vrele(fvp); 1923 } 1924 vrele(tond.ni_startdir); 1925 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1926 out1: 1927 if (fromnd.ni_startdir) 1928 vrele(fromnd.ni_startdir); 1929 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1930 if (error == -1) 1931 return (0); 1932 return (error); 1933 } 1934 1935 /* 1936 * Make a directory file. 1937 */ 1938 /* ARGSUSED */ 1939 int 1940 mkdir(p, uap, retval) 1941 struct proc *p; 1942 register struct mkdir_args /* { 1943 syscallarg(char *) path; 1944 syscallarg(int) mode; 1945 } */ *uap; 1946 register_t *retval; 1947 { 1948 register struct vnode *vp; 1949 struct vattr vattr; 1950 int error; 1951 struct nameidata nd; 1952 1953 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1954 if (error = namei(&nd)) 1955 return (error); 1956 vp = nd.ni_vp; 1957 if (vp != NULL) { 1958 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1959 if (nd.ni_dvp == vp) 1960 vrele(nd.ni_dvp); 1961 else 1962 vput(nd.ni_dvp); 1963 vrele(vp); 1964 return (EEXIST); 1965 } 1966 VATTR_NULL(&vattr); 1967 vattr.va_type = VDIR; 1968 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 1969 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1970 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1971 if (!error) 1972 vput(nd.ni_vp); 1973 return (error); 1974 } 1975 1976 /* 1977 * Remove a directory file. 1978 */ 1979 /* ARGSUSED */ 1980 int 1981 rmdir(p, uap, retval) 1982 struct proc *p; 1983 struct rmdir_args /* { 1984 syscallarg(char *) path; 1985 } */ *uap; 1986 register_t *retval; 1987 { 1988 register struct vnode *vp; 1989 int error; 1990 struct nameidata nd; 1991 1992 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 1993 SCARG(uap, path), p); 1994 if (error = namei(&nd)) 1995 return (error); 1996 vp = nd.ni_vp; 1997 if (vp->v_type != VDIR) { 1998 error = ENOTDIR; 1999 goto out; 2000 } 2001 /* 2002 * No rmdir "." please. 2003 */ 2004 if (nd.ni_dvp == vp) { 2005 error = EINVAL; 2006 goto out; 2007 } 2008 /* 2009 * The root of a mounted filesystem cannot be deleted. 2010 */ 2011 if (vp->v_flag & VROOT) 2012 error = EBUSY; 2013 out: 2014 if (!error) { 2015 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2016 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2017 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2018 } else { 2019 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2020 if (nd.ni_dvp == vp) 2021 vrele(nd.ni_dvp); 2022 else 2023 vput(nd.ni_dvp); 2024 vput(vp); 2025 } 2026 return (error); 2027 } 2028 2029 #ifdef COMPAT_43 2030 /* 2031 * Read a block of directory entries in a file system independent format. 2032 */ 2033 int 2034 compat_43_getdirentries(p, uap, retval) 2035 struct proc *p; 2036 register struct compat_43_getdirentries_args /* { 2037 syscallarg(int) fd; 2038 syscallarg(char *) buf; 2039 syscallarg(u_int) count; 2040 syscallarg(long *) basep; 2041 } */ *uap; 2042 register_t *retval; 2043 { 2044 register struct vnode *vp; 2045 struct file *fp; 2046 struct uio auio, kuio; 2047 struct iovec aiov, kiov; 2048 struct dirent *dp, *edp; 2049 caddr_t dirbuf; 2050 int error, eofflag, readcnt; 2051 long loff; 2052 2053 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2054 return (error); 2055 if ((fp->f_flag & FREAD) == 0) 2056 return (EBADF); 2057 vp = (struct vnode *)fp->f_data; 2058 unionread: 2059 if (vp->v_type != VDIR) 2060 return (EINVAL); 2061 aiov.iov_base = SCARG(uap, buf); 2062 aiov.iov_len = SCARG(uap, count); 2063 auio.uio_iov = &aiov; 2064 auio.uio_iovcnt = 1; 2065 auio.uio_rw = UIO_READ; 2066 auio.uio_segflg = UIO_USERSPACE; 2067 auio.uio_procp = p; 2068 auio.uio_resid = SCARG(uap, count); 2069 VOP_LOCK(vp); 2070 loff = auio.uio_offset = fp->f_offset; 2071 # if (BYTE_ORDER != LITTLE_ENDIAN) 2072 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2073 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2074 (u_long *)0, 0); 2075 fp->f_offset = auio.uio_offset; 2076 } else 2077 # endif 2078 { 2079 kuio = auio; 2080 kuio.uio_iov = &kiov; 2081 kuio.uio_segflg = UIO_SYSSPACE; 2082 kiov.iov_len = SCARG(uap, count); 2083 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2084 kiov.iov_base = dirbuf; 2085 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2086 (u_long *)0, 0); 2087 fp->f_offset = kuio.uio_offset; 2088 if (error == 0) { 2089 readcnt = SCARG(uap, count) - kuio.uio_resid; 2090 edp = (struct dirent *)&dirbuf[readcnt]; 2091 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2092 # if (BYTE_ORDER == LITTLE_ENDIAN) 2093 /* 2094 * The expected low byte of 2095 * dp->d_namlen is our dp->d_type. 2096 * The high MBZ byte of dp->d_namlen 2097 * is our dp->d_namlen. 2098 */ 2099 dp->d_type = dp->d_namlen; 2100 dp->d_namlen = 0; 2101 # else 2102 /* 2103 * The dp->d_type is the high byte 2104 * of the expected dp->d_namlen, 2105 * so must be zero'ed. 2106 */ 2107 dp->d_type = 0; 2108 # endif 2109 if (dp->d_reclen > 0) { 2110 dp = (struct dirent *) 2111 ((char *)dp + dp->d_reclen); 2112 } else { 2113 error = EIO; 2114 break; 2115 } 2116 } 2117 if (dp >= edp) 2118 error = uiomove(dirbuf, readcnt, &auio); 2119 } 2120 FREE(dirbuf, M_TEMP); 2121 } 2122 VOP_UNLOCK(vp); 2123 if (error) 2124 return (error); 2125 2126 #ifdef UNION 2127 { 2128 extern int (**union_vnodeop_p)(); 2129 extern struct vnode *union_dircache __P((struct vnode *)); 2130 2131 if ((SCARG(uap, count) == auio.uio_resid) && 2132 (vp->v_op == union_vnodeop_p)) { 2133 struct vnode *lvp; 2134 2135 lvp = union_dircache(vp); 2136 if (lvp != NULLVP) { 2137 struct vattr va; 2138 2139 /* 2140 * If the directory is opaque, 2141 * then don't show lower entries 2142 */ 2143 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2144 if (va.va_flags & OPAQUE) { 2145 vput(lvp); 2146 lvp = NULL; 2147 } 2148 } 2149 2150 if (lvp != NULLVP) { 2151 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2152 VOP_UNLOCK(lvp); 2153 2154 if (error) { 2155 vrele(lvp); 2156 return (error); 2157 } 2158 fp->f_data = (caddr_t) lvp; 2159 fp->f_offset = 0; 2160 error = vn_close(vp, FREAD, fp->f_cred, p); 2161 if (error) 2162 return (error); 2163 vp = lvp; 2164 goto unionread; 2165 } 2166 } 2167 } 2168 #endif /* UNION */ 2169 2170 if ((SCARG(uap, count) == auio.uio_resid) && 2171 (vp->v_flag & VROOT) && 2172 (vp->v_mount->mnt_flag & MNT_UNION)) { 2173 struct vnode *tvp = vp; 2174 vp = vp->v_mount->mnt_vnodecovered; 2175 VREF(vp); 2176 fp->f_data = (caddr_t) vp; 2177 fp->f_offset = 0; 2178 vrele(tvp); 2179 goto unionread; 2180 } 2181 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2182 sizeof(long)); 2183 *retval = SCARG(uap, count) - auio.uio_resid; 2184 return (error); 2185 } 2186 #endif /* COMPAT_43 */ 2187 2188 /* 2189 * Read a block of directory entries in a file system independent format. 2190 */ 2191 int 2192 getdirentries(p, uap, retval) 2193 struct proc *p; 2194 register struct getdirentries_args /* { 2195 syscallarg(int) fd; 2196 syscallarg(char *) buf; 2197 syscallarg(u_int) count; 2198 syscallarg(long *) basep; 2199 } */ *uap; 2200 register_t *retval; 2201 { 2202 register struct vnode *vp; 2203 struct file *fp; 2204 struct uio auio; 2205 struct iovec aiov; 2206 long loff; 2207 int error, eofflag; 2208 2209 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2210 return (error); 2211 if ((fp->f_flag & FREAD) == 0) 2212 return (EBADF); 2213 vp = (struct vnode *)fp->f_data; 2214 unionread: 2215 if (vp->v_type != VDIR) 2216 return (EINVAL); 2217 aiov.iov_base = SCARG(uap, buf); 2218 aiov.iov_len = SCARG(uap, count); 2219 auio.uio_iov = &aiov; 2220 auio.uio_iovcnt = 1; 2221 auio.uio_rw = UIO_READ; 2222 auio.uio_segflg = UIO_USERSPACE; 2223 auio.uio_procp = p; 2224 auio.uio_resid = SCARG(uap, count); 2225 VOP_LOCK(vp); 2226 loff = auio.uio_offset = fp->f_offset; 2227 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0); 2228 fp->f_offset = auio.uio_offset; 2229 VOP_UNLOCK(vp); 2230 if (error) 2231 return (error); 2232 2233 #ifdef UNION 2234 { 2235 extern int (**union_vnodeop_p)(); 2236 extern struct vnode *union_dircache __P((struct vnode *)); 2237 2238 if ((SCARG(uap, count) == auio.uio_resid) && 2239 (vp->v_op == union_vnodeop_p)) { 2240 struct vnode *lvp; 2241 2242 lvp = union_dircache(vp); 2243 if (lvp != NULLVP) { 2244 struct vattr va; 2245 2246 /* 2247 * If the directory is opaque, 2248 * then don't show lower entries 2249 */ 2250 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2251 if (va.va_flags & OPAQUE) { 2252 vput(lvp); 2253 lvp = NULL; 2254 } 2255 } 2256 2257 if (lvp != NULLVP) { 2258 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2259 VOP_UNLOCK(lvp); 2260 2261 if (error) { 2262 vrele(lvp); 2263 return (error); 2264 } 2265 fp->f_data = (caddr_t) lvp; 2266 fp->f_offset = 0; 2267 error = vn_close(vp, FREAD, fp->f_cred, p); 2268 if (error) 2269 return (error); 2270 vp = lvp; 2271 goto unionread; 2272 } 2273 } 2274 } 2275 #endif /* UNION */ 2276 2277 if ((SCARG(uap, count) == auio.uio_resid) && 2278 (vp->v_flag & VROOT) && 2279 (vp->v_mount->mnt_flag & MNT_UNION)) { 2280 struct vnode *tvp = vp; 2281 vp = vp->v_mount->mnt_vnodecovered; 2282 VREF(vp); 2283 fp->f_data = (caddr_t) vp; 2284 fp->f_offset = 0; 2285 vrele(tvp); 2286 goto unionread; 2287 } 2288 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2289 sizeof(long)); 2290 *retval = SCARG(uap, count) - auio.uio_resid; 2291 return (error); 2292 } 2293 2294 /* 2295 * Set the mode mask for creation of filesystem nodes. 2296 */ 2297 int 2298 umask(p, uap, retval) 2299 struct proc *p; 2300 struct umask_args /* { 2301 syscallarg(int) newmask; 2302 } */ *uap; 2303 register_t *retval; 2304 { 2305 register struct filedesc *fdp; 2306 2307 fdp = p->p_fd; 2308 *retval = fdp->fd_cmask; 2309 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2310 return (0); 2311 } 2312 2313 /* 2314 * Void all references to file by ripping underlying filesystem 2315 * away from vnode. 2316 */ 2317 /* ARGSUSED */ 2318 int 2319 revoke(p, uap, retval) 2320 struct proc *p; 2321 register struct revoke_args /* { 2322 syscallarg(char *) path; 2323 } */ *uap; 2324 register_t *retval; 2325 { 2326 register struct vnode *vp; 2327 struct vattr vattr; 2328 int error; 2329 struct nameidata nd; 2330 2331 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2332 if (error = namei(&nd)) 2333 return (error); 2334 vp = nd.ni_vp; 2335 if (vp->v_type != VCHR && vp->v_type != VBLK) { 2336 error = EINVAL; 2337 goto out; 2338 } 2339 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2340 goto out; 2341 if (p->p_ucred->cr_uid != vattr.va_uid && 2342 (error = suser(p->p_ucred, &p->p_acflag))) 2343 goto out; 2344 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2345 vgoneall(vp); 2346 out: 2347 vrele(vp); 2348 return (error); 2349 } 2350 2351 /* 2352 * Convert a user file descriptor to a kernel file entry. 2353 */ 2354 int 2355 getvnode(fdp, fd, fpp) 2356 struct filedesc *fdp; 2357 struct file **fpp; 2358 int fd; 2359 { 2360 struct file *fp; 2361 2362 if ((u_int)fd >= fdp->fd_nfiles || 2363 (fp = fdp->fd_ofiles[fd]) == NULL) 2364 return (EBADF); 2365 if (fp->f_type != DTYPE_VNODE) 2366 return (EINVAL); 2367 *fpp = fp; 2368 return (0); 2369 } 2370