xref: /netbsd-src/sbin/mknod/pack_dev.c (revision c7276dbc049012298f6fa60a0abfc1f4aa0b6a52)
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