ia64/xen-unstable

view tools/xenstore/xenstore_client.c @ 10911:8f452e26224a

[TOOLS] Modify xenstore_client.c to include a new utility, xenstore-chmod.
This utility permits developers and administrators to
manually change the permissions on arbitrary locations in XenStore
from the command line. This is often helpful if you're trying to debug an
application that relies on XenStore and is encountering difficulties
with permissions.

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
author kfraser@localhost.localdomain
date Wed Aug 02 14:58:37 2006 +0100 (2006-08-02)
parents e629bb62c63e
children 5297ced4d610
line source
1 /*
2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of
4 * this archive for more details.
5 *
6 * Copyright (C) 2005 by Christian Limpach
7 * Copyright (C) 2005 XenSource Ltd.
8 *
9 */
11 #include <err.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <getopt.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <xs.h>
21 static char *output_buf = NULL;
22 static int output_pos = 0;
24 #if defined(CLIENT_read) || defined(CLIENT_list)
25 static int output_size = 0;
27 static void
28 output(const char *fmt, ...) {
29 va_list ap;
30 int len;
31 char buf[1];
33 va_start(ap, fmt);
34 len = vsnprintf(buf, 1, fmt, ap);
35 if (len < 0)
36 err(1, "output");
37 va_end(ap);
38 if (len + 1 + output_pos > output_size) {
39 output_size += len + 1024;
40 output_buf = realloc(output_buf, output_size);
41 if (output_buf == NULL)
42 err(1, "malloc");
43 }
44 va_start(ap, fmt);
45 if (vsnprintf(&output_buf[output_pos], len + 1, fmt, ap) != len)
46 err(1, "output");
47 va_end(ap);
48 output_pos += len;
49 }
50 #endif
52 static void
53 usage(const char *progname)
54 {
55 #if defined(CLIENT_read)
56 errx(1, "Usage: %s [-h] [-p] [-s] key [...]", progname);
57 #elif defined(CLIENT_write)
58 errx(1, "Usage: %s [-h] [-s] key value [...]", progname);
59 #elif defined(CLIENT_rm)
60 errx(1, "Usage: %s [-h] [-s] [-t] key [...]", progname);
61 #elif defined(CLIENT_exists) || defined(CLIENT_list)
62 errx(1, "Usage: %s [-h] [-s] key [...]", progname);
63 #elif defined(CLIENT_chmod)
64 errx(1, "Usage: %s [-h] [-s] key <mode [modes...]>", progname);
65 #endif
66 }
69 #if defined(CLIENT_rm)
70 static int
71 do_rm(char *path, struct xs_handle *xsh, xs_transaction_t xth)
72 {
73 if (xs_rm(xsh, xth, path)) {
74 return 0;
75 }
76 else {
77 warnx("could not remove path %s", path);
78 return 1;
79 }
80 }
81 #endif
83 #if defined(CLIENT_chmod)
84 #define PATH_SEP '/'
85 #define MAX_PATH_LEN 256
87 static void
88 do_chmod(char *path, struct xs_permissions *perms, int nperms, int upto,
89 int recurse, struct xs_handle *xsh, xs_transaction_t xth)
90 {
91 int ret;
93 if (!path[0])
94 return;
96 ret = xs_set_permissions(xsh, xth, path, perms, nperms);
97 if (!ret)
98 err(1, "Error occurred setting permissions on '%s'", path);
100 if (upto) {
101 /* apply same permissions to all parent entries: */
102 char *path_sep_ptr = strrchr(path, PATH_SEP);
103 if (!path_sep_ptr)
104 errx(1, "Unable to locate path separator '%c' in '%s'",
105 PATH_SEP, path);
107 *path_sep_ptr = '\0'; /* truncate path */
109 do_chmod(path, perms, nperms, 1, 0, xsh, xth);
111 *path_sep_ptr = PATH_SEP;
112 }
114 if (recurse) {
115 char buf[MAX_PATH_LEN];
117 /* apply same permissions to all child entries: */
118 unsigned int xsval_n;
119 char **xsval = xs_directory(xsh, xth, path, &xsval_n);
121 if (xsval) {
122 int i;
123 for (i = 0; i < xsval_n; i++) {
124 snprintf(buf, MAX_PATH_LEN, "%s/%s", path, xsval[i]);
126 do_chmod(buf, perms, nperms, 0, 1, xsh, xth);
127 }
129 free(xsval);
130 }
131 }
132 }
133 #endif
135 static int
136 perform(int optind, int argc, char **argv, struct xs_handle *xsh,
137 xs_transaction_t xth, int prefix, int tidy, int upto, int recurse)
138 {
139 while (optind < argc) {
140 #if defined(CLIENT_read)
141 char *val = xs_read(xsh, xth, argv[optind], NULL);
142 if (val == NULL) {
143 warnx("couldn't read path %s", argv[optind]);
144 return 1;
145 }
146 if (prefix)
147 output("%s: ", argv[optind]);
148 output("%s\n", val);
149 free(val);
150 optind++;
151 #elif defined(CLIENT_write)
152 if (!xs_write(xsh, xth, argv[optind], argv[optind + 1],
153 strlen(argv[optind + 1]))) {
154 warnx("could not write path %s", argv[optind]);
155 return 1;
156 }
157 optind += 2;
158 #elif defined(CLIENT_rm)
159 /* Remove the specified path. If the tidy flag is set, then also
160 remove any containing directories that are both empty and have no
161 value attached, and repeat, recursing all the way up to the root if
162 necessary.
163 */
165 char *slash, *path = argv[optind];
167 if (tidy) {
168 /* Copy path, because we can't modify argv because we will need it
169 again if xs_transaction_end gives us EAGAIN. */
170 char *p = malloc(strlen(path) + 1);
171 strcpy(p, path);
172 path = p;
174 again:
175 if (do_rm(path, xsh, xth)) {
176 return 1;
177 }
179 slash = strrchr(p, '/');
180 if (slash) {
181 char *val;
182 *slash = '\0';
183 val = xs_read(xsh, xth, p, NULL);
184 if (val && strlen(val) == 0) {
185 unsigned int num;
186 char ** list = xs_directory(xsh, xth, p, &num);
188 if (list && num == 0) {
189 goto again;
190 }
191 }
192 }
194 free(path);
195 }
196 else {
197 if (do_rm(path, xsh, xth)) {
198 return 1;
199 }
200 }
202 optind++;
203 #elif defined(CLIENT_exists)
204 char *val = xs_read(xsh, xth, argv[optind], NULL);
205 if (val == NULL) {
206 return 1;
207 }
208 free(val);
209 optind++;
210 #elif defined(CLIENT_list)
211 unsigned int i, num;
212 char **list = xs_directory(xsh, xth, argv[optind], &num);
213 if (list == NULL) {
214 warnx("could not list path %s", argv[optind]);
215 return 1;
216 }
217 for (i = 0; i < num; i++) {
218 if (prefix)
219 output("%s/", argv[optind]);
220 output("%s\n", list[i]);
221 }
222 free(list);
223 optind++;
224 #elif defined(CLIENT_chmod)
225 #define MAX_PERMS 16
226 struct xs_permissions perms[MAX_PERMS];
227 int nperms = 0;
228 /* save path pointer: */
229 char *path = argv[optind++];
230 for (; argv[optind]; optind++, nperms++)
231 {
232 if (MAX_PERMS <= nperms)
233 errx(1, "Too many permissions specified. "
234 "Maximum per invocation is %d.", MAX_PERMS);
236 perms[nperms].id = atoi(argv[optind]+1);
238 switch (argv[optind][0])
239 {
240 case 'n':
241 perms[nperms].perms = XS_PERM_NONE;
242 break;
243 case 'r':
244 perms[nperms].perms = XS_PERM_READ;
245 break;
246 case 'w':
247 perms[nperms].perms = XS_PERM_WRITE;
248 break;
249 case 'b':
250 perms[nperms].perms = XS_PERM_READ | XS_PERM_WRITE;
251 break;
252 default:
253 errx(1, "Invalid permission specification: '%c'",
254 argv[optind][0]);
255 }
256 }
258 do_chmod(path, perms, nperms, upto, recurse, xsh, xth);
259 #endif
260 }
262 return 0;
263 }
266 int
267 main(int argc, char **argv)
268 {
269 struct xs_handle *xsh;
270 xs_transaction_t xth;
271 int ret = 0, socket = 0;
272 int prefix = 0;
273 int tidy = 0;
274 int upto = 0;
275 int recurse = 0;
277 while (1) {
278 int c, index = 0;
279 static struct option long_options[] = {
280 {"help", 0, 0, 'h'},
281 {"socket", 0, 0, 's'},
282 #if defined(CLIENT_read) || defined(CLIENT_list)
283 {"prefix", 0, 0, 'p'},
284 #elif defined(CLIENT_rm)
285 {"tidy", 0, 0, 't'},
286 #elif defined(CLIENT_chmod)
287 {"upto", 0, 0, 'u'},
288 {"recurse", 0, 0, 'r'},
289 #endif
290 {0, 0, 0, 0}
291 };
293 c = getopt_long(argc, argv, "hs"
294 #if defined(CLIENT_read) || defined(CLIENT_list)
295 "p"
296 #elif defined(CLIENT_rm)
297 "t"
298 #elif defined(CLIENT_chmod)
299 "ur"
300 #endif
301 , long_options, &index);
302 if (c == -1)
303 break;
305 switch (c) {
306 case 'h':
307 usage(argv[0]);
308 /* NOTREACHED */
309 case 's':
310 socket = 1;
311 break;
312 #if defined(CLIENT_read) || defined(CLIENT_list)
313 case 'p':
314 prefix = 1;
315 break;
316 #elif defined(CLIENT_rm)
317 case 't':
318 tidy = 1;
319 break;
320 #elif defined(CLIENT_chmod)
321 case 'u':
322 upto = 1;
323 break;
324 case 'r':
325 recurse = 1;
326 break;
327 #endif
328 }
329 }
331 if (optind == argc) {
332 usage(argv[0]);
333 /* NOTREACHED */
334 }
335 #if defined(CLIENT_write)
336 if ((argc - optind) % 2 == 1) {
337 usage(argv[0]);
338 /* NOTREACHED */
339 }
340 #endif
342 xsh = socket ? xs_daemon_open() : xs_domain_open();
343 if (xsh == NULL)
344 err(1, socket ? "xs_daemon_open" : "xs_domain_open");
346 again:
347 xth = xs_transaction_start(xsh);
348 if (xth == XBT_NULL)
349 errx(1, "couldn't start transaction");
351 ret = perform(optind, argc, argv, xsh, xth, prefix, tidy, upto, recurse);
353 if (!xs_transaction_end(xsh, xth, ret)) {
354 if (ret == 0 && errno == EAGAIN) {
355 output_pos = 0;
356 goto again;
357 }
358 errx(1, "couldn't end transaction");
359 }
361 if (output_pos)
362 printf("%s", output_buf);
364 return ret;
365 }