/* * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of * this archive for more details. * * Copyright (C) 2005 by Christian Limpach * Copyright (C) 2005 XenSource Ltd. * */ #include #include #include #include #include #include #include #include #include #include #include #include #define PATH_SEP '/' #define MAX_PATH_LEN 256 enum mode { MODE_unknown, MODE_chmod, MODE_exists, MODE_list, MODE_ls, MODE_read, MODE_rm, MODE_write, MODE_watch, }; static char *output_buf = NULL; static int output_pos = 0; static int output_size = 0; static void output(const char *fmt, ...) { va_list ap; int len; char buf[1]; va_start(ap, fmt); len = vsnprintf(buf, 1, fmt, ap); if (len < 0) err(1, "output"); va_end(ap); if (len + 1 + output_pos > output_size) { output_size += len + 1024; output_buf = realloc(output_buf, output_size); if (output_buf == NULL) err(1, "malloc"); } va_start(ap, fmt); if (vsnprintf(&output_buf[output_pos], len + 1, fmt, ap) != len) err(1, "output"); va_end(ap); output_pos += len; } static void usage(enum mode mode, int incl_mode, const char *progname) { const char *mstr = NULL; switch (mode) { case MODE_unknown: errx(1, "Usage: %s [-h] [...]", progname); case MODE_read: mstr = incl_mode ? "read " : ""; errx(1, "Usage: %s %s[-h] [-p] [-s] key [...]", progname, mstr); case MODE_write: mstr = incl_mode ? "write " : ""; errx(1, "Usage: %s %s[-h] [-s] key value [...]", progname, mstr); case MODE_rm: mstr = incl_mode ? "rm " : ""; errx(1, "Usage: %s %s[-h] [-s] [-t] key [...]", progname, mstr); case MODE_exists: mstr = incl_mode ? "exists " : ""; case MODE_list: mstr = mstr ? : incl_mode ? "list " : ""; errx(1, "Usage: %s %s[-h] [-p] [-s] key [...]", progname, mstr); case MODE_ls: mstr = mstr ? : incl_mode ? "ls " : ""; errx(1, "Usage: %s %s[-h] [-f] [-p] [-s] [path]", progname, mstr); case MODE_chmod: mstr = incl_mode ? "chmod " : ""; errx(1, "Usage: %s %s[-h] [-u] [-r] [-s] key ", progname, mstr); case MODE_watch: mstr = incl_mode ? "watch " : ""; errx(1, "Usage: %s %s[-h] [-n NR] key", progname, mstr); } } static int do_rm(char *path, struct xs_handle *xsh, xs_transaction_t xth) { if (xs_rm(xsh, xth, path)) { return 0; } else { warnx("could not remove path %s", path); return 1; } } #define STRING_MAX XENSTORE_ABS_PATH_MAX+1024 static int max_width = 80; static int desired_width = 60; static int show_whole_path = 0; #define TAG " = \"...\"" #define TAG_LEN strlen(TAG) #define MIN(a, b) (((a) < (b))? (a) : (b)) static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms) { static struct expanding_buffer ebuf; char **e; char newpath[STRING_MAX], *val; int newpath_len; int i; unsigned int num, len; e = xs_directory(h, XBT_NULL, path, &num); if (e == NULL) err(1, "xs_directory (%s)", path); for (i = 0; i 1; break; case MODE_write: transaction = (argc - switch_argv - optind) > 2; break; case MODE_ls: case MODE_watch: transaction = 0; break; default: transaction = 1; break; } if ( mode == MODE_ls ) { memset(&ws, 0, sizeof(ws)); ret = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); if (!ret) max_width = ws.ws_col - 2; } xsh = xs_open(socket ? XS_OPEN_SOCKETONLY : 0); if (xsh == NULL) err(1, "xs_open"); again: if (transaction) { xth = xs_transaction_start(xsh); if (xth == XBT_NULL) errx(1, "couldn't start transaction"); } ret = perform(mode, optind, argc - switch_argv, argv + switch_argv, xsh, xth, prefix, tidy, upto, recurse, nr_watches); if (transaction && !xs_transaction_end(xsh, xth, ret)) { if (ret == 0 && errno == EAGAIN) { output_pos = 0; goto again; } errx(1, "couldn't end transaction"); } if (output_pos) printf("%s", output_buf); return ret; }