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