1/*
2 * create_floppy_devices
3 *
4 * Create all possible floppy device based on the CMOS type.
5 * Based upon code from drivers/block/floppy.c
6 *
7 * Copyright(C) 2005, SUSE Linux Products GmbH
8 *
9 * Author:
10 *	Hannes Reinecke <hare@suse.de>
11 *
12 *	This program is free software; you can redistribute it and/or modify it
13 *	under the terms of the GNU General Public License as published by the
14 *	Free Software Foundation version 2 of the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <unistd.h>
23#include <string.h>
24#include <pwd.h>
25#include <grp.h>
26
27#include "../../udev.h"
28#include "../../udev_selinux.h"
29
30static char *table[] = {
31	"", "d360", "h1200", "u360", "u720", "h360", "h720",
32	"u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
33	"u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
34	"h880", "u1040", "u1120", "h1600", "u1760", "u1920",
35	"u3200", "u3520", "u3840", "u1840", "u800", "u1600",
36	NULL
37};
38
39static int t360[] = { 1, 0 };
40static int t1200[] = { 2, 5, 6, 10, 12, 14, 16, 18, 20, 23, 0 };
41static int t3in[] = { 8, 9, 26, 27, 28, 7, 11, 15, 19, 24, 25, 29, 31, 3, 4, 13, 17, 21, 22, 30, 0 };
42static int *table_sup[] = { NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in };
43
44#ifdef USE_LOG
45void log_message(int priority, const char *format, ...)
46{
47	va_list args;
48	static int udev_log = -1;
49
50	if (udev_log == -1) {
51		const char *value;
52
53		value = getenv("UDEV_LOG");
54		if (value)
55			udev_log = log_priority(value);
56		else
57			udev_log = LOG_ERR;
58	}
59
60	if (priority > udev_log)
61		return;
62
63	va_start(args, format);
64	vsyslog(priority, format, args);
65	va_end(args);
66}
67#endif
68
69int main(int argc, char **argv)
70{
71	char *dev;
72	char node[64];
73	int type = 0, i, fdnum, c;
74	int major = 2, minor;
75	uid_t uid = 0;
76	gid_t gid = 0;
77	mode_t mode = 0660;
78	int create_nodes = 0;
79	int print_nodes = 0;
80	int is_err = 0;
81
82	while ((c = getopt(argc, argv, "cudm:U:G:M:t:")) != -1) {
83		switch (c) {
84		case 'c':
85			create_nodes = 1;
86			break;
87		case 'd':
88			print_nodes = 1;
89			break;
90		case 'U':
91			uid = lookup_user(optarg);
92			break;
93		case 'G':
94			gid = lookup_group(optarg);
95			break;
96		case 'M':
97			mode = strtol(optarg, NULL, 0);
98			mode = mode & 0666;
99			break;
100		case 'm':
101			major = strtol(optarg, NULL, 0);
102			break;
103		case 't':
104			type = strtol(optarg, NULL, 0);
105			break;
106		default:
107			is_err++;
108			break;
109		}
110	}
111
112	if (is_err || optind >= argc) {
113		printf("Usage:  %s [OPTION] device\n"
114		       "  -c   create\n"
115		       "  -d   debug\n"
116		       "  -m   Major number\n"
117		       "  -t   floppy type number\n"
118		       "  -U   device node user ownership\n"
119		       "  -G   device node group owner\n"
120		       "  -M   device node mode\n"
121		       "\n", argv[0]);
122		return 1;
123	}
124
125	dev = argv[optind];
126	if (dev[strlen(dev) - 3] != 'f' || dev[strlen(dev) -2 ] != 'd') {
127		fprintf(stderr,"Device '%s' is not a floppy device\n", dev);
128		return 1;
129	}
130
131	fdnum = strtol(dev + 2, NULL, 10);
132	if (fdnum < 0 || fdnum > 7) {
133		fprintf(stderr,"Floppy device number %d out of range (0-7)\n", fdnum);
134		return 1;
135	}
136	if (fdnum > 3)
137		fdnum += 128;
138
139	if (major < 1) {
140		fprintf(stderr,"Invalid major number %d\n", major);
141		return 1;
142	}
143
144	if (type < 0 || type > (int) sizeof(table)) {
145		fprintf(stderr,"Invalid CMOS type %d\n", type);
146		return 1;
147	}
148
149	if (type == 0)
150		return 0;
151
152	udev_config_init();
153	selinux_init();
154
155	i = 0;
156	while (table_sup[type][i]) {
157		sprintf(node, "%s%s", dev, table[table_sup[type][i]]);
158		minor = (table_sup[type][i] << 2) + fdnum;
159		if (print_nodes)
160			printf("%s b %d %d %d\n", node, mode, major, minor);
161		if (create_nodes) {
162			unlink(node);
163			selinux_setfscreatecon(node, NULL, S_IFBLK | mode);
164			mknod(node, S_IFBLK | mode, makedev(major,minor));
165			selinux_resetfscreatecon();
166			chown(node, uid, gid);
167			chmod(node, S_IFBLK | mode);
168		}
169		i++;
170	}
171
172	selinux_exit();
173	return 0;
174}
175