1 /* $NetBSD: mknod.c,v 1.40 2011/08/27 18:37:41 joerg 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.40 2011/08/27 18:37:41 joerg 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 __dead
static void usage(void);
69 static struct kinfo_drivers
*kern_drivers
;
70 static int num_drivers
;
72 static void get_device_info(void);
73 static void print_device_info(char **);
74 static int major_from_name(const char *, mode_t
);
77 #define MAXARGS 3 /* 3 for bsdos, 2 for rest */
80 main(int argc
, char **argv
)
86 u_long numbers
[MAXARGS
];
87 int n
, ch
, fifo
, hasformat
;
88 int r_flag
= 0; /* force: delete existing entry */
90 int l_flag
= 0; /* list device names and numbers */
103 while ((ch
= getopt(argc
, argv
, "lrRF:g:m:u:")) != -1) {
105 while ((ch
= getopt(argc
, argv
, "rRF:g:m:u:")) != -1) {
124 pack
= pack_find(optarg
);
126 errx(1, "invalid format: %s", optarg
);
131 if (optarg
[0] == '#') {
132 gid
= strtol(optarg
+ 1, &p
, 10);
136 if (gid_name(optarg
, &gid
) == 0)
138 gid
= strtol(optarg
, &p
, 10);
141 errx(1, "%s: invalid group name", optarg
);
144 modes
= setmode(optarg
);
146 err(1, "Cannot set file mode `%s'", optarg
);
150 if (optarg
[0] == '#') {
151 uid
= strtol(optarg
+ 1, &p
, 10);
155 if (uid_from_user(optarg
, &uid
) == 0)
157 uid
= strtol(optarg
, &p
, 10);
160 errx(1, "%s: invalid user name", optarg
);
172 print_device_info(argv
);
177 if (argc
< 2 || argc
> 10)
184 umask(mode
= umask(0));
185 mode
= (S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
) & ~mode
;
187 if (argv
[0][1] != '\0')
200 errx(1, "format is meaningless for fifos");
207 errx(1, "node type must be 'b', 'c' or 'p'.");
216 if (argc
< 1 || argc
> MAXARGS
)
220 for (n
= 0; n
< argc
; n
++) {
222 numbers
[n
] = strtoul(argv
[n
], &p
, 0);
223 if (*p
== 0 && errno
== 0)
227 major
= major_from_name(argv
[0], mode
);
232 if (!isdigit(*(unsigned char *)argv
[0]))
233 errx(1, "unknown driver: %s", argv
[0]);
236 errx(1, "invalid number: %s", argv
[n
]);
249 dev
= callPack(pack
, argc
, numbers
);
254 mode
= getmode(modes
, mode
);
256 rval
= fifo
? mkfifo(name
, mode
) : mknod(name
, mode
, dev
);
257 if (rval
< 0 && errno
== EEXIST
&& r_flag
) {
259 if (lstat(name
, &sb
) != 0 || (!fifo
&& sb
.st_rdev
!= dev
))
262 if ((sb
.st_mode
& S_IFMT
) == (mode
& S_IFMT
)) {
264 /* Ignore permissions and user/group */
266 if (sb
.st_mode
!= mode
)
267 rval
= chmod(name
, mode
);
272 rval
= fifo
? mkfifo(name
, mode
)
273 : mknod(name
, mode
, dev
);
278 if ((uid
!= (uid_t
)-1 || gid
!= (uid_t
)-1) && chown(name
, uid
, gid
) == -1)
279 /* XXX Should we unlink the files here? */
280 warn("%s: uid/gid not changed", name
);
288 const char *progname
= getprogname();
290 (void)fprintf(stderr
,
291 "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
293 (void)fprintf(stderr
,
295 " [ name [b | c] [major | driver] minor\n"
297 " [ name [b | c] major minor\n"
299 " | name [b | c] major unit subunit\n"
300 " | name [b | c] number\n"
303 (void)fprintf(stderr
, " %s -l [driver] ...\n", progname
);
309 gid_name(const char *name
, gid_t
*gid
)
321 callPack(pack_t
*f
, int n
, u_long
*numbers
)
324 const char *error
= NULL
;
326 d
= (*f
)(n
, numbers
, &error
);
328 errx(1, "%s", error
);
334 get_device_info(void)
336 static int mib
[2] = {CTL_KERN
, KERN_DRIVERS
};
339 if (sysctl(mib
, 2, NULL
, &len
, NULL
, 0) != 0)
340 err(1, "kern.drivers" );
341 kern_drivers
= malloc(len
);
342 if (kern_drivers
== NULL
)
344 if (sysctl(mib
, 2, kern_drivers
, &len
, NULL
, 0) != 0)
345 err(1, "kern.drivers" );
347 num_drivers
= len
/ sizeof *kern_drivers
;
351 print_device_info(char **names
)
354 struct kinfo_drivers
*kd
;
356 if (kern_drivers
== NULL
)
361 for (i
= 0; i
< num_drivers
; kd
++, i
++) {
362 if (*names
&& strcmp(*names
, kd
->d_name
))
364 printf("%s", kd
->d_name
);
365 if (kd
->d_cmajor
!= -1)
366 printf(" character major %d", kd
->d_cmajor
);
367 if (kd
->d_bmajor
!= -1)
368 printf(" block major %d", kd
->d_bmajor
);
371 } while (*names
&& *++names
);
375 major_from_name(const char *name
, mode_t mode
)
378 struct kinfo_drivers
*kd
;
380 if (kern_drivers
== NULL
)
384 for (i
= 0; i
< num_drivers
; kd
++, i
++) {
385 if (strcmp(name
, kd
->d_name
))