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