vfs_extattr.c revision 116601
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 39 */ 40 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD: head/sys/kern/vfs_extattr.c 116601 2003-06-20 08:02:30Z phk $"); 43 44/* For 4.3 integer FS ID compatibility */ 45#include "opt_compat.h" 46#include "opt_mac.h" 47 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/bio.h> 51#include <sys/buf.h> 52#include <sys/sysent.h> 53#include <sys/mac.h> 54#include <sys/malloc.h> 55#include <sys/mount.h> 56#include <sys/mutex.h> 57#include <sys/sysproto.h> 58#include <sys/namei.h> 59#include <sys/filedesc.h> 60#include <sys/kernel.h> 61#include <sys/fcntl.h> 62#include <sys/file.h> 63#include <sys/limits.h> 64#include <sys/linker.h> 65#include <sys/stat.h> 66#include <sys/sx.h> 67#include <sys/unistd.h> 68#include <sys/vnode.h> 69#include <sys/proc.h> 70#include <sys/dirent.h> 71#include <sys/extattr.h> 72#include <sys/jail.h> 73#include <sys/syscallsubr.h> 74#include <sys/sysctl.h> 75 76#include <machine/stdarg.h> 77 78#include <vm/vm.h> 79#include <vm/vm_object.h> 80#include <vm/vm_page.h> 81#include <vm/uma.h> 82 83static int chroot_refuse_vdir_fds(struct filedesc *fdp); 84static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); 85static int setfown(struct thread *td, struct vnode *, uid_t, gid_t); 86static int setfmode(struct thread *td, struct vnode *, int); 87static int setfflags(struct thread *td, struct vnode *, int); 88static int setutimes(struct thread *td, struct vnode *, 89 const struct timespec *, int, int); 90static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred, 91 struct thread *td); 92 93static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, 94 size_t nbytes, struct thread *td); 95 96int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *); 97int (*softdep_fsync_hook)(struct vnode *); 98 99/* 100 * The module initialization routine for POSIX asynchronous I/O will 101 * set this to the version of AIO that it implements. (Zero means 102 * that it is not implemented.) This value is used here by pathconf() 103 * and in kern_descrip.c by fpathconf(). 104 */ 105int async_io_version; 106 107/* 108 * Sync each mounted filesystem. 109 */ 110#ifndef _SYS_SYSPROTO_H_ 111struct sync_args { 112 int dummy; 113}; 114#endif 115 116#ifdef DEBUG 117static int syncprt = 0; 118SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 119#endif 120 121/* ARGSUSED */ 122int 123sync(td, uap) 124 struct thread *td; 125 struct sync_args *uap; 126{ 127 struct mount *mp, *nmp; 128 int asyncflag; 129 130 mtx_lock(&mountlist_mtx); 131 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 132 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 133 nmp = TAILQ_NEXT(mp, mnt_list); 134 continue; 135 } 136 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 137 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 138 asyncflag = mp->mnt_flag & MNT_ASYNC; 139 mp->mnt_flag &= ~MNT_ASYNC; 140 vfs_msync(mp, MNT_NOWAIT); 141 VFS_SYNC(mp, MNT_NOWAIT, 142 ((td != NULL) ? td->td_ucred : NOCRED), td); 143 mp->mnt_flag |= asyncflag; 144 vn_finished_write(mp); 145 } 146 mtx_lock(&mountlist_mtx); 147 nmp = TAILQ_NEXT(mp, mnt_list); 148 vfs_unbusy(mp, td); 149 } 150 mtx_unlock(&mountlist_mtx); 151#if 0 152/* 153 * XXX don't call vfs_bufstats() yet because that routine 154 * was not imported in the Lite2 merge. 155 */ 156#ifdef DIAGNOSTIC 157 if (syncprt) 158 vfs_bufstats(); 159#endif /* DIAGNOSTIC */ 160#endif 161 return (0); 162} 163 164/* XXX PRISON: could be per prison flag */ 165static int prison_quotas; 166#if 0 167SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 168#endif 169 170/* 171 * Change filesystem quotas. 172 */ 173#ifndef _SYS_SYSPROTO_H_ 174struct quotactl_args { 175 char *path; 176 int cmd; 177 int uid; 178 caddr_t arg; 179}; 180#endif 181/* ARGSUSED */ 182int 183quotactl(td, uap) 184 struct thread *td; 185 register struct quotactl_args /* { 186 char *path; 187 int cmd; 188 int uid; 189 caddr_t arg; 190 } */ *uap; 191{ 192 struct mount *mp; 193 int error; 194 struct nameidata nd; 195 196 if (jailed(td->td_ucred) && !prison_quotas) 197 return (EPERM); 198 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 199 if ((error = namei(&nd)) != 0) 200 return (error); 201 NDFREE(&nd, NDF_ONLY_PNBUF); 202 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 203 vrele(nd.ni_vp); 204 if (error) 205 return (error); 206 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td); 207 vn_finished_write(mp); 208 return (error); 209} 210 211/* 212 * Get filesystem statistics. 213 */ 214#ifndef _SYS_SYSPROTO_H_ 215struct statfs_args { 216 char *path; 217 struct statfs *buf; 218}; 219#endif 220/* ARGSUSED */ 221int 222statfs(td, uap) 223 struct thread *td; 224 register struct statfs_args /* { 225 char *path; 226 struct statfs *buf; 227 } */ *uap; 228{ 229 register struct mount *mp; 230 register struct statfs *sp; 231 int error; 232 struct nameidata nd; 233 struct statfs sb; 234 235 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 236 if ((error = namei(&nd)) != 0) 237 return (error); 238 mp = nd.ni_vp->v_mount; 239 sp = &mp->mnt_stat; 240 NDFREE(&nd, NDF_ONLY_PNBUF); 241 vrele(nd.ni_vp); 242#ifdef MAC 243 error = mac_check_mount_stat(td->td_ucred, mp); 244 if (error) 245 return (error); 246#endif 247 error = VFS_STATFS(mp, sp, td); 248 if (error) 249 return (error); 250 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 251 if (suser(td)) { 252 bcopy(sp, &sb, sizeof(sb)); 253 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 254 sp = &sb; 255 } 256 return (copyout(sp, uap->buf, sizeof(*sp))); 257} 258 259/* 260 * Get filesystem statistics. 261 */ 262#ifndef _SYS_SYSPROTO_H_ 263struct fstatfs_args { 264 int fd; 265 struct statfs *buf; 266}; 267#endif 268/* ARGSUSED */ 269int 270fstatfs(td, uap) 271 struct thread *td; 272 register struct fstatfs_args /* { 273 int fd; 274 struct statfs *buf; 275 } */ *uap; 276{ 277 struct file *fp; 278 struct mount *mp; 279 register struct statfs *sp; 280 int error; 281 struct statfs sb; 282 283 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 284 return (error); 285 mp = ((struct vnode *)fp->f_data)->v_mount; 286 fdrop(fp, td); 287 if (mp == NULL) 288 return (EBADF); 289#ifdef MAC 290 error = mac_check_mount_stat(td->td_ucred, mp); 291 if (error) 292 return (error); 293#endif 294 sp = &mp->mnt_stat; 295 error = VFS_STATFS(mp, sp, td); 296 if (error) 297 return (error); 298 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 299 if (suser(td)) { 300 bcopy(sp, &sb, sizeof(sb)); 301 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 302 sp = &sb; 303 } 304 return (copyout(sp, uap->buf, sizeof(*sp))); 305} 306 307/* 308 * Get statistics on all filesystems. 309 */ 310#ifndef _SYS_SYSPROTO_H_ 311struct getfsstat_args { 312 struct statfs *buf; 313 long bufsize; 314 int flags; 315}; 316#endif 317int 318getfsstat(td, uap) 319 struct thread *td; 320 register struct getfsstat_args /* { 321 struct statfs *buf; 322 long bufsize; 323 int flags; 324 } */ *uap; 325{ 326 register struct mount *mp, *nmp; 327 register struct statfs *sp; 328 caddr_t sfsp; 329 long count, maxcount, error; 330 331 maxcount = uap->bufsize / sizeof(struct statfs); 332 sfsp = (caddr_t)uap->buf; 333 count = 0; 334 mtx_lock(&mountlist_mtx); 335 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 336#ifdef MAC 337 if (mac_check_mount_stat(td->td_ucred, mp) != 0) { 338 nmp = TAILQ_NEXT(mp, mnt_list); 339 continue; 340 } 341#endif 342 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 343 nmp = TAILQ_NEXT(mp, mnt_list); 344 continue; 345 } 346 if (sfsp && count < maxcount) { 347 sp = &mp->mnt_stat; 348 /* 349 * If MNT_NOWAIT or MNT_LAZY is specified, do not 350 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 351 * overrides MNT_WAIT. 352 */ 353 if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 354 (uap->flags & MNT_WAIT)) && 355 (error = VFS_STATFS(mp, sp, td))) { 356 mtx_lock(&mountlist_mtx); 357 nmp = TAILQ_NEXT(mp, mnt_list); 358 vfs_unbusy(mp, td); 359 continue; 360 } 361 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 362 error = copyout(sp, sfsp, sizeof(*sp)); 363 if (error) { 364 vfs_unbusy(mp, td); 365 return (error); 366 } 367 sfsp += sizeof(*sp); 368 } 369 count++; 370 mtx_lock(&mountlist_mtx); 371 nmp = TAILQ_NEXT(mp, mnt_list); 372 vfs_unbusy(mp, td); 373 } 374 mtx_unlock(&mountlist_mtx); 375 if (sfsp && count > maxcount) 376 td->td_retval[0] = maxcount; 377 else 378 td->td_retval[0] = count; 379 return (0); 380} 381 382/* 383 * Change current working directory to a given file descriptor. 384 */ 385#ifndef _SYS_SYSPROTO_H_ 386struct fchdir_args { 387 int fd; 388}; 389#endif 390/* ARGSUSED */ 391int 392fchdir(td, uap) 393 struct thread *td; 394 struct fchdir_args /* { 395 int fd; 396 } */ *uap; 397{ 398 register struct filedesc *fdp = td->td_proc->p_fd; 399 struct vnode *vp, *tdp, *vpold; 400 struct mount *mp; 401 struct file *fp; 402 int error; 403 404 if ((error = getvnode(fdp, uap->fd, &fp)) != 0) 405 return (error); 406 vp = fp->f_data; 407 VREF(vp); 408 fdrop(fp, td); 409 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 410 if (vp->v_type != VDIR) 411 error = ENOTDIR; 412#ifdef MAC 413 else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) { 414 } 415#endif 416 else 417 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 418 while (!error && (mp = vp->v_mountedhere) != NULL) { 419 if (vfs_busy(mp, 0, 0, td)) 420 continue; 421 error = VFS_ROOT(mp, &tdp); 422 vfs_unbusy(mp, td); 423 if (error) 424 break; 425 vput(vp); 426 vp = tdp; 427 } 428 if (error) { 429 vput(vp); 430 return (error); 431 } 432 VOP_UNLOCK(vp, 0, td); 433 FILEDESC_LOCK(fdp); 434 vpold = fdp->fd_cdir; 435 fdp->fd_cdir = vp; 436 FILEDESC_UNLOCK(fdp); 437 vrele(vpold); 438 return (0); 439} 440 441/* 442 * Change current working directory (``.''). 443 */ 444#ifndef _SYS_SYSPROTO_H_ 445struct chdir_args { 446 char *path; 447}; 448#endif 449/* ARGSUSED */ 450int 451chdir(td, uap) 452 struct thread *td; 453 struct chdir_args /* { 454 char *path; 455 } */ *uap; 456{ 457 458 return (kern_chdir(td, uap->path, UIO_USERSPACE)); 459} 460 461int 462kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) 463{ 464 register struct filedesc *fdp = td->td_proc->p_fd; 465 int error; 466 struct nameidata nd; 467 struct vnode *vp; 468 469 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td); 470 if ((error = namei(&nd)) != 0) 471 return (error); 472 if ((error = change_dir(nd.ni_vp, td)) != 0) { 473 vput(nd.ni_vp); 474 NDFREE(&nd, NDF_ONLY_PNBUF); 475 return (error); 476 } 477 VOP_UNLOCK(nd.ni_vp, 0, td); 478 NDFREE(&nd, NDF_ONLY_PNBUF); 479 FILEDESC_LOCK(fdp); 480 vp = fdp->fd_cdir; 481 fdp->fd_cdir = nd.ni_vp; 482 FILEDESC_UNLOCK(fdp); 483 vrele(vp); 484 return (0); 485} 486 487/* 488 * Helper function for raised chroot(2) security function: Refuse if 489 * any filedescriptors are open directories. 490 */ 491static int 492chroot_refuse_vdir_fds(fdp) 493 struct filedesc *fdp; 494{ 495 struct vnode *vp; 496 struct file *fp; 497 int fd; 498 499 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); 500 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 501 fp = fget_locked(fdp, fd); 502 if (fp == NULL) 503 continue; 504 if (fp->f_type == DTYPE_VNODE) { 505 vp = fp->f_data; 506 if (vp->v_type == VDIR) 507 return (EPERM); 508 } 509 } 510 return (0); 511} 512 513/* 514 * This sysctl determines if we will allow a process to chroot(2) if it 515 * has a directory open: 516 * 0: disallowed for all processes. 517 * 1: allowed for processes that were not already chroot(2)'ed. 518 * 2: allowed for all processes. 519 */ 520 521static int chroot_allow_open_directories = 1; 522 523SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 524 &chroot_allow_open_directories, 0, ""); 525 526/* 527 * Change notion of root (``/'') directory. 528 */ 529#ifndef _SYS_SYSPROTO_H_ 530struct chroot_args { 531 char *path; 532}; 533#endif 534/* ARGSUSED */ 535int 536chroot(td, uap) 537 struct thread *td; 538 struct chroot_args /* { 539 char *path; 540 } */ *uap; 541{ 542 int error; 543 struct nameidata nd; 544 545 error = suser_cred(td->td_ucred, PRISON_ROOT); 546 if (error) 547 return (error); 548 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td); 549 mtx_lock(&Giant); 550 error = namei(&nd); 551 if (error) 552 goto error; 553 if ((error = change_dir(nd.ni_vp, td)) != 0) 554 goto e_vunlock; 555#ifdef MAC 556 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp))) 557 goto e_vunlock; 558#endif 559 VOP_UNLOCK(nd.ni_vp, 0, td); 560 error = change_root(nd.ni_vp, td); 561 vrele(nd.ni_vp); 562 NDFREE(&nd, NDF_ONLY_PNBUF); 563 mtx_unlock(&Giant); 564 return (error); 565e_vunlock: 566 vput(nd.ni_vp); 567error: 568 mtx_unlock(&Giant); 569 NDFREE(&nd, NDF_ONLY_PNBUF); 570 return (error); 571} 572 573/* 574 * Common routine for chroot and chdir. Callers must provide a locked vnode 575 * instance. 576 */ 577int 578change_dir(vp, td) 579 struct vnode *vp; 580 struct thread *td; 581{ 582 int error; 583 584 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked"); 585 if (vp->v_type != VDIR) 586 return (ENOTDIR); 587#ifdef MAC 588 error = mac_check_vnode_chdir(td->td_ucred, vp); 589 if (error) 590 return (error); 591#endif 592 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 593 return (error); 594} 595 596/* 597 * Common routine for kern_chroot() and jail_attach(). The caller is 598 * responsible for invoking suser() and mac_check_chroot() to authorize this 599 * operation. 600 */ 601int 602change_root(vp, td) 603 struct vnode *vp; 604 struct thread *td; 605{ 606 struct filedesc *fdp; 607 struct vnode *oldvp; 608 int error; 609 610 mtx_assert(&Giant, MA_OWNED); 611 fdp = td->td_proc->p_fd; 612 FILEDESC_LOCK(fdp); 613 if (chroot_allow_open_directories == 0 || 614 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 615 error = chroot_refuse_vdir_fds(fdp); 616 if (error) { 617 FILEDESC_UNLOCK(fdp); 618 return (error); 619 } 620 } 621 oldvp = fdp->fd_rdir; 622 fdp->fd_rdir = vp; 623 VREF(fdp->fd_rdir); 624 if (!fdp->fd_jdir) { 625 fdp->fd_jdir = vp; 626 VREF(fdp->fd_jdir); 627 } 628 FILEDESC_UNLOCK(fdp); 629 vrele(oldvp); 630 return (0); 631} 632 633/* 634 * Check permissions, allocate an open file structure, 635 * and call the device open routine if any. 636 */ 637#ifndef _SYS_SYSPROTO_H_ 638struct open_args { 639 char *path; 640 int flags; 641 int mode; 642}; 643#endif 644int 645open(td, uap) 646 struct thread *td; 647 register struct open_args /* { 648 char *path; 649 int flags; 650 int mode; 651 } */ *uap; 652{ 653 654 return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode)); 655} 656 657int 658kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, 659 int mode) 660{ 661 struct proc *p = td->td_proc; 662 struct filedesc *fdp = p->p_fd; 663 struct file *fp; 664 struct vnode *vp; 665 struct vattr vat; 666 struct mount *mp; 667 int cmode; 668 struct file *nfp; 669 int type, indx, error; 670 struct flock lf; 671 struct nameidata nd; 672 673 if ((flags & O_ACCMODE) == O_ACCMODE) 674 return (EINVAL); 675 flags = FFLAGS(flags); 676 error = falloc(td, &nfp, &indx); 677 if (error) 678 return (error); 679 fp = nfp; 680 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 681 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); 682 td->td_dupfd = -indx - 1; /* XXX check for fdopen */ 683 /* 684 * Bump the ref count to prevent another process from closing 685 * the descriptor while we are blocked in vn_open() 686 */ 687 fhold(fp); 688 error = vn_open(&nd, &flags, cmode); 689 if (error) { 690 /* 691 * release our own reference 692 */ 693 fdrop(fp, td); 694 695 /* 696 * handle special fdopen() case. bleh. dupfdopen() is 697 * responsible for dropping the old contents of ofiles[indx] 698 * if it succeeds. 699 */ 700 if ((error == ENODEV || error == ENXIO) && 701 td->td_dupfd >= 0 && /* XXX from fdopen */ 702 (error = 703 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 704 td->td_retval[0] = indx; 705 return (0); 706 } 707 /* 708 * Clean up the descriptor, but only if another thread hadn't 709 * replaced or closed it. 710 */ 711 FILEDESC_LOCK(fdp); 712 if (fdp->fd_ofiles[indx] == fp) { 713 fdp->fd_ofiles[indx] = NULL; 714 FILEDESC_UNLOCK(fdp); 715 fdrop(fp, td); 716 } else 717 FILEDESC_UNLOCK(fdp); 718 719 if (error == ERESTART) 720 error = EINTR; 721 return (error); 722 } 723 td->td_dupfd = 0; 724 NDFREE(&nd, NDF_ONLY_PNBUF); 725 vp = nd.ni_vp; 726 727 /* 728 * There should be 2 references on the file, one from the descriptor 729 * table, and one for us. 730 * 731 * Handle the case where someone closed the file (via its file 732 * descriptor) while we were blocked. The end result should look 733 * like opening the file succeeded but it was immediately closed. 734 */ 735 FILEDESC_LOCK(fdp); 736 FILE_LOCK(fp); 737 if (fp->f_count == 1) { 738 KASSERT(fdp->fd_ofiles[indx] != fp, 739 ("Open file descriptor lost all refs")); 740 FILEDESC_UNLOCK(fdp); 741 FILE_UNLOCK(fp); 742 VOP_UNLOCK(vp, 0, td); 743 vn_close(vp, flags & FMASK, fp->f_cred, td); 744 fdrop(fp, td); 745 td->td_retval[0] = indx; 746 return 0; 747 } 748 fp->f_data = vp; 749 fp->f_flag = flags & FMASK; 750 fp->f_ops = &vnops; 751 fp->f_seqcount = 1; 752 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 753 FILEDESC_UNLOCK(fdp); 754 FILE_UNLOCK(fp); 755 756 /* assert that vn_open created a backing object if one is needed */ 757 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 758 ("open: vmio vnode has no backing object after vn_open")); 759 760 VOP_UNLOCK(vp, 0, td); 761 if (flags & (O_EXLOCK | O_SHLOCK)) { 762 lf.l_whence = SEEK_SET; 763 lf.l_start = 0; 764 lf.l_len = 0; 765 if (flags & O_EXLOCK) 766 lf.l_type = F_WRLCK; 767 else 768 lf.l_type = F_RDLCK; 769 type = F_FLOCK; 770 if ((flags & FNONBLOCK) == 0) 771 type |= F_WAIT; 772 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 773 type)) != 0) 774 goto bad; 775 fp->f_flag |= FHASLOCK; 776 } 777 if (flags & O_TRUNC) { 778 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 779 goto bad; 780 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 781 VATTR_NULL(&vat); 782 vat.va_size = 0; 783 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 784#ifdef MAC 785 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp); 786 if (error == 0) 787#endif 788 error = VOP_SETATTR(vp, &vat, td->td_ucred, td); 789 VOP_UNLOCK(vp, 0, td); 790 vn_finished_write(mp); 791 if (error) 792 goto bad; 793 } 794 /* 795 * Release our private reference, leaving the one associated with 796 * the descriptor table intact. 797 */ 798 fdrop(fp, td); 799 td->td_retval[0] = indx; 800 return (0); 801bad: 802 FILEDESC_LOCK(fdp); 803 if (fdp->fd_ofiles[indx] == fp) { 804 fdp->fd_ofiles[indx] = NULL; 805 FILEDESC_UNLOCK(fdp); 806 fdrop(fp, td); 807 } else 808 FILEDESC_UNLOCK(fdp); 809 fdrop(fp, td); 810 return (error); 811} 812 813#ifdef COMPAT_43 814/* 815 * Create a file. 816 */ 817#ifndef _SYS_SYSPROTO_H_ 818struct ocreat_args { 819 char *path; 820 int mode; 821}; 822#endif 823int 824ocreat(td, uap) 825 struct thread *td; 826 register struct ocreat_args /* { 827 char *path; 828 int mode; 829 } */ *uap; 830{ 831 struct open_args /* { 832 char *path; 833 int flags; 834 int mode; 835 } */ nuap; 836 837 nuap.path = uap->path; 838 nuap.mode = uap->mode; 839 nuap.flags = O_WRONLY | O_CREAT | O_TRUNC; 840 return (open(td, &nuap)); 841} 842#endif /* COMPAT_43 */ 843 844/* 845 * Create a special file. 846 */ 847#ifndef _SYS_SYSPROTO_H_ 848struct mknod_args { 849 char *path; 850 int mode; 851 int dev; 852}; 853#endif 854/* ARGSUSED */ 855int 856mknod(td, uap) 857 struct thread *td; 858 register struct mknod_args /* { 859 char *path; 860 int mode; 861 int dev; 862 } */ *uap; 863{ 864 865 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); 866} 867 868int 869kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, 870 int dev) 871{ 872 struct vnode *vp; 873 struct mount *mp; 874 struct vattr vattr; 875 int error; 876 int whiteout = 0; 877 struct nameidata nd; 878 879 switch (mode & S_IFMT) { 880 case S_IFCHR: 881 case S_IFBLK: 882 error = suser(td); 883 break; 884 default: 885 error = suser_cred(td->td_ucred, PRISON_ROOT); 886 break; 887 } 888 if (error) 889 return (error); 890restart: 891 bwillwrite(); 892 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); 893 if ((error = namei(&nd)) != 0) 894 return (error); 895 vp = nd.ni_vp; 896 if (vp != NULL) { 897 vrele(vp); 898 error = EEXIST; 899 } else { 900 VATTR_NULL(&vattr); 901 FILEDESC_LOCK(td->td_proc->p_fd); 902 vattr.va_mode = (mode & ALLPERMS) & 903 ~td->td_proc->p_fd->fd_cmask; 904 FILEDESC_UNLOCK(td->td_proc->p_fd); 905 vattr.va_rdev = dev; 906 whiteout = 0; 907 908 switch (mode & S_IFMT) { 909 case S_IFMT: /* used by badsect to flag bad sectors */ 910 vattr.va_type = VBAD; 911 break; 912 case S_IFCHR: 913 vattr.va_type = VCHR; 914 break; 915 case S_IFBLK: 916 vattr.va_type = VBLK; 917 break; 918 case S_IFWHT: 919 whiteout = 1; 920 break; 921 default: 922 error = EINVAL; 923 break; 924 } 925 } 926 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 927 NDFREE(&nd, NDF_ONLY_PNBUF); 928 vput(nd.ni_dvp); 929 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 930 return (error); 931 goto restart; 932 } 933#ifdef MAC 934 if (error == 0 && !whiteout) 935 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, 936 &nd.ni_cnd, &vattr); 937#endif 938 if (!error) { 939 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 940 if (whiteout) 941 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 942 else { 943 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 944 &nd.ni_cnd, &vattr); 945 if (error == 0) 946 vput(nd.ni_vp); 947 } 948 } 949 NDFREE(&nd, NDF_ONLY_PNBUF); 950 vput(nd.ni_dvp); 951 vn_finished_write(mp); 952 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 953 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 954 return (error); 955} 956 957/* 958 * Create a named pipe. 959 */ 960#ifndef _SYS_SYSPROTO_H_ 961struct mkfifo_args { 962 char *path; 963 int mode; 964}; 965#endif 966/* ARGSUSED */ 967int 968mkfifo(td, uap) 969 struct thread *td; 970 register struct mkfifo_args /* { 971 char *path; 972 int mode; 973 } */ *uap; 974{ 975 976 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); 977} 978 979int 980kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) 981{ 982 struct mount *mp; 983 struct vattr vattr; 984 int error; 985 struct nameidata nd; 986 987restart: 988 bwillwrite(); 989 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); 990 if ((error = namei(&nd)) != 0) 991 return (error); 992 if (nd.ni_vp != NULL) { 993 NDFREE(&nd, NDF_ONLY_PNBUF); 994 vrele(nd.ni_vp); 995 vput(nd.ni_dvp); 996 return (EEXIST); 997 } 998 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 999 NDFREE(&nd, NDF_ONLY_PNBUF); 1000 vput(nd.ni_dvp); 1001 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1002 return (error); 1003 goto restart; 1004 } 1005 VATTR_NULL(&vattr); 1006 vattr.va_type = VFIFO; 1007 FILEDESC_LOCK(td->td_proc->p_fd); 1008 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask; 1009 FILEDESC_UNLOCK(td->td_proc->p_fd); 1010#ifdef MAC 1011 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 1012 &vattr); 1013 if (error) 1014 goto out; 1015#endif 1016 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1017 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1018 if (error == 0) 1019 vput(nd.ni_vp); 1020#ifdef MAC 1021out: 1022#endif 1023 NDFREE(&nd, NDF_ONLY_PNBUF); 1024 vput(nd.ni_dvp); 1025 vn_finished_write(mp); 1026 return (error); 1027} 1028 1029/* 1030 * Make a hard file link. 1031 */ 1032#ifndef _SYS_SYSPROTO_H_ 1033struct link_args { 1034 char *path; 1035 char *link; 1036}; 1037#endif 1038/* ARGSUSED */ 1039int 1040link(td, uap) 1041 struct thread *td; 1042 register struct link_args /* { 1043 char *path; 1044 char *link; 1045 } */ *uap; 1046{ 1047 1048 return (kern_link(td, uap->path, uap->link, UIO_USERSPACE)); 1049} 1050 1051int 1052kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) 1053{ 1054 struct vnode *vp; 1055 struct mount *mp; 1056 struct nameidata nd; 1057 int error; 1058 1059 bwillwrite(); 1060 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td); 1061 if ((error = namei(&nd)) != 0) 1062 return (error); 1063 NDFREE(&nd, NDF_ONLY_PNBUF); 1064 vp = nd.ni_vp; 1065 if (vp->v_type == VDIR) { 1066 vrele(vp); 1067 return (EPERM); /* POSIX */ 1068 } 1069 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 1070 vrele(vp); 1071 return (error); 1072 } 1073 NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); 1074 if ((error = namei(&nd)) == 0) { 1075 if (nd.ni_vp != NULL) { 1076 vrele(nd.ni_vp); 1077 error = EEXIST; 1078 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) 1079 == 0) { 1080 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1081 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1082#ifdef MAC 1083 error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp, 1084 vp, &nd.ni_cnd); 1085 if (error == 0) 1086#endif 1087 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1088 VOP_UNLOCK(vp, 0, td); 1089 } 1090 NDFREE(&nd, NDF_ONLY_PNBUF); 1091 vput(nd.ni_dvp); 1092 } 1093 vrele(vp); 1094 vn_finished_write(mp); 1095 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1096 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1097 return (error); 1098} 1099 1100/* 1101 * Make a symbolic link. 1102 */ 1103#ifndef _SYS_SYSPROTO_H_ 1104struct symlink_args { 1105 char *path; 1106 char *link; 1107}; 1108#endif 1109/* ARGSUSED */ 1110int 1111symlink(td, uap) 1112 struct thread *td; 1113 register struct symlink_args /* { 1114 char *path; 1115 char *link; 1116 } */ *uap; 1117{ 1118 1119 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); 1120} 1121 1122int 1123kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) 1124{ 1125 struct mount *mp; 1126 struct vattr vattr; 1127 char *syspath; 1128 int error; 1129 struct nameidata nd; 1130 1131 if (segflg == UIO_SYSSPACE) { 1132 syspath = path; 1133 } else { 1134 syspath = uma_zalloc(namei_zone, M_WAITOK); 1135 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) 1136 goto out; 1137 } 1138restart: 1139 bwillwrite(); 1140 NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); 1141 if ((error = namei(&nd)) != 0) 1142 goto out; 1143 if (nd.ni_vp) { 1144 NDFREE(&nd, NDF_ONLY_PNBUF); 1145 vrele(nd.ni_vp); 1146 vput(nd.ni_dvp); 1147 error = EEXIST; 1148 goto out; 1149 } 1150 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1151 NDFREE(&nd, NDF_ONLY_PNBUF); 1152 vput(nd.ni_dvp); 1153 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1154 return (error); 1155 goto restart; 1156 } 1157 VATTR_NULL(&vattr); 1158 FILEDESC_LOCK(td->td_proc->p_fd); 1159 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1160 FILEDESC_UNLOCK(td->td_proc->p_fd); 1161#ifdef MAC 1162 vattr.va_type = VLNK; 1163 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 1164 &vattr); 1165 if (error) 1166 goto out2; 1167#endif 1168 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1169 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); 1170 if (error == 0) 1171 vput(nd.ni_vp); 1172#ifdef MAC 1173out2: 1174#endif 1175 NDFREE(&nd, NDF_ONLY_PNBUF); 1176 vput(nd.ni_dvp); 1177 vn_finished_write(mp); 1178 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1179 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1180out: 1181 if (segflg != UIO_SYSSPACE) 1182 uma_zfree(namei_zone, syspath); 1183 return (error); 1184} 1185 1186/* 1187 * Delete a whiteout from the filesystem. 1188 */ 1189/* ARGSUSED */ 1190int 1191undelete(td, uap) 1192 struct thread *td; 1193 register struct undelete_args /* { 1194 char *path; 1195 } */ *uap; 1196{ 1197 int error; 1198 struct mount *mp; 1199 struct nameidata nd; 1200 1201restart: 1202 bwillwrite(); 1203 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1204 uap->path, td); 1205 error = namei(&nd); 1206 if (error) 1207 return (error); 1208 1209 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1210 NDFREE(&nd, NDF_ONLY_PNBUF); 1211 if (nd.ni_vp) 1212 vrele(nd.ni_vp); 1213 vput(nd.ni_dvp); 1214 return (EEXIST); 1215 } 1216 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1217 NDFREE(&nd, NDF_ONLY_PNBUF); 1218 vput(nd.ni_dvp); 1219 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1220 return (error); 1221 goto restart; 1222 } 1223 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1224 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1225 NDFREE(&nd, NDF_ONLY_PNBUF); 1226 vput(nd.ni_dvp); 1227 vn_finished_write(mp); 1228 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1229 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1230 return (error); 1231} 1232 1233/* 1234 * Delete a name from the filesystem. 1235 */ 1236#ifndef _SYS_SYSPROTO_H_ 1237struct unlink_args { 1238 char *path; 1239}; 1240#endif 1241/* ARGSUSED */ 1242int 1243unlink(td, uap) 1244 struct thread *td; 1245 struct unlink_args /* { 1246 char *path; 1247 } */ *uap; 1248{ 1249 1250 return (kern_unlink(td, uap->path, UIO_USERSPACE)); 1251} 1252 1253int 1254kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) 1255{ 1256 struct mount *mp; 1257 struct vnode *vp; 1258 int error; 1259 struct nameidata nd; 1260 1261restart: 1262 bwillwrite(); 1263 NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td); 1264 if ((error = namei(&nd)) != 0) 1265 return (error); 1266 vp = nd.ni_vp; 1267 if (vp->v_type == VDIR) 1268 error = EPERM; /* POSIX */ 1269 else { 1270 /* 1271 * The root of a mounted filesystem cannot be deleted. 1272 * 1273 * XXX: can this only be a VDIR case? 1274 */ 1275 if (vp->v_vflag & VV_ROOT) 1276 error = EBUSY; 1277 } 1278 if (error == 0) { 1279 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1280 NDFREE(&nd, NDF_ONLY_PNBUF); 1281 if (vp == nd.ni_dvp) 1282 vrele(vp); 1283 else 1284 vput(vp); 1285 vput(nd.ni_dvp); 1286 if ((error = vn_start_write(NULL, &mp, 1287 V_XSLEEP | PCATCH)) != 0) 1288 return (error); 1289 goto restart; 1290 } 1291#ifdef MAC 1292 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, 1293 &nd.ni_cnd); 1294 if (error) 1295 goto out; 1296#endif 1297 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1298 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1299#ifdef MAC 1300out: 1301#endif 1302 vn_finished_write(mp); 1303 } 1304 NDFREE(&nd, NDF_ONLY_PNBUF); 1305 if (vp == nd.ni_dvp) 1306 vrele(vp); 1307 else 1308 vput(vp); 1309 vput(nd.ni_dvp); 1310 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1311 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1312 return (error); 1313} 1314 1315/* 1316 * Reposition read/write file offset. 1317 */ 1318#ifndef _SYS_SYSPROTO_H_ 1319struct lseek_args { 1320 int fd; 1321 int pad; 1322 off_t offset; 1323 int whence; 1324}; 1325#endif 1326int 1327lseek(td, uap) 1328 struct thread *td; 1329 register struct lseek_args /* { 1330 int fd; 1331 int pad; 1332 off_t offset; 1333 int whence; 1334 } */ *uap; 1335{ 1336 struct ucred *cred = td->td_ucred; 1337 struct file *fp; 1338 struct vnode *vp; 1339 struct vattr vattr; 1340 off_t offset; 1341 int error, noneg; 1342 1343 if ((error = fget(td, uap->fd, &fp)) != 0) 1344 return (error); 1345 if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) { 1346 fdrop(fp, td); 1347 return (ESPIPE); 1348 } 1349 vp = fp->f_data; 1350 noneg = (vp->v_type != VCHR); 1351 offset = uap->offset; 1352 switch (uap->whence) { 1353 case L_INCR: 1354 if (noneg && 1355 (fp->f_offset < 0 || 1356 (offset > 0 && fp->f_offset > OFF_MAX - offset))) { 1357 error = EOVERFLOW; 1358 break; 1359 } 1360 offset += fp->f_offset; 1361 break; 1362 case L_XTND: 1363 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1364 error = VOP_GETATTR(vp, &vattr, cred, td); 1365 VOP_UNLOCK(vp, 0, td); 1366 if (error) 1367 break; 1368 if (noneg && 1369 (vattr.va_size > OFF_MAX || 1370 (offset > 0 && vattr.va_size > OFF_MAX - offset))) { 1371 error = EOVERFLOW; 1372 break; 1373 } 1374 offset += vattr.va_size; 1375 break; 1376 case L_SET: 1377 break; 1378 default: 1379 error = EINVAL; 1380 } 1381 if (error == 0 && noneg && offset < 0) 1382 error = EINVAL; 1383 if (error != 0) { 1384 fdrop(fp, td); 1385 return (error); 1386 } 1387 fp->f_offset = offset; 1388 *(off_t *)(td->td_retval) = fp->f_offset; 1389 fdrop(fp, td); 1390 return (0); 1391} 1392 1393#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1394/* 1395 * Reposition read/write file offset. 1396 */ 1397#ifndef _SYS_SYSPROTO_H_ 1398struct olseek_args { 1399 int fd; 1400 long offset; 1401 int whence; 1402}; 1403#endif 1404int 1405olseek(td, uap) 1406 struct thread *td; 1407 register struct olseek_args /* { 1408 int fd; 1409 long offset; 1410 int whence; 1411 } */ *uap; 1412{ 1413 struct lseek_args /* { 1414 int fd; 1415 int pad; 1416 off_t offset; 1417 int whence; 1418 } */ nuap; 1419 int error; 1420 1421 nuap.fd = uap->fd; 1422 nuap.offset = uap->offset; 1423 nuap.whence = uap->whence; 1424 error = lseek(td, &nuap); 1425 return (error); 1426} 1427#endif /* COMPAT_43 */ 1428 1429/* 1430 * Check access permissions using passed credentials. 1431 */ 1432static int 1433vn_access(vp, user_flags, cred, td) 1434 struct vnode *vp; 1435 int user_flags; 1436 struct ucred *cred; 1437 struct thread *td; 1438{ 1439 int error, flags; 1440 1441 /* Flags == 0 means only check for existence. */ 1442 error = 0; 1443 if (user_flags) { 1444 flags = 0; 1445 if (user_flags & R_OK) 1446 flags |= VREAD; 1447 if (user_flags & W_OK) 1448 flags |= VWRITE; 1449 if (user_flags & X_OK) 1450 flags |= VEXEC; 1451#ifdef MAC 1452 error = mac_check_vnode_access(cred, vp, flags); 1453 if (error) 1454 return (error); 1455#endif 1456 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1457 error = VOP_ACCESS(vp, flags, cred, td); 1458 } 1459 return (error); 1460} 1461 1462/* 1463 * Check access permissions using "real" credentials. 1464 */ 1465#ifndef _SYS_SYSPROTO_H_ 1466struct access_args { 1467 char *path; 1468 int flags; 1469}; 1470#endif 1471int 1472access(td, uap) 1473 struct thread *td; 1474 register struct access_args /* { 1475 char *path; 1476 int flags; 1477 } */ *uap; 1478{ 1479 1480 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); 1481} 1482 1483int 1484kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) 1485{ 1486 struct ucred *cred, *tmpcred; 1487 register struct vnode *vp; 1488 int error; 1489 struct nameidata nd; 1490 1491 /* 1492 * Create and modify a temporary credential instead of one that 1493 * is potentially shared. This could also mess up socket 1494 * buffer accounting which can run in an interrupt context. 1495 * 1496 * XXX - Depending on how "threads" are finally implemented, it 1497 * may be better to explicitly pass the credential to namei() 1498 * rather than to modify the potentially shared process structure. 1499 */ 1500 cred = td->td_ucred; 1501 tmpcred = crdup(cred); 1502 tmpcred->cr_uid = cred->cr_ruid; 1503 tmpcred->cr_groups[0] = cred->cr_rgid; 1504 td->td_ucred = tmpcred; 1505 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); 1506 if ((error = namei(&nd)) != 0) 1507 goto out1; 1508 vp = nd.ni_vp; 1509 1510 error = vn_access(vp, flags, tmpcred, td); 1511 NDFREE(&nd, NDF_ONLY_PNBUF); 1512 vput(vp); 1513out1: 1514 td->td_ucred = cred; 1515 crfree(tmpcred); 1516 return (error); 1517} 1518 1519/* 1520 * Check access permissions using "effective" credentials. 1521 */ 1522#ifndef _SYS_SYSPROTO_H_ 1523struct eaccess_args { 1524 char *path; 1525 int flags; 1526}; 1527#endif 1528int 1529eaccess(td, uap) 1530 struct thread *td; 1531 register struct eaccess_args /* { 1532 char *path; 1533 int flags; 1534 } */ *uap; 1535{ 1536 struct nameidata nd; 1537 struct vnode *vp; 1538 int error; 1539 1540 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1541 uap->path, td); 1542 if ((error = namei(&nd)) != 0) 1543 return (error); 1544 vp = nd.ni_vp; 1545 1546 error = vn_access(vp, uap->flags, td->td_ucred, td); 1547 NDFREE(&nd, NDF_ONLY_PNBUF); 1548 vput(vp); 1549 return (error); 1550} 1551 1552#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1553/* 1554 * Get file status; this version follows links. 1555 */ 1556#ifndef _SYS_SYSPROTO_H_ 1557struct ostat_args { 1558 char *path; 1559 struct ostat *ub; 1560}; 1561#endif 1562/* ARGSUSED */ 1563int 1564ostat(td, uap) 1565 struct thread *td; 1566 register struct ostat_args /* { 1567 char *path; 1568 struct ostat *ub; 1569 } */ *uap; 1570{ 1571 struct stat sb; 1572 struct ostat osb; 1573 int error; 1574 struct nameidata nd; 1575 1576 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1577 uap->path, td); 1578 if ((error = namei(&nd)) != 0) 1579 return (error); 1580 NDFREE(&nd, NDF_ONLY_PNBUF); 1581 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); 1582 vput(nd.ni_vp); 1583 if (error) 1584 return (error); 1585 cvtstat(&sb, &osb); 1586 error = copyout(&osb, uap->ub, sizeof (osb)); 1587 return (error); 1588} 1589 1590/* 1591 * Get file status; this version does not follow links. 1592 */ 1593#ifndef _SYS_SYSPROTO_H_ 1594struct olstat_args { 1595 char *path; 1596 struct ostat *ub; 1597}; 1598#endif 1599/* ARGSUSED */ 1600int 1601olstat(td, uap) 1602 struct thread *td; 1603 register struct olstat_args /* { 1604 char *path; 1605 struct ostat *ub; 1606 } */ *uap; 1607{ 1608 struct vnode *vp; 1609 struct stat sb; 1610 struct ostat osb; 1611 int error; 1612 struct nameidata nd; 1613 1614 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1615 uap->path, td); 1616 if ((error = namei(&nd)) != 0) 1617 return (error); 1618 vp = nd.ni_vp; 1619 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 1620 NDFREE(&nd, NDF_ONLY_PNBUF); 1621 vput(vp); 1622 if (error) 1623 return (error); 1624 cvtstat(&sb, &osb); 1625 error = copyout(&osb, uap->ub, sizeof (osb)); 1626 return (error); 1627} 1628 1629/* 1630 * Convert from an old to a new stat structure. 1631 */ 1632void 1633cvtstat(st, ost) 1634 struct stat *st; 1635 struct ostat *ost; 1636{ 1637 1638 ost->st_dev = st->st_dev; 1639 ost->st_ino = st->st_ino; 1640 ost->st_mode = st->st_mode; 1641 ost->st_nlink = st->st_nlink; 1642 ost->st_uid = st->st_uid; 1643 ost->st_gid = st->st_gid; 1644 ost->st_rdev = st->st_rdev; 1645 if (st->st_size < (quad_t)1 << 32) 1646 ost->st_size = st->st_size; 1647 else 1648 ost->st_size = -2; 1649 ost->st_atime = st->st_atime; 1650 ost->st_mtime = st->st_mtime; 1651 ost->st_ctime = st->st_ctime; 1652 ost->st_blksize = st->st_blksize; 1653 ost->st_blocks = st->st_blocks; 1654 ost->st_flags = st->st_flags; 1655 ost->st_gen = st->st_gen; 1656} 1657#endif /* COMPAT_43 || COMPAT_SUNOS */ 1658 1659/* 1660 * Get file status; this version follows links. 1661 */ 1662#ifndef _SYS_SYSPROTO_H_ 1663struct stat_args { 1664 char *path; 1665 struct stat *ub; 1666}; 1667#endif 1668/* ARGSUSED */ 1669int 1670stat(td, uap) 1671 struct thread *td; 1672 register struct stat_args /* { 1673 char *path; 1674 struct stat *ub; 1675 } */ *uap; 1676{ 1677 struct stat sb; 1678 int error; 1679 struct nameidata nd; 1680 1681#ifdef LOOKUP_SHARED 1682 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ, 1683 UIO_USERSPACE, uap->path, td); 1684#else 1685 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1686 uap->path, td); 1687#endif 1688 if ((error = namei(&nd)) != 0) 1689 return (error); 1690 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); 1691 NDFREE(&nd, NDF_ONLY_PNBUF); 1692 vput(nd.ni_vp); 1693 if (error) 1694 return (error); 1695 error = copyout(&sb, uap->ub, sizeof (sb)); 1696 return (error); 1697} 1698 1699/* 1700 * Get file status; this version does not follow links. 1701 */ 1702#ifndef _SYS_SYSPROTO_H_ 1703struct lstat_args { 1704 char *path; 1705 struct stat *ub; 1706}; 1707#endif 1708/* ARGSUSED */ 1709int 1710lstat(td, uap) 1711 struct thread *td; 1712 register struct lstat_args /* { 1713 char *path; 1714 struct stat *ub; 1715 } */ *uap; 1716{ 1717 int error; 1718 struct vnode *vp; 1719 struct stat sb; 1720 struct nameidata nd; 1721 1722 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1723 uap->path, td); 1724 if ((error = namei(&nd)) != 0) 1725 return (error); 1726 vp = nd.ni_vp; 1727 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 1728 NDFREE(&nd, NDF_ONLY_PNBUF); 1729 vput(vp); 1730 if (error) 1731 return (error); 1732 error = copyout(&sb, uap->ub, sizeof (sb)); 1733 return (error); 1734} 1735 1736/* 1737 * Implementation of the NetBSD stat() function. 1738 * XXX This should probably be collapsed with the FreeBSD version, 1739 * as the differences are only due to vn_stat() clearing spares at 1740 * the end of the structures. vn_stat could be split to avoid this, 1741 * and thus collapse the following to close to zero code. 1742 */ 1743void 1744cvtnstat(sb, nsb) 1745 struct stat *sb; 1746 struct nstat *nsb; 1747{ 1748 bzero(nsb, sizeof *nsb); 1749 nsb->st_dev = sb->st_dev; 1750 nsb->st_ino = sb->st_ino; 1751 nsb->st_mode = sb->st_mode; 1752 nsb->st_nlink = sb->st_nlink; 1753 nsb->st_uid = sb->st_uid; 1754 nsb->st_gid = sb->st_gid; 1755 nsb->st_rdev = sb->st_rdev; 1756 nsb->st_atimespec = sb->st_atimespec; 1757 nsb->st_mtimespec = sb->st_mtimespec; 1758 nsb->st_ctimespec = sb->st_ctimespec; 1759 nsb->st_size = sb->st_size; 1760 nsb->st_blocks = sb->st_blocks; 1761 nsb->st_blksize = sb->st_blksize; 1762 nsb->st_flags = sb->st_flags; 1763 nsb->st_gen = sb->st_gen; 1764 nsb->st_birthtimespec = sb->st_birthtimespec; 1765} 1766 1767#ifndef _SYS_SYSPROTO_H_ 1768struct nstat_args { 1769 char *path; 1770 struct nstat *ub; 1771}; 1772#endif 1773/* ARGSUSED */ 1774int 1775nstat(td, uap) 1776 struct thread *td; 1777 register struct nstat_args /* { 1778 char *path; 1779 struct nstat *ub; 1780 } */ *uap; 1781{ 1782 struct stat sb; 1783 struct nstat nsb; 1784 int error; 1785 struct nameidata nd; 1786 1787 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1788 uap->path, td); 1789 if ((error = namei(&nd)) != 0) 1790 return (error); 1791 NDFREE(&nd, NDF_ONLY_PNBUF); 1792 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); 1793 vput(nd.ni_vp); 1794 if (error) 1795 return (error); 1796 cvtnstat(&sb, &nsb); 1797 error = copyout(&nsb, uap->ub, sizeof (nsb)); 1798 return (error); 1799} 1800 1801/* 1802 * NetBSD lstat. Get file status; this version does not follow links. 1803 */ 1804#ifndef _SYS_SYSPROTO_H_ 1805struct lstat_args { 1806 char *path; 1807 struct stat *ub; 1808}; 1809#endif 1810/* ARGSUSED */ 1811int 1812nlstat(td, uap) 1813 struct thread *td; 1814 register struct nlstat_args /* { 1815 char *path; 1816 struct nstat *ub; 1817 } */ *uap; 1818{ 1819 int error; 1820 struct vnode *vp; 1821 struct stat sb; 1822 struct nstat nsb; 1823 struct nameidata nd; 1824 1825 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1826 uap->path, td); 1827 if ((error = namei(&nd)) != 0) 1828 return (error); 1829 vp = nd.ni_vp; 1830 NDFREE(&nd, NDF_ONLY_PNBUF); 1831 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 1832 vput(vp); 1833 if (error) 1834 return (error); 1835 cvtnstat(&sb, &nsb); 1836 error = copyout(&nsb, uap->ub, sizeof (nsb)); 1837 return (error); 1838} 1839 1840/* 1841 * Get configurable pathname variables. 1842 */ 1843#ifndef _SYS_SYSPROTO_H_ 1844struct pathconf_args { 1845 char *path; 1846 int name; 1847}; 1848#endif 1849/* ARGSUSED */ 1850int 1851pathconf(td, uap) 1852 struct thread *td; 1853 register struct pathconf_args /* { 1854 char *path; 1855 int name; 1856 } */ *uap; 1857{ 1858 int error; 1859 struct nameidata nd; 1860 1861 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1862 uap->path, td); 1863 if ((error = namei(&nd)) != 0) 1864 return (error); 1865 NDFREE(&nd, NDF_ONLY_PNBUF); 1866 1867 /* If asynchronous I/O is available, it works for all files. */ 1868 if (uap->name == _PC_ASYNC_IO) 1869 td->td_retval[0] = async_io_version; 1870 else 1871 error = VOP_PATHCONF(nd.ni_vp, uap->name, td->td_retval); 1872 vput(nd.ni_vp); 1873 return (error); 1874} 1875 1876/* 1877 * Return target name of a symbolic link. 1878 */ 1879#ifndef _SYS_SYSPROTO_H_ 1880struct readlink_args { 1881 char *path; 1882 char *buf; 1883 int count; 1884}; 1885#endif 1886/* ARGSUSED */ 1887int 1888readlink(td, uap) 1889 struct thread *td; 1890 register struct readlink_args /* { 1891 char *path; 1892 char *buf; 1893 int count; 1894 } */ *uap; 1895{ 1896 1897 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, 1898 UIO_USERSPACE, uap->count)); 1899} 1900 1901int 1902kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, 1903 enum uio_seg bufseg, int count) 1904{ 1905 register struct vnode *vp; 1906 struct iovec aiov; 1907 struct uio auio; 1908 int error; 1909 struct nameidata nd; 1910 1911 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); 1912 if ((error = namei(&nd)) != 0) 1913 return (error); 1914 NDFREE(&nd, NDF_ONLY_PNBUF); 1915 vp = nd.ni_vp; 1916#ifdef MAC 1917 error = mac_check_vnode_readlink(td->td_ucred, vp); 1918 if (error) { 1919 vput(vp); 1920 return (error); 1921 } 1922#endif 1923 if (vp->v_type != VLNK) 1924 error = EINVAL; 1925 else { 1926 aiov.iov_base = buf; 1927 aiov.iov_len = count; 1928 auio.uio_iov = &aiov; 1929 auio.uio_iovcnt = 1; 1930 auio.uio_offset = 0; 1931 auio.uio_rw = UIO_READ; 1932 auio.uio_segflg = bufseg; 1933 auio.uio_td = td; 1934 auio.uio_resid = count; 1935 error = VOP_READLINK(vp, &auio, td->td_ucred); 1936 } 1937 vput(vp); 1938 td->td_retval[0] = count - auio.uio_resid; 1939 return (error); 1940} 1941 1942/* 1943 * Common implementation code for chflags() and fchflags(). 1944 */ 1945static int 1946setfflags(td, vp, flags) 1947 struct thread *td; 1948 struct vnode *vp; 1949 int flags; 1950{ 1951 int error; 1952 struct mount *mp; 1953 struct vattr vattr; 1954 1955 /* 1956 * Prevent non-root users from setting flags on devices. When 1957 * a device is reused, users can retain ownership of the device 1958 * if they are allowed to set flags and programs assume that 1959 * chown can't fail when done as root. 1960 */ 1961 if (vp->v_type == VCHR || vp->v_type == VBLK) { 1962 error = suser_cred(td->td_ucred, PRISON_ROOT); 1963 if (error) 1964 return (error); 1965 } 1966 1967 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1968 return (error); 1969 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1970 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1971 VATTR_NULL(&vattr); 1972 vattr.va_flags = flags; 1973#ifdef MAC 1974 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags); 1975 if (error == 0) 1976#endif 1977 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 1978 VOP_UNLOCK(vp, 0, td); 1979 vn_finished_write(mp); 1980 return (error); 1981} 1982 1983/* 1984 * Change flags of a file given a path name. 1985 */ 1986#ifndef _SYS_SYSPROTO_H_ 1987struct chflags_args { 1988 char *path; 1989 int flags; 1990}; 1991#endif 1992/* ARGSUSED */ 1993int 1994chflags(td, uap) 1995 struct thread *td; 1996 register struct chflags_args /* { 1997 char *path; 1998 int flags; 1999 } */ *uap; 2000{ 2001 int error; 2002 struct nameidata nd; 2003 2004 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 2005 if ((error = namei(&nd)) != 0) 2006 return (error); 2007 NDFREE(&nd, NDF_ONLY_PNBUF); 2008 error = setfflags(td, nd.ni_vp, uap->flags); 2009 vrele(nd.ni_vp); 2010 return error; 2011} 2012 2013/* 2014 * Same as chflags() but doesn't follow symlinks. 2015 */ 2016int 2017lchflags(td, uap) 2018 struct thread *td; 2019 register struct lchflags_args /* { 2020 char *path; 2021 int flags; 2022 } */ *uap; 2023{ 2024 int error; 2025 struct nameidata nd; 2026 2027 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 2028 if ((error = namei(&nd)) != 0) 2029 return (error); 2030 NDFREE(&nd, NDF_ONLY_PNBUF); 2031 error = setfflags(td, nd.ni_vp, uap->flags); 2032 vrele(nd.ni_vp); 2033 return error; 2034} 2035 2036/* 2037 * Change flags of a file given a file descriptor. 2038 */ 2039#ifndef _SYS_SYSPROTO_H_ 2040struct fchflags_args { 2041 int fd; 2042 int flags; 2043}; 2044#endif 2045/* ARGSUSED */ 2046int 2047fchflags(td, uap) 2048 struct thread *td; 2049 register struct fchflags_args /* { 2050 int fd; 2051 int flags; 2052 } */ *uap; 2053{ 2054 struct file *fp; 2055 int error; 2056 2057 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2058 return (error); 2059 error = setfflags(td, fp->f_data, uap->flags); 2060 fdrop(fp, td); 2061 return (error); 2062} 2063 2064/* 2065 * Common implementation code for chmod(), lchmod() and fchmod(). 2066 */ 2067static int 2068setfmode(td, vp, mode) 2069 struct thread *td; 2070 struct vnode *vp; 2071 int mode; 2072{ 2073 int error; 2074 struct mount *mp; 2075 struct vattr vattr; 2076 2077 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2078 return (error); 2079 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2080 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2081 VATTR_NULL(&vattr); 2082 vattr.va_mode = mode & ALLPERMS; 2083#ifdef MAC 2084 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode); 2085 if (error == 0) 2086#endif 2087 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2088 VOP_UNLOCK(vp, 0, td); 2089 vn_finished_write(mp); 2090 return error; 2091} 2092 2093/* 2094 * Change mode of a file given path name. 2095 */ 2096#ifndef _SYS_SYSPROTO_H_ 2097struct chmod_args { 2098 char *path; 2099 int mode; 2100}; 2101#endif 2102/* ARGSUSED */ 2103int 2104chmod(td, uap) 2105 struct thread *td; 2106 register struct chmod_args /* { 2107 char *path; 2108 int mode; 2109 } */ *uap; 2110{ 2111 2112 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); 2113} 2114 2115int 2116kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) 2117{ 2118 int error; 2119 struct nameidata nd; 2120 2121 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); 2122 if ((error = namei(&nd)) != 0) 2123 return (error); 2124 NDFREE(&nd, NDF_ONLY_PNBUF); 2125 error = setfmode(td, nd.ni_vp, mode); 2126 vrele(nd.ni_vp); 2127 return error; 2128} 2129 2130/* 2131 * Change mode of a file given path name (don't follow links.) 2132 */ 2133#ifndef _SYS_SYSPROTO_H_ 2134struct lchmod_args { 2135 char *path; 2136 int mode; 2137}; 2138#endif 2139/* ARGSUSED */ 2140int 2141lchmod(td, uap) 2142 struct thread *td; 2143 register struct lchmod_args /* { 2144 char *path; 2145 int mode; 2146 } */ *uap; 2147{ 2148 int error; 2149 struct nameidata nd; 2150 2151 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 2152 if ((error = namei(&nd)) != 0) 2153 return (error); 2154 NDFREE(&nd, NDF_ONLY_PNBUF); 2155 error = setfmode(td, nd.ni_vp, uap->mode); 2156 vrele(nd.ni_vp); 2157 return error; 2158} 2159 2160/* 2161 * Change mode of a file given a file descriptor. 2162 */ 2163#ifndef _SYS_SYSPROTO_H_ 2164struct fchmod_args { 2165 int fd; 2166 int mode; 2167}; 2168#endif 2169/* ARGSUSED */ 2170int 2171fchmod(td, uap) 2172 struct thread *td; 2173 register struct fchmod_args /* { 2174 int fd; 2175 int mode; 2176 } */ *uap; 2177{ 2178 struct file *fp; 2179 int error; 2180 2181 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2182 return (error); 2183 error = setfmode(td, fp->f_data, uap->mode); 2184 fdrop(fp, td); 2185 return (error); 2186} 2187 2188/* 2189 * Common implementation for chown(), lchown(), and fchown() 2190 */ 2191static int 2192setfown(td, vp, uid, gid) 2193 struct thread *td; 2194 struct vnode *vp; 2195 uid_t uid; 2196 gid_t gid; 2197{ 2198 int error; 2199 struct mount *mp; 2200 struct vattr vattr; 2201 2202 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2203 return (error); 2204 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2205 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2206 VATTR_NULL(&vattr); 2207 vattr.va_uid = uid; 2208 vattr.va_gid = gid; 2209#ifdef MAC 2210 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid, 2211 vattr.va_gid); 2212 if (error == 0) 2213#endif 2214 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2215 VOP_UNLOCK(vp, 0, td); 2216 vn_finished_write(mp); 2217 return error; 2218} 2219 2220/* 2221 * Set ownership given a path name. 2222 */ 2223#ifndef _SYS_SYSPROTO_H_ 2224struct chown_args { 2225 char *path; 2226 int uid; 2227 int gid; 2228}; 2229#endif 2230/* ARGSUSED */ 2231int 2232chown(td, uap) 2233 struct thread *td; 2234 register struct chown_args /* { 2235 char *path; 2236 int uid; 2237 int gid; 2238 } */ *uap; 2239{ 2240 2241 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); 2242} 2243 2244int 2245kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, 2246 int gid) 2247{ 2248 int error; 2249 struct nameidata nd; 2250 2251 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); 2252 if ((error = namei(&nd)) != 0) 2253 return (error); 2254 NDFREE(&nd, NDF_ONLY_PNBUF); 2255 error = setfown(td, nd.ni_vp, uid, gid); 2256 vrele(nd.ni_vp); 2257 return (error); 2258} 2259 2260/* 2261 * Set ownership given a path name, do not cross symlinks. 2262 */ 2263#ifndef _SYS_SYSPROTO_H_ 2264struct lchown_args { 2265 char *path; 2266 int uid; 2267 int gid; 2268}; 2269#endif 2270/* ARGSUSED */ 2271int 2272lchown(td, uap) 2273 struct thread *td; 2274 register struct lchown_args /* { 2275 char *path; 2276 int uid; 2277 int gid; 2278 } */ *uap; 2279{ 2280 2281 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); 2282} 2283 2284int 2285kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, 2286 int gid) 2287{ 2288 int error; 2289 struct nameidata nd; 2290 2291 NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); 2292 if ((error = namei(&nd)) != 0) 2293 return (error); 2294 NDFREE(&nd, NDF_ONLY_PNBUF); 2295 error = setfown(td, nd.ni_vp, uid, gid); 2296 vrele(nd.ni_vp); 2297 return (error); 2298} 2299 2300/* 2301 * Set ownership given a file descriptor. 2302 */ 2303#ifndef _SYS_SYSPROTO_H_ 2304struct fchown_args { 2305 int fd; 2306 int uid; 2307 int gid; 2308}; 2309#endif 2310/* ARGSUSED */ 2311int 2312fchown(td, uap) 2313 struct thread *td; 2314 register struct fchown_args /* { 2315 int fd; 2316 int uid; 2317 int gid; 2318 } */ *uap; 2319{ 2320 struct file *fp; 2321 int error; 2322 2323 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2324 return (error); 2325 error = setfown(td, fp->f_data, uap->uid, uap->gid); 2326 fdrop(fp, td); 2327 return (error); 2328} 2329 2330/* 2331 * Common implementation code for utimes(), lutimes(), and futimes(). 2332 */ 2333static int 2334getutimes(usrtvp, tvpseg, tsp) 2335 const struct timeval *usrtvp; 2336 enum uio_seg tvpseg; 2337 struct timespec *tsp; 2338{ 2339 struct timeval tv[2]; 2340 const struct timeval *tvp; 2341 int error; 2342 2343 if (usrtvp == NULL) { 2344 microtime(&tv[0]); 2345 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2346 tsp[1] = tsp[0]; 2347 } else { 2348 if (tvpseg == UIO_SYSSPACE) { 2349 tvp = usrtvp; 2350 } else { 2351 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0) 2352 return (error); 2353 tvp = tv; 2354 } 2355 2356 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); 2357 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); 2358 } 2359 return 0; 2360} 2361 2362/* 2363 * Common implementation code for utimes(), lutimes(), and futimes(). 2364 */ 2365static int 2366setutimes(td, vp, ts, numtimes, nullflag) 2367 struct thread *td; 2368 struct vnode *vp; 2369 const struct timespec *ts; 2370 int numtimes; 2371 int nullflag; 2372{ 2373 int error, setbirthtime; 2374 struct mount *mp; 2375 struct vattr vattr; 2376 2377 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2378 return (error); 2379 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2380 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2381 setbirthtime = 0; 2382 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 && 2383 timespeccmp(&ts[1], &vattr.va_birthtime, < )) 2384 setbirthtime = 1; 2385 VATTR_NULL(&vattr); 2386 vattr.va_atime = ts[0]; 2387 vattr.va_mtime = ts[1]; 2388 if (setbirthtime) 2389 vattr.va_birthtime = ts[1]; 2390 if (numtimes > 2) 2391 vattr.va_birthtime = ts[2]; 2392 if (nullflag) 2393 vattr.va_vaflags |= VA_UTIMES_NULL; 2394#ifdef MAC 2395 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime, 2396 vattr.va_mtime); 2397#endif 2398 if (error == 0) 2399 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2400 VOP_UNLOCK(vp, 0, td); 2401 vn_finished_write(mp); 2402 return error; 2403} 2404 2405/* 2406 * Set the access and modification times of a file. 2407 */ 2408#ifndef _SYS_SYSPROTO_H_ 2409struct utimes_args { 2410 char *path; 2411 struct timeval *tptr; 2412}; 2413#endif 2414/* ARGSUSED */ 2415int 2416utimes(td, uap) 2417 struct thread *td; 2418 register struct utimes_args /* { 2419 char *path; 2420 struct timeval *tptr; 2421 } */ *uap; 2422{ 2423 2424 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr, 2425 UIO_USERSPACE)); 2426} 2427 2428int 2429kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, 2430 struct timeval *tptr, enum uio_seg tptrseg) 2431{ 2432 struct timespec ts[2]; 2433 int error; 2434 struct nameidata nd; 2435 2436 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2437 return (error); 2438 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); 2439 if ((error = namei(&nd)) != 0) 2440 return (error); 2441 NDFREE(&nd, NDF_ONLY_PNBUF); 2442 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); 2443 vrele(nd.ni_vp); 2444 return (error); 2445} 2446 2447/* 2448 * Set the access and modification times of a file. 2449 */ 2450#ifndef _SYS_SYSPROTO_H_ 2451struct lutimes_args { 2452 char *path; 2453 struct timeval *tptr; 2454}; 2455#endif 2456/* ARGSUSED */ 2457int 2458lutimes(td, uap) 2459 struct thread *td; 2460 register struct lutimes_args /* { 2461 char *path; 2462 struct timeval *tptr; 2463 } */ *uap; 2464{ 2465 2466 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr, 2467 UIO_USERSPACE)); 2468} 2469 2470int 2471kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, 2472 struct timeval *tptr, enum uio_seg tptrseg) 2473{ 2474 struct timespec ts[2]; 2475 int error; 2476 struct nameidata nd; 2477 2478 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2479 return (error); 2480 NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); 2481 if ((error = namei(&nd)) != 0) 2482 return (error); 2483 NDFREE(&nd, NDF_ONLY_PNBUF); 2484 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); 2485 vrele(nd.ni_vp); 2486 return (error); 2487} 2488 2489/* 2490 * Set the access and modification times of a file. 2491 */ 2492#ifndef _SYS_SYSPROTO_H_ 2493struct futimes_args { 2494 int fd; 2495 struct timeval *tptr; 2496}; 2497#endif 2498/* ARGSUSED */ 2499int 2500futimes(td, uap) 2501 struct thread *td; 2502 register struct futimes_args /* { 2503 int fd; 2504 struct timeval *tptr; 2505 } */ *uap; 2506{ 2507 2508 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE)); 2509} 2510 2511int 2512kern_futimes(struct thread *td, int fd, struct timeval *tptr, 2513 enum uio_seg tptrseg) 2514{ 2515 struct timespec ts[2]; 2516 struct file *fp; 2517 int error; 2518 2519 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2520 return (error); 2521 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) 2522 return (error); 2523 error = setutimes(td, fp->f_data, ts, 2, tptr == NULL); 2524 fdrop(fp, td); 2525 return (error); 2526} 2527 2528/* 2529 * Truncate a file given its path name. 2530 */ 2531#ifndef _SYS_SYSPROTO_H_ 2532struct truncate_args { 2533 char *path; 2534 int pad; 2535 off_t length; 2536}; 2537#endif 2538/* ARGSUSED */ 2539int 2540truncate(td, uap) 2541 struct thread *td; 2542 register struct truncate_args /* { 2543 char *path; 2544 int pad; 2545 off_t length; 2546 } */ *uap; 2547{ 2548 2549 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length)); 2550} 2551 2552int 2553kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length) 2554{ 2555 struct mount *mp; 2556 struct vnode *vp; 2557 struct vattr vattr; 2558 int error; 2559 struct nameidata nd; 2560 2561 if (length < 0) 2562 return(EINVAL); 2563 NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); 2564 if ((error = namei(&nd)) != 0) 2565 return (error); 2566 vp = nd.ni_vp; 2567 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2568 vrele(vp); 2569 return (error); 2570 } 2571 NDFREE(&nd, NDF_ONLY_PNBUF); 2572 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2573 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2574 if (vp->v_type == VDIR) 2575 error = EISDIR; 2576#ifdef MAC 2577 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) { 2578 } 2579#endif 2580 else if ((error = vn_writechk(vp)) == 0 && 2581 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { 2582 VATTR_NULL(&vattr); 2583 vattr.va_size = length; 2584 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2585 } 2586 vput(vp); 2587 vn_finished_write(mp); 2588 return (error); 2589} 2590 2591/* 2592 * Truncate a file given a file descriptor. 2593 */ 2594#ifndef _SYS_SYSPROTO_H_ 2595struct ftruncate_args { 2596 int fd; 2597 int pad; 2598 off_t length; 2599}; 2600#endif 2601/* ARGSUSED */ 2602int 2603ftruncate(td, uap) 2604 struct thread *td; 2605 register struct ftruncate_args /* { 2606 int fd; 2607 int pad; 2608 off_t length; 2609 } */ *uap; 2610{ 2611 struct mount *mp; 2612 struct vattr vattr; 2613 struct vnode *vp; 2614 struct file *fp; 2615 int error; 2616 2617 if (uap->length < 0) 2618 return(EINVAL); 2619 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2620 return (error); 2621 if ((fp->f_flag & FWRITE) == 0) { 2622 fdrop(fp, td); 2623 return (EINVAL); 2624 } 2625 vp = fp->f_data; 2626 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2627 fdrop(fp, td); 2628 return (error); 2629 } 2630 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2631 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2632 if (vp->v_type == VDIR) 2633 error = EISDIR; 2634#ifdef MAC 2635 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred, 2636 vp))) { 2637 } 2638#endif 2639 else if ((error = vn_writechk(vp)) == 0) { 2640 VATTR_NULL(&vattr); 2641 vattr.va_size = uap->length; 2642 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2643 } 2644 VOP_UNLOCK(vp, 0, td); 2645 vn_finished_write(mp); 2646 fdrop(fp, td); 2647 return (error); 2648} 2649 2650#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2651/* 2652 * Truncate a file given its path name. 2653 */ 2654#ifndef _SYS_SYSPROTO_H_ 2655struct otruncate_args { 2656 char *path; 2657 long length; 2658}; 2659#endif 2660/* ARGSUSED */ 2661int 2662otruncate(td, uap) 2663 struct thread *td; 2664 register struct otruncate_args /* { 2665 char *path; 2666 long length; 2667 } */ *uap; 2668{ 2669 struct truncate_args /* { 2670 char *path; 2671 int pad; 2672 off_t length; 2673 } */ nuap; 2674 2675 nuap.path = uap->path; 2676 nuap.length = uap->length; 2677 return (truncate(td, &nuap)); 2678} 2679 2680/* 2681 * Truncate a file given a file descriptor. 2682 */ 2683#ifndef _SYS_SYSPROTO_H_ 2684struct oftruncate_args { 2685 int fd; 2686 long length; 2687}; 2688#endif 2689/* ARGSUSED */ 2690int 2691oftruncate(td, uap) 2692 struct thread *td; 2693 register struct oftruncate_args /* { 2694 int fd; 2695 long length; 2696 } */ *uap; 2697{ 2698 struct ftruncate_args /* { 2699 int fd; 2700 int pad; 2701 off_t length; 2702 } */ nuap; 2703 2704 nuap.fd = uap->fd; 2705 nuap.length = uap->length; 2706 return (ftruncate(td, &nuap)); 2707} 2708#endif /* COMPAT_43 || COMPAT_SUNOS */ 2709 2710/* 2711 * Sync an open file. 2712 */ 2713#ifndef _SYS_SYSPROTO_H_ 2714struct fsync_args { 2715 int fd; 2716}; 2717#endif 2718/* ARGSUSED */ 2719int 2720fsync(td, uap) 2721 struct thread *td; 2722 struct fsync_args /* { 2723 int fd; 2724 } */ *uap; 2725{ 2726 struct vnode *vp; 2727 struct mount *mp; 2728 struct file *fp; 2729 vm_object_t obj; 2730 int error; 2731 2732 GIANT_REQUIRED; 2733 2734 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2735 return (error); 2736 vp = fp->f_data; 2737 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2738 fdrop(fp, td); 2739 return (error); 2740 } 2741 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2742 if (VOP_GETVOBJECT(vp, &obj) == 0) { 2743 VM_OBJECT_LOCK(obj); 2744 vm_object_page_clean(obj, 0, 0, 0); 2745 VM_OBJECT_UNLOCK(obj); 2746 } 2747 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td); 2748 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) 2749 && softdep_fsync_hook != NULL) 2750 error = (*softdep_fsync_hook)(vp); 2751 2752 VOP_UNLOCK(vp, 0, td); 2753 vn_finished_write(mp); 2754 fdrop(fp, td); 2755 return (error); 2756} 2757 2758/* 2759 * Rename files. Source and destination must either both be directories, 2760 * or both not be directories. If target is a directory, it must be empty. 2761 */ 2762#ifndef _SYS_SYSPROTO_H_ 2763struct rename_args { 2764 char *from; 2765 char *to; 2766}; 2767#endif 2768/* ARGSUSED */ 2769int 2770rename(td, uap) 2771 struct thread *td; 2772 register struct rename_args /* { 2773 char *from; 2774 char *to; 2775 } */ *uap; 2776{ 2777 2778 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); 2779} 2780 2781int 2782kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) 2783{ 2784 struct mount *mp = NULL; 2785 struct vnode *tvp, *fvp, *tdvp; 2786 struct nameidata fromnd, tond; 2787 int error; 2788 2789 bwillwrite(); 2790#ifdef MAC 2791 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART, pathseg, 2792 from, td); 2793#else 2794 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td); 2795#endif 2796 if ((error = namei(&fromnd)) != 0) 2797 return (error); 2798#ifdef MAC 2799 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp, 2800 fromnd.ni_vp, &fromnd.ni_cnd); 2801 VOP_UNLOCK(fromnd.ni_dvp, 0, td); 2802 VOP_UNLOCK(fromnd.ni_vp, 0, td); 2803#endif 2804 fvp = fromnd.ni_vp; 2805 if (error == 0) 2806 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH); 2807 if (error != 0) { 2808 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2809 vrele(fromnd.ni_dvp); 2810 vrele(fvp); 2811 goto out1; 2812 } 2813 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | 2814 NOOBJ, pathseg, to, td); 2815 if (fromnd.ni_vp->v_type == VDIR) 2816 tond.ni_cnd.cn_flags |= WILLBEDIR; 2817 if ((error = namei(&tond)) != 0) { 2818 /* Translate error code for rename("dir1", "dir2/."). */ 2819 if (error == EISDIR && fvp->v_type == VDIR) 2820 error = EINVAL; 2821 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2822 vrele(fromnd.ni_dvp); 2823 vrele(fvp); 2824 goto out1; 2825 } 2826 tdvp = tond.ni_dvp; 2827 tvp = tond.ni_vp; 2828 if (tvp != NULL) { 2829 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2830 error = ENOTDIR; 2831 goto out; 2832 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2833 error = EISDIR; 2834 goto out; 2835 } 2836 } 2837 if (fvp == tdvp) 2838 error = EINVAL; 2839 /* 2840 * If the source is the same as the destination (that is, if they 2841 * are links to the same vnode), then there is nothing to do. 2842 */ 2843 if (fvp == tvp) 2844 error = -1; 2845#ifdef MAC 2846 else 2847 error = mac_check_vnode_rename_to(td->td_ucred, tdvp, 2848 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd); 2849#endif 2850out: 2851 if (!error) { 2852 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE); 2853 if (fromnd.ni_dvp != tdvp) { 2854 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 2855 } 2856 if (tvp) { 2857 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE); 2858 } 2859 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2860 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2861 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2862 NDFREE(&tond, NDF_ONLY_PNBUF); 2863 } else { 2864 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2865 NDFREE(&tond, NDF_ONLY_PNBUF); 2866 if (tdvp == tvp) 2867 vrele(tdvp); 2868 else 2869 vput(tdvp); 2870 if (tvp) 2871 vput(tvp); 2872 vrele(fromnd.ni_dvp); 2873 vrele(fvp); 2874 } 2875 vrele(tond.ni_startdir); 2876 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 2877 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 2878 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 2879 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 2880out1: 2881 vn_finished_write(mp); 2882 if (fromnd.ni_startdir) 2883 vrele(fromnd.ni_startdir); 2884 if (error == -1) 2885 return (0); 2886 return (error); 2887} 2888 2889/* 2890 * Make a directory file. 2891 */ 2892#ifndef _SYS_SYSPROTO_H_ 2893struct mkdir_args { 2894 char *path; 2895 int mode; 2896}; 2897#endif 2898/* ARGSUSED */ 2899int 2900mkdir(td, uap) 2901 struct thread *td; 2902 register struct mkdir_args /* { 2903 char *path; 2904 int mode; 2905 } */ *uap; 2906{ 2907 2908 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); 2909} 2910 2911int 2912kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) 2913{ 2914 struct mount *mp; 2915 struct vnode *vp; 2916 struct vattr vattr; 2917 int error; 2918 struct nameidata nd; 2919 2920restart: 2921 bwillwrite(); 2922 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, segflg, path, td); 2923 nd.ni_cnd.cn_flags |= WILLBEDIR; 2924 if ((error = namei(&nd)) != 0) 2925 return (error); 2926 vp = nd.ni_vp; 2927 if (vp != NULL) { 2928 NDFREE(&nd, NDF_ONLY_PNBUF); 2929 vrele(vp); 2930 /* 2931 * XXX namei called with LOCKPARENT but not LOCKLEAF has 2932 * the strange behaviour of leaving the vnode unlocked 2933 * if the target is the same vnode as the parent. 2934 */ 2935 if (vp == nd.ni_dvp) 2936 vrele(nd.ni_dvp); 2937 else 2938 vput(nd.ni_dvp); 2939 return (EEXIST); 2940 } 2941 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 2942 NDFREE(&nd, NDF_ONLY_PNBUF); 2943 vput(nd.ni_dvp); 2944 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 2945 return (error); 2946 goto restart; 2947 } 2948 VATTR_NULL(&vattr); 2949 vattr.va_type = VDIR; 2950 FILEDESC_LOCK(td->td_proc->p_fd); 2951 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 2952 FILEDESC_UNLOCK(td->td_proc->p_fd); 2953#ifdef MAC 2954 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 2955 &vattr); 2956 if (error) 2957 goto out; 2958#endif 2959 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 2960 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2961#ifdef MAC 2962out: 2963#endif 2964 NDFREE(&nd, NDF_ONLY_PNBUF); 2965 vput(nd.ni_dvp); 2966 if (!error) 2967 vput(nd.ni_vp); 2968 vn_finished_write(mp); 2969 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 2970 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 2971 return (error); 2972} 2973 2974/* 2975 * Remove a directory file. 2976 */ 2977#ifndef _SYS_SYSPROTO_H_ 2978struct rmdir_args { 2979 char *path; 2980}; 2981#endif 2982/* ARGSUSED */ 2983int 2984rmdir(td, uap) 2985 struct thread *td; 2986 struct rmdir_args /* { 2987 char *path; 2988 } */ *uap; 2989{ 2990 2991 return (kern_rmdir(td, uap->path, UIO_USERSPACE)); 2992} 2993 2994int 2995kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) 2996{ 2997 struct mount *mp; 2998 struct vnode *vp; 2999 int error; 3000 struct nameidata nd; 3001 3002restart: 3003 bwillwrite(); 3004 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td); 3005 if ((error = namei(&nd)) != 0) 3006 return (error); 3007 vp = nd.ni_vp; 3008 if (vp->v_type != VDIR) { 3009 error = ENOTDIR; 3010 goto out; 3011 } 3012 /* 3013 * No rmdir "." please. 3014 */ 3015 if (nd.ni_dvp == vp) { 3016 error = EINVAL; 3017 goto out; 3018 } 3019 /* 3020 * The root of a mounted filesystem cannot be deleted. 3021 */ 3022 if (vp->v_vflag & VV_ROOT) { 3023 error = EBUSY; 3024 goto out; 3025 } 3026#ifdef MAC 3027 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, 3028 &nd.ni_cnd); 3029 if (error) 3030 goto out; 3031#endif 3032 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3033 NDFREE(&nd, NDF_ONLY_PNBUF); 3034 if (nd.ni_dvp == vp) 3035 vrele(nd.ni_dvp); 3036 else 3037 vput(nd.ni_dvp); 3038 vput(vp); 3039 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3040 return (error); 3041 goto restart; 3042 } 3043 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 3044 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3045 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3046 vn_finished_write(mp); 3047out: 3048 NDFREE(&nd, NDF_ONLY_PNBUF); 3049 if (nd.ni_dvp == vp) 3050 vrele(nd.ni_dvp); 3051 else 3052 vput(nd.ni_dvp); 3053 vput(vp); 3054 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 3055 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 3056 return (error); 3057} 3058 3059#ifdef COMPAT_43 3060/* 3061 * Read a block of directory entries in a filesystem independent format. 3062 */ 3063#ifndef _SYS_SYSPROTO_H_ 3064struct ogetdirentries_args { 3065 int fd; 3066 char *buf; 3067 u_int count; 3068 long *basep; 3069}; 3070#endif 3071int 3072ogetdirentries(td, uap) 3073 struct thread *td; 3074 register struct ogetdirentries_args /* { 3075 int fd; 3076 char *buf; 3077 u_int count; 3078 long *basep; 3079 } */ *uap; 3080{ 3081 struct vnode *vp; 3082 struct file *fp; 3083 struct uio auio, kuio; 3084 struct iovec aiov, kiov; 3085 struct dirent *dp, *edp; 3086 caddr_t dirbuf; 3087 int error, eofflag, readcnt; 3088 long loff; 3089 3090 /* XXX arbitrary sanity limit on `count'. */ 3091 if (uap->count > 64 * 1024) 3092 return (EINVAL); 3093 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3094 return (error); 3095 if ((fp->f_flag & FREAD) == 0) { 3096 fdrop(fp, td); 3097 return (EBADF); 3098 } 3099 vp = fp->f_data; 3100unionread: 3101 if (vp->v_type != VDIR) { 3102 fdrop(fp, td); 3103 return (EINVAL); 3104 } 3105 aiov.iov_base = uap->buf; 3106 aiov.iov_len = uap->count; 3107 auio.uio_iov = &aiov; 3108 auio.uio_iovcnt = 1; 3109 auio.uio_rw = UIO_READ; 3110 auio.uio_segflg = UIO_USERSPACE; 3111 auio.uio_td = td; 3112 auio.uio_resid = uap->count; 3113 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3114 loff = auio.uio_offset = fp->f_offset; 3115#ifdef MAC 3116 error = mac_check_vnode_readdir(td->td_ucred, vp); 3117 if (error) { 3118 VOP_UNLOCK(vp, 0, td); 3119 fdrop(fp, td); 3120 return (error); 3121 } 3122#endif 3123# if (BYTE_ORDER != LITTLE_ENDIAN) 3124 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 3125 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 3126 NULL, NULL); 3127 fp->f_offset = auio.uio_offset; 3128 } else 3129# endif 3130 { 3131 kuio = auio; 3132 kuio.uio_iov = &kiov; 3133 kuio.uio_segflg = UIO_SYSSPACE; 3134 kiov.iov_len = uap->count; 3135 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 3136 kiov.iov_base = dirbuf; 3137 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 3138 NULL, NULL); 3139 fp->f_offset = kuio.uio_offset; 3140 if (error == 0) { 3141 readcnt = uap->count - kuio.uio_resid; 3142 edp = (struct dirent *)&dirbuf[readcnt]; 3143 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 3144# if (BYTE_ORDER == LITTLE_ENDIAN) 3145 /* 3146 * The expected low byte of 3147 * dp->d_namlen is our dp->d_type. 3148 * The high MBZ byte of dp->d_namlen 3149 * is our dp->d_namlen. 3150 */ 3151 dp->d_type = dp->d_namlen; 3152 dp->d_namlen = 0; 3153# else 3154 /* 3155 * The dp->d_type is the high byte 3156 * of the expected dp->d_namlen, 3157 * so must be zero'ed. 3158 */ 3159 dp->d_type = 0; 3160# endif 3161 if (dp->d_reclen > 0) { 3162 dp = (struct dirent *) 3163 ((char *)dp + dp->d_reclen); 3164 } else { 3165 error = EIO; 3166 break; 3167 } 3168 } 3169 if (dp >= edp) 3170 error = uiomove(dirbuf, readcnt, &auio); 3171 } 3172 FREE(dirbuf, M_TEMP); 3173 } 3174 VOP_UNLOCK(vp, 0, td); 3175 if (error) { 3176 fdrop(fp, td); 3177 return (error); 3178 } 3179 if (uap->count == auio.uio_resid) { 3180 if (union_dircheckp) { 3181 error = union_dircheckp(td, &vp, fp); 3182 if (error == -1) 3183 goto unionread; 3184 if (error) { 3185 fdrop(fp, td); 3186 return (error); 3187 } 3188 } 3189 /* 3190 * XXX We could delay dropping the lock above but 3191 * union_dircheckp complicates things. 3192 */ 3193 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td); 3194 if ((vp->v_vflag & VV_ROOT) && 3195 (vp->v_mount->mnt_flag & MNT_UNION)) { 3196 struct vnode *tvp = vp; 3197 vp = vp->v_mount->mnt_vnodecovered; 3198 VREF(vp); 3199 fp->f_data = vp; 3200 fp->f_offset = 0; 3201 vput(tvp); 3202 goto unionread; 3203 } 3204 VOP_UNLOCK(vp, 0, td); 3205 } 3206 error = copyout(&loff, uap->basep, sizeof(long)); 3207 fdrop(fp, td); 3208 td->td_retval[0] = uap->count - auio.uio_resid; 3209 return (error); 3210} 3211#endif /* COMPAT_43 */ 3212 3213/* 3214 * Read a block of directory entries in a filesystem independent format. 3215 */ 3216#ifndef _SYS_SYSPROTO_H_ 3217struct getdirentries_args { 3218 int fd; 3219 char *buf; 3220 u_int count; 3221 long *basep; 3222}; 3223#endif 3224int 3225getdirentries(td, uap) 3226 struct thread *td; 3227 register struct getdirentries_args /* { 3228 int fd; 3229 char *buf; 3230 u_int count; 3231 long *basep; 3232 } */ *uap; 3233{ 3234 struct vnode *vp; 3235 struct file *fp; 3236 struct uio auio; 3237 struct iovec aiov; 3238 long loff; 3239 int error, eofflag; 3240 3241 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3242 return (error); 3243 if ((fp->f_flag & FREAD) == 0) { 3244 fdrop(fp, td); 3245 return (EBADF); 3246 } 3247 vp = fp->f_data; 3248unionread: 3249 if (vp->v_type != VDIR) { 3250 fdrop(fp, td); 3251 return (EINVAL); 3252 } 3253 aiov.iov_base = uap->buf; 3254 aiov.iov_len = uap->count; 3255 auio.uio_iov = &aiov; 3256 auio.uio_iovcnt = 1; 3257 auio.uio_rw = UIO_READ; 3258 auio.uio_segflg = UIO_USERSPACE; 3259 auio.uio_td = td; 3260 auio.uio_resid = uap->count; 3261 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 3262 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3263 loff = auio.uio_offset = fp->f_offset; 3264#ifdef MAC 3265 error = mac_check_vnode_readdir(td->td_ucred, vp); 3266 if (error == 0) 3267#endif 3268 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, 3269 NULL); 3270 fp->f_offset = auio.uio_offset; 3271 VOP_UNLOCK(vp, 0, td); 3272 if (error) { 3273 fdrop(fp, td); 3274 return (error); 3275 } 3276 if (uap->count == auio.uio_resid) { 3277 if (union_dircheckp) { 3278 error = union_dircheckp(td, &vp, fp); 3279 if (error == -1) 3280 goto unionread; 3281 if (error) { 3282 fdrop(fp, td); 3283 return (error); 3284 } 3285 } 3286 /* 3287 * XXX We could delay dropping the lock above but 3288 * union_dircheckp complicates things. 3289 */ 3290 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3291 if ((vp->v_vflag & VV_ROOT) && 3292 (vp->v_mount->mnt_flag & MNT_UNION)) { 3293 struct vnode *tvp = vp; 3294 vp = vp->v_mount->mnt_vnodecovered; 3295 VREF(vp); 3296 fp->f_data = vp; 3297 fp->f_offset = 0; 3298 vput(tvp); 3299 goto unionread; 3300 } 3301 VOP_UNLOCK(vp, 0, td); 3302 } 3303 if (uap->basep != NULL) { 3304 error = copyout(&loff, uap->basep, sizeof(long)); 3305 } 3306 td->td_retval[0] = uap->count - auio.uio_resid; 3307 fdrop(fp, td); 3308 return (error); 3309} 3310#ifndef _SYS_SYSPROTO_H_ 3311struct getdents_args { 3312 int fd; 3313 char *buf; 3314 size_t count; 3315}; 3316#endif 3317int 3318getdents(td, uap) 3319 struct thread *td; 3320 register struct getdents_args /* { 3321 int fd; 3322 char *buf; 3323 u_int count; 3324 } */ *uap; 3325{ 3326 struct getdirentries_args ap; 3327 ap.fd = uap->fd; 3328 ap.buf = uap->buf; 3329 ap.count = uap->count; 3330 ap.basep = NULL; 3331 return getdirentries(td, &ap); 3332} 3333 3334/* 3335 * Set the mode mask for creation of filesystem nodes. 3336 * 3337 * MP SAFE 3338 */ 3339#ifndef _SYS_SYSPROTO_H_ 3340struct umask_args { 3341 int newmask; 3342}; 3343#endif 3344int 3345umask(td, uap) 3346 struct thread *td; 3347 struct umask_args /* { 3348 int newmask; 3349 } */ *uap; 3350{ 3351 register struct filedesc *fdp; 3352 3353 FILEDESC_LOCK(td->td_proc->p_fd); 3354 fdp = td->td_proc->p_fd; 3355 td->td_retval[0] = fdp->fd_cmask; 3356 fdp->fd_cmask = uap->newmask & ALLPERMS; 3357 FILEDESC_UNLOCK(td->td_proc->p_fd); 3358 return (0); 3359} 3360 3361/* 3362 * Void all references to file by ripping underlying filesystem 3363 * away from vnode. 3364 */ 3365#ifndef _SYS_SYSPROTO_H_ 3366struct revoke_args { 3367 char *path; 3368}; 3369#endif 3370/* ARGSUSED */ 3371int 3372revoke(td, uap) 3373 struct thread *td; 3374 register struct revoke_args /* { 3375 char *path; 3376 } */ *uap; 3377{ 3378 struct mount *mp; 3379 struct vnode *vp; 3380 struct vattr vattr; 3381 int error; 3382 struct nameidata nd; 3383 3384 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td); 3385 if ((error = namei(&nd)) != 0) 3386 return (error); 3387 vp = nd.ni_vp; 3388 NDFREE(&nd, NDF_ONLY_PNBUF); 3389 if (vp->v_type != VCHR) { 3390 vput(vp); 3391 return (EINVAL); 3392 } 3393#ifdef MAC 3394 error = mac_check_vnode_revoke(td->td_ucred, vp); 3395 if (error) { 3396 vput(vp); 3397 return (error); 3398 } 3399#endif 3400 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); 3401 if (error) { 3402 vput(vp); 3403 return (error); 3404 } 3405 VOP_UNLOCK(vp, 0, td); 3406 if (td->td_ucred->cr_uid != vattr.va_uid) { 3407 error = suser_cred(td->td_ucred, PRISON_ROOT); 3408 if (error) 3409 goto out; 3410 } 3411 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3412 goto out; 3413 if (vcount(vp) > 1) 3414 VOP_REVOKE(vp, REVOKEALL); 3415 vn_finished_write(mp); 3416out: 3417 vrele(vp); 3418 return (error); 3419} 3420 3421/* 3422 * Convert a user file descriptor to a kernel file entry. 3423 * The file entry is locked upon returning. 3424 */ 3425int 3426getvnode(fdp, fd, fpp) 3427 struct filedesc *fdp; 3428 int fd; 3429 struct file **fpp; 3430{ 3431 int error; 3432 struct file *fp; 3433 3434 fp = NULL; 3435 if (fdp == NULL) 3436 error = EBADF; 3437 else { 3438 FILEDESC_LOCK(fdp); 3439 if ((u_int)fd >= fdp->fd_nfiles || 3440 (fp = fdp->fd_ofiles[fd]) == NULL) 3441 error = EBADF; 3442 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) { 3443 fp = NULL; 3444 error = EINVAL; 3445 } else { 3446 fhold(fp); 3447 error = 0; 3448 } 3449 FILEDESC_UNLOCK(fdp); 3450 } 3451 *fpp = fp; 3452 return (error); 3453} 3454/* 3455 * Get (NFS) file handle 3456 */ 3457#ifndef _SYS_SYSPROTO_H_ 3458struct getfh_args { 3459 char *fname; 3460 fhandle_t *fhp; 3461}; 3462#endif 3463int 3464getfh(td, uap) 3465 struct thread *td; 3466 register struct getfh_args *uap; 3467{ 3468 struct nameidata nd; 3469 fhandle_t fh; 3470 register struct vnode *vp; 3471 int error; 3472 3473 /* 3474 * Must be super user 3475 */ 3476 error = suser(td); 3477 if (error) 3478 return (error); 3479 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td); 3480 error = namei(&nd); 3481 if (error) 3482 return (error); 3483 NDFREE(&nd, NDF_ONLY_PNBUF); 3484 vp = nd.ni_vp; 3485 bzero(&fh, sizeof(fh)); 3486 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3487 error = VFS_VPTOFH(vp, &fh.fh_fid); 3488 vput(vp); 3489 if (error) 3490 return (error); 3491 error = copyout(&fh, uap->fhp, sizeof (fh)); 3492 return (error); 3493} 3494 3495/* 3496 * syscall for the rpc.lockd to use to translate a NFS file handle into 3497 * an open descriptor. 3498 * 3499 * warning: do not remove the suser() call or this becomes one giant 3500 * security hole. 3501 */ 3502#ifndef _SYS_SYSPROTO_H_ 3503struct fhopen_args { 3504 const struct fhandle *u_fhp; 3505 int flags; 3506}; 3507#endif 3508int 3509fhopen(td, uap) 3510 struct thread *td; 3511 struct fhopen_args /* { 3512 const struct fhandle *u_fhp; 3513 int flags; 3514 } */ *uap; 3515{ 3516 struct proc *p = td->td_proc; 3517 struct mount *mp; 3518 struct vnode *vp; 3519 struct fhandle fhp; 3520 struct vattr vat; 3521 struct vattr *vap = &vat; 3522 struct flock lf; 3523 struct file *fp; 3524 register struct filedesc *fdp = p->p_fd; 3525 int fmode, mode, error, type; 3526 struct file *nfp; 3527 int indx; 3528 3529 /* 3530 * Must be super user 3531 */ 3532 error = suser(td); 3533 if (error) 3534 return (error); 3535 3536 fmode = FFLAGS(uap->flags); 3537 /* why not allow a non-read/write open for our lockd? */ 3538 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3539 return (EINVAL); 3540 error = copyin(uap->u_fhp, &fhp, sizeof(fhp)); 3541 if (error) 3542 return(error); 3543 /* find the mount point */ 3544 mp = vfs_getvfs(&fhp.fh_fsid); 3545 if (mp == NULL) 3546 return (ESTALE); 3547 /* now give me my vnode, it gets returned to me locked */ 3548 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3549 if (error) 3550 return (error); 3551 /* 3552 * from now on we have to make sure not 3553 * to forget about the vnode 3554 * any error that causes an abort must vput(vp) 3555 * just set error = err and 'goto bad;'. 3556 */ 3557 3558 /* 3559 * from vn_open 3560 */ 3561 if (vp->v_type == VLNK) { 3562 error = EMLINK; 3563 goto bad; 3564 } 3565 if (vp->v_type == VSOCK) { 3566 error = EOPNOTSUPP; 3567 goto bad; 3568 } 3569 mode = 0; 3570 if (fmode & (FWRITE | O_TRUNC)) { 3571 if (vp->v_type == VDIR) { 3572 error = EISDIR; 3573 goto bad; 3574 } 3575 error = vn_writechk(vp); 3576 if (error) 3577 goto bad; 3578 mode |= VWRITE; 3579 } 3580 if (fmode & FREAD) 3581 mode |= VREAD; 3582 if (fmode & O_APPEND) 3583 mode |= VAPPEND; 3584#ifdef MAC 3585 error = mac_check_vnode_open(td->td_ucred, vp, mode); 3586 if (error) 3587 goto bad; 3588#endif 3589 if (mode) { 3590 error = VOP_ACCESS(vp, mode, td->td_ucred, td); 3591 if (error) 3592 goto bad; 3593 } 3594 if (fmode & O_TRUNC) { 3595 VOP_UNLOCK(vp, 0, td); /* XXX */ 3596 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 3597 vrele(vp); 3598 return (error); 3599 } 3600 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3601 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3602#ifdef MAC 3603 /* 3604 * We don't yet have fp->f_cred, so use td->td_ucred, which 3605 * should be right. 3606 */ 3607 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp); 3608 if (error == 0) { 3609#endif 3610 VATTR_NULL(vap); 3611 vap->va_size = 0; 3612 error = VOP_SETATTR(vp, vap, td->td_ucred, td); 3613#ifdef MAC 3614 } 3615#endif 3616 vn_finished_write(mp); 3617 if (error) 3618 goto bad; 3619 } 3620 error = VOP_OPEN(vp, fmode, td->td_ucred, td); 3621 if (error) 3622 goto bad; 3623 /* 3624 * Make sure that a VM object is created for VMIO support. 3625 */ 3626 if (vn_canvmio(vp) == TRUE) { 3627 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0) 3628 goto bad; 3629 } 3630 if (fmode & FWRITE) 3631 vp->v_writecount++; 3632 3633 /* 3634 * end of vn_open code 3635 */ 3636 3637 if ((error = falloc(td, &nfp, &indx)) != 0) { 3638 if (fmode & FWRITE) 3639 vp->v_writecount--; 3640 goto bad; 3641 } 3642 fp = nfp; 3643 3644 /* 3645 * Hold an extra reference to avoid having fp ripped out 3646 * from under us while we block in the lock op 3647 */ 3648 fhold(fp); 3649 nfp->f_data = vp; 3650 nfp->f_flag = fmode & FMASK; 3651 nfp->f_ops = &vnops; 3652 nfp->f_type = DTYPE_VNODE; 3653 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3654 lf.l_whence = SEEK_SET; 3655 lf.l_start = 0; 3656 lf.l_len = 0; 3657 if (fmode & O_EXLOCK) 3658 lf.l_type = F_WRLCK; 3659 else 3660 lf.l_type = F_RDLCK; 3661 type = F_FLOCK; 3662 if ((fmode & FNONBLOCK) == 0) 3663 type |= F_WAIT; 3664 VOP_UNLOCK(vp, 0, td); 3665 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 3666 type)) != 0) { 3667 /* 3668 * The lock request failed. Normally close the 3669 * descriptor but handle the case where someone might 3670 * have dup()d or close()d it when we weren't looking. 3671 */ 3672 FILEDESC_LOCK(fdp); 3673 if (fdp->fd_ofiles[indx] == fp) { 3674 fdp->fd_ofiles[indx] = NULL; 3675 FILEDESC_UNLOCK(fdp); 3676 fdrop(fp, td); 3677 } else 3678 FILEDESC_UNLOCK(fdp); 3679 /* 3680 * release our private reference 3681 */ 3682 fdrop(fp, td); 3683 return(error); 3684 } 3685 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3686 fp->f_flag |= FHASLOCK; 3687 } 3688 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3689 vfs_object_create(vp, td, td->td_ucred); 3690 3691 VOP_UNLOCK(vp, 0, td); 3692 fdrop(fp, td); 3693 td->td_retval[0] = indx; 3694 return (0); 3695 3696bad: 3697 vput(vp); 3698 return (error); 3699} 3700 3701/* 3702 * Stat an (NFS) file handle. 3703 */ 3704#ifndef _SYS_SYSPROTO_H_ 3705struct fhstat_args { 3706 struct fhandle *u_fhp; 3707 struct stat *sb; 3708}; 3709#endif 3710int 3711fhstat(td, uap) 3712 struct thread *td; 3713 register struct fhstat_args /* { 3714 struct fhandle *u_fhp; 3715 struct stat *sb; 3716 } */ *uap; 3717{ 3718 struct stat sb; 3719 fhandle_t fh; 3720 struct mount *mp; 3721 struct vnode *vp; 3722 int error; 3723 3724 /* 3725 * Must be super user 3726 */ 3727 error = suser(td); 3728 if (error) 3729 return (error); 3730 3731 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 3732 if (error) 3733 return (error); 3734 3735 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3736 return (ESTALE); 3737 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3738 return (error); 3739 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 3740 vput(vp); 3741 if (error) 3742 return (error); 3743 error = copyout(&sb, uap->sb, sizeof(sb)); 3744 return (error); 3745} 3746 3747/* 3748 * Implement fstatfs() for (NFS) file handles. 3749 */ 3750#ifndef _SYS_SYSPROTO_H_ 3751struct fhstatfs_args { 3752 struct fhandle *u_fhp; 3753 struct statfs *buf; 3754}; 3755#endif 3756int 3757fhstatfs(td, uap) 3758 struct thread *td; 3759 struct fhstatfs_args /* { 3760 struct fhandle *u_fhp; 3761 struct statfs *buf; 3762 } */ *uap; 3763{ 3764 struct statfs *sp; 3765 struct mount *mp; 3766 struct vnode *vp; 3767 struct statfs sb; 3768 fhandle_t fh; 3769 int error; 3770 3771 /* 3772 * Must be super user 3773 */ 3774 error = suser(td); 3775 if (error) 3776 return (error); 3777 3778 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 3779 return (error); 3780 3781 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3782 return (ESTALE); 3783 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3784 return (error); 3785 mp = vp->v_mount; 3786 sp = &mp->mnt_stat; 3787 vput(vp); 3788#ifdef MAC 3789 error = mac_check_mount_stat(td->td_ucred, mp); 3790 if (error) 3791 return (error); 3792#endif 3793 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3794 return (error); 3795 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3796 if (suser(td)) { 3797 bcopy(sp, &sb, sizeof(sb)); 3798 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3799 sp = &sb; 3800 } 3801 return (copyout(sp, uap->buf, sizeof(*sp))); 3802} 3803 3804/* 3805 * Syscall to push extended attribute configuration information into the 3806 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3807 * a command (int cmd), and attribute name and misc data. For now, the 3808 * attribute name is left in userspace for consumption by the VFS_op. 3809 * It will probably be changed to be copied into sysspace by the 3810 * syscall in the future, once issues with various consumers of the 3811 * attribute code have raised their hands. 3812 * 3813 * Currently this is used only by UFS Extended Attributes. 3814 */ 3815int 3816extattrctl(td, uap) 3817 struct thread *td; 3818 struct extattrctl_args /* { 3819 const char *path; 3820 int cmd; 3821 const char *filename; 3822 int attrnamespace; 3823 const char *attrname; 3824 } */ *uap; 3825{ 3826 struct vnode *filename_vp; 3827 struct nameidata nd; 3828 struct mount *mp, *mp_writable; 3829 char attrname[EXTATTR_MAXNAMELEN]; 3830 int error; 3831 3832 /* 3833 * uap->attrname is not always defined. We check again later when we 3834 * invoke the VFS call so as to pass in NULL there if needed. 3835 */ 3836 if (uap->attrname != NULL) { 3837 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, 3838 NULL); 3839 if (error) 3840 return (error); 3841 } 3842 3843 /* 3844 * uap->filename is not always defined. If it is, grab a vnode lock, 3845 * which VFS_EXTATTRCTL() will later release. 3846 */ 3847 filename_vp = NULL; 3848 if (uap->filename != NULL) { 3849 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 3850 uap->filename, td); 3851 error = namei(&nd); 3852 if (error) 3853 return (error); 3854 filename_vp = nd.ni_vp; 3855 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK); 3856 } 3857 3858 /* uap->path is always defined. */ 3859 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3860 error = namei(&nd); 3861 if (error) { 3862 if (filename_vp != NULL) 3863 vput(filename_vp); 3864 return (error); 3865 } 3866 mp = nd.ni_vp->v_mount; 3867 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH); 3868 NDFREE(&nd, 0); 3869 if (error) { 3870 if (filename_vp != NULL) 3871 vput(filename_vp); 3872 return (error); 3873 } 3874 3875 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace, 3876 uap->attrname != NULL ? attrname : NULL, td); 3877 3878 vn_finished_write(mp_writable); 3879 /* 3880 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, 3881 * filename_vp, so vrele it if it is defined. 3882 */ 3883 if (filename_vp != NULL) 3884 vrele(filename_vp); 3885 return (error); 3886} 3887 3888/*- 3889 * Set a named extended attribute on a file or directory 3890 * 3891 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3892 * kernelspace string pointer "attrname", userspace buffer 3893 * pointer "data", buffer length "nbytes", thread "td". 3894 * Returns: 0 on success, an error number otherwise 3895 * Locks: none 3896 * References: vp must be a valid reference for the duration of the call 3897 */ 3898static int 3899extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 3900 void *data, size_t nbytes, struct thread *td) 3901{ 3902 struct mount *mp; 3903 struct uio auio; 3904 struct iovec aiov; 3905 ssize_t cnt; 3906 int error; 3907 3908 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3909 if (error) 3910 return (error); 3911 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3912 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3913 3914 aiov.iov_base = data; 3915 aiov.iov_len = nbytes; 3916 auio.uio_iov = &aiov; 3917 auio.uio_iovcnt = 1; 3918 auio.uio_offset = 0; 3919 if (nbytes > INT_MAX) { 3920 error = EINVAL; 3921 goto done; 3922 } 3923 auio.uio_resid = nbytes; 3924 auio.uio_rw = UIO_WRITE; 3925 auio.uio_segflg = UIO_USERSPACE; 3926 auio.uio_td = td; 3927 cnt = nbytes; 3928 3929#ifdef MAC 3930 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, 3931 attrname, &auio); 3932 if (error) 3933 goto done; 3934#endif 3935 3936 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, 3937 td->td_ucred, td); 3938 cnt -= auio.uio_resid; 3939 td->td_retval[0] = cnt; 3940 3941done: 3942 VOP_UNLOCK(vp, 0, td); 3943 vn_finished_write(mp); 3944 return (error); 3945} 3946 3947int 3948extattr_set_fd(td, uap) 3949 struct thread *td; 3950 struct extattr_set_fd_args /* { 3951 int fd; 3952 int attrnamespace; 3953 const char *attrname; 3954 void *data; 3955 size_t nbytes; 3956 } */ *uap; 3957{ 3958 struct file *fp; 3959 char attrname[EXTATTR_MAXNAMELEN]; 3960 int error; 3961 3962 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3963 if (error) 3964 return (error); 3965 3966 error = getvnode(td->td_proc->p_fd, uap->fd, &fp); 3967 if (error) 3968 return (error); 3969 3970 error = extattr_set_vp(fp->f_data, uap->attrnamespace, 3971 attrname, uap->data, uap->nbytes, td); 3972 fdrop(fp, td); 3973 3974 return (error); 3975} 3976 3977int 3978extattr_set_file(td, uap) 3979 struct thread *td; 3980 struct extattr_set_file_args /* { 3981 const char *path; 3982 int attrnamespace; 3983 const char *attrname; 3984 void *data; 3985 size_t nbytes; 3986 } */ *uap; 3987{ 3988 struct nameidata nd; 3989 char attrname[EXTATTR_MAXNAMELEN]; 3990 int error; 3991 3992 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 3993 if (error) 3994 return (error); 3995 3996 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 3997 error = namei(&nd); 3998 if (error) 3999 return (error); 4000 NDFREE(&nd, NDF_ONLY_PNBUF); 4001 4002 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, 4003 uap->data, uap->nbytes, td); 4004 4005 vrele(nd.ni_vp); 4006 return (error); 4007} 4008 4009int 4010extattr_set_link(td, uap) 4011 struct thread *td; 4012 struct extattr_set_link_args /* { 4013 const char *path; 4014 int attrnamespace; 4015 const char *attrname; 4016 void *data; 4017 size_t nbytes; 4018 } */ *uap; 4019{ 4020 struct nameidata nd; 4021 char attrname[EXTATTR_MAXNAMELEN]; 4022 int error; 4023 4024 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4025 if (error) 4026 return (error); 4027 4028 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4029 error = namei(&nd); 4030 if (error) 4031 return (error); 4032 NDFREE(&nd, NDF_ONLY_PNBUF); 4033 4034 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname, 4035 uap->data, uap->nbytes, td); 4036 4037 vrele(nd.ni_vp); 4038 return (error); 4039} 4040 4041/*- 4042 * Get a named extended attribute on a file or directory 4043 * 4044 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4045 * kernelspace string pointer "attrname", userspace buffer 4046 * pointer "data", buffer length "nbytes", thread "td". 4047 * Returns: 0 on success, an error number otherwise 4048 * Locks: none 4049 * References: vp must be a valid reference for the duration of the call 4050 */ 4051static int 4052extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4053 void *data, size_t nbytes, struct thread *td) 4054{ 4055 struct uio auio, *auiop; 4056 struct iovec aiov; 4057 ssize_t cnt; 4058 size_t size, *sizep; 4059 int error; 4060 4061 /* 4062 * XXX: Temporary API compatibility for applications that know 4063 * about this hack ("" means list), but haven't been updated 4064 * for the extattr_list_*() system calls yet. This will go 4065 * away for FreeBSD 5.3. 4066 */ 4067 if (strlen(attrname) == 0) 4068 return (extattr_list_vp(vp, attrnamespace, data, nbytes, td)); 4069 4070 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ); 4071 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4072 4073 /* 4074 * Slightly unusual semantics: if the user provides a NULL data 4075 * pointer, they don't want to receive the data, just the 4076 * maximum read length. 4077 */ 4078 auiop = NULL; 4079 sizep = NULL; 4080 cnt = 0; 4081 if (data != NULL) { 4082 aiov.iov_base = data; 4083 aiov.iov_len = nbytes; 4084 auio.uio_iov = &aiov; 4085 auio.uio_offset = 0; 4086 if (nbytes > INT_MAX) { 4087 error = EINVAL; 4088 goto done; 4089 } 4090 auio.uio_resid = nbytes; 4091 auio.uio_rw = UIO_READ; 4092 auio.uio_segflg = UIO_USERSPACE; 4093 auio.uio_td = td; 4094 auiop = &auio; 4095 cnt = nbytes; 4096 } else 4097 sizep = &size; 4098 4099#ifdef MAC 4100 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, 4101 attrname, &auio); 4102 if (error) 4103 goto done; 4104#endif 4105 4106 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep, 4107 td->td_ucred, td); 4108 4109 if (auiop != NULL) { 4110 cnt -= auio.uio_resid; 4111 td->td_retval[0] = cnt; 4112 } else 4113 td->td_retval[0] = size; 4114 4115done: 4116 VOP_UNLOCK(vp, 0, td); 4117 return (error); 4118} 4119 4120int 4121extattr_get_fd(td, uap) 4122 struct thread *td; 4123 struct extattr_get_fd_args /* { 4124 int fd; 4125 int attrnamespace; 4126 const char *attrname; 4127 void *data; 4128 size_t nbytes; 4129 } */ *uap; 4130{ 4131 struct file *fp; 4132 char attrname[EXTATTR_MAXNAMELEN]; 4133 int error; 4134 4135 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4136 if (error) 4137 return (error); 4138 4139 error = getvnode(td->td_proc->p_fd, uap->fd, &fp); 4140 if (error) 4141 return (error); 4142 4143 error = extattr_get_vp(fp->f_data, uap->attrnamespace, 4144 attrname, uap->data, uap->nbytes, td); 4145 4146 fdrop(fp, td); 4147 return (error); 4148} 4149 4150int 4151extattr_get_file(td, uap) 4152 struct thread *td; 4153 struct extattr_get_file_args /* { 4154 const char *path; 4155 int attrnamespace; 4156 const char *attrname; 4157 void *data; 4158 size_t nbytes; 4159 } */ *uap; 4160{ 4161 struct nameidata nd; 4162 char attrname[EXTATTR_MAXNAMELEN]; 4163 int error; 4164 4165 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4166 if (error) 4167 return (error); 4168 4169 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 4170 error = namei(&nd); 4171 if (error) 4172 return (error); 4173 NDFREE(&nd, NDF_ONLY_PNBUF); 4174 4175 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, 4176 uap->data, uap->nbytes, td); 4177 4178 vrele(nd.ni_vp); 4179 return (error); 4180} 4181 4182int 4183extattr_get_link(td, uap) 4184 struct thread *td; 4185 struct extattr_get_link_args /* { 4186 const char *path; 4187 int attrnamespace; 4188 const char *attrname; 4189 void *data; 4190 size_t nbytes; 4191 } */ *uap; 4192{ 4193 struct nameidata nd; 4194 char attrname[EXTATTR_MAXNAMELEN]; 4195 int error; 4196 4197 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4198 if (error) 4199 return (error); 4200 4201 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4202 error = namei(&nd); 4203 if (error) 4204 return (error); 4205 NDFREE(&nd, NDF_ONLY_PNBUF); 4206 4207 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname, 4208 uap->data, uap->nbytes, td); 4209 4210 vrele(nd.ni_vp); 4211 return (error); 4212} 4213 4214/* 4215 * extattr_delete_vp(): Delete a named extended attribute on a file or 4216 * directory 4217 * 4218 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4219 * kernelspace string pointer "attrname", proc "p" 4220 * Returns: 0 on success, an error number otherwise 4221 * Locks: none 4222 * References: vp must be a valid reference for the duration of the call 4223 */ 4224static int 4225extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4226 struct thread *td) 4227{ 4228 struct mount *mp; 4229 int error; 4230 4231 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 4232 if (error) 4233 return (error); 4234 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 4235 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4236 4237#ifdef MAC 4238 error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, 4239 attrname, NULL); 4240 if (error) 4241 goto done; 4242#endif 4243 4244 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred, 4245 td); 4246#ifdef MAC 4247done: 4248#endif 4249 VOP_UNLOCK(vp, 0, td); 4250 vn_finished_write(mp); 4251 return (error); 4252} 4253 4254int 4255extattr_delete_fd(td, uap) 4256 struct thread *td; 4257 struct extattr_delete_fd_args /* { 4258 int fd; 4259 int attrnamespace; 4260 const char *attrname; 4261 } */ *uap; 4262{ 4263 struct file *fp; 4264 struct vnode *vp; 4265 char attrname[EXTATTR_MAXNAMELEN]; 4266 int error; 4267 4268 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4269 if (error) 4270 return (error); 4271 4272 error = getvnode(td->td_proc->p_fd, uap->fd, &fp); 4273 if (error) 4274 return (error); 4275 vp = fp->f_data; 4276 4277 error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td); 4278 fdrop(fp, td); 4279 return (error); 4280} 4281 4282int 4283extattr_delete_file(td, uap) 4284 struct thread *td; 4285 struct extattr_delete_file_args /* { 4286 const char *path; 4287 int attrnamespace; 4288 const char *attrname; 4289 } */ *uap; 4290{ 4291 struct nameidata nd; 4292 char attrname[EXTATTR_MAXNAMELEN]; 4293 int error; 4294 4295 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4296 if (error) 4297 return(error); 4298 4299 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 4300 error = namei(&nd); 4301 if (error) 4302 return(error); 4303 NDFREE(&nd, NDF_ONLY_PNBUF); 4304 4305 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td); 4306 vrele(nd.ni_vp); 4307 return(error); 4308} 4309 4310int 4311extattr_delete_link(td, uap) 4312 struct thread *td; 4313 struct extattr_delete_link_args /* { 4314 const char *path; 4315 int attrnamespace; 4316 const char *attrname; 4317 } */ *uap; 4318{ 4319 struct nameidata nd; 4320 char attrname[EXTATTR_MAXNAMELEN]; 4321 int error; 4322 4323 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL); 4324 if (error) 4325 return(error); 4326 4327 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4328 error = namei(&nd); 4329 if (error) 4330 return(error); 4331 NDFREE(&nd, NDF_ONLY_PNBUF); 4332 4333 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td); 4334 vrele(nd.ni_vp); 4335 return(error); 4336} 4337 4338/*- 4339 * Retrieve a list of extended attributes on a file or directory. 4340 * 4341 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace", 4342 * userspace buffer pointer "data", buffer length "nbytes", 4343 * thread "td". 4344 * Returns: 0 on success, an error number otherwise 4345 * Locks: none 4346 * References: vp must be a valid reference for the duration of the call 4347 */ 4348static int 4349extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, 4350 size_t nbytes, struct thread *td) 4351{ 4352 struct uio auio, *auiop; 4353 size_t size, *sizep; 4354 struct iovec aiov; 4355 ssize_t cnt; 4356 int error; 4357 4358 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ); 4359 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4360 4361 auiop = NULL; 4362 sizep = NULL; 4363 cnt = 0; 4364 if (data != NULL) { 4365 aiov.iov_base = data; 4366 aiov.iov_len = nbytes; 4367 auio.uio_iov = &aiov; 4368 auio.uio_offset = 0; 4369 if (nbytes > INT_MAX) { 4370 error = EINVAL; 4371 goto done; 4372 } 4373 auio.uio_resid = nbytes; 4374 auio.uio_rw = UIO_READ; 4375 auio.uio_segflg = UIO_USERSPACE; 4376 auio.uio_td = td; 4377 auiop = &auio; 4378 cnt = nbytes; 4379 } else 4380 sizep = &size; 4381 4382#ifdef MAC 4383 error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, 4384 "", &auio); 4385 if (error) 4386 goto done; 4387#endif 4388 4389 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep, 4390 td->td_ucred, td); 4391 4392 if (auiop != NULL) { 4393 cnt -= auio.uio_resid; 4394 td->td_retval[0] = cnt; 4395 } else 4396 td->td_retval[0] = size; 4397 4398done: 4399 VOP_UNLOCK(vp, 0, td); 4400 return (error); 4401} 4402 4403 4404int 4405extattr_list_fd(td, uap) 4406 struct thread *td; 4407 struct extattr_list_fd_args /* { 4408 int fd; 4409 int attrnamespace; 4410 void *data; 4411 size_t nbytes; 4412 } */ *uap; 4413{ 4414 struct file *fp; 4415 int error; 4416 4417 error = getvnode(td->td_proc->p_fd, uap->fd, &fp); 4418 if (error) 4419 return (error); 4420 4421 error = extattr_list_vp(fp->f_data, uap->attrnamespace, uap->data, 4422 uap->nbytes, td); 4423 4424 fdrop(fp, td); 4425 return (error); 4426} 4427 4428int 4429extattr_list_file(td, uap) 4430 struct thread*td; 4431 struct extattr_list_file_args /* { 4432 const char *path; 4433 int attrnamespace; 4434 void *data; 4435 size_t nbytes; 4436 } */ *uap; 4437{ 4438 struct nameidata nd; 4439 int error; 4440 4441 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); 4442 error = namei(&nd); 4443 if (error) 4444 return (error); 4445 NDFREE(&nd, NDF_ONLY_PNBUF); 4446 4447 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, 4448 uap->nbytes, td); 4449 4450 vrele(nd.ni_vp); 4451 return (error); 4452} 4453 4454int 4455extattr_list_link(td, uap) 4456 struct thread*td; 4457 struct extattr_list_link_args /* { 4458 const char *path; 4459 int attrnamespace; 4460 void *data; 4461 size_t nbytes; 4462 } */ *uap; 4463{ 4464 struct nameidata nd; 4465 int error; 4466 4467 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); 4468 error = namei(&nd); 4469 if (error) 4470 return (error); 4471 NDFREE(&nd, NDF_ONLY_PNBUF); 4472 4473 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, 4474 uap->nbytes, td); 4475 4476 vrele(nd.ni_vp); 4477 return (error); 4478} 4479 4480