1 /* $OpenBSD: devopen.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Rolf Grossmann. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "libsa.h" 33 34 #define MAXDEVNAME 16 35 36 /* 37 * Parse a device spec. 38 * 39 * [A-Za-z]*[0-9]*[A-Za-z]:file 40 * dev uint part 41 */ 42 int 43 devparse(const char *fname, int *dev, int *unit, int *part, const char **file) 44 { 45 const char *s; 46 47 *unit = 0; /* default to wd0a */ 48 *part = 0; 49 *dev = 0; 50 51 s = strchr(fname, ':'); 52 if (s != NULL) { 53 int devlen; 54 int i, u, p = 0; 55 struct devsw *dp; 56 char devname[MAXDEVNAME]; 57 58 devlen = s - fname; 59 if (devlen > MAXDEVNAME) 60 return (EINVAL); 61 62 /* extract device name */ 63 for (i = 0; isalpha(fname[i]) && (i < devlen); i++) 64 devname[i] = fname[i]; 65 devname[i] = 0; 66 67 if (!isdigit(fname[i])) 68 return (EUNIT); 69 70 /* device number */ 71 for (u = 0; isdigit(fname[i]) && (i < devlen); i++) 72 u = u * 10 + (fname[i] - '0'); 73 74 if (!isalpha(fname[i])) 75 return (EPART); 76 77 /* partition number */ 78 if (i < devlen) 79 p = fname[i++] - 'a'; 80 81 if (i != devlen) 82 return (ENXIO); 83 84 /* check device name */ 85 for (dp = devsw, i = 0; i < ndevs; dp++, i++) { 86 if (dp->dv_name && !strcmp(devname, dp->dv_name)) 87 break; 88 } 89 90 if (i >= ndevs) 91 return (ENXIO); 92 93 *unit = u; 94 *part = p; 95 *dev = i; 96 fname = ++s; 97 } 98 99 *file = fname; 100 101 return (0); 102 } 103 104 int 105 devopen(struct open_file *f, const char *fname, char **file) 106 { 107 struct devsw *dp; 108 int dev, unit, part, error; 109 110 error = devparse(fname, &dev, &unit, &part, (const char **)file); 111 if (error) 112 return (error); 113 114 dp = &devsw[dev]; 115 if ((void *)dp->dv_open == (void *)nodev) 116 return (ENXIO); 117 118 f->f_dev = dp; 119 120 return (*dp->dv_open)(f, unit, part); 121 } 122