ia64/xen-unstable

view tools/xenstore/xenstore_client.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents e629bb62c63e
children 8f452e26224a
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 #endif
64 }
67 #if defined(CLIENT_rm)
68 static int
69 do_rm(char *path, struct xs_handle *xsh, xs_transaction_t xth)
70 {
71 if (xs_rm(xsh, xth, path)) {
72 return 0;
73 }
74 else {
75 warnx("could not remove path %s", path);
76 return 1;
77 }
78 }
79 #endif
82 static int
83 perform(int optind, int argc, char **argv, struct xs_handle *xsh,
84 xs_transaction_t xth, int prefix, int tidy)
85 {
86 while (optind < argc) {
87 #if defined(CLIENT_read)
88 char *val = xs_read(xsh, xth, argv[optind], NULL);
89 if (val == NULL) {
90 warnx("couldn't read path %s", argv[optind]);
91 return 1;
92 }
93 if (prefix)
94 output("%s: ", argv[optind]);
95 output("%s\n", val);
96 free(val);
97 optind++;
98 #elif defined(CLIENT_write)
99 if (!xs_write(xsh, xth, argv[optind], argv[optind + 1],
100 strlen(argv[optind + 1]))) {
101 warnx("could not write path %s", argv[optind]);
102 return 1;
103 }
104 optind += 2;
105 #elif defined(CLIENT_rm)
106 /* Remove the specified path. If the tidy flag is set, then also
107 remove any containing directories that are both empty and have no
108 value attached, and repeat, recursing all the way up to the root if
109 necessary.
110 */
112 char *slash, *path = argv[optind];
114 if (tidy) {
115 /* Copy path, because we can't modify argv because we will need it
116 again if xs_transaction_end gives us EAGAIN. */
117 char *p = malloc(strlen(path) + 1);
118 strcpy(p, path);
119 path = p;
121 again:
122 if (do_rm(path, xsh, xth)) {
123 return 1;
124 }
126 slash = strrchr(p, '/');
127 if (slash) {
128 char *val;
129 *slash = '\0';
130 val = xs_read(xsh, xth, p, NULL);
131 if (val && strlen(val) == 0) {
132 unsigned int num;
133 char ** list = xs_directory(xsh, xth, p, &num);
135 if (list && num == 0) {
136 goto again;
137 }
138 }
139 }
141 free(path);
142 }
143 else {
144 if (do_rm(path, xsh, xth)) {
145 return 1;
146 }
147 }
149 optind++;
150 #elif defined(CLIENT_exists)
151 char *val = xs_read(xsh, xth, argv[optind], NULL);
152 if (val == NULL) {
153 return 1;
154 }
155 free(val);
156 optind++;
157 #elif defined(CLIENT_list)
158 unsigned int i, num;
159 char **list = xs_directory(xsh, xth, argv[optind], &num);
160 if (list == NULL) {
161 warnx("could not list path %s", argv[optind]);
162 return 1;
163 }
164 for (i = 0; i < num; i++) {
165 if (prefix)
166 output("%s/", argv[optind]);
167 output("%s\n", list[i]);
168 }
169 free(list);
170 optind++;
171 #endif
172 }
174 return 0;
175 }
178 int
179 main(int argc, char **argv)
180 {
181 struct xs_handle *xsh;
182 xs_transaction_t xth;
183 int ret = 0, socket = 0;
184 int prefix = 0;
185 int tidy = 0;
187 while (1) {
188 int c, index = 0;
189 static struct option long_options[] = {
190 {"help", 0, 0, 'h'},
191 {"socket", 0, 0, 's'},
192 #if defined(CLIENT_read) || defined(CLIENT_list)
193 {"prefix", 0, 0, 'p'},
194 #elif defined(CLIENT_rm)
195 {"tidy", 0, 0, 't'},
196 #endif
197 {0, 0, 0, 0}
198 };
200 c = getopt_long(argc, argv, "hs"
201 #if defined(CLIENT_read) || defined(CLIENT_list)
202 "p"
203 #elif defined(CLIENT_rm)
204 "t"
205 #endif
206 , long_options, &index);
207 if (c == -1)
208 break;
210 switch (c) {
211 case 'h':
212 usage(argv[0]);
213 /* NOTREACHED */
214 case 's':
215 socket = 1;
216 break;
217 #if defined(CLIENT_read) || defined(CLIENT_list)
218 case 'p':
219 prefix = 1;
220 break;
221 #elif defined(CLIENT_rm)
222 case 't':
223 tidy = 1;
224 break;
225 #endif
226 }
227 }
229 if (optind == argc) {
230 usage(argv[0]);
231 /* NOTREACHED */
232 }
233 #if defined(CLIENT_write)
234 if ((argc - optind) % 2 == 1) {
235 usage(argv[0]);
236 /* NOTREACHED */
237 }
238 #endif
240 xsh = socket ? xs_daemon_open() : xs_domain_open();
241 if (xsh == NULL)
242 err(1, socket ? "xs_daemon_open" : "xs_domain_open");
244 again:
245 xth = xs_transaction_start(xsh);
246 if (xth == XBT_NULL)
247 errx(1, "couldn't start transaction");
249 ret = perform(optind, argc, argv, xsh, xth, prefix, tidy);
251 if (!xs_transaction_end(xsh, xth, ret)) {
252 if (ret == 0 && errno == EAGAIN) {
253 output_pos = 0;
254 goto again;
255 }
256 errx(1, "couldn't end transaction");
257 }
259 if (output_pos)
260 printf("%s", output_buf);
262 return ret;
263 }