1 /* $NetBSD: mknod.c,v 1.38 2008/07/20 01:20:22 lukem Exp $ */
4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/cdefs.h>
38 __COPYRIGHT("@(#) Copyright (c) 1998\
39 The NetBSD Foundation, Inc. All rights reserved.");
40 __RCSID("$NetBSD: mknod.c,v 1.38 2008/07/20 01:20:22 lukem Exp $");
43 #include <sys/types.h>
45 #include <sys/param.h>
46 #if !HAVE_NBTOOL_CONFIG_H
47 #include <sys/sysctl.h>
63 static int gid_name(const char *, gid_t
*);
64 static portdev_t
callPack(pack_t
*, int, u_long
*);
66 int main(int, char *[]);
67 static void usage(void);
70 static struct kinfo_drivers
*kern_drivers
;
71 static int num_drivers
;
73 static void get_device_info(void);
74 static void print_device_info(char **);
75 static int major_from_name(const char *, mode_t
);
78 #define MAXARGS 3 /* 3 for bsdos, 2 for rest */
81 main(int argc
, char **argv
)
87 u_long numbers
[MAXARGS
];
88 int n
, ch
, fifo
, hasformat
;
89 int r_flag
= 0; /* force: delete existing entry */
91 int l_flag
= 0; /* list device names and numbers */
100 fifo
= hasformat
= 0;
104 while ((ch
= getopt(argc
, argv
, "lrRF:g:m:u:")) != -1) {
106 while ((ch
= getopt(argc
, argv
, "rRF:g:m:u:")) != -1) {
125 pack
= pack_find(optarg
);
127 errx(1, "invalid format: %s", optarg
);
132 if (optarg
[0] == '#') {
133 gid
= strtol(optarg
+ 1, &p
, 10);
137 if (gid_name(optarg
, &gid
) == 0)
139 gid
= strtol(optarg
, &p
, 10);
142 errx(1, "%s: invalid group name", optarg
);
145 modes
= setmode(optarg
);
147 err(1, "Cannot set file mode `%s'", optarg
);
151 if (optarg
[0] == '#') {
152 uid
= strtol(optarg
+ 1, &p
, 10);
156 if (uid_from_user(optarg
, &uid
) == 0)
158 uid
= strtol(optarg
, &p
, 10);
161 errx(1, "%s: invalid user name", optarg
);
173 print_device_info(argv
);
178 if (argc
< 2 || argc
> 10)
185 umask(mode
= umask(0));
186 mode
= (S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
) & ~mode
;
188 if (argv
[0][1] != '\0')
201 errx(1, "format is meaningless for fifos");
208 errx(1, "node type must be 'b', 'c' or 'p'.");
217 if (argc
< 1 || argc
> MAXARGS
)
221 for (n
= 0; n
< argc
; n
++) {
223 numbers
[n
] = strtoul(argv
[n
], &p
, 0);
224 if (*p
== 0 && errno
== 0)
228 major
= major_from_name(argv
[0], mode
);
233 if (!isdigit(*(unsigned char *)argv
[0]))
234 errx(1, "unknown driver: %s", argv
[0]);
237 errx(1, "invalid number: %s", argv
[n
]);
250 dev
= callPack(pack
, argc
, numbers
);
255 mode
= getmode(modes
, mode
);
257 rval
= fifo
? mkfifo(name
, mode
) : mknod(name
, mode
, dev
);
258 if (rval
< 0 && errno
== EEXIST
&& r_flag
) {
260 if (lstat(name
, &sb
) != 0 || (!fifo
&& sb
.st_rdev
!= dev
))
263 if ((sb
.st_mode
& S_IFMT
) == (mode
& S_IFMT
)) {
265 /* Ignore permissions and user/group */
267 if (sb
.st_mode
!= mode
)
268 rval
= chmod(name
, mode
);
273 rval
= fifo
? mkfifo(name
, mode
)
274 : mknod(name
, mode
, dev
);
279 if ((uid
!= (uid_t
)-1 || gid
!= (uid_t
)-1) && chown(name
, uid
, gid
) == -1)
280 /* XXX Should we unlink the files here? */
281 warn("%s: uid/gid not changed", name
);
289 const char *progname
= getprogname();
291 (void)fprintf(stderr
,
292 "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
294 (void)fprintf(stderr
,
296 " [ name [b | c] [major | driver] minor\n"
298 " [ name [b | c] major minor\n"
300 " | name [b | c] major unit subunit\n"
301 " | name [b | c] number\n"
304 (void)fprintf(stderr
, " %s -l [driver] ...\n", progname
);
310 gid_name(const char *name
, gid_t
*gid
)
322 callPack(pack_t
*f
, int n
, u_long
*numbers
)
325 const char *error
= NULL
;
327 d
= (*f
)(n
, numbers
, &error
);
329 errx(1, "%s", error
);
335 get_device_info(void)
337 static int mib
[2] = {CTL_KERN
, KERN_DRIVERS
};
340 if (sysctl(mib
, 2, NULL
, &len
, NULL
, 0) != 0)
341 err(1, "kern.drivers" );
342 kern_drivers
= malloc(len
);
343 if (kern_drivers
== NULL
)
345 if (sysctl(mib
, 2, kern_drivers
, &len
, NULL
, 0) != 0)
346 err(1, "kern.drivers" );
348 num_drivers
= len
/ sizeof *kern_drivers
;
352 print_device_info(char **names
)
355 struct kinfo_drivers
*kd
;
357 if (kern_drivers
== NULL
)
362 for (i
= 0; i
< num_drivers
; kd
++, i
++) {
363 if (*names
&& strcmp(*names
, kd
->d_name
))
365 printf("%s", kd
->d_name
);
366 if (kd
->d_cmajor
!= -1)
367 printf(" character major %d", kd
->d_cmajor
);
368 if (kd
->d_bmajor
!= -1)
369 printf(" block major %d", kd
->d_bmajor
);
372 } while (*names
&& *++names
);
376 major_from_name(const char *name
, mode_t mode
)
379 struct kinfo_drivers
*kd
;
381 if (kern_drivers
== NULL
)
385 for (i
= 0; i
< num_drivers
; kd
++, i
++) {
386 if (strcmp(name
, kd
->d_name
))