1 /* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 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 <sys/param.h> 33 #include <sys/stat.h> 34 35 #include <limits.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "pack_dev.h" 42 43 static pack_t pack_netbsd; 44 static pack_t pack_freebsd; 45 static pack_t pack_8_8; 46 static pack_t pack_12_20; 47 static pack_t pack_14_18; 48 static pack_t pack_8_24; 49 static pack_t pack_bsdos; 50 static int compare_format(const void *, const void *); 51 52 static const char iMajorError[] = "invalid major number"; 53 static const char iMinorError[] = "invalid minor number"; 54 static const char tooManyFields[] = "too many fields for format"; 55 56 /* exported */ 57 dev_t 58 pack_native(int n, u_long numbers[], const char **error) 59 { 60 dev_t dev = 0; 61 62 if (n == 2) { 63 dev = makedev(numbers[0], numbers[1]); 64 if ((u_long)major(dev) != numbers[0]) 65 *error = iMajorError; 66 else if ((u_long)minor(dev) != numbers[1]) 67 *error = iMinorError; 68 } else 69 *error = tooManyFields; 70 return (dev); 71 } 72 73 74 static dev_t 75 pack_netbsd(int n, u_long numbers[], const char **error) 76 { 77 dev_t dev = 0; 78 79 if (n == 2) { 80 dev = makedev_netbsd(numbers[0], numbers[1]); 81 if ((u_long)major_netbsd(dev) != numbers[0]) 82 *error = iMajorError; 83 else if ((u_long)minor_netbsd(dev) != numbers[1]) 84 *error = iMinorError; 85 } else 86 *error = tooManyFields; 87 return (dev); 88 } 89 90 91 #define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 92 #define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 93 #define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 94 (((y) << 0) & 0xffff00ff))) 95 96 static dev_t 97 pack_freebsd(int n, u_long numbers[], const char **error) 98 { 99 dev_t dev = 0; 100 101 if (n == 2) { 102 dev = makedev_freebsd(numbers[0], numbers[1]); 103 if ((u_long)major_freebsd(dev) != numbers[0]) 104 *error = iMajorError; 105 if ((u_long)minor_freebsd(dev) != numbers[1]) 106 *error = iMinorError; 107 } else 108 *error = tooManyFields; 109 return (dev); 110 } 111 112 113 #define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 114 #define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 115 #define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 116 (((y) << 0) & 0x000000ff))) 117 118 static dev_t 119 pack_8_8(int n, u_long numbers[], const char **error) 120 { 121 dev_t dev = 0; 122 123 if (n == 2) { 124 dev = makedev_8_8(numbers[0], numbers[1]); 125 if ((u_long)major_8_8(dev) != numbers[0]) 126 *error = iMajorError; 127 if ((u_long)minor_8_8(dev) != numbers[1]) 128 *error = iMinorError; 129 } else 130 *error = tooManyFields; 131 return (dev); 132 } 133 134 135 #define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 136 #define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 137 #define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ 138 (((y) << 0) & 0x000fffff))) 139 140 static dev_t 141 pack_12_20(int n, u_long numbers[], const char **error) 142 { 143 dev_t dev = 0; 144 145 if (n == 2) { 146 dev = makedev_12_20(numbers[0], numbers[1]); 147 if ((u_long)major_12_20(dev) != numbers[0]) 148 *error = iMajorError; 149 if ((u_long)minor_12_20(dev) != numbers[1]) 150 *error = iMinorError; 151 } else 152 *error = tooManyFields; 153 return (dev); 154 } 155 156 157 #define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 158 #define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 159 #define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ 160 (((y) << 0) & 0x0003ffff))) 161 162 static dev_t 163 pack_14_18(int n, u_long numbers[], const char **error) 164 { 165 dev_t dev = 0; 166 167 if (n == 2) { 168 dev = makedev_14_18(numbers[0], numbers[1]); 169 if ((u_long)major_14_18(dev) != numbers[0]) 170 *error = iMajorError; 171 if ((u_long)minor_14_18(dev) != numbers[1]) 172 *error = iMinorError; 173 } else 174 *error = tooManyFields; 175 return (dev); 176 } 177 178 179 #define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 180 #define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 181 #define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ 182 (((y) << 0) & 0x00ffffff))) 183 184 static dev_t 185 pack_8_24(int n, u_long numbers[], const char **error) 186 { 187 dev_t dev = 0; 188 189 if (n == 2) { 190 dev = makedev_8_24(numbers[0], numbers[1]); 191 if ((u_long)major_8_24(dev) != numbers[0]) 192 *error = iMajorError; 193 if ((u_long)minor_8_24(dev) != numbers[1]) 194 *error = iMinorError; 195 } else 196 *error = tooManyFields; 197 return (dev); 198 } 199 200 201 #define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 202 #define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 203 #define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 204 #define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ 205 (((y) << 8) & 0x000fff00) | \ 206 (((z) << 0) & 0x000000ff))) 207 208 static dev_t 209 pack_bsdos(int n, u_long numbers[], const char **error) 210 { 211 dev_t dev = 0; 212 213 if (n == 2) { 214 dev = makedev_12_20(numbers[0], numbers[1]); 215 if ((u_long)major_12_20(dev) != numbers[0]) 216 *error = iMajorError; 217 if ((u_long)minor_12_20(dev) != numbers[1]) 218 *error = iMinorError; 219 } else if (n == 3) { 220 dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 221 if ((u_long)major_12_12_8(dev) != numbers[0]) 222 *error = iMajorError; 223 if ((u_long)unit_12_12_8(dev) != numbers[1]) 224 *error = "invalid unit number"; 225 if ((u_long)subunit_12_12_8(dev) != numbers[2]) 226 *error = "invalid subunit number"; 227 } else 228 *error = tooManyFields; 229 return (dev); 230 } 231 232 233 /* list of formats and pack functions */ 234 /* this list must be sorted lexically */ 235 static struct format { 236 const char *name; 237 pack_t *pack; 238 } formats[] = { 239 {"386bsd", pack_8_8}, 240 {"4bsd", pack_8_8}, 241 {"bsdos", pack_bsdos}, 242 {"freebsd", pack_freebsd}, 243 {"hpux", pack_8_24}, 244 {"isc", pack_8_8}, 245 {"linux", pack_8_8}, 246 {"native", pack_native}, 247 {"netbsd", pack_netbsd}, 248 {"osf1", pack_12_20}, 249 {"sco", pack_8_8}, 250 {"solaris", pack_14_18}, 251 {"sunos", pack_8_8}, 252 {"svr3", pack_8_8}, 253 {"svr4", pack_14_18}, 254 {"ultrix", pack_8_8}, 255 }; 256 257 static int 258 compare_format(const void *key, const void *element) 259 { 260 const char *name; 261 const struct format *format; 262 263 name = key; 264 format = element; 265 266 return (strcmp(name, format->name)); 267 } 268 269 270 pack_t * 271 pack_find(const char *name) 272 { 273 struct format *format; 274 275 format = bsearch(name, formats, 276 sizeof(formats)/sizeof(formats[0]), 277 sizeof(formats[0]), compare_format); 278 if (format == NULL) 279 return (NULL); 280 return (format->pack); 281 } 282