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