/* * Write the machine-dependent part of a core dump. */ int cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred, struct core *chdr) { struct coreseg cseg; struct md_coredump md_core; int error; CORE_SETMAGIC(*chdr, COREMAGIC, MID_POWERPC, 0); chdr->c_hdrsize = ALIGN(sizeof *chdr); chdr->c_seghdrsize = ALIGN(sizeof cseg); chdr->c_cpusize = sizeof md_core; process_read_regs(p, &(md_core.regs)); CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_POWERPC, CORE_CPU); cseg.c_addr = 0; cseg.c_size = chdr->c_cpusize; error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); if (error) return error; error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof md_core, (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); if (error) return error; chdr->c_nseg++; return 0; }
static int splat_vnode_test3(struct file *file, void *arg) { vnode_t *vp; char buf1[32] = "SPL VNode Interface Test File\n"; char buf2[32] = ""; int rc; if ((rc = splat_vnode_unlink_all(file, arg, SPLAT_VNODE_TEST3_NAME))) return rc; if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, FWRITE | FREAD | FCREAT | FEXCL, 0644, &vp, 0, 0))) { splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Failed to vn_open test file: %s (%d)\n", SPLAT_VNODE_TEST_FILE_RW, rc); return -rc; } rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0, UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL); if (rc) { splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Failed vn_rdwr write of test file: %s (%d)\n", SPLAT_VNODE_TEST_FILE_RW, rc); goto out; } rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0, UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL); if (rc) { splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Failed vn_rdwr read of test file: %s (%d)\n", SPLAT_VNODE_TEST_FILE_RW, rc); goto out; } if (strncmp(buf1, buf2, strlen(buf1))) { rc = EINVAL; splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Failed strncmp data written does not match " "data read\nWrote: %sRead: %s\n", buf1, buf2); goto out; } rc = 0; splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1); splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read: %s", buf2); splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and " "read expected data pattern to test file: %s\n", SPLAT_VNODE_TEST_FILE_RW); out: VOP_CLOSE(vp, 0, 0, 0, 0, 0); vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE); return -rc; } /* splat_vnode_test3() */
/* * ulfs_read_dotdot: Store in *ino_ret the inode number of the parent * of the directory vp. */ static int ulfs_read_dotdot(struct vnode *vp, kauth_cred_t cred, ino_t *ino_ret) { struct lfs_dirtemplate dirbuf; int error; KASSERT(vp != NULL); KASSERT(ino_ret != NULL); KASSERT(vp->v_type == VDIR); error = vn_rdwr(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL, NULL); if (error) return error; if (ulfs_dirbuf_dotdot_namlen(&dirbuf, vp) != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') /* XXX Panic? Print warning? */ return ENOTDIR; *ino_ret = ulfs_rw32(dirbuf.dotdot_ino, ULFS_IPNEEDSWAP(VTOI(vp))); return 0; }
/* * symlink -- make a symbolic link */ static int ext2_symlink(struct vop_symlink_args *ap) { struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ext2_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { ip = VTOI(vp); bcopy(ap->a_target, (char *)ip->i_shortlink, len); ip->i_size = len; ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, ap->a_cnp->cn_cred, NOCRED, NULL, NULL); if (error) vput(vp); return (error); }
static int zfs_replay_write(zfsvfs_t *zsb, lr_write_t *lr, boolean_t byteswap) { char *data = (char *)(lr + 1); /* data follows lr_write_t */ znode_t *zp; int error; uint64_t eod, offset, length; ssize_t resid; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0) { /* * As we can log writes out of order, it's possible the * file has been removed. In this case just drop the write * and return success. */ if (error == ENOENT) error = 0; return (error); } zfs_znode_wait_vnode(zp); offset = lr->lr_offset; length = lr->lr_length; eod = offset + length; /* end of data for this write */ /* * This may be a write from a dmu_sync() for a whole block, * and may extend beyond the current end of the file. * We can't just replay what was written for this TX_WRITE as * a future TX_WRITE2 may extend the eof and the data for that * write needs to be there. So we write the whole block and * reduce the eof. This needs to be done within the single dmu * transaction created within vn_rdwr -> zfs_write. So a possible * new end of file is passed through in zsb->z_replay_eof */ zsb->z_replay_eof = 0; /* 0 means don't change end of file */ /* If it's a dmu_sync() block, write the whole block */ if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); if (length < blocksize) { offset -= offset % blocksize; length = blocksize; } if (zp->z_size < eod) zsb->z_replay_eof = eod; } error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); VN_RELE(ZTOV(zp)); zsb->z_replay_eof = 0; /* safety */ return (error); }
/* Generic write interface */ int afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr, afs_int32 asize) { unsigned int resid; afs_int32 code; AFS_STATCNT(osi_Write); if (!afile) osi_Panic("afs_osi_Write called with null afile"); if (offset != -1) afile->offset = offset; AFS_GUNLOCK(); VOP_LOCK(afile->vnode, LK_EXCLUSIVE | LK_RETRY); code = vn_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize, afile->offset, AFS_UIOSYS, IO_UNIT, afs_osi_credp, &resid, osi_curproc()); VOP_UNLOCK(afile->vnode, 0); AFS_GLOCK(); if (code == 0) { code = asize - resid; afile->offset += code; if (afile->offset > afile->size) afile->size = afile->offset; } else code = -1; if (afile->proc) (*afile->proc) (afile, code); return code; }
static int vfs_mountroot_readconf(struct thread *td, struct sbuf *sb) { static char buf[128]; struct nameidata nd; off_t ofs; ssize_t resid; int error, flags, len; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/.mount.conf", td); flags = FREAD; error = vn_open(&nd, &flags, 0, NULL); if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); ofs = 0; len = sizeof(buf) - 1; while (1) { error = vn_rdwr(UIO_READ, nd.ni_vp, buf, len, ofs, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); if (error) break; if (resid == len) break; buf[len - resid] = 0; sbuf_printf(sb, "%s", buf); ofs += len - resid; } VOP_UNLOCK(nd.ni_vp, 0); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); return (error); }
static int kfread(kfile_t *fp, char *buf, ssize_t bufsiz, ssize_t *ret_n) { ssize_t resid; int err; ssize_t n; ASSERT(modrootloaded); if (fp->kf_state != 0) return (fp->kf_state); err = vn_rdwr(UIO_READ, fp->kf_vp, buf, bufsiz, fp->kf_fpos, UIO_SYSSPACE, 0, (rlim64_t)0, kcred, &resid); if (err != 0) { KFDEBUG((CE_CONT, "%s: read error %d\n", fp->kf_fname, err)); fp->kf_state = err; return (err); } ASSERT(resid >= 0 && resid <= bufsiz); n = bufsiz - resid; KFDEBUG1((CE_CONT, "%s: read %ld bytes ok %ld bufsiz, %ld resid\n", fp->kf_fname, n, bufsiz, resid)); fp->kf_fpos += n; *ret_n = n; return (0); }
/* Generic write interface */ int afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr, afs_int32 asize) { size_t resid; afs_int32 code; AFS_STATCNT(osi_Write); if (!afile) osi_Panic("afs_osi_Write called with null afile"); if (offset != -1) afile->offset = offset; AFS_GUNLOCK(); code = vn_rdwr(UIO_WRITE, afile->vnode, aptr, asize, afile->offset, AFS_UIOSYS, IO_UNIT, afs_osi_credp, &resid, osi_curproc()); AFS_GLOCK(); if (code == 0) { code = asize - resid; afile->offset += code; if (afile->offset > afile->size) afile->size = afile->offset; } else { if (code > 0) { code = -code; } } if (afile->proc) (*afile->proc) (afile, code); return code; }
/* * symlink -- make a symbolic link */ int ufs_symlink(void *v) { struct vop_symlink_args *ap = v; struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); VN_KNOTE(ap->a_dvp, NOTE_WRITE); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { ip = VTOI(vp); bcopy(ap->a_target, (char *)SHORTLINK(ip), len); DIP_ASSIGN(ip, size, len); ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL, curproc); vput(vp); return (error); }
int randomdev_write_file(const char *filename, void *buf, size_t length) { struct nameidata nd; struct thread* td = curthread; int error; ssize_t resid; int flags; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); flags = FWRITE | O_CREAT | O_TRUNC; error = vn_open(&nd, &flags, 0, NULL); if (error == 0) { NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_vp->v_type != VREG) error = ENOEXEC; else error = vn_rdwr(UIO_WRITE, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); VOP_UNLOCK(nd.ni_vp, 0); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); } return (error); }
static void sd_log(vfs_context_t ctx, const char *fmt, ...) { int resid, log_error, len; char logbuf[100]; va_list arglist; /* If the log isn't open yet, open it */ if (sd_logvp == NULLVP) { if (sd_openlog(ctx) != 0) { /* Couldn't open, we fail out */ return; } } va_start(arglist, fmt); len = vsnprintf(logbuf, sizeof(logbuf), fmt, arglist); log_error = vn_rdwr(UIO_WRITE, sd_logvp, (caddr_t)logbuf, len, sd_log_offset, UIO_SYSSPACE, IO_UNIT | IO_NOAUTH, vfs_context_ucred(ctx), &resid, vfs_context_proc(ctx)); if (log_error == EIO || log_error == 0) { sd_log_offset += (len - resid); } va_end(arglist); }
/* * symlink -- make a symbolic link */ int ext2fs_symlink(void *v) { struct vop_symlink_args *ap = v; struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ext2fs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { ip = VTOI(vp); bcopy(ap->a_target, (char *)ip->i_e2din->e2di_shortlink, len); error = ext2fs_setsize(ip, len); if (error) goto bad; ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL, curproc); bad: vput(vp); return (error); }
static int zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) { char *data = (char *)(lr + 1); /* data follows lr_write_t */ znode_t *zp; int error; ssize_t resid; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { /* * As we can log writes out of order, it's possible the * file has been removed. In this case just drop the write * and return success. */ if (error == ENOENT) error = 0; return (error); } error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, lr->lr_length, lr->lr_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); VN_RELE(ZTOV(zp)); return (error); }
/* * Crack open a '#!' line. */ static int getintphead(struct vnode *vp, struct intpdata *idatap) { int error; char *cp, *linep = idatap->intp; ssize_t resid; /* * Read the entire line and confirm that it starts with '#!'. */ if (error = vn_rdwr(UIO_READ, vp, linep, INTPSZ, (offset_t)0, UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid)) return (error); if (resid > INTPSZ-2 || linep[0] != '#' || linep[1] != '!') return (ENOEXEC); /* * Blank all white space and find the newline. */ for (cp = &linep[2]; cp < &linep[INTPSZ] && *cp != '\n'; cp++) if (*cp == '\t') *cp = ' '; if (cp >= &linep[INTPSZ]) return (ENOEXEC); ASSERT(*cp == '\n'); *cp = '\0'; /* * Locate the beginning and end of the interpreter name. * In addition to the name, one additional argument may * optionally be included here, to be prepended to the * arguments provided on the command line. Thus, for * example, you can say * * #! /usr/bin/awk -f */ for (cp = &linep[2]; *cp == ' '; cp++) ; if (*cp == '\0') return (ENOEXEC); idatap->intp_name = cp; while (*cp && *cp != ' ') cp++; if (*cp == '\0') idatap->intp_arg = NULL; else { *cp++ = '\0'; while (*cp == ' ') cp++; if (*cp == '\0') idatap->intp_arg = NULL; else { idatap->intp_arg = cp; while (*cp && *cp != ' ') cp++; *cp = '\0'; } } return (0); }
int cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred, struct core *chdr) { int error; struct { struct reg regs; struct fpreg fpregs; } cpustate; struct coreseg cseg; CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); chdr->c_hdrsize = ALIGN(sizeof(*chdr)); chdr->c_seghdrsize = ALIGN(sizeof(cseg)); chdr->c_cpusize = sizeof(cpustate); /* Save integer registers. */ error = process_read_regs(p, &cpustate.regs); if (error) return error; /* Save floating point registers. */ error = process_read_fpregs(p, &cpustate.fpregs); if (error) return error; CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); cseg.c_addr = 0; cseg.c_size = chdr->c_cpusize; error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); if (error) return error; error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cpustate, sizeof(cpustate), (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); if (error) return error; chdr->c_nseg++; return error; }
int kern_write_file(struct kern_direct_file_io_ref_t * ref, off_t offset, caddr_t addr, vm_size_t len) { return (vn_rdwr(UIO_WRITE, ref->vp, addr, len, offset, UIO_SYSSPACE, IO_SYNC|IO_NODELOCKED|IO_UNIT, vfs_context_ucred(ref->ctx), (int *) 0, vfs_context_proc(ref->ctx))); }
int kern_read_file(struct kern_direct_file_io_ref_t * ref, off_t offset, void * addr, size_t len, int ioflag) { return (vn_rdwr(UIO_READ, ref->vp, addr, len, offset, UIO_SYSSPACE, ioflag|IO_SYNC|IO_NODELOCKED|IO_UNIT, vfs_context_ucred(ref->ctx), (int *) 0, vfs_context_proc(ref->ctx))); }
static int zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) { char *data = (char *)(lr + 1); /* data follows lr_write_t */ znode_t *zp; int error; ssize_t resid; uint64_t orig_eof, eod, offset, length; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { /* * As we can log writes out of order, it's possible the * file has been removed. In this case just drop the write * and return success. */ if (error == ENOENT) error = 0; return (error); } offset = lr->lr_offset; length = lr->lr_length; eod = offset + length; /* end of data for this write */ orig_eof = zp->z_phys->zp_size; /* If it's a dmu_sync() block, write the whole block */ if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); if (length < blocksize) { offset -= offset % blocksize; length = blocksize; } } error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); /* * This may be a write from a dmu_sync() for a whole block, * and may extend beyond the current end of the file. * We can't just replay what was written for this TX_WRITE as * a future TX_WRITE2 may extend the eof and the data for that * write needs to be there. So we write the whole block and * reduce the eof. */ if (orig_eof < zp->z_phys->zp_size) /* file length grew ? */ zp->z_phys->zp_size = eod; VN_RELE(ZTOV(zp)); return (error); }
static void vdev_file_io_start(zio_t *zio) { vdev_t *vd = zio->io_vd; vdev_file_t *vf = vd->vdev_tsd; ssize_t resid = 0; if (zio->io_type == ZIO_TYPE_IOCTL) { if (!vdev_readable(vd)) { zio->io_error = SET_ERROR(ENXIO); zio_interrupt(zio); return; } switch (zio->io_cmd) { case DKIOCFLUSHWRITECACHE: if (!vnode_getwithvid(vf->vf_vnode, vf->vf_vid)) { zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, kcred, NULL); vnode_put(vf->vf_vnode); } break; default: zio->io_error = SET_ERROR(ENOTSUP); } zio_interrupt(zio); return; } ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); if (!vnode_getwithvid(vf->vf_vnode, vf->vf_vid)) { /* VERIFY3U(taskq_dispatch(vdev_file_taskq, vdev_file_io_strategy, zio, TQ_PUSHPAGE), !=, 0); */ zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data, zio->io_size, zio->io_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); vnode_put(vf->vf_vnode); } if (resid != 0 && zio->io_error == 0) zio->io_error = SET_ERROR(ENOSPC); zio_interrupt(zio); return; }
int vmcmd_readvn(struct lwp *l, struct exec_vmcmd *cmd) { struct proc *p = l->l_proc; int error; vm_prot_t prot, maxprot; error = vn_rdwr(UIO_READ, cmd->ev_vp, (void *)cmd->ev_addr, cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT, l->l_cred, NULL, l); if (error) return error; prot = cmd->ev_prot; maxprot = VM_PROT_ALL; #ifdef PAX_MPROTECT pax_mprotect(l, &prot, &maxprot); #endif /* PAX_MPROTECT */ #ifdef PMAP_NEED_PROCWR /* * we had to write the process, make sure the pages are synched * with the instruction cache. */ if (prot & VM_PROT_EXECUTE) pmap_procwr(p, cmd->ev_addr, cmd->ev_len); #endif /* * we had to map in the area at PROT_ALL so that vn_rdwr() * could write to it. however, the caller seems to want * it mapped read-only, so now we are going to have to call * uvm_map_protect() to fix up the protection. ICK. */ if (maxprot != VM_PROT_ALL) { error = uvm_map_protect(&p->p_vmspace->vm_map, trunc_page(cmd->ev_addr), round_page(cmd->ev_addr + cmd->ev_len), maxprot, true); if (error) return (error); } if (prot != maxprot) { error = uvm_map_protect(&p->p_vmspace->vm_map, trunc_page(cmd->ev_addr), round_page(cmd->ev_addr + cmd->ev_len), prot, false); if (error) return (error); } return 0; }
/* * Check if source directory is in the path of the target directory. * Target is supplied locked, source is unlocked. * The target is always vput before returning. */ int ext2_checkpath(struct inode *source, struct inode *target, struct ucred *cred) { struct vnode *vp; int error, rootino, namlen; struct dirtemplate dirbuf; vp = ITOV(target); if (target->i_number == source->i_number) { error = EEXIST; goto out; } rootino = ROOTINO; error = 0; if (target->i_number == rootino) goto out; for (;;) { if (vp->v_type != VDIR) { error = ENOTDIR; break; } error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL); if (error != 0) break; namlen = dirbuf.dotdot_type; /* like ufs little-endian */ if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { error = ENOTDIR; break; } if (dirbuf.dotdot_ino == source->i_number) { error = EINVAL; break; } if (dirbuf.dotdot_ino == rootino) break; vput(vp); if ((error = VFS_VGET(vp->v_mount, NULL, dirbuf.dotdot_ino, &vp)) != 0) { vp = NULL; break; } } out: if (error == ENOTDIR) kprintf("checkpath: .. not a directory\n"); if (vp != NULL) vput(vp); return (error); }
static int kfwrite(kfile_t *fp, char *buf, ssize_t bufsiz, ssize_t *ret_n) { rlim64_t rlimit; ssize_t resid; int err; ssize_t len; ssize_t n = 0; ASSERT(modrootloaded); if (fp->kf_state != 0) return (fp->kf_state); len = bufsiz; rlimit = bufsiz + 1; for (;;) { err = vn_rdwr(UIO_WRITE, fp->kf_vp, buf, len, fp->kf_fpos, UIO_SYSSPACE, FSYNC, rlimit, kcred, &resid); if (err) { KFDEBUG((CE_CONT, "%s: write error %d\n", fp->kf_fname, err)); fp->kf_state = err; return (err); } KFDEBUG1((CE_CONT, "%s: write %ld bytes ok %ld resid\n", fp->kf_fname, len-resid, resid)); ASSERT(resid >= 0 && resid <= len); n += (len - resid); if (resid == 0) break; if (resid == len) { KFDEBUG((CE_CONT, "%s: filesystem full?\n", fp->kf_fname)); fp->kf_state = ENOSPC; return (ENOSPC); } len -= resid; buf += len; fp->kf_fpos += len; len = resid; } ASSERT(n == bufsiz); KFDEBUG1((CE_CONT, "%s: wrote %ld bytes ok\n", fp->kf_fname, n)); *ret_n = n; return (0); }
static int spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl) { size_t buflen; char *buf; vnode_t *vp; int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX; char *temp; int err; /* * If the nvlist is empty (NULL), then remove the old cachefile. */ if (nvl == NULL) { err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE); return (err); } /* * Pack the configuration into a buffer. */ VERIFY(nvlist_size(nvl, &buflen, NV_ENCODE_XDR) == 0); buf = kmem_alloc(buflen, KM_SLEEP); temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP); VERIFY(nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_XDR, KM_SLEEP) == 0); /* * Write the configuration to disk. We need to do the traditional * 'write to temporary file, sync, move over original' to make sure we * always have a consistent view of the data. */ (void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path); err = vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0); if (err == 0) { err = vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, NULL); if (err == 0) err = VOP_FSYNC(vp, FSYNC, kcred, NULL); if (err == 0) err = vn_rename(temp, dp->scd_path, UIO_SYSSPACE); (void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL); } (void) vn_remove(temp, UIO_SYSSPACE, RMFILE); kmem_free(buf, buflen); kmem_free(temp, MAXPATHLEN); return (err); }
/* * Check if a directory is empty or not. * Inode supplied must be locked. * * Using a struct dirtemplate here is not precisely * what we want, but better than using a struct direct. * * NB: does not handle corrupted directories. */ int ufs_dirempty(struct inode *ip, ufsino_t parentino, struct ucred *cred) { off_t off, m; struct dirtemplate dbuf; struct direct *dp = (struct direct *)&dbuf; int error, namlen; size_t count; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) m = DIP(ip, size); for (off = 0; off < m; off += dp->d_reclen) { error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED, cred, &count, curproc); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. */ if (error || count != 0) return (0); /* avoid infinite loops */ if (dp->d_reclen == 0) return (0); /* skip empty entries */ if (dp->d_ino == 0) continue; /* accept only "." and ".." */ # if (BYTE_ORDER == LITTLE_ENDIAN) if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0) namlen = dp->d_namlen; else namlen = dp->d_type; # else namlen = dp->d_namlen; # endif if (namlen > 2) return (0); if (dp->d_name[0] != '.') return (0); /* * At this point namlen must be 1 or 2. * 1 implies ".", 2 implies ".." if second * char is also "." */ if (namlen == 1 && dp->d_ino == ip->i_number) continue; if (dp->d_name[1] == '.' && dp->d_ino == parentino) continue; return (0); } return (1); }
int vm_record_file_write(vnode_t vp, uint64_t offset, char *buf, int size) { int error = 0; vfs_context_t ctx; ctx = vfs_context_kernel(); error = vn_rdwr(UIO_WRITE, vp, (caddr_t)buf, size, offset, UIO_SYSSPACE, IO_NODELOCKED, vfs_context_ucred(ctx), (int *) 0, vfs_context_proc(ctx)); return (error); }
static int verify_file(struct ucred *cred, struct vnode *vp) { char buffer[256]; char hash[SHA256_DIGEST_LENGTH > uECC_BYTES ? SHA256_DIGEST_LENGTH : uECC_BYTES]; char signature[2*uECC_BYTES]; int error, len; ssize_t resid; off_t i, size; SHA256_CTX ctx; struct stat stat; i = 0; error = vn_stat(vp, &stat, cred, NOCRED, curthread); size = stat.st_size; if (error) return (EPERM); len = sizeof(signature); error = vn_extattr_get(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM, "signature", &len, signature, curthread); if (error) return (EPERM); #ifdef DEBUG printf("Signature: "); print_hex(signature, sizeof(signature)); #endif SHA256_Init(&ctx); while(i < size && !error) { len = size - i > sizeof(buffer) ? sizeof(buffer) : size - i; error = vn_rdwr(UIO_READ, vp, buffer, len, i, UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &resid, curthread); SHA256_Update(&ctx, buffer, len); i += len; } if (error) return (EPERM); SHA256_Final(hash, &ctx); #ifdef DEBUG printf("Hash: "); print_hex(hash, sizeof(hash)); #endif if (!uECC_verify(pubkey, hash, signature)) return (EPERM); return (0); }
/* * Helper function for findroot(): * Return non-zero if wedge device matches bootinfo. */ static int match_bootwedge(device_t dv, struct btinfo_bootwedge *biw) { MD5_CTX ctx; struct vnode *tmpvn; int error; uint8_t bf[DEV_BSIZE]; uint8_t hash[16]; int found = 0; daddr_t blk; uint64_t nblks; /* * If the boot loader didn't specify the sector, abort. */ if (biw->matchblk == -1) { DPRINTF(("%s: no sector specified for %s\n", __func__, device_xname(dv))); return 0; } if ((tmpvn = opendisk(dv)) == NULL) { DPRINTF(("%s: can't open %s\n", __func__, device_xname(dv))); return 0; } MD5Init(&ctx); for (blk = biw->matchblk, nblks = biw->matchnblks; nblks != 0; nblks--, blk++) { error = vn_rdwr(UIO_READ, tmpvn, (void *) bf, sizeof(bf), blk * DEV_BSIZE, UIO_SYSSPACE, 0, NOCRED, NULL, NULL); if (error) { printf("%s: unable to read block %" PRId64 " " "of dev %s (%d)\n", __func__, blk, device_xname(dv), error); goto closeout; } MD5Update(&ctx, bf, sizeof(bf)); } MD5Final(hash, &ctx); /* Compare with the provided hash. */ found = memcmp(biw->matchhash, hash, sizeof(hash)) == 0; DPRINTF(("%s: %s found=%d\n", __func__, device_xname(dv), found)); closeout: VOP_CLOSE(tmpvn, FREAD, NOCRED); vput(tmpvn); return found; }
/* * ext2fs_rename_replace_dotdot: Change the target of the `..' entry of * the directory vp from fdvp to tdvp. */ static int ext2fs_rename_replace_dotdot(struct vnode *vp, struct vnode *fdvp, struct vnode *tdvp, kauth_cred_t cred) { struct ext2fs_dirtemplate dirbuf; int error; /* XXX Does it make sense to do this before the sanity checks below? */ KASSERT(0 < VTOI(fdvp)->i_e2fs_nlink); VTOI(fdvp)->i_e2fs_nlink--; VTOI(fdvp)->i_flag |= IN_CHANGE; error = vn_rdwr(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL, NULL); if (error) return error; if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { ufs_dirbad(VTOI(vp), (doff_t)12, "bad `..' entry"); return 0; } if (fs2h32(dirbuf.dotdot_ino) != VTOI(fdvp)->i_number) { ufs_dirbad(VTOI(vp), (doff_t)12, "`..' does not point at parent"); return 0; } dirbuf.dotdot_ino = h2fs32(VTOI(tdvp)->i_number); /* XXX WTF? Why not check error? */ (void)vn_rdwr(UIO_WRITE, vp, &dirbuf, sizeof dirbuf, (off_t)0, UIO_SYSSPACE, (IO_NODELOCKED | IO_SYNC), cred, NULL, NULL); return 0; }
static int in_write(struct vnode *vp, offset_t *vo, caddr_t buf, int count) { int error; ssize_t resid; rlim64_t rlimit = *vo + count + 1; error = vn_rdwr(UIO_WRITE, vp, buf, count, *vo, UIO_SYSSPACE, 0, rlimit, CRED(), &resid); *vo += (offset_t)(count - resid); return (error); }