1 /* $OpenBSD: vfs_syscalls.c,v 1.178 2011/07/25 19:51:24 miod Exp $ */ 2 /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/namei.h> 43 #include <sys/filedesc.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/stat.h> 47 #include <sys/vnode.h> 48 #include <sys/mount.h> 49 #include <sys/proc.h> 50 #include <sys/uio.h> 51 #include <sys/malloc.h> 52 #include <sys/pool.h> 53 #include <sys/dirent.h> 54 #include <sys/dkio.h> 55 #include <sys/disklabel.h> 56 #include <sys/ktrace.h> 57 58 #include <sys/syscallargs.h> 59 60 #include <uvm/uvm_extern.h> 61 #include <sys/sysctl.h> 62 63 extern int suid_clear; 64 int usermount = 0; /* sysctl: by default, users may not mount */ 65 66 static int change_dir(struct nameidata *, struct proc *); 67 68 void checkdirs(struct vnode *); 69 70 int copyout_statfs(struct statfs *, void *, struct proc *); 71 72 int getdirentries_internal(struct proc *, int, char *, int, off_t *, 73 register_t *); 74 75 int doopenat(struct proc *, int, const char *, int, mode_t, register_t *); 76 int domknodat(struct proc *, int, const char *, mode_t, dev_t, register_t *); 77 int domkfifoat(struct proc *, int, const char *, mode_t, register_t *); 78 int dolinkat(struct proc *, int, const char *, int, const char *, int, 79 register_t *); 80 int dosymlinkat(struct proc *, const char *, int, const char *, register_t *); 81 int dounlinkat(struct proc *, int, const char *, int, register_t *); 82 int dofaccessat(struct proc *, int, const char *, int, int, register_t *); 83 int dofstatat(struct proc *, int, const char *, struct stat *, int, 84 register_t *); 85 int doreadlinkat(struct proc *, int, const char *, char *, size_t, 86 register_t *); 87 int dofchmodat(struct proc *, int, const char *, mode_t, int, register_t *); 88 int dofchownat(struct proc *, int, const char *, uid_t, gid_t, int, 89 register_t *); 90 int dorenameat(struct proc *, int, const char *, int, const char *, 91 register_t *); 92 int domkdirat(struct proc *, int, const char *, mode_t, register_t *); 93 int doutimensat(struct proc *, int, const char *, struct timespec [2], 94 int, register_t *); 95 int dovutimens(struct proc *, struct vnode *, struct timespec [2], 96 register_t *); 97 int dofutimens(struct proc *, int, struct timespec [2], register_t *); 98 99 /* 100 * Virtual File System System Calls 101 */ 102 103 /* 104 * Mount a file system. 105 */ 106 /* ARGSUSED */ 107 int 108 sys_mount(struct proc *p, void *v, register_t *retval) 109 { 110 struct sys_mount_args /* { 111 syscallarg(const char *) type; 112 syscallarg(const char *) path; 113 syscallarg(int) flags; 114 syscallarg(void *) data; 115 } */ *uap = v; 116 struct vnode *vp; 117 struct mount *mp; 118 int error, mntflag = 0; 119 char fstypename[MFSNAMELEN]; 120 char fspath[MNAMELEN]; 121 struct vattr va; 122 struct nameidata nd; 123 struct vfsconf *vfsp; 124 int flags = SCARG(uap, flags); 125 126 if (usermount == 0 && (error = suser(p, 0))) 127 return (error); 128 129 /* 130 * Mount points must fit in MNAMELEN, not MAXPATHLEN. 131 */ 132 error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL); 133 if (error) 134 return(error); 135 136 /* 137 * Get vnode to be covered 138 */ 139 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p); 140 if ((error = namei(&nd)) != 0) 141 return (error); 142 vp = nd.ni_vp; 143 if (flags & MNT_UPDATE) { 144 if ((vp->v_flag & VROOT) == 0) { 145 vput(vp); 146 return (EINVAL); 147 } 148 mp = vp->v_mount; 149 vfsp = mp->mnt_vfc; 150 mntflag = mp->mnt_flag; 151 /* 152 * We only allow the filesystem to be reloaded if it 153 * is currently mounted read-only. 154 */ 155 if ((flags & MNT_RELOAD) && 156 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 157 vput(vp); 158 return (EOPNOTSUPP); /* Needs translation */ 159 } 160 161 /* 162 * Only root, or the user that did the original mount is 163 * permitted to update it. 164 */ 165 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 166 (error = suser(p, 0))) { 167 vput(vp); 168 return (error); 169 } 170 /* 171 * Do not allow NFS export by non-root users. Silently 172 * enforce MNT_NOSUID and MNT_NODEV for non-root users, and 173 * inherit MNT_NOEXEC from the mount point. 174 */ 175 if (suser(p, 0) != 0) { 176 if (flags & MNT_EXPORTED) { 177 vput(vp); 178 return (EPERM); 179 } 180 flags |= MNT_NOSUID | MNT_NODEV; 181 if (mntflag & MNT_NOEXEC) 182 flags |= MNT_NOEXEC; 183 } 184 if ((error = vfs_busy(mp, VB_READ|VB_NOWAIT)) != 0) { 185 vput(vp); 186 return (error); 187 } 188 mp->mnt_flag |= flags & (MNT_RELOAD | MNT_UPDATE); 189 goto update; 190 } 191 /* 192 * If the user is not root, ensure that they own the directory 193 * onto which we are attempting to mount. 194 */ 195 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 196 (va.va_uid != p->p_ucred->cr_uid && 197 (error = suser(p, 0)))) { 198 vput(vp); 199 return (error); 200 } 201 /* 202 * Do not allow NFS export by non-root users. Silently 203 * enforce MNT_NOSUID and MNT_NODEV for non-root users, and inherit 204 * MNT_NOEXEC from the mount point. 205 */ 206 if (suser(p, 0) != 0) { 207 if (flags & MNT_EXPORTED) { 208 vput(vp); 209 return (EPERM); 210 } 211 flags |= MNT_NOSUID | MNT_NODEV; 212 if (vp->v_mount->mnt_flag & MNT_NOEXEC) 213 flags |= MNT_NOEXEC; 214 } 215 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) { 216 vput(vp); 217 return (error); 218 } 219 if (vp->v_type != VDIR) { 220 vput(vp); 221 return (ENOTDIR); 222 } 223 error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL); 224 if (error) { 225 vput(vp); 226 return (error); 227 } 228 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { 229 if (!strcmp(vfsp->vfc_name, fstypename)) 230 break; 231 } 232 233 if (vfsp == NULL) { 234 vput(vp); 235 return (EOPNOTSUPP); 236 } 237 238 if (vp->v_mountedhere != NULL) { 239 vput(vp); 240 return (EBUSY); 241 } 242 243 /* 244 * Allocate and initialize the file system. 245 */ 246 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 247 M_MOUNT, M_WAITOK|M_ZERO); 248 (void) vfs_busy(mp, VB_READ|VB_NOWAIT); 249 mp->mnt_op = vfsp->vfc_vfsops; 250 mp->mnt_vfc = vfsp; 251 mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK); 252 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 253 mp->mnt_vnodecovered = vp; 254 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 255 update: 256 /* 257 * Set the mount level flags. 258 */ 259 if (flags & MNT_RDONLY) 260 mp->mnt_flag |= MNT_RDONLY; 261 else if (mp->mnt_flag & MNT_RDONLY) 262 mp->mnt_flag |= MNT_WANTRDWR; 263 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 264 MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | MNT_NOATIME | 265 MNT_FORCE); 266 mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC | 267 MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | 268 MNT_NOATIME | MNT_FORCE); 269 /* 270 * Mount the filesystem. 271 */ 272 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 273 if (!error) { 274 mp->mnt_stat.f_ctime = time_second; 275 } 276 if (mp->mnt_flag & MNT_UPDATE) { 277 vput(vp); 278 if (mp->mnt_flag & MNT_WANTRDWR) 279 mp->mnt_flag &= ~MNT_RDONLY; 280 mp->mnt_flag &=~ 281 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); 282 if (error) 283 mp->mnt_flag = mntflag; 284 285 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 286 if (mp->mnt_syncer == NULL) 287 error = vfs_allocate_syncvnode(mp); 288 } else { 289 if (mp->mnt_syncer != NULL) 290 vgone(mp->mnt_syncer); 291 mp->mnt_syncer = NULL; 292 } 293 294 vfs_unbusy(mp); 295 return (error); 296 } 297 298 vp->v_mountedhere = mp; 299 300 /* 301 * Put the new filesystem on the mount list after root. 302 */ 303 cache_purge(vp); 304 if (!error) { 305 vfsp->vfc_refcount++; 306 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 307 checkdirs(vp); 308 VOP_UNLOCK(vp, 0, p); 309 if ((mp->mnt_flag & MNT_RDONLY) == 0) 310 error = vfs_allocate_syncvnode(mp); 311 vfs_unbusy(mp); 312 (void) VFS_STATFS(mp, &mp->mnt_stat, p); 313 if ((error = VFS_START(mp, 0, p)) != 0) 314 vrele(vp); 315 } else { 316 mp->mnt_vnodecovered->v_mountedhere = NULL; 317 vfs_unbusy(mp); 318 free(mp, M_MOUNT); 319 vput(vp); 320 } 321 return (error); 322 } 323 324 /* 325 * Scan all active processes to see if any of them have a current 326 * or root directory onto which the new filesystem has just been 327 * mounted. If so, replace them with the new mount point. 328 */ 329 void 330 checkdirs(struct vnode *olddp) 331 { 332 struct filedesc *fdp; 333 struct vnode *newdp, *vp; 334 struct proc *p; 335 336 if (olddp->v_usecount == 1) 337 return; 338 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 339 panic("mount: lost mount"); 340 again: 341 LIST_FOREACH(p, &allproc, p_list) { 342 fdp = p->p_fd; 343 if (fdp->fd_cdir == olddp) { 344 vp = fdp->fd_cdir; 345 vref(newdp); 346 fdp->fd_cdir = newdp; 347 if (vrele(vp)) 348 goto again; 349 } 350 if (fdp->fd_rdir == olddp) { 351 vp = fdp->fd_rdir; 352 vref(newdp); 353 fdp->fd_rdir = newdp; 354 if (vrele(vp)) 355 goto again; 356 } 357 } 358 if (rootvnode == olddp) { 359 vrele(rootvnode); 360 vref(newdp); 361 rootvnode = newdp; 362 } 363 vput(newdp); 364 } 365 366 /* 367 * Unmount a file system. 368 * 369 * Note: unmount takes a path to the vnode mounted on as argument, 370 * not special file (as before). 371 */ 372 /* ARGSUSED */ 373 int 374 sys_unmount(struct proc *p, void *v, register_t *retval) 375 { 376 struct sys_unmount_args /* { 377 syscallarg(const char *) path; 378 syscallarg(int) flags; 379 } */ *uap = v; 380 struct vnode *vp; 381 struct mount *mp; 382 int error; 383 struct nameidata nd; 384 385 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 386 SCARG(uap, path), p); 387 if ((error = namei(&nd)) != 0) 388 return (error); 389 vp = nd.ni_vp; 390 mp = vp->v_mount; 391 392 /* 393 * Only root, or the user that did the original mount is 394 * permitted to unmount this filesystem. 395 */ 396 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 397 (error = suser(p, 0))) { 398 vput(vp); 399 return (error); 400 } 401 402 /* 403 * Don't allow unmounting the root file system. 404 */ 405 if (mp->mnt_flag & MNT_ROOTFS) { 406 vput(vp); 407 return (EINVAL); 408 } 409 410 /* 411 * Must be the root of the filesystem 412 */ 413 if ((vp->v_flag & VROOT) == 0) { 414 vput(vp); 415 return (EINVAL); 416 } 417 vput(vp); 418 419 if (vfs_busy(mp, VB_WRITE|VB_WAIT)) 420 return (EBUSY); 421 422 return (dounmount(mp, SCARG(uap, flags), p, vp)); 423 } 424 425 /* 426 * Do the actual file system unmount. 427 */ 428 int 429 dounmount(struct mount *mp, int flags, struct proc *p, struct vnode *olddp) 430 { 431 struct vnode *coveredvp; 432 int error; 433 int hadsyncer = 0; 434 435 mp->mnt_flag &=~ MNT_ASYNC; 436 cache_purgevfs(mp); /* remove cache entries for this file sys */ 437 if (mp->mnt_syncer != NULL) { 438 hadsyncer = 1; 439 vgone(mp->mnt_syncer); 440 mp->mnt_syncer = NULL; 441 } 442 if (((mp->mnt_flag & MNT_RDONLY) || 443 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 444 (flags & MNT_FORCE)) 445 error = VFS_UNMOUNT(mp, flags, p); 446 447 if (error && error != EIO && !(flags & MNT_DOOMED)) { 448 if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer) 449 (void) vfs_allocate_syncvnode(mp); 450 vfs_unbusy(mp); 451 return (error); 452 } 453 454 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 455 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 456 coveredvp->v_mountedhere = NULL; 457 vrele(coveredvp); 458 } 459 460 mp->mnt_vfc->vfc_refcount--; 461 462 if (!LIST_EMPTY(&mp->mnt_vnodelist)) 463 panic("unmount: dangling vnode"); 464 465 vfs_unbusy(mp); 466 free(mp, M_MOUNT); 467 468 return (0); 469 } 470 471 /* 472 * Sync each mounted filesystem. 473 */ 474 #ifdef DEBUG 475 int syncprt = 0; 476 struct ctldebug debug0 = { "syncprt", &syncprt }; 477 #endif 478 479 /* ARGSUSED */ 480 int 481 sys_sync(struct proc *p, void *v, register_t *retval) 482 { 483 struct mount *mp, *nmp; 484 int asyncflag; 485 486 for (mp = CIRCLEQ_LAST(&mountlist); mp != CIRCLEQ_END(&mountlist); 487 mp = nmp) { 488 if (vfs_busy(mp, VB_READ|VB_NOWAIT)) { 489 nmp = CIRCLEQ_PREV(mp, mnt_list); 490 continue; 491 } 492 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 493 asyncflag = mp->mnt_flag & MNT_ASYNC; 494 mp->mnt_flag &= ~MNT_ASYNC; 495 uvm_vnp_sync(mp); 496 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 497 if (asyncflag) 498 mp->mnt_flag |= MNT_ASYNC; 499 } 500 nmp = CIRCLEQ_PREV(mp, mnt_list); 501 vfs_unbusy(mp); 502 } 503 504 return (0); 505 } 506 507 /* 508 * Change filesystem quotas. 509 */ 510 /* ARGSUSED */ 511 int 512 sys_quotactl(struct proc *p, void *v, register_t *retval) 513 { 514 struct sys_quotactl_args /* { 515 syscallarg(const char *) path; 516 syscallarg(int) cmd; 517 syscallarg(int) uid; 518 syscallarg(char *) arg; 519 } */ *uap = v; 520 struct mount *mp; 521 int error; 522 struct nameidata nd; 523 524 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 525 if ((error = namei(&nd)) != 0) 526 return (error); 527 mp = nd.ni_vp->v_mount; 528 vrele(nd.ni_vp); 529 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 530 SCARG(uap, arg), p)); 531 } 532 533 int 534 copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p) 535 { 536 size_t co_sz1 = offsetof(struct statfs, f_fsid); 537 size_t co_off2 = co_sz1 + sizeof(fsid_t); 538 size_t co_sz2 = sizeof(struct statfs) - co_off2; 539 char *s, *d; 540 int error; 541 542 /* Don't let non-root see filesystem id (for NFS security) */ 543 if (suser(p, 0)) { 544 fsid_t fsid; 545 546 s = (char *)sp; 547 d = (char *)uaddr; 548 549 memset(&fsid, 0, sizeof(fsid)); 550 551 if ((error = copyout(s, d, co_sz1)) != 0) 552 return (error); 553 if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0) 554 return (error); 555 return (copyout(s + co_off2, d + co_off2, co_sz2)); 556 } 557 558 return (copyout(sp, uaddr, sizeof(*sp))); 559 } 560 561 /* 562 * Get filesystem statistics. 563 */ 564 /* ARGSUSED */ 565 int 566 sys_statfs(struct proc *p, void *v, register_t *retval) 567 { 568 struct sys_statfs_args /* { 569 syscallarg(const char *) path; 570 syscallarg(struct statfs *) buf; 571 } */ *uap = v; 572 struct mount *mp; 573 struct statfs *sp; 574 int error; 575 struct nameidata nd; 576 577 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 578 if ((error = namei(&nd)) != 0) 579 return (error); 580 mp = nd.ni_vp->v_mount; 581 sp = &mp->mnt_stat; 582 vrele(nd.ni_vp); 583 if ((error = VFS_STATFS(mp, sp, p)) != 0) 584 return (error); 585 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 586 587 return (copyout_statfs(sp, SCARG(uap, buf), p)); 588 } 589 590 /* 591 * Get filesystem statistics. 592 */ 593 /* ARGSUSED */ 594 int 595 sys_fstatfs(struct proc *p, void *v, register_t *retval) 596 { 597 struct sys_fstatfs_args /* { 598 syscallarg(int) fd; 599 syscallarg(struct statfs *) buf; 600 } */ *uap = v; 601 struct file *fp; 602 struct mount *mp; 603 struct statfs *sp; 604 int error; 605 606 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 607 return (error); 608 mp = ((struct vnode *)fp->f_data)->v_mount; 609 if (!mp) { 610 FRELE(fp); 611 return (ENOENT); 612 } 613 sp = &mp->mnt_stat; 614 error = VFS_STATFS(mp, sp, p); 615 FRELE(fp); 616 if (error) 617 return (error); 618 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 619 620 return (copyout_statfs(sp, SCARG(uap, buf), p)); 621 } 622 623 /* 624 * Get statistics on all filesystems. 625 */ 626 int 627 sys_getfsstat(struct proc *p, void *v, register_t *retval) 628 { 629 struct sys_getfsstat_args /* { 630 syscallarg(struct statfs *) buf; 631 syscallarg(size_t) bufsize; 632 syscallarg(int) flags; 633 } */ *uap = v; 634 struct mount *mp, *nmp; 635 struct statfs *sp; 636 struct statfs *sfsp; 637 size_t count, maxcount; 638 int error, flags = SCARG(uap, flags); 639 640 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 641 sfsp = SCARG(uap, buf); 642 count = 0; 643 644 for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist); 645 mp = nmp) { 646 if (vfs_busy(mp, VB_READ|VB_NOWAIT)) { 647 nmp = CIRCLEQ_NEXT(mp, mnt_list); 648 continue; 649 } 650 if (sfsp && count < maxcount) { 651 sp = &mp->mnt_stat; 652 653 /* Refresh stats unless MNT_NOWAIT is specified */ 654 if (flags != MNT_NOWAIT && 655 flags != MNT_LAZY && 656 (flags == MNT_WAIT || 657 flags == 0) && 658 (error = VFS_STATFS(mp, sp, p))) { 659 nmp = CIRCLEQ_NEXT(mp, mnt_list); 660 vfs_unbusy(mp); 661 continue; 662 } 663 664 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 665 #if notyet 666 if (mp->mnt_flag & MNT_SOFTDEP) 667 sp->f_eflags = STATFS_SOFTUPD; 668 #endif 669 error = (copyout_statfs(sp, sfsp, p)); 670 if (error) { 671 vfs_unbusy(mp); 672 return (error); 673 } 674 sfsp++; 675 } 676 count++; 677 nmp = CIRCLEQ_NEXT(mp, mnt_list); 678 vfs_unbusy(mp); 679 } 680 681 if (sfsp && count > maxcount) 682 *retval = maxcount; 683 else 684 *retval = count; 685 686 return (0); 687 } 688 689 /* 690 * Change current working directory to a given file descriptor. 691 */ 692 /* ARGSUSED */ 693 int 694 sys_fchdir(struct proc *p, void *v, register_t *retval) 695 { 696 struct sys_fchdir_args /* { 697 syscallarg(int) fd; 698 } */ *uap = v; 699 struct filedesc *fdp = p->p_fd; 700 struct vnode *vp, *tdp; 701 struct mount *mp; 702 struct file *fp; 703 int error; 704 705 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 706 return (EBADF); 707 vp = (struct vnode *)fp->f_data; 708 if (fp->f_type != DTYPE_VNODE || vp->v_type != VDIR) 709 return (ENOTDIR); 710 vref(vp); 711 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 712 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 713 714 while (!error && (mp = vp->v_mountedhere) != NULL) { 715 if (vfs_busy(mp, VB_READ|VB_WAIT)) 716 continue; 717 error = VFS_ROOT(mp, &tdp); 718 vfs_unbusy(mp); 719 if (error) 720 break; 721 vput(vp); 722 vp = tdp; 723 } 724 if (error) { 725 vput(vp); 726 return (error); 727 } 728 VOP_UNLOCK(vp, 0, p); 729 vrele(fdp->fd_cdir); 730 fdp->fd_cdir = vp; 731 return (0); 732 } 733 734 /* 735 * Change current working directory (``.''). 736 */ 737 /* ARGSUSED */ 738 int 739 sys_chdir(struct proc *p, void *v, register_t *retval) 740 { 741 struct sys_chdir_args /* { 742 syscallarg(const char *) path; 743 } */ *uap = v; 744 struct filedesc *fdp = p->p_fd; 745 int error; 746 struct nameidata nd; 747 748 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 749 SCARG(uap, path), p); 750 if ((error = change_dir(&nd, p)) != 0) 751 return (error); 752 vrele(fdp->fd_cdir); 753 fdp->fd_cdir = nd.ni_vp; 754 return (0); 755 } 756 757 /* 758 * Change notion of root (``/'') directory. 759 */ 760 /* ARGSUSED */ 761 int 762 sys_chroot(struct proc *p, void *v, register_t *retval) 763 { 764 struct sys_chroot_args /* { 765 syscallarg(const char *) path; 766 } */ *uap = v; 767 struct filedesc *fdp = p->p_fd; 768 int error; 769 struct nameidata nd; 770 771 if ((error = suser(p, 0)) != 0) 772 return (error); 773 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 774 SCARG(uap, path), p); 775 if ((error = change_dir(&nd, p)) != 0) 776 return (error); 777 if (fdp->fd_rdir != NULL) { 778 /* 779 * A chroot() done inside a changed root environment does 780 * an automatic chdir to avoid the out-of-tree experience. 781 */ 782 vrele(fdp->fd_rdir); 783 vrele(fdp->fd_cdir); 784 vref(nd.ni_vp); 785 fdp->fd_cdir = nd.ni_vp; 786 } 787 fdp->fd_rdir = nd.ni_vp; 788 return (0); 789 } 790 791 /* 792 * Common routine for chroot and chdir. 793 */ 794 static int 795 change_dir(struct nameidata *ndp, struct proc *p) 796 { 797 struct vnode *vp; 798 int error; 799 800 if ((error = namei(ndp)) != 0) 801 return (error); 802 vp = ndp->ni_vp; 803 if (vp->v_type != VDIR) 804 error = ENOTDIR; 805 else 806 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 807 if (error) 808 vput(vp); 809 else 810 VOP_UNLOCK(vp, 0, p); 811 return (error); 812 } 813 814 /* 815 * Check permissions, allocate an open file structure, 816 * and call the device open routine if any. 817 */ 818 int 819 sys_open(struct proc *p, void *v, register_t *retval) 820 { 821 struct sys_open_args /* { 822 syscallarg(const char *) path; 823 syscallarg(int) flags; 824 syscallarg(mode_t) mode; 825 } */ *uap = v; 826 827 return (doopenat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, flags), 828 SCARG(uap, mode), retval)); 829 } 830 831 int 832 sys_openat(struct proc *p, void *v, register_t *retval) 833 { 834 struct sys_openat_args /* { 835 syscallarg(int) fd; 836 syscallarg(const char *) path; 837 syscallarg(int) flags; 838 syscallarg(mode_t) mode; 839 } */ *uap = v; 840 841 return (doopenat(p, SCARG(uap, fd), SCARG(uap, path), 842 SCARG(uap, flags), SCARG(uap, mode), retval)); 843 } 844 845 int 846 doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode, 847 register_t *retval) 848 { 849 struct filedesc *fdp = p->p_fd; 850 struct file *fp; 851 struct vnode *vp; 852 struct vattr vattr; 853 int flags, cmode; 854 int type, indx, error, localtrunc = 0; 855 struct flock lf; 856 struct nameidata nd; 857 858 fdplock(fdp); 859 860 if ((error = falloc(p, &fp, &indx)) != 0) 861 goto out; 862 863 flags = FFLAGS(oflags); 864 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 865 NDINITAT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fd, path, p); 866 p->p_dupfd = -1; /* XXX check for fdopen */ 867 if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) { 868 localtrunc = 1; 869 flags &= ~O_TRUNC; /* Must do truncate ourselves */ 870 } 871 if ((error = vn_open(&nd, flags, cmode)) != 0) { 872 if ((error == ENODEV || error == ENXIO) && 873 p->p_dupfd >= 0 && /* XXX from fdopen */ 874 (error = 875 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 876 closef(fp, p); 877 *retval = indx; 878 goto out; 879 } 880 if (error == ERESTART) 881 error = EINTR; 882 fdremove(fdp, indx); 883 closef(fp, p); 884 goto out; 885 } 886 p->p_dupfd = 0; 887 vp = nd.ni_vp; 888 fp->f_flag = flags & FMASK; 889 fp->f_type = DTYPE_VNODE; 890 fp->f_ops = &vnops; 891 fp->f_data = vp; 892 if (flags & (O_EXLOCK | O_SHLOCK)) { 893 lf.l_whence = SEEK_SET; 894 lf.l_start = 0; 895 lf.l_len = 0; 896 if (flags & O_EXLOCK) 897 lf.l_type = F_WRLCK; 898 else 899 lf.l_type = F_RDLCK; 900 type = F_FLOCK; 901 if ((flags & FNONBLOCK) == 0) 902 type |= F_WAIT; 903 VOP_UNLOCK(vp, 0, p); 904 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); 905 if (error) { 906 /* closef will vn_close the file for us. */ 907 fdremove(fdp, indx); 908 closef(fp, p); 909 goto out; 910 } 911 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 912 fp->f_flag |= FHASLOCK; 913 } 914 if (localtrunc) { 915 if ((fp->f_flag & FWRITE) == 0) 916 error = EACCES; 917 else if (vp->v_mount->mnt_flag & MNT_RDONLY) 918 error = EROFS; 919 else if (vp->v_type == VDIR) 920 error = EISDIR; 921 else if ((error = vn_writechk(vp)) == 0) { 922 VATTR_NULL(&vattr); 923 vattr.va_size = 0; 924 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 925 } 926 if (error) { 927 VOP_UNLOCK(vp, 0, p); 928 /* closef will close the file for us. */ 929 fdremove(fdp, indx); 930 closef(fp, p); 931 goto out; 932 } 933 } 934 VOP_UNLOCK(vp, 0, p); 935 if (flags & O_CLOEXEC) 936 fdp->fd_ofileflags[indx] |= UF_EXCLOSE; 937 *retval = indx; 938 FILE_SET_MATURE(fp); 939 out: 940 fdpunlock(fdp); 941 return (error); 942 } 943 944 /* 945 * Get file handle system call 946 */ 947 int 948 sys_getfh(struct proc *p, void *v, register_t *retval) 949 { 950 struct sys_getfh_args /* { 951 syscallarg(const char *) fname; 952 syscallarg(fhandle_t *) fhp; 953 } */ *uap = v; 954 struct vnode *vp; 955 fhandle_t fh; 956 int error; 957 struct nameidata nd; 958 959 /* 960 * Must be super user 961 */ 962 error = suser(p, 0); 963 if (error) 964 return (error); 965 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 966 SCARG(uap, fname), p); 967 error = namei(&nd); 968 if (error) 969 return (error); 970 vp = nd.ni_vp; 971 bzero(&fh, sizeof(fh)); 972 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 973 error = VFS_VPTOFH(vp, &fh.fh_fid); 974 vput(vp); 975 if (error) 976 return (error); 977 error = copyout(&fh, SCARG(uap, fhp), sizeof(fh)); 978 return (error); 979 } 980 981 /* 982 * Open a file given a file handle. 983 * 984 * Check permissions, allocate an open file structure, 985 * and call the device open routine if any. 986 */ 987 int 988 sys_fhopen(struct proc *p, void *v, register_t *retval) 989 { 990 struct sys_fhopen_args /* { 991 syscallarg(const fhandle_t *) fhp; 992 syscallarg(int) flags; 993 } */ *uap = v; 994 struct filedesc *fdp = p->p_fd; 995 struct file *fp; 996 struct vnode *vp = NULL; 997 struct mount *mp; 998 struct ucred *cred = p->p_ucred; 999 int flags; 1000 int type, indx, error=0; 1001 struct flock lf; 1002 struct vattr va; 1003 fhandle_t fh; 1004 1005 /* 1006 * Must be super user 1007 */ 1008 if ((error = suser(p, 0))) 1009 return (error); 1010 1011 flags = FFLAGS(SCARG(uap, flags)); 1012 if ((flags & (FREAD | FWRITE)) == 0) 1013 return (EINVAL); 1014 if ((flags & O_CREAT)) 1015 return (EINVAL); 1016 1017 fdplock(fdp); 1018 if ((error = falloc(p, &fp, &indx)) != 0) { 1019 fp = NULL; 1020 goto bad; 1021 } 1022 1023 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1024 goto bad; 1025 1026 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { 1027 error = ESTALE; 1028 goto bad; 1029 } 1030 1031 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) { 1032 vp = NULL; /* most likely unnecessary sanity for bad: */ 1033 goto bad; 1034 } 1035 1036 /* Now do an effective vn_open */ 1037 1038 if (vp->v_type == VSOCK) { 1039 error = EOPNOTSUPP; 1040 goto bad; 1041 } 1042 if (flags & FREAD) { 1043 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) 1044 goto bad; 1045 } 1046 if (flags & (FWRITE | O_TRUNC)) { 1047 if (vp->v_type == VDIR) { 1048 error = EISDIR; 1049 goto bad; 1050 } 1051 if ((error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0 || 1052 (error = vn_writechk(vp)) != 0) 1053 goto bad; 1054 } 1055 if (flags & O_TRUNC) { 1056 VATTR_NULL(&va); 1057 va.va_size = 0; 1058 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) 1059 goto bad; 1060 } 1061 if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) 1062 goto bad; 1063 if (flags & FWRITE) 1064 vp->v_writecount++; 1065 1066 /* done with modified vn_open, now finish what sys_open does. */ 1067 1068 fp->f_flag = flags & FMASK; 1069 fp->f_type = DTYPE_VNODE; 1070 fp->f_ops = &vnops; 1071 fp->f_data = vp; 1072 if (flags & (O_EXLOCK | O_SHLOCK)) { 1073 lf.l_whence = SEEK_SET; 1074 lf.l_start = 0; 1075 lf.l_len = 0; 1076 if (flags & O_EXLOCK) 1077 lf.l_type = F_WRLCK; 1078 else 1079 lf.l_type = F_RDLCK; 1080 type = F_FLOCK; 1081 if ((flags & FNONBLOCK) == 0) 1082 type |= F_WAIT; 1083 VOP_UNLOCK(vp, 0, p); 1084 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); 1085 if (error) { 1086 vp = NULL; /* closef will vn_close the file */ 1087 goto bad; 1088 } 1089 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1090 fp->f_flag |= FHASLOCK; 1091 } 1092 VOP_UNLOCK(vp, 0, p); 1093 *retval = indx; 1094 FILE_SET_MATURE(fp); 1095 1096 fdpunlock(fdp); 1097 return (0); 1098 1099 bad: 1100 if (fp) { 1101 fdremove(fdp, indx); 1102 closef(fp, p); 1103 if (vp != NULL) 1104 vput(vp); 1105 } 1106 fdpunlock(fdp); 1107 return (error); 1108 } 1109 1110 /* ARGSUSED */ 1111 int 1112 sys_fhstat(struct proc *p, void *v, register_t *retval) 1113 { 1114 struct sys_fhstat_args /* { 1115 syscallarg(const fhandle_t *) fhp; 1116 syscallarg(struct stat *) sb; 1117 } */ *uap = v; 1118 struct stat sb; 1119 int error; 1120 fhandle_t fh; 1121 struct mount *mp; 1122 struct vnode *vp; 1123 1124 /* 1125 * Must be super user 1126 */ 1127 if ((error = suser(p, 0))) 1128 return (error); 1129 1130 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1131 return (error); 1132 1133 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1134 return (ESTALE); 1135 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1136 return (error); 1137 error = vn_stat(vp, &sb, p); 1138 vput(vp); 1139 if (error) 1140 return (error); 1141 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 1142 return (error); 1143 } 1144 1145 /* ARGSUSED */ 1146 int 1147 sys_fhstatfs(struct proc *p, void *v, register_t *retval) 1148 { 1149 struct sys_fhstatfs_args /* { 1150 syscallarg(const fhandle_t *) fhp; 1151 syscallarg(struct statfs *) buf; 1152 } */ *uap = v; 1153 struct statfs *sp; 1154 fhandle_t fh; 1155 struct mount *mp; 1156 struct vnode *vp; 1157 int error; 1158 1159 /* 1160 * Must be super user 1161 */ 1162 if ((error = suser(p, 0))) 1163 return (error); 1164 1165 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1166 return (error); 1167 1168 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1169 return (ESTALE); 1170 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1171 return (error); 1172 mp = vp->v_mount; 1173 sp = &mp->mnt_stat; 1174 vput(vp); 1175 if ((error = VFS_STATFS(mp, sp, p)) != 0) 1176 return (error); 1177 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 1178 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 1179 } 1180 1181 /* 1182 * Create a special file. 1183 */ 1184 /* ARGSUSED */ 1185 int 1186 sys_mknod(struct proc *p, void *v, register_t *retval) 1187 { 1188 struct sys_mknod_args /* { 1189 syscallarg(const char *) path; 1190 syscallarg(mode_t) mode; 1191 syscallarg(int) dev; 1192 } */ *uap = v; 1193 1194 return (domknodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 1195 SCARG(uap, dev), retval)); 1196 } 1197 1198 int 1199 sys_mknodat(struct proc *p, void *v, register_t *retval) 1200 { 1201 struct sys_mknodat_args /* { 1202 syscallarg(int) fd; 1203 syscallarg(const char *) path; 1204 syscallarg(mode_t) mode; 1205 syscallarg(dev_t) dev; 1206 } */ *uap = v; 1207 1208 return (domknodat(p, SCARG(uap, fd), SCARG(uap, path), 1209 SCARG(uap, mode), SCARG(uap, dev), retval)); 1210 } 1211 1212 int 1213 domknodat(struct proc *p, int fd, const char *path, mode_t mode, dev_t dev, 1214 register_t *retval) 1215 { 1216 struct vnode *vp; 1217 struct vattr vattr; 1218 int error; 1219 struct nameidata nd; 1220 1221 if ((error = suser(p, 0)) != 0) 1222 return (error); 1223 if (p->p_fd->fd_rdir) 1224 return (EINVAL); 1225 NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, path, p); 1226 if ((error = namei(&nd)) != 0) 1227 return (error); 1228 vp = nd.ni_vp; 1229 if (vp != NULL) 1230 error = EEXIST; 1231 else { 1232 VATTR_NULL(&vattr); 1233 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 1234 vattr.va_rdev = dev; 1235 1236 switch (mode & S_IFMT) { 1237 case S_IFMT: /* used by badsect to flag bad sectors */ 1238 vattr.va_type = VBAD; 1239 break; 1240 case S_IFCHR: 1241 vattr.va_type = VCHR; 1242 break; 1243 case S_IFBLK: 1244 vattr.va_type = VBLK; 1245 break; 1246 default: 1247 error = EINVAL; 1248 break; 1249 } 1250 } 1251 if (!error) { 1252 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1253 } else { 1254 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1255 if (nd.ni_dvp == vp) 1256 vrele(nd.ni_dvp); 1257 else 1258 vput(nd.ni_dvp); 1259 if (vp) 1260 vrele(vp); 1261 } 1262 return (error); 1263 } 1264 1265 /* 1266 * Create a named pipe. 1267 */ 1268 /* ARGSUSED */ 1269 int 1270 sys_mkfifo(struct proc *p, void *v, register_t *retval) 1271 { 1272 struct sys_mkfifo_args /* { 1273 syscallarg(const char *) path; 1274 syscallarg(mode_t) mode; 1275 } */ *uap = v; 1276 1277 return (domkfifoat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 1278 retval)); 1279 } 1280 1281 int 1282 sys_mkfifoat(struct proc *p, void *v, register_t *retval) 1283 { 1284 struct sys_mkfifoat_args /* { 1285 syscallarg(int) fd; 1286 syscallarg(const char *) path; 1287 syscallarg(mode_t) mode; 1288 } */ *uap = v; 1289 1290 return (domkfifoat(p, SCARG(uap, fd), SCARG(uap, path), 1291 SCARG(uap, mode), retval)); 1292 } 1293 1294 int 1295 domkfifoat(struct proc *p, int fd, const char *path, mode_t mode, register_t *retval) 1296 { 1297 #ifndef FIFO 1298 return (EOPNOTSUPP); 1299 #else 1300 struct vattr vattr; 1301 int error; 1302 struct nameidata nd; 1303 1304 NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, path, p); 1305 if ((error = namei(&nd)) != 0) 1306 return (error); 1307 if (nd.ni_vp != NULL) { 1308 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1309 if (nd.ni_dvp == nd.ni_vp) 1310 vrele(nd.ni_dvp); 1311 else 1312 vput(nd.ni_dvp); 1313 vrele(nd.ni_vp); 1314 return (EEXIST); 1315 } 1316 VATTR_NULL(&vattr); 1317 vattr.va_type = VFIFO; 1318 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 1319 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1320 #endif /* FIFO */ 1321 } 1322 1323 /* 1324 * Make a hard file link. 1325 */ 1326 /* ARGSUSED */ 1327 int 1328 sys_link(struct proc *p, void *v, register_t *retval) 1329 { 1330 struct sys_link_args /* { 1331 syscallarg(const char *) path; 1332 syscallarg(const char *) link; 1333 } */ *uap = v; 1334 1335 return (dolinkat(p, AT_FDCWD, SCARG(uap, path), AT_FDCWD, 1336 SCARG(uap, link), AT_SYMLINK_FOLLOW, retval)); 1337 } 1338 1339 int 1340 sys_linkat(struct proc *p, void *v, register_t *retval) 1341 { 1342 struct sys_linkat_args /* { 1343 syscallarg(int) fd1; 1344 syscallarg(const char *) path1; 1345 syscallarg(int) fd2; 1346 syscallarg(const char *) path2; 1347 syscallarg(int) flag; 1348 } */ *uap = v; 1349 1350 return (dolinkat(p, SCARG(uap, fd1), SCARG(uap, path1), 1351 SCARG(uap, fd2), SCARG(uap, path2), SCARG(uap, flag), retval)); 1352 } 1353 1354 int 1355 dolinkat(struct proc *p, int fd1, const char *path1, int fd2, 1356 const char *path2, int flag, register_t *retval) 1357 { 1358 struct vnode *vp; 1359 struct nameidata nd; 1360 int error, follow; 1361 int flags; 1362 1363 if (flag & ~AT_SYMLINK_FOLLOW) 1364 return (EINVAL); 1365 1366 follow = (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : NOFOLLOW; 1367 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd1, path1, p); 1368 if ((error = namei(&nd)) != 0) 1369 return (error); 1370 vp = nd.ni_vp; 1371 1372 flags = LOCKPARENT; 1373 if (vp->v_type == VDIR) { 1374 flags |= STRIPSLASHES; 1375 } 1376 1377 NDINITAT(&nd, CREATE, flags, UIO_USERSPACE, fd2, path2, p); 1378 if ((error = namei(&nd)) != 0) 1379 goto out; 1380 if (nd.ni_vp) { 1381 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1382 if (nd.ni_dvp == nd.ni_vp) 1383 vrele(nd.ni_dvp); 1384 else 1385 vput(nd.ni_dvp); 1386 vrele(nd.ni_vp); 1387 error = EEXIST; 1388 goto out; 1389 } 1390 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1391 out: 1392 vrele(vp); 1393 return (error); 1394 } 1395 1396 /* 1397 * Make a symbolic link. 1398 */ 1399 /* ARGSUSED */ 1400 int 1401 sys_symlink(struct proc *p, void *v, register_t *retval) 1402 { 1403 struct sys_symlink_args /* { 1404 syscallarg(const char *) path; 1405 syscallarg(const char *) link; 1406 } */ *uap = v; 1407 1408 return (dosymlinkat(p, SCARG(uap, path), AT_FDCWD, SCARG(uap, link), 1409 retval)); 1410 } 1411 1412 int 1413 sys_symlinkat(struct proc *p, void *v, register_t *retval) 1414 { 1415 struct sys_symlinkat_args /* { 1416 syscallarg(const char *) path; 1417 syscallarg(int) fd; 1418 syscallarg(const char *) link; 1419 } */ *uap = v; 1420 1421 return (dosymlinkat(p, SCARG(uap, path), SCARG(uap, fd), 1422 SCARG(uap, link), retval)); 1423 } 1424 1425 int 1426 dosymlinkat(struct proc *p, const char *upath, int fd, const char *link, 1427 register_t *retval) 1428 { 1429 struct vattr vattr; 1430 char *path; 1431 int error; 1432 struct nameidata nd; 1433 1434 path = pool_get(&namei_pool, PR_WAITOK); 1435 error = copyinstr(upath, path, MAXPATHLEN, NULL); 1436 if (error) 1437 goto out; 1438 NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, link, p); 1439 if ((error = namei(&nd)) != 0) 1440 goto out; 1441 if (nd.ni_vp) { 1442 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1443 if (nd.ni_dvp == nd.ni_vp) 1444 vrele(nd.ni_dvp); 1445 else 1446 vput(nd.ni_dvp); 1447 vrele(nd.ni_vp); 1448 error = EEXIST; 1449 goto out; 1450 } 1451 VATTR_NULL(&vattr); 1452 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1453 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1454 out: 1455 pool_put(&namei_pool, path); 1456 return (error); 1457 } 1458 1459 /* 1460 * Delete a name from the filesystem. 1461 */ 1462 /* ARGSUSED */ 1463 int 1464 sys_unlink(struct proc *p, void *v, register_t *retval) 1465 { 1466 struct sys_unlink_args /* { 1467 syscallarg(const char *) path; 1468 } */ *uap = v; 1469 1470 return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), 0, retval)); 1471 } 1472 1473 int 1474 sys_unlinkat(struct proc *p, void *v, register_t *retval) 1475 { 1476 struct sys_unlinkat_args /* { 1477 syscallarg(int) fd; 1478 syscallarg(const char *) path; 1479 syscallarg(int) flag; 1480 } */ *uap = v; 1481 1482 return (dounlinkat(p, SCARG(uap, fd), SCARG(uap, path), 1483 SCARG(uap, flag), retval)); 1484 } 1485 1486 int 1487 dounlinkat(struct proc *p, int fd, const char *path, int flag, 1488 register_t *retval) 1489 { 1490 struct vnode *vp; 1491 int error; 1492 struct nameidata nd; 1493 1494 if (flag & ~AT_REMOVEDIR) 1495 return (EINVAL); 1496 1497 NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 1498 fd, path, p); 1499 if ((error = namei(&nd)) != 0) 1500 return (error); 1501 vp = nd.ni_vp; 1502 1503 if (flag & AT_REMOVEDIR) { 1504 if (vp->v_type != VDIR) { 1505 error = ENOTDIR; 1506 goto out; 1507 } 1508 /* 1509 * No rmdir "." please. 1510 */ 1511 if (nd.ni_dvp == vp) { 1512 error = EBUSY; 1513 goto out; 1514 } 1515 } 1516 1517 /* 1518 * The root of a mounted filesystem cannot be deleted. 1519 */ 1520 if (vp->v_flag & VROOT) 1521 error = EBUSY; 1522 out: 1523 if (!error) { 1524 if (flag & AT_REMOVEDIR) { 1525 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1526 } else { 1527 (void)uvm_vnp_uncache(vp); 1528 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1529 } 1530 } else { 1531 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1532 if (nd.ni_dvp == vp) 1533 vrele(nd.ni_dvp); 1534 else 1535 vput(nd.ni_dvp); 1536 vput(vp); 1537 } 1538 return (error); 1539 } 1540 1541 /* 1542 * Reposition read/write file offset. 1543 */ 1544 int 1545 sys_lseek(struct proc *p, void *v, register_t *retval) 1546 { 1547 struct sys_lseek_args /* { 1548 syscallarg(int) fd; 1549 syscallarg(int) pad; 1550 syscallarg(off_t) offset; 1551 syscallarg(int) whence; 1552 } */ *uap = v; 1553 struct ucred *cred = p->p_ucred; 1554 struct filedesc *fdp = p->p_fd; 1555 struct file *fp; 1556 struct vattr vattr; 1557 struct vnode *vp; 1558 off_t offarg, newoff; 1559 int error, special; 1560 1561 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 1562 return (EBADF); 1563 if (fp->f_type != DTYPE_VNODE) 1564 return (ESPIPE); 1565 vp = (struct vnode *)fp->f_data; 1566 if (vp->v_type == VFIFO) 1567 return (ESPIPE); 1568 FREF(fp); 1569 if (vp->v_type == VCHR) 1570 special = 1; 1571 else 1572 special = 0; 1573 offarg = SCARG(uap, offset); 1574 1575 switch (SCARG(uap, whence)) { 1576 case SEEK_CUR: 1577 newoff = fp->f_offset + offarg; 1578 break; 1579 case SEEK_END: 1580 error = VOP_GETATTR(vp, &vattr, cred, p); 1581 if (error) 1582 goto bad; 1583 newoff = offarg + (off_t)vattr.va_size; 1584 break; 1585 case SEEK_SET: 1586 newoff = offarg; 1587 break; 1588 default: 1589 error = EINVAL; 1590 goto bad; 1591 } 1592 if (!special) { 1593 if (newoff < 0) { 1594 error = EINVAL; 1595 goto bad; 1596 } 1597 } 1598 *(off_t *)retval = fp->f_offset = newoff; 1599 fp->f_seek++; 1600 error = 0; 1601 bad: 1602 FRELE(fp); 1603 return (error); 1604 } 1605 1606 /* 1607 * Check access permissions. 1608 */ 1609 int 1610 sys_access(struct proc *p, void *v, register_t *retval) 1611 { 1612 struct sys_access_args /* { 1613 syscallarg(const char *) path; 1614 syscallarg(int) flags; 1615 } */ *uap = v; 1616 1617 return (dofaccessat(p, AT_FDCWD, SCARG(uap, path), 1618 SCARG(uap, flags), 0, retval)); 1619 } 1620 1621 int 1622 sys_faccessat(struct proc *p, void *v, register_t *retval) 1623 { 1624 struct sys_faccessat_args /* { 1625 syscallarg(int) fd; 1626 syscallarg(const char *) path; 1627 syscallarg(int) amode; 1628 syscallarg(int) flag; 1629 } */ *uap = v; 1630 1631 return (dofaccessat(p, SCARG(uap, fd), SCARG(uap, path), 1632 SCARG(uap, amode), SCARG(uap, flag), retval)); 1633 } 1634 1635 int 1636 dofaccessat(struct proc *p, int fd, const char *path, int amode, int flag, 1637 register_t *retval) 1638 { 1639 struct vnode *vp; 1640 int error; 1641 struct nameidata nd; 1642 1643 if (amode & ~(R_OK | W_OK | X_OK)) 1644 return (EINVAL); 1645 if (flag & ~AT_EACCESS) 1646 return (EINVAL); 1647 1648 NDINITAT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p); 1649 if ((error = namei(&nd)) != 0) 1650 return (error); 1651 vp = nd.ni_vp; 1652 1653 /* Flags == 0 means only check for existence. */ 1654 if (amode) { 1655 struct ucred *cred = p->p_ucred; 1656 int vflags = 0; 1657 1658 crhold(cred); 1659 1660 if (!(flag & AT_EACCESS)) { 1661 cred = crcopy(cred); 1662 cred->cr_uid = p->p_cred->p_ruid; 1663 cred->cr_gid = p->p_cred->p_rgid; 1664 } 1665 1666 if (amode & R_OK) 1667 vflags |= VREAD; 1668 if (amode & W_OK) 1669 vflags |= VWRITE; 1670 if (amode & X_OK) 1671 vflags |= VEXEC; 1672 1673 error = VOP_ACCESS(vp, vflags, cred, p); 1674 if (!error && (vflags & VWRITE)) 1675 error = vn_writechk(vp); 1676 1677 crfree(cred); 1678 } 1679 vput(vp); 1680 return (error); 1681 } 1682 1683 /* 1684 * Get file status; this version follows links. 1685 */ 1686 /* ARGSUSED */ 1687 int 1688 sys_stat(struct proc *p, void *v, register_t *retval) 1689 { 1690 struct sys_stat_args /* { 1691 syscallarg(const char *) path; 1692 syscallarg(struct stat *) ub; 1693 } */ *uap = v; 1694 1695 return (dofstatat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, ub), 0, 1696 retval)); 1697 } 1698 1699 int 1700 sys_fstatat(struct proc *p, void *v, register_t *retval) 1701 { 1702 struct sys_fstatat_args /* { 1703 syscallarg(int) fd; 1704 syscallarg(const char *) path; 1705 syscallarg(struct stat *) buf; 1706 syscallarg(int) flag; 1707 } */ *uap = v; 1708 1709 return (dofstatat(p, SCARG(uap, fd), SCARG(uap, path), 1710 SCARG(uap, buf), SCARG(uap, flag), retval)); 1711 } 1712 1713 int 1714 dofstatat(struct proc *p, int fd, const char *path, struct stat *buf, 1715 int flag, register_t *retval) 1716 { 1717 struct stat sb; 1718 int error, follow; 1719 struct nameidata nd; 1720 1721 if (flag & ~AT_SYMLINK_NOFOLLOW) 1722 return (EINVAL); 1723 1724 follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1725 NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p); 1726 if ((error = namei(&nd)) != 0) 1727 return (error); 1728 error = vn_stat(nd.ni_vp, &sb, p); 1729 vput(nd.ni_vp); 1730 if (error) 1731 return (error); 1732 /* Don't let non-root see generation numbers (for NFS security) */ 1733 if (suser(p, 0)) 1734 sb.st_gen = 0; 1735 error = copyout(&sb, buf, sizeof(sb)); 1736 #ifdef KTRACE 1737 if (error == 0 && KTRPOINT(p, KTR_STRUCT)) 1738 ktrstat(p, &sb); 1739 #endif 1740 return (error); 1741 } 1742 1743 /* 1744 * Get file status; this version does not follow links. 1745 */ 1746 /* ARGSUSED */ 1747 int 1748 sys_lstat(struct proc *p, void *v, register_t *retval) 1749 { 1750 struct sys_lstat_args /* { 1751 syscallarg(const char *) path; 1752 syscallarg(struct stat *) ub; 1753 } */ *uap = v; 1754 1755 return (dofstatat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, ub), 1756 AT_SYMLINK_NOFOLLOW, retval)); 1757 } 1758 1759 /* 1760 * Get configurable pathname variables. 1761 */ 1762 /* ARGSUSED */ 1763 int 1764 sys_pathconf(struct proc *p, void *v, register_t *retval) 1765 { 1766 struct sys_pathconf_args /* { 1767 syscallarg(const char *) path; 1768 syscallarg(int) name; 1769 } */ *uap = v; 1770 int error; 1771 struct nameidata nd; 1772 1773 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1774 SCARG(uap, path), p); 1775 if ((error = namei(&nd)) != 0) 1776 return (error); 1777 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 1778 vput(nd.ni_vp); 1779 return (error); 1780 } 1781 1782 /* 1783 * Return target name of a symbolic link. 1784 */ 1785 /* ARGSUSED */ 1786 int 1787 sys_readlink(struct proc *p, void *v, register_t *retval) 1788 { 1789 struct sys_readlink_args /* { 1790 syscallarg(const char *) path; 1791 syscallarg(char *) buf; 1792 syscallarg(size_t) count; 1793 } */ *uap = v; 1794 1795 return (doreadlinkat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, buf), 1796 SCARG(uap, count), retval)); 1797 } 1798 1799 int 1800 sys_readlinkat(struct proc *p, void *v, register_t *retval) 1801 { 1802 struct sys_readlinkat_args /* { 1803 syscallarg(int) fd; 1804 syscallarg(const char *) path; 1805 syscallarg(char *) buf; 1806 syscallarg(size_t) count; 1807 } */ *uap = v; 1808 1809 return (doreadlinkat(p, SCARG(uap, fd), SCARG(uap, path), 1810 SCARG(uap, buf), SCARG(uap, count), retval)); 1811 } 1812 1813 int 1814 doreadlinkat(struct proc *p, int fd, const char *path, char *buf, 1815 size_t count, register_t *retval) 1816 { 1817 struct vnode *vp; 1818 struct iovec aiov; 1819 struct uio auio; 1820 int error; 1821 struct nameidata nd; 1822 1823 NDINITAT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p); 1824 if ((error = namei(&nd)) != 0) 1825 return (error); 1826 vp = nd.ni_vp; 1827 if (vp->v_type != VLNK) 1828 error = EINVAL; 1829 else { 1830 aiov.iov_base = buf; 1831 aiov.iov_len = count; 1832 auio.uio_iov = &aiov; 1833 auio.uio_iovcnt = 1; 1834 auio.uio_offset = 0; 1835 auio.uio_rw = UIO_READ; 1836 auio.uio_segflg = UIO_USERSPACE; 1837 auio.uio_procp = p; 1838 auio.uio_resid = count; 1839 error = VOP_READLINK(vp, &auio, p->p_ucred); 1840 } 1841 vput(vp); 1842 *retval = count - auio.uio_resid; 1843 return (error); 1844 } 1845 1846 /* 1847 * Change flags of a file given a path name. 1848 */ 1849 /* ARGSUSED */ 1850 int 1851 sys_chflags(struct proc *p, void *v, register_t *retval) 1852 { 1853 struct sys_chflags_args /* { 1854 syscallarg(const char *) path; 1855 syscallarg(u_int) flags; 1856 } */ *uap = v; 1857 struct vnode *vp; 1858 struct vattr vattr; 1859 int error; 1860 struct nameidata nd; 1861 u_int flags = SCARG(uap, flags); 1862 1863 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1864 if ((error = namei(&nd)) != 0) 1865 return (error); 1866 vp = nd.ni_vp; 1867 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1868 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1869 error = EROFS; 1870 else if (flags == VNOVAL) 1871 error = EINVAL; 1872 else { 1873 if (suser(p, 0)) { 1874 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 1875 goto out; 1876 if (vattr.va_type == VCHR || vattr.va_type == VBLK) { 1877 error = EINVAL; 1878 goto out; 1879 } 1880 } 1881 VATTR_NULL(&vattr); 1882 vattr.va_flags = flags; 1883 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1884 } 1885 out: 1886 vput(vp); 1887 return (error); 1888 } 1889 1890 /* 1891 * Change flags of a file given a file descriptor. 1892 */ 1893 /* ARGSUSED */ 1894 int 1895 sys_fchflags(struct proc *p, void *v, register_t *retval) 1896 { 1897 struct sys_fchflags_args /* { 1898 syscallarg(int) fd; 1899 syscallarg(u_int) flags; 1900 } */ *uap = v; 1901 struct vattr vattr; 1902 struct vnode *vp; 1903 struct file *fp; 1904 int error; 1905 u_int flags = SCARG(uap, flags); 1906 1907 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 1908 return (error); 1909 vp = (struct vnode *)fp->f_data; 1910 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1911 if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY) 1912 error = EROFS; 1913 else if (flags == VNOVAL) 1914 error = EINVAL; 1915 else { 1916 if (suser(p, 0)) { 1917 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 1918 != 0) 1919 goto out; 1920 if (vattr.va_type == VCHR || vattr.va_type == VBLK) { 1921 error = EINVAL; 1922 goto out; 1923 } 1924 } 1925 VATTR_NULL(&vattr); 1926 vattr.va_flags = flags; 1927 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1928 } 1929 out: 1930 VOP_UNLOCK(vp, 0, p); 1931 FRELE(fp); 1932 return (error); 1933 } 1934 1935 /* 1936 * Change mode of a file given path name. 1937 */ 1938 /* ARGSUSED */ 1939 int 1940 sys_chmod(struct proc *p, void *v, register_t *retval) 1941 { 1942 struct sys_chmod_args /* { 1943 syscallarg(const char *) path; 1944 syscallarg(mode_t) mode; 1945 } */ *uap = v; 1946 1947 return (dofchmodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 1948 0, retval)); 1949 } 1950 1951 int 1952 sys_fchmodat(struct proc *p, void *v, register_t *retval) 1953 { 1954 struct sys_fchmodat_args /* { 1955 syscallarg(int) fd; 1956 syscallarg(const char *) path; 1957 syscallarg(mode_t) mode; 1958 syscallarg(int) flag; 1959 } */ *uap = v; 1960 1961 return (dofchmodat(p, SCARG(uap, fd), SCARG(uap, path), 1962 SCARG(uap, mode), SCARG(uap, flag), retval)); 1963 } 1964 1965 int 1966 dofchmodat(struct proc *p, int fd, const char *path, mode_t mode, int flag, 1967 register_t *retval) 1968 { 1969 struct vnode *vp; 1970 struct vattr vattr; 1971 int error, follow; 1972 struct nameidata nd; 1973 1974 if (mode & ~(S_IFMT | ALLPERMS)) 1975 return (EINVAL); 1976 if (flag & ~AT_SYMLINK_NOFOLLOW) 1977 return (EINVAL); 1978 1979 follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1980 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); 1981 if ((error = namei(&nd)) != 0) 1982 return (error); 1983 vp = nd.ni_vp; 1984 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1985 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1986 error = EROFS; 1987 else { 1988 VATTR_NULL(&vattr); 1989 vattr.va_mode = mode & ALLPERMS; 1990 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1991 } 1992 vput(vp); 1993 return (error); 1994 } 1995 1996 /* 1997 * Change mode of a file given a file descriptor. 1998 */ 1999 /* ARGSUSED */ 2000 int 2001 sys_fchmod(struct proc *p, void *v, register_t *retval) 2002 { 2003 struct sys_fchmod_args /* { 2004 syscallarg(int) fd; 2005 syscallarg(mode_t) mode; 2006 } */ *uap = v; 2007 struct vattr vattr; 2008 struct vnode *vp; 2009 struct file *fp; 2010 int error; 2011 2012 if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS)) 2013 return (EINVAL); 2014 2015 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2016 return (error); 2017 vp = (struct vnode *)fp->f_data; 2018 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2019 if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY) 2020 error = EROFS; 2021 else { 2022 VATTR_NULL(&vattr); 2023 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 2024 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2025 } 2026 VOP_UNLOCK(vp, 0, p); 2027 FRELE(fp); 2028 return (error); 2029 } 2030 2031 /* 2032 * Set ownership given a path name. 2033 */ 2034 /* ARGSUSED */ 2035 int 2036 sys_chown(struct proc *p, void *v, register_t *retval) 2037 { 2038 struct sys_chown_args /* { 2039 syscallarg(const char *) path; 2040 syscallarg(uid_t) uid; 2041 syscallarg(gid_t) gid; 2042 } */ *uap = v; 2043 2044 return (dofchownat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, uid), 2045 SCARG(uap, gid), 0, retval)); 2046 } 2047 2048 int 2049 sys_fchownat(struct proc *p, void *v, register_t *retval) 2050 { 2051 struct sys_fchownat_args /* { 2052 syscallarg(int) fd; 2053 syscallarg(const char *) path; 2054 syscallarg(uid_t) uid; 2055 syscallarg(gid_t) gid; 2056 syscallarg(int) flag; 2057 } */ *uap = v; 2058 2059 return (dofchownat(p, SCARG(uap, fd), SCARG(uap, path), 2060 SCARG(uap, uid), SCARG(uap, gid), SCARG(uap, flag), retval)); 2061 } 2062 2063 int 2064 dofchownat(struct proc *p, int fd, const char *path, uid_t uid, gid_t gid, 2065 int flag, register_t *retval) 2066 { 2067 struct vnode *vp; 2068 struct vattr vattr; 2069 int error, follow; 2070 struct nameidata nd; 2071 mode_t mode; 2072 2073 if (flag & ~AT_SYMLINK_NOFOLLOW) 2074 return (EINVAL); 2075 2076 follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 2077 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); 2078 if ((error = namei(&nd)) != 0) 2079 return (error); 2080 vp = nd.ni_vp; 2081 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2082 if (vp->v_mount->mnt_flag & MNT_RDONLY) 2083 error = EROFS; 2084 else { 2085 if ((uid != -1 || gid != -1) && 2086 (suser(p, 0) || suid_clear)) { 2087 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 2088 if (error) 2089 goto out; 2090 mode = vattr.va_mode & ~(VSUID | VSGID); 2091 if (mode == vattr.va_mode) 2092 mode = VNOVAL; 2093 } 2094 else 2095 mode = VNOVAL; 2096 VATTR_NULL(&vattr); 2097 vattr.va_uid = uid; 2098 vattr.va_gid = gid; 2099 vattr.va_mode = mode; 2100 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2101 } 2102 out: 2103 vput(vp); 2104 return (error); 2105 } 2106 2107 /* 2108 * Set ownership given a path name, without following links. 2109 */ 2110 /* ARGSUSED */ 2111 int 2112 sys_lchown(struct proc *p, void *v, register_t *retval) 2113 { 2114 struct sys_lchown_args /* { 2115 syscallarg(const char *) path; 2116 syscallarg(uid_t) uid; 2117 syscallarg(gid_t) gid; 2118 } */ *uap = v; 2119 struct vnode *vp; 2120 struct vattr vattr; 2121 int error; 2122 struct nameidata nd; 2123 mode_t mode; 2124 uid_t uid = SCARG(uap, uid); 2125 gid_t gid = SCARG(uap, gid); 2126 2127 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2128 if ((error = namei(&nd)) != 0) 2129 return (error); 2130 vp = nd.ni_vp; 2131 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2132 if (vp->v_mount->mnt_flag & MNT_RDONLY) 2133 error = EROFS; 2134 else { 2135 if ((uid != -1 || gid != -1) && 2136 (suser(p, 0) || suid_clear)) { 2137 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 2138 if (error) 2139 goto out; 2140 mode = vattr.va_mode & ~(VSUID | VSGID); 2141 if (mode == vattr.va_mode) 2142 mode = VNOVAL; 2143 } 2144 else 2145 mode = VNOVAL; 2146 VATTR_NULL(&vattr); 2147 vattr.va_uid = uid; 2148 vattr.va_gid = gid; 2149 vattr.va_mode = mode; 2150 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2151 } 2152 out: 2153 vput(vp); 2154 return (error); 2155 } 2156 2157 /* 2158 * Set ownership given a file descriptor. 2159 */ 2160 /* ARGSUSED */ 2161 int 2162 sys_fchown(struct proc *p, void *v, register_t *retval) 2163 { 2164 struct sys_fchown_args /* { 2165 syscallarg(int) fd; 2166 syscallarg(uid_t) uid; 2167 syscallarg(gid_t) gid; 2168 } */ *uap = v; 2169 struct vnode *vp; 2170 struct vattr vattr; 2171 int error; 2172 struct file *fp; 2173 mode_t mode; 2174 uid_t uid = SCARG(uap, uid); 2175 gid_t gid = SCARG(uap, gid); 2176 2177 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2178 return (error); 2179 vp = (struct vnode *)fp->f_data; 2180 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2181 if (vp->v_mount->mnt_flag & MNT_RDONLY) 2182 error = EROFS; 2183 else { 2184 if ((uid != -1 || gid != -1) && 2185 (suser(p, 0) || suid_clear)) { 2186 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 2187 if (error) 2188 goto out; 2189 mode = vattr.va_mode & ~(VSUID | VSGID); 2190 if (mode == vattr.va_mode) 2191 mode = VNOVAL; 2192 } else 2193 mode = VNOVAL; 2194 VATTR_NULL(&vattr); 2195 vattr.va_uid = uid; 2196 vattr.va_gid = gid; 2197 vattr.va_mode = mode; 2198 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2199 } 2200 out: 2201 VOP_UNLOCK(vp, 0, p); 2202 FRELE(fp); 2203 return (error); 2204 } 2205 2206 /* 2207 * Set the access and modification times given a path name. 2208 */ 2209 /* ARGSUSED */ 2210 int 2211 sys_utimes(struct proc *p, void *v, register_t *retval) 2212 { 2213 struct sys_utimes_args /* { 2214 syscallarg(const char *) path; 2215 syscallarg(const struct timeval *) tptr; 2216 } */ *uap = v; 2217 2218 struct timespec ts[2]; 2219 struct timeval tv[2]; 2220 const struct timeval *tvp; 2221 int error; 2222 2223 tvp = SCARG(uap, tptr); 2224 if (tvp != NULL) { 2225 error = copyin(tvp, tv, sizeof(tv)); 2226 if (error) 2227 return (error); 2228 TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0]); 2229 TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1]); 2230 } else 2231 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; 2232 2233 return (doutimensat(p, AT_FDCWD, SCARG(uap, path), ts, 0, retval)); 2234 } 2235 2236 int 2237 sys_utimensat(struct proc *p, void *v, register_t *retval) 2238 { 2239 struct sys_utimensat_args /* { 2240 syscallarg(int) fd; 2241 syscallarg(const char *) path; 2242 syscallarg(const struct timespec *) times; 2243 syscallarg(int) flag; 2244 } */ *uap = v; 2245 2246 struct timespec ts[2]; 2247 const struct timespec *tsp; 2248 int error; 2249 2250 tsp = SCARG(uap, times); 2251 if (tsp != NULL) { 2252 error = copyin(tsp, ts, sizeof(ts)); 2253 if (error) 2254 return (error); 2255 } else 2256 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; 2257 2258 return (doutimensat(p, SCARG(uap, fd), SCARG(uap, path), ts, 2259 SCARG(uap, flag), retval)); 2260 } 2261 2262 int 2263 doutimensat(struct proc *p, int fd, const char *path, 2264 struct timespec ts[2], int flag, register_t *retval) 2265 { 2266 struct vnode *vp; 2267 int error, follow; 2268 struct nameidata nd; 2269 2270 if (flag & ~AT_SYMLINK_NOFOLLOW) 2271 return (EINVAL); 2272 2273 follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 2274 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p); 2275 if ((error = namei(&nd)) != 0) 2276 return (error); 2277 vp = nd.ni_vp; 2278 2279 return (dovutimens(p, vp, ts, retval)); 2280 } 2281 2282 int 2283 dovutimens(struct proc *p, struct vnode *vp, struct timespec ts[2], 2284 register_t *retval) 2285 { 2286 struct vattr vattr; 2287 struct timespec now; 2288 int error; 2289 2290 VATTR_NULL(&vattr); 2291 if (ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) { 2292 if (ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW) 2293 vattr.va_vaflags |= VA_UTIMES_NULL; 2294 2295 getnanotime(&now); 2296 if (ts[0].tv_nsec == UTIME_NOW) 2297 ts[0] = now; 2298 if (ts[1].tv_nsec == UTIME_NOW) 2299 ts[1] = now; 2300 } 2301 2302 /* 2303 * XXX: Ideally the filesystem code would check tv_nsec == 2304 * UTIME_OMIT instead of tv_sec == VNOVAL, but until then we 2305 * need to fudge tv_sec if it happens to equal VNOVAL. 2306 */ 2307 if (ts[0].tv_nsec == UTIME_OMIT) 2308 ts[0].tv_sec = VNOVAL; 2309 else if (ts[0].tv_sec == VNOVAL) 2310 ts[0].tv_sec = VNOVAL - 1; 2311 2312 if (ts[1].tv_nsec == UTIME_OMIT) 2313 ts[1].tv_sec = VNOVAL; 2314 else if (ts[1].tv_sec == VNOVAL) 2315 ts[1].tv_sec = VNOVAL - 1; 2316 2317 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2318 if (vp->v_mount->mnt_flag & MNT_RDONLY) 2319 error = EROFS; 2320 else { 2321 vattr.va_atime = ts[0]; 2322 vattr.va_mtime = ts[1]; 2323 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2324 } 2325 vput(vp); 2326 return (error); 2327 } 2328 2329 /* 2330 * Set the access and modification times given a file descriptor. 2331 */ 2332 /* ARGSUSED */ 2333 int 2334 sys_futimes(struct proc *p, void *v, register_t *retval) 2335 { 2336 struct sys_futimes_args /* { 2337 syscallarg(int) fd; 2338 syscallarg(const struct timeval *) tptr; 2339 } */ *uap = v; 2340 struct timeval tv[2]; 2341 struct timespec ts[2]; 2342 const struct timeval *tvp; 2343 int error; 2344 2345 tvp = SCARG(uap, tptr); 2346 if (tvp != NULL) { 2347 error = copyin(tvp, tv, sizeof(tv)); 2348 if (error) 2349 return (error); 2350 TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0]); 2351 TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1]); 2352 } else 2353 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; 2354 2355 return (dofutimens(p, SCARG(uap, fd), ts, retval)); 2356 } 2357 2358 int 2359 sys_futimens(struct proc *p, void *v, register_t *retval) 2360 { 2361 struct sys_futimens_args /* { 2362 syscallarg(int) fd; 2363 syscallarg(const struct timespec *) times; 2364 } */ *uap = v; 2365 struct timespec ts[2]; 2366 const struct timespec *tsp; 2367 int error; 2368 2369 tsp = SCARG(uap, times); 2370 if (tsp != NULL) { 2371 error = copyin(tsp, ts, sizeof(ts)); 2372 if (error) 2373 return (error); 2374 } else 2375 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; 2376 2377 return (dofutimens(p, SCARG(uap, fd), ts, retval)); 2378 } 2379 2380 int 2381 dofutimens(struct proc *p, int fd, struct timespec ts[2], register_t *retval) 2382 { 2383 struct file *fp; 2384 struct vnode *vp; 2385 int error; 2386 2387 if ((error = getvnode(p->p_fd, fd, &fp)) != 0) 2388 return (error); 2389 vp = (struct vnode *)fp->f_data; 2390 vref(vp); 2391 FRELE(fp); 2392 2393 return (dovutimens(p, vp, ts, retval)); 2394 } 2395 2396 /* 2397 * Truncate a file given its path name. 2398 */ 2399 /* ARGSUSED */ 2400 int 2401 sys_truncate(struct proc *p, void *v, register_t *retval) 2402 { 2403 struct sys_truncate_args /* { 2404 syscallarg(const char *) path; 2405 syscallarg(int) pad; 2406 syscallarg(off_t) length; 2407 } */ *uap = v; 2408 struct vnode *vp; 2409 struct vattr vattr; 2410 int error; 2411 struct nameidata nd; 2412 2413 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2414 if ((error = namei(&nd)) != 0) 2415 return (error); 2416 vp = nd.ni_vp; 2417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2418 if (vp->v_type == VDIR) 2419 error = EISDIR; 2420 else if ((error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0 && 2421 (error = vn_writechk(vp)) == 0) { 2422 VATTR_NULL(&vattr); 2423 vattr.va_size = SCARG(uap, length); 2424 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2425 } 2426 vput(vp); 2427 return (error); 2428 } 2429 2430 /* 2431 * Truncate a file given a file descriptor. 2432 */ 2433 /* ARGSUSED */ 2434 int 2435 sys_ftruncate(struct proc *p, void *v, register_t *retval) 2436 { 2437 struct sys_ftruncate_args /* { 2438 syscallarg(int) fd; 2439 syscallarg(int) pad; 2440 syscallarg(off_t) length; 2441 } */ *uap = v; 2442 struct vattr vattr; 2443 struct vnode *vp; 2444 struct file *fp; 2445 off_t len; 2446 int error; 2447 2448 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2449 return (error); 2450 len = SCARG(uap, length); 2451 if ((fp->f_flag & FWRITE) == 0 || len < 0) { 2452 error = EINVAL; 2453 goto bad; 2454 } 2455 vp = (struct vnode *)fp->f_data; 2456 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2457 if (vp->v_type == VDIR) 2458 error = EISDIR; 2459 else if ((error = vn_writechk(vp)) == 0) { 2460 VATTR_NULL(&vattr); 2461 vattr.va_size = len; 2462 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2463 } 2464 VOP_UNLOCK(vp, 0, p); 2465 bad: 2466 FRELE(fp); 2467 return (error); 2468 } 2469 2470 /* 2471 * Sync an open file. 2472 */ 2473 /* ARGSUSED */ 2474 int 2475 sys_fsync(struct proc *p, void *v, register_t *retval) 2476 { 2477 struct sys_fsync_args /* { 2478 syscallarg(int) fd; 2479 } */ *uap = v; 2480 struct vnode *vp; 2481 struct file *fp; 2482 int error; 2483 2484 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2485 return (error); 2486 vp = (struct vnode *)fp->f_data; 2487 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2488 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 2489 #ifdef FFS_SOFTUPDATES 2490 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 2491 error = softdep_fsync(vp); 2492 #endif 2493 2494 VOP_UNLOCK(vp, 0, p); 2495 FRELE(fp); 2496 return (error); 2497 } 2498 2499 /* 2500 * Rename files. Source and destination must either both be directories, 2501 * or both not be directories. If target is a directory, it must be empty. 2502 */ 2503 /* ARGSUSED */ 2504 int 2505 sys_rename(struct proc *p, void *v, register_t *retval) 2506 { 2507 struct sys_rename_args /* { 2508 syscallarg(const char *) from; 2509 syscallarg(const char *) to; 2510 } */ *uap = v; 2511 2512 return (dorenameat(p, AT_FDCWD, SCARG(uap, from), AT_FDCWD, 2513 SCARG(uap, to), retval)); 2514 } 2515 2516 int 2517 sys_renameat(struct proc *p, void *v, register_t *retval) 2518 { 2519 struct sys_renameat_args /* { 2520 syscallarg(int) fromfd; 2521 syscallarg(const char *) from; 2522 syscallarg(int) tofd; 2523 syscallarg(const char *) to; 2524 } */ *uap = v; 2525 2526 return (dorenameat(p, SCARG(uap, fromfd), SCARG(uap, from), 2527 SCARG(uap, tofd), SCARG(uap, to), retval)); 2528 } 2529 2530 int 2531 dorenameat(struct proc *p, int fromfd, const char *from, int tofd, 2532 const char *to, register_t *retval) 2533 { 2534 struct vnode *tvp, *fvp, *tdvp; 2535 struct nameidata fromnd, tond; 2536 int error; 2537 int flags; 2538 2539 NDINITAT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2540 fromfd, from, p); 2541 if ((error = namei(&fromnd)) != 0) 2542 return (error); 2543 fvp = fromnd.ni_vp; 2544 2545 flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; 2546 /* 2547 * rename("foo/", "bar/"); is OK 2548 */ 2549 if (fvp->v_type == VDIR) 2550 flags |= STRIPSLASHES; 2551 2552 NDINITAT(&tond, RENAME, flags, UIO_USERSPACE, tofd, to, p); 2553 if ((error = namei(&tond)) != 0) { 2554 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2555 vrele(fromnd.ni_dvp); 2556 vrele(fvp); 2557 goto out1; 2558 } 2559 tdvp = tond.ni_dvp; 2560 tvp = tond.ni_vp; 2561 if (tvp != NULL) { 2562 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2563 error = ENOTDIR; 2564 goto out; 2565 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2566 error = EISDIR; 2567 goto out; 2568 } 2569 } 2570 if (fvp == tdvp) 2571 error = EINVAL; 2572 /* 2573 * If source is the same as the destination (that is the 2574 * same inode number) 2575 */ 2576 if (fvp == tvp) 2577 error = -1; 2578 out: 2579 if (!error) { 2580 if (tvp) { 2581 (void)uvm_vnp_uncache(tvp); 2582 } 2583 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2584 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2585 } else { 2586 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2587 if (tdvp == tvp) 2588 vrele(tdvp); 2589 else 2590 vput(tdvp); 2591 if (tvp) 2592 vput(tvp); 2593 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2594 vrele(fromnd.ni_dvp); 2595 vrele(fvp); 2596 } 2597 vrele(tond.ni_startdir); 2598 pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf); 2599 out1: 2600 if (fromnd.ni_startdir) 2601 vrele(fromnd.ni_startdir); 2602 pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf); 2603 if (error == -1) 2604 return (0); 2605 return (error); 2606 } 2607 2608 /* 2609 * Make a directory file. 2610 */ 2611 /* ARGSUSED */ 2612 int 2613 sys_mkdir(struct proc *p, void *v, register_t *retval) 2614 { 2615 struct sys_mkdir_args /* { 2616 syscallarg(const char *) path; 2617 syscallarg(mode_t) mode; 2618 } */ *uap = v; 2619 2620 return (domkdirat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 2621 retval)); 2622 } 2623 2624 int 2625 sys_mkdirat(struct proc *p, void *v, register_t *retval) 2626 { 2627 struct sys_mkdirat_args /* { 2628 syscallarg(int) fd; 2629 syscallarg(const char *) path; 2630 syscallarg(mode_t) mode; 2631 } */ *uap = v; 2632 2633 return (domkdirat(p, SCARG(uap, fd), SCARG(uap, path), 2634 SCARG(uap, mode), retval)); 2635 } 2636 2637 int 2638 domkdirat(struct proc *p, int fd, const char *path, mode_t mode, 2639 register_t *retval) 2640 { 2641 struct vnode *vp; 2642 struct vattr vattr; 2643 int error; 2644 struct nameidata nd; 2645 2646 NDINITAT(&nd, CREATE, LOCKPARENT | STRIPSLASHES, UIO_USERSPACE, 2647 fd, path, p); 2648 if ((error = namei(&nd)) != 0) 2649 return (error); 2650 vp = nd.ni_vp; 2651 if (vp != NULL) { 2652 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2653 if (nd.ni_dvp == vp) 2654 vrele(nd.ni_dvp); 2655 else 2656 vput(nd.ni_dvp); 2657 vrele(vp); 2658 return (EEXIST); 2659 } 2660 VATTR_NULL(&vattr); 2661 vattr.va_type = VDIR; 2662 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2663 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2664 if (!error) 2665 vput(nd.ni_vp); 2666 return (error); 2667 } 2668 2669 /* 2670 * Remove a directory file. 2671 */ 2672 /* ARGSUSED */ 2673 int 2674 sys_rmdir(struct proc *p, void *v, register_t *retval) 2675 { 2676 struct sys_rmdir_args /* { 2677 syscallarg(const char *) path; 2678 } */ *uap = v; 2679 2680 return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), AT_REMOVEDIR, 2681 retval)); 2682 } 2683 2684 /* 2685 * Read a block of directory entries in a file system independent format. 2686 */ 2687 int 2688 getdirentries_internal(struct proc *p, int fd, char *buf, int count, 2689 off_t *basep, register_t *retval) 2690 { 2691 struct vnode *vp; 2692 struct file *fp; 2693 struct uio auio; 2694 struct iovec aiov; 2695 int error, eofflag; 2696 2697 if (count < 0) 2698 return EINVAL; 2699 if ((error = getvnode(p->p_fd, fd, &fp)) != 0) 2700 return (error); 2701 if ((fp->f_flag & FREAD) == 0) { 2702 error = EBADF; 2703 goto bad; 2704 } 2705 if (fp->f_offset < 0) { 2706 error = EINVAL; 2707 goto bad; 2708 } 2709 vp = (struct vnode *)fp->f_data; 2710 if (vp->v_type != VDIR) { 2711 error = EINVAL; 2712 goto bad; 2713 } 2714 aiov.iov_base = buf; 2715 aiov.iov_len = count; 2716 auio.uio_iov = &aiov; 2717 auio.uio_iovcnt = 1; 2718 auio.uio_rw = UIO_READ; 2719 auio.uio_segflg = UIO_USERSPACE; 2720 auio.uio_procp = p; 2721 auio.uio_resid = count; 2722 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2723 *basep = auio.uio_offset = fp->f_offset; 2724 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0); 2725 fp->f_offset = auio.uio_offset; 2726 VOP_UNLOCK(vp, 0, p); 2727 if (error) 2728 goto bad; 2729 *retval = count - auio.uio_resid; 2730 bad: 2731 FRELE(fp); 2732 return (error); 2733 } 2734 2735 int 2736 sys_getdirentries(struct proc *p, void *v, register_t *retval) 2737 { 2738 struct sys_getdirentries_args /* { 2739 syscallarg(int) fd; 2740 syscallarg(char *) buf; 2741 syscallarg(int) count; 2742 syscallarg(off_t *) basep; 2743 } */ *uap = v; 2744 int error; 2745 off_t off; 2746 2747 error = getdirentries_internal(p, SCARG(uap, fd), SCARG(uap, buf), 2748 SCARG(uap, count), &off, retval); 2749 if (!error) 2750 error = copyout(&off, SCARG(uap, basep), sizeof(off_t)); 2751 return error; 2752 } 2753 2754 #ifdef COMPAT_O48 2755 int 2756 compat_o48_sys_getdirentries(struct proc *p, void *v, register_t *retval) 2757 { 2758 struct compat_o48_sys_getdirentries_args /* { 2759 syscallarg(int) fd; 2760 syscallarg(char *) buf; 2761 syscallarg(int) count; 2762 syscallarg(long *) basep; 2763 } */ *uap = v; 2764 int error; 2765 off_t off; 2766 2767 error = getdirentries_internal(p, SCARG(uap, fd), SCARG(uap, buf), 2768 SCARG(uap, count), &off, retval); 2769 if (!error) { 2770 long loff = (long)off; 2771 error = copyout(&loff, SCARG(uap, basep), sizeof(long)); 2772 } 2773 return error; 2774 } 2775 #endif 2776 2777 /* 2778 * Set the mode mask for creation of filesystem nodes. 2779 */ 2780 int 2781 sys_umask(struct proc *p, void *v, register_t *retval) 2782 { 2783 struct sys_umask_args /* { 2784 syscallarg(mode_t) newmask; 2785 } */ *uap = v; 2786 struct filedesc *fdp; 2787 2788 fdp = p->p_fd; 2789 *retval = fdp->fd_cmask; 2790 fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS; 2791 return (0); 2792 } 2793 2794 /* 2795 * Void all references to file by ripping underlying filesystem 2796 * away from vnode. 2797 */ 2798 /* ARGSUSED */ 2799 int 2800 sys_revoke(struct proc *p, void *v, register_t *retval) 2801 { 2802 struct sys_revoke_args /* { 2803 syscallarg(const char *) path; 2804 } */ *uap = v; 2805 struct vnode *vp; 2806 struct vattr vattr; 2807 int error; 2808 struct nameidata nd; 2809 2810 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2811 if ((error = namei(&nd)) != 0) 2812 return (error); 2813 vp = nd.ni_vp; 2814 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 2815 goto out; 2816 if (p->p_ucred->cr_uid != vattr.va_uid && 2817 (error = suser(p, 0))) 2818 goto out; 2819 if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED))) 2820 VOP_REVOKE(vp, REVOKEALL); 2821 out: 2822 vrele(vp); 2823 return (error); 2824 } 2825 2826 /* 2827 * Convert a user file descriptor to a kernel file entry. 2828 * 2829 * On return *fpp is FREF:ed. 2830 */ 2831 int 2832 getvnode(struct filedesc *fdp, int fd, struct file **fpp) 2833 { 2834 struct file *fp; 2835 struct vnode *vp; 2836 2837 if ((fp = fd_getfile(fdp, fd)) == NULL) 2838 return (EBADF); 2839 2840 if (fp->f_type != DTYPE_VNODE) 2841 return (EINVAL); 2842 2843 vp = (struct vnode *)fp->f_data; 2844 if (vp->v_type == VBAD) 2845 return (EBADF); 2846 2847 FREF(fp); 2848 *fpp = fp; 2849 2850 return (0); 2851 } 2852 2853 /* 2854 * Positional read system call. 2855 */ 2856 int 2857 sys_pread(struct proc *p, void *v, register_t *retval) 2858 { 2859 struct sys_pread_args /* { 2860 syscallarg(int) fd; 2861 syscallarg(void *) buf; 2862 syscallarg(size_t) nbyte; 2863 syscallarg(int) pad; 2864 syscallarg(off_t) offset; 2865 } */ *uap = v; 2866 struct iovec iov; 2867 struct filedesc *fdp = p->p_fd; 2868 struct file *fp; 2869 struct vnode *vp; 2870 off_t offset; 2871 int fd = SCARG(uap, fd); 2872 2873 if ((fp = fd_getfile(fdp, fd)) == NULL) 2874 return (EBADF); 2875 if ((fp->f_flag & FREAD) == 0) 2876 return (EBADF); 2877 2878 vp = (struct vnode *)fp->f_data; 2879 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2880 return (ESPIPE); 2881 } 2882 2883 iov.iov_base = SCARG(uap, buf); 2884 iov.iov_len = SCARG(uap, nbyte); 2885 2886 offset = SCARG(uap, offset); 2887 2888 FREF(fp); 2889 2890 /* dofilereadv() will FRELE the descriptor for us */ 2891 return (dofilereadv(p, fd, fp, &iov, 1, 0, &offset, retval)); 2892 } 2893 2894 /* 2895 * Positional scatter read system call. 2896 */ 2897 int 2898 sys_preadv(struct proc *p, void *v, register_t *retval) 2899 { 2900 struct sys_preadv_args /* { 2901 syscallarg(int) fd; 2902 syscallarg(const struct iovec *) iovp; 2903 syscallarg(int) iovcnt; 2904 syscallarg(int) pad; 2905 syscallarg(off_t) offset; 2906 } */ *uap = v; 2907 struct filedesc *fdp = p->p_fd; 2908 struct file *fp; 2909 struct vnode *vp; 2910 off_t offset; 2911 int fd = SCARG(uap, fd); 2912 2913 if ((fp = fd_getfile(fdp, fd)) == NULL) 2914 return (EBADF); 2915 if ((fp->f_flag & FREAD) == 0) 2916 return (EBADF); 2917 2918 vp = (struct vnode *)fp->f_data; 2919 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2920 return (ESPIPE); 2921 } 2922 2923 FREF(fp); 2924 2925 offset = SCARG(uap, offset); 2926 2927 /* dofilereadv() will FRELE the descriptor for us */ 2928 return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 1, 2929 &offset, retval)); 2930 } 2931 2932 /* 2933 * Positional write system call. 2934 */ 2935 int 2936 sys_pwrite(struct proc *p, void *v, register_t *retval) 2937 { 2938 struct sys_pwrite_args /* { 2939 syscallarg(int) fd; 2940 syscallarg(const void *) buf; 2941 syscallarg(size_t) nbyte; 2942 syscallarg(int) pad; 2943 syscallarg(off_t) offset; 2944 } */ *uap = v; 2945 struct iovec iov; 2946 struct filedesc *fdp = p->p_fd; 2947 struct file *fp; 2948 struct vnode *vp; 2949 off_t offset; 2950 int fd = SCARG(uap, fd); 2951 2952 if ((fp = fd_getfile(fdp, fd)) == NULL) 2953 return (EBADF); 2954 if ((fp->f_flag & FWRITE) == 0) 2955 return (EBADF); 2956 2957 vp = (struct vnode *)fp->f_data; 2958 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2959 return (ESPIPE); 2960 } 2961 2962 iov.iov_base = (void *)SCARG(uap, buf); 2963 iov.iov_len = SCARG(uap, nbyte); 2964 2965 FREF(fp); 2966 2967 offset = SCARG(uap, offset); 2968 2969 /* dofilewrite() will FRELE the descriptor for us */ 2970 return (dofilewritev(p, fd, fp, &iov, 1, 0, &offset, retval)); 2971 } 2972 2973 /* 2974 * Positional gather write system call. 2975 */ 2976 int 2977 sys_pwritev(struct proc *p, void *v, register_t *retval) 2978 { 2979 struct sys_pwritev_args /* { 2980 syscallarg(int) fd; 2981 syscallarg(const struct iovec *) iovp; 2982 syscallarg(int) iovcnt; 2983 syscallarg(int) pad; 2984 syscallarg(off_t) offset; 2985 } */ *uap = v; 2986 struct filedesc *fdp = p->p_fd; 2987 struct file *fp; 2988 struct vnode *vp; 2989 off_t offset; 2990 int fd = SCARG(uap, fd); 2991 2992 if ((fp = fd_getfile(fdp, fd)) == NULL) 2993 return (EBADF); 2994 if ((fp->f_flag & FWRITE) == 0) 2995 return (EBADF); 2996 2997 vp = (struct vnode *)fp->f_data; 2998 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2999 return (ESPIPE); 3000 } 3001 3002 FREF(fp); 3003 3004 offset = SCARG(uap, offset); 3005 3006 /* dofilewritev() will FRELE the descriptor for us */ 3007 return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 3008 1, &offset, retval)); 3009 } 3010