root / osdep.c @ 7b5f699d
History | View | Annotate | Download (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 | dfe5fff3 | Juan Quintela | #ifdef CONFIG_SOLARIS
|
32 | 605686cd | ths | #include <sys/types.h> |
33 | 605686cd | ths | #include <sys/statvfs.h> |
34 | 605686cd | ths | #endif
|
35 | ea88812f | bellard | |
36 | 71e72a19 | Juan Quintela | /* Needed early for CONFIG_BSD etc. */
|
37 | d40cdb10 | blueswir1 | #include "config-host.h" |
38 | d40cdb10 | blueswir1 | |
39 | 6e4255f6 | bellard | #ifdef _WIN32
|
40 | 6e4255f6 | bellard | #include <windows.h> |
41 | 71e72a19 | Juan Quintela | #elif defined(CONFIG_BSD)
|
42 | 194884dd | bellard | #include <stdlib.h> |
43 | 194884dd | bellard | #else
|
44 | 49b470eb | bellard | #include <malloc.h> |
45 | 194884dd | bellard | #endif
|
46 | 49b470eb | bellard | |
47 | 511d2b14 | blueswir1 | #include "qemu-common.h" |
48 | 511d2b14 | blueswir1 | #include "sysemu.h" |
49 | 03ff3ca3 | aliguori | #include "qemu_socket.h" |
50 | 03ff3ca3 | aliguori | |
51 | d741429a | Blue Swirl | #if !defined(_POSIX_C_SOURCE) || defined(_WIN32) || defined(__sun__)
|
52 | d644f8be | malc | static void *oom_check(void *ptr) |
53 | d644f8be | malc | { |
54 | d644f8be | malc | if (ptr == NULL) { |
55 | d644f8be | malc | abort(); |
56 | d644f8be | malc | } |
57 | d644f8be | malc | return ptr;
|
58 | d644f8be | malc | } |
59 | d644f8be | malc | #endif
|
60 | d644f8be | malc | |
61 | 6e4255f6 | bellard | #if defined(_WIN32)
|
62 | 33f00271 | balrog | void *qemu_memalign(size_t alignment, size_t size)
|
63 | 33f00271 | balrog | { |
64 | d644f8be | malc | if (!size) {
|
65 | d644f8be | malc | abort(); |
66 | d644f8be | malc | } |
67 | d644f8be | malc | return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); |
68 | 33f00271 | balrog | } |
69 | 6e4255f6 | bellard | |
70 | 6e4255f6 | bellard | void *qemu_vmalloc(size_t size)
|
71 | 6e4255f6 | bellard | { |
72 | 6e4255f6 | bellard | /* FIXME: this is not exactly optimal solution since VirtualAlloc
|
73 | 6e4255f6 | bellard | has 64Kb granularity, but at least it guarantees us that the
|
74 | 6e4255f6 | bellard | memory is page aligned. */
|
75 | d644f8be | malc | if (!size) {
|
76 | d644f8be | malc | abort(); |
77 | d644f8be | malc | } |
78 | d644f8be | malc | return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); |
79 | 6e4255f6 | bellard | } |
80 | 6e4255f6 | bellard | |
81 | 6e4255f6 | bellard | void qemu_vfree(void *ptr) |
82 | 6e4255f6 | bellard | { |
83 | 6e4255f6 | bellard | VirtualFree(ptr, 0, MEM_RELEASE);
|
84 | 6e4255f6 | bellard | } |
85 | 6e4255f6 | bellard | |
86 | 6cb7ee85 | pbrook | #else
|
87 | 6cb7ee85 | pbrook | |
88 | 33f00271 | balrog | void *qemu_memalign(size_t alignment, size_t size)
|
89 | 33f00271 | balrog | { |
90 | d741429a | Blue Swirl | #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
|
91 | 33f00271 | balrog | int ret;
|
92 | 33f00271 | balrog | void *ptr;
|
93 | 33f00271 | balrog | ret = posix_memalign(&ptr, alignment, size); |
94 | 33f00271 | balrog | if (ret != 0) |
95 | d644f8be | malc | abort(); |
96 | 33f00271 | balrog | return ptr;
|
97 | 71e72a19 | Juan Quintela | #elif defined(CONFIG_BSD)
|
98 | d644f8be | malc | return oom_check(valloc(size));
|
99 | 33f00271 | balrog | #else
|
100 | d644f8be | malc | return oom_check(memalign(alignment, size));
|
101 | 33f00271 | balrog | #endif
|
102 | 33f00271 | balrog | } |
103 | 33f00271 | balrog | |
104 | 49b470eb | bellard | /* alloc shared memory pages */
|
105 | 49b470eb | bellard | void *qemu_vmalloc(size_t size)
|
106 | 49b470eb | bellard | { |
107 | 48253bd8 | malc | return qemu_memalign(getpagesize(), size);
|
108 | 49b470eb | bellard | } |
109 | 49b470eb | bellard | |
110 | 49b470eb | bellard | void qemu_vfree(void *ptr) |
111 | 49b470eb | bellard | { |
112 | 49b470eb | bellard | free(ptr); |
113 | 49b470eb | bellard | } |
114 | 49b470eb | bellard | |
115 | 49b470eb | bellard | #endif
|
116 | 49b470eb | bellard | |
117 | aa26bb2d | ths | int qemu_create_pidfile(const char *filename) |
118 | aa26bb2d | ths | { |
119 | aa26bb2d | ths | char buffer[128]; |
120 | aa26bb2d | ths | int len;
|
121 | aa26bb2d | ths | #ifndef _WIN32
|
122 | aa26bb2d | ths | int fd;
|
123 | aa26bb2d | ths | |
124 | 40ff6d7e | Kevin Wolf | fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
|
125 | aa26bb2d | ths | if (fd == -1) |
126 | aa26bb2d | ths | return -1; |
127 | aa26bb2d | ths | |
128 | aa26bb2d | ths | if (lockf(fd, F_TLOCK, 0) == -1) |
129 | aa26bb2d | ths | return -1; |
130 | aa26bb2d | ths | |
131 | aa26bb2d | ths | len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); |
132 | aa26bb2d | ths | if (write(fd, buffer, len) != len)
|
133 | aa26bb2d | ths | return -1; |
134 | aa26bb2d | ths | #else
|
135 | aa26bb2d | ths | HANDLE file; |
136 | aa26bb2d | ths | OVERLAPPED overlap; |
137 | aa26bb2d | ths | BOOL ret; |
138 | 099fe236 | Juha Riihimäki | memset(&overlap, 0, sizeof(overlap)); |
139 | aa26bb2d | ths | |
140 | 099fe236 | Juha Riihimäki | file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
141 | aa26bb2d | ths | OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
142 | aa26bb2d | ths | |
143 | aa26bb2d | ths | if (file == INVALID_HANDLE_VALUE)
|
144 | aa26bb2d | ths | return -1; |
145 | aa26bb2d | ths | |
146 | aa26bb2d | ths | len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); |
147 | 5fafdf24 | ths | ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, |
148 | aa26bb2d | ths | &overlap, NULL);
|
149 | aa26bb2d | ths | if (ret == 0) |
150 | aa26bb2d | ths | return -1; |
151 | aa26bb2d | ths | #endif
|
152 | aa26bb2d | ths | return 0; |
153 | aa26bb2d | ths | } |
154 | 29b3a662 | pbrook | |
155 | 29b3a662 | pbrook | #ifdef _WIN32
|
156 | 29b3a662 | pbrook | |
157 | 29b3a662 | pbrook | /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
|
158 | 29b3a662 | pbrook | #define _W32_FT_OFFSET (116444736000000000ULL) |
159 | 29b3a662 | pbrook | |
160 | 29b3a662 | pbrook | int qemu_gettimeofday(qemu_timeval *tp)
|
161 | 29b3a662 | pbrook | { |
162 | 29b3a662 | pbrook | union {
|
163 | 29b3a662 | pbrook | unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ |
164 | 29b3a662 | pbrook | FILETIME ft; |
165 | 29b3a662 | pbrook | } _now; |
166 | 29b3a662 | pbrook | |
167 | 29b3a662 | pbrook | if(tp)
|
168 | 29b3a662 | pbrook | { |
169 | 29b3a662 | pbrook | GetSystemTimeAsFileTime (&_now.ft); |
170 | 29b3a662 | pbrook | tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); |
171 | 29b3a662 | pbrook | tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); |
172 | 29b3a662 | pbrook | } |
173 | 29b3a662 | pbrook | /* Always return 0 as per Open Group Base Specifications Issue 6.
|
174 | 29b3a662 | pbrook | Do not set errno on error. */
|
175 | 29b3a662 | pbrook | return 0; |
176 | 29b3a662 | pbrook | } |
177 | 29b3a662 | pbrook | #endif /* _WIN32 */ |
178 | 03ff3ca3 | aliguori | |
179 | 03ff3ca3 | aliguori | |
180 | 03ff3ca3 | aliguori | #ifdef _WIN32
|
181 | 03ff3ca3 | aliguori | void socket_set_nonblock(int fd) |
182 | 03ff3ca3 | aliguori | { |
183 | 03ff3ca3 | aliguori | unsigned long opt = 1; |
184 | 03ff3ca3 | aliguori | ioctlsocket(fd, FIONBIO, &opt); |
185 | 03ff3ca3 | aliguori | } |
186 | 03ff3ca3 | aliguori | |
187 | 03ff3ca3 | aliguori | int inet_aton(const char *cp, struct in_addr *ia) |
188 | 03ff3ca3 | aliguori | { |
189 | 03ff3ca3 | aliguori | uint32_t addr = inet_addr(cp); |
190 | 03ff3ca3 | aliguori | if (addr == 0xffffffff) |
191 | 03ff3ca3 | aliguori | return 0; |
192 | 03ff3ca3 | aliguori | ia->s_addr = addr; |
193 | 03ff3ca3 | aliguori | return 1; |
194 | 03ff3ca3 | aliguori | } |
195 | 40ff6d7e | Kevin Wolf | |
196 | 40ff6d7e | Kevin Wolf | void qemu_set_cloexec(int fd) |
197 | 40ff6d7e | Kevin Wolf | { |
198 | 40ff6d7e | Kevin Wolf | } |
199 | 40ff6d7e | Kevin Wolf | |
200 | 03ff3ca3 | aliguori | #else
|
201 | 40ff6d7e | Kevin Wolf | |
202 | 03ff3ca3 | aliguori | void socket_set_nonblock(int fd) |
203 | 03ff3ca3 | aliguori | { |
204 | 03ff3ca3 | aliguori | int f;
|
205 | 03ff3ca3 | aliguori | f = fcntl(fd, F_GETFL); |
206 | 03ff3ca3 | aliguori | fcntl(fd, F_SETFL, f | O_NONBLOCK); |
207 | 03ff3ca3 | aliguori | } |
208 | 40ff6d7e | Kevin Wolf | |
209 | 40ff6d7e | Kevin Wolf | void qemu_set_cloexec(int fd) |
210 | 40ff6d7e | Kevin Wolf | { |
211 | 40ff6d7e | Kevin Wolf | int f;
|
212 | 40ff6d7e | Kevin Wolf | f = fcntl(fd, F_GETFD); |
213 | 40ff6d7e | Kevin Wolf | fcntl(fd, F_SETFD, f | FD_CLOEXEC); |
214 | 40ff6d7e | Kevin Wolf | } |
215 | 40ff6d7e | Kevin Wolf | |
216 | 40ff6d7e | Kevin Wolf | #endif
|
217 | 40ff6d7e | Kevin Wolf | |
218 | 40ff6d7e | Kevin Wolf | /*
|
219 | 40ff6d7e | Kevin Wolf | * Opens a file with FD_CLOEXEC set
|
220 | 40ff6d7e | Kevin Wolf | */
|
221 | 40ff6d7e | Kevin Wolf | int qemu_open(const char *name, int flags, ...) |
222 | 40ff6d7e | Kevin Wolf | { |
223 | 40ff6d7e | Kevin Wolf | int ret;
|
224 | 40ff6d7e | Kevin Wolf | int mode = 0; |
225 | 40ff6d7e | Kevin Wolf | |
226 | 40ff6d7e | Kevin Wolf | if (flags & O_CREAT) {
|
227 | 40ff6d7e | Kevin Wolf | va_list ap; |
228 | 40ff6d7e | Kevin Wolf | |
229 | 40ff6d7e | Kevin Wolf | va_start(ap, flags); |
230 | 40ff6d7e | Kevin Wolf | mode = va_arg(ap, int);
|
231 | 40ff6d7e | Kevin Wolf | va_end(ap); |
232 | 40ff6d7e | Kevin Wolf | } |
233 | 40ff6d7e | Kevin Wolf | |
234 | 40ff6d7e | Kevin Wolf | #ifdef O_CLOEXEC
|
235 | 40ff6d7e | Kevin Wolf | ret = open(name, flags | O_CLOEXEC, mode); |
236 | 40ff6d7e | Kevin Wolf | #else
|
237 | 40ff6d7e | Kevin Wolf | ret = open(name, flags, mode); |
238 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
239 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
240 | 40ff6d7e | Kevin Wolf | } |
241 | 03ff3ca3 | aliguori | #endif
|
242 | 40ff6d7e | Kevin Wolf | |
243 | 40ff6d7e | Kevin Wolf | return ret;
|
244 | 40ff6d7e | Kevin Wolf | } |
245 | 40ff6d7e | Kevin Wolf | |
246 | 7b5f699d | Kirill A. Shutemov | /*
|
247 | 7b5f699d | Kirill A. Shutemov | * A variant of write(2) which handles partial write.
|
248 | 7b5f699d | Kirill A. Shutemov | *
|
249 | 7b5f699d | Kirill A. Shutemov | * Return the number of bytes transferred.
|
250 | 7b5f699d | Kirill A. Shutemov | * Set errno if fewer than `count' bytes are written.
|
251 | 7b5f699d | Kirill A. Shutemov | */
|
252 | 7b5f699d | Kirill A. Shutemov | ssize_t qemu_write_full(int fd, const void *buf, size_t count) |
253 | 7b5f699d | Kirill A. Shutemov | { |
254 | 7b5f699d | Kirill A. Shutemov | ssize_t ret = 0;
|
255 | 7b5f699d | Kirill A. Shutemov | ssize_t total = 0;
|
256 | 7b5f699d | Kirill A. Shutemov | |
257 | 7b5f699d | Kirill A. Shutemov | while (count) {
|
258 | 7b5f699d | Kirill A. Shutemov | ret = write(fd, buf, count); |
259 | 7b5f699d | Kirill A. Shutemov | if (ret < 0) { |
260 | 7b5f699d | Kirill A. Shutemov | if (errno == EINTR)
|
261 | 7b5f699d | Kirill A. Shutemov | continue;
|
262 | 7b5f699d | Kirill A. Shutemov | break;
|
263 | 7b5f699d | Kirill A. Shutemov | } |
264 | 7b5f699d | Kirill A. Shutemov | |
265 | 7b5f699d | Kirill A. Shutemov | count -= ret; |
266 | 7b5f699d | Kirill A. Shutemov | buf += ret; |
267 | 7b5f699d | Kirill A. Shutemov | total += ret; |
268 | 7b5f699d | Kirill A. Shutemov | } |
269 | 7b5f699d | Kirill A. Shutemov | |
270 | 7b5f699d | Kirill A. Shutemov | return total;
|
271 | 7b5f699d | Kirill A. Shutemov | } |
272 | 7b5f699d | Kirill A. Shutemov | |
273 | 40ff6d7e | Kevin Wolf | #ifndef _WIN32
|
274 | 40ff6d7e | Kevin Wolf | /*
|
275 | 40ff6d7e | Kevin Wolf | * Creates a pipe with FD_CLOEXEC set on both file descriptors
|
276 | 40ff6d7e | Kevin Wolf | */
|
277 | 40ff6d7e | Kevin Wolf | int qemu_pipe(int pipefd[2]) |
278 | 40ff6d7e | Kevin Wolf | { |
279 | 40ff6d7e | Kevin Wolf | int ret;
|
280 | 40ff6d7e | Kevin Wolf | |
281 | 40ff6d7e | Kevin Wolf | #ifdef CONFIG_PIPE2
|
282 | 40ff6d7e | Kevin Wolf | ret = pipe2(pipefd, O_CLOEXEC); |
283 | 3a03bfa5 | Andre Przywara | if (ret != -1 || errno != ENOSYS) { |
284 | 3a03bfa5 | Andre Przywara | return ret;
|
285 | 3a03bfa5 | Andre Przywara | } |
286 | 3a03bfa5 | Andre Przywara | #endif
|
287 | 40ff6d7e | Kevin Wolf | ret = pipe(pipefd); |
288 | 40ff6d7e | Kevin Wolf | if (ret == 0) { |
289 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(pipefd[0]);
|
290 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(pipefd[1]);
|
291 | 40ff6d7e | Kevin Wolf | } |
292 | 40ff6d7e | Kevin Wolf | |
293 | 40ff6d7e | Kevin Wolf | return ret;
|
294 | 40ff6d7e | Kevin Wolf | } |
295 | 40ff6d7e | Kevin Wolf | #endif
|
296 | 40ff6d7e | Kevin Wolf | |
297 | 40ff6d7e | Kevin Wolf | /*
|
298 | 40ff6d7e | Kevin Wolf | * Opens a socket with FD_CLOEXEC set
|
299 | 40ff6d7e | Kevin Wolf | */
|
300 | 40ff6d7e | Kevin Wolf | int qemu_socket(int domain, int type, int protocol) |
301 | 40ff6d7e | Kevin Wolf | { |
302 | 40ff6d7e | Kevin Wolf | int ret;
|
303 | 40ff6d7e | Kevin Wolf | |
304 | 40ff6d7e | Kevin Wolf | #ifdef SOCK_CLOEXEC
|
305 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type | SOCK_CLOEXEC, protocol); |
306 | 3a03bfa5 | Andre Przywara | if (ret != -1 || errno != EINVAL) { |
307 | 3a03bfa5 | Andre Przywara | return ret;
|
308 | 3a03bfa5 | Andre Przywara | } |
309 | 3a03bfa5 | Andre Przywara | #endif
|
310 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type, protocol); |
311 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
312 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
313 | 40ff6d7e | Kevin Wolf | } |
314 | 40ff6d7e | Kevin Wolf | |
315 | 40ff6d7e | Kevin Wolf | return ret;
|
316 | 40ff6d7e | Kevin Wolf | } |
317 | 40ff6d7e | Kevin Wolf | |
318 | 40ff6d7e | Kevin Wolf | /*
|
319 | 40ff6d7e | Kevin Wolf | * Accept a connection and set FD_CLOEXEC
|
320 | 40ff6d7e | Kevin Wolf | */
|
321 | 40ff6d7e | Kevin Wolf | int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) |
322 | 40ff6d7e | Kevin Wolf | { |
323 | 40ff6d7e | Kevin Wolf | int ret;
|
324 | 40ff6d7e | Kevin Wolf | |
325 | 40ff6d7e | Kevin Wolf | #ifdef CONFIG_ACCEPT4
|
326 | 40ff6d7e | Kevin Wolf | ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); |
327 | 347ed55c | Kevin Wolf | if (ret != -1 || errno != ENOSYS) { |
328 | 3a03bfa5 | Andre Przywara | return ret;
|
329 | 3a03bfa5 | Andre Przywara | } |
330 | 3a03bfa5 | Andre Przywara | #endif
|
331 | 40ff6d7e | Kevin Wolf | ret = accept(s, addr, addrlen); |
332 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
333 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
334 | 40ff6d7e | Kevin Wolf | } |
335 | 40ff6d7e | Kevin Wolf | |
336 | 40ff6d7e | Kevin Wolf | return ret;
|
337 | 40ff6d7e | Kevin Wolf | } |