xref: /minix3/minix/usr.sbin/fbdctl/fbdctl.c (revision 33513d60e9146da3430d6f4919674c6d67636992)
1*33513d60SDavid van Moolenbroek /* fbdctl - FBD control tool - by D.C. van Moolenbroek */
2*33513d60SDavid van Moolenbroek #include <stdlib.h>
3*33513d60SDavid van Moolenbroek #include <stdio.h>
4*33513d60SDavid van Moolenbroek #include <string.h>
5*33513d60SDavid van Moolenbroek #include <minix/u64.h>
6*33513d60SDavid van Moolenbroek #include <sys/ioctl.h>
7*33513d60SDavid van Moolenbroek #include <unistd.h>
8*33513d60SDavid van Moolenbroek #include <fcntl.h>
9*33513d60SDavid van Moolenbroek #include <errno.h>
10*33513d60SDavid van Moolenbroek 
11*33513d60SDavid van Moolenbroek #define PATH_DEV_FBD	"/dev/fbd"
12*33513d60SDavid van Moolenbroek 
13*33513d60SDavid van Moolenbroek static void __dead
usage(void)14*33513d60SDavid van Moolenbroek usage(void)
15*33513d60SDavid van Moolenbroek {
16*33513d60SDavid van Moolenbroek 
17*33513d60SDavid van Moolenbroek 	fprintf(stderr, "usage:\n");
18*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  %s list\n", getprogname());
19*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  %s add [-a start[-end]] [-s skip] [-c count] [-rw] "
20*33513d60SDavid van Moolenbroek 	    "<action> [params]\n", getprogname());
21*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  %s del N\n", getprogname());
22*33513d60SDavid van Moolenbroek 	fprintf(stderr, "\n");
23*33513d60SDavid van Moolenbroek 	fprintf(stderr, "actions and params:\n");
24*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  corrupt [zero|persist|random]\n");
25*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  error [OK|EIO]\n");
26*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  misdir <start>-<end> <align>\n");
27*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  lost\n");
28*33513d60SDavid van Moolenbroek 	fprintf(stderr, "  torn <lead>\n");
29*33513d60SDavid van Moolenbroek 	fprintf(stderr, "use %s -d <device> to specify a device other than "
30*33513d60SDavid van Moolenbroek 	    "%s\n", getprogname(), PATH_DEV_FBD);
31*33513d60SDavid van Moolenbroek 
32*33513d60SDavid van Moolenbroek 	exit(EXIT_FAILURE);
33*33513d60SDavid van Moolenbroek }
34*33513d60SDavid van Moolenbroek 
35*33513d60SDavid van Moolenbroek static void
print_rule(struct fbd_rule * rule)36*33513d60SDavid van Moolenbroek print_rule(struct fbd_rule * rule)
37*33513d60SDavid van Moolenbroek {
38*33513d60SDavid van Moolenbroek 	printf("%-2d %04lX%08lX-%04lX%08lX %-4d %-5d %c%c ",
39*33513d60SDavid van Moolenbroek 	    rule->num, ex64hi(rule->start), ex64lo(rule->start),
40*33513d60SDavid van Moolenbroek 	    ex64hi(rule->end), ex64lo(rule->end), rule->skip,
41*33513d60SDavid van Moolenbroek 	    rule->count, (rule->flags & FBD_FLAG_READ) ? 'r' : ' ',
42*33513d60SDavid van Moolenbroek 	    (rule->flags & FBD_FLAG_WRITE) ? 'w' : ' ');
43*33513d60SDavid van Moolenbroek 
44*33513d60SDavid van Moolenbroek 	switch (rule->action) {
45*33513d60SDavid van Moolenbroek 	case FBD_ACTION_CORRUPT:
46*33513d60SDavid van Moolenbroek 		printf("%-7s ", "corrupt");
47*33513d60SDavid van Moolenbroek 		switch (rule->params.corrupt.type) {
48*33513d60SDavid van Moolenbroek 		case FBD_CORRUPT_ZERO: printf("zero"); break;
49*33513d60SDavid van Moolenbroek 		case FBD_CORRUPT_PERSIST: printf("persist"); break;
50*33513d60SDavid van Moolenbroek 		case FBD_CORRUPT_RANDOM: printf("random"); break;
51*33513d60SDavid van Moolenbroek 		default: printf("<unknown>");
52*33513d60SDavid van Moolenbroek 		}
53*33513d60SDavid van Moolenbroek 		break;
54*33513d60SDavid van Moolenbroek 
55*33513d60SDavid van Moolenbroek 	case FBD_ACTION_ERROR:
56*33513d60SDavid van Moolenbroek 		printf("%-7s ", "error");
57*33513d60SDavid van Moolenbroek 
58*33513d60SDavid van Moolenbroek 		switch (rule->params.error.code) {
59*33513d60SDavid van Moolenbroek 		case 0:
60*33513d60SDavid van Moolenbroek 			printf("OK");
61*33513d60SDavid van Moolenbroek 			break;
62*33513d60SDavid van Moolenbroek 		case EIO:
63*33513d60SDavid van Moolenbroek 		case -EIO:
64*33513d60SDavid van Moolenbroek 			printf("EIO");
65*33513d60SDavid van Moolenbroek 			break;
66*33513d60SDavid van Moolenbroek 		default:
67*33513d60SDavid van Moolenbroek 			printf("%d", rule->params.error.code);
68*33513d60SDavid van Moolenbroek 		}
69*33513d60SDavid van Moolenbroek 
70*33513d60SDavid van Moolenbroek 		break;
71*33513d60SDavid van Moolenbroek 
72*33513d60SDavid van Moolenbroek 	case FBD_ACTION_MISDIR:
73*33513d60SDavid van Moolenbroek 		printf("%-7s %04lX%08lX-%04lX%08lX %u",
74*33513d60SDavid van Moolenbroek 		    "misdir", ex64hi(rule->params.misdir.start),
75*33513d60SDavid van Moolenbroek 		    ex64lo(rule->params.misdir.start),
76*33513d60SDavid van Moolenbroek 		    ex64hi(rule->params.misdir.end),
77*33513d60SDavid van Moolenbroek 		    ex64lo(rule->params.misdir.end),
78*33513d60SDavid van Moolenbroek 		    rule->params.misdir.align);
79*33513d60SDavid van Moolenbroek 		break;
80*33513d60SDavid van Moolenbroek 
81*33513d60SDavid van Moolenbroek 	case FBD_ACTION_LOSTTORN:
82*33513d60SDavid van Moolenbroek 		if (rule->params.losttorn.lead > 0)
83*33513d60SDavid van Moolenbroek 			printf("%-7s %u", "torn", rule->params.losttorn.lead);
84*33513d60SDavid van Moolenbroek 		else
85*33513d60SDavid van Moolenbroek 			printf("%-7s", "lost");
86*33513d60SDavid van Moolenbroek 	}
87*33513d60SDavid van Moolenbroek 
88*33513d60SDavid van Moolenbroek 	printf("\n");
89*33513d60SDavid van Moolenbroek }
90*33513d60SDavid van Moolenbroek 
91*33513d60SDavid van Moolenbroek static int
do_list(int fd)92*33513d60SDavid van Moolenbroek do_list(int fd)
93*33513d60SDavid van Moolenbroek {
94*33513d60SDavid van Moolenbroek 	struct fbd_rule rule;
95*33513d60SDavid van Moolenbroek 	int i;
96*33513d60SDavid van Moolenbroek 
97*33513d60SDavid van Moolenbroek 	printf("N  Start        End          Skip Count RW Action  Params\n");
98*33513d60SDavid van Moolenbroek 
99*33513d60SDavid van Moolenbroek 	for (i = 1; ; i++) {
100*33513d60SDavid van Moolenbroek 		rule.num = i;
101*33513d60SDavid van Moolenbroek 
102*33513d60SDavid van Moolenbroek 		if (ioctl(fd, FBDCGETRULE, &rule) < 0) {
103*33513d60SDavid van Moolenbroek 			if (errno == ENOENT)
104*33513d60SDavid van Moolenbroek 				continue;
105*33513d60SDavid van Moolenbroek 			break;
106*33513d60SDavid van Moolenbroek 		}
107*33513d60SDavid van Moolenbroek 
108*33513d60SDavid van Moolenbroek 		print_rule(&rule);
109*33513d60SDavid van Moolenbroek 	}
110*33513d60SDavid van Moolenbroek 
111*33513d60SDavid van Moolenbroek 	return EXIT_SUCCESS;
112*33513d60SDavid van Moolenbroek }
113*33513d60SDavid van Moolenbroek 
114*33513d60SDavid van Moolenbroek static int
scan_hex64(char * input,u64_t * val)115*33513d60SDavid van Moolenbroek scan_hex64(char * input, u64_t * val)
116*33513d60SDavid van Moolenbroek {
117*33513d60SDavid van Moolenbroek 	u32_t lo, hi;
118*33513d60SDavid van Moolenbroek 	char buf[9];
119*33513d60SDavid van Moolenbroek 	int len;
120*33513d60SDavid van Moolenbroek 
121*33513d60SDavid van Moolenbroek 	len = strlen(input);
122*33513d60SDavid van Moolenbroek 
123*33513d60SDavid van Moolenbroek 	if (len < 1 || len > 16) return 0;
124*33513d60SDavid van Moolenbroek 
125*33513d60SDavid van Moolenbroek 	if (len > 8) {
126*33513d60SDavid van Moolenbroek 		memcpy(buf, input, len - 8);
127*33513d60SDavid van Moolenbroek 		buf[len - 8] = 0;
128*33513d60SDavid van Moolenbroek 		input += len - 8;
129*33513d60SDavid van Moolenbroek 
130*33513d60SDavid van Moolenbroek 		hi = strtoul(buf, NULL, 16);
131*33513d60SDavid van Moolenbroek 	}
132*33513d60SDavid van Moolenbroek 	else hi = 0;
133*33513d60SDavid van Moolenbroek 
134*33513d60SDavid van Moolenbroek 	lo = strtoul(input, NULL, 16);
135*33513d60SDavid van Moolenbroek 
136*33513d60SDavid van Moolenbroek 	*val = make64(lo, hi);
137*33513d60SDavid van Moolenbroek 
138*33513d60SDavid van Moolenbroek 	return 1;
139*33513d60SDavid van Moolenbroek }
140*33513d60SDavid van Moolenbroek 
141*33513d60SDavid van Moolenbroek static int
scan_range(char * input,u64_t * start,u64_t * end,int need_end)142*33513d60SDavid van Moolenbroek scan_range(char * input, u64_t * start, u64_t * end, int need_end)
143*33513d60SDavid van Moolenbroek {
144*33513d60SDavid van Moolenbroek 	char *p;
145*33513d60SDavid van Moolenbroek 
146*33513d60SDavid van Moolenbroek 	if ((p = strchr(input, '-')) != NULL) {
147*33513d60SDavid van Moolenbroek 		*p++ = 0;
148*33513d60SDavid van Moolenbroek 
149*33513d60SDavid van Moolenbroek 		if (!scan_hex64(p, end)) return 0;
150*33513d60SDavid van Moolenbroek 	}
151*33513d60SDavid van Moolenbroek 	else if (need_end) return 0;
152*33513d60SDavid van Moolenbroek 
153*33513d60SDavid van Moolenbroek 	return scan_hex64(input, start);
154*33513d60SDavid van Moolenbroek }
155*33513d60SDavid van Moolenbroek 
156*33513d60SDavid van Moolenbroek static int
do_add(int fd,int argc,char ** argv,int off)157*33513d60SDavid van Moolenbroek do_add(int fd, int argc, char ** argv, int off)
158*33513d60SDavid van Moolenbroek {
159*33513d60SDavid van Moolenbroek 	struct fbd_rule rule;
160*33513d60SDavid van Moolenbroek 	int c, r;
161*33513d60SDavid van Moolenbroek 
162*33513d60SDavid van Moolenbroek 	memset(&rule, 0, sizeof(rule));
163*33513d60SDavid van Moolenbroek 
164*33513d60SDavid van Moolenbroek 	while ((c = getopt(argc-off, argv+off, "a:s:c:rw")) != EOF) {
165*33513d60SDavid van Moolenbroek 		switch (c) {
166*33513d60SDavid van Moolenbroek 		case 'a':
167*33513d60SDavid van Moolenbroek 			if (!scan_range(optarg, &rule.start, &rule.end, 0))
168*33513d60SDavid van Moolenbroek 				usage();
169*33513d60SDavid van Moolenbroek 			break;
170*33513d60SDavid van Moolenbroek 		case 's':
171*33513d60SDavid van Moolenbroek 			rule.skip = atoi(optarg);
172*33513d60SDavid van Moolenbroek 			break;
173*33513d60SDavid van Moolenbroek 		case 'c':
174*33513d60SDavid van Moolenbroek 			rule.count = atoi(optarg);
175*33513d60SDavid van Moolenbroek 			break;
176*33513d60SDavid van Moolenbroek 		case 'r':
177*33513d60SDavid van Moolenbroek 			rule.flags |= FBD_FLAG_READ;
178*33513d60SDavid van Moolenbroek 			break;
179*33513d60SDavid van Moolenbroek 		case 'w':
180*33513d60SDavid van Moolenbroek 			rule.flags |= FBD_FLAG_WRITE;
181*33513d60SDavid van Moolenbroek 			break;
182*33513d60SDavid van Moolenbroek 		default:
183*33513d60SDavid van Moolenbroek 			usage();
184*33513d60SDavid van Moolenbroek 		}
185*33513d60SDavid van Moolenbroek 	}
186*33513d60SDavid van Moolenbroek 
187*33513d60SDavid van Moolenbroek 	optind += off; /* compensate for the shifted argc/argv */
188*33513d60SDavid van Moolenbroek 
189*33513d60SDavid van Moolenbroek 	if (optind >= argc) usage();
190*33513d60SDavid van Moolenbroek 
191*33513d60SDavid van Moolenbroek 	/* default to reads and writes */
192*33513d60SDavid van Moolenbroek 	if (!rule.flags) rule.flags = FBD_FLAG_READ | FBD_FLAG_WRITE;
193*33513d60SDavid van Moolenbroek 
194*33513d60SDavid van Moolenbroek 	if (!strcmp(argv[optind], "corrupt")) {
195*33513d60SDavid van Moolenbroek 		if (optind+1 >= argc) usage();
196*33513d60SDavid van Moolenbroek 
197*33513d60SDavid van Moolenbroek 		rule.action = FBD_ACTION_CORRUPT;
198*33513d60SDavid van Moolenbroek 
199*33513d60SDavid van Moolenbroek 		if (!strcmp(argv[optind+1], "zero"))
200*33513d60SDavid van Moolenbroek 			rule.params.corrupt.type = FBD_CORRUPT_ZERO;
201*33513d60SDavid van Moolenbroek 		else if (!strcmp(argv[optind+1], "persist"))
202*33513d60SDavid van Moolenbroek 			rule.params.corrupt.type = FBD_CORRUPT_PERSIST;
203*33513d60SDavid van Moolenbroek 		else if (!strcmp(argv[optind+1], "random"))
204*33513d60SDavid van Moolenbroek 			rule.params.corrupt.type = FBD_CORRUPT_RANDOM;
205*33513d60SDavid van Moolenbroek 		else usage();
206*33513d60SDavid van Moolenbroek 	}
207*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[optind], "error")) {
208*33513d60SDavid van Moolenbroek 		if (optind+1 >= argc) usage();
209*33513d60SDavid van Moolenbroek 
210*33513d60SDavid van Moolenbroek 		rule.action = FBD_ACTION_ERROR;
211*33513d60SDavid van Moolenbroek 
212*33513d60SDavid van Moolenbroek 		if (!strcmp(argv[optind+1], "OK"))
213*33513d60SDavid van Moolenbroek 			rule.params.error.code = 0;
214*33513d60SDavid van Moolenbroek 		else if (!strcmp(argv[optind+1], "EIO")) {
215*33513d60SDavid van Moolenbroek 			if (EIO > 0)
216*33513d60SDavid van Moolenbroek 				rule.params.error.code = -EIO;
217*33513d60SDavid van Moolenbroek 			else
218*33513d60SDavid van Moolenbroek 				rule.params.error.code = EIO;
219*33513d60SDavid van Moolenbroek 		}
220*33513d60SDavid van Moolenbroek 		else usage();
221*33513d60SDavid van Moolenbroek 	}
222*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[optind], "misdir")) {
223*33513d60SDavid van Moolenbroek 		if (optind+2 >= argc) usage();
224*33513d60SDavid van Moolenbroek 
225*33513d60SDavid van Moolenbroek 		rule.action = FBD_ACTION_MISDIR;
226*33513d60SDavid van Moolenbroek 
227*33513d60SDavid van Moolenbroek 		if (!scan_range(argv[optind+1], &rule.params.misdir.start,
228*33513d60SDavid van Moolenbroek 		    &rule.params.misdir.end, 1))
229*33513d60SDavid van Moolenbroek 			usage();
230*33513d60SDavid van Moolenbroek 
231*33513d60SDavid van Moolenbroek 		rule.params.misdir.align = atoi(argv[optind+2]);
232*33513d60SDavid van Moolenbroek 
233*33513d60SDavid van Moolenbroek 		if ((int)rule.params.misdir.align <= 0)
234*33513d60SDavid van Moolenbroek 			usage();
235*33513d60SDavid van Moolenbroek 	}
236*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[optind], "lost")) {
237*33513d60SDavid van Moolenbroek 		rule.action = FBD_ACTION_LOSTTORN;
238*33513d60SDavid van Moolenbroek 
239*33513d60SDavid van Moolenbroek 		rule.params.losttorn.lead = 0;
240*33513d60SDavid van Moolenbroek 	}
241*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[optind], "torn")) {
242*33513d60SDavid van Moolenbroek 		if (optind+1 >= argc) usage();
243*33513d60SDavid van Moolenbroek 
244*33513d60SDavid van Moolenbroek 		rule.action = FBD_ACTION_LOSTTORN;
245*33513d60SDavid van Moolenbroek 
246*33513d60SDavid van Moolenbroek 		rule.params.losttorn.lead = atoi(argv[optind+1]);
247*33513d60SDavid van Moolenbroek 
248*33513d60SDavid van Moolenbroek 		if ((int)rule.params.losttorn.lead <= 0)
249*33513d60SDavid van Moolenbroek 			usage();
250*33513d60SDavid van Moolenbroek 	}
251*33513d60SDavid van Moolenbroek 	else usage();
252*33513d60SDavid van Moolenbroek 
253*33513d60SDavid van Moolenbroek #if DEBUG
254*33513d60SDavid van Moolenbroek 	print_rule(&rule);
255*33513d60SDavid van Moolenbroek #endif
256*33513d60SDavid van Moolenbroek 
257*33513d60SDavid van Moolenbroek 	r = ioctl(fd, FBDCADDRULE, &rule);
258*33513d60SDavid van Moolenbroek 
259*33513d60SDavid van Moolenbroek 	if (r < 0) {
260*33513d60SDavid van Moolenbroek 		perror("ioctl");
261*33513d60SDavid van Moolenbroek 
262*33513d60SDavid van Moolenbroek 		return EXIT_FAILURE;
263*33513d60SDavid van Moolenbroek 	}
264*33513d60SDavid van Moolenbroek 
265*33513d60SDavid van Moolenbroek 	printf("Added rule %d\n", r);
266*33513d60SDavid van Moolenbroek 
267*33513d60SDavid van Moolenbroek 	return EXIT_SUCCESS;
268*33513d60SDavid van Moolenbroek }
269*33513d60SDavid van Moolenbroek 
270*33513d60SDavid van Moolenbroek static int
do_del(int fd,int argc,char ** argv,int off)271*33513d60SDavid van Moolenbroek do_del(int fd, int argc, char ** argv, int off)
272*33513d60SDavid van Moolenbroek {
273*33513d60SDavid van Moolenbroek 	fbd_rulenum_t num;
274*33513d60SDavid van Moolenbroek 
275*33513d60SDavid van Moolenbroek 	if (argc < off + 2)
276*33513d60SDavid van Moolenbroek 		usage();
277*33513d60SDavid van Moolenbroek 
278*33513d60SDavid van Moolenbroek 	num = atoi(argv[off + 1]);
279*33513d60SDavid van Moolenbroek 
280*33513d60SDavid van Moolenbroek 	if (ioctl(fd, FBDCDELRULE, &num)) {
281*33513d60SDavid van Moolenbroek 		perror("ioctl");
282*33513d60SDavid van Moolenbroek 
283*33513d60SDavid van Moolenbroek 		return EXIT_FAILURE;
284*33513d60SDavid van Moolenbroek 	}
285*33513d60SDavid van Moolenbroek 
286*33513d60SDavid van Moolenbroek 	printf("Deleted rule %d\n", num);
287*33513d60SDavid van Moolenbroek 
288*33513d60SDavid van Moolenbroek 	return EXIT_SUCCESS;
289*33513d60SDavid van Moolenbroek }
290*33513d60SDavid van Moolenbroek 
291*33513d60SDavid van Moolenbroek int
main(int argc,char ** argv)292*33513d60SDavid van Moolenbroek main(int argc, char ** argv)
293*33513d60SDavid van Moolenbroek {
294*33513d60SDavid van Moolenbroek 	int r, fd, off = 1;
295*33513d60SDavid van Moolenbroek 	const char *dev = PATH_DEV_FBD;
296*33513d60SDavid van Moolenbroek 
297*33513d60SDavid van Moolenbroek 	setprogname(argv[0]);
298*33513d60SDavid van Moolenbroek 
299*33513d60SDavid van Moolenbroek 	if (argc < 2)
300*33513d60SDavid van Moolenbroek 		usage();
301*33513d60SDavid van Moolenbroek 
302*33513d60SDavid van Moolenbroek 	if (!strcmp(argv[1], "-d")) {
303*33513d60SDavid van Moolenbroek 		if (argc < 4)
304*33513d60SDavid van Moolenbroek 			usage();
305*33513d60SDavid van Moolenbroek 
306*33513d60SDavid van Moolenbroek 		dev = argv[2];
307*33513d60SDavid van Moolenbroek 
308*33513d60SDavid van Moolenbroek 		off += 2;
309*33513d60SDavid van Moolenbroek 	}
310*33513d60SDavid van Moolenbroek 
311*33513d60SDavid van Moolenbroek 	fd = open(dev, O_RDONLY);
312*33513d60SDavid van Moolenbroek 	if (fd < 0) {
313*33513d60SDavid van Moolenbroek 		perror(dev);
314*33513d60SDavid van Moolenbroek 
315*33513d60SDavid van Moolenbroek 		return EXIT_FAILURE;
316*33513d60SDavid van Moolenbroek 	}
317*33513d60SDavid van Moolenbroek 
318*33513d60SDavid van Moolenbroek 	if (!strcmp(argv[off], "list"))
319*33513d60SDavid van Moolenbroek 		r = do_list(fd);
320*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[off], "add"))
321*33513d60SDavid van Moolenbroek 		r = do_add(fd, argc, argv, off);
322*33513d60SDavid van Moolenbroek 	else if (!strcmp(argv[off], "del"))
323*33513d60SDavid van Moolenbroek 		r = do_del(fd, argc, argv, off);
324*33513d60SDavid van Moolenbroek 	else
325*33513d60SDavid van Moolenbroek 		usage();
326*33513d60SDavid van Moolenbroek 
327*33513d60SDavid van Moolenbroek 	close(fd);
328*33513d60SDavid van Moolenbroek 
329*33513d60SDavid van Moolenbroek 	return r;
330*33513d60SDavid van Moolenbroek }
331