root / util / osdep.c @ cb77d192
History | View | Annotate | Download (10.1 kB)
1 | ea88812f | bellard | /*
|
---|---|---|---|
2 | ea88812f | bellard | * QEMU low level functions
|
3 | 5fafdf24 | ths | *
|
4 | ea88812f | bellard | * Copyright (c) 2003 Fabrice Bellard
|
5 | 5fafdf24 | ths | *
|
6 | ea88812f | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | ea88812f | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | ea88812f | bellard | * in the Software without restriction, including without limitation the rights
|
9 | ea88812f | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | ea88812f | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | ea88812f | bellard | * furnished to do so, subject to the following conditions:
|
12 | ea88812f | bellard | *
|
13 | ea88812f | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | ea88812f | bellard | * all copies or substantial portions of the Software.
|
15 | ea88812f | bellard | *
|
16 | ea88812f | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | ea88812f | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | ea88812f | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | ea88812f | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | ea88812f | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | ea88812f | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | ea88812f | bellard | * THE SOFTWARE.
|
23 | ea88812f | bellard | */
|
24 | ea88812f | bellard | #include <stdlib.h> |
25 | ea88812f | bellard | #include <stdio.h> |
26 | ea88812f | bellard | #include <stdarg.h> |
27 | 0f66998f | Paul Moore | #include <stdbool.h> |
28 | ea88812f | bellard | #include <string.h> |
29 | ea88812f | bellard | #include <errno.h> |
30 | ea88812f | bellard | #include <unistd.h> |
31 | aa26bb2d | ths | #include <fcntl.h> |
32 | f582af58 | Paolo Bonzini | |
33 | f582af58 | Paolo Bonzini | /* Needed early for CONFIG_BSD etc. */
|
34 | f582af58 | Paolo Bonzini | #include "config-host.h" |
35 | f582af58 | Paolo Bonzini | |
36 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
|
37 | e78815a5 | Andreas Färber | #include <sys/mman.h> |
38 | e78815a5 | Andreas Färber | #endif
|
39 | e78815a5 | Andreas Färber | |
40 | dfe5fff3 | Juan Quintela | #ifdef CONFIG_SOLARIS
|
41 | 605686cd | ths | #include <sys/types.h> |
42 | 605686cd | ths | #include <sys/statvfs.h> |
43 | e78815a5 | Andreas Färber | /* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
|
44 | e78815a5 | Andreas Färber | discussion about Solaris header problems */
|
45 | e78815a5 | Andreas Färber | extern int madvise(caddr_t, size_t, int); |
46 | 605686cd | ths | #endif
|
47 | ea88812f | bellard | |
48 | 511d2b14 | blueswir1 | #include "qemu-common.h" |
49 | cd245a19 | Stefan Hajnoczi | #include "trace.h" |
50 | 1de7afc9 | Paolo Bonzini | #include "qemu/sockets.h" |
51 | 83c9089e | Paolo Bonzini | #include "monitor/monitor.h" |
52 | 03ff3ca3 | aliguori | |
53 | 0f66998f | Paul Moore | static bool fips_enabled = false; |
54 | 0f66998f | Paul Moore | |
55 | 93bfef4c | Crístian Viana | static const char *qemu_version = QEMU_VERSION; |
56 | 93bfef4c | Crístian Viana | |
57 | 128aa589 | Paolo Bonzini | int socket_set_cork(int fd, int v) |
58 | 128aa589 | Paolo Bonzini | { |
59 | 128aa589 | Paolo Bonzini | #if defined(SOL_TCP) && defined(TCP_CORK)
|
60 | 4bd1afbd | Lei Li | return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v)); |
61 | 128aa589 | Paolo Bonzini | #else
|
62 | 128aa589 | Paolo Bonzini | return 0; |
63 | 128aa589 | Paolo Bonzini | #endif
|
64 | 128aa589 | Paolo Bonzini | } |
65 | 128aa589 | Paolo Bonzini | |
66 | bf1c852a | MORITA Kazutaka | int socket_set_nodelay(int fd) |
67 | bf1c852a | MORITA Kazutaka | { |
68 | bf1c852a | MORITA Kazutaka | int v = 1; |
69 | 4bd1afbd | Lei Li | return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); |
70 | bf1c852a | MORITA Kazutaka | } |
71 | bf1c852a | MORITA Kazutaka | |
72 | e78815a5 | Andreas Färber | int qemu_madvise(void *addr, size_t len, int advice) |
73 | e78815a5 | Andreas Färber | { |
74 | e78815a5 | Andreas Färber | if (advice == QEMU_MADV_INVALID) {
|
75 | e78815a5 | Andreas Färber | errno = EINVAL; |
76 | e78815a5 | Andreas Färber | return -1; |
77 | e78815a5 | Andreas Färber | } |
78 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE)
|
79 | e78815a5 | Andreas Färber | return madvise(addr, len, advice);
|
80 | e78815a5 | Andreas Färber | #elif defined(CONFIG_POSIX_MADVISE)
|
81 | e78815a5 | Andreas Färber | return posix_madvise(addr, len, advice);
|
82 | e78815a5 | Andreas Färber | #else
|
83 | e78815a5 | Andreas Färber | errno = EINVAL; |
84 | e78815a5 | Andreas Färber | return -1; |
85 | e78815a5 | Andreas Färber | #endif
|
86 | e78815a5 | Andreas Färber | } |
87 | e78815a5 | Andreas Färber | |
88 | adb696f3 | Corey Bryant | #ifndef _WIN32
|
89 | adb696f3 | Corey Bryant | /*
|
90 | adb696f3 | Corey Bryant | * Dups an fd and sets the flags
|
91 | adb696f3 | Corey Bryant | */
|
92 | adb696f3 | Corey Bryant | static int qemu_dup_flags(int fd, int flags) |
93 | adb696f3 | Corey Bryant | { |
94 | adb696f3 | Corey Bryant | int ret;
|
95 | adb696f3 | Corey Bryant | int serrno;
|
96 | adb696f3 | Corey Bryant | int dup_flags;
|
97 | adb696f3 | Corey Bryant | |
98 | adb696f3 | Corey Bryant | #ifdef F_DUPFD_CLOEXEC
|
99 | adb696f3 | Corey Bryant | ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
|
100 | adb696f3 | Corey Bryant | #else
|
101 | adb696f3 | Corey Bryant | ret = dup(fd); |
102 | adb696f3 | Corey Bryant | if (ret != -1) { |
103 | adb696f3 | Corey Bryant | qemu_set_cloexec(ret); |
104 | adb696f3 | Corey Bryant | } |
105 | adb696f3 | Corey Bryant | #endif
|
106 | adb696f3 | Corey Bryant | if (ret == -1) { |
107 | adb696f3 | Corey Bryant | goto fail;
|
108 | adb696f3 | Corey Bryant | } |
109 | adb696f3 | Corey Bryant | |
110 | adb696f3 | Corey Bryant | dup_flags = fcntl(ret, F_GETFL); |
111 | adb696f3 | Corey Bryant | if (dup_flags == -1) { |
112 | adb696f3 | Corey Bryant | goto fail;
|
113 | adb696f3 | Corey Bryant | } |
114 | adb696f3 | Corey Bryant | |
115 | adb696f3 | Corey Bryant | if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
|
116 | adb696f3 | Corey Bryant | errno = EINVAL; |
117 | adb696f3 | Corey Bryant | goto fail;
|
118 | adb696f3 | Corey Bryant | } |
119 | adb696f3 | Corey Bryant | |
120 | adb696f3 | Corey Bryant | /* Set/unset flags that we can with fcntl */
|
121 | 3b6eda2f | Corey Bryant | if (fcntl(ret, F_SETFL, flags) == -1) { |
122 | adb696f3 | Corey Bryant | goto fail;
|
123 | adb696f3 | Corey Bryant | } |
124 | adb696f3 | Corey Bryant | |
125 | adb696f3 | Corey Bryant | /* Truncate the file in the cases that open() would truncate it */
|
126 | adb696f3 | Corey Bryant | if (flags & O_TRUNC ||
|
127 | adb696f3 | Corey Bryant | ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) { |
128 | adb696f3 | Corey Bryant | if (ftruncate(ret, 0) == -1) { |
129 | adb696f3 | Corey Bryant | goto fail;
|
130 | adb696f3 | Corey Bryant | } |
131 | adb696f3 | Corey Bryant | } |
132 | adb696f3 | Corey Bryant | |
133 | adb696f3 | Corey Bryant | return ret;
|
134 | adb696f3 | Corey Bryant | |
135 | adb696f3 | Corey Bryant | fail:
|
136 | adb696f3 | Corey Bryant | serrno = errno; |
137 | adb696f3 | Corey Bryant | if (ret != -1) { |
138 | adb696f3 | Corey Bryant | close(ret); |
139 | adb696f3 | Corey Bryant | } |
140 | adb696f3 | Corey Bryant | errno = serrno; |
141 | adb696f3 | Corey Bryant | return -1; |
142 | adb696f3 | Corey Bryant | } |
143 | 0100fbbe | Paolo Bonzini | |
144 | 0100fbbe | Paolo Bonzini | static int qemu_parse_fdset(const char *param) |
145 | 0100fbbe | Paolo Bonzini | { |
146 | 0100fbbe | Paolo Bonzini | return qemu_parse_fd(param);
|
147 | 0100fbbe | Paolo Bonzini | } |
148 | adb696f3 | Corey Bryant | #endif
|
149 | 03ff3ca3 | aliguori | |
150 | 40ff6d7e | Kevin Wolf | /*
|
151 | 40ff6d7e | Kevin Wolf | * Opens a file with FD_CLOEXEC set
|
152 | 40ff6d7e | Kevin Wolf | */
|
153 | 40ff6d7e | Kevin Wolf | int qemu_open(const char *name, int flags, ...) |
154 | 40ff6d7e | Kevin Wolf | { |
155 | 40ff6d7e | Kevin Wolf | int ret;
|
156 | 40ff6d7e | Kevin Wolf | int mode = 0; |
157 | 40ff6d7e | Kevin Wolf | |
158 | adb696f3 | Corey Bryant | #ifndef _WIN32
|
159 | adb696f3 | Corey Bryant | const char *fdset_id_str; |
160 | adb696f3 | Corey Bryant | |
161 | adb696f3 | Corey Bryant | /* Attempt dup of fd from fd set */
|
162 | adb696f3 | Corey Bryant | if (strstart(name, "/dev/fdset/", &fdset_id_str)) { |
163 | adb696f3 | Corey Bryant | int64_t fdset_id; |
164 | adb696f3 | Corey Bryant | int fd, dupfd;
|
165 | adb696f3 | Corey Bryant | |
166 | adb696f3 | Corey Bryant | fdset_id = qemu_parse_fdset(fdset_id_str); |
167 | adb696f3 | Corey Bryant | if (fdset_id == -1) { |
168 | adb696f3 | Corey Bryant | errno = EINVAL; |
169 | adb696f3 | Corey Bryant | return -1; |
170 | adb696f3 | Corey Bryant | } |
171 | adb696f3 | Corey Bryant | |
172 | adb696f3 | Corey Bryant | fd = monitor_fdset_get_fd(fdset_id, flags); |
173 | adb696f3 | Corey Bryant | if (fd == -1) { |
174 | adb696f3 | Corey Bryant | return -1; |
175 | adb696f3 | Corey Bryant | } |
176 | adb696f3 | Corey Bryant | |
177 | adb696f3 | Corey Bryant | dupfd = qemu_dup_flags(fd, flags); |
178 | adb696f3 | Corey Bryant | if (dupfd == -1) { |
179 | adb696f3 | Corey Bryant | return -1; |
180 | adb696f3 | Corey Bryant | } |
181 | adb696f3 | Corey Bryant | |
182 | adb696f3 | Corey Bryant | ret = monitor_fdset_dup_fd_add(fdset_id, dupfd); |
183 | adb696f3 | Corey Bryant | if (ret == -1) { |
184 | adb696f3 | Corey Bryant | close(dupfd); |
185 | adb696f3 | Corey Bryant | errno = EINVAL; |
186 | adb696f3 | Corey Bryant | return -1; |
187 | adb696f3 | Corey Bryant | } |
188 | adb696f3 | Corey Bryant | |
189 | adb696f3 | Corey Bryant | return dupfd;
|
190 | adb696f3 | Corey Bryant | } |
191 | adb696f3 | Corey Bryant | #endif
|
192 | adb696f3 | Corey Bryant | |
193 | 40ff6d7e | Kevin Wolf | if (flags & O_CREAT) {
|
194 | 40ff6d7e | Kevin Wolf | va_list ap; |
195 | 40ff6d7e | Kevin Wolf | |
196 | 40ff6d7e | Kevin Wolf | va_start(ap, flags); |
197 | 40ff6d7e | Kevin Wolf | mode = va_arg(ap, int);
|
198 | 40ff6d7e | Kevin Wolf | va_end(ap); |
199 | 40ff6d7e | Kevin Wolf | } |
200 | 40ff6d7e | Kevin Wolf | |
201 | 40ff6d7e | Kevin Wolf | #ifdef O_CLOEXEC
|
202 | 40ff6d7e | Kevin Wolf | ret = open(name, flags | O_CLOEXEC, mode); |
203 | 40ff6d7e | Kevin Wolf | #else
|
204 | 40ff6d7e | Kevin Wolf | ret = open(name, flags, mode); |
205 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
206 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
207 | 40ff6d7e | Kevin Wolf | } |
208 | 03ff3ca3 | aliguori | #endif
|
209 | 40ff6d7e | Kevin Wolf | |
210 | 40ff6d7e | Kevin Wolf | return ret;
|
211 | 40ff6d7e | Kevin Wolf | } |
212 | 40ff6d7e | Kevin Wolf | |
213 | 2e1e79da | Corey Bryant | int qemu_close(int fd) |
214 | 2e1e79da | Corey Bryant | { |
215 | adb696f3 | Corey Bryant | int64_t fdset_id; |
216 | adb696f3 | Corey Bryant | |
217 | adb696f3 | Corey Bryant | /* Close fd that was dup'd from an fdset */
|
218 | adb696f3 | Corey Bryant | fdset_id = monitor_fdset_dup_fd_find(fd); |
219 | adb696f3 | Corey Bryant | if (fdset_id != -1) { |
220 | adb696f3 | Corey Bryant | int ret;
|
221 | adb696f3 | Corey Bryant | |
222 | adb696f3 | Corey Bryant | ret = close(fd); |
223 | adb696f3 | Corey Bryant | if (ret == 0) { |
224 | adb696f3 | Corey Bryant | monitor_fdset_dup_fd_remove(fd); |
225 | adb696f3 | Corey Bryant | } |
226 | adb696f3 | Corey Bryant | |
227 | adb696f3 | Corey Bryant | return ret;
|
228 | adb696f3 | Corey Bryant | } |
229 | adb696f3 | Corey Bryant | |
230 | 2e1e79da | Corey Bryant | return close(fd);
|
231 | 2e1e79da | Corey Bryant | } |
232 | 2e1e79da | Corey Bryant | |
233 | 7b5f699d | Kirill A. Shutemov | /*
|
234 | 7b5f699d | Kirill A. Shutemov | * A variant of write(2) which handles partial write.
|
235 | 7b5f699d | Kirill A. Shutemov | *
|
236 | 7b5f699d | Kirill A. Shutemov | * Return the number of bytes transferred.
|
237 | 7b5f699d | Kirill A. Shutemov | * Set errno if fewer than `count' bytes are written.
|
238 | 1298cb68 | Juan Quintela | *
|
239 | 1298cb68 | Juan Quintela | * This function don't work with non-blocking fd's.
|
240 | 1298cb68 | Juan Quintela | * Any of the possibilities with non-bloking fd's is bad:
|
241 | 1298cb68 | Juan Quintela | * - return a short write (then name is wrong)
|
242 | 1298cb68 | Juan Quintela | * - busy wait adding (errno == EAGAIN) to the loop
|
243 | 7b5f699d | Kirill A. Shutemov | */
|
244 | 7b5f699d | Kirill A. Shutemov | ssize_t qemu_write_full(int fd, const void *buf, size_t count) |
245 | 7b5f699d | Kirill A. Shutemov | { |
246 | 7b5f699d | Kirill A. Shutemov | ssize_t ret = 0;
|
247 | 7b5f699d | Kirill A. Shutemov | ssize_t total = 0;
|
248 | 7b5f699d | Kirill A. Shutemov | |
249 | 7b5f699d | Kirill A. Shutemov | while (count) {
|
250 | 7b5f699d | Kirill A. Shutemov | ret = write(fd, buf, count); |
251 | 7b5f699d | Kirill A. Shutemov | if (ret < 0) { |
252 | 7b5f699d | Kirill A. Shutemov | if (errno == EINTR)
|
253 | 7b5f699d | Kirill A. Shutemov | continue;
|
254 | 7b5f699d | Kirill A. Shutemov | break;
|
255 | 7b5f699d | Kirill A. Shutemov | } |
256 | 7b5f699d | Kirill A. Shutemov | |
257 | 7b5f699d | Kirill A. Shutemov | count -= ret; |
258 | 7b5f699d | Kirill A. Shutemov | buf += ret; |
259 | 7b5f699d | Kirill A. Shutemov | total += ret; |
260 | 7b5f699d | Kirill A. Shutemov | } |
261 | 7b5f699d | Kirill A. Shutemov | |
262 | 7b5f699d | Kirill A. Shutemov | return total;
|
263 | 7b5f699d | Kirill A. Shutemov | } |
264 | 7b5f699d | Kirill A. Shutemov | |
265 | 40ff6d7e | Kevin Wolf | /*
|
266 | 40ff6d7e | Kevin Wolf | * Opens a socket with FD_CLOEXEC set
|
267 | 40ff6d7e | Kevin Wolf | */
|
268 | 40ff6d7e | Kevin Wolf | int qemu_socket(int domain, int type, int protocol) |
269 | 40ff6d7e | Kevin Wolf | { |
270 | 40ff6d7e | Kevin Wolf | int ret;
|
271 | 40ff6d7e | Kevin Wolf | |
272 | 40ff6d7e | Kevin Wolf | #ifdef SOCK_CLOEXEC
|
273 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type | SOCK_CLOEXEC, protocol); |
274 | 3a03bfa5 | Andre Przywara | if (ret != -1 || errno != EINVAL) { |
275 | 3a03bfa5 | Andre Przywara | return ret;
|
276 | 3a03bfa5 | Andre Przywara | } |
277 | 3a03bfa5 | Andre Przywara | #endif
|
278 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type, protocol); |
279 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
280 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
281 | 40ff6d7e | Kevin Wolf | } |
282 | 40ff6d7e | Kevin Wolf | |
283 | 40ff6d7e | Kevin Wolf | return ret;
|
284 | 40ff6d7e | Kevin Wolf | } |
285 | 40ff6d7e | Kevin Wolf | |
286 | 40ff6d7e | Kevin Wolf | /*
|
287 | 40ff6d7e | Kevin Wolf | * Accept a connection and set FD_CLOEXEC
|
288 | 40ff6d7e | Kevin Wolf | */
|
289 | 40ff6d7e | Kevin Wolf | int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) |
290 | 40ff6d7e | Kevin Wolf | { |
291 | 40ff6d7e | Kevin Wolf | int ret;
|
292 | 40ff6d7e | Kevin Wolf | |
293 | 40ff6d7e | Kevin Wolf | #ifdef CONFIG_ACCEPT4
|
294 | 40ff6d7e | Kevin Wolf | ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); |
295 | 347ed55c | Kevin Wolf | if (ret != -1 || errno != ENOSYS) { |
296 | 3a03bfa5 | Andre Przywara | return ret;
|
297 | 3a03bfa5 | Andre Przywara | } |
298 | 3a03bfa5 | Andre Przywara | #endif
|
299 | 40ff6d7e | Kevin Wolf | ret = accept(s, addr, addrlen); |
300 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
301 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
302 | 40ff6d7e | Kevin Wolf | } |
303 | 40ff6d7e | Kevin Wolf | |
304 | 40ff6d7e | Kevin Wolf | return ret;
|
305 | 40ff6d7e | Kevin Wolf | } |
306 | 993295fe | Paolo Bonzini | |
307 | 993295fe | Paolo Bonzini | /*
|
308 | 993295fe | Paolo Bonzini | * A variant of send(2) which handles partial write.
|
309 | 993295fe | Paolo Bonzini | *
|
310 | 993295fe | Paolo Bonzini | * Return the number of bytes transferred, which is only
|
311 | 993295fe | Paolo Bonzini | * smaller than `count' if there is an error.
|
312 | 993295fe | Paolo Bonzini | *
|
313 | 993295fe | Paolo Bonzini | * This function won't work with non-blocking fd's.
|
314 | 993295fe | Paolo Bonzini | * Any of the possibilities with non-bloking fd's is bad:
|
315 | 993295fe | Paolo Bonzini | * - return a short write (then name is wrong)
|
316 | 993295fe | Paolo Bonzini | * - busy wait adding (errno == EAGAIN) to the loop
|
317 | 993295fe | Paolo Bonzini | */
|
318 | 993295fe | Paolo Bonzini | ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags) |
319 | 993295fe | Paolo Bonzini | { |
320 | 993295fe | Paolo Bonzini | ssize_t ret = 0;
|
321 | 993295fe | Paolo Bonzini | ssize_t total = 0;
|
322 | 993295fe | Paolo Bonzini | |
323 | 993295fe | Paolo Bonzini | while (count) {
|
324 | 993295fe | Paolo Bonzini | ret = send(fd, buf, count, flags); |
325 | 993295fe | Paolo Bonzini | if (ret < 0) { |
326 | 993295fe | Paolo Bonzini | if (errno == EINTR) {
|
327 | 993295fe | Paolo Bonzini | continue;
|
328 | 993295fe | Paolo Bonzini | } |
329 | 993295fe | Paolo Bonzini | break;
|
330 | 993295fe | Paolo Bonzini | } |
331 | 993295fe | Paolo Bonzini | |
332 | 993295fe | Paolo Bonzini | count -= ret; |
333 | 993295fe | Paolo Bonzini | buf += ret; |
334 | 993295fe | Paolo Bonzini | total += ret; |
335 | 993295fe | Paolo Bonzini | } |
336 | 993295fe | Paolo Bonzini | |
337 | 993295fe | Paolo Bonzini | return total;
|
338 | 993295fe | Paolo Bonzini | } |
339 | 993295fe | Paolo Bonzini | |
340 | 993295fe | Paolo Bonzini | /*
|
341 | 993295fe | Paolo Bonzini | * A variant of recv(2) which handles partial write.
|
342 | 993295fe | Paolo Bonzini | *
|
343 | 993295fe | Paolo Bonzini | * Return the number of bytes transferred, which is only
|
344 | 993295fe | Paolo Bonzini | * smaller than `count' if there is an error.
|
345 | 993295fe | Paolo Bonzini | *
|
346 | 993295fe | Paolo Bonzini | * This function won't work with non-blocking fd's.
|
347 | 993295fe | Paolo Bonzini | * Any of the possibilities with non-bloking fd's is bad:
|
348 | 993295fe | Paolo Bonzini | * - return a short write (then name is wrong)
|
349 | 993295fe | Paolo Bonzini | * - busy wait adding (errno == EAGAIN) to the loop
|
350 | 993295fe | Paolo Bonzini | */
|
351 | 993295fe | Paolo Bonzini | ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags) |
352 | 993295fe | Paolo Bonzini | { |
353 | 993295fe | Paolo Bonzini | ssize_t ret = 0;
|
354 | 993295fe | Paolo Bonzini | ssize_t total = 0;
|
355 | 993295fe | Paolo Bonzini | |
356 | 993295fe | Paolo Bonzini | while (count) {
|
357 | 993295fe | Paolo Bonzini | ret = qemu_recv(fd, buf, count, flags); |
358 | 993295fe | Paolo Bonzini | if (ret <= 0) { |
359 | 993295fe | Paolo Bonzini | if (ret < 0 && errno == EINTR) { |
360 | 993295fe | Paolo Bonzini | continue;
|
361 | 993295fe | Paolo Bonzini | } |
362 | 993295fe | Paolo Bonzini | break;
|
363 | 993295fe | Paolo Bonzini | } |
364 | 993295fe | Paolo Bonzini | |
365 | 993295fe | Paolo Bonzini | count -= ret; |
366 | 993295fe | Paolo Bonzini | buf += ret; |
367 | 993295fe | Paolo Bonzini | total += ret; |
368 | 993295fe | Paolo Bonzini | } |
369 | 993295fe | Paolo Bonzini | |
370 | 993295fe | Paolo Bonzini | return total;
|
371 | 993295fe | Paolo Bonzini | } |
372 | 993295fe | Paolo Bonzini | |
373 | 93bfef4c | Crístian Viana | void qemu_set_version(const char *version) |
374 | 93bfef4c | Crístian Viana | { |
375 | 93bfef4c | Crístian Viana | qemu_version = version; |
376 | 93bfef4c | Crístian Viana | } |
377 | 93bfef4c | Crístian Viana | |
378 | 93bfef4c | Crístian Viana | const char *qemu_get_version(void) |
379 | 93bfef4c | Crístian Viana | { |
380 | 93bfef4c | Crístian Viana | return qemu_version;
|
381 | 93bfef4c | Crístian Viana | } |
382 | 0f66998f | Paul Moore | |
383 | 0f66998f | Paul Moore | void fips_set_state(bool requested) |
384 | 0f66998f | Paul Moore | { |
385 | 0f66998f | Paul Moore | #ifdef __linux__
|
386 | 0f66998f | Paul Moore | if (requested) {
|
387 | 0f66998f | Paul Moore | FILE *fds = fopen("/proc/sys/crypto/fips_enabled", "r"); |
388 | 0f66998f | Paul Moore | if (fds != NULL) { |
389 | 0f66998f | Paul Moore | fips_enabled = (fgetc(fds) == '1');
|
390 | 0f66998f | Paul Moore | fclose(fds); |
391 | 0f66998f | Paul Moore | } |
392 | 0f66998f | Paul Moore | } |
393 | 0f66998f | Paul Moore | #else
|
394 | 0f66998f | Paul Moore | fips_enabled = false;
|
395 | 0f66998f | Paul Moore | #endif /* __linux__ */ |
396 | 0f66998f | Paul Moore | |
397 | 0f66998f | Paul Moore | #ifdef _FIPS_DEBUG
|
398 | 0f66998f | Paul Moore | fprintf(stderr, "FIPS mode %s (requested %s)\n",
|
399 | 0f66998f | Paul Moore | (fips_enabled ? "enabled" : "disabled"), |
400 | 0f66998f | Paul Moore | (requested ? "enabled" : "disabled")); |
401 | 0f66998f | Paul Moore | #endif
|
402 | 0f66998f | Paul Moore | } |
403 | 0f66998f | Paul Moore | |
404 | 0f66998f | Paul Moore | bool fips_get_state(void) |
405 | 0f66998f | Paul Moore | { |
406 | 0f66998f | Paul Moore | return fips_enabled;
|
407 | 0f66998f | Paul Moore | } |
408 | 0100fbbe | Paolo Bonzini | |
409 | d3bf825e | Marc-André Lureau | #ifdef _WIN32
|
410 | d3bf825e | Marc-André Lureau | static void socket_cleanup(void) |
411 | d3bf825e | Marc-André Lureau | { |
412 | d3bf825e | Marc-André Lureau | WSACleanup(); |
413 | d3bf825e | Marc-André Lureau | } |
414 | d3bf825e | Marc-André Lureau | #endif
|
415 | d3bf825e | Marc-André Lureau | |
416 | d3bf825e | Marc-André Lureau | int socket_init(void) |
417 | d3bf825e | Marc-André Lureau | { |
418 | d3bf825e | Marc-André Lureau | #ifdef _WIN32
|
419 | d3bf825e | Marc-André Lureau | WSADATA Data; |
420 | d3bf825e | Marc-André Lureau | int ret, err;
|
421 | d3bf825e | Marc-André Lureau | |
422 | d3bf825e | Marc-André Lureau | ret = WSAStartup(MAKEWORD(2, 2), &Data); |
423 | d3bf825e | Marc-André Lureau | if (ret != 0) { |
424 | d3bf825e | Marc-André Lureau | err = WSAGetLastError(); |
425 | d3bf825e | Marc-André Lureau | fprintf(stderr, "WSAStartup: %d\n", err);
|
426 | d3bf825e | Marc-André Lureau | return -1; |
427 | d3bf825e | Marc-André Lureau | } |
428 | d3bf825e | Marc-André Lureau | atexit(socket_cleanup); |
429 | d3bf825e | Marc-André Lureau | #endif
|
430 | d3bf825e | Marc-André Lureau | return 0; |
431 | d3bf825e | Marc-André Lureau | } |
432 | 9adea5f7 | Paolo Bonzini | |
433 | 9adea5f7 | Paolo Bonzini | #ifndef CONFIG_IOVEC
|
434 | 9adea5f7 | Paolo Bonzini | /* helper function for iov_send_recv() */
|
435 | 9adea5f7 | Paolo Bonzini | static ssize_t
|
436 | 9adea5f7 | Paolo Bonzini | readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write) |
437 | 9adea5f7 | Paolo Bonzini | { |
438 | 9adea5f7 | Paolo Bonzini | unsigned i = 0; |
439 | 9adea5f7 | Paolo Bonzini | ssize_t ret = 0;
|
440 | 9adea5f7 | Paolo Bonzini | while (i < iov_cnt) {
|
441 | 9adea5f7 | Paolo Bonzini | ssize_t r = do_write |
442 | 9adea5f7 | Paolo Bonzini | ? write(fd, iov[i].iov_base, iov[i].iov_len) |
443 | 9adea5f7 | Paolo Bonzini | : read(fd, iov[i].iov_base, iov[i].iov_len); |
444 | 9adea5f7 | Paolo Bonzini | if (r > 0) { |
445 | 9adea5f7 | Paolo Bonzini | ret += r; |
446 | 9adea5f7 | Paolo Bonzini | } else if (!r) { |
447 | 9adea5f7 | Paolo Bonzini | break;
|
448 | 9adea5f7 | Paolo Bonzini | } else if (errno == EINTR) { |
449 | 9adea5f7 | Paolo Bonzini | continue;
|
450 | 9adea5f7 | Paolo Bonzini | } else {
|
451 | 9adea5f7 | Paolo Bonzini | /* else it is some "other" error,
|
452 | 9adea5f7 | Paolo Bonzini | * only return if there was no data processed. */
|
453 | 9adea5f7 | Paolo Bonzini | if (ret == 0) { |
454 | 9adea5f7 | Paolo Bonzini | ret = -1;
|
455 | 9adea5f7 | Paolo Bonzini | } |
456 | 9adea5f7 | Paolo Bonzini | break;
|
457 | 9adea5f7 | Paolo Bonzini | } |
458 | 9adea5f7 | Paolo Bonzini | i++; |
459 | 9adea5f7 | Paolo Bonzini | } |
460 | 9adea5f7 | Paolo Bonzini | return ret;
|
461 | 9adea5f7 | Paolo Bonzini | } |
462 | 9adea5f7 | Paolo Bonzini | |
463 | 9adea5f7 | Paolo Bonzini | ssize_t |
464 | 9adea5f7 | Paolo Bonzini | readv(int fd, const struct iovec *iov, int iov_cnt) |
465 | 9adea5f7 | Paolo Bonzini | { |
466 | 9adea5f7 | Paolo Bonzini | return readv_writev(fd, iov, iov_cnt, false); |
467 | 9adea5f7 | Paolo Bonzini | } |
468 | 9adea5f7 | Paolo Bonzini | |
469 | 9adea5f7 | Paolo Bonzini | ssize_t |
470 | 9adea5f7 | Paolo Bonzini | writev(int fd, const struct iovec *iov, int iov_cnt) |
471 | 9adea5f7 | Paolo Bonzini | { |
472 | 9adea5f7 | Paolo Bonzini | return readv_writev(fd, iov, iov_cnt, true); |
473 | 9adea5f7 | Paolo Bonzini | } |
474 | 9adea5f7 | Paolo Bonzini | #endif |