1*c7276dbcStsutsui /* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */
27ca2a2b5Slukem
37ca2a2b5Slukem /*-
47ca2a2b5Slukem * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
57ca2a2b5Slukem * All rights reserved.
67ca2a2b5Slukem *
77ca2a2b5Slukem * This code is derived from software contributed to The NetBSD Foundation
87ca2a2b5Slukem * by Charles M. Hannum.
97ca2a2b5Slukem *
107ca2a2b5Slukem * Redistribution and use in source and binary forms, with or without
117ca2a2b5Slukem * modification, are permitted provided that the following conditions
127ca2a2b5Slukem * are met:
137ca2a2b5Slukem * 1. Redistributions of source code must retain the above copyright
147ca2a2b5Slukem * notice, this list of conditions and the following disclaimer.
157ca2a2b5Slukem * 2. Redistributions in binary form must reproduce the above copyright
167ca2a2b5Slukem * notice, this list of conditions and the following disclaimer in the
177ca2a2b5Slukem * documentation and/or other materials provided with the distribution.
187ca2a2b5Slukem *
197ca2a2b5Slukem * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
207ca2a2b5Slukem * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
217ca2a2b5Slukem * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
227ca2a2b5Slukem * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
237ca2a2b5Slukem * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
247ca2a2b5Slukem * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
257ca2a2b5Slukem * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
267ca2a2b5Slukem * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
277ca2a2b5Slukem * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
287ca2a2b5Slukem * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
297ca2a2b5Slukem * POSSIBILITY OF SUCH DAMAGE.
307ca2a2b5Slukem */
317ca2a2b5Slukem
32171d6532Slukem #if HAVE_NBTOOL_CONFIG_H
33171d6532Slukem #include "nbtool_config.h"
34171d6532Slukem #endif
35171d6532Slukem
367ca2a2b5Slukem #include <sys/cdefs.h>
37171d6532Slukem #if !defined(lint)
38*c7276dbcStsutsui __RCSID("$NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $");
397ca2a2b5Slukem #endif /* not lint */
407ca2a2b5Slukem
417ca2a2b5Slukem #include <sys/types.h>
427ca2a2b5Slukem #include <sys/stat.h>
437ca2a2b5Slukem
447ca2a2b5Slukem #include <limits.h>
457ca2a2b5Slukem #include <stdio.h>
467ca2a2b5Slukem #include <stdlib.h>
477ca2a2b5Slukem #include <string.h>
48fcae5f73Stv #include <unistd.h>
49fcae5f73Stv
507ca2a2b5Slukem #include "pack_dev.h"
517ca2a2b5Slukem
527ca2a2b5Slukem static pack_t pack_netbsd;
537ca2a2b5Slukem static pack_t pack_freebsd;
547ca2a2b5Slukem static pack_t pack_8_8;
557ca2a2b5Slukem static pack_t pack_12_20;
567ca2a2b5Slukem static pack_t pack_14_18;
577ca2a2b5Slukem static pack_t pack_8_24;
587ca2a2b5Slukem static pack_t pack_bsdos;
597ca2a2b5Slukem static int compare_format(const void *, const void *);
607ca2a2b5Slukem
619e68dee1Schristos static const char iMajorError[] = "invalid major number";
629e68dee1Schristos static const char iMinorError[] = "invalid minor number";
639e68dee1Schristos static const char tooManyFields[] = "too many fields for format";
647ca2a2b5Slukem
657ca2a2b5Slukem /* exported */
66*c7276dbcStsutsui dev_t
pack_native(int n,u_long numbers[],const char ** error)679e68dee1Schristos pack_native(int n, u_long numbers[], const char **error)
687ca2a2b5Slukem {
69*c7276dbcStsutsui dev_t dev = 0;
707ca2a2b5Slukem
717ca2a2b5Slukem if (n == 2) {
727ca2a2b5Slukem dev = makedev(numbers[0], numbers[1]);
739abbf3c3Slukem if ((u_long)major(dev) != numbers[0])
749e754b37Sross *error = iMajorError;
759abbf3c3Slukem else if ((u_long)minor(dev) != numbers[1])
769e754b37Sross *error = iMinorError;
777ca2a2b5Slukem } else
789e754b37Sross *error = tooManyFields;
797ca2a2b5Slukem return (dev);
807ca2a2b5Slukem }
817ca2a2b5Slukem
827ca2a2b5Slukem
83*c7276dbcStsutsui static dev_t
pack_netbsd(int n,u_long numbers[],const char ** error)849e68dee1Schristos pack_netbsd(int n, u_long numbers[], const char **error)
857ca2a2b5Slukem {
86*c7276dbcStsutsui dev_t dev = 0;
877ca2a2b5Slukem
887ca2a2b5Slukem if (n == 2) {
897ca2a2b5Slukem dev = makedev_netbsd(numbers[0], numbers[1]);
909abbf3c3Slukem if ((u_long)major_netbsd(dev) != numbers[0])
919e754b37Sross *error = iMajorError;
929abbf3c3Slukem else if ((u_long)minor_netbsd(dev) != numbers[1])
939e754b37Sross *error = iMinorError;
947ca2a2b5Slukem } else
959e754b37Sross *error = tooManyFields;
967ca2a2b5Slukem return (dev);
977ca2a2b5Slukem }
987ca2a2b5Slukem
997ca2a2b5Slukem
1007ca2a2b5Slukem #define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
1017ca2a2b5Slukem #define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
102*c7276dbcStsutsui #define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
1037ca2a2b5Slukem (((y) << 0) & 0xffff00ff)))
1047ca2a2b5Slukem
105*c7276dbcStsutsui static dev_t
pack_freebsd(int n,u_long numbers[],const char ** error)1069e68dee1Schristos pack_freebsd(int n, u_long numbers[], const char **error)
1077ca2a2b5Slukem {
108*c7276dbcStsutsui dev_t dev = 0;
1097ca2a2b5Slukem
1107ca2a2b5Slukem if (n == 2) {
1117ca2a2b5Slukem dev = makedev_freebsd(numbers[0], numbers[1]);
1129abbf3c3Slukem if ((u_long)major_freebsd(dev) != numbers[0])
1139e754b37Sross *error = iMajorError;
1149abbf3c3Slukem if ((u_long)minor_freebsd(dev) != numbers[1])
1159e754b37Sross *error = iMinorError;
1167ca2a2b5Slukem } else
1179e754b37Sross *error = tooManyFields;
1187ca2a2b5Slukem return (dev);
1197ca2a2b5Slukem }
1207ca2a2b5Slukem
1217ca2a2b5Slukem
1227ca2a2b5Slukem #define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
1237ca2a2b5Slukem #define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
124*c7276dbcStsutsui #define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
1257ca2a2b5Slukem (((y) << 0) & 0x000000ff)))
1267ca2a2b5Slukem
127*c7276dbcStsutsui static dev_t
pack_8_8(int n,u_long numbers[],const char ** error)1289e68dee1Schristos pack_8_8(int n, u_long numbers[], const char **error)
1297ca2a2b5Slukem {
130*c7276dbcStsutsui dev_t dev = 0;
1317ca2a2b5Slukem
1327ca2a2b5Slukem if (n == 2) {
1337ca2a2b5Slukem dev = makedev_8_8(numbers[0], numbers[1]);
1349abbf3c3Slukem if ((u_long)major_8_8(dev) != numbers[0])
1359e754b37Sross *error = iMajorError;
1369abbf3c3Slukem if ((u_long)minor_8_8(dev) != numbers[1])
1379e754b37Sross *error = iMinorError;
1387ca2a2b5Slukem } else
1399e754b37Sross *error = tooManyFields;
1407ca2a2b5Slukem return (dev);
1417ca2a2b5Slukem }
1427ca2a2b5Slukem
1437ca2a2b5Slukem
1447ca2a2b5Slukem #define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
1457ca2a2b5Slukem #define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
146*c7276dbcStsutsui #define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \
1477ca2a2b5Slukem (((y) << 0) & 0x000fffff)))
1487ca2a2b5Slukem
149*c7276dbcStsutsui static dev_t
pack_12_20(int n,u_long numbers[],const char ** error)1509e68dee1Schristos pack_12_20(int n, u_long numbers[], const char **error)
1517ca2a2b5Slukem {
152*c7276dbcStsutsui dev_t dev = 0;
1537ca2a2b5Slukem
1547ca2a2b5Slukem if (n == 2) {
1557ca2a2b5Slukem dev = makedev_12_20(numbers[0], numbers[1]);
1569abbf3c3Slukem if ((u_long)major_12_20(dev) != numbers[0])
1579e754b37Sross *error = iMajorError;
1589abbf3c3Slukem if ((u_long)minor_12_20(dev) != numbers[1])
1599e754b37Sross *error = iMinorError;
1607ca2a2b5Slukem } else
1619e754b37Sross *error = tooManyFields;
1627ca2a2b5Slukem return (dev);
1637ca2a2b5Slukem }
1647ca2a2b5Slukem
1657ca2a2b5Slukem
1667ca2a2b5Slukem #define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
1677ca2a2b5Slukem #define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
168*c7276dbcStsutsui #define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \
1697ca2a2b5Slukem (((y) << 0) & 0x0003ffff)))
1707ca2a2b5Slukem
171*c7276dbcStsutsui static dev_t
pack_14_18(int n,u_long numbers[],const char ** error)1729e68dee1Schristos pack_14_18(int n, u_long numbers[], const char **error)
1737ca2a2b5Slukem {
174*c7276dbcStsutsui dev_t dev = 0;
1757ca2a2b5Slukem
1767ca2a2b5Slukem if (n == 2) {
1777ca2a2b5Slukem dev = makedev_14_18(numbers[0], numbers[1]);
1789abbf3c3Slukem if ((u_long)major_14_18(dev) != numbers[0])
1799e754b37Sross *error = iMajorError;
1809abbf3c3Slukem if ((u_long)minor_14_18(dev) != numbers[1])
1819e754b37Sross *error = iMinorError;
1827ca2a2b5Slukem } else
1839e754b37Sross *error = tooManyFields;
1847ca2a2b5Slukem return (dev);
1857ca2a2b5Slukem }
1867ca2a2b5Slukem
1877ca2a2b5Slukem
1887ca2a2b5Slukem #define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
1897ca2a2b5Slukem #define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
190*c7276dbcStsutsui #define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \
1917ca2a2b5Slukem (((y) << 0) & 0x00ffffff)))
1927ca2a2b5Slukem
193*c7276dbcStsutsui static dev_t
pack_8_24(int n,u_long numbers[],const char ** error)1949e68dee1Schristos pack_8_24(int n, u_long numbers[], const char **error)
1957ca2a2b5Slukem {
196*c7276dbcStsutsui dev_t dev = 0;
1977ca2a2b5Slukem
1987ca2a2b5Slukem if (n == 2) {
1997ca2a2b5Slukem dev = makedev_8_24(numbers[0], numbers[1]);
2009abbf3c3Slukem if ((u_long)major_8_24(dev) != numbers[0])
2019e754b37Sross *error = iMajorError;
2029abbf3c3Slukem if ((u_long)minor_8_24(dev) != numbers[1])
2039e754b37Sross *error = iMinorError;
2047ca2a2b5Slukem } else
2059e754b37Sross *error = tooManyFields;
2067ca2a2b5Slukem return (dev);
2077ca2a2b5Slukem }
2087ca2a2b5Slukem
2097ca2a2b5Slukem
2107ca2a2b5Slukem #define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
2117ca2a2b5Slukem #define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
2127ca2a2b5Slukem #define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
213*c7276dbcStsutsui #define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \
2147ca2a2b5Slukem (((y) << 8) & 0x000fff00) | \
2157ca2a2b5Slukem (((z) << 0) & 0x000000ff)))
2167ca2a2b5Slukem
217*c7276dbcStsutsui static dev_t
pack_bsdos(int n,u_long numbers[],const char ** error)2189e68dee1Schristos pack_bsdos(int n, u_long numbers[], const char **error)
2197ca2a2b5Slukem {
220*c7276dbcStsutsui dev_t dev = 0;
2217ca2a2b5Slukem
2227ca2a2b5Slukem if (n == 2) {
2237ca2a2b5Slukem dev = makedev_12_20(numbers[0], numbers[1]);
2249abbf3c3Slukem if ((u_long)major_12_20(dev) != numbers[0])
2259e754b37Sross *error = iMajorError;
2269abbf3c3Slukem if ((u_long)minor_12_20(dev) != numbers[1])
2279e754b37Sross *error = iMinorError;
2287ca2a2b5Slukem } else if (n == 3) {
2297ca2a2b5Slukem dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
2309abbf3c3Slukem if ((u_long)major_12_12_8(dev) != numbers[0])
2319e754b37Sross *error = iMajorError;
2329abbf3c3Slukem if ((u_long)unit_12_12_8(dev) != numbers[1])
2339e754b37Sross *error = "invalid unit number";
2349abbf3c3Slukem if ((u_long)subunit_12_12_8(dev) != numbers[2])
2359e754b37Sross *error = "invalid subunit number";
2367ca2a2b5Slukem } else
2379e754b37Sross *error = tooManyFields;
2387ca2a2b5Slukem return (dev);
2397ca2a2b5Slukem }
2407ca2a2b5Slukem
2417ca2a2b5Slukem
2427ca2a2b5Slukem /* list of formats and pack functions */
2437ca2a2b5Slukem /* this list must be sorted lexically */
244c6d7b0bbSjoerg static struct format {
2457ca2a2b5Slukem const char *name;
2467ca2a2b5Slukem pack_t *pack;
2477ca2a2b5Slukem } formats[] = {
2487ca2a2b5Slukem {"386bsd", pack_8_8},
2497ca2a2b5Slukem {"4bsd", pack_8_8},
2507ca2a2b5Slukem {"bsdos", pack_bsdos},
2517ca2a2b5Slukem {"freebsd", pack_freebsd},
2527ca2a2b5Slukem {"hpux", pack_8_24},
2537ca2a2b5Slukem {"isc", pack_8_8},
2547ca2a2b5Slukem {"linux", pack_8_8},
2557ca2a2b5Slukem {"native", pack_native},
2567ca2a2b5Slukem {"netbsd", pack_netbsd},
2577ca2a2b5Slukem {"osf1", pack_12_20},
2587ca2a2b5Slukem {"sco", pack_8_8},
2597ca2a2b5Slukem {"solaris", pack_14_18},
2607ca2a2b5Slukem {"sunos", pack_8_8},
2617ca2a2b5Slukem {"svr3", pack_8_8},
2627ca2a2b5Slukem {"svr4", pack_14_18},
2637ca2a2b5Slukem {"ultrix", pack_8_8},
2647ca2a2b5Slukem };
2657ca2a2b5Slukem
2667ca2a2b5Slukem static int
compare_format(const void * key,const void * element)2677ca2a2b5Slukem compare_format(const void *key, const void *element)
2687ca2a2b5Slukem {
2697ca2a2b5Slukem const char *name;
2707ca2a2b5Slukem const struct format *format;
2717ca2a2b5Slukem
2727ca2a2b5Slukem name = key;
2737ca2a2b5Slukem format = element;
2747ca2a2b5Slukem
2757ca2a2b5Slukem return (strcmp(name, format->name));
2767ca2a2b5Slukem }
2777ca2a2b5Slukem
2787ca2a2b5Slukem
2797ca2a2b5Slukem pack_t *
pack_find(const char * name)2807ca2a2b5Slukem pack_find(const char *name)
2817ca2a2b5Slukem {
2827ca2a2b5Slukem struct format *format;
2837ca2a2b5Slukem
2847ca2a2b5Slukem format = bsearch(name, formats,
2857ca2a2b5Slukem sizeof(formats)/sizeof(formats[0]),
2867ca2a2b5Slukem sizeof(formats[0]), compare_format);
2877ca2a2b5Slukem if (format == 0)
2887ca2a2b5Slukem return (NULL);
2897ca2a2b5Slukem return (format->pack);
2907ca2a2b5Slukem }
291