Home | History | Annotate | Line # | Download | only in mknod
mknod.c revision 1.12
      1 /*	$NetBSD: mknod.c,v 1.12 1998/01/17 13:04:18 mycroft Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998 Charles M. Hannum.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Charles M. Hannum.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __COPYRIGHT("@(#) Copyright (c) 1998 Charles M. Hannum.  All rights reserved.\n");
     35 __RCSID("$NetBSD: mknod.c,v 1.12 1998/01/17 13:04:18 mycroft Exp $");
     36 #endif /* not lint */
     37 
     38 #include <sys/types.h>
     39 #include <sys/stat.h>
     40 
     41 #include <err.h>
     42 #include <errno.h>
     43 #include <limits.h>
     44 #include <stdio.h>
     45 #include <stdlib.h>
     46 #include <unistd.h>
     47 
     48 int main __P((int, char *[]));
     49 static void usage __P((void));
     50 typedef	dev_t pack_t __P((u_long, u_long, u_long *, u_long *));
     51 
     52 
     53 pack_t pack_native;
     54 
     55 dev_t
     56 pack_native(maj, min, maj2, min2)
     57 	u_long maj, min, *maj2, *min2;
     58 {
     59 	dev_t dev;
     60 
     61 	dev = makedev(maj, min);
     62 	*maj2 = major(dev);
     63 	*min2 = minor(dev);
     64 	return (dev);
     65 }
     66 
     67 
     68 #define	major_netbsd(x)		((int32_t)((((x) & 0x000fff00) >>  8)))
     69 #define	minor_netbsd(x)		((int32_t)((((x) & 0xfff00000) >> 12) | \
     70 					   (((x) & 0x000000ff) >>  0)))
     71 #define	makedev_netbsd(x,y)	((dev_t)((((x) <<  8) & 0x000fff00) | \
     72 					 (((y) << 12) & 0xfff00000) | \
     73 					 (((y) <<  0) & 0x000000ff)))
     74 
     75 pack_t pack_netbsd;
     76 
     77 dev_t
     78 pack_netbsd(maj, min, maj2, min2)
     79 	u_long maj, min, *maj2, *min2;
     80 {
     81 	dev_t dev;
     82 
     83 	dev = makedev_netbsd(maj, min);
     84 	*maj2 = major_netbsd(dev);
     85 	*min2 = minor_netbsd(dev);
     86 	return (dev);
     87 }
     88 
     89 
     90 #define	major_freebsd(x)	((int32_t)(((x) & 0x0000ff00) >> 8))
     91 #define	minor_freebsd(x)	((int32_t)(((x) & 0xffff00ff) >> 0))
     92 #define	makedev_freebsd(x,y)	((dev_t)((((x) << 8) & 0x0000ff00) | \
     93 					 (((y) << 0) & 0xffff00ff)))
     94 
     95 pack_t pack_freebsd;
     96 
     97 dev_t
     98 pack_freebsd(maj, min, maj2, min2)
     99 	u_long maj, min, *maj2, *min2;
    100 {
    101 	dev_t dev;
    102 
    103 	dev = makedev_freebsd(maj, min);
    104 	*maj2 = major_freebsd(dev);
    105 	*min2 = minor_freebsd(dev);
    106 	return (dev);
    107 }
    108 
    109 
    110 #define	major_8_8(x)		((int32_t)(((x) & 0x0000ff00) >> 8))
    111 #define	minor_8_8(x)		((int32_t)(((x) & 0x000000ff) >> 0))
    112 #define	makedev_8_8(x,y)	((dev_t)((((x) << 8) & 0x0000ff00) | \
    113 					 (((y) << 0) & 0x000000ff)))
    114 
    115 pack_t pack_8_8;
    116 
    117 dev_t
    118 pack_8_8(maj, min, maj2, min2)
    119 	u_long maj, min, *maj2, *min2;
    120 {
    121 	dev_t dev;
    122 
    123 	dev = makedev_8_8(maj, min);
    124 	*maj2 = major_8_8(dev);
    125 	*min2 = minor_8_8(dev);
    126 	return (dev);
    127 }
    128 
    129 
    130 #define	major_12_20(x)		((int32_t)(((x) & 0xfff00000) >> 20))
    131 #define	minor_12_20(x)		((int32_t)(((x) & 0x000fffff) >>  0))
    132 #define	makedev_12_20(x,y)	((dev_t)((((x) << 20) & 0xfff00000) | \
    133 					 (((y) <<  0) & 0x000fffff)))
    134 
    135 pack_t pack_12_20;
    136 
    137 dev_t
    138 pack_12_20(maj, min, maj2, min2)
    139 	u_long maj, min, *maj2, *min2;
    140 {
    141 	dev_t dev;
    142 
    143 	dev = makedev_12_20(maj, min);
    144 	*maj2 = major_12_20(dev);
    145 	*min2 = minor_12_20(dev);
    146 	return (dev);
    147 }
    148 
    149 
    150 #define	major_14_18(x)		((int32_t)(((x) & 0xfffc0000) >> 18))
    151 #define	minor_14_18(x)		((int32_t)(((x) & 0x0003ffff) >>  0))
    152 #define	makedev_14_18(x,y)	((dev_t)((((x) << 18) & 0xfffc0000) | \
    153 					 (((y) <<  0) & 0x0003ffff)))
    154 
    155 pack_t pack_14_18;
    156 
    157 dev_t
    158 pack_14_18(maj, min, maj2, min2)
    159 	u_long maj, min, *maj2, *min2;
    160 {
    161 	dev_t dev;
    162 
    163 	dev = makedev_14_18(maj, min);
    164 	*maj2 = major_14_18(dev);
    165 	*min2 = minor_14_18(dev);
    166 	return (dev);
    167 }
    168 
    169 
    170 #define	major_8_24(x)		((int32_t)(((x) & 0xff000000) >> 24))
    171 #define	minor_8_24(x)		((int32_t)(((x) & 0x00ffffff) >>  0))
    172 #define	makedev_8_24(x,y)	((dev_t)((((x) << 24) & 0xff000000) | \
    173 					 (((y) <<  0) & 0x00ffffff)))
    174 
    175 pack_t pack_8_24;
    176 
    177 dev_t
    178 pack_8_24(maj, min, maj2, min2)
    179 	u_long maj, min, *maj2, *min2;
    180 {
    181 	dev_t dev;
    182 
    183 	dev = makedev_8_24(maj, min);
    184 	*maj2 = major_8_24(dev);
    185 	*min2 = minor_8_24(dev);
    186 	return (dev);
    187 }
    188 
    189 
    190 struct format {
    191 	char	*name;
    192 	pack_t	*pack;
    193 } formats[] = {
    194 	{"386bsd",  pack_8_8},
    195 	{"4bsd",    pack_8_8},
    196 	{"bsdos",   pack_12_20},
    197 	{"freebsd", pack_freebsd},
    198 	{"hpux",    pack_8_24},
    199 	{"linux",   pack_8_8},
    200 	{"native",  pack_native},
    201 	{"netbsd",  pack_netbsd},
    202 	{"osf1",    pack_12_20},
    203 	{"solaris", pack_14_18},
    204 	{"sunos",   pack_8_8},
    205 	{"svr3",    pack_8_8},
    206 	{"svr4",    pack_14_18},
    207 	{"ultrix",  pack_8_8},
    208 };
    209 
    210 int compare_format __P((const void *, const void *));
    211 
    212 int
    213 compare_format(key, element)
    214 	const void *key;
    215 	const void *element;
    216 {
    217 	const char *name;
    218 	const struct format *format;
    219 
    220 	name = key;
    221 	format = element;
    222 
    223 	return (strcmp(name, format->name));
    224 }
    225 
    226 
    227 int
    228 main(argc, argv)
    229 	int argc;
    230 	char **argv;
    231 {
    232 	struct format *format;
    233 	pack_t *pack;
    234 	char *p;
    235 	u_long maj, min, maj2, min2;
    236 	mode_t mode;
    237 	dev_t dev;
    238 	int ch;
    239 
    240 	pack = pack_native;
    241 
    242 	while ((ch = getopt(argc, argv, "F:")) != -1) {
    243 		switch (ch) {
    244 		case 'F':
    245 			format = bsearch(optarg, formats,
    246 			    sizeof(formats)/sizeof(formats[0]),
    247 			    sizeof(formats[0]), compare_format);
    248 			if (format == 0)
    249 				errx(1, "invalid format: %s", optarg);
    250 			pack = format->pack;
    251 			break;
    252 
    253 		default:
    254 		case '?':
    255 			usage();
    256 		}
    257 	}
    258 	argc -= optind;
    259 	argv += optind;
    260 
    261 	if (argc != 3 && argc != 4)
    262 		usage();
    263 
    264 	mode = 0666;
    265 	if (argv[1][0] == 'c')
    266 		mode |= S_IFCHR;
    267 	else if (argv[1][0] == 'b')
    268 		mode |= S_IFBLK;
    269 	else
    270 		errx(1, "node must be type 'b' or 'c'.");
    271 
    272 	if (argc == 4) {
    273 		maj = strtoul(argv[2], &p, 0);
    274 		if ((p && *p != '\0') || (maj == ULONG_MAX && errno == ERANGE))
    275 			errx(1, "invalid major number: %s", argv[2]);
    276 
    277 		min = strtoul(argv[3], &p, 0);
    278 		if ((p && *p != '\0') || (min == ULONG_MAX && errno == ERANGE))
    279 			errx(1, "invalid minor number: %s", argv[3]);
    280 
    281 		dev = (*pack)(maj, min, &maj2, &min2);
    282 
    283 		if (maj2 != maj)
    284 			errx(1, "major number out of range: %s", argv[2]);
    285 
    286 		if (min2 != min)
    287 			errx(1, "minor number out of range: %s", argv[3]);
    288 	} else {
    289 		dev = (dev_t) strtoul(argv[2], &p, 0);
    290 		if ((p && *p != '\0') || (dev == ULONG_MAX && errno == ERANGE))
    291 			errx(1, "invalid device number: %s", argv[2]);
    292 	}
    293 
    294 	if (mknod(argv[0], mode, dev) < 0)
    295 		err(1, "%s", argv[0]);
    296 
    297 	exit(0);
    298 }
    299 
    300 void
    301 usage()
    302 {
    303 
    304 	fprintf(stderr, "usage: mknod [-F format] name [b | c] major minor\n");
    305 	fprintf(stderr, "       mknod name [b | c] number\n");
    306 	exit(1);
    307 }
    308