1 /*
2  * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <err.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <xenctrl.h>
12 
13 #include <xen/errno.h>
14 #include <xen-tools/libs.h>
15 
16 static xc_interface *xch;
17 
show_help(void)18 void show_help(void)
19 {
20     fprintf(stderr,
21             "xen-diag: xen diagnostic utility\n"
22             "Usage: xen-diag command [args]\n"
23             "Commands:\n"
24             "  help                       display this help\n"
25             "  gnttab_query_size <domid>  dump the current and max grant frames for <domid>\n");
26 }
27 
28 /* wrapper function */
help_func(int argc,char * argv[])29 static int help_func(int argc, char *argv[])
30 {
31     show_help();
32     return 0;
33 }
34 
gnttab_query_size_func(int argc,char * argv[])35 static int gnttab_query_size_func(int argc, char *argv[])
36 {
37     int domid, rc = 1;
38     struct gnttab_query_size query;
39 
40     if ( argc != 1 )
41     {
42         show_help();
43         return rc;
44     }
45 
46     domid = strtol(argv[0], NULL, 10);
47     query.dom = domid;
48     rc = xc_gnttab_query_size(xch, &query);
49 
50     if ( rc == 0 && (query.status == GNTST_okay) )
51         printf("domid=%d: nr_frames=%d, max_nr_frames=%d\n",
52                query.dom, query.nr_frames, query.max_nr_frames);
53 
54     return rc == 0 && (query.status == GNTST_okay) ? 0 : 1;
55 }
56 
57 struct {
58     const char *name;
59     int (*function)(int argc, char *argv[]);
60 } main_options[] = {
61     { "help", help_func },
62     { "gnttab_query_size", gnttab_query_size_func},
63 };
64 
main(int argc,char * argv[])65 int main(int argc, char *argv[])
66 {
67     int ret, i;
68 
69     /*
70      * Set stdout to be unbuffered to avoid having to fflush when
71      * printing without a newline.
72      */
73     setvbuf(stdout, NULL, _IONBF, 0);
74 
75     if ( argc <= 1 )
76     {
77         show_help();
78         return 0;
79     }
80 
81     for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
82         if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
83             break;
84 
85     if ( i == ARRAY_SIZE(main_options) )
86     {
87         show_help();
88         return 0;
89     }
90     else
91     {
92         xch = xc_interface_open(0, 0, 0);
93         if ( !xch )
94         {
95             fprintf(stderr, "failed to get the handler\n");
96             return 0;
97         }
98 
99         ret = main_options[i].function(argc - 2, argv + 2);
100 
101         xc_interface_close(xch);
102     }
103 
104     /*
105      * Exitcode 0 for success.
106      * Exitcode 1 for an error.
107      * Exitcode 2 if the operation should be retried for any reason (e.g. a
108      * timeout or because another operation was in progress).
109      */
110 
111 #define EXIT_TIMEOUT (EXIT_FAILURE + 1)
112 
113     BUILD_BUG_ON(EXIT_SUCCESS != 0);
114     BUILD_BUG_ON(EXIT_FAILURE != 1);
115     BUILD_BUG_ON(EXIT_TIMEOUT != 2);
116 
117     switch ( ret )
118     {
119     case 0:
120         return EXIT_SUCCESS;
121     case EAGAIN:
122     case EBUSY:
123         return EXIT_TIMEOUT;
124     default:
125         return EXIT_FAILURE;
126     }
127 }
128