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