1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <xenhypfs.h>
7 
8 static struct xenhypfs_handle *hdl;
9 
usage(void)10 static int usage(void)
11 {
12     fprintf(stderr, "usage: xenhypfs ls <path>\n");
13     fprintf(stderr, "       xenhypfs cat [-b] <path>\n");
14     fprintf(stderr, "       xenhypfs write <path> <val>\n");
15     fprintf(stderr, "       xenhypfs tree\n");
16 
17     return 1;
18 }
19 
xenhypfs_print_escaped(char * string)20 static void xenhypfs_print_escaped(char *string)
21 {
22     char *c;
23 
24     for (c = string; *c; c++) {
25         if (isgraph(*c) || isspace(*c))
26             printf("%c", *c);
27         else
28             printf("\\x%02x", *c);
29     }
30     printf("\n");
31 }
32 
xenhypfs_cat(int argc,char * argv[])33 static int xenhypfs_cat(int argc, char *argv[])
34 {
35     int ret = 0;
36     char *result;
37     char *path;
38     bool bin = false;
39 
40     switch (argc) {
41     case 1:
42         path = argv[0];
43         break;
44 
45     case 2:
46         if (strcmp(argv[0], "-b"))
47             return usage();
48         bin = true;
49         path = argv[1];
50         break;
51 
52     default:
53         return usage();
54     }
55 
56     result = xenhypfs_read(hdl, path);
57     if (!result) {
58         perror("could not read");
59         ret = 3;
60     } else {
61         if (!bin)
62             printf("%s\n", result);
63         else
64             xenhypfs_print_escaped(result);
65         free(result);
66     }
67 
68     return ret;
69 }
70 
xenhypfs_wr(char * path,char * val)71 static int xenhypfs_wr(char *path, char *val)
72 {
73     int ret;
74 
75     ret = xenhypfs_write(hdl, path, val);
76     if (ret) {
77         perror("could not write");
78         ret = 3;
79     }
80 
81     return ret;
82 }
83 
xenhypfs_type(struct xenhypfs_dirent * ent)84 static char *xenhypfs_type(struct xenhypfs_dirent *ent)
85 {
86     char *res;
87 
88     switch (ent->type) {
89     case xenhypfs_type_dir:
90         res = "<dir>   ";
91         break;
92     case xenhypfs_type_blob:
93         res = "<blob>  ";
94         break;
95     case xenhypfs_type_string:
96         res = "<string>";
97         break;
98     case xenhypfs_type_uint:
99         res = "<uint>  ";
100         break;
101     case xenhypfs_type_int:
102         res = "<int>   ";
103         break;
104     case xenhypfs_type_bool:
105         res = "<bool>  ";
106         break;
107     default:
108         res = "<\?\?\?>   ";
109         break;
110     }
111 
112     return res;
113 }
114 
xenhypfs_ls(char * path)115 static int xenhypfs_ls(char *path)
116 {
117     struct xenhypfs_dirent *ent;
118     unsigned int n, i;
119     int ret = 0;
120 
121     ent = xenhypfs_readdir(hdl, path, &n);
122     if (!ent) {
123         perror("could not read dir");
124         ret = 3;
125     } else {
126         for (i = 0; i < n; i++)
127             printf("%s r%c %s\n", xenhypfs_type(ent + i),
128                    (ent[i].flags & XENHYPFS_FLAG_WRITABLE) ? 'w' : '-',
129                    ent[i].name);
130 
131         free(ent);
132     }
133 
134     return ret;
135 }
136 
xenhypfs_tree_sub(char * path,unsigned int depth)137 static int xenhypfs_tree_sub(char *path, unsigned int depth)
138 {
139     struct xenhypfs_dirent *ent;
140     unsigned int n, i;
141     int ret = 0;
142     char *p;
143 
144     ent = xenhypfs_readdir(hdl, path, &n);
145     if (!ent)
146         return 2;
147 
148     for (i = 0; i < n; i++) {
149         printf("%*s%s%s\n", depth * 2, "", ent[i].name,
150                ent[i].type == xenhypfs_type_dir ? "/" : "");
151         if (ent[i].type == xenhypfs_type_dir) {
152             if (asprintf(&p, "%s%s%s", path, (depth == 1) ? "" : "/",
153                          ent[i].name) < 0) {
154                 ret = 2;
155                 break;
156             }
157             if (xenhypfs_tree_sub(p, depth + 1))
158                 ret = 2;
159             free(p);
160         }
161     }
162 
163     free(ent);
164 
165     return ret;
166 }
167 
xenhypfs_tree(void)168 static int xenhypfs_tree(void)
169 {
170     printf("/\n");
171 
172     return xenhypfs_tree_sub("/", 1);
173 }
174 
main(int argc,char * argv[])175 int main(int argc, char *argv[])
176 {
177     int ret;
178 
179     hdl = xenhypfs_open(NULL, 0);
180 
181     if (!hdl) {
182         fprintf(stderr, "Could not open libxenhypfs\n");
183         ret = 2;
184     } else if (argc >= 3 && !strcmp(argv[1], "cat"))
185         ret = xenhypfs_cat(argc - 2, argv + 2);
186     else if (argc == 3 && !strcmp(argv[1], "ls"))
187         ret = xenhypfs_ls(argv[2]);
188     else if (argc == 4 && !strcmp(argv[1], "write"))
189         ret = xenhypfs_wr(argv[2], argv[3]);
190     else if (argc == 2 && !strcmp(argv[1], "tree"))
191         ret = xenhypfs_tree();
192     else
193         ret = usage();
194 
195     xenhypfs_close(hdl);
196 
197     return ret;
198 }
199