vm: fix potential null deref
[minix.git] / commands / fbdctl / fbdctl.c
blob5e951f06189e7ddaf599a41e0c7876caa1f9b085
1 /* fbdctl - FBD control tool - by D.C. van Moolenbroek */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <minix/ioctl.h>
6 #include <minix/u64.h>
7 #include <sys/ioc_fbd.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <errno.h>
12 static int usage(char *name)
14 printf("usage:\n");
15 printf(" %s list\n", name);
16 printf(" %s add [-a start[-end]] [-s skip] [-c count] [-rw] "
17 "<action> [params]\n", name);
18 printf(" %s del N\n", name);
19 printf("\n");
20 printf("actions and params:\n");
21 printf(" corrupt [zero|persist|random]\n");
22 printf(" error [OK|EIO]\n");
23 printf(" misdir <start>-<end> <align>\n");
24 printf(" lost\n");
25 printf(" torn <lead>\n");
26 printf("use %s -d <device> to specify a device other than /dev/fbd\n",
27 name);
29 return EXIT_FAILURE;
32 static void print_rule(struct fbd_rule *rule)
34 printf("%-2d %04lX%08lX-%04lX%08lX %-4d %-5d %c%c ",
35 rule->num, ex64hi(rule->start), ex64lo(rule->start),
36 ex64hi(rule->end), ex64lo(rule->end), rule->skip,
37 rule->count, (rule->flags & FBD_FLAG_READ) ? 'r' : ' ',
38 (rule->flags & FBD_FLAG_WRITE) ? 'w' : ' ');
40 switch (rule->action) {
41 case FBD_ACTION_CORRUPT:
42 printf("%-7s ", "corrupt");
43 switch (rule->params.corrupt.type) {
44 case FBD_CORRUPT_ZERO: printf("zero"); break;
45 case FBD_CORRUPT_PERSIST: printf("persist"); break;
46 case FBD_CORRUPT_RANDOM: printf("random"); break;
47 default: printf("<unknown>");
49 break;
51 case FBD_ACTION_ERROR:
52 printf("%-7s ", "error");
54 switch (rule->params.error.code) {
55 case 0:
56 printf("OK");
57 break;
58 case EIO:
59 case -EIO:
60 printf("EIO");
61 break;
62 default:
63 printf("%d", rule->params.error.code);
66 break;
68 case FBD_ACTION_MISDIR:
69 printf("%-7s %04lX%08lX-%04lX%08lX %u",
70 "misdir", ex64hi(rule->params.misdir.start),
71 ex64lo(rule->params.misdir.start),
72 ex64hi(rule->params.misdir.end),
73 ex64lo(rule->params.misdir.end),
74 rule->params.misdir.align);
75 break;
77 case FBD_ACTION_LOSTTORN:
78 if (rule->params.losttorn.lead > 0)
79 printf("%-7s %u", "torn",
80 rule->params.losttorn.lead);
81 else
82 printf("%-7s", "lost");
85 printf("\n");
88 static int do_list(int fd)
90 struct fbd_rule rule;
91 int i;
93 printf("N Start End Skip Count RW Action Params\n");
95 for (i = 1; ; i++) {
96 rule.num = i;
98 if (ioctl(fd, FBDCGETRULE, &rule) < 0) {
99 if (errno == ENOENT)
100 continue;
101 break;
104 print_rule(&rule);
107 return EXIT_SUCCESS;
110 static int scan_hex64(char *input, u64_t *val)
112 u32_t lo, hi;
113 char buf[9];
114 int len;
116 len = strlen(input);
118 if (len < 1 || len > 16) return 0;
120 if (len > 8) {
121 memcpy(buf, input, len - 8);
122 buf[len - 8] = 0;
123 input += len - 8;
125 hi = strtoul(buf, NULL, 16);
127 else hi = 0;
129 lo = strtoul(input, NULL, 16);
131 *val = make64(lo, hi);
133 return 1;
136 static int scan_range(char *input, u64_t *start, u64_t *end, int need_end)
138 char *p;
140 if ((p = strchr(input, '-')) != NULL) {
141 *p++ = 0;
143 if (!scan_hex64(p, end)) return 0;
145 else if (need_end) return 0;
147 return scan_hex64(input, start);
150 static int do_add(int fd, int argc, char **argv, int off)
152 struct fbd_rule rule;
153 int c, r;
155 memset(&rule, 0, sizeof(rule));
157 while ((c = getopt(argc-off, argv+off, "a:s:c:rw")) != EOF) {
158 switch (c) {
159 case 'a':
160 if (!scan_range(optarg, &rule.start, &rule.end, 0))
161 return usage(argv[0]);
162 break;
163 case 's':
164 rule.skip = atoi(optarg);
165 break;
166 case 'c':
167 rule.count = atoi(optarg);
168 break;
169 case 'r':
170 rule.flags |= FBD_FLAG_READ;
171 break;
172 case 'w':
173 rule.flags |= FBD_FLAG_WRITE;
174 break;
175 default:
176 return usage(argv[0]);
180 optind += off; /* compensate for the shifted argc/argv */
182 if (optind >= argc) return usage(argv[0]);
184 /* default to reads and writes */
185 if (!rule.flags) rule.flags = FBD_FLAG_READ | FBD_FLAG_WRITE;
187 if (!strcmp(argv[optind], "corrupt")) {
188 if (optind+1 >= argc) return usage(argv[0]);
190 rule.action = FBD_ACTION_CORRUPT;
192 if (!strcmp(argv[optind+1], "zero"))
193 rule.params.corrupt.type = FBD_CORRUPT_ZERO;
194 else if (!strcmp(argv[optind+1], "persist"))
195 rule.params.corrupt.type = FBD_CORRUPT_PERSIST;
196 else if (!strcmp(argv[optind+1], "random"))
197 rule.params.corrupt.type = FBD_CORRUPT_RANDOM;
198 else return usage(argv[0]);
200 else if (!strcmp(argv[optind], "error")) {
201 if (optind+1 >= argc) return usage(argv[0]);
203 rule.action = FBD_ACTION_ERROR;
205 if (!strcmp(argv[optind+1], "OK"))
206 rule.params.error.code = 0;
207 else if (!strcmp(argv[optind+1], "EIO")) {
208 if (EIO > 0)
209 rule.params.error.code = -EIO;
210 else
211 rule.params.error.code = EIO;
213 else return usage(argv[0]);
215 else if (!strcmp(argv[optind], "misdir")) {
216 if (optind+2 >= argc) return usage(argv[0]);
218 rule.action = FBD_ACTION_MISDIR;
220 if (!scan_range(argv[optind+1], &rule.params.misdir.start,
221 &rule.params.misdir.end, 1))
222 return usage(argv[0]);
224 rule.params.misdir.align = atoi(argv[optind+2]);
226 if ((int) rule.params.misdir.align <= 0)
227 return usage(argv[0]);
229 else if (!strcmp(argv[optind], "lost")) {
230 rule.action = FBD_ACTION_LOSTTORN;
232 rule.params.losttorn.lead = 0;
234 else if (!strcmp(argv[optind], "torn")) {
235 if (optind+1 >= argc) return usage(argv[0]);
237 rule.action = FBD_ACTION_LOSTTORN;
239 rule.params.losttorn.lead = atoi(argv[optind+1]);
241 if ((int) rule.params.losttorn.lead <= 0)
242 return usage(argv[0]);
244 else return usage(argv[0]);
246 #if DEBUG
247 print_rule(&rule);
248 #endif
250 r = ioctl(fd, FBDCADDRULE, &rule);
252 if (r < 0) {
253 perror("ioctl");
255 return EXIT_FAILURE;
258 printf("Added rule %d\n", r);
260 return EXIT_SUCCESS;
263 static int do_del(int fd, int argc, char **argv, int off)
265 fbd_rulenum_t num;
267 if (argc < off + 2)
268 return usage(argv[0]);
270 num = atoi(argv[off + 1]);
272 if (ioctl(fd, FBDCDELRULE, &num)) {
273 perror("ioctl");
275 return EXIT_FAILURE;
278 printf("Deleted rule %d\n", num);
280 return EXIT_SUCCESS;
283 int main(int argc, char **argv)
285 int r, fd, off = 1;
286 char *dev = "/dev/fbd";
288 if (argc < 2)
289 return usage(argv[0]);
291 if (!strcmp(argv[1], "-d")) {
292 if (argc < 4)
293 return usage(argv[0]);
295 dev = argv[2];
297 off += 2;
300 fd = open(dev, O_RDONLY);
301 if (fd < 0) {
302 perror(dev);
304 return EXIT_FAILURE;
307 else if (!strcmp(argv[off], "list"))
308 r = do_list(fd);
309 else if (!strcmp(argv[off], "add"))
310 r = do_add(fd, argc, argv, off);
311 else if (!strcmp(argv[off], "del"))
312 r = do_del(fd, argc, argv, off);
313 else
314 r = usage(argv[0]);
316 close(fd);
318 return r;