/* $OpenBSD: diskmap.c,v 1.20 2018/05/09 08:42:02 mpi Exp $ */ /* * Copyright (c) 2009, 2010 Joel Sing * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Disk mapper. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int diskmapopen(dev_t dev, int flag, int fmt, struct proc *p) { return 0; } int diskmapclose(dev_t dev, int flag, int fmt, struct proc *p) { return 0; } int diskmapioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct dk_diskmap *dm; struct nameidata ndp; struct filedesc *fdp = p->p_fd; struct file *fp = NULL; struct vnode *vp = NULL, *ovp; char *devname; int fd, error = EINVAL; if (cmd != DIOCMAP) return EINVAL; /* * Map a request for a disk to the correct device. We should be * supplied with either a diskname or a disklabel UID. */ dm = (struct dk_diskmap *)addr; fd = dm->fd; devname = malloc(PATH_MAX, M_DEVBUF, M_WAITOK); if (copyinstr(dm->device, devname, PATH_MAX, NULL)) goto invalid; if (disk_map(devname, devname, PATH_MAX, dm->flags) == 0) if (copyoutstr(devname, dm->device, PATH_MAX, NULL)) goto invalid; /* Attempt to open actual device. */ if ((error = getvnode(p, fd, &fp)) != 0) goto invalid; KASSERT(fp->f_type == DTYPE_VNODE); KASSERT(fp->f_ops == &vnops); fdplock(fdp); NDINIT(&ndp, 0, 0, UIO_SYSSPACE, devname, p); ndp.ni_pledge = PLEDGE_RPATH; if ((error = vn_open(&ndp, fp->f_flag, 0)) != 0) goto bad; vp = ndp.ni_vp; /* Close the original vnode. */ ovp = (struct vnode *)fp->f_data; if (fp->f_flag & FWRITE) ovp->v_writecount--; if (ovp->v_writecount == 0) { vn_lock(ovp, LK_EXCLUSIVE | LK_RETRY); VOP_CLOSE(ovp, fp->f_flag, p->p_ucred, p); vput(ovp); } fp->f_data = (caddr_t)vp; fp->f_offset = 0; mtx_enter(&fp->f_mtx); fp->f_rxfer = 0; fp->f_wxfer = 0; fp->f_seek = 0; fp->f_rbytes = 0; fp->f_wbytes = 0; mtx_leave(&fp->f_mtx); VOP_UNLOCK(vp); FRELE(fp, p); fdpunlock(fdp); free(devname, M_DEVBUF, PATH_MAX); return 0; bad: if (vp) vput(vp); if (fp) FRELE(fp, p); fdpunlock(fdp); invalid: free(devname, M_DEVBUF, PATH_MAX); return (error); } int diskmapread(dev_t dev, struct uio *uio, int flag) { return ENXIO; } int diskmapwrite(dev_t dev, struct uio *uio, int flag) { return ENXIO; }