debuggers.hg

view tools/blktap2/control/tap-ctl.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents a34358c64b63
children
line source
1 /*
2 * Copyright (c) 2008, XenSource Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <getopt.h>
35 #include "tap-ctl.h"
37 typedef int (*tap_ctl_func_t) (int, char **);
39 struct command {
40 char *name;
41 tap_ctl_func_t func;
42 };
44 static void
45 tap_cli_list_usage(FILE *stream)
46 {
47 fprintf(stream,
48 "usage: list [-h] [-p pid] [-m minor] [-t type] [-f file]\n");
49 }
51 static void
52 tap_ctl_list_row(tap_list_t *entry)
53 {
54 char minor_str[10] = "-";
55 char state_str[10] = "-";
56 char pid_str[10] = "-";
58 if (entry->pid != -1)
59 sprintf(pid_str, "%d", entry->pid);
61 if (entry->minor != -1)
62 sprintf(minor_str, "%d", entry->minor);
64 if (entry->state != -1)
65 sprintf(state_str, "%x", entry->state);
67 printf("%8s %2s %4s %10s %s\n",
68 pid_str, minor_str, state_str,
69 entry->type ? : "-", entry->path ? : "-");
70 }
72 static void
73 tap_ctl_list_dict(tap_list_t *entry)
74 {
75 int d = 0;
77 if (entry->pid != -1) {
78 if (d) putc(' ', stdout);
79 d = printf("pid=%d", entry->pid);
80 }
82 if (entry->minor != -1) {
83 if (d) putc(' ', stdout);
84 d = printf("minor=%d", entry->minor);
85 }
87 if (entry->state != -1) {
88 if (d) putc(' ', stdout);
89 d = printf("state=%d", entry->state);
90 }
92 if (entry->type && entry->path) {
93 if (d) putc(' ', stdout);
94 d = printf("args=%s:%s", entry->type, entry->path);
95 }
97 putc('\n', stdout);
98 }
100 int
101 tap_cli_list(int argc, char **argv)
102 {
103 tap_list_t **list, **_entry;
104 int c, minor, tty, err;
105 const char *type, *file;
106 pid_t pid;
108 err = tap_ctl_list(&list);
109 if (err)
110 return -err;
112 pid = -1;
113 minor = -1;
114 type = NULL;
115 file = NULL;
117 while ((c = getopt(argc, argv, "m:p:t:f:h")) != -1) {
118 switch (c) {
119 case 'm':
120 minor = atoi(optarg);
121 break;
122 case 'p':
123 pid = atoi(optarg);
124 break;
125 case 't':
126 type = optarg;
127 break;
128 case 'f':
129 file = optarg;
130 break;
131 case '?':
132 goto usage;
133 case 'h':
134 tap_cli_list_usage(stdout);
135 return 0;
136 }
137 }
139 tty = isatty(STDOUT_FILENO);
141 for (_entry = list; *_entry != NULL; ++_entry) {
142 tap_list_t *entry = *_entry;
144 if (minor >= 0 && entry->minor != minor)
145 continue;
147 if (pid >= 0 && entry->pid != pid)
148 continue;
150 if (type && (!entry->type || strcmp(entry->type, type)))
151 continue;
153 if (file && (!entry->path || strcmp(entry->path, file)))
154 continue;
156 if (tty)
157 tap_ctl_list_row(entry);
158 else
159 tap_ctl_list_dict(entry);
160 }
162 tap_ctl_free_list(list);
164 return 0;
166 usage:
167 tap_cli_list_usage(stderr);
168 return EINVAL;
169 }
171 static void
172 tap_cli_allocate_usage(FILE *stream)
173 {
174 fprintf(stream, "usage: allocate [-d device name]>\n");
175 }
177 static int
178 tap_cli_allocate(int argc, char **argv)
179 {
180 char *devname;
181 int c, minor, err;
183 devname = NULL;
185 optind = 0;
186 while ((c = getopt(argc, argv, "d:h")) != -1) {
187 switch (c) {
188 case 'd':
189 devname = optarg;
190 break;
191 case '?':
192 goto usage;
193 case 'h':
194 tap_cli_allocate_usage(stdout);
195 return 0;
196 }
197 }
199 err = tap_ctl_allocate(&minor, &devname);
200 if (!err)
201 printf("%s\n", devname);
203 return err;
205 usage:
206 tap_cli_allocate_usage(stderr);
207 return EINVAL;
208 }
210 static void
211 tap_cli_free_usage(FILE *stream)
212 {
213 fprintf(stream, "usage: free <-m minor>\n");
214 }
216 static int
217 tap_cli_free(int argc, char **argv)
218 {
219 int c, minor;
221 minor = -1;
223 optind = 0;
224 while ((c = getopt(argc, argv, "m:h")) != -1) {
225 switch (c) {
226 case 'm':
227 minor = atoi(optarg);
228 break;
229 case '?':
230 goto usage;
231 case 'h':
232 tap_cli_free_usage(stdout);
233 return 0;
234 }
235 }
237 if (minor == -1)
238 goto usage;
240 return tap_ctl_free(minor);
242 usage:
243 tap_cli_free_usage(stderr);
244 return EINVAL;
245 }
247 static void
248 tap_cli_create_usage(FILE *stream)
249 {
250 fprintf(stream, "usage: create <-a args> [-d device name]\n");
251 }
253 static int
254 tap_cli_create(int argc, char **argv)
255 {
256 int c, err;
257 char *args, *devname;
259 args = NULL;
260 devname = NULL;
262 optind = 0;
263 while ((c = getopt(argc, argv, "a:d:h")) != -1) {
264 switch (c) {
265 case 'a':
266 args = optarg;
267 break;
268 case 'd':
269 devname = optarg;
270 break;
271 case '?':
272 goto usage;
273 case 'h':
274 tap_cli_create_usage(stdout);
275 return 0;
276 }
277 }
279 if (!args)
280 goto usage;
282 err = tap_ctl_create(args, &devname);
283 if (!err)
284 printf("%s\n", devname);
286 return err;
288 usage:
289 tap_cli_create_usage(stderr);
290 return EINVAL;
291 }
293 static void
294 tap_cli_destroy_usage(FILE *stream)
295 {
296 fprintf(stream, "usage: destroy <-p pid> <-m minor>\n");
297 }
299 static int
300 tap_cli_destroy(int argc, char **argv)
301 {
302 int c, pid, minor;
304 pid = -1;
305 minor = -1;
307 optind = 0;
308 while ((c = getopt(argc, argv, "p:m:h")) != -1) {
309 switch (c) {
310 case 'p':
311 pid = atoi(optarg);
312 break;
313 case 'm':
314 minor = atoi(optarg);
315 break;
316 case '?':
317 goto usage;
318 case 'h':
319 tap_cli_destroy_usage(stdout);
320 return 0;
321 }
322 }
324 if (pid == -1 || minor == -1)
325 goto usage;
327 return tap_ctl_destroy(pid, minor);
329 usage:
330 tap_cli_destroy_usage(stderr);
331 return EINVAL;
332 }
334 static void
335 tap_cli_spawn_usage(FILE *stream)
336 {
337 fprintf(stream, "usage: spawn\n");
338 }
340 static int
341 tap_cli_spawn(int argc, char **argv)
342 {
343 int c;
344 pid_t task;
346 optind = 0;
347 while ((c = getopt(argc, argv, "h")) != -1) {
348 switch (c) {
349 case '?':
350 goto usage;
351 case 'h':
352 tap_cli_spawn_usage(stdout);
353 return 0;
354 }
355 }
357 task = tap_ctl_spawn();
358 if (task < 0) {
359 printf("spawn failed: %d\n", errno);
360 return task;
361 }
363 printf("tapdisk spawned with pid %d\n", task);
364 return 0;
366 usage:
367 tap_cli_spawn_usage(stderr);
368 return EINVAL;
369 }
371 static void
372 tap_cli_attach_usage(FILE *stream)
373 {
374 fprintf(stream, "usage: attach <-p pid> <-m minor>\n");
375 }
377 static int
378 tap_cli_attach(int argc, char **argv)
379 {
380 int c, pid, minor;
382 pid = -1;
383 minor = -1;
385 optind = 0;
386 while ((c = getopt(argc, argv, "p:m:h")) != -1) {
387 switch (c) {
388 case 'p':
389 pid = atoi(optarg);
390 break;
391 case 'm':
392 minor = atoi(optarg);
393 break;
394 case '?':
395 goto usage;
396 case 'h':
397 tap_cli_attach_usage(stderr);
398 return 0;
399 }
400 }
402 if (pid == -1 || minor == -1)
403 goto usage;
405 return tap_ctl_attach(pid, minor);
407 usage:
408 tap_cli_attach_usage(stderr);
409 return EINVAL;
410 }
412 static void
413 tap_cli_detach_usage(FILE *stream)
414 {
415 fprintf(stream, "usage: detach <-p pid> <-m minor>\n");
416 }
418 static int
419 tap_cli_detach(int argc, char **argv)
420 {
421 int c, pid, minor;
423 pid = -1;
424 minor = -1;
426 optind = 0;
427 while ((c = getopt(argc, argv, "p:m:h")) != -1) {
428 switch (c) {
429 case 'p':
430 pid = atoi(optarg);
431 break;
432 case 'm':
433 minor = atoi(optarg);
434 break;
435 case '?':
436 goto usage;
437 case 'h':
438 tap_cli_detach_usage(stdout);
439 return 0;
440 }
441 }
443 if (pid == -1 || minor == -1)
444 goto usage;
446 return tap_ctl_detach(pid, minor);
448 usage:
449 tap_cli_detach_usage(stderr);
450 return EINVAL;
451 }
453 static void
454 tap_cli_close_usage(FILE *stream)
455 {
456 fprintf(stream, "usage: close <-p pid> <-m minor> [-f force]\n");
457 }
459 static int
460 tap_cli_close(int argc, char **argv)
461 {
462 int c, pid, minor, force;
464 pid = -1;
465 minor = -1;
466 force = 0;
468 optind = 0;
469 while ((c = getopt(argc, argv, "p:m:fh")) != -1) {
470 switch (c) {
471 case 'p':
472 pid = atoi(optarg);
473 break;
474 case 'm':
475 minor = atoi(optarg);
476 break;
477 case 'f':
478 force = -1;
479 break;
480 case '?':
481 goto usage;
482 case 'h':
483 tap_cli_close_usage(stdout);
484 return 0;
485 }
486 }
488 if (pid == -1 || minor == -1)
489 goto usage;
491 return tap_ctl_close(pid, minor, force);
493 usage:
494 tap_cli_close_usage(stderr);
495 return EINVAL;
496 }
498 static void
499 tap_cli_pause_usage(FILE *stream)
500 {
501 fprintf(stream, "usage: pause <-p pid> <-m minor>\n");
502 }
504 static int
505 tap_cli_pause(int argc, char **argv)
506 {
507 int c, pid, minor;
509 pid = -1;
510 minor = -1;
512 optind = 0;
513 while ((c = getopt(argc, argv, "p:m:h")) != -1) {
514 switch (c) {
515 case 'p':
516 pid = atoi(optarg);
517 break;
518 case 'm':
519 minor = atoi(optarg);
520 break;
521 case '?':
522 goto usage;
523 case 'h':
524 tap_cli_pause_usage(stdout);
525 return 0;
526 }
527 }
529 if (pid == -1 || minor == -1)
530 goto usage;
532 return tap_ctl_pause(pid, minor);
534 usage:
535 tap_cli_pause_usage(stderr);
536 return EINVAL;
537 }
539 static void
540 tap_cli_unpause_usage(FILE *stream)
541 {
542 fprintf(stream, "usage: unpause <-p pid> <-m minor> [-a args]\n");
543 }
545 int
546 tap_cli_unpause(int argc, char **argv)
547 {
548 const char *args;
549 int c, pid, minor;
551 pid = -1;
552 minor = -1;
553 args = NULL;
555 optind = 0;
556 while ((c = getopt(argc, argv, "p:m:a:h")) != -1) {
557 switch (c) {
558 case 'p':
559 pid = atoi(optarg);
560 break;
561 case 'm':
562 minor = atoi(optarg);
563 break;
564 case 'a':
565 args = optarg;
566 break;
567 case '?':
568 goto usage;
569 case 'h':
570 tap_cli_unpause_usage(stdout);
571 return 0;
572 }
573 }
575 if (pid == -1 || minor == -1)
576 goto usage;
578 return tap_ctl_unpause(pid, minor, args);
580 usage:
581 tap_cli_unpause_usage(stderr);
582 return EINVAL;
583 }
585 static void
586 tap_cli_major_usage(FILE *stream)
587 {
588 fprintf(stream, "usage: major [-h]\n");
589 }
591 static int
592 tap_cli_major(int argc, char **argv)
593 {
594 int c, chr, major;
596 chr = 0;
598 while ((c = getopt(argc, argv, "bch")) != -1) {
599 switch (c) {
600 case 'b':
601 chr = 0;
602 break;
603 case 'c':
604 chr = 1;
605 break;
606 case '?':
607 goto usage;
608 case 'h':
609 tap_cli_major_usage(stdout);
610 return 0;
611 default:
612 goto usage;
613 }
614 }
616 if (chr)
617 major = -EINVAL;
618 else
619 major = tap_ctl_blk_major();
621 if (major < 0)
622 return -major;
624 printf("%d\n", major);
626 return 0;
628 usage:
629 tap_cli_major_usage(stderr);
630 return EINVAL;
631 }
633 static void
634 tap_cli_open_usage(FILE *stream)
635 {
636 fprintf(stream, "usage: open <-p pid> <-m minor> <-a args>\n");
637 }
639 static int
640 tap_cli_open(int argc, char **argv)
641 {
642 const char *args;
643 int c, pid, minor;
645 pid = -1;
646 minor = -1;
647 args = NULL;
649 optind = 0;
650 while ((c = getopt(argc, argv, "a:m:p:h")) != -1) {
651 switch (c) {
652 case 'p':
653 pid = atoi(optarg);
654 break;
655 case 'm':
656 minor = atoi(optarg);
657 break;
658 case 'a':
659 args = optarg;
660 break;
661 case '?':
662 goto usage;
663 case 'h':
664 tap_cli_open_usage(stdout);
665 return 0;
666 }
667 }
669 if (pid == -1 || minor == -1 || !args)
670 goto usage;
672 return tap_ctl_open(pid, minor, args);
674 usage:
675 tap_cli_open_usage(stderr);
676 return EINVAL;
677 }
679 static void
680 tap_cli_check_usage(FILE *stream)
681 {
682 fprintf(stream, "usage: check\n"
683 "(checks whether environment is suitable for tapdisk2)\n");
684 }
686 static int
687 tap_cli_check(int argc, char **argv)
688 {
689 int err;
690 const char *msg;
692 if (argc != 1)
693 goto usage;
695 err = tap_ctl_check(&msg);
696 printf("%s\n", msg);
698 return err;
700 usage:
701 tap_cli_check_usage(stderr);
702 return EINVAL;
703 }
705 struct command commands[] = {
706 { .name = "list", .func = tap_cli_list },
707 { .name = "allocate", .func = tap_cli_allocate },
708 { .name = "free", .func = tap_cli_free },
709 { .name = "create", .func = tap_cli_create },
710 { .name = "destroy", .func = tap_cli_destroy },
711 { .name = "spawn", .func = tap_cli_spawn },
712 { .name = "attach", .func = tap_cli_attach },
713 { .name = "detach", .func = tap_cli_detach },
714 { .name = "open", .func = tap_cli_open },
715 { .name = "close", .func = tap_cli_close },
716 { .name = "pause", .func = tap_cli_pause },
717 { .name = "unpause", .func = tap_cli_unpause },
718 { .name = "major", .func = tap_cli_major },
719 { .name = "check", .func = tap_cli_check },
720 };
722 #define print_commands() \
723 do { \
724 int i, n; \
725 n = sizeof(commands) / sizeof(struct command); \
726 printf("COMMAND := { "); \
727 printf("%s", commands[0].name); \
728 for (i = 1; i < n; i++) \
729 printf(" | %s", commands[i].name); \
730 printf(" }\n"); \
731 } while (0)
733 void
734 help(void)
735 {
736 printf("usage: tap-ctl COMMAND [OPTIONS]\n");
737 print_commands();
738 exit(0);
739 }
741 struct command *
742 get_command(char *command)
743 {
744 int i, n;
746 if (strnlen(command, 25) >= 25)
747 return NULL;
749 n = sizeof(commands) / sizeof (struct command);
751 for (i = 0; i < n; i++)
752 if (!strcmp(command, commands[i].name))
753 return &commands[i];
755 return NULL;
756 }
758 int
759 main(int argc, char *argv[])
760 {
761 char **cargv;
762 const char *msg;
763 struct command *cmd;
764 int cargc, i, cnt, ret;
766 #ifdef CORE_DUMP
767 #include <sys/resource.h>
768 struct rlimit rlim;
769 rlim.rlim_cur = RLIM_INFINITY;
770 rlim.rlim_max = RLIM_INFINITY;
771 if (setrlimit(RLIMIT_CORE, &rlim) < 0)
772 PERROR("setrlimit failed");
773 #endif
775 ret = 0;
777 if (argc < 2)
778 help();
780 cargc = argc - 1;
781 cmd = get_command(argv[1]);
782 if (!cmd) {
783 EPRINTF("invalid COMMAND %s", argv[1]);
784 help();
785 }
787 ret = tap_ctl_check(&msg);
788 if (ret) {
789 printf("%s\n", msg);
790 return ret;
791 }
793 cargv = malloc(sizeof(char *) * cargc);
794 if (!cargv)
795 exit(ENOMEM);
797 cnt = 1;
798 cargv[0] = cmd->name;
799 for (i = 1; i < cargc; i++) {
800 char *arg = argv[i + (argc - cargc)];
802 if (!strcmp(arg, "--debug")) {
803 tap_ctl_debug = 1;
804 continue;
805 }
807 cargv[cnt++] = arg;
808 }
810 ret = cmd->func(cnt, cargv);
812 free(cargv);
814 return (ret >= 0 ? ret : -ret);
815 }