/* $OpenBSD: devopen.c,v 1.3 2008/06/26 05:42:10 ray Exp $ */ /* $NetBSD: devopen.c,v 1.1 2003/06/25 17:24:22 cdi Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Rolf Grossmann. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "libsa.h" #define MAXDEVNAME 16 /* * Parse a device spec. * * [A-Za-z]*[0-9]*[A-Za-z]:file * dev uint part */ int devparse(const char *fname, int *dev, int *unit, int *part, const char **file) { const char *s; *unit = 0; /* default to wd0a */ *part = 0; *dev = 0; s = strchr(fname, ':'); if (s != NULL) { int devlen; int i, u, p; struct devsw *dp; char devname[MAXDEVNAME]; devlen = s - fname; if (devlen > MAXDEVNAME) return (EINVAL); /* extract device name */ for (i = 0; isalpha(fname[i]) && (i < devlen); i++) devname[i] = fname[i]; devname[i] = 0; if (!isdigit(fname[i])) return (EUNIT); /* device number */ for (u = 0; isdigit(fname[i]) && (i < devlen); i++) u = u * 10 + (fname[i] - '0'); if (!isalpha(fname[i])) return (EPART); /* partition number */ if (i < devlen) p = fname[i++] - 'a'; if (i != devlen) return (ENXIO); /* check device name */ for (dp = devsw, i = 0; i < ndevs; dp++, i++) { if (dp->dv_name && !strcmp(devname, dp->dv_name)) break; } if (i >= ndevs) return (ENXIO); *unit = u; *part = p; *dev = i; fname = ++s; } *file = fname; return (0); } int devopen(struct open_file *f, const char *fname, char **file) { struct devsw *dp; int dev, unit, part, error; error = devparse(fname, &dev, &unit, &part, (const char **)file); if (error) return (error); dp = &devsw[dev]; if ((void *)dp->dv_open == (void *)nodev) return (ENXIO); f->f_dev = dp; return (*dp->dv_open)(f, unit, part); }