summaryrefslogtreecommitdiffstats
path: root/usr/utils/mknod.c
blob: fa7ac7a68485d2be72d65bc7a73c0e256de0b4f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

char *progname;

static __noreturn usage(void)
{
	fprintf(stderr, "Usage: %s [-m mode] name {b|c|p} major minor\n",
			progname);
	exit(1);
}

int main(int argc, char *argv[])
{
	char *name, *type, typec, *endp;
	unsigned int major_num, minor_num;
	mode_t mode, mode_set = 0;
	dev_t dev;

	progname = *argv++;
	if (argc == 1)
		usage();

	if (argv[0][0] == '-' && argv[0][1] == 'm' && !argv[0][2]) {
		mode_set = strtoul(argv[1], &endp, 8);
		argv += 2;
	}

	name = *argv++;
	if (!name)
		usage();

	type = *argv++;
	if (!type || !type[0] || type[1])
		usage();
	typec = type[0];

	mode = 0;
	switch (typec) {
	case 'c':
		mode = S_IFCHR;
		break;
	case 'b':
		mode = S_IFBLK;
		break;
	case 'p':
		mode = S_IFIFO;
		break;
	default:
		usage();
	}

	if (mode == S_IFIFO) {
		dev = 0;
	} else {
		if (!argv[0] || !argv[1])
			usage();

		major_num = strtol(*argv++, &endp, 0);
		if (*endp != '\0')
			usage();
		minor_num = strtol(*argv++, &endp, 0);
		if (*endp != '\0')
			usage();
		dev = makedev(major_num, minor_num);
	}

	if (*argv)
		usage();

	if (mknod(name, mode|0666, dev) == -1) {
		perror("mknod");
		exit(1);
	}

	if (mode_set && chmod(name, mode_set)) {
		perror("chmod");
		exit(1);
	}

	exit(0);
}