root / osdep.c @ e3e87df4
History | View | Annotate | Download (5.7 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 | ea88812f | bellard | #include <string.h> |
28 | ea88812f | bellard | #include <errno.h> |
29 | ea88812f | bellard | #include <unistd.h> |
30 | aa26bb2d | ths | #include <fcntl.h> |
31 | f582af58 | Paolo Bonzini | |
32 | f582af58 | Paolo Bonzini | /* Needed early for CONFIG_BSD etc. */
|
33 | f582af58 | Paolo Bonzini | #include "config-host.h" |
34 | f582af58 | Paolo Bonzini | |
35 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
|
36 | e78815a5 | Andreas Färber | #include <sys/mman.h> |
37 | e78815a5 | Andreas Färber | #endif
|
38 | e78815a5 | Andreas Färber | |
39 | dfe5fff3 | Juan Quintela | #ifdef CONFIG_SOLARIS
|
40 | 605686cd | ths | #include <sys/types.h> |
41 | 605686cd | ths | #include <sys/statvfs.h> |
42 | e78815a5 | Andreas Färber | /* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
|
43 | e78815a5 | Andreas Färber | discussion about Solaris header problems */
|
44 | e78815a5 | Andreas Färber | extern int madvise(caddr_t, size_t, int); |
45 | 605686cd | ths | #endif
|
46 | ea88812f | bellard | |
47 | 511d2b14 | blueswir1 | #include "qemu-common.h" |
48 | cd245a19 | Stefan Hajnoczi | #include "trace.h" |
49 | 03ff3ca3 | aliguori | #include "qemu_socket.h" |
50 | 03ff3ca3 | aliguori | |
51 | 128aa589 | Paolo Bonzini | int socket_set_cork(int fd, int v) |
52 | 128aa589 | Paolo Bonzini | { |
53 | 128aa589 | Paolo Bonzini | #if defined(SOL_TCP) && defined(TCP_CORK)
|
54 | 128aa589 | Paolo Bonzini | return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v)); |
55 | 128aa589 | Paolo Bonzini | #else
|
56 | 128aa589 | Paolo Bonzini | return 0; |
57 | 128aa589 | Paolo Bonzini | #endif
|
58 | 128aa589 | Paolo Bonzini | } |
59 | 128aa589 | Paolo Bonzini | |
60 | e78815a5 | Andreas Färber | int qemu_madvise(void *addr, size_t len, int advice) |
61 | e78815a5 | Andreas Färber | { |
62 | e78815a5 | Andreas Färber | if (advice == QEMU_MADV_INVALID) {
|
63 | e78815a5 | Andreas Färber | errno = EINVAL; |
64 | e78815a5 | Andreas Färber | return -1; |
65 | e78815a5 | Andreas Färber | } |
66 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE)
|
67 | e78815a5 | Andreas Färber | return madvise(addr, len, advice);
|
68 | e78815a5 | Andreas Färber | #elif defined(CONFIG_POSIX_MADVISE)
|
69 | e78815a5 | Andreas Färber | return posix_madvise(addr, len, advice);
|
70 | e78815a5 | Andreas Färber | #else
|
71 | e78815a5 | Andreas Färber | errno = EINVAL; |
72 | e78815a5 | Andreas Färber | return -1; |
73 | e78815a5 | Andreas Färber | #endif
|
74 | e78815a5 | Andreas Färber | } |
75 | e78815a5 | Andreas Färber | |
76 | 03ff3ca3 | aliguori | |
77 | 40ff6d7e | Kevin Wolf | /*
|
78 | 40ff6d7e | Kevin Wolf | * Opens a file with FD_CLOEXEC set
|
79 | 40ff6d7e | Kevin Wolf | */
|
80 | 40ff6d7e | Kevin Wolf | int qemu_open(const char *name, int flags, ...) |
81 | 40ff6d7e | Kevin Wolf | { |
82 | 40ff6d7e | Kevin Wolf | int ret;
|
83 | 40ff6d7e | Kevin Wolf | int mode = 0; |
84 | 40ff6d7e | Kevin Wolf | |
85 | 40ff6d7e | Kevin Wolf | if (flags & O_CREAT) {
|
86 | 40ff6d7e | Kevin Wolf | va_list ap; |
87 | 40ff6d7e | Kevin Wolf | |
88 | 40ff6d7e | Kevin Wolf | va_start(ap, flags); |
89 | 40ff6d7e | Kevin Wolf | mode = va_arg(ap, int);
|
90 | 40ff6d7e | Kevin Wolf | va_end(ap); |
91 | 40ff6d7e | Kevin Wolf | } |
92 | 40ff6d7e | Kevin Wolf | |
93 | 40ff6d7e | Kevin Wolf | #ifdef O_CLOEXEC
|
94 | 40ff6d7e | Kevin Wolf | ret = open(name, flags | O_CLOEXEC, mode); |
95 | 40ff6d7e | Kevin Wolf | #else
|
96 | 40ff6d7e | Kevin Wolf | ret = open(name, flags, mode); |
97 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
98 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
99 | 40ff6d7e | Kevin Wolf | } |
100 | 03ff3ca3 | aliguori | #endif
|
101 | 40ff6d7e | Kevin Wolf | |
102 | 40ff6d7e | Kevin Wolf | return ret;
|
103 | 40ff6d7e | Kevin Wolf | } |
104 | 40ff6d7e | Kevin Wolf | |
105 | 7b5f699d | Kirill A. Shutemov | /*
|
106 | 7b5f699d | Kirill A. Shutemov | * A variant of write(2) which handles partial write.
|
107 | 7b5f699d | Kirill A. Shutemov | *
|
108 | 7b5f699d | Kirill A. Shutemov | * Return the number of bytes transferred.
|
109 | 7b5f699d | Kirill A. Shutemov | * Set errno if fewer than `count' bytes are written.
|
110 | 1298cb68 | Juan Quintela | *
|
111 | 1298cb68 | Juan Quintela | * This function don't work with non-blocking fd's.
|
112 | 1298cb68 | Juan Quintela | * Any of the possibilities with non-bloking fd's is bad:
|
113 | 1298cb68 | Juan Quintela | * - return a short write (then name is wrong)
|
114 | 1298cb68 | Juan Quintela | * - busy wait adding (errno == EAGAIN) to the loop
|
115 | 7b5f699d | Kirill A. Shutemov | */
|
116 | 7b5f699d | Kirill A. Shutemov | ssize_t qemu_write_full(int fd, const void *buf, size_t count) |
117 | 7b5f699d | Kirill A. Shutemov | { |
118 | 7b5f699d | Kirill A. Shutemov | ssize_t ret = 0;
|
119 | 7b5f699d | Kirill A. Shutemov | ssize_t total = 0;
|
120 | 7b5f699d | Kirill A. Shutemov | |
121 | 7b5f699d | Kirill A. Shutemov | while (count) {
|
122 | 7b5f699d | Kirill A. Shutemov | ret = write(fd, buf, count); |
123 | 7b5f699d | Kirill A. Shutemov | if (ret < 0) { |
124 | 7b5f699d | Kirill A. Shutemov | if (errno == EINTR)
|
125 | 7b5f699d | Kirill A. Shutemov | continue;
|
126 | 7b5f699d | Kirill A. Shutemov | break;
|
127 | 7b5f699d | Kirill A. Shutemov | } |
128 | 7b5f699d | Kirill A. Shutemov | |
129 | 7b5f699d | Kirill A. Shutemov | count -= ret; |
130 | 7b5f699d | Kirill A. Shutemov | buf += ret; |
131 | 7b5f699d | Kirill A. Shutemov | total += ret; |
132 | 7b5f699d | Kirill A. Shutemov | } |
133 | 7b5f699d | Kirill A. Shutemov | |
134 | 7b5f699d | Kirill A. Shutemov | return total;
|
135 | 7b5f699d | Kirill A. Shutemov | } |
136 | 7b5f699d | Kirill A. Shutemov | |
137 | 40ff6d7e | Kevin Wolf | /*
|
138 | 40ff6d7e | Kevin Wolf | * Opens a socket with FD_CLOEXEC set
|
139 | 40ff6d7e | Kevin Wolf | */
|
140 | 40ff6d7e | Kevin Wolf | int qemu_socket(int domain, int type, int protocol) |
141 | 40ff6d7e | Kevin Wolf | { |
142 | 40ff6d7e | Kevin Wolf | int ret;
|
143 | 40ff6d7e | Kevin Wolf | |
144 | 40ff6d7e | Kevin Wolf | #ifdef SOCK_CLOEXEC
|
145 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type | SOCK_CLOEXEC, protocol); |
146 | 3a03bfa5 | Andre Przywara | if (ret != -1 || errno != EINVAL) { |
147 | 3a03bfa5 | Andre Przywara | return ret;
|
148 | 3a03bfa5 | Andre Przywara | } |
149 | 3a03bfa5 | Andre Przywara | #endif
|
150 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type, protocol); |
151 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
152 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
153 | 40ff6d7e | Kevin Wolf | } |
154 | 40ff6d7e | Kevin Wolf | |
155 | 40ff6d7e | Kevin Wolf | return ret;
|
156 | 40ff6d7e | Kevin Wolf | } |
157 | 40ff6d7e | Kevin Wolf | |
158 | 40ff6d7e | Kevin Wolf | /*
|
159 | 40ff6d7e | Kevin Wolf | * Accept a connection and set FD_CLOEXEC
|
160 | 40ff6d7e | Kevin Wolf | */
|
161 | 40ff6d7e | Kevin Wolf | int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) |
162 | 40ff6d7e | Kevin Wolf | { |
163 | 40ff6d7e | Kevin Wolf | int ret;
|
164 | 40ff6d7e | Kevin Wolf | |
165 | 40ff6d7e | Kevin Wolf | #ifdef CONFIG_ACCEPT4
|
166 | 40ff6d7e | Kevin Wolf | ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); |
167 | 347ed55c | Kevin Wolf | if (ret != -1 || errno != ENOSYS) { |
168 | 3a03bfa5 | Andre Przywara | return ret;
|
169 | 3a03bfa5 | Andre Przywara | } |
170 | 3a03bfa5 | Andre Przywara | #endif
|
171 | 40ff6d7e | Kevin Wolf | ret = accept(s, addr, addrlen); |
172 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
173 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
174 | 40ff6d7e | Kevin Wolf | } |
175 | 40ff6d7e | Kevin Wolf | |
176 | 40ff6d7e | Kevin Wolf | return ret;
|
177 | 40ff6d7e | Kevin Wolf | } |
178 | 993295fe | Paolo Bonzini | |
179 | 993295fe | Paolo Bonzini | /*
|
180 | 993295fe | Paolo Bonzini | * A variant of send(2) which handles partial write.
|
181 | 993295fe | Paolo Bonzini | *
|
182 | 993295fe | Paolo Bonzini | * Return the number of bytes transferred, which is only
|
183 | 993295fe | Paolo Bonzini | * smaller than `count' if there is an error.
|
184 | 993295fe | Paolo Bonzini | *
|
185 | 993295fe | Paolo Bonzini | * This function won't work with non-blocking fd's.
|
186 | 993295fe | Paolo Bonzini | * Any of the possibilities with non-bloking fd's is bad:
|
187 | 993295fe | Paolo Bonzini | * - return a short write (then name is wrong)
|
188 | 993295fe | Paolo Bonzini | * - busy wait adding (errno == EAGAIN) to the loop
|
189 | 993295fe | Paolo Bonzini | */
|
190 | 993295fe | Paolo Bonzini | ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags) |
191 | 993295fe | Paolo Bonzini | { |
192 | 993295fe | Paolo Bonzini | ssize_t ret = 0;
|
193 | 993295fe | Paolo Bonzini | ssize_t total = 0;
|
194 | 993295fe | Paolo Bonzini | |
195 | 993295fe | Paolo Bonzini | while (count) {
|
196 | 993295fe | Paolo Bonzini | ret = send(fd, buf, count, flags); |
197 | 993295fe | Paolo Bonzini | if (ret < 0) { |
198 | 993295fe | Paolo Bonzini | if (errno == EINTR) {
|
199 | 993295fe | Paolo Bonzini | continue;
|
200 | 993295fe | Paolo Bonzini | } |
201 | 993295fe | Paolo Bonzini | break;
|
202 | 993295fe | Paolo Bonzini | } |
203 | 993295fe | Paolo Bonzini | |
204 | 993295fe | Paolo Bonzini | count -= ret; |
205 | 993295fe | Paolo Bonzini | buf += ret; |
206 | 993295fe | Paolo Bonzini | total += ret; |
207 | 993295fe | Paolo Bonzini | } |
208 | 993295fe | Paolo Bonzini | |
209 | 993295fe | Paolo Bonzini | return total;
|
210 | 993295fe | Paolo Bonzini | } |
211 | 993295fe | Paolo Bonzini | |
212 | 993295fe | Paolo Bonzini | /*
|
213 | 993295fe | Paolo Bonzini | * A variant of recv(2) which handles partial write.
|
214 | 993295fe | Paolo Bonzini | *
|
215 | 993295fe | Paolo Bonzini | * Return the number of bytes transferred, which is only
|
216 | 993295fe | Paolo Bonzini | * smaller than `count' if there is an error.
|
217 | 993295fe | Paolo Bonzini | *
|
218 | 993295fe | Paolo Bonzini | * This function won't work with non-blocking fd's.
|
219 | 993295fe | Paolo Bonzini | * Any of the possibilities with non-bloking fd's is bad:
|
220 | 993295fe | Paolo Bonzini | * - return a short write (then name is wrong)
|
221 | 993295fe | Paolo Bonzini | * - busy wait adding (errno == EAGAIN) to the loop
|
222 | 993295fe | Paolo Bonzini | */
|
223 | 993295fe | Paolo Bonzini | ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags) |
224 | 993295fe | Paolo Bonzini | { |
225 | 993295fe | Paolo Bonzini | ssize_t ret = 0;
|
226 | 993295fe | Paolo Bonzini | ssize_t total = 0;
|
227 | 993295fe | Paolo Bonzini | |
228 | 993295fe | Paolo Bonzini | while (count) {
|
229 | 993295fe | Paolo Bonzini | ret = qemu_recv(fd, buf, count, flags); |
230 | 993295fe | Paolo Bonzini | if (ret <= 0) { |
231 | 993295fe | Paolo Bonzini | if (ret < 0 && errno == EINTR) { |
232 | 993295fe | Paolo Bonzini | continue;
|
233 | 993295fe | Paolo Bonzini | } |
234 | 993295fe | Paolo Bonzini | break;
|
235 | 993295fe | Paolo Bonzini | } |
236 | 993295fe | Paolo Bonzini | |
237 | 993295fe | Paolo Bonzini | count -= ret; |
238 | 993295fe | Paolo Bonzini | buf += ret; |
239 | 993295fe | Paolo Bonzini | total += ret; |
240 | 993295fe | Paolo Bonzini | } |
241 | 993295fe | Paolo Bonzini | |
242 | 993295fe | Paolo Bonzini | return total;
|
243 | 993295fe | Paolo Bonzini | } |