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 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 39 * $FreeBSD$ 40 */ 41 42 /* For 4.3 integer FS ID compatibility */ 43 #include "opt_compat.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/buf.h> 48 #include <sys/sysent.h> 49 #include <sys/malloc.h> 50 #include <sys/mount.h> 51 #include <sys/sysproto.h> 52 #include <sys/namei.h> 53 #include <sys/filedesc.h> 54 #include <sys/kernel.h> 55 #include <sys/fcntl.h> 56 #include <sys/file.h> 57 #include <sys/linker.h> 58 #include <sys/stat.h> 59 #include <sys/unistd.h> 60 #include <sys/vnode.h> 61 #include <sys/proc.h> 62 #include <sys/dirent.h> 63 #include <sys/extattr.h> 64 65 #include <machine/limits.h> 66 #include <miscfs/union/union.h> 67 #include <sys/sysctl.h> 68 #include <vm/vm.h> 69 #include <vm/vm_object.h> 70 #include <vm/vm_zone.h> 71 72 static int change_dir __P((struct nameidata *ndp, struct proc *p)); 73 static void checkdirs __P((struct vnode *olddp)); 74 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp)); 75 static int getutimes __P((const struct timeval *, struct timespec *)); 76 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t)); 77 static int setfmode __P((struct proc *, struct vnode *, int)); 78 static int setfflags __P((struct proc *, struct vnode *, int)); 79 static int setutimes __P((struct proc *, struct vnode *, 80 const struct timespec *, int)); 81 static int usermount = 0; /* if 1, non-root can mount fs. */ 82 83 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *)); 84 85 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); 86 87 /* 88 * Virtual File System System Calls 89 */ 90 91 /* 92 * Mount a file system. 93 */ 94 #ifndef _SYS_SYSPROTO_H_ 95 struct mount_args { 96 char *type; 97 char *path; 98 int flags; 99 caddr_t data; 100 }; 101 #endif 102 /* ARGSUSED */ 103 int 104 mount(p, uap) 105 struct proc *p; 106 register struct mount_args /* { 107 syscallarg(char *) type; 108 syscallarg(char *) path; 109 syscallarg(int) flags; 110 syscallarg(caddr_t) data; 111 } */ *uap; 112 { 113 struct vnode *vp; 114 struct mount *mp; 115 struct vfsconf *vfsp; 116 int error, flag = 0, flag2 = 0; 117 struct vattr va; 118 #ifdef COMPAT_43 119 u_long fstypenum; 120 #endif 121 struct nameidata nd; 122 char fstypename[MFSNAMELEN]; 123 124 if (usermount == 0 && (error = suser(p))) 125 return (error); 126 /* 127 * Do not allow NFS export by non-root users. 128 */ 129 if (SCARG(uap, flags) & MNT_EXPORTED) { 130 error = suser(p); 131 if (error) 132 return (error); 133 } 134 /* 135 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users 136 */ 137 if (suser_xxx(p->p_ucred, 0, 0)) 138 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 139 /* 140 * Get vnode to be covered 141 */ 142 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 143 SCARG(uap, path), p); 144 if ((error = namei(&nd)) != 0) 145 return (error); 146 NDFREE(&nd, NDF_ONLY_PNBUF); 147 vp = nd.ni_vp; 148 if (SCARG(uap, flags) & MNT_UPDATE) { 149 if ((vp->v_flag & VROOT) == 0) { 150 vput(vp); 151 return (EINVAL); 152 } 153 mp = vp->v_mount; 154 flag = mp->mnt_flag; 155 flag2 = mp->mnt_kern_flag; 156 /* 157 * We only allow the filesystem to be reloaded if it 158 * is currently mounted read-only. 159 */ 160 if ((SCARG(uap, flags) & MNT_RELOAD) && 161 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 162 vput(vp); 163 return (EOPNOTSUPP); /* Needs translation */ 164 } 165 mp->mnt_flag |= 166 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 167 /* 168 * Only root, or the user that did the original mount is 169 * permitted to update it. 170 */ 171 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 172 (error = suser(p))) { 173 vput(vp); 174 return (error); 175 } 176 if (vfs_busy(mp, LK_NOWAIT, 0, p)) { 177 vput(vp); 178 return (EBUSY); 179 } 180 VOP_UNLOCK(vp, 0, p); 181 goto update; 182 } 183 /* 184 * If the user is not root, ensure that they own the directory 185 * onto which we are attempting to mount. 186 */ 187 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 188 (va.va_uid != p->p_ucred->cr_uid && 189 (error = suser(p)))) { 190 vput(vp); 191 return (error); 192 } 193 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) 194 return (error); 195 if (vp->v_type != VDIR) { 196 vput(vp); 197 return (ENOTDIR); 198 } 199 #ifdef COMPAT_43 200 /* 201 * Historically filesystem types were identified by number. If we 202 * get an integer for the filesystem type instead of a string, we 203 * check to see if it matches one of the historic filesystem types. 204 */ 205 fstypenum = (uintptr_t)SCARG(uap, type); 206 if (fstypenum < maxvfsconf) { 207 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 208 if (vfsp->vfc_typenum == fstypenum) 209 break; 210 if (vfsp == NULL) { 211 vput(vp); 212 return (ENODEV); 213 } 214 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); 215 } else 216 #endif /* COMPAT_43 */ 217 if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) { 218 vput(vp); 219 return (error); 220 } 221 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 222 if (!strcmp(vfsp->vfc_name, fstypename)) 223 break; 224 if (vfsp == NULL) { 225 linker_file_t lf; 226 227 /* Refuse to load modules if securelevel raised */ 228 if (securelevel > 0) { 229 vput(vp); 230 return EPERM; 231 } 232 /* Only load modules for root (very important!) */ 233 if ((error = suser(p)) != 0) { 234 vput(vp); 235 return error; 236 } 237 error = linker_load_file(fstypename, &lf); 238 if (error || lf == NULL) { 239 vput(vp); 240 if (lf == NULL) 241 error = ENODEV; 242 return error; 243 } 244 lf->userrefs++; 245 /* lookup again, see if the VFS was loaded */ 246 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 247 if (!strcmp(vfsp->vfc_name, fstypename)) 248 break; 249 if (vfsp == NULL) { 250 lf->userrefs--; 251 linker_file_unload(lf); 252 vput(vp); 253 return (ENODEV); 254 } 255 } 256 simple_lock(&vp->v_interlock); 257 if ((vp->v_flag & VMOUNT) != 0 || 258 vp->v_mountedhere != NULL) { 259 simple_unlock(&vp->v_interlock); 260 vput(vp); 261 return (EBUSY); 262 } 263 vp->v_flag |= VMOUNT; 264 simple_unlock(&vp->v_interlock); 265 266 /* 267 * Allocate and initialize the filesystem. 268 */ 269 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK); 270 bzero((char *)mp, (u_long)sizeof(struct mount)); 271 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE); 272 (void)vfs_busy(mp, LK_NOWAIT, 0, p); 273 mp->mnt_op = vfsp->vfc_vfsops; 274 mp->mnt_vfc = vfsp; 275 vfsp->vfc_refcount++; 276 mp->mnt_stat.f_type = vfsp->vfc_typenum; 277 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 278 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 279 mp->mnt_vnodecovered = vp; 280 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 281 mp->mnt_iosize_max = DFLTPHYS; 282 VOP_UNLOCK(vp, 0, p); 283 update: 284 /* 285 * Set the mount level flags. 286 */ 287 if (SCARG(uap, flags) & MNT_RDONLY) 288 mp->mnt_flag |= MNT_RDONLY; 289 else if (mp->mnt_flag & MNT_RDONLY) 290 mp->mnt_kern_flag |= MNTK_WANTRDWR; 291 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 292 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME | 293 MNT_NOSYMFOLLOW | MNT_IGNORE | 294 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 295 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | 296 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | 297 MNT_NOSYMFOLLOW | MNT_IGNORE | 298 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 299 /* 300 * Mount the filesystem. 301 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they 302 * get. No freeing of cn_pnbuf. 303 */ 304 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 305 if (mp->mnt_flag & MNT_UPDATE) { 306 vrele(vp); 307 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 308 mp->mnt_flag &= ~MNT_RDONLY; 309 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 310 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 311 if (error) { 312 mp->mnt_flag = flag; 313 mp->mnt_kern_flag = flag2; 314 } 315 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 316 if (mp->mnt_syncer == NULL) 317 error = vfs_allocate_syncvnode(mp); 318 } else { 319 if (mp->mnt_syncer != NULL) 320 vrele(mp->mnt_syncer); 321 mp->mnt_syncer = NULL; 322 } 323 vfs_unbusy(mp, p); 324 return (error); 325 } 326 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 327 /* 328 * Put the new filesystem on the mount list after root. 329 */ 330 cache_purge(vp); 331 if (!error) { 332 simple_lock(&vp->v_interlock); 333 vp->v_flag &= ~VMOUNT; 334 vp->v_mountedhere = mp; 335 simple_unlock(&vp->v_interlock); 336 simple_lock(&mountlist_slock); 337 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 338 simple_unlock(&mountlist_slock); 339 checkdirs(vp); 340 VOP_UNLOCK(vp, 0, p); 341 if ((mp->mnt_flag & MNT_RDONLY) == 0) 342 error = vfs_allocate_syncvnode(mp); 343 vfs_unbusy(mp, p); 344 if ((error = VFS_START(mp, 0, p)) != 0) 345 vrele(vp); 346 } else { 347 simple_lock(&vp->v_interlock); 348 vp->v_flag &= ~VMOUNT; 349 simple_unlock(&vp->v_interlock); 350 mp->mnt_vfc->vfc_refcount--; 351 vfs_unbusy(mp, p); 352 free((caddr_t)mp, M_MOUNT); 353 vput(vp); 354 } 355 return (error); 356 } 357 358 /* 359 * Scan all active processes to see if any of them have a current 360 * or root directory onto which the new filesystem has just been 361 * mounted. If so, replace them with the new mount point. 362 */ 363 static void 364 checkdirs(olddp) 365 struct vnode *olddp; 366 { 367 struct filedesc *fdp; 368 struct vnode *newdp; 369 struct proc *p; 370 371 if (olddp->v_usecount == 1) 372 return; 373 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 374 panic("mount: lost mount"); 375 LIST_FOREACH(p, &allproc, p_list) { 376 fdp = p->p_fd; 377 if (fdp->fd_cdir == olddp) { 378 vrele(fdp->fd_cdir); 379 VREF(newdp); 380 fdp->fd_cdir = newdp; 381 } 382 if (fdp->fd_rdir == olddp) { 383 vrele(fdp->fd_rdir); 384 VREF(newdp); 385 fdp->fd_rdir = newdp; 386 } 387 } 388 if (rootvnode == olddp) { 389 vrele(rootvnode); 390 VREF(newdp); 391 rootvnode = newdp; 392 } 393 vput(newdp); 394 } 395 396 /* 397 * Unmount a file system. 398 * 399 * Note: unmount takes a path to the vnode mounted on as argument, 400 * not special file (as before). 401 */ 402 #ifndef _SYS_SYSPROTO_H_ 403 struct unmount_args { 404 char *path; 405 int flags; 406 }; 407 #endif 408 /* ARGSUSED */ 409 int 410 unmount(p, uap) 411 struct proc *p; 412 register struct unmount_args /* { 413 syscallarg(char *) path; 414 syscallarg(int) flags; 415 } */ *uap; 416 { 417 register struct vnode *vp; 418 struct mount *mp; 419 int error; 420 struct nameidata nd; 421 422 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 423 SCARG(uap, path), p); 424 if ((error = namei(&nd)) != 0) 425 return (error); 426 vp = nd.ni_vp; 427 NDFREE(&nd, NDF_ONLY_PNBUF); 428 mp = vp->v_mount; 429 430 /* 431 * Only root, or the user that did the original mount is 432 * permitted to unmount this filesystem. 433 */ 434 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 435 (error = suser(p))) { 436 vput(vp); 437 return (error); 438 } 439 440 /* 441 * Don't allow unmounting the root file system. 442 */ 443 if (mp->mnt_flag & MNT_ROOTFS) { 444 vput(vp); 445 return (EINVAL); 446 } 447 448 /* 449 * Must be the root of the filesystem 450 */ 451 if ((vp->v_flag & VROOT) == 0) { 452 vput(vp); 453 return (EINVAL); 454 } 455 vput(vp); 456 return (dounmount(mp, SCARG(uap, flags), p)); 457 } 458 459 /* 460 * Do the actual file system unmount. 461 */ 462 int 463 dounmount(mp, flags, p) 464 register struct mount *mp; 465 int flags; 466 struct proc *p; 467 { 468 struct vnode *coveredvp; 469 int error; 470 int async_flag; 471 472 simple_lock(&mountlist_slock); 473 mp->mnt_kern_flag |= MNTK_UNMOUNT; 474 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); 475 476 if (mp->mnt_flag & MNT_EXPUBLIC) 477 vfs_setpublicfs(NULL, NULL, NULL); 478 479 vfs_msync(mp, MNT_WAIT); 480 async_flag = mp->mnt_flag & MNT_ASYNC; 481 mp->mnt_flag &=~ MNT_ASYNC; 482 cache_purgevfs(mp); /* remove cache entries for this file sys */ 483 if (mp->mnt_syncer != NULL) 484 vrele(mp->mnt_syncer); 485 if (((mp->mnt_flag & MNT_RDONLY) || 486 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 487 (flags & MNT_FORCE)) 488 error = VFS_UNMOUNT(mp, flags, p); 489 simple_lock(&mountlist_slock); 490 if (error) { 491 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) 492 (void) vfs_allocate_syncvnode(mp); 493 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 494 mp->mnt_flag |= async_flag; 495 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 496 &mountlist_slock, p); 497 if (mp->mnt_kern_flag & MNTK_MWAIT) 498 wakeup((caddr_t)mp); 499 return (error); 500 } 501 TAILQ_REMOVE(&mountlist, mp, mnt_list); 502 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 503 coveredvp->v_mountedhere = (struct mount *)0; 504 vrele(coveredvp); 505 } 506 mp->mnt_vfc->vfc_refcount--; 507 if (!LIST_EMPTY(&mp->mnt_vnodelist)) 508 panic("unmount: dangling vnode"); 509 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); 510 if (mp->mnt_kern_flag & MNTK_MWAIT) 511 wakeup((caddr_t)mp); 512 free((caddr_t)mp, M_MOUNT); 513 return (0); 514 } 515 516 /* 517 * Sync each mounted filesystem. 518 */ 519 #ifndef _SYS_SYSPROTO_H_ 520 struct sync_args { 521 int dummy; 522 }; 523 #endif 524 525 #ifdef DEBUG 526 static int syncprt = 0; 527 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 528 #endif 529 530 /* ARGSUSED */ 531 int 532 sync(p, uap) 533 struct proc *p; 534 struct sync_args *uap; 535 { 536 register struct mount *mp, *nmp; 537 int asyncflag; 538 539 simple_lock(&mountlist_slock); 540 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 541 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 542 nmp = TAILQ_NEXT(mp, mnt_list); 543 continue; 544 } 545 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 546 asyncflag = mp->mnt_flag & MNT_ASYNC; 547 mp->mnt_flag &= ~MNT_ASYNC; 548 vfs_msync(mp, MNT_NOWAIT); 549 VFS_SYNC(mp, MNT_NOWAIT, 550 ((p != NULL) ? p->p_ucred : NOCRED), p); 551 mp->mnt_flag |= asyncflag; 552 } 553 simple_lock(&mountlist_slock); 554 nmp = TAILQ_NEXT(mp, mnt_list); 555 vfs_unbusy(mp, p); 556 } 557 simple_unlock(&mountlist_slock); 558 #if 0 559 /* 560 * XXX don't call vfs_bufstats() yet because that routine 561 * was not imported in the Lite2 merge. 562 */ 563 #ifdef DIAGNOSTIC 564 if (syncprt) 565 vfs_bufstats(); 566 #endif /* DIAGNOSTIC */ 567 #endif 568 return (0); 569 } 570 571 /* XXX PRISON: could be per prison flag */ 572 static int prison_quotas; 573 #if 0 574 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 575 #endif 576 577 /* 578 * Change filesystem quotas. 579 */ 580 #ifndef _SYS_SYSPROTO_H_ 581 struct quotactl_args { 582 char *path; 583 int cmd; 584 int uid; 585 caddr_t arg; 586 }; 587 #endif 588 /* ARGSUSED */ 589 int 590 quotactl(p, uap) 591 struct proc *p; 592 register struct quotactl_args /* { 593 syscallarg(char *) path; 594 syscallarg(int) cmd; 595 syscallarg(int) uid; 596 syscallarg(caddr_t) arg; 597 } */ *uap; 598 { 599 register struct mount *mp; 600 int error; 601 struct nameidata nd; 602 603 if (p->p_prison && !prison_quotas) 604 return (EPERM); 605 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 606 if ((error = namei(&nd)) != 0) 607 return (error); 608 mp = nd.ni_vp->v_mount; 609 NDFREE(&nd, NDF_ONLY_PNBUF); 610 vrele(nd.ni_vp); 611 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 612 SCARG(uap, arg), p)); 613 } 614 615 /* 616 * Get filesystem statistics. 617 */ 618 #ifndef _SYS_SYSPROTO_H_ 619 struct statfs_args { 620 char *path; 621 struct statfs *buf; 622 }; 623 #endif 624 /* ARGSUSED */ 625 int 626 statfs(p, uap) 627 struct proc *p; 628 register struct statfs_args /* { 629 syscallarg(char *) path; 630 syscallarg(struct statfs *) buf; 631 } */ *uap; 632 { 633 register struct mount *mp; 634 register struct statfs *sp; 635 int error; 636 struct nameidata nd; 637 struct statfs sb; 638 639 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 640 if ((error = namei(&nd)) != 0) 641 return (error); 642 mp = nd.ni_vp->v_mount; 643 sp = &mp->mnt_stat; 644 NDFREE(&nd, NDF_ONLY_PNBUF); 645 vrele(nd.ni_vp); 646 error = VFS_STATFS(mp, sp, p); 647 if (error) 648 return (error); 649 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 650 if (suser_xxx(p->p_ucred, 0, 0)) { 651 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 652 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 653 sp = &sb; 654 } 655 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 656 } 657 658 /* 659 * Get filesystem statistics. 660 */ 661 #ifndef _SYS_SYSPROTO_H_ 662 struct fstatfs_args { 663 int fd; 664 struct statfs *buf; 665 }; 666 #endif 667 /* ARGSUSED */ 668 int 669 fstatfs(p, uap) 670 struct proc *p; 671 register struct fstatfs_args /* { 672 syscallarg(int) fd; 673 syscallarg(struct statfs *) buf; 674 } */ *uap; 675 { 676 struct file *fp; 677 struct mount *mp; 678 register struct statfs *sp; 679 int error; 680 struct statfs sb; 681 682 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 683 return (error); 684 mp = ((struct vnode *)fp->f_data)->v_mount; 685 sp = &mp->mnt_stat; 686 error = VFS_STATFS(mp, sp, p); 687 if (error) 688 return (error); 689 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 690 if (suser_xxx(p->p_ucred, 0, 0)) { 691 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 692 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 693 sp = &sb; 694 } 695 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 696 } 697 698 /* 699 * Get statistics on all filesystems. 700 */ 701 #ifndef _SYS_SYSPROTO_H_ 702 struct getfsstat_args { 703 struct statfs *buf; 704 long bufsize; 705 int flags; 706 }; 707 #endif 708 int 709 getfsstat(p, uap) 710 struct proc *p; 711 register struct getfsstat_args /* { 712 syscallarg(struct statfs *) buf; 713 syscallarg(long) bufsize; 714 syscallarg(int) flags; 715 } */ *uap; 716 { 717 register struct mount *mp, *nmp; 718 register struct statfs *sp; 719 caddr_t sfsp; 720 long count, maxcount, error; 721 722 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 723 sfsp = (caddr_t)SCARG(uap, buf); 724 count = 0; 725 simple_lock(&mountlist_slock); 726 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 727 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { 728 nmp = TAILQ_NEXT(mp, mnt_list); 729 continue; 730 } 731 if (sfsp && count < maxcount) { 732 sp = &mp->mnt_stat; 733 /* 734 * If MNT_NOWAIT or MNT_LAZY is specified, do not 735 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 736 * overrides MNT_WAIT. 737 */ 738 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 739 (SCARG(uap, flags) & MNT_WAIT)) && 740 (error = VFS_STATFS(mp, sp, p))) { 741 simple_lock(&mountlist_slock); 742 nmp = TAILQ_NEXT(mp, mnt_list); 743 vfs_unbusy(mp, p); 744 continue; 745 } 746 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 747 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 748 if (error) { 749 vfs_unbusy(mp, p); 750 return (error); 751 } 752 sfsp += sizeof(*sp); 753 } 754 count++; 755 simple_lock(&mountlist_slock); 756 nmp = TAILQ_NEXT(mp, mnt_list); 757 vfs_unbusy(mp, p); 758 } 759 simple_unlock(&mountlist_slock); 760 if (sfsp && count > maxcount) 761 p->p_retval[0] = maxcount; 762 else 763 p->p_retval[0] = count; 764 return (0); 765 } 766 767 /* 768 * Change current working directory to a given file descriptor. 769 */ 770 #ifndef _SYS_SYSPROTO_H_ 771 struct fchdir_args { 772 int fd; 773 }; 774 #endif 775 /* ARGSUSED */ 776 int 777 fchdir(p, uap) 778 struct proc *p; 779 struct fchdir_args /* { 780 syscallarg(int) fd; 781 } */ *uap; 782 { 783 register struct filedesc *fdp = p->p_fd; 784 struct vnode *vp, *tdp; 785 struct mount *mp; 786 struct file *fp; 787 int error; 788 789 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 790 return (error); 791 vp = (struct vnode *)fp->f_data; 792 VREF(vp); 793 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 794 if (vp->v_type != VDIR) 795 error = ENOTDIR; 796 else 797 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 798 while (!error && (mp = vp->v_mountedhere) != NULL) { 799 if (vfs_busy(mp, 0, 0, p)) 800 continue; 801 error = VFS_ROOT(mp, &tdp); 802 vfs_unbusy(mp, p); 803 if (error) 804 break; 805 vput(vp); 806 vp = tdp; 807 } 808 if (error) { 809 vput(vp); 810 return (error); 811 } 812 VOP_UNLOCK(vp, 0, p); 813 vrele(fdp->fd_cdir); 814 fdp->fd_cdir = vp; 815 return (0); 816 } 817 818 /* 819 * Change current working directory (``.''). 820 */ 821 #ifndef _SYS_SYSPROTO_H_ 822 struct chdir_args { 823 char *path; 824 }; 825 #endif 826 /* ARGSUSED */ 827 int 828 chdir(p, uap) 829 struct proc *p; 830 struct chdir_args /* { 831 syscallarg(char *) path; 832 } */ *uap; 833 { 834 register struct filedesc *fdp = p->p_fd; 835 int error; 836 struct nameidata nd; 837 838 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 839 SCARG(uap, path), p); 840 if ((error = change_dir(&nd, p)) != 0) 841 return (error); 842 NDFREE(&nd, NDF_ONLY_PNBUF); 843 vrele(fdp->fd_cdir); 844 fdp->fd_cdir = nd.ni_vp; 845 return (0); 846 } 847 848 /* 849 * Helper function for raised chroot(2) security function: Refuse if 850 * any filedescriptors are open directories. 851 */ 852 static int 853 chroot_refuse_vdir_fds(fdp) 854 struct filedesc *fdp; 855 { 856 struct vnode *vp; 857 struct file *fp; 858 int error; 859 int fd; 860 861 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 862 error = getvnode(fdp, fd, &fp); 863 if (error) 864 continue; 865 vp = (struct vnode *)fp->f_data; 866 if (vp->v_type != VDIR) 867 continue; 868 return(EPERM); 869 } 870 return (0); 871 } 872 873 /* 874 * This sysctl determines if we will allow a process to chroot(2) if it 875 * has a directory open: 876 * 0: disallowed for all processes. 877 * 1: allowed for processes that were not already chroot(2)'ed. 878 * 2: allowed for all processes. 879 */ 880 881 static int chroot_allow_open_directories = 1; 882 883 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 884 &chroot_allow_open_directories, 0, ""); 885 886 /* 887 * Change notion of root (``/'') directory. 888 */ 889 #ifndef _SYS_SYSPROTO_H_ 890 struct chroot_args { 891 char *path; 892 }; 893 #endif 894 /* ARGSUSED */ 895 int 896 chroot(p, uap) 897 struct proc *p; 898 struct chroot_args /* { 899 syscallarg(char *) path; 900 } */ *uap; 901 { 902 register struct filedesc *fdp = p->p_fd; 903 int error; 904 struct nameidata nd; 905 906 error = suser_xxx(0, p, PRISON_ROOT); 907 if (error) 908 return (error); 909 if (chroot_allow_open_directories == 0 || 910 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) 911 error = chroot_refuse_vdir_fds(fdp); 912 if (error) 913 return (error); 914 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 915 SCARG(uap, path), p); 916 if ((error = change_dir(&nd, p)) != 0) 917 return (error); 918 NDFREE(&nd, NDF_ONLY_PNBUF); 919 vrele(fdp->fd_rdir); 920 fdp->fd_rdir = nd.ni_vp; 921 if (!fdp->fd_jdir) { 922 fdp->fd_jdir = nd.ni_vp; 923 VREF(fdp->fd_jdir); 924 } 925 return (0); 926 } 927 928 /* 929 * Common routine for chroot and chdir. 930 */ 931 static int 932 change_dir(ndp, p) 933 register struct nameidata *ndp; 934 struct proc *p; 935 { 936 struct vnode *vp; 937 int error; 938 939 error = namei(ndp); 940 if (error) 941 return (error); 942 vp = ndp->ni_vp; 943 if (vp->v_type != VDIR) 944 error = ENOTDIR; 945 else 946 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 947 if (error) 948 vput(vp); 949 else 950 VOP_UNLOCK(vp, 0, p); 951 return (error); 952 } 953 954 /* 955 * Check permissions, allocate an open file structure, 956 * and call the device open routine if any. 957 */ 958 #ifndef _SYS_SYSPROTO_H_ 959 struct open_args { 960 char *path; 961 int flags; 962 int mode; 963 }; 964 #endif 965 int 966 open(p, uap) 967 struct proc *p; 968 register struct open_args /* { 969 syscallarg(char *) path; 970 syscallarg(int) flags; 971 syscallarg(int) mode; 972 } */ *uap; 973 { 974 register struct filedesc *fdp = p->p_fd; 975 register struct file *fp; 976 register struct vnode *vp; 977 int cmode, flags, oflags; 978 struct file *nfp; 979 int type, indx, error; 980 struct flock lf; 981 struct nameidata nd; 982 983 oflags = SCARG(uap, flags); 984 if ((oflags & O_ACCMODE) == O_ACCMODE) 985 return (EINVAL); 986 flags = FFLAGS(oflags); 987 error = falloc(p, &nfp, &indx); 988 if (error) 989 return (error); 990 fp = nfp; 991 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 992 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 993 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 994 error = vn_open(&nd, flags, cmode); 995 if (error) { 996 ffree(fp); 997 if ((error == ENODEV || error == ENXIO) && 998 p->p_dupfd >= 0 && /* XXX from fdopen */ 999 (error = 1000 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 1001 p->p_retval[0] = indx; 1002 return (0); 1003 } 1004 if (error == ERESTART) 1005 error = EINTR; 1006 fdp->fd_ofiles[indx] = NULL; 1007 return (error); 1008 } 1009 p->p_dupfd = 0; 1010 NDFREE(&nd, NDF_ONLY_PNBUF); 1011 vp = nd.ni_vp; 1012 1013 fp->f_data = (caddr_t)vp; 1014 fp->f_flag = flags & FMASK; 1015 fp->f_ops = &vnops; 1016 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 1017 if (flags & (O_EXLOCK | O_SHLOCK)) { 1018 lf.l_whence = SEEK_SET; 1019 lf.l_start = 0; 1020 lf.l_len = 0; 1021 if (flags & O_EXLOCK) 1022 lf.l_type = F_WRLCK; 1023 else 1024 lf.l_type = F_RDLCK; 1025 type = F_FLOCK; 1026 if ((flags & FNONBLOCK) == 0) 1027 type |= F_WAIT; 1028 VOP_UNLOCK(vp, 0, p); 1029 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 1030 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 1031 ffree(fp); 1032 fdp->fd_ofiles[indx] = NULL; 1033 return (error); 1034 } 1035 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1036 fp->f_flag |= FHASLOCK; 1037 } 1038 /* assert that vn_open created a backing object if one is needed */ 1039 KASSERT(!vn_canvmio(vp) || vp->v_object != NULL, 1040 ("open: vmio vnode has no backing object after vn_open")); 1041 VOP_UNLOCK(vp, 0, p); 1042 p->p_retval[0] = indx; 1043 return (0); 1044 } 1045 1046 #ifdef COMPAT_43 1047 /* 1048 * Create a file. 1049 */ 1050 #ifndef _SYS_SYSPROTO_H_ 1051 struct ocreat_args { 1052 char *path; 1053 int mode; 1054 }; 1055 #endif 1056 int 1057 ocreat(p, uap) 1058 struct proc *p; 1059 register struct ocreat_args /* { 1060 syscallarg(char *) path; 1061 syscallarg(int) mode; 1062 } */ *uap; 1063 { 1064 struct open_args /* { 1065 syscallarg(char *) path; 1066 syscallarg(int) flags; 1067 syscallarg(int) mode; 1068 } */ nuap; 1069 1070 SCARG(&nuap, path) = SCARG(uap, path); 1071 SCARG(&nuap, mode) = SCARG(uap, mode); 1072 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 1073 return (open(p, &nuap)); 1074 } 1075 #endif /* COMPAT_43 */ 1076 1077 /* 1078 * Create a special file. 1079 */ 1080 #ifndef _SYS_SYSPROTO_H_ 1081 struct mknod_args { 1082 char *path; 1083 int mode; 1084 int dev; 1085 }; 1086 #endif 1087 /* ARGSUSED */ 1088 int 1089 mknod(p, uap) 1090 struct proc *p; 1091 register struct mknod_args /* { 1092 syscallarg(char *) path; 1093 syscallarg(int) mode; 1094 syscallarg(int) dev; 1095 } */ *uap; 1096 { 1097 register struct vnode *vp; 1098 struct vattr vattr; 1099 int error; 1100 int whiteout = 0; 1101 struct nameidata nd; 1102 1103 switch (SCARG(uap, mode) & S_IFMT) { 1104 case S_IFCHR: 1105 case S_IFBLK: 1106 error = suser(p); 1107 break; 1108 default: 1109 error = suser_xxx(0, p, PRISON_ROOT); 1110 break; 1111 } 1112 if (error) 1113 return (error); 1114 bwillwrite(); 1115 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1116 if ((error = namei(&nd)) != 0) 1117 return (error); 1118 vp = nd.ni_vp; 1119 if (vp != NULL) 1120 error = EEXIST; 1121 else { 1122 VATTR_NULL(&vattr); 1123 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1124 vattr.va_rdev = SCARG(uap, dev); 1125 whiteout = 0; 1126 1127 switch (SCARG(uap, mode) & S_IFMT) { 1128 case S_IFMT: /* used by badsect to flag bad sectors */ 1129 vattr.va_type = VBAD; 1130 break; 1131 case S_IFCHR: 1132 vattr.va_type = VCHR; 1133 break; 1134 case S_IFBLK: 1135 vattr.va_type = VBLK; 1136 break; 1137 case S_IFWHT: 1138 whiteout = 1; 1139 break; 1140 default: 1141 error = EINVAL; 1142 break; 1143 } 1144 } 1145 if (!error) { 1146 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1147 if (whiteout) 1148 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1149 else { 1150 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1151 &nd.ni_cnd, &vattr); 1152 if (error == 0) 1153 vput(nd.ni_vp); 1154 } 1155 NDFREE(&nd, NDF_ONLY_PNBUF); 1156 vput(nd.ni_dvp); 1157 } else { 1158 NDFREE(&nd, NDF_ONLY_PNBUF); 1159 if (nd.ni_dvp == vp) 1160 vrele(nd.ni_dvp); 1161 else 1162 vput(nd.ni_dvp); 1163 if (vp) 1164 vrele(vp); 1165 } 1166 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1167 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1168 return (error); 1169 } 1170 1171 /* 1172 * Create a named pipe. 1173 */ 1174 #ifndef _SYS_SYSPROTO_H_ 1175 struct mkfifo_args { 1176 char *path; 1177 int mode; 1178 }; 1179 #endif 1180 /* ARGSUSED */ 1181 int 1182 mkfifo(p, uap) 1183 struct proc *p; 1184 register struct mkfifo_args /* { 1185 syscallarg(char *) path; 1186 syscallarg(int) mode; 1187 } */ *uap; 1188 { 1189 struct vattr vattr; 1190 int error; 1191 struct nameidata nd; 1192 1193 bwillwrite(); 1194 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1195 if ((error = namei(&nd)) != 0) 1196 return (error); 1197 if (nd.ni_vp != NULL) { 1198 NDFREE(&nd, NDF_ONLY_PNBUF); 1199 if (nd.ni_dvp == nd.ni_vp) 1200 vrele(nd.ni_dvp); 1201 else 1202 vput(nd.ni_dvp); 1203 vrele(nd.ni_vp); 1204 return (EEXIST); 1205 } 1206 VATTR_NULL(&vattr); 1207 vattr.va_type = VFIFO; 1208 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1209 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1210 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1211 if (error == 0) 1212 vput(nd.ni_vp); 1213 NDFREE(&nd, NDF_ONLY_PNBUF); 1214 vput(nd.ni_dvp); 1215 return (error); 1216 } 1217 1218 /* 1219 * Make a hard file link. 1220 */ 1221 #ifndef _SYS_SYSPROTO_H_ 1222 struct link_args { 1223 char *path; 1224 char *link; 1225 }; 1226 #endif 1227 /* ARGSUSED */ 1228 int 1229 link(p, uap) 1230 struct proc *p; 1231 register struct link_args /* { 1232 syscallarg(char *) path; 1233 syscallarg(char *) link; 1234 } */ *uap; 1235 { 1236 register struct vnode *vp; 1237 struct nameidata nd; 1238 int error; 1239 1240 bwillwrite(); 1241 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p); 1242 if ((error = namei(&nd)) != 0) 1243 return (error); 1244 NDFREE(&nd, NDF_ONLY_PNBUF); 1245 vp = nd.ni_vp; 1246 if (vp->v_type == VDIR) 1247 error = EPERM; /* POSIX */ 1248 else { 1249 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1250 error = namei(&nd); 1251 if (!error) { 1252 if (nd.ni_vp != NULL) { 1253 if (nd.ni_vp) 1254 vrele(nd.ni_vp); 1255 error = EEXIST; 1256 } else { 1257 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1258 LEASE_WRITE); 1259 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1260 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1261 } 1262 NDFREE(&nd, NDF_ONLY_PNBUF); 1263 if (nd.ni_dvp == nd.ni_vp) 1264 vrele(nd.ni_dvp); 1265 else 1266 vput(nd.ni_dvp); 1267 } 1268 } 1269 vrele(vp); 1270 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1271 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1272 return (error); 1273 } 1274 1275 /* 1276 * Make a symbolic link. 1277 */ 1278 #ifndef _SYS_SYSPROTO_H_ 1279 struct symlink_args { 1280 char *path; 1281 char *link; 1282 }; 1283 #endif 1284 /* ARGSUSED */ 1285 int 1286 symlink(p, uap) 1287 struct proc *p; 1288 register struct symlink_args /* { 1289 syscallarg(char *) path; 1290 syscallarg(char *) link; 1291 } */ *uap; 1292 { 1293 struct vattr vattr; 1294 char *path; 1295 int error; 1296 struct nameidata nd; 1297 1298 path = zalloc(namei_zone); 1299 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) 1300 goto out; 1301 bwillwrite(); 1302 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p); 1303 if ((error = namei(&nd)) != 0) 1304 goto out; 1305 if (nd.ni_vp) { 1306 NDFREE(&nd, NDF_ONLY_PNBUF); 1307 if (nd.ni_dvp == nd.ni_vp) 1308 vrele(nd.ni_dvp); 1309 else 1310 vput(nd.ni_dvp); 1311 vrele(nd.ni_vp); 1312 error = EEXIST; 1313 goto out; 1314 } 1315 VATTR_NULL(&vattr); 1316 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1317 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1318 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1319 NDFREE(&nd, NDF_ONLY_PNBUF); 1320 if (error == 0) 1321 vput(nd.ni_vp); 1322 vput(nd.ni_dvp); 1323 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1324 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1325 out: 1326 zfree(namei_zone, path); 1327 return (error); 1328 } 1329 1330 /* 1331 * Delete a whiteout from the filesystem. 1332 */ 1333 /* ARGSUSED */ 1334 int 1335 undelete(p, uap) 1336 struct proc *p; 1337 register struct undelete_args /* { 1338 syscallarg(char *) path; 1339 } */ *uap; 1340 { 1341 int error; 1342 struct nameidata nd; 1343 1344 bwillwrite(); 1345 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1346 SCARG(uap, path), p); 1347 error = namei(&nd); 1348 if (error) 1349 return (error); 1350 1351 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1352 NDFREE(&nd, NDF_ONLY_PNBUF); 1353 if (nd.ni_dvp == nd.ni_vp) 1354 vrele(nd.ni_dvp); 1355 else 1356 vput(nd.ni_dvp); 1357 if (nd.ni_vp) 1358 vrele(nd.ni_vp); 1359 return (EEXIST); 1360 } 1361 1362 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1363 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1364 NDFREE(&nd, NDF_ONLY_PNBUF); 1365 vput(nd.ni_dvp); 1366 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1367 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1368 return (error); 1369 } 1370 1371 /* 1372 * Delete a name from the filesystem. 1373 */ 1374 #ifndef _SYS_SYSPROTO_H_ 1375 struct unlink_args { 1376 char *path; 1377 }; 1378 #endif 1379 /* ARGSUSED */ 1380 int 1381 unlink(p, uap) 1382 struct proc *p; 1383 struct unlink_args /* { 1384 syscallarg(char *) path; 1385 } */ *uap; 1386 { 1387 register struct vnode *vp; 1388 int error; 1389 struct nameidata nd; 1390 1391 bwillwrite(); 1392 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1393 if ((error = namei(&nd)) != 0) 1394 return (error); 1395 vp = nd.ni_vp; 1396 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1397 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1398 1399 if (vp->v_type == VDIR) 1400 error = EPERM; /* POSIX */ 1401 else { 1402 /* 1403 * The root of a mounted filesystem cannot be deleted. 1404 * 1405 * XXX: can this only be a VDIR case? 1406 */ 1407 if (vp->v_flag & VROOT) 1408 error = EBUSY; 1409 } 1410 1411 if (!error) { 1412 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1413 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1414 } 1415 NDFREE(&nd, NDF_ONLY_PNBUF); 1416 if (nd.ni_dvp == vp) 1417 vrele(nd.ni_dvp); 1418 else 1419 vput(nd.ni_dvp); 1420 if (vp != NULLVP) 1421 vput(vp); 1422 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1423 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1424 return (error); 1425 } 1426 1427 /* 1428 * Reposition read/write file offset. 1429 */ 1430 #ifndef _SYS_SYSPROTO_H_ 1431 struct lseek_args { 1432 int fd; 1433 int pad; 1434 off_t offset; 1435 int whence; 1436 }; 1437 #endif 1438 int 1439 lseek(p, uap) 1440 struct proc *p; 1441 register struct lseek_args /* { 1442 syscallarg(int) fd; 1443 syscallarg(int) pad; 1444 syscallarg(off_t) offset; 1445 syscallarg(int) whence; 1446 } */ *uap; 1447 { 1448 struct ucred *cred = p->p_ucred; 1449 register struct filedesc *fdp = p->p_fd; 1450 register struct file *fp; 1451 struct vattr vattr; 1452 int error; 1453 1454 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1455 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1456 return (EBADF); 1457 if (fp->f_type != DTYPE_VNODE) 1458 return (ESPIPE); 1459 switch (SCARG(uap, whence)) { 1460 case L_INCR: 1461 fp->f_offset += SCARG(uap, offset); 1462 break; 1463 case L_XTND: 1464 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1465 if (error) 1466 return (error); 1467 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1468 break; 1469 case L_SET: 1470 fp->f_offset = SCARG(uap, offset); 1471 break; 1472 default: 1473 return (EINVAL); 1474 } 1475 *(off_t *)(p->p_retval) = fp->f_offset; 1476 return (0); 1477 } 1478 1479 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1480 /* 1481 * Reposition read/write file offset. 1482 */ 1483 #ifndef _SYS_SYSPROTO_H_ 1484 struct olseek_args { 1485 int fd; 1486 long offset; 1487 int whence; 1488 }; 1489 #endif 1490 int 1491 olseek(p, uap) 1492 struct proc *p; 1493 register struct olseek_args /* { 1494 syscallarg(int) fd; 1495 syscallarg(long) offset; 1496 syscallarg(int) whence; 1497 } */ *uap; 1498 { 1499 struct lseek_args /* { 1500 syscallarg(int) fd; 1501 syscallarg(int) pad; 1502 syscallarg(off_t) offset; 1503 syscallarg(int) whence; 1504 } */ nuap; 1505 int error; 1506 1507 SCARG(&nuap, fd) = SCARG(uap, fd); 1508 SCARG(&nuap, offset) = SCARG(uap, offset); 1509 SCARG(&nuap, whence) = SCARG(uap, whence); 1510 error = lseek(p, &nuap); 1511 return (error); 1512 } 1513 #endif /* COMPAT_43 */ 1514 1515 /* 1516 * Check access permissions. 1517 */ 1518 #ifndef _SYS_SYSPROTO_H_ 1519 struct access_args { 1520 char *path; 1521 int flags; 1522 }; 1523 #endif 1524 int 1525 access(p, uap) 1526 struct proc *p; 1527 register struct access_args /* { 1528 syscallarg(char *) path; 1529 syscallarg(int) flags; 1530 } */ *uap; 1531 { 1532 register struct ucred *cred = p->p_ucred; 1533 register struct vnode *vp; 1534 int error, flags, t_gid, t_uid; 1535 struct nameidata nd; 1536 1537 t_uid = cred->cr_uid; 1538 t_gid = cred->cr_groups[0]; 1539 cred->cr_uid = p->p_cred->p_ruid; 1540 cred->cr_groups[0] = p->p_cred->p_rgid; 1541 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1542 SCARG(uap, path), p); 1543 if ((error = namei(&nd)) != 0) 1544 goto out1; 1545 vp = nd.ni_vp; 1546 1547 /* Flags == 0 means only check for existence. */ 1548 if (SCARG(uap, flags)) { 1549 flags = 0; 1550 if (SCARG(uap, flags) & R_OK) 1551 flags |= VREAD; 1552 if (SCARG(uap, flags) & W_OK) 1553 flags |= VWRITE; 1554 if (SCARG(uap, flags) & X_OK) 1555 flags |= VEXEC; 1556 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1557 error = VOP_ACCESS(vp, flags, cred, p); 1558 } 1559 NDFREE(&nd, NDF_ONLY_PNBUF); 1560 vput(vp); 1561 out1: 1562 cred->cr_uid = t_uid; 1563 cred->cr_groups[0] = t_gid; 1564 return (error); 1565 } 1566 1567 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1568 /* 1569 * Get file status; this version follows links. 1570 */ 1571 #ifndef _SYS_SYSPROTO_H_ 1572 struct ostat_args { 1573 char *path; 1574 struct ostat *ub; 1575 }; 1576 #endif 1577 /* ARGSUSED */ 1578 int 1579 ostat(p, uap) 1580 struct proc *p; 1581 register struct ostat_args /* { 1582 syscallarg(char *) path; 1583 syscallarg(struct ostat *) ub; 1584 } */ *uap; 1585 { 1586 struct stat sb; 1587 struct ostat osb; 1588 int error; 1589 struct nameidata nd; 1590 1591 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1592 SCARG(uap, path), p); 1593 if ((error = namei(&nd)) != 0) 1594 return (error); 1595 NDFREE(&nd, NDF_ONLY_PNBUF); 1596 error = vn_stat(nd.ni_vp, &sb, p); 1597 vput(nd.ni_vp); 1598 if (error) 1599 return (error); 1600 cvtstat(&sb, &osb); 1601 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1602 return (error); 1603 } 1604 1605 /* 1606 * Get file status; this version does not follow links. 1607 */ 1608 #ifndef _SYS_SYSPROTO_H_ 1609 struct olstat_args { 1610 char *path; 1611 struct ostat *ub; 1612 }; 1613 #endif 1614 /* ARGSUSED */ 1615 int 1616 olstat(p, uap) 1617 struct proc *p; 1618 register struct olstat_args /* { 1619 syscallarg(char *) path; 1620 syscallarg(struct ostat *) ub; 1621 } */ *uap; 1622 { 1623 struct vnode *vp; 1624 struct stat sb; 1625 struct ostat osb; 1626 int error; 1627 struct nameidata nd; 1628 1629 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1630 SCARG(uap, path), p); 1631 if ((error = namei(&nd)) != 0) 1632 return (error); 1633 vp = nd.ni_vp; 1634 error = vn_stat(vp, &sb, p); 1635 NDFREE(&nd, NDF_ONLY_PNBUF); 1636 vput(vp); 1637 if (error) 1638 return (error); 1639 cvtstat(&sb, &osb); 1640 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1641 return (error); 1642 } 1643 1644 /* 1645 * Convert from an old to a new stat structure. 1646 */ 1647 void 1648 cvtstat(st, ost) 1649 struct stat *st; 1650 struct ostat *ost; 1651 { 1652 1653 ost->st_dev = st->st_dev; 1654 ost->st_ino = st->st_ino; 1655 ost->st_mode = st->st_mode; 1656 ost->st_nlink = st->st_nlink; 1657 ost->st_uid = st->st_uid; 1658 ost->st_gid = st->st_gid; 1659 ost->st_rdev = st->st_rdev; 1660 if (st->st_size < (quad_t)1 << 32) 1661 ost->st_size = st->st_size; 1662 else 1663 ost->st_size = -2; 1664 ost->st_atime = st->st_atime; 1665 ost->st_mtime = st->st_mtime; 1666 ost->st_ctime = st->st_ctime; 1667 ost->st_blksize = st->st_blksize; 1668 ost->st_blocks = st->st_blocks; 1669 ost->st_flags = st->st_flags; 1670 ost->st_gen = st->st_gen; 1671 } 1672 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1673 1674 /* 1675 * Get file status; this version follows links. 1676 */ 1677 #ifndef _SYS_SYSPROTO_H_ 1678 struct stat_args { 1679 char *path; 1680 struct stat *ub; 1681 }; 1682 #endif 1683 /* ARGSUSED */ 1684 int 1685 stat(p, uap) 1686 struct proc *p; 1687 register struct stat_args /* { 1688 syscallarg(char *) path; 1689 syscallarg(struct stat *) ub; 1690 } */ *uap; 1691 { 1692 struct stat sb; 1693 int error; 1694 struct nameidata nd; 1695 1696 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1697 SCARG(uap, path), p); 1698 if ((error = namei(&nd)) != 0) 1699 return (error); 1700 error = vn_stat(nd.ni_vp, &sb, p); 1701 NDFREE(&nd, NDF_ONLY_PNBUF); 1702 vput(nd.ni_vp); 1703 if (error) 1704 return (error); 1705 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1706 return (error); 1707 } 1708 1709 /* 1710 * Get file status; this version does not follow links. 1711 */ 1712 #ifndef _SYS_SYSPROTO_H_ 1713 struct lstat_args { 1714 char *path; 1715 struct stat *ub; 1716 }; 1717 #endif 1718 /* ARGSUSED */ 1719 int 1720 lstat(p, uap) 1721 struct proc *p; 1722 register struct lstat_args /* { 1723 syscallarg(char *) path; 1724 syscallarg(struct stat *) ub; 1725 } */ *uap; 1726 { 1727 int error; 1728 struct vnode *vp; 1729 struct stat sb; 1730 struct nameidata nd; 1731 1732 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1733 SCARG(uap, path), p); 1734 if ((error = namei(&nd)) != 0) 1735 return (error); 1736 vp = nd.ni_vp; 1737 error = vn_stat(vp, &sb, p); 1738 NDFREE(&nd, NDF_ONLY_PNBUF); 1739 vput(vp); 1740 if (error) 1741 return (error); 1742 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1743 return (error); 1744 } 1745 1746 void 1747 cvtnstat(sb, nsb) 1748 struct stat *sb; 1749 struct nstat *nsb; 1750 { 1751 nsb->st_dev = sb->st_dev; 1752 nsb->st_ino = sb->st_ino; 1753 nsb->st_mode = sb->st_mode; 1754 nsb->st_nlink = sb->st_nlink; 1755 nsb->st_uid = sb->st_uid; 1756 nsb->st_gid = sb->st_gid; 1757 nsb->st_rdev = sb->st_rdev; 1758 nsb->st_atimespec = sb->st_atimespec; 1759 nsb->st_mtimespec = sb->st_mtimespec; 1760 nsb->st_ctimespec = sb->st_ctimespec; 1761 nsb->st_size = sb->st_size; 1762 nsb->st_blocks = sb->st_blocks; 1763 nsb->st_blksize = sb->st_blksize; 1764 nsb->st_flags = sb->st_flags; 1765 nsb->st_gen = sb->st_gen; 1766 nsb->st_qspare[0] = sb->st_qspare[0]; 1767 nsb->st_qspare[1] = sb->st_qspare[1]; 1768 } 1769 1770 #ifndef _SYS_SYSPROTO_H_ 1771 struct nstat_args { 1772 char *path; 1773 struct nstat *ub; 1774 }; 1775 #endif 1776 /* ARGSUSED */ 1777 int 1778 nstat(p, uap) 1779 struct proc *p; 1780 register struct nstat_args /* { 1781 syscallarg(char *) path; 1782 syscallarg(struct nstat *) ub; 1783 } */ *uap; 1784 { 1785 struct stat sb; 1786 struct nstat nsb; 1787 int error; 1788 struct nameidata nd; 1789 1790 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1791 SCARG(uap, path), p); 1792 if ((error = namei(&nd)) != 0) 1793 return (error); 1794 NDFREE(&nd, NDF_ONLY_PNBUF); 1795 error = vn_stat(nd.ni_vp, &sb, p); 1796 vput(nd.ni_vp); 1797 if (error) 1798 return (error); 1799 cvtnstat(&sb, &nsb); 1800 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 1801 return (error); 1802 } 1803 1804 /* 1805 * Get file status; this version does not follow links. 1806 */ 1807 #ifndef _SYS_SYSPROTO_H_ 1808 struct lstat_args { 1809 char *path; 1810 struct stat *ub; 1811 }; 1812 #endif 1813 /* ARGSUSED */ 1814 int 1815 nlstat(p, uap) 1816 struct proc *p; 1817 register struct nlstat_args /* { 1818 syscallarg(char *) path; 1819 syscallarg(struct nstat *) ub; 1820 } */ *uap; 1821 { 1822 int error; 1823 struct vnode *vp; 1824 struct stat sb; 1825 struct nstat nsb; 1826 struct nameidata nd; 1827 1828 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1829 SCARG(uap, path), p); 1830 if ((error = namei(&nd)) != 0) 1831 return (error); 1832 vp = nd.ni_vp; 1833 NDFREE(&nd, NDF_ONLY_PNBUF); 1834 error = vn_stat(vp, &sb, p); 1835 vput(vp); 1836 if (error) 1837 return (error); 1838 cvtnstat(&sb, &nsb); 1839 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 1840 return (error); 1841 } 1842 1843 /* 1844 * Get configurable pathname variables. 1845 */ 1846 #ifndef _SYS_SYSPROTO_H_ 1847 struct pathconf_args { 1848 char *path; 1849 int name; 1850 }; 1851 #endif 1852 /* ARGSUSED */ 1853 int 1854 pathconf(p, uap) 1855 struct proc *p; 1856 register struct pathconf_args /* { 1857 syscallarg(char *) path; 1858 syscallarg(int) name; 1859 } */ *uap; 1860 { 1861 int error; 1862 struct nameidata nd; 1863 1864 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1865 SCARG(uap, path), p); 1866 if ((error = namei(&nd)) != 0) 1867 return (error); 1868 NDFREE(&nd, NDF_ONLY_PNBUF); 1869 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval); 1870 vput(nd.ni_vp); 1871 return (error); 1872 } 1873 1874 /* 1875 * Return target name of a symbolic link. 1876 */ 1877 #ifndef _SYS_SYSPROTO_H_ 1878 struct readlink_args { 1879 char *path; 1880 char *buf; 1881 int count; 1882 }; 1883 #endif 1884 /* ARGSUSED */ 1885 int 1886 readlink(p, uap) 1887 struct proc *p; 1888 register struct readlink_args /* { 1889 syscallarg(char *) path; 1890 syscallarg(char *) buf; 1891 syscallarg(int) count; 1892 } */ *uap; 1893 { 1894 register struct vnode *vp; 1895 struct iovec aiov; 1896 struct uio auio; 1897 int error; 1898 struct nameidata nd; 1899 1900 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1901 SCARG(uap, path), p); 1902 if ((error = namei(&nd)) != 0) 1903 return (error); 1904 NDFREE(&nd, NDF_ONLY_PNBUF); 1905 vp = nd.ni_vp; 1906 if (vp->v_type != VLNK) 1907 error = EINVAL; 1908 else { 1909 aiov.iov_base = SCARG(uap, buf); 1910 aiov.iov_len = SCARG(uap, count); 1911 auio.uio_iov = &aiov; 1912 auio.uio_iovcnt = 1; 1913 auio.uio_offset = 0; 1914 auio.uio_rw = UIO_READ; 1915 auio.uio_segflg = UIO_USERSPACE; 1916 auio.uio_procp = p; 1917 auio.uio_resid = SCARG(uap, count); 1918 error = VOP_READLINK(vp, &auio, p->p_ucred); 1919 } 1920 vput(vp); 1921 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 1922 return (error); 1923 } 1924 1925 static int 1926 setfflags(p, vp, flags) 1927 struct proc *p; 1928 struct vnode *vp; 1929 int flags; 1930 { 1931 int error; 1932 struct vattr vattr; 1933 1934 /* 1935 * Prevent non-root users from setting flags on devices. When 1936 * a device is reused, users can retain ownership of the device 1937 * if they are allowed to set flags and programs assume that 1938 * chown can't fail when done as root. 1939 */ 1940 if ((vp->v_type == VCHR || vp->v_type == VBLK) && 1941 ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0)) 1942 return (error); 1943 1944 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1946 VATTR_NULL(&vattr); 1947 vattr.va_flags = flags; 1948 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1949 VOP_UNLOCK(vp, 0, p); 1950 return (error); 1951 } 1952 1953 /* 1954 * Change flags of a file given a path name. 1955 */ 1956 #ifndef _SYS_SYSPROTO_H_ 1957 struct chflags_args { 1958 char *path; 1959 int flags; 1960 }; 1961 #endif 1962 /* ARGSUSED */ 1963 int 1964 chflags(p, uap) 1965 struct proc *p; 1966 register struct chflags_args /* { 1967 syscallarg(char *) path; 1968 syscallarg(int) flags; 1969 } */ *uap; 1970 { 1971 int error; 1972 struct nameidata nd; 1973 1974 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1975 if ((error = namei(&nd)) != 0) 1976 return (error); 1977 NDFREE(&nd, NDF_ONLY_PNBUF); 1978 error = setfflags(p, nd.ni_vp, SCARG(uap, flags)); 1979 vrele(nd.ni_vp); 1980 return error; 1981 } 1982 1983 /* 1984 * Change flags of a file given a file descriptor. 1985 */ 1986 #ifndef _SYS_SYSPROTO_H_ 1987 struct fchflags_args { 1988 int fd; 1989 int flags; 1990 }; 1991 #endif 1992 /* ARGSUSED */ 1993 int 1994 fchflags(p, uap) 1995 struct proc *p; 1996 register struct fchflags_args /* { 1997 syscallarg(int) fd; 1998 syscallarg(int) flags; 1999 } */ *uap; 2000 { 2001 struct file *fp; 2002 int error; 2003 2004 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2005 return (error); 2006 return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags)); 2007 } 2008 2009 static int 2010 setfmode(p, vp, mode) 2011 struct proc *p; 2012 struct vnode *vp; 2013 int mode; 2014 { 2015 int error; 2016 struct vattr vattr; 2017 2018 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2019 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2020 VATTR_NULL(&vattr); 2021 vattr.va_mode = mode & ALLPERMS; 2022 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2023 VOP_UNLOCK(vp, 0, p); 2024 return error; 2025 } 2026 2027 /* 2028 * Change mode of a file given path name. 2029 */ 2030 #ifndef _SYS_SYSPROTO_H_ 2031 struct chmod_args { 2032 char *path; 2033 int mode; 2034 }; 2035 #endif 2036 /* ARGSUSED */ 2037 int 2038 chmod(p, uap) 2039 struct proc *p; 2040 register struct chmod_args /* { 2041 syscallarg(char *) path; 2042 syscallarg(int) mode; 2043 } */ *uap; 2044 { 2045 int error; 2046 struct nameidata nd; 2047 2048 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2049 if ((error = namei(&nd)) != 0) 2050 return (error); 2051 NDFREE(&nd, NDF_ONLY_PNBUF); 2052 error = setfmode(p, nd.ni_vp, SCARG(uap, mode)); 2053 vrele(nd.ni_vp); 2054 return error; 2055 } 2056 2057 /* 2058 * Change mode of a file given path name (don't follow links.) 2059 */ 2060 #ifndef _SYS_SYSPROTO_H_ 2061 struct lchmod_args { 2062 char *path; 2063 int mode; 2064 }; 2065 #endif 2066 /* ARGSUSED */ 2067 int 2068 lchmod(p, uap) 2069 struct proc *p; 2070 register struct lchmod_args /* { 2071 syscallarg(char *) path; 2072 syscallarg(int) mode; 2073 } */ *uap; 2074 { 2075 int error; 2076 struct nameidata nd; 2077 2078 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2079 if ((error = namei(&nd)) != 0) 2080 return (error); 2081 NDFREE(&nd, NDF_ONLY_PNBUF); 2082 error = setfmode(p, nd.ni_vp, SCARG(uap, mode)); 2083 vrele(nd.ni_vp); 2084 return error; 2085 } 2086 2087 /* 2088 * Change mode of a file given a file descriptor. 2089 */ 2090 #ifndef _SYS_SYSPROTO_H_ 2091 struct fchmod_args { 2092 int fd; 2093 int mode; 2094 }; 2095 #endif 2096 /* ARGSUSED */ 2097 int 2098 fchmod(p, uap) 2099 struct proc *p; 2100 register struct fchmod_args /* { 2101 syscallarg(int) fd; 2102 syscallarg(int) mode; 2103 } */ *uap; 2104 { 2105 struct file *fp; 2106 int error; 2107 2108 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2109 return (error); 2110 return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode)); 2111 } 2112 2113 static int 2114 setfown(p, vp, uid, gid) 2115 struct proc *p; 2116 struct vnode *vp; 2117 uid_t uid; 2118 gid_t gid; 2119 { 2120 int error; 2121 struct vattr vattr; 2122 2123 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2124 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2125 VATTR_NULL(&vattr); 2126 vattr.va_uid = uid; 2127 vattr.va_gid = gid; 2128 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2129 VOP_UNLOCK(vp, 0, p); 2130 return error; 2131 } 2132 2133 /* 2134 * Set ownership given a path name. 2135 */ 2136 #ifndef _SYS_SYSPROTO_H_ 2137 struct chown_args { 2138 char *path; 2139 int uid; 2140 int gid; 2141 }; 2142 #endif 2143 /* ARGSUSED */ 2144 int 2145 chown(p, uap) 2146 struct proc *p; 2147 register struct chown_args /* { 2148 syscallarg(char *) path; 2149 syscallarg(int) uid; 2150 syscallarg(int) gid; 2151 } */ *uap; 2152 { 2153 int error; 2154 struct nameidata nd; 2155 2156 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2157 if ((error = namei(&nd)) != 0) 2158 return (error); 2159 NDFREE(&nd, NDF_ONLY_PNBUF); 2160 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2161 vrele(nd.ni_vp); 2162 return (error); 2163 } 2164 2165 /* 2166 * Set ownership given a path name, do not cross symlinks. 2167 */ 2168 #ifndef _SYS_SYSPROTO_H_ 2169 struct lchown_args { 2170 char *path; 2171 int uid; 2172 int gid; 2173 }; 2174 #endif 2175 /* ARGSUSED */ 2176 int 2177 lchown(p, uap) 2178 struct proc *p; 2179 register struct lchown_args /* { 2180 syscallarg(char *) path; 2181 syscallarg(int) uid; 2182 syscallarg(int) gid; 2183 } */ *uap; 2184 { 2185 int error; 2186 struct nameidata nd; 2187 2188 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2189 if ((error = namei(&nd)) != 0) 2190 return (error); 2191 NDFREE(&nd, NDF_ONLY_PNBUF); 2192 error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2193 vrele(nd.ni_vp); 2194 return (error); 2195 } 2196 2197 /* 2198 * Set ownership given a file descriptor. 2199 */ 2200 #ifndef _SYS_SYSPROTO_H_ 2201 struct fchown_args { 2202 int fd; 2203 int uid; 2204 int gid; 2205 }; 2206 #endif 2207 /* ARGSUSED */ 2208 int 2209 fchown(p, uap) 2210 struct proc *p; 2211 register struct fchown_args /* { 2212 syscallarg(int) fd; 2213 syscallarg(int) uid; 2214 syscallarg(int) gid; 2215 } */ *uap; 2216 { 2217 struct file *fp; 2218 int error; 2219 2220 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2221 return (error); 2222 return setfown(p, (struct vnode *)fp->f_data, 2223 SCARG(uap, uid), SCARG(uap, gid)); 2224 } 2225 2226 static int 2227 getutimes(usrtvp, tsp) 2228 const struct timeval *usrtvp; 2229 struct timespec *tsp; 2230 { 2231 struct timeval tv[2]; 2232 int error; 2233 2234 if (usrtvp == NULL) { 2235 microtime(&tv[0]); 2236 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2237 tsp[1] = tsp[0]; 2238 } else { 2239 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) 2240 return (error); 2241 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2242 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); 2243 } 2244 return 0; 2245 } 2246 2247 static int 2248 setutimes(p, vp, ts, nullflag) 2249 struct proc *p; 2250 struct vnode *vp; 2251 const struct timespec *ts; 2252 int nullflag; 2253 { 2254 int error; 2255 struct vattr vattr; 2256 2257 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2258 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2259 VATTR_NULL(&vattr); 2260 vattr.va_atime = ts[0]; 2261 vattr.va_mtime = ts[1]; 2262 if (nullflag) 2263 vattr.va_vaflags |= VA_UTIMES_NULL; 2264 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2265 VOP_UNLOCK(vp, 0, p); 2266 return error; 2267 } 2268 2269 /* 2270 * Set the access and modification times of a file. 2271 */ 2272 #ifndef _SYS_SYSPROTO_H_ 2273 struct utimes_args { 2274 char *path; 2275 struct timeval *tptr; 2276 }; 2277 #endif 2278 /* ARGSUSED */ 2279 int 2280 utimes(p, uap) 2281 struct proc *p; 2282 register struct utimes_args /* { 2283 syscallarg(char *) path; 2284 syscallarg(struct timeval *) tptr; 2285 } */ *uap; 2286 { 2287 struct timespec ts[2]; 2288 struct timeval *usrtvp; 2289 int error; 2290 struct nameidata nd; 2291 2292 usrtvp = SCARG(uap, tptr); 2293 if ((error = getutimes(usrtvp, ts)) != 0) 2294 return (error); 2295 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2296 if ((error = namei(&nd)) != 0) 2297 return (error); 2298 NDFREE(&nd, NDF_ONLY_PNBUF); 2299 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL); 2300 vrele(nd.ni_vp); 2301 return (error); 2302 } 2303 2304 /* 2305 * Set the access and modification times of a file. 2306 */ 2307 #ifndef _SYS_SYSPROTO_H_ 2308 struct lutimes_args { 2309 char *path; 2310 struct timeval *tptr; 2311 }; 2312 #endif 2313 /* ARGSUSED */ 2314 int 2315 lutimes(p, uap) 2316 struct proc *p; 2317 register struct lutimes_args /* { 2318 syscallarg(char *) path; 2319 syscallarg(struct timeval *) tptr; 2320 } */ *uap; 2321 { 2322 struct timespec ts[2]; 2323 struct timeval *usrtvp; 2324 int error; 2325 struct nameidata nd; 2326 2327 usrtvp = SCARG(uap, tptr); 2328 if ((error = getutimes(usrtvp, ts)) != 0) 2329 return (error); 2330 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2331 if ((error = namei(&nd)) != 0) 2332 return (error); 2333 NDFREE(&nd, NDF_ONLY_PNBUF); 2334 error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL); 2335 vrele(nd.ni_vp); 2336 return (error); 2337 } 2338 2339 /* 2340 * Set the access and modification times of a file. 2341 */ 2342 #ifndef _SYS_SYSPROTO_H_ 2343 struct futimes_args { 2344 int fd; 2345 struct timeval *tptr; 2346 }; 2347 #endif 2348 /* ARGSUSED */ 2349 int 2350 futimes(p, uap) 2351 struct proc *p; 2352 register struct futimes_args /* { 2353 syscallarg(int ) fd; 2354 syscallarg(struct timeval *) tptr; 2355 } */ *uap; 2356 { 2357 struct timespec ts[2]; 2358 struct file *fp; 2359 struct timeval *usrtvp; 2360 int error; 2361 2362 usrtvp = SCARG(uap, tptr); 2363 if ((error = getutimes(usrtvp, ts)) != 0) 2364 return (error); 2365 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2366 return (error); 2367 return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL); 2368 } 2369 2370 /* 2371 * Truncate a file given its path name. 2372 */ 2373 #ifndef _SYS_SYSPROTO_H_ 2374 struct truncate_args { 2375 char *path; 2376 int pad; 2377 off_t length; 2378 }; 2379 #endif 2380 /* ARGSUSED */ 2381 int 2382 truncate(p, uap) 2383 struct proc *p; 2384 register struct truncate_args /* { 2385 syscallarg(char *) path; 2386 syscallarg(int) pad; 2387 syscallarg(off_t) length; 2388 } */ *uap; 2389 { 2390 register struct vnode *vp; 2391 struct vattr vattr; 2392 int error; 2393 struct nameidata nd; 2394 2395 if (uap->length < 0) 2396 return(EINVAL); 2397 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2398 if ((error = namei(&nd)) != 0) 2399 return (error); 2400 vp = nd.ni_vp; 2401 NDFREE(&nd, NDF_ONLY_PNBUF); 2402 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2403 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2404 if (vp->v_type == VDIR) 2405 error = EISDIR; 2406 else if ((error = vn_writechk(vp)) == 0 && 2407 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2408 VATTR_NULL(&vattr); 2409 vattr.va_size = SCARG(uap, length); 2410 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2411 } 2412 vput(vp); 2413 return (error); 2414 } 2415 2416 /* 2417 * Truncate a file given a file descriptor. 2418 */ 2419 #ifndef _SYS_SYSPROTO_H_ 2420 struct ftruncate_args { 2421 int fd; 2422 int pad; 2423 off_t length; 2424 }; 2425 #endif 2426 /* ARGSUSED */ 2427 int 2428 ftruncate(p, uap) 2429 struct proc *p; 2430 register struct ftruncate_args /* { 2431 syscallarg(int) fd; 2432 syscallarg(int) pad; 2433 syscallarg(off_t) length; 2434 } */ *uap; 2435 { 2436 struct vattr vattr; 2437 struct vnode *vp; 2438 struct file *fp; 2439 int error; 2440 2441 if (uap->length < 0) 2442 return(EINVAL); 2443 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2444 return (error); 2445 if ((fp->f_flag & FWRITE) == 0) 2446 return (EINVAL); 2447 vp = (struct vnode *)fp->f_data; 2448 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2449 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2450 if (vp->v_type == VDIR) 2451 error = EISDIR; 2452 else if ((error = vn_writechk(vp)) == 0) { 2453 VATTR_NULL(&vattr); 2454 vattr.va_size = SCARG(uap, length); 2455 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2456 } 2457 VOP_UNLOCK(vp, 0, p); 2458 return (error); 2459 } 2460 2461 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2462 /* 2463 * Truncate a file given its path name. 2464 */ 2465 #ifndef _SYS_SYSPROTO_H_ 2466 struct otruncate_args { 2467 char *path; 2468 long length; 2469 }; 2470 #endif 2471 /* ARGSUSED */ 2472 int 2473 otruncate(p, uap) 2474 struct proc *p; 2475 register struct otruncate_args /* { 2476 syscallarg(char *) path; 2477 syscallarg(long) length; 2478 } */ *uap; 2479 { 2480 struct truncate_args /* { 2481 syscallarg(char *) path; 2482 syscallarg(int) pad; 2483 syscallarg(off_t) length; 2484 } */ nuap; 2485 2486 SCARG(&nuap, path) = SCARG(uap, path); 2487 SCARG(&nuap, length) = SCARG(uap, length); 2488 return (truncate(p, &nuap)); 2489 } 2490 2491 /* 2492 * Truncate a file given a file descriptor. 2493 */ 2494 #ifndef _SYS_SYSPROTO_H_ 2495 struct oftruncate_args { 2496 int fd; 2497 long length; 2498 }; 2499 #endif 2500 /* ARGSUSED */ 2501 int 2502 oftruncate(p, uap) 2503 struct proc *p; 2504 register struct oftruncate_args /* { 2505 syscallarg(int) fd; 2506 syscallarg(long) length; 2507 } */ *uap; 2508 { 2509 struct ftruncate_args /* { 2510 syscallarg(int) fd; 2511 syscallarg(int) pad; 2512 syscallarg(off_t) length; 2513 } */ nuap; 2514 2515 SCARG(&nuap, fd) = SCARG(uap, fd); 2516 SCARG(&nuap, length) = SCARG(uap, length); 2517 return (ftruncate(p, &nuap)); 2518 } 2519 #endif /* COMPAT_43 || COMPAT_SUNOS */ 2520 2521 /* 2522 * Sync an open file. 2523 */ 2524 #ifndef _SYS_SYSPROTO_H_ 2525 struct fsync_args { 2526 int fd; 2527 }; 2528 #endif 2529 /* ARGSUSED */ 2530 int 2531 fsync(p, uap) 2532 struct proc *p; 2533 struct fsync_args /* { 2534 syscallarg(int) fd; 2535 } */ *uap; 2536 { 2537 register struct vnode *vp; 2538 struct file *fp; 2539 int error; 2540 2541 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2542 return (error); 2543 vp = (struct vnode *)fp->f_data; 2544 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2545 if (vp->v_object) 2546 vm_object_page_clean(vp->v_object, 0, 0, 0); 2547 if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 && 2548 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) && 2549 bioops.io_fsync) 2550 error = (*bioops.io_fsync)(vp); 2551 VOP_UNLOCK(vp, 0, p); 2552 return (error); 2553 } 2554 2555 /* 2556 * Rename files. Source and destination must either both be directories, 2557 * or both not be directories. If target is a directory, it must be empty. 2558 */ 2559 #ifndef _SYS_SYSPROTO_H_ 2560 struct rename_args { 2561 char *from; 2562 char *to; 2563 }; 2564 #endif 2565 /* ARGSUSED */ 2566 int 2567 rename(p, uap) 2568 struct proc *p; 2569 register struct rename_args /* { 2570 syscallarg(char *) from; 2571 syscallarg(char *) to; 2572 } */ *uap; 2573 { 2574 register struct vnode *tvp, *fvp, *tdvp; 2575 struct nameidata fromnd, tond; 2576 int error; 2577 2578 bwillwrite(); 2579 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2580 SCARG(uap, from), p); 2581 if ((error = namei(&fromnd)) != 0) 2582 return (error); 2583 fvp = fromnd.ni_vp; 2584 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 2585 UIO_USERSPACE, SCARG(uap, to), p); 2586 if (fromnd.ni_vp->v_type == VDIR) 2587 tond.ni_cnd.cn_flags |= WILLBEDIR; 2588 if ((error = namei(&tond)) != 0) { 2589 /* Translate error code for rename("dir1", "dir2/."). */ 2590 if (error == EISDIR && fvp->v_type == VDIR) 2591 error = EINVAL; 2592 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2593 vrele(fromnd.ni_dvp); 2594 vrele(fvp); 2595 goto out1; 2596 } 2597 tdvp = tond.ni_dvp; 2598 tvp = tond.ni_vp; 2599 if (tvp != NULL) { 2600 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2601 error = ENOTDIR; 2602 goto out; 2603 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2604 error = EISDIR; 2605 goto out; 2606 } 2607 } 2608 if (fvp == tdvp) 2609 error = EINVAL; 2610 /* 2611 * If source is the same as the destination (that is the 2612 * same inode number with the same name in the same directory), 2613 * then there is nothing to do. 2614 */ 2615 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2616 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2617 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2618 fromnd.ni_cnd.cn_namelen)) 2619 error = -1; 2620 out: 2621 if (!error) { 2622 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2623 if (fromnd.ni_dvp != tdvp) { 2624 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2625 } 2626 if (tvp) { 2627 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2628 } 2629 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2630 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2631 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2632 NDFREE(&tond, NDF_ONLY_PNBUF); 2633 } else { 2634 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2635 NDFREE(&tond, NDF_ONLY_PNBUF); 2636 if (tdvp == tvp) 2637 vrele(tdvp); 2638 else 2639 vput(tdvp); 2640 if (tvp) 2641 vput(tvp); 2642 vrele(fromnd.ni_dvp); 2643 vrele(fvp); 2644 } 2645 vrele(tond.ni_startdir); 2646 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2647 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2648 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2649 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2650 out1: 2651 if (fromnd.ni_startdir) 2652 vrele(fromnd.ni_startdir); 2653 if (error == -1) 2654 return (0); 2655 return (error); 2656 } 2657 2658 /* 2659 * Make a directory file. 2660 */ 2661 #ifndef _SYS_SYSPROTO_H_ 2662 struct mkdir_args { 2663 char *path; 2664 int mode; 2665 }; 2666 #endif 2667 /* ARGSUSED */ 2668 int 2669 mkdir(p, uap) 2670 struct proc *p; 2671 register struct mkdir_args /* { 2672 syscallarg(char *) path; 2673 syscallarg(int) mode; 2674 } */ *uap; 2675 { 2676 register struct vnode *vp; 2677 struct vattr vattr; 2678 int error; 2679 struct nameidata nd; 2680 2681 bwillwrite(); 2682 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2683 nd.ni_cnd.cn_flags |= WILLBEDIR; 2684 if ((error = namei(&nd)) != 0) 2685 return (error); 2686 vp = nd.ni_vp; 2687 if (vp != NULL) { 2688 NDFREE(&nd, NDF_ONLY_PNBUF); 2689 if (nd.ni_dvp == vp) 2690 vrele(nd.ni_dvp); 2691 else 2692 vput(nd.ni_dvp); 2693 vrele(vp); 2694 return (EEXIST); 2695 } 2696 VATTR_NULL(&vattr); 2697 vattr.va_type = VDIR; 2698 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2699 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2700 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2701 NDFREE(&nd, NDF_ONLY_PNBUF); 2702 vput(nd.ni_dvp); 2703 if (!error) 2704 vput(nd.ni_vp); 2705 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2706 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2707 return (error); 2708 } 2709 2710 /* 2711 * Remove a directory file. 2712 */ 2713 #ifndef _SYS_SYSPROTO_H_ 2714 struct rmdir_args { 2715 char *path; 2716 }; 2717 #endif 2718 /* ARGSUSED */ 2719 int 2720 rmdir(p, uap) 2721 struct proc *p; 2722 struct rmdir_args /* { 2723 syscallarg(char *) path; 2724 } */ *uap; 2725 { 2726 register struct vnode *vp; 2727 int error; 2728 struct nameidata nd; 2729 2730 bwillwrite(); 2731 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2732 SCARG(uap, path), p); 2733 if ((error = namei(&nd)) != 0) 2734 return (error); 2735 vp = nd.ni_vp; 2736 if (vp->v_type != VDIR) { 2737 error = ENOTDIR; 2738 goto out; 2739 } 2740 /* 2741 * No rmdir "." please. 2742 */ 2743 if (nd.ni_dvp == vp) { 2744 error = EINVAL; 2745 goto out; 2746 } 2747 /* 2748 * The root of a mounted filesystem cannot be deleted. 2749 */ 2750 if (vp->v_flag & VROOT) 2751 error = EBUSY; 2752 else { 2753 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2754 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2755 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2756 } 2757 out: 2758 NDFREE(&nd, NDF_ONLY_PNBUF); 2759 if (nd.ni_dvp == vp) 2760 vrele(nd.ni_dvp); 2761 else 2762 vput(nd.ni_dvp); 2763 if (vp != NULLVP) 2764 vput(vp); 2765 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 2766 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 2767 return (error); 2768 } 2769 2770 #ifdef COMPAT_43 2771 /* 2772 * Read a block of directory entries in a file system independent format. 2773 */ 2774 #ifndef _SYS_SYSPROTO_H_ 2775 struct ogetdirentries_args { 2776 int fd; 2777 char *buf; 2778 u_int count; 2779 long *basep; 2780 }; 2781 #endif 2782 int 2783 ogetdirentries(p, uap) 2784 struct proc *p; 2785 register struct ogetdirentries_args /* { 2786 syscallarg(int) fd; 2787 syscallarg(char *) buf; 2788 syscallarg(u_int) count; 2789 syscallarg(long *) basep; 2790 } */ *uap; 2791 { 2792 struct vnode *vp; 2793 struct file *fp; 2794 struct uio auio, kuio; 2795 struct iovec aiov, kiov; 2796 struct dirent *dp, *edp; 2797 caddr_t dirbuf; 2798 int error, eofflag, readcnt; 2799 long loff; 2800 2801 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2802 return (error); 2803 if ((fp->f_flag & FREAD) == 0) 2804 return (EBADF); 2805 vp = (struct vnode *)fp->f_data; 2806 unionread: 2807 if (vp->v_type != VDIR) 2808 return (EINVAL); 2809 aiov.iov_base = SCARG(uap, buf); 2810 aiov.iov_len = SCARG(uap, count); 2811 auio.uio_iov = &aiov; 2812 auio.uio_iovcnt = 1; 2813 auio.uio_rw = UIO_READ; 2814 auio.uio_segflg = UIO_USERSPACE; 2815 auio.uio_procp = p; 2816 auio.uio_resid = SCARG(uap, count); 2817 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2818 loff = auio.uio_offset = fp->f_offset; 2819 # if (BYTE_ORDER != LITTLE_ENDIAN) 2820 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2821 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2822 NULL, NULL); 2823 fp->f_offset = auio.uio_offset; 2824 } else 2825 # endif 2826 { 2827 kuio = auio; 2828 kuio.uio_iov = &kiov; 2829 kuio.uio_segflg = UIO_SYSSPACE; 2830 kiov.iov_len = SCARG(uap, count); 2831 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2832 kiov.iov_base = dirbuf; 2833 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2834 NULL, NULL); 2835 fp->f_offset = kuio.uio_offset; 2836 if (error == 0) { 2837 readcnt = SCARG(uap, count) - kuio.uio_resid; 2838 edp = (struct dirent *)&dirbuf[readcnt]; 2839 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2840 # if (BYTE_ORDER == LITTLE_ENDIAN) 2841 /* 2842 * The expected low byte of 2843 * dp->d_namlen is our dp->d_type. 2844 * The high MBZ byte of dp->d_namlen 2845 * is our dp->d_namlen. 2846 */ 2847 dp->d_type = dp->d_namlen; 2848 dp->d_namlen = 0; 2849 # else 2850 /* 2851 * The dp->d_type is the high byte 2852 * of the expected dp->d_namlen, 2853 * so must be zero'ed. 2854 */ 2855 dp->d_type = 0; 2856 # endif 2857 if (dp->d_reclen > 0) { 2858 dp = (struct dirent *) 2859 ((char *)dp + dp->d_reclen); 2860 } else { 2861 error = EIO; 2862 break; 2863 } 2864 } 2865 if (dp >= edp) 2866 error = uiomove(dirbuf, readcnt, &auio); 2867 } 2868 FREE(dirbuf, M_TEMP); 2869 } 2870 VOP_UNLOCK(vp, 0, p); 2871 if (error) 2872 return (error); 2873 if (SCARG(uap, count) == auio.uio_resid) { 2874 if (union_dircheckp) { 2875 error = union_dircheckp(p, &vp, fp); 2876 if (error == -1) 2877 goto unionread; 2878 if (error) 2879 return (error); 2880 } 2881 if ((vp->v_flag & VROOT) && 2882 (vp->v_mount->mnt_flag & MNT_UNION)) { 2883 struct vnode *tvp = vp; 2884 vp = vp->v_mount->mnt_vnodecovered; 2885 VREF(vp); 2886 fp->f_data = (caddr_t) vp; 2887 fp->f_offset = 0; 2888 vrele(tvp); 2889 goto unionread; 2890 } 2891 } 2892 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2893 sizeof(long)); 2894 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2895 return (error); 2896 } 2897 #endif /* COMPAT_43 */ 2898 2899 /* 2900 * Read a block of directory entries in a file system independent format. 2901 */ 2902 #ifndef _SYS_SYSPROTO_H_ 2903 struct getdirentries_args { 2904 int fd; 2905 char *buf; 2906 u_int count; 2907 long *basep; 2908 }; 2909 #endif 2910 int 2911 getdirentries(p, uap) 2912 struct proc *p; 2913 register struct getdirentries_args /* { 2914 syscallarg(int) fd; 2915 syscallarg(char *) buf; 2916 syscallarg(u_int) count; 2917 syscallarg(long *) basep; 2918 } */ *uap; 2919 { 2920 struct vnode *vp; 2921 struct file *fp; 2922 struct uio auio; 2923 struct iovec aiov; 2924 long loff; 2925 int error, eofflag; 2926 2927 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2928 return (error); 2929 if ((fp->f_flag & FREAD) == 0) 2930 return (EBADF); 2931 vp = (struct vnode *)fp->f_data; 2932 unionread: 2933 if (vp->v_type != VDIR) 2934 return (EINVAL); 2935 aiov.iov_base = SCARG(uap, buf); 2936 aiov.iov_len = SCARG(uap, count); 2937 auio.uio_iov = &aiov; 2938 auio.uio_iovcnt = 1; 2939 auio.uio_rw = UIO_READ; 2940 auio.uio_segflg = UIO_USERSPACE; 2941 auio.uio_procp = p; 2942 auio.uio_resid = SCARG(uap, count); 2943 /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */ 2944 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2945 loff = auio.uio_offset = fp->f_offset; 2946 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2947 fp->f_offset = auio.uio_offset; 2948 VOP_UNLOCK(vp, 0, p); 2949 if (error) 2950 return (error); 2951 if (SCARG(uap, count) == auio.uio_resid) { 2952 if (union_dircheckp) { 2953 error = union_dircheckp(p, &vp, fp); 2954 if (error == -1) 2955 goto unionread; 2956 if (error) 2957 return (error); 2958 } 2959 if ((vp->v_flag & VROOT) && 2960 (vp->v_mount->mnt_flag & MNT_UNION)) { 2961 struct vnode *tvp = vp; 2962 vp = vp->v_mount->mnt_vnodecovered; 2963 VREF(vp); 2964 fp->f_data = (caddr_t) vp; 2965 fp->f_offset = 0; 2966 vrele(tvp); 2967 goto unionread; 2968 } 2969 } 2970 if (SCARG(uap, basep) != NULL) { 2971 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2972 sizeof(long)); 2973 } 2974 p->p_retval[0] = SCARG(uap, count) - auio.uio_resid; 2975 return (error); 2976 } 2977 #ifndef _SYS_SYSPROTO_H_ 2978 struct getdents_args { 2979 int fd; 2980 char *buf; 2981 size_t count; 2982 }; 2983 #endif 2984 int 2985 getdents(p, uap) 2986 struct proc *p; 2987 register struct getdents_args /* { 2988 syscallarg(int) fd; 2989 syscallarg(char *) buf; 2990 syscallarg(u_int) count; 2991 } */ *uap; 2992 { 2993 struct getdirentries_args ap; 2994 ap.fd = uap->fd; 2995 ap.buf = uap->buf; 2996 ap.count = uap->count; 2997 ap.basep = NULL; 2998 return getdirentries(p, &ap); 2999 } 3000 3001 /* 3002 * Set the mode mask for creation of filesystem nodes. 3003 * 3004 * MP SAFE 3005 */ 3006 #ifndef _SYS_SYSPROTO_H_ 3007 struct umask_args { 3008 int newmask; 3009 }; 3010 #endif 3011 int 3012 umask(p, uap) 3013 struct proc *p; 3014 struct umask_args /* { 3015 syscallarg(int) newmask; 3016 } */ *uap; 3017 { 3018 register struct filedesc *fdp; 3019 3020 fdp = p->p_fd; 3021 p->p_retval[0] = fdp->fd_cmask; 3022 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 3023 return (0); 3024 } 3025 3026 /* 3027 * Void all references to file by ripping underlying filesystem 3028 * away from vnode. 3029 */ 3030 #ifndef _SYS_SYSPROTO_H_ 3031 struct revoke_args { 3032 char *path; 3033 }; 3034 #endif 3035 /* ARGSUSED */ 3036 int 3037 revoke(p, uap) 3038 struct proc *p; 3039 register struct revoke_args /* { 3040 syscallarg(char *) path; 3041 } */ *uap; 3042 { 3043 register struct vnode *vp; 3044 struct vattr vattr; 3045 int error; 3046 struct nameidata nd; 3047 3048 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 3049 if ((error = namei(&nd)) != 0) 3050 return (error); 3051 vp = nd.ni_vp; 3052 NDFREE(&nd, NDF_ONLY_PNBUF); 3053 if (vp->v_type != VCHR && vp->v_type != VBLK) { 3054 error = EINVAL; 3055 goto out; 3056 } 3057 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 3058 goto out; 3059 if (p->p_ucred->cr_uid != vattr.va_uid && 3060 (error = suser_xxx(0, p, PRISON_ROOT))) 3061 goto out; 3062 if (vcount(vp) > 1) 3063 VOP_REVOKE(vp, REVOKEALL); 3064 out: 3065 vrele(vp); 3066 return (error); 3067 } 3068 3069 /* 3070 * Convert a user file descriptor to a kernel file entry. 3071 */ 3072 int 3073 getvnode(fdp, fd, fpp) 3074 struct filedesc *fdp; 3075 int fd; 3076 struct file **fpp; 3077 { 3078 struct file *fp; 3079 3080 if ((u_int)fd >= fdp->fd_nfiles || 3081 (fp = fdp->fd_ofiles[fd]) == NULL) 3082 return (EBADF); 3083 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 3084 return (EINVAL); 3085 *fpp = fp; 3086 return (0); 3087 } 3088 /* 3089 * Get (NFS) file handle 3090 */ 3091 #ifndef _SYS_SYSPROTO_H_ 3092 struct getfh_args { 3093 char *fname; 3094 fhandle_t *fhp; 3095 }; 3096 #endif 3097 int 3098 getfh(p, uap) 3099 struct proc *p; 3100 register struct getfh_args *uap; 3101 { 3102 struct nameidata nd; 3103 fhandle_t fh; 3104 register struct vnode *vp; 3105 int error; 3106 3107 /* 3108 * Must be super user 3109 */ 3110 error = suser(p); 3111 if (error) 3112 return (error); 3113 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 3114 error = namei(&nd); 3115 if (error) 3116 return (error); 3117 NDFREE(&nd, NDF_ONLY_PNBUF); 3118 vp = nd.ni_vp; 3119 bzero(&fh, sizeof(fh)); 3120 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3121 error = VFS_VPTOFH(vp, &fh.fh_fid); 3122 vput(vp); 3123 if (error) 3124 return (error); 3125 error = copyout(&fh, uap->fhp, sizeof (fh)); 3126 return (error); 3127 } 3128 3129 /* 3130 * syscall for the rpc.lockd to use to translate a NFS file handle into 3131 * an open descriptor. 3132 * 3133 * warning: do not remove the suser() call or this becomes one giant 3134 * security hole. 3135 */ 3136 #ifndef _SYS_SYSPROTO_H_ 3137 struct fhopen_args { 3138 const struct fhandle *u_fhp; 3139 int flags; 3140 }; 3141 #endif 3142 int 3143 fhopen(p, uap) 3144 struct proc *p; 3145 struct fhopen_args /* { 3146 syscallarg(const struct fhandle *) u_fhp; 3147 syscallarg(int) flags; 3148 } */ *uap; 3149 { 3150 struct mount *mp; 3151 struct vnode *vp; 3152 struct fhandle fhp; 3153 struct vattr vat; 3154 struct vattr *vap = &vat; 3155 struct flock lf; 3156 struct file *fp; 3157 register struct filedesc *fdp = p->p_fd; 3158 int fmode, mode, error, type; 3159 struct file *nfp; 3160 int indx; 3161 3162 /* 3163 * Must be super user 3164 */ 3165 error = suser(p); 3166 if (error) 3167 return (error); 3168 3169 fmode = FFLAGS(SCARG(uap, flags)); 3170 /* why not allow a non-read/write open for our lockd? */ 3171 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3172 return (EINVAL); 3173 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); 3174 if (error) 3175 return(error); 3176 /* find the mount point */ 3177 mp = vfs_getvfs(&fhp.fh_fsid); 3178 if (mp == NULL) 3179 return (ESTALE); 3180 /* now give me my vnode, it gets returned to me locked */ 3181 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3182 if (error) 3183 return (error); 3184 /* 3185 * from now on we have to make sure not 3186 * to forget about the vnode 3187 * any error that causes an abort must vput(vp) 3188 * just set error = err and 'goto bad;'. 3189 */ 3190 3191 /* 3192 * from vn_open 3193 */ 3194 if (vp->v_type == VLNK) { 3195 error = EMLINK; 3196 goto bad; 3197 } 3198 if (vp->v_type == VSOCK) { 3199 error = EOPNOTSUPP; 3200 goto bad; 3201 } 3202 mode = 0; 3203 if (fmode & (FWRITE | O_TRUNC)) { 3204 if (vp->v_type == VDIR) { 3205 error = EISDIR; 3206 goto bad; 3207 } 3208 error = vn_writechk(vp); 3209 if (error) 3210 goto bad; 3211 mode |= VWRITE; 3212 } 3213 if (fmode & FREAD) 3214 mode |= VREAD; 3215 if (mode) { 3216 error = VOP_ACCESS(vp, mode, p->p_ucred, p); 3217 if (error) 3218 goto bad; 3219 } 3220 if (fmode & O_TRUNC) { 3221 VOP_UNLOCK(vp, 0, p); /* XXX */ 3222 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 3223 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ 3224 VATTR_NULL(vap); 3225 vap->va_size = 0; 3226 error = VOP_SETATTR(vp, vap, p->p_ucred, p); 3227 if (error) 3228 goto bad; 3229 } 3230 error = VOP_OPEN(vp, fmode, p->p_ucred, p); 3231 if (error) 3232 goto bad; 3233 /* 3234 * Make sure that a VM object is created for VMIO support. 3235 */ 3236 if (vn_canvmio(vp) == TRUE) { 3237 if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0) 3238 goto bad; 3239 } 3240 if (fmode & FWRITE) 3241 vp->v_writecount++; 3242 3243 /* 3244 * end of vn_open code 3245 */ 3246 3247 if ((error = falloc(p, &nfp, &indx)) != 0) 3248 goto bad; 3249 fp = nfp; 3250 nfp->f_data = (caddr_t)vp; 3251 nfp->f_flag = fmode & FMASK; 3252 nfp->f_ops = &vnops; 3253 nfp->f_type = DTYPE_VNODE; 3254 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3255 lf.l_whence = SEEK_SET; 3256 lf.l_start = 0; 3257 lf.l_len = 0; 3258 if (fmode & O_EXLOCK) 3259 lf.l_type = F_WRLCK; 3260 else 3261 lf.l_type = F_RDLCK; 3262 type = F_FLOCK; 3263 if ((fmode & FNONBLOCK) == 0) 3264 type |= F_WAIT; 3265 VOP_UNLOCK(vp, 0, p); 3266 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 3267 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 3268 ffree(fp); 3269 fdp->fd_ofiles[indx] = NULL; 3270 return (error); 3271 } 3272 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 3273 fp->f_flag |= FHASLOCK; 3274 } 3275 if ((vp->v_type == VREG) && (vp->v_object == NULL)) 3276 vfs_object_create(vp, p, p->p_ucred); 3277 3278 VOP_UNLOCK(vp, 0, p); 3279 p->p_retval[0] = indx; 3280 return (0); 3281 3282 bad: 3283 vput(vp); 3284 return (error); 3285 } 3286 3287 #ifndef _SYS_SYSPROTO_H_ 3288 struct fhstat_args { 3289 struct fhandle *u_fhp; 3290 struct stat *sb; 3291 }; 3292 #endif 3293 int 3294 fhstat(p, uap) 3295 struct proc *p; 3296 register struct fhstat_args /* { 3297 syscallarg(struct fhandle *) u_fhp; 3298 syscallarg(struct stat *) sb; 3299 } */ *uap; 3300 { 3301 struct stat sb; 3302 fhandle_t fh; 3303 struct mount *mp; 3304 struct vnode *vp; 3305 int error; 3306 3307 /* 3308 * Must be super user 3309 */ 3310 error = suser(p); 3311 if (error) 3312 return (error); 3313 3314 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); 3315 if (error) 3316 return (error); 3317 3318 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3319 return (ESTALE); 3320 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3321 return (error); 3322 error = vn_stat(vp, &sb, p); 3323 vput(vp); 3324 if (error) 3325 return (error); 3326 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 3327 return (error); 3328 } 3329 3330 #ifndef _SYS_SYSPROTO_H_ 3331 struct fhstatfs_args { 3332 struct fhandle *u_fhp; 3333 struct statfs *buf; 3334 }; 3335 #endif 3336 int 3337 fhstatfs(p, uap) 3338 struct proc *p; 3339 struct fhstatfs_args /* { 3340 syscallarg(struct fhandle) *u_fhp; 3341 syscallarg(struct statfs) *buf; 3342 } */ *uap; 3343 { 3344 struct statfs *sp; 3345 struct mount *mp; 3346 struct vnode *vp; 3347 struct statfs sb; 3348 fhandle_t fh; 3349 int error; 3350 3351 /* 3352 * Must be super user 3353 */ 3354 if ((error = suser(p))) 3355 return (error); 3356 3357 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) 3358 return (error); 3359 3360 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3361 return (ESTALE); 3362 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3363 return (error); 3364 mp = vp->v_mount; 3365 sp = &mp->mnt_stat; 3366 vput(vp); 3367 if ((error = VFS_STATFS(mp, sp, p)) != 0) 3368 return (error); 3369 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3370 if (suser_xxx(p->p_ucred, 0, 0)) { 3371 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 3372 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3373 sp = &sb; 3374 } 3375 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 3376 } 3377 3378 /* 3379 * Syscall to push extended attribute configuration information into the 3380 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3381 * a command (int cmd), and attribute name and misc data. For now, the 3382 * attribute name is left in userspace for consumption by the VFS_op. 3383 * It will probably be changed to be copied into sysspace by the 3384 * syscall in the future, once issues with various consumers of the 3385 * attribute code have raised their hands. 3386 * 3387 * Currently this is used only by UFS Extended Attributes. 3388 */ 3389 int 3390 extattrctl(p, uap) 3391 struct proc *p; 3392 struct extattrctl_args *uap; 3393 { 3394 struct nameidata nd; 3395 struct mount *mp; 3396 int error; 3397 3398 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 3399 if ((error = namei(&nd)) != 0) 3400 return (error); 3401 mp = nd.ni_vp->v_mount; 3402 NDFREE(&nd, 0); 3403 return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname), 3404 SCARG(uap, arg), p)); 3405 } 3406 3407 /* 3408 * Syscall to set a named extended attribute on a file or directory. 3409 * Accepts attribute name, and a uio structure pointing to the data to set. 3410 * The uio is consumed in the style of writev(). The real work happens 3411 * in VOP_SETEXTATTR(). 3412 */ 3413 int 3414 extattr_set_file(p, uap) 3415 struct proc *p; 3416 struct extattr_set_file_args *uap; 3417 { 3418 struct nameidata nd; 3419 struct uio auio; 3420 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 3421 char attrname[EXTATTR_MAXNAMELEN]; 3422 u_int iovlen, cnt; 3423 int error, i; 3424 3425 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); 3426 if (error) 3427 return (error); 3428 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path), 3429 p); 3430 if ((error = namei(&nd)) != 0) 3431 return(error); 3432 iovlen = uap->iovcnt * sizeof(struct iovec); 3433 if (uap->iovcnt > UIO_SMALLIOV) { 3434 if (uap->iovcnt > UIO_MAXIOV) { 3435 error = EINVAL; 3436 goto done; 3437 } 3438 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3439 needfree = iov; 3440 } else 3441 iov = aiov; 3442 auio.uio_iov = iov; 3443 auio.uio_iovcnt = uap->iovcnt; 3444 auio.uio_rw = UIO_WRITE; 3445 auio.uio_segflg = UIO_USERSPACE; 3446 auio.uio_procp = p; 3447 auio.uio_offset = 0; 3448 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) 3449 goto done; 3450 auio.uio_resid = 0; 3451 for (i = 0; i < uap->iovcnt; i++) { 3452 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3453 error = EINVAL; 3454 goto done; 3455 } 3456 auio.uio_resid += iov->iov_len; 3457 iov++; 3458 } 3459 cnt = auio.uio_resid; 3460 error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred, 3461 p); 3462 if (auio.uio_resid != cnt && (error == ERESTART || 3463 error == EINTR || error == EWOULDBLOCK)) 3464 error = 0; 3465 cnt -= auio.uio_resid; 3466 p->p_retval[0] = cnt; 3467 done: 3468 if (needfree) 3469 FREE(needfree, M_IOV); 3470 NDFREE(&nd, 0); 3471 return (error); 3472 } 3473 3474 /* 3475 * Syscall to get a named extended attribute on a file or directory. 3476 * Accepts attribute name, and a uio structure pointing to a buffer for the 3477 * data. The uio is consumed in the style of readv(). The real work 3478 * happens in VOP_GETEXTATTR(); 3479 */ 3480 int 3481 extattr_get_file(p, uap) 3482 struct proc *p; 3483 struct extattr_get_file_args *uap; 3484 { 3485 struct nameidata nd; 3486 struct uio auio; 3487 struct iovec *iov, *needfree, aiov[UIO_SMALLIOV]; 3488 char attrname[EXTATTR_MAXNAMELEN]; 3489 u_int iovlen, cnt; 3490 int error, i; 3491 3492 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); 3493 if (error) 3494 return (error); 3495 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 3496 if ((error = namei(&nd)) != 0) 3497 return (error); 3498 iovlen = uap->iovcnt * sizeof (struct iovec); 3499 if (uap->iovcnt > UIO_SMALLIOV) { 3500 if (uap->iovcnt > UIO_MAXIOV) { 3501 NDFREE(&nd, 0); 3502 return (EINVAL); 3503 } 3504 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3505 needfree = iov; 3506 } else { 3507 iov = aiov; 3508 needfree = NULL; 3509 } 3510 auio.uio_iov = iov; 3511 auio.uio_iovcnt = uap->iovcnt; 3512 auio.uio_rw = UIO_READ; 3513 auio.uio_segflg = UIO_USERSPACE; 3514 auio.uio_procp = p; 3515 auio.uio_offset = 0; 3516 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))) 3517 goto done; 3518 auio.uio_resid = 0; 3519 for (i = 0; i < uap->iovcnt; i++) { 3520 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3521 error = EINVAL; 3522 goto done; 3523 } 3524 auio.uio_resid += iov->iov_len; 3525 iov++; 3526 } 3527 cnt = auio.uio_resid; 3528 error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred, 3529 p); 3530 if (auio.uio_resid != cnt && (error == ERESTART || 3531 error == EINTR || error == EWOULDBLOCK)) 3532 error = 0; 3533 cnt -= auio.uio_resid; 3534 p->p_retval[0] = cnt; 3535 done: 3536 if (needfree) 3537 FREE(needfree, M_IOV); 3538 NDFREE(&nd, 0); 3539 return(error); 3540 } 3541 3542 /* 3543 * Syscall to delete a named extended attribute from a file or directory. 3544 * Accepts attribute name. The real work happens in VOP_SETEXTATTR(). 3545 */ 3546 int 3547 extattr_delete_file(p, uap) 3548 struct proc *p; 3549 struct extattr_delete_file_args *uap; 3550 { 3551 struct nameidata nd; 3552 char attrname[EXTATTR_MAXNAMELEN]; 3553 int error; 3554 3555 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN); 3556 if (error) 3557 return(error); 3558 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path), 3559 p); 3560 if ((error = namei(&nd)) != 0) 3561 return(error); 3562 error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred, 3563 p); 3564 NDFREE(&nd, 0); 3565 return(error); 3566 } 3567