ia64/xen-unstable

view tools/xenstore/xenstore_client.c @ 19731:01748ccc4da3

Intel VT-d: fix Stoakley boot issue with iommu=1

Signed-off-by: Weidong Han <Weidong.han@intel.com>
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 09:25:50 2009 +0100 (2009-06-05)
parents 750eee596adf
children
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 <termios.h>
20 #include <unistd.h>
21 #include <xs.h>
23 #include <sys/ioctl.h>
25 #define PATH_SEP '/'
26 #define MAX_PATH_LEN 256
28 #define MAX_PERMS 16
30 enum mode {
31 MODE_unknown,
32 MODE_chmod,
33 MODE_exists,
34 MODE_list,
35 MODE_ls,
36 MODE_read,
37 MODE_rm,
38 MODE_write,
39 };
41 static char *output_buf = NULL;
42 static int output_pos = 0;
44 static int output_size = 0;
46 static void
47 output(const char *fmt, ...) {
48 va_list ap;
49 int len;
50 char buf[1];
52 va_start(ap, fmt);
53 len = vsnprintf(buf, 1, fmt, ap);
54 if (len < 0)
55 err(1, "output");
56 va_end(ap);
57 if (len + 1 + output_pos > output_size) {
58 output_size += len + 1024;
59 output_buf = realloc(output_buf, output_size);
60 if (output_buf == NULL)
61 err(1, "malloc");
62 }
63 va_start(ap, fmt);
64 if (vsnprintf(&output_buf[output_pos], len + 1, fmt, ap) != len)
65 err(1, "output");
66 va_end(ap);
67 output_pos += len;
68 }
70 static void
71 usage(enum mode mode, int incl_mode, const char *progname)
72 {
73 const char *mstr = NULL;
75 switch (mode) {
76 case MODE_unknown:
77 errx(1, "Usage: %s <mode> [-h] [...]", progname);
78 case MODE_read:
79 mstr = incl_mode ? "read " : "";
80 errx(1, "Usage: %s %s[-h] [-p] [-s] key [...]", progname, mstr);
81 case MODE_write:
82 mstr = incl_mode ? "write " : "";
83 errx(1, "Usage: %s %s[-h] [-s] key value [...]", progname, mstr);
84 case MODE_rm:
85 mstr = incl_mode ? "rm " : "";
86 errx(1, "Usage: %s %s[-h] [-s] [-t] key [...]", progname, mstr);
87 case MODE_exists:
88 mstr = incl_mode ? "exists " : "";
89 case MODE_list:
90 mstr = mstr ? : incl_mode ? "list " : "";
91 errx(1, "Usage: %s %s[-h] [-s] key [...]", progname, mstr);
92 case MODE_ls:
93 mstr = mstr ? : incl_mode ? "ls " : "";
94 errx(1, "Usage: %s %s[-h] [-s] [path]", progname, mstr);
95 case MODE_chmod:
96 mstr = incl_mode ? "chmod " : "";
97 errx(1, "Usage: %s %s[-h] [-s] key <mode [modes...]>", progname, mstr);
98 }
99 }
102 static int
103 do_rm(char *path, struct xs_handle *xsh, xs_transaction_t xth)
104 {
105 if (xs_rm(xsh, xth, path)) {
106 return 0;
107 }
108 else {
109 warnx("could not remove path %s", path);
110 return 1;
111 }
112 }
114 #define STRING_MAX XENSTORE_ABS_PATH_MAX+1024
115 static int max_width = 80;
116 static int desired_width = 60;
117 static int show_whole_path = 0;
119 #define TAG " = \"...\""
120 #define TAG_LEN strlen(TAG)
122 #define MIN(a, b) (((a) < (b))? (a) : (b))
124 static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms)
125 {
126 static struct expanding_buffer ebuf;
127 char **e;
128 char newpath[STRING_MAX], *val;
129 int newpath_len;
130 int i;
131 unsigned int num, len;
133 e = xs_directory(h, XBT_NULL, path, &num);
134 if (e == NULL)
135 err(1, "xs_directory (%s)", path);
137 for (i = 0; i<num; i++) {
138 char buf[MAX_STRLEN(unsigned int)+1];
139 struct xs_permissions *perms;
140 unsigned int nperms;
141 int linewid;
143 /* Compose fullpath */
144 newpath_len = snprintf(newpath, sizeof(newpath), "%s%s%s", path,
145 path[strlen(path)-1] == '/' ? "" : "/",
146 e[i]);
148 /* Print indent and path basename */
149 linewid = 0;
150 if (show_whole_path) {
151 fputs(newpath, stdout);
152 } else {
153 for (; linewid<cur_depth; linewid++) {
154 putchar(' ');
155 }
156 linewid += printf("%.*s",
157 (int) (max_width - TAG_LEN - linewid), e[i]);
158 }
160 /* Fetch value */
161 if ( newpath_len < sizeof(newpath) ) {
162 val = xs_read(h, XBT_NULL, newpath, &len);
163 }
164 else {
165 /* Path was truncated and thus invalid */
166 val = NULL;
167 len = 0;
168 }
170 /* Print value */
171 if (val == NULL) {
172 printf(":\n");
173 }
174 else {
175 if (max_width < (linewid + len + TAG_LEN)) {
176 printf(" = \"%.*s\\...\"",
177 (int)(max_width - TAG_LEN - linewid),
178 sanitise_value(&ebuf, val, len));
179 }
180 else {
181 linewid += printf(" = \"%s\"",
182 sanitise_value(&ebuf, val, len));
183 if (show_perms) {
184 putchar(' ');
185 for (linewid++;
186 linewid < MIN(desired_width, max_width);
187 linewid++)
188 putchar((linewid & 1)? '.' : ' ');
189 }
190 }
191 }
192 free(val);
194 if (show_perms) {
195 perms = xs_get_permissions(h, XBT_NULL, newpath, &nperms);
196 if (perms == NULL) {
197 warn("\ncould not access permissions for %s", e[i]);
198 }
199 else {
200 int i;
201 fputs(" (", stdout);
202 for (i = 0; i < nperms; i++) {
203 if (i)
204 putchar(',');
205 xs_perm_to_string(perms+i, buf, sizeof(buf));
206 fputs(buf, stdout);
207 }
208 putchar(')');
209 }
210 }
212 putchar('\n');
214 do_ls(h, newpath, cur_depth+1, show_perms);
215 }
216 free(e);
217 }
219 static void
220 do_chmod(char *path, struct xs_permissions *perms, int nperms, int upto,
221 int recurse, struct xs_handle *xsh, xs_transaction_t xth)
222 {
223 int ret;
225 if (!path[0])
226 return;
228 ret = xs_set_permissions(xsh, xth, path, perms, nperms);
229 if (!ret)
230 err(1, "Error occurred setting permissions on '%s'", path);
232 if (upto) {
233 /* apply same permissions to all parent entries: */
234 char *path_sep_ptr = strrchr(path, PATH_SEP);
235 if (!path_sep_ptr)
236 errx(1, "Unable to locate path separator '%c' in '%s'",
237 PATH_SEP, path);
239 *path_sep_ptr = '\0'; /* truncate path */
241 do_chmod(path, perms, nperms, 1, 0, xsh, xth);
243 *path_sep_ptr = PATH_SEP;
244 }
246 if (recurse) {
247 char buf[MAX_PATH_LEN];
249 /* apply same permissions to all child entries: */
250 unsigned int xsval_n;
251 char **xsval = xs_directory(xsh, xth, path, &xsval_n);
253 if (xsval) {
254 int i;
255 for (i = 0; i < xsval_n; i++) {
256 snprintf(buf, MAX_PATH_LEN, "%s/%s", path, xsval[i]);
258 do_chmod(buf, perms, nperms, 0, 1, xsh, xth);
259 }
261 free(xsval);
262 }
263 }
264 }
266 static int
267 perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh,
268 xs_transaction_t xth, int prefix, int tidy, int upto, int recurse)
269 {
270 switch (mode) {
271 case MODE_ls:
272 if (optind == argc)
273 {
274 optind=0;
275 argc=1;
276 argv[0] = "/";
277 }
278 break;
279 default:
280 break;
281 }
283 while (optind < argc) {
284 switch (mode) {
285 case MODE_unknown:
286 /* CANNOT BE REACHED */
287 errx(1, "invalid mode %d", mode);
288 case MODE_read: {
289 static struct expanding_buffer ebuf;
290 unsigned len;
291 char *val = xs_read(xsh, xth, argv[optind], &len);
292 if (val == NULL) {
293 warnx("couldn't read path %s", argv[optind]);
294 return 1;
295 }
296 if (prefix)
297 output("%s: ", argv[optind]);
298 output("%s\n", sanitise_value(&ebuf, val, len));
299 free(val);
300 optind++;
301 break;
302 }
303 case MODE_write: {
304 static struct expanding_buffer ebuf;
305 char *val_spec = argv[optind + 1];
306 unsigned len;
307 expanding_buffer_ensure(&ebuf, strlen(val_spec)+1);
308 unsanitise_value(ebuf.buf, &len, val_spec);
309 if (!xs_write(xsh, xth, argv[optind], ebuf.buf, len)) {
310 warnx("could not write path %s", argv[optind]);
311 return 1;
312 }
313 optind += 2;
314 } break;
315 case MODE_rm: {
316 /* Remove the specified path. If the tidy flag is set, then also
317 remove any containing directories that are both empty and have no
318 value attached, and repeat, recursing all the way up to the root if
319 necessary.
320 */
322 char *slash, *path = argv[optind];
324 if (tidy) {
325 /* Copy path, because we can't modify argv because we will need it
326 again if xs_transaction_end gives us EAGAIN. */
327 char *p = malloc(strlen(path) + 1);
328 strcpy(p, path);
329 path = p;
331 again:
332 if (do_rm(path, xsh, xth)) {
333 return 1;
334 }
336 slash = strrchr(p, '/');
337 if (slash) {
338 char *val;
339 unsigned len;
340 *slash = '\0';
341 val = xs_read(xsh, xth, p, &len);
342 if (val && len == 0) {
343 unsigned int num;
344 char ** list = xs_directory(xsh, xth, p, &num);
346 if (list && num == 0) {
347 goto again;
348 }
349 }
350 }
352 free(path);
353 }
354 else {
355 if (do_rm(path, xsh, xth)) {
356 return 1;
357 }
358 }
360 optind++;
361 break;
362 }
363 case MODE_exists: {
364 char *val = xs_read(xsh, xth, argv[optind], NULL);
365 if (val == NULL) {
366 return 1;
367 }
368 free(val);
369 optind++;
370 break;
371 }
372 case MODE_list: {
373 unsigned int i, num;
374 char **list = xs_directory(xsh, xth, argv[optind], &num);
375 if (list == NULL) {
376 warnx("could not list path %s", argv[optind]);
377 return 1;
378 }
379 for (i = 0; i < num; i++) {
380 if (prefix)
381 output("%s/", argv[optind]);
382 output("%s\n", list[i]);
383 }
384 free(list);
385 optind++;
386 break;
387 }
388 case MODE_ls: {
389 do_ls(xsh, argv[optind], 0, prefix);
390 optind++;
391 break;
392 }
393 case MODE_chmod: {
394 struct xs_permissions perms[MAX_PERMS];
395 int nperms = 0;
396 /* save path pointer: */
397 char *path = argv[optind++];
398 for (; argv[optind]; optind++, nperms++)
399 {
400 if (MAX_PERMS <= nperms)
401 errx(1, "Too many permissions specified. "
402 "Maximum per invocation is %d.", MAX_PERMS);
404 perms[nperms].id = atoi(argv[optind]+1);
406 switch (argv[optind][0])
407 {
408 case 'n':
409 perms[nperms].perms = XS_PERM_NONE;
410 break;
411 case 'r':
412 perms[nperms].perms = XS_PERM_READ;
413 break;
414 case 'w':
415 perms[nperms].perms = XS_PERM_WRITE;
416 break;
417 case 'b':
418 perms[nperms].perms = XS_PERM_READ | XS_PERM_WRITE;
419 break;
420 default:
421 errx(1, "Invalid permission specification: '%c'",
422 argv[optind][0]);
423 }
424 }
426 do_chmod(path, perms, nperms, upto, recurse, xsh, xth);
427 break;
428 }
429 }
430 }
432 return 0;
433 }
435 static enum mode lookup_mode(const char *m)
436 {
437 if (strcmp(m, "read") == 0)
438 return MODE_read;
439 else if (strcmp(m, "chmod") == 0)
440 return MODE_chmod;
441 else if (strcmp(m, "exists") == 0)
442 return MODE_exists;
443 else if (strcmp(m, "list") == 0)
444 return MODE_list;
445 else if (strcmp(m, "ls") == 0)
446 return MODE_ls;
447 else if (strcmp(m, "rm") == 0)
448 return MODE_rm;
449 else if (strcmp(m, "write") == 0)
450 return MODE_write;
451 else if (strcmp(m, "read") == 0)
452 return MODE_read;
454 errx(1, "unknown mode %s\n", m);
455 return 0;
456 }
458 int
459 main(int argc, char **argv)
460 {
461 struct xs_handle *xsh;
462 xs_transaction_t xth = XBT_NULL;
463 int ret = 0, socket = 0;
464 int prefix = 0;
465 int tidy = 0;
466 int upto = 0;
467 int recurse = 0;
468 int transaction;
469 struct winsize ws;
470 enum mode mode;
472 const char *_command = strrchr(argv[0], '/');
473 const char *command = _command ? &_command[1] : argv[0];
474 int switch_argv = -1; /* which element of argv did we switch on */
476 if (strncmp(command, "xenstore-", strlen("xenstore-")) == 0)
477 {
478 switch_argv = 0;
479 command = command + strlen("xenstore-");
480 }
481 else if (argc < 2)
482 usage(MODE_unknown, 0, argv[0]);
483 else
484 {
485 command = argv[1];
486 switch_argv = 1;
487 }
489 mode = lookup_mode(command);
491 while (1) {
492 int c, index = 0;
493 static struct option long_options[] = {
494 {"help", 0, 0, 'h'},
495 {"socket", 0, 0, 's'},
496 {"prefix", 0, 0, 'p'}, /* MODE_read || MODE_list */
497 {"tidy", 0, 0, 't'}, /* MODE_rm */
498 {"upto", 0, 0, 'u'}, /* MODE_chmod */
499 {"recurse", 0, 0, 'r'}, /* MODE_chmod */
500 {0, 0, 0, 0}
501 };
503 c = getopt_long(argc - switch_argv, argv + switch_argv, "fhsptur",
504 long_options, &index);
505 if (c == -1)
506 break;
508 switch (c) {
509 case 'h':
510 usage(mode, switch_argv, argv[0]);
511 /* NOTREACHED */
512 case 'f':
513 if ( mode == MODE_read || mode == MODE_list || mode == MODE_ls ) {
514 max_width = INT_MAX/2;
515 desired_width = 0;
516 show_whole_path = 1;
517 } else {
518 usage(mode, switch_argv, argv[0]);
519 }
520 break;
521 case 's':
522 socket = 1;
523 break;
524 case 'p':
525 if ( mode == MODE_read || mode == MODE_list || mode == MODE_ls )
526 prefix = 1;
527 else
528 usage(mode, switch_argv, argv[0]);
529 break;
530 case 't':
531 if ( mode == MODE_rm )
532 tidy = 1;
533 else
534 usage(mode, switch_argv, argv[0]);
535 break;
536 case 'u':
537 if ( mode == MODE_chmod )
538 upto = 1;
539 else
540 usage(mode, switch_argv, argv[0]);
541 break;
542 case 'r':
543 if ( mode == MODE_chmod )
544 recurse = 1;
545 else
546 usage(mode, switch_argv, argv[0]);
547 break;
548 }
549 }
551 switch (mode) {
552 case MODE_ls:
553 break;
554 case MODE_write:
555 if ((argc - switch_argv - optind) % 2 == 1) {
556 usage(mode, switch_argv, argv[0]);
557 /* NOTREACHED */
558 }
559 /* DROP-THRU */
560 default:
561 if (optind == argc - switch_argv) {
562 usage(mode, switch_argv, argv[0]);
563 /* NOTREACHED */
564 }
565 }
567 switch (mode) {
568 case MODE_read:
569 transaction = (argc - switch_argv - optind) > 1;
570 break;
571 case MODE_write:
572 transaction = (argc - switch_argv - optind) > 2;
573 break;
574 case MODE_ls:
575 transaction = 0;
576 break;
577 default:
578 transaction = 1;
579 break;
580 }
582 if ( mode == MODE_ls )
583 {
584 memset(&ws, 0, sizeof(ws));
585 ret = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
586 if (!ret)
587 max_width = ws.ws_col - 2;
588 }
590 xsh = socket ? xs_daemon_open() : xs_domain_open();
591 if (xsh == NULL)
592 err(1, socket ? "xs_daemon_open" : "xs_domain_open");
594 again:
595 if (transaction) {
596 xth = xs_transaction_start(xsh);
597 if (xth == XBT_NULL)
598 errx(1, "couldn't start transaction");
599 }
601 ret = perform(mode, optind, argc - switch_argv, argv + switch_argv, xsh, xth, prefix, tidy, upto, recurse);
603 if (transaction && !xs_transaction_end(xsh, xth, ret)) {
604 if (ret == 0 && errno == EAGAIN) {
605 output_pos = 0;
606 goto again;
607 }
608 errx(1, "couldn't end transaction");
609 }
611 if (output_pos)
612 printf("%s", output_buf);
614 return ret;
615 }