]>
Commit | Line | Data |
---|---|---|
44a7a5ab A |
1 | /* $NetBSD: mknod.c,v 1.15 1998/09/11 07:22:13 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.15 1998/09/11 07:22:13 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> | |
440bd198 | 54 | #include <string.h> |
44a7a5ab A |
55 | |
56 | int main __P((int, char *[])); | |
57 | static void usage __P((void)); | |
58 | typedef dev_t pack_t __P((int, u_long [])); | |
59 | ||
60 | ||
61 | pack_t pack_native; | |
62 | ||
63 | dev_t | |
64 | pack_native(n, numbers) | |
65 | int n; | |
66 | u_long numbers[]; | |
67 | { | |
68 | dev_t dev=0; /* Quiet -Wall */ | |
69 | ||
70 | if (n == 2) { | |
71 | dev = makedev(numbers[0], numbers[1]); | |
72 | if (major(dev) != numbers[0]) | |
73 | errx(1, "invalid major number"); | |
74 | if (minor(dev) != numbers[1]) | |
75 | errx(1, "invalid minor number"); | |
76 | } else | |
77 | errx(1, "too many fields for format"); | |
78 | return (dev); | |
79 | } | |
80 | ||
81 | ||
82 | #define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8))) | |
83 | #define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \ | |
84 | (((x) & 0x000000ff) >> 0))) | |
85 | #define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \ | |
86 | (((y) << 12) & 0xfff00000) | \ | |
87 | (((y) << 0) & 0x000000ff))) | |
88 | ||
89 | pack_t pack_netbsd; | |
90 | ||
91 | dev_t | |
92 | pack_netbsd(n, numbers) | |
93 | int n; | |
94 | u_long numbers[]; | |
95 | { | |
96 | dev_t dev=0; /* Quiet -Wall */ | |
97 | ||
98 | if (n == 2) { | |
99 | dev = makedev_netbsd(numbers[0], numbers[1]); | |
100 | if (major_netbsd(dev) != numbers[0]) | |
101 | errx(1, "invalid major number"); | |
102 | if (minor_netbsd(dev) != numbers[1]) | |
103 | errx(1, "invalid minor number"); | |
104 | } else | |
105 | errx(1, "too many fields for format"); | |
106 | return (dev); | |
107 | } | |
108 | ||
109 | ||
110 | #define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) | |
111 | #define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) | |
112 | #define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ | |
113 | (((y) << 0) & 0xffff00ff))) | |
114 | ||
115 | pack_t pack_freebsd; | |
116 | ||
117 | dev_t | |
118 | pack_freebsd(n, numbers) | |
119 | int n; | |
120 | u_long numbers[]; | |
121 | { | |
122 | dev_t dev=0; /* Quiet -Wall */ | |
123 | ||
124 | if (n == 2) { | |
125 | dev = makedev_freebsd(numbers[0], numbers[1]); | |
126 | if (major_freebsd(dev) != numbers[0]) | |
127 | errx(1, "invalid major number"); | |
128 | if (minor_freebsd(dev) != numbers[1]) | |
129 | errx(1, "invalid minor number"); | |
130 | } else | |
131 | errx(1, "too many fields for format"); | |
132 | return (dev); | |
133 | } | |
134 | ||
135 | ||
136 | #define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) | |
137 | #define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) | |
138 | #define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ | |
139 | (((y) << 0) & 0x000000ff))) | |
140 | ||
141 | pack_t pack_8_8; | |
142 | ||
143 | dev_t | |
144 | pack_8_8(n, numbers) | |
145 | int n; | |
146 | u_long numbers[]; | |
147 | { | |
148 | dev_t dev=0; /* Quiet -Wall */ | |
149 | ||
150 | if (n == 2) { | |
151 | dev = makedev_8_8(numbers[0], numbers[1]); | |
152 | if (major_8_8(dev) != numbers[0]) | |
153 | errx(1, "invalid major number"); | |
154 | if (minor_8_8(dev) != numbers[1]) | |
155 | errx(1, "invalid minor number"); | |
156 | } else | |
157 | errx(1, "too many fields for format"); | |
158 | return (dev); | |
159 | } | |
160 | ||
161 | ||
162 | #define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) | |
163 | #define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) | |
164 | #define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ | |
165 | (((y) << 0) & 0x000fffff))) | |
166 | ||
167 | pack_t pack_12_20; | |
168 | ||
169 | dev_t | |
170 | pack_12_20(n, numbers) | |
171 | int n; | |
172 | u_long numbers[]; | |
173 | { | |
174 | dev_t dev=0; /* Quiet -Wall */ | |
175 | ||
176 | if (n == 2) { | |
177 | dev = makedev_12_20(numbers[0], numbers[1]); | |
178 | if (major_12_20(dev) != numbers[0]) | |
179 | errx(1, "invalid major number"); | |
180 | if (minor_12_20(dev) != numbers[1]) | |
181 | errx(1, "invalid minor number"); | |
182 | } else | |
183 | errx(1, "too many fields for format"); | |
184 | return (dev); | |
185 | } | |
186 | ||
187 | ||
188 | #define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) | |
189 | #define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) | |
190 | #define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ | |
191 | (((y) << 0) & 0x0003ffff))) | |
192 | ||
193 | pack_t pack_14_18; | |
194 | ||
195 | dev_t | |
196 | pack_14_18(n, numbers) | |
197 | int n; | |
198 | u_long numbers[]; | |
199 | { | |
200 | dev_t dev=0; /* Quiet -Wall */ | |
201 | ||
202 | if (n == 2) { | |
203 | dev = makedev_14_18(numbers[0], numbers[1]); | |
204 | if (major_14_18(dev) != numbers[0]) | |
205 | errx(1, "invalid major number"); | |
206 | if (minor_14_18(dev) != numbers[1]) | |
207 | errx(1, "invalid minor number"); | |
208 | } else | |
209 | errx(1, "too many fields for format"); | |
210 | return (dev); | |
211 | } | |
212 | ||
213 | ||
214 | #define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) | |
215 | #define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) | |
216 | #define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ | |
217 | (((y) << 0) & 0x00ffffff))) | |
218 | ||
219 | pack_t pack_8_24; | |
220 | ||
221 | dev_t | |
222 | pack_8_24(n, numbers) | |
223 | int n; | |
224 | u_long numbers[]; | |
225 | { | |
226 | dev_t dev=0; /* Quiet -Wall */ | |
227 | ||
228 | if (n == 2) { | |
229 | dev = makedev_8_24(numbers[0], numbers[1]); | |
230 | if (major_8_24(dev) != numbers[0]) | |
231 | errx(1, "invalid major number"); | |
232 | if (minor_8_24(dev) != numbers[1]) | |
233 | errx(1, "invalid minor number"); | |
234 | } else | |
235 | errx(1, "too many fields for format"); | |
236 | return (dev); | |
237 | } | |
238 | ||
239 | ||
240 | #define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) | |
241 | #define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) | |
242 | #define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) | |
243 | #define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ | |
244 | (((y) << 8) & 0x000fff00) | \ | |
245 | (((z) << 0) & 0x000000ff))) | |
246 | ||
247 | pack_t pack_bsdos; | |
248 | ||
249 | dev_t | |
250 | pack_bsdos(n, numbers) | |
251 | int n; | |
252 | u_long numbers[]; | |
253 | { | |
254 | dev_t dev=0; /* Quiet -Wall */ | |
255 | ||
256 | if (n == 2) { | |
257 | dev = makedev_12_20(numbers[0], numbers[1]); | |
258 | if (major_12_20(dev) != numbers[0]) | |
259 | errx(1, "invalid major number"); | |
260 | if (minor_12_20(dev) != numbers[1]) | |
261 | errx(1, "invalid minor number"); | |
262 | } else if (n == 3) { | |
263 | dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); | |
264 | if (major_12_12_8(dev) != numbers[0]) | |
265 | errx(1, "invalid major number"); | |
266 | if (unit_12_12_8(dev) != numbers[1]) | |
267 | errx(1, "invalid unit number"); | |
268 | if (subunit_12_12_8(dev) != numbers[2]) | |
269 | errx(1, "invalid subunit number"); | |
270 | } else | |
271 | errx(1, "too many fields for format"); | |
272 | return (dev); | |
273 | } | |
274 | ||
275 | ||
276 | struct format { | |
277 | char *name; | |
278 | pack_t *pack; | |
279 | } formats[] = { | |
280 | {"386bsd", pack_8_8}, | |
281 | {"4bsd", pack_8_8}, | |
282 | {"bsdos", pack_bsdos}, | |
283 | {"freebsd", pack_freebsd}, | |
284 | {"hpux", pack_8_24}, | |
285 | {"isc", pack_8_8}, | |
286 | {"linux", pack_8_8}, | |
287 | {"native", pack_native}, | |
288 | {"netbsd", pack_netbsd}, | |
289 | {"osf1", pack_12_20}, | |
290 | {"sco", pack_8_8}, | |
291 | {"solaris", pack_14_18}, | |
292 | {"sunos", pack_8_8}, | |
293 | {"svr3", pack_8_8}, | |
294 | {"svr4", pack_14_18}, | |
295 | {"ultrix", pack_8_8}, | |
296 | }; | |
297 | ||
298 | int compare_format __P((const void *, const void *)); | |
299 | ||
300 | int | |
301 | compare_format(key, element) | |
302 | const void *key; | |
303 | const void *element; | |
304 | { | |
305 | const char *name; | |
306 | const struct format *format; | |
307 | ||
308 | name = key; | |
309 | format = element; | |
310 | ||
311 | return (strcmp(name, format->name)); | |
312 | } | |
313 | ||
314 | ||
315 | int | |
316 | main(argc, argv) | |
317 | int argc; | |
318 | char **argv; | |
319 | { | |
320 | char *name; | |
321 | mode_t mode; | |
322 | dev_t dev; | |
323 | pack_t *pack; | |
324 | u_long numbers[8]; | |
325 | struct format *format; | |
326 | char *p; | |
327 | int n; | |
328 | int ch; | |
329 | ||
330 | pack = pack_native; | |
331 | ||
332 | while ((ch = getopt(argc, argv, "F:")) != -1) { | |
333 | switch (ch) { | |
334 | case 'F': | |
335 | format = bsearch(optarg, formats, | |
336 | sizeof(formats)/sizeof(formats[0]), | |
337 | sizeof(formats[0]), compare_format); | |
338 | if (format == 0) | |
339 | errx(1, "invalid format: %s", optarg); | |
340 | pack = format->pack; | |
341 | break; | |
342 | ||
343 | default: | |
344 | case '?': | |
345 | usage(); | |
346 | } | |
347 | } | |
348 | argc -= optind; | |
349 | argv += optind; | |
350 | ||
864a4b6e | 351 | if (argc < 2 || argc > 10) |
44a7a5ab A |
352 | usage(); |
353 | ||
354 | name = *argv; | |
355 | argc--; | |
356 | argv++; | |
357 | ||
358 | mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; | |
359 | if (*argv[0] == 'c') | |
360 | mode |= S_IFCHR; | |
361 | else if (*argv[0] == 'b') | |
362 | mode |= S_IFBLK; | |
864a4b6e A |
363 | else if (*argv[0] == 'w') |
364 | mode |= S_IFWHT; | |
44a7a5ab | 365 | else |
864a4b6e | 366 | errx(1, "node type must be 'b' or 'c' or 'w'."); |
44a7a5ab A |
367 | argc--; |
368 | argv++; | |
369 | ||
370 | for (n = 0; n < argc; n++) { | |
864a4b6e A |
371 | if (S_ISWHT(mode)) { |
372 | errx(1, "whiteout nodes have no device numbers."); | |
373 | } | |
44a7a5ab A |
374 | numbers[n] = strtoul(argv[n], &p, 0); |
375 | if ((p && *p != '\0') || (numbers[n] == ULONG_MAX && errno == ERANGE)) | |
376 | errx(1, "invalid number: %s", argv[n]); | |
377 | } | |
378 | ||
864a4b6e A |
379 | if (S_ISWHT(mode)) |
380 | dev = 0; | |
381 | else if (argc == 1) | |
4d0bb651 | 382 | dev = (dev_t)numbers[0]; |
44a7a5ab A |
383 | else |
384 | dev = (*pack)(argc, numbers); | |
385 | ||
386 | #if 0 | |
387 | printf("name: %s\nmode: %05o\ndev: %08x\n", name, mode, dev); | |
388 | #else | |
389 | if (mknod(name, mode, dev) < 0) | |
6c780a1f | 390 | err(1, "%s", name); |
44a7a5ab A |
391 | #endif |
392 | ||
393 | exit(0); | |
394 | } | |
395 | ||
396 | void | |
397 | usage() | |
398 | { | |
399 | ||
400 | fprintf(stderr, "usage: mknod [-F format] name [b | c] major minor\n"); | |
401 | fprintf(stderr, " mknod [-F format] name [b | c] major unit subunit\n"); | |
402 | fprintf(stderr, " mknod name [b | c] number\n"); | |
864a4b6e | 403 | fprintf(stderr, " mknod name w\n"); |
44a7a5ab A |
404 | exit(1); |
405 | } |