1 /*
2 * mknod - build special file
3 *
4 * Gunnar Ritter, Freiburg i. Br., Germany, August 2003.
5 */
6 /*
7 * Copyright (c) 2003 Gunnar Ritter
8 *
9 * This software is provided 'as-is', without any express or implied
10 * warranty. In no event will the authors be held liable for any damages
11 * arising from the use of this software.
12 *
13 * Permission is granted to anyone to use this software for any purpose,
14 * including commercial applications, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
16 *
17 * 1. The origin of this software must not be misrepresented; you must not
18 * claim that you wrote the original software. If you use this software
19 * in a product, an acknowledgment in the product documentation would be
20 * appreciated but is not required.
21 *
22 * 2. Altered source versions must be plainly marked as such, and must not be
23 * misrepresented as being the original software.
24 *
25 * 3. This notice may not be removed or altered from any source distribution.
26 */
27
28 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
29 #define USED __attribute__ ((used))
30 #elif defined __GNUC__
31 #define USED __attribute__ ((unused))
32 #else
33 #define USED
34 #endif
35 static const char sccsid[] USED = "@(#)mknod.sl 1.8 (gritter) 5/29/05";
36
37 #if defined (__GLIBC__) || defined (_AIX)
38 #include <sys/sysmacros.h>
39 #endif /* __GLIBC__ || _AIX */
40 #include <sys/stat.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <libgen.h>
44 #include <errno.h>
45 #include <string.h>
46 #include <limits.h>
47 #include <unistd.h>
48 #ifndef major
49 #include <sys/mkdev.h>
50 #endif /* !major */
51
52 #ifndef S_IFNAM
53 #define S_IFNAM 0x5000
54 #endif
55 #ifndef S_INSEM
56 #define S_INSEM 0x1
57 #endif
58 #ifndef S_INSHD
59 #define S_INSHD 0x2
60 #endif
61
62 static char *progname;
63 static long max_major;
64 static long max_minor;
65
66 static void
usage(void)67 usage(void)
68 {
69 fprintf(stderr, "usage: %s name [ b/c major minor ] [ p ]\n",
70 progname);
71 exit(2);
72 }
73
74 static int
mnode(const char * name,mode_t type,dev_t dev)75 mnode(const char *name, mode_t type, dev_t dev)
76 {
77 if (mknod(name, type|0666, dev) == 0)
78 return 0;
79 switch (errno) {
80 case EPERM:
81 fprintf(stderr, "%s: must be super-user\n", progname);
82 break;
83 default:
84 fprintf(stderr, "%s: %s\n", progname, strerror(errno));
85 }
86 return 1;
87 }
88
89 static dev_t
nu(const char * s,const char * msg,dev_t max)90 nu(const char *s, const char *msg, dev_t max)
91 {
92 int n;
93
94 n = atoi(s);
95 if (n < 0 || n > max) {
96 fprintf(stderr, "%s: invalid %s number '%s' - "
97 "valid range is 0-%d\n",
98 progname, msg, s, (int)max);
99 exit(2);
100 }
101 return n;
102 }
103
104 static int
mspec(int ac,char ** av,mode_t type)105 mspec(int ac, char **av, mode_t type)
106 {
107 dev_t major, minor;
108
109 if (ac != 5)
110 usage();
111 major = nu(av[3], "major", max_major);
112 minor = nu(av[4], "minor", max_minor);
113 return mnode(av[1], type, makedev(major, minor));
114 }
115
116 static int
mfifo(int ac,char ** av)117 mfifo(int ac, char **av)
118 {
119 if (ac != 3)
120 usage();
121 return mnode(av[1], S_IFIFO, 0);
122 }
123
124 static int
mnam(int ac,char ** av,mode_t type)125 mnam(int ac, char **av, mode_t type)
126 {
127 if (ac != 3)
128 usage();
129 return mnode(av[1], S_IFNAM, type);
130 }
131
132 static void
getlimits(void)133 getlimits(void)
134 {
135 #ifdef __linux__
136 #ifndef WORD_BIT
137 int WORD_BIT;
138 for (WORD_BIT = 2; (1<<WORD_BIT) != 1; WORD_BIT++);
139 #endif /* !WORD_BIT */
140 max_major = (1<<(WORD_BIT-20)) - 1;
141 max_minor = (1<<20) - 1;
142 #else /* !__linux__ */
143 max_major = (1<<14) - 1;
144 max_minor = (1<<18) - 1;
145 #endif /* !__linux__ */
146 }
147
148 int
main(int argc,char ** argv)149 main(int argc, char **argv)
150 {
151 progname = basename(argv[0]);
152 if (argc < 3)
153 usage();
154 if (argv[2][1] != '\0')
155 usage();
156 getlimits();
157 switch (argv[2][0]) {
158 case 'b':
159 return mspec(argc, argv, S_IFBLK);
160 case 'c':
161 return mspec(argc, argv, S_IFCHR);
162 case 'p':
163 return mfifo(argc, argv);
164 case 'm':
165 return mnam(argc, argv, S_INSHD);
166 case 's':
167 return mnam(argc, argv, S_INSEM);
168 default:
169 usage();
170 }
171 /*NOTREACHED*/
172 return 0;
173 }
174