1 /*
2 * Copyright (C) 2009 Citrix Ltd.
3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; version 2.1 only. with the special
8 * exception on linking described in file LICENSE.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 */
15
16 #include "libxl_osdeps.h" /* must come before any other headers */
17
18 #include "libxl_internal.h"
19
libxl__xs_kvs_of_flexarray(libxl__gc * gc,flexarray_t * array)20 char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array)
21 {
22 char **kvs;
23 int i, length;
24
25 if (!array)
26 return NULL;
27
28 length = array->count;
29 if (!length)
30 return NULL;
31
32 kvs = libxl__calloc(gc, length + 2, sizeof(char *));
33 if (kvs) {
34 for (i = 0; i < length; i += 2) {
35 void *ptr;
36
37 flexarray_get(array, i, &ptr);
38 kvs[i] = (char *) ptr;
39 flexarray_get(array, i + 1, &ptr);
40 kvs[i + 1] = (char *) ptr;
41 }
42 kvs[i] = NULL;
43 kvs[i + 1] = NULL;
44 }
45 return kvs;
46 }
47
libxl__xs_writev_perms(libxl__gc * gc,xs_transaction_t t,const char * dir,char * kvs[],struct xs_permissions * perms,unsigned int num_perms)48 int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
49 const char *dir, char *kvs[],
50 struct xs_permissions *perms,
51 unsigned int num_perms)
52 {
53 libxl_ctx *ctx = libxl__gc_owner(gc);
54 char *path;
55 int i;
56
57 if (!kvs)
58 return 0;
59
60 for (i = 0; kvs[i] != NULL; i += 2) {
61 path = GCSPRINTF("%s/%s", dir, kvs[i]);
62 if (path && kvs[i + 1]) {
63 size_t length = strlen(kvs[i + 1]);
64 if (length > UINT_MAX)
65 return ERROR_FAIL;
66 if (!xs_write(ctx->xsh, t, path, kvs[i + 1], length))
67 return ERROR_FAIL;
68 if (perms) {
69 if (!xs_set_permissions(ctx->xsh, t, path, perms, num_perms))
70 return ERROR_FAIL;
71 }
72 }
73 }
74 return 0;
75 }
76
libxl__xs_writev(libxl__gc * gc,xs_transaction_t t,const char * dir,char * kvs[])77 int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
78 const char *dir, char *kvs[])
79 {
80 return libxl__xs_writev_perms(gc, t, dir, kvs, NULL, 0);
81 }
82
libxl__xs_writev_atonce(libxl__gc * gc,const char * dir,char * kvs[])83 int libxl__xs_writev_atonce(libxl__gc *gc,
84 const char *dir, char *kvs[])
85 {
86 int rc;
87 xs_transaction_t t = XBT_NULL;
88
89 for (;;) {
90 rc = libxl__xs_transaction_start(gc, &t);
91 if (rc) goto out;
92
93 rc = libxl__xs_writev(gc, t, dir, kvs);
94 if (rc) goto out;
95
96 rc = libxl__xs_transaction_commit(gc, &t);
97 if (!rc) break;
98 if (rc<0) goto out;
99 }
100
101 out:
102 libxl__xs_transaction_abort(gc, &t);
103
104 return rc;
105
106 }
107
libxl__xs_vprintf(libxl__gc * gc,xs_transaction_t t,const char * path,const char * fmt,va_list ap)108 int libxl__xs_vprintf(libxl__gc *gc, xs_transaction_t t,
109 const char *path, const char *fmt, va_list ap)
110 {
111 libxl_ctx *ctx = libxl__gc_owner(gc);
112 char *s;
113 bool ok;
114
115 s = libxl__vsprintf(gc, fmt, ap);
116
117 ok = xs_write(ctx->xsh, t, path, s, strlen(s));
118 if (!ok) {
119 LOGE(ERROR, "xenstore write failed: `%s' = `%s'", path, s);
120 return ERROR_FAIL;
121 }
122
123 return 0;
124 }
125
libxl__xs_printf(libxl__gc * gc,xs_transaction_t t,const char * path,const char * fmt,...)126 int libxl__xs_printf(libxl__gc *gc, xs_transaction_t t,
127 const char *path, const char *fmt, ...)
128 {
129 va_list ap;
130 int rc;
131
132 va_start(ap, fmt);
133 rc = libxl__xs_vprintf(gc, t, path, fmt, ap);
134 va_end(ap);
135
136 return rc;
137 }
138
libxl__xs_read(libxl__gc * gc,xs_transaction_t t,const char * path)139 char * libxl__xs_read(libxl__gc *gc, xs_transaction_t t, const char *path)
140 {
141 libxl_ctx *ctx = libxl__gc_owner(gc);
142 char *ptr;
143
144 ptr = xs_read(ctx->xsh, t, path, NULL);
145 libxl__ptr_add(gc, ptr);
146 return ptr;
147 }
148
libxl__xs_get_dompath(libxl__gc * gc,uint32_t domid)149 char *libxl__xs_get_dompath(libxl__gc *gc, uint32_t domid)
150 {
151 libxl_ctx *ctx = libxl__gc_owner(gc);
152 char *s = xs_get_domain_path(ctx->xsh, domid);
153 if (!s) {
154 LOGED(ERROR, domid, "Failed to get dompath");
155 return NULL;
156 }
157 libxl__ptr_add(gc, s);
158 return s;
159 }
160
libxl__xs_directory(libxl__gc * gc,xs_transaction_t t,const char * path,unsigned int * nb)161 char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t,
162 const char *path, unsigned int *nb)
163 {
164 libxl_ctx *ctx = libxl__gc_owner(gc);
165 char **ret = NULL;
166 ret = xs_directory(ctx->xsh, t, path, nb);
167 libxl__ptr_add(gc, ret);
168 return ret;
169 }
170
libxl__xs_mknod(libxl__gc * gc,xs_transaction_t t,const char * path,struct xs_permissions * perms,unsigned int num_perms)171 int libxl__xs_mknod(libxl__gc *gc, xs_transaction_t t,
172 const char *path, struct xs_permissions *perms,
173 unsigned int num_perms)
174 {
175 libxl_ctx *ctx = libxl__gc_owner(gc);
176 bool ok;
177
178 ok = xs_write(ctx->xsh, t, path, "", 0);
179 if (!ok) {
180 LOGE(ERROR, "xenstore write failed: `%s' = ''", path);
181 return ERROR_FAIL;
182 }
183
184 ok = xs_set_permissions(ctx->xsh, t, path, perms, num_perms);
185 if (!ok) {
186 LOGE(ERROR, "xenstore set permissions failed on `%s'", path);
187 return ERROR_FAIL;
188 }
189
190 return 0;
191 }
192
libxl__xs_libxl_path(libxl__gc * gc,uint32_t domid)193 char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid)
194 {
195 char *s = GCSPRINTF("/libxl/%i", domid);
196 if (!s)
197 LOGD(ERROR, domid, "cannot allocate create paths");
198 return s;
199 }
200
libxl__xs_read_mandatory(libxl__gc * gc,xs_transaction_t t,const char * path,const char ** result_out)201 int libxl__xs_read_mandatory(libxl__gc *gc, xs_transaction_t t,
202 const char *path, const char **result_out)
203 {
204 char *result = libxl__xs_read(gc, t, path);
205 if (!result) {
206 LOGE(ERROR, "xenstore read failed: `%s'", path);
207 return ERROR_FAIL;
208 }
209 *result_out = result;
210 return 0;
211 }
212
libxl__xs_read_checked(libxl__gc * gc,xs_transaction_t t,const char * path,const char ** result_out)213 int libxl__xs_read_checked(libxl__gc *gc, xs_transaction_t t,
214 const char *path, const char **result_out)
215 {
216 char *result = libxl__xs_read(gc, t, path);
217 if (!result && errno != ENOENT) {
218 LOGE(ERROR, "xenstore read failed: `%s'", path);
219 return ERROR_FAIL;
220 }
221 *result_out = result;
222 return 0;
223 }
224
libxl__xs_write_checked(libxl__gc * gc,xs_transaction_t t,const char * path,const char * string)225 int libxl__xs_write_checked(libxl__gc *gc, xs_transaction_t t,
226 const char *path, const char *string)
227 {
228 size_t length = strlen(string);
229 if (!xs_write(CTX->xsh, t, path, string, length)) {
230 LOGE(ERROR, "xenstore write failed: `%s' = `%s'", path, string);
231 return ERROR_FAIL;
232 }
233 return 0;
234 }
235
libxl__xs_rm_checked(libxl__gc * gc,xs_transaction_t t,const char * path)236 int libxl__xs_rm_checked(libxl__gc *gc, xs_transaction_t t, const char *path)
237 {
238 if (!xs_rm(CTX->xsh, t, path)) {
239 if (errno == ENOENT)
240 return 0;
241
242 LOGE(ERROR, "xenstore rm failed: `%s'", path);
243 return ERROR_FAIL;
244 }
245 return 0;
246 }
247
libxl__xs_transaction_start(libxl__gc * gc,xs_transaction_t * t)248 int libxl__xs_transaction_start(libxl__gc *gc, xs_transaction_t *t)
249 {
250 assert(!*t);
251 *t = xs_transaction_start(CTX->xsh);
252 if (!*t) {
253 LOGE(ERROR, "could not create xenstore transaction");
254 return ERROR_FAIL;
255 }
256 return 0;
257 }
258
libxl__xs_transaction_commit(libxl__gc * gc,xs_transaction_t * t)259 int libxl__xs_transaction_commit(libxl__gc *gc, xs_transaction_t *t)
260 {
261 assert(*t);
262
263 if (!xs_transaction_end(CTX->xsh, *t, 0)) {
264 *t = 0;
265 if (errno == EAGAIN)
266 return +1;
267
268 LOGE(ERROR, "could not commit xenstore transaction");
269 return ERROR_FAIL;
270 }
271
272 *t = 0;
273 return 0;
274 }
275
libxl__xs_transaction_abort(libxl__gc * gc,xs_transaction_t * t)276 void libxl__xs_transaction_abort(libxl__gc *gc, xs_transaction_t *t)
277 {
278 if (!*t)
279 return;
280
281 if (!xs_transaction_end(CTX->xsh, *t, 1))
282 LOGE(ERROR, "could not abort xenstore transaction");
283
284 *t = 0;
285 }
286
libxl__xs_path_cleanup(libxl__gc * gc,xs_transaction_t t,const char * user_path)287 int libxl__xs_path_cleanup(libxl__gc *gc, xs_transaction_t t,
288 const char *user_path)
289 {
290 unsigned int nb = 0;
291 char *path, *last, *val;
292 int rc;
293
294 /* A path and transaction must be provided by the caller */
295 assert(user_path && t);
296
297 path = libxl__strdup(gc, user_path);
298 if (!xs_rm(CTX->xsh, t, path)) {
299 if (errno != ENOENT)
300 LOGE(DEBUG, "unable to remove path %s", path);
301 rc = ERROR_FAIL;
302 goto out;
303 }
304
305 for (last = strrchr(path, '/'); last != NULL; last = strrchr(path, '/')) {
306 *last = '\0';
307
308 if (!strlen(path)) break;
309
310 val = libxl__xs_read(gc, t, path);
311 if (!val || strlen(val) != 0) break;
312
313 if (!libxl__xs_directory(gc, t, path, &nb) || nb != 0) break;
314
315 if (!xs_rm(CTX->xsh, t, path)) {
316 if (errno != ENOENT)
317 LOGE(DEBUG, "unable to remove path %s", path);
318 rc = ERROR_FAIL;
319 goto out;
320 }
321 }
322 rc = 0;
323
324 out:
325 return rc;
326 }
327
328 /*
329 * Local variables:
330 * mode: C
331 * c-basic-offset: 4
332 * indent-tabs-mode: nil
333 * End:
334 */
335