/* $OpenBSD: diskmap.c,v 1.24 2018/08/20 14:59:02 visa 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 *fp0 = NULL, *fp = NULL; struct vnode *vp = NULL; char *devname, flags; 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, &fp0)) != 0) goto invalid; NDINIT(&ndp, 0, 0, UIO_SYSSPACE, devname, p); ndp.ni_pledge = PLEDGE_RPATH; ndp.ni_unveil = UNVEIL_READ; if ((error = vn_open(&ndp, fp0->f_flag, 0)) != 0) goto invalid; vp = ndp.ni_vp; VOP_UNLOCK(vp); fdplock(fdp); /* * Stop here if the 'struct file *' has been replaced, * for example by another thread calling dup2(2), while * this thread was sleeping in vn_open(). * * Note that this would not happen for correct usages of * "/dev/diskmap". */ if (fdp->fd_ofiles[fd] != fp0) { error = EAGAIN; goto bad; } fp = fnew(p); if (fp == NULL) { error = ENFILE; goto bad; } /* Zap old file. */ mtx_enter(&fdp->fd_fplock); KASSERT(fdp->fd_ofiles[fd] == fp0); flags = fdp->fd_ofileflags[fd]; fdp->fd_ofiles[fd] = NULL; fdp->fd_ofileflags[fd] = 0; mtx_leave(&fdp->fd_fplock); /* Insert new file. */ fp->f_flag = fp0->f_flag; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; fdinsert(fdp, fd, flags, fp); fdpunlock(fdp); closef(fp0, p); free(devname, M_DEVBUF, PATH_MAX); return 0; bad: fdpunlock(fdp); if (vp) vrele(vp); invalid: if (fp0) FRELE(fp0, p); 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; }