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