Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #include <stdarg.h>
32 : : #include <stdio.h>
33 : : #include <stdlib.h>
34 : : #include <string.h>
35 : :
36 : : #include "blktap.h"
37 : : #include "tapback.h"
38 : :
39 : : char *
40 : 0 : tapback_xs_vread(struct xs_handle * const xs, xs_transaction_t xst,
41 : : const char * const fmt, va_list ap)
42 : : {
43 : 0 : char *path, *data = NULL;
44 : 0 : unsigned int len = 0;
45 : 0 : int err = 0;
46 : :
47 : 0 : ASSERT(xs);
48 : :
49 : 0 : if (vasprintf(&path, fmt, ap) == -1) {
50 : 0 : err = errno;
51 : 0 : WARN(NULL, "failed to vasprintf: %s\n", strerror(err));
52 : : goto fail;
53 : : }
54 : 0 : ASSERT(path);
55 : :
56 : 0 : data = xs_read(xs, xst, path, &len);
57 : 0 : err = errno;
58 : 0 : free(path);
59 : :
60 : 0 : if (!data)
61 : 0 : return NULL;
62 : :
63 : : /*
64 : : * According to the documentation of xs_read the string is NULL-terminated,
65 : : * though in the prototype there was code checking for that, so lets ensure
66 : : * this is correct.
67 : : */
68 : 0 : if (data[len] != '\0') {
69 : 0 : err = EINVAL;
70 : 0 : WARN(NULL, "XenStore value '%.*s' is not NULL-terminated\n", len,
71 : : data);
72 : : goto fail;
73 : : }
74 : :
75 : : /*
76 : : * Make sure the returned string does not containing NULL characters, apart
77 : : * from the NULL-terminating one.
78 : : */
79 : 0 : if ((unsigned int)(strchr(data, '\0') - data) != len) {
80 : 0 : err = EINVAL;
81 : : /* TODO print extraneous '\0' characters */
82 : 0 : WARN(NULL, "XenStore value '%s' contains extraneous NULLs\n", data);
83 : : goto fail;
84 : : }
85 : :
86 : : return data;
87 : : fail:
88 : 0 : free(data);
89 : 0 : errno = err;
90 : 0 : return NULL;
91 : : }
92 : :
93 : : __printf(3, 4)
94 : : char *
95 : 0 : tapback_xs_read(struct xs_handle * const xs, xs_transaction_t xst,
96 : : const char * const fmt, ...)
97 : : {
98 : : va_list ap;
99 : : char *s;
100 : :
101 : 0 : ASSERT(xs);
102 : :
103 : 0 : va_start(ap, fmt);
104 : 0 : s = tapback_xs_vread(xs, xst, fmt, ap);
105 : 0 : va_end(ap);
106 : :
107 : 0 : return s;
108 : : }
109 : :
110 : : char *
111 : 0 : tapback_device_read(const vbd_t * const device, xs_transaction_t xst,
112 : : const char * const path)
113 : : {
114 : 0 : ASSERT(device);
115 : 0 : ASSERT(path);
116 : :
117 : 0 : return tapback_xs_read(device->backend->xs, xst, "%s/%s/%s",
118 : 0 : device->backend->path, device->name, path);
119 : : }
120 : :
121 : : char *
122 : 0 : tapback_device_read_otherend(vbd_t * const device, xs_transaction_t xst,
123 : : const char * const path)
124 : : {
125 : 0 : ASSERT(device);
126 : 0 : ASSERT(path);
127 : 0 : ASSERT(device->frontend_path);
128 : :
129 : 0 : return tapback_xs_read(device->backend->xs, xst, "%s/%s",
130 : : device->frontend_path, path);
131 : : }
132 : :
133 : : int
134 : 0 : tapback_device_scanf_otherend(vbd_t * const device, xs_transaction_t xst,
135 : : const char * const path, const char * const fmt, ...)
136 : : {
137 : : va_list ap;
138 : 0 : int n = 0;
139 : 0 : char *s = NULL;
140 : :
141 : 0 : ASSERT(device);
142 : 0 : ASSERT(path);
143 : :
144 : 0 : if (!(s = tapback_device_read_otherend(device, xst, path)))
145 : 0 : return -1;
146 : 0 : va_start(ap, fmt);
147 : 0 : n = vsscanf(s, fmt, ap);
148 : 0 : free(s);
149 : 0 : va_end(ap);
150 : :
151 : 0 : return n;
152 : : }
153 : :
154 : : int
155 : 0 : tapback_device_printf(vbd_t * const device, xs_transaction_t xst,
156 : : const char * const key, const bool mkread, const char * const fmt, ...)
157 : : {
158 : : va_list ap;
159 : 0 : int err = 0;
160 : 0 : char *path = NULL, *val = NULL;
161 : 0 : bool nerr = false;
162 : :
163 : 0 : ASSERT(device);
164 : 0 : ASSERT(key);
165 : :
166 : 0 : if (-1 == asprintf(&path, "%s/%s/%s", device->backend->path,
167 : : device->name, key)) {
168 : 0 : err = -errno;
169 : 0 : goto fail;
170 : : }
171 : :
172 : 0 : va_start(ap, fmt);
173 : 0 : if (-1 == vasprintf(&val, fmt, ap))
174 : 0 : val = NULL;
175 : 0 : va_end(ap);
176 : :
177 : 0 : if (!val) {
178 : 0 : err = -errno;
179 : 0 : goto fail;
180 : : }
181 : :
182 : 0 : if (!(nerr = xs_write(device->backend->xs, xst, path, val, strlen(val)))) {
183 : 0 : err = -errno;
184 : 0 : goto fail;
185 : : }
186 : :
187 : 0 : if (mkread) {
188 : 0 : struct xs_permissions perms[2] = {
189 : 0 : {device->backend->domid, XS_PERM_NONE},
190 : 0 : {device->domid, XS_PERM_READ}
191 : : };
192 : :
193 : 0 : if (!(nerr = xs_set_permissions(device->backend->xs, xst, path, perms,
194 : : ARRAY_SIZE(perms)))) {
195 : 0 : err = -errno;
196 : 0 : goto fail;
197 : : }
198 : : }
199 : :
200 : : fail:
201 : 0 : free(path);
202 : 0 : free(val);
203 : :
204 : 0 : return err;
205 : : }
206 : :
207 : : int
208 : 0 : tapback_xs_exists(struct xs_handle * const xs, xs_transaction_t xst,
209 : : char *path, const int *len)
210 : : {
211 : 0 : int err = 0;
212 : 0 : char *s = NULL;
213 : 0 : bool exists = false;
214 : 0 : char c = '\0';
215 : :
216 : 0 : ASSERT(xs);
217 : 0 : ASSERT(path);
218 : :
219 : 0 : if (len) {
220 : 0 : c = path[*len];
221 : 0 : path[*len] = '\0';
222 : : }
223 : :
224 : 0 : s = tapback_xs_read(xs, xst, "%s", path);
225 : 0 : if (s)
226 : : exists = true;
227 : : else {
228 : 0 : err = errno;
229 : 0 : ASSERT(err != 0);
230 : 0 : if (err == ENOENT) {
231 : 0 : err = 0;
232 : 0 : exists = false;
233 : : }
234 : : }
235 : :
236 : 0 : free(s);
237 : :
238 : 0 : if (len)
239 : 0 : path[*len] = c;
240 : :
241 : 0 : if (!err) {
242 : 0 : if (exists) {
243 : : return 1;
244 : : } else {
245 : 0 : return 0;
246 : : }
247 : : } else {
248 : 0 : return -err;
249 : : }
250 : : }
|