1244543Sbrooks/* $NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $ */ 2244543Sbrooks 3244543Sbrooks/*- 4244543Sbrooks * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5244543Sbrooks * All rights reserved. 6244543Sbrooks * 7244543Sbrooks * This code is derived from software contributed to The NetBSD Foundation 8244543Sbrooks * by Charles M. Hannum. 9244543Sbrooks * 10244543Sbrooks * Redistribution and use in source and binary forms, with or without 11244543Sbrooks * modification, are permitted provided that the following conditions 12244543Sbrooks * are met: 13244543Sbrooks * 1. Redistributions of source code must retain the above copyright 14244543Sbrooks * notice, this list of conditions and the following disclaimer. 15244543Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 16244543Sbrooks * notice, this list of conditions and the following disclaimer in the 17244543Sbrooks * documentation and/or other materials provided with the distribution. 18244543Sbrooks * 19244543Sbrooks * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20244543Sbrooks * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21244543Sbrooks * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22244543Sbrooks * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23244543Sbrooks * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24244543Sbrooks * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25244543Sbrooks * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26244543Sbrooks * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27244543Sbrooks * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28244543Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29244543Sbrooks * POSSIBILITY OF SUCH DAMAGE. 30244543Sbrooks */ 31244543Sbrooks 32244543Sbrooks#if HAVE_NBTOOL_CONFIG_H 33244543Sbrooks#include "nbtool_config.h" 34244543Sbrooks#endif 35244543Sbrooks 36244543Sbrooks#include <sys/cdefs.h> 37244543Sbrooks#if !defined(lint) 38244543Sbrooks__RCSID("$NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $"); 39244543Sbrooks#endif /* not lint */ 40244543Sbrooks 41244543Sbrooks#include <sys/types.h> 42244543Sbrooks#include <sys/stat.h> 43244543Sbrooks 44244543Sbrooks#include <limits.h> 45244543Sbrooks#include <stdio.h> 46244543Sbrooks#include <stdlib.h> 47244543Sbrooks#include <string.h> 48244543Sbrooks#include <unistd.h> 49244543Sbrooks 50244543Sbrooks#include "pack_dev.h" 51244543Sbrooks 52244543Sbrooksstatic pack_t pack_netbsd; 53244543Sbrooksstatic pack_t pack_freebsd; 54244543Sbrooksstatic pack_t pack_8_8; 55244543Sbrooksstatic pack_t pack_12_20; 56244543Sbrooksstatic pack_t pack_14_18; 57244543Sbrooksstatic pack_t pack_8_24; 58244543Sbrooksstatic pack_t pack_bsdos; 59244543Sbrooksstatic int compare_format(const void *, const void *); 60244543Sbrooks 61244543Sbrooksstatic const char iMajorError[] = "invalid major number"; 62244543Sbrooksstatic const char iMinorError[] = "invalid minor number"; 63244543Sbrooksstatic const char tooManyFields[] = "too many fields for format"; 64244543Sbrooks 65244543Sbrooks /* exported */ 66244543Sbrooksportdev_t 67244543Sbrookspack_native(int n, u_long numbers[], const char **error) 68244543Sbrooks{ 69244543Sbrooks portdev_t dev = 0; 70244543Sbrooks 71244543Sbrooks if (n == 2) { 72244543Sbrooks dev = makedev(numbers[0], numbers[1]); 73244543Sbrooks if ((u_long)major(dev) != numbers[0]) 74244543Sbrooks *error = iMajorError; 75244543Sbrooks else if ((u_long)minor(dev) != numbers[1]) 76244543Sbrooks *error = iMinorError; 77244543Sbrooks } else 78244543Sbrooks *error = tooManyFields; 79244543Sbrooks return (dev); 80244543Sbrooks} 81244543Sbrooks 82244543Sbrooks 83244543Sbrooksstatic portdev_t 84244543Sbrookspack_netbsd(int n, u_long numbers[], const char **error) 85244543Sbrooks{ 86244543Sbrooks portdev_t dev = 0; 87244543Sbrooks 88244543Sbrooks if (n == 2) { 89244543Sbrooks dev = makedev_netbsd(numbers[0], numbers[1]); 90244543Sbrooks if ((u_long)major_netbsd(dev) != numbers[0]) 91244543Sbrooks *error = iMajorError; 92244543Sbrooks else if ((u_long)minor_netbsd(dev) != numbers[1]) 93244543Sbrooks *error = iMinorError; 94244543Sbrooks } else 95244543Sbrooks *error = tooManyFields; 96244543Sbrooks return (dev); 97244543Sbrooks} 98244543Sbrooks 99244543Sbrooks 100244543Sbrooks#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 101244543Sbrooks#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 102244543Sbrooks#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ 103244543Sbrooks (((y) << 0) & 0xffff00ff))) 104244543Sbrooks 105244543Sbrooksstatic portdev_t 106244543Sbrookspack_freebsd(int n, u_long numbers[], const char **error) 107244543Sbrooks{ 108244543Sbrooks portdev_t dev = 0; 109244543Sbrooks 110244543Sbrooks if (n == 2) { 111244543Sbrooks dev = makedev_freebsd(numbers[0], numbers[1]); 112244543Sbrooks if ((u_long)major_freebsd(dev) != numbers[0]) 113244543Sbrooks *error = iMajorError; 114244543Sbrooks if ((u_long)minor_freebsd(dev) != numbers[1]) 115244543Sbrooks *error = iMinorError; 116244543Sbrooks } else 117244543Sbrooks *error = tooManyFields; 118244543Sbrooks return (dev); 119244543Sbrooks} 120244543Sbrooks 121244543Sbrooks 122244543Sbrooks#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 123244543Sbrooks#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 124244543Sbrooks#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ 125244543Sbrooks (((y) << 0) & 0x000000ff))) 126244543Sbrooks 127244543Sbrooksstatic portdev_t 128244543Sbrookspack_8_8(int n, u_long numbers[], const char **error) 129244543Sbrooks{ 130244543Sbrooks portdev_t dev = 0; 131244543Sbrooks 132244543Sbrooks if (n == 2) { 133244543Sbrooks dev = makedev_8_8(numbers[0], numbers[1]); 134244543Sbrooks if ((u_long)major_8_8(dev) != numbers[0]) 135244543Sbrooks *error = iMajorError; 136244543Sbrooks if ((u_long)minor_8_8(dev) != numbers[1]) 137244543Sbrooks *error = iMinorError; 138244543Sbrooks } else 139244543Sbrooks *error = tooManyFields; 140244543Sbrooks return (dev); 141244543Sbrooks} 142244543Sbrooks 143244543Sbrooks 144244543Sbrooks#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 145244543Sbrooks#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 146244543Sbrooks#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \ 147244543Sbrooks (((y) << 0) & 0x000fffff))) 148244543Sbrooks 149244543Sbrooksstatic portdev_t 150244543Sbrookspack_12_20(int n, u_long numbers[], const char **error) 151244543Sbrooks{ 152244543Sbrooks portdev_t dev = 0; 153244543Sbrooks 154244543Sbrooks if (n == 2) { 155244543Sbrooks dev = makedev_12_20(numbers[0], numbers[1]); 156244543Sbrooks if ((u_long)major_12_20(dev) != numbers[0]) 157244543Sbrooks *error = iMajorError; 158244543Sbrooks if ((u_long)minor_12_20(dev) != numbers[1]) 159244543Sbrooks *error = iMinorError; 160244543Sbrooks } else 161244543Sbrooks *error = tooManyFields; 162244543Sbrooks return (dev); 163244543Sbrooks} 164244543Sbrooks 165244543Sbrooks 166244543Sbrooks#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 167244543Sbrooks#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 168244543Sbrooks#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \ 169244543Sbrooks (((y) << 0) & 0x0003ffff))) 170244543Sbrooks 171244543Sbrooksstatic portdev_t 172244543Sbrookspack_14_18(int n, u_long numbers[], const char **error) 173244543Sbrooks{ 174244543Sbrooks portdev_t dev = 0; 175244543Sbrooks 176244543Sbrooks if (n == 2) { 177244543Sbrooks dev = makedev_14_18(numbers[0], numbers[1]); 178244543Sbrooks if ((u_long)major_14_18(dev) != numbers[0]) 179244543Sbrooks *error = iMajorError; 180244543Sbrooks if ((u_long)minor_14_18(dev) != numbers[1]) 181244543Sbrooks *error = iMinorError; 182244543Sbrooks } else 183244543Sbrooks *error = tooManyFields; 184244543Sbrooks return (dev); 185244543Sbrooks} 186244543Sbrooks 187244543Sbrooks 188244543Sbrooks#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 189244543Sbrooks#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 190244543Sbrooks#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \ 191244543Sbrooks (((y) << 0) & 0x00ffffff))) 192244543Sbrooks 193244543Sbrooksstatic portdev_t 194244543Sbrookspack_8_24(int n, u_long numbers[], const char **error) 195244543Sbrooks{ 196244543Sbrooks portdev_t dev = 0; 197244543Sbrooks 198244543Sbrooks if (n == 2) { 199244543Sbrooks dev = makedev_8_24(numbers[0], numbers[1]); 200244543Sbrooks if ((u_long)major_8_24(dev) != numbers[0]) 201244543Sbrooks *error = iMajorError; 202244543Sbrooks if ((u_long)minor_8_24(dev) != numbers[1]) 203244543Sbrooks *error = iMinorError; 204244543Sbrooks } else 205244543Sbrooks *error = tooManyFields; 206244543Sbrooks return (dev); 207244543Sbrooks} 208244543Sbrooks 209244543Sbrooks 210244543Sbrooks#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 211244543Sbrooks#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 212244543Sbrooks#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 213244543Sbrooks#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \ 214244543Sbrooks (((y) << 8) & 0x000fff00) | \ 215244543Sbrooks (((z) << 0) & 0x000000ff))) 216244543Sbrooks 217244543Sbrooksstatic portdev_t 218244543Sbrookspack_bsdos(int n, u_long numbers[], const char **error) 219244543Sbrooks{ 220244543Sbrooks portdev_t dev = 0; 221244543Sbrooks 222244543Sbrooks if (n == 2) { 223244543Sbrooks dev = makedev_12_20(numbers[0], numbers[1]); 224244543Sbrooks if ((u_long)major_12_20(dev) != numbers[0]) 225244543Sbrooks *error = iMajorError; 226244543Sbrooks if ((u_long)minor_12_20(dev) != numbers[1]) 227244543Sbrooks *error = iMinorError; 228244543Sbrooks } else if (n == 3) { 229244543Sbrooks dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 230244543Sbrooks if ((u_long)major_12_12_8(dev) != numbers[0]) 231244543Sbrooks *error = iMajorError; 232244543Sbrooks if ((u_long)unit_12_12_8(dev) != numbers[1]) 233244543Sbrooks *error = "invalid unit number"; 234244543Sbrooks if ((u_long)subunit_12_12_8(dev) != numbers[2]) 235244543Sbrooks *error = "invalid subunit number"; 236244543Sbrooks } else 237244543Sbrooks *error = tooManyFields; 238244543Sbrooks return (dev); 239244543Sbrooks} 240244543Sbrooks 241244543Sbrooks 242244543Sbrooks /* list of formats and pack functions */ 243244543Sbrooks /* this list must be sorted lexically */ 244244543Sbrooksstatic struct format { 245244543Sbrooks const char *name; 246244543Sbrooks pack_t *pack; 247244543Sbrooks} formats[] = { 248244543Sbrooks {"386bsd", pack_8_8}, 249244543Sbrooks {"4bsd", pack_8_8}, 250244543Sbrooks {"bsdos", pack_bsdos}, 251244543Sbrooks {"freebsd", pack_freebsd}, 252244543Sbrooks {"hpux", pack_8_24}, 253244543Sbrooks {"isc", pack_8_8}, 254244543Sbrooks {"linux", pack_8_8}, 255244543Sbrooks {"native", pack_native}, 256244543Sbrooks {"netbsd", pack_netbsd}, 257244543Sbrooks {"osf1", pack_12_20}, 258244543Sbrooks {"sco", pack_8_8}, 259244543Sbrooks {"solaris", pack_14_18}, 260244543Sbrooks {"sunos", pack_8_8}, 261244543Sbrooks {"svr3", pack_8_8}, 262244543Sbrooks {"svr4", pack_14_18}, 263244543Sbrooks {"ultrix", pack_8_8}, 264244543Sbrooks}; 265244543Sbrooks 266244543Sbrooksstatic int 267244543Sbrookscompare_format(const void *key, const void *element) 268244543Sbrooks{ 269244543Sbrooks const char *name; 270244543Sbrooks const struct format *format; 271244543Sbrooks 272244543Sbrooks name = key; 273244543Sbrooks format = element; 274244543Sbrooks 275244543Sbrooks return (strcmp(name, format->name)); 276244543Sbrooks} 277244543Sbrooks 278244543Sbrooks 279244543Sbrookspack_t * 280244543Sbrookspack_find(const char *name) 281244543Sbrooks{ 282244543Sbrooks struct format *format; 283244543Sbrooks 284244543Sbrooks format = bsearch(name, formats, 285244543Sbrooks sizeof(formats)/sizeof(formats[0]), 286244543Sbrooks sizeof(formats[0]), compare_format); 287244543Sbrooks if (format == 0) 288244543Sbrooks return (NULL); 289244543Sbrooks return (format->pack); 290244543Sbrooks} 291