blob: 46c779d70ff905b880614be2ad8e3297fdbc9352 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * QEMU low level functions
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include <stdlib.h>
25#include <stdio.h>
26#include <stdarg.h>
27#include <string.h>
28#include <errno.h>
29#include <unistd.h>
30#include <fcntl.h>
David Turnerf7dd2202010-09-10 10:59:22 +020031
32/* Needed early for CONFIG_BSD etc. */
33#include "config-host.h"
34
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070035#ifdef CONFIG_SOLARIS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080036#include <sys/types.h>
37#include <sys/statvfs.h>
38#endif
39
David Turnerf7dd2202010-09-10 10:59:22 +020040#ifdef CONFIG_EVENTFD
41#include <sys/eventfd.h>
42#endif
David 'Digit' Turner2910f182010-05-10 18:48:35 -070043
44#ifdef _WIN32
45#include <windows.h>
46#elif defined(CONFIG_BSD)
47#include <stdlib.h>
48#else
49#include <malloc.h>
50#endif
51
David Turner315ceb82010-09-10 14:15:17 +020052#ifdef CONFIG_ANDROID
53#ifdef WIN32
54#include <winsock2.h>
David 'Digit' Turner37a43dc2010-09-13 00:15:41 -070055#include <stdint.h>
David Turner315ceb82010-09-10 14:15:17 +020056typedef int32_t socklen_t;
57#else
58#include <sys/socket.h>
59#endif
60#endif /* CONFIG_ANDROID */
61
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080062#include "qemu-common.h"
63#include "sysemu.h"
David Turnerf7dd2202010-09-10 10:59:22 +020064#include "qemu_socket.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080065
David 'Digit' Turner747f7d12011-01-06 22:24:26 +010066#if !defined(_POSIX_C_SOURCE) || defined(_WIN32) || defined(__sun__) || defined(__APPLE__)
David Turnerf7dd2202010-09-10 10:59:22 +020067static void *oom_check(void *ptr)
68{
69 if (ptr == NULL) {
70#if defined(_WIN32)
71 fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080072#else
David Turnerf7dd2202010-09-10 10:59:22 +020073 fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080074#endif
David Turnerf7dd2202010-09-10 10:59:22 +020075 abort();
76 }
77 return ptr;
78}
79#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080080
81#if defined(_WIN32)
82void *qemu_memalign(size_t alignment, size_t size)
83{
David Turnerf7dd2202010-09-10 10:59:22 +020084 if (!size) {
85 abort();
86 }
87 return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088}
89
90void *qemu_vmalloc(size_t size)
91{
92 /* FIXME: this is not exactly optimal solution since VirtualAlloc
93 has 64Kb granularity, but at least it guarantees us that the
94 memory is page aligned. */
David Turnerf7dd2202010-09-10 10:59:22 +020095 if (!size) {
96 abort();
97 }
98 return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080099}
100
101void qemu_vfree(void *ptr)
102{
103 VirtualFree(ptr, 0, MEM_RELEASE);
104}
105
106#else
107
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800108void *qemu_memalign(size_t alignment, size_t size)
109{
David 'Digit' Turner747f7d12011-01-06 22:24:26 +0100110#if defined(_POSIX_C_SOURCE) && !defined(__sun__) && !defined(__APPLE__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800111 int ret;
112 void *ptr;
113 ret = posix_memalign(&ptr, alignment, size);
David Turnerf7dd2202010-09-10 10:59:22 +0200114 if (ret != 0) {
115 fprintf(stderr, "Failed to allocate %zu B: %s\n",
116 size, strerror(ret));
117 abort();
118 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800119 return ptr;
David 'Digit' Turner2c538c82010-05-10 16:48:20 -0700120#elif defined(CONFIG_BSD)
David Turnerf7dd2202010-09-10 10:59:22 +0200121 return oom_check(valloc(size));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800122#else
David Turnerf7dd2202010-09-10 10:59:22 +0200123 return oom_check(memalign(alignment, size));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800124#endif
125}
126
127/* alloc shared memory pages */
128void *qemu_vmalloc(size_t size)
129{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700130 return qemu_memalign(getpagesize(), size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800131}
132
133void qemu_vfree(void *ptr)
134{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800135 free(ptr);
136}
137
138#endif
139
140int qemu_create_pidfile(const char *filename)
141{
142 char buffer[128];
143 int len;
144#ifndef _WIN32
145 int fd;
146
David Turnerf7dd2202010-09-10 10:59:22 +0200147 fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800148 if (fd == -1)
149 return -1;
150
151 if (lockf(fd, F_TLOCK, 0) == -1)
152 return -1;
153
154 len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
155 if (write(fd, buffer, len) != len)
156 return -1;
157#else
158 HANDLE file;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800159 OVERLAPPED overlap;
160 BOOL ret;
David Turnerf7dd2202010-09-10 10:59:22 +0200161 memset(&overlap, 0, sizeof(overlap));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800162
David Turnerf7dd2202010-09-10 10:59:22 +0200163 file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800164 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
165
166 if (file == INVALID_HANDLE_VALUE)
167 return -1;
168
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169 len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
170 ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
171 &overlap, NULL);
172 if (ret == 0)
173 return -1;
174#endif
175 return 0;
176}
177
178#ifdef _WIN32
179
David Turnerf7dd2202010-09-10 10:59:22 +0200180/* mingw32 needs ffs for compilations without optimization. */
181int ffs(int i)
182{
183 /* Use gcc's builtin ffs. */
184 return __builtin_ffs(i);
185}
186
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800187/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
188#define _W32_FT_OFFSET (116444736000000000ULL)
189
190int qemu_gettimeofday(qemu_timeval *tp)
191{
192 union {
193 unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
194 FILETIME ft;
195 } _now;
196
197 if(tp)
198 {
199 GetSystemTimeAsFileTime (&_now.ft);
200 tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
201 tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
202 }
203 /* Always return 0 as per Open Group Base Specifications Issue 6.
204 Do not set errno on error. */
205 return 0;
206}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800207#endif /* _WIN32 */
208
209
David Turnerf7dd2202010-09-10 10:59:22 +0200210#ifdef _WIN32
211#ifndef CONFIG_ANDROID
212void socket_set_nonblock(int fd)
213{
214 unsigned long opt = 1;
215 ioctlsocket(fd, FIONBIO, &opt);
216}
217#endif
218
219int inet_aton(const char *cp, struct in_addr *ia)
220{
221 uint32_t addr = inet_addr(cp);
222 if (addr == 0xffffffff)
223 return 0;
224 ia->s_addr = addr;
225 return 1;
226}
227
228void qemu_set_cloexec(int fd)
229{
230}
231
232#else
233
234#ifndef CONFIG_ANDROID
235void socket_set_nonblock(int fd)
236{
237 int f;
238 f = fcntl(fd, F_GETFL);
239 fcntl(fd, F_SETFL, f | O_NONBLOCK);
240}
241#endif
242
243void qemu_set_cloexec(int fd)
244{
245 int f;
246 f = fcntl(fd, F_GETFD);
247 fcntl(fd, F_SETFD, f | FD_CLOEXEC);
248}
249
250#endif
251
252/*
253 * Opens a file with FD_CLOEXEC set
254 */
255int qemu_open(const char *name, int flags, ...)
256{
257 int ret;
258 int mode = 0;
259
260 if (flags & O_CREAT) {
261 va_list ap;
262
263 va_start(ap, flags);
264 mode = va_arg(ap, int);
265 va_end(ap);
266 }
267
268#ifdef O_CLOEXEC
269 ret = open(name, flags | O_CLOEXEC, mode);
270#else
271 ret = open(name, flags, mode);
272 if (ret >= 0) {
273 qemu_set_cloexec(ret);
274 }
275#endif
276
277 return ret;
278}
279
280/*
281 * A variant of write(2) which handles partial write.
282 *
283 * Return the number of bytes transferred.
284 * Set errno if fewer than `count' bytes are written.
285 *
286 * This function don't work with non-blocking fd's.
287 * Any of the possibilities with non-bloking fd's is bad:
288 * - return a short write (then name is wrong)
289 * - busy wait adding (errno == EAGAIN) to the loop
290 */
291ssize_t qemu_write_full(int fd, const void *buf, size_t count)
292{
293 ssize_t ret = 0;
294 ssize_t total = 0;
295
296 while (count) {
297 ret = write(fd, buf, count);
298 if (ret < 0) {
299 if (errno == EINTR)
300 continue;
301 break;
302 }
303
304 count -= ret;
305 buf += ret;
306 total += ret;
307 }
308
309 return total;
310}
311
312#ifndef _WIN32
313/*
314 * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
315 */
316int qemu_eventfd(int fds[2])
317{
318#ifdef CONFIG_EVENTFD
319 int ret;
320
321 ret = eventfd(0, 0);
322 if (ret >= 0) {
323 fds[0] = ret;
324 qemu_set_cloexec(ret);
325 if ((fds[1] = dup(ret)) == -1) {
326 close(ret);
327 return -1;
328 }
329 qemu_set_cloexec(fds[1]);
330 return 0;
331 }
332
333 if (errno != ENOSYS) {
334 return -1;
335 }
336#endif
337
338 return qemu_pipe(fds);
339}
340
341/*
342 * Creates a pipe with FD_CLOEXEC set on both file descriptors
343 */
344int qemu_pipe(int pipefd[2])
345{
346 int ret;
347
348#ifdef CONFIG_PIPE2
349 ret = pipe2(pipefd, O_CLOEXEC);
350 if (ret != -1 || errno != ENOSYS) {
351 return ret;
352 }
353#endif
354 ret = pipe(pipefd);
355 if (ret == 0) {
356 qemu_set_cloexec(pipefd[0]);
357 qemu_set_cloexec(pipefd[1]);
358 }
359
360 return ret;
361}
362#endif
363
364/*
365 * Opens a socket with FD_CLOEXEC set
366 */
367int qemu_socket(int domain, int type, int protocol)
368{
369 int ret;
370
371#ifdef SOCK_CLOEXEC
372 ret = socket(domain, type | SOCK_CLOEXEC, protocol);
373 if (ret != -1 || errno != EINVAL) {
374 return ret;
375 }
376#endif
377 ret = socket(domain, type, protocol);
378 if (ret >= 0) {
379 qemu_set_cloexec(ret);
380 }
381
382 return ret;
383}
384
385/*
386 * Accept a connection and set FD_CLOEXEC
387 */
388int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
389{
390 int ret;
391
392#ifdef CONFIG_ACCEPT4
393 ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
394 if (ret != -1 || errno != ENOSYS) {
395 return ret;
396 }
397#endif
398 ret = accept(s, addr, addrlen);
399 if (ret >= 0) {
400 qemu_set_cloexec(ret);
401 }
402
403 return ret;
404}
David Turnerb9198052010-09-10 11:50:34 +0200405
406#ifdef WIN32
407int asprintf( char **, char *, ... );
408int vasprintf( char **, char *, va_list );
409
410int vasprintf( char **sptr, char *fmt, va_list argv )
411{
412 int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv );
413 if( (wanted > 0) && ((*sptr = malloc( 1 + wanted )) != NULL) )
414 return vsprintf( *sptr, fmt, argv );
415
416 return wanted;
417}
418
419int asprintf( char **sptr, char *fmt, ... )
420{
421 int retval;
422 va_list argv;
423 va_start( argv, fmt );
424 retval = vasprintf( sptr, fmt, argv );
425 va_end( argv );
426 return retval;
427}
428#endif