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