blob: 5879eed016af53cdb1bb1ce8725aebc8f08a31ed [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 'Digit' Turner2910f182010-05-10 18:48:35 -070040#ifdef _WIN32
41#include <windows.h>
42#elif defined(CONFIG_BSD)
43#include <stdlib.h>
44#else
45#include <malloc.h>
46#endif
47
David Turner315ceb82010-09-10 14:15:17 +020048#ifdef CONFIG_ANDROID
49#ifdef WIN32
50#include <winsock2.h>
David 'Digit' Turner37a43dc2010-09-13 00:15:41 -070051#include <stdint.h>
David Turner315ceb82010-09-10 14:15:17 +020052typedef int32_t socklen_t;
53#else
54#include <sys/socket.h>
55#endif
56#endif /* CONFIG_ANDROID */
57
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080058#include "qemu-common.h"
59#include "sysemu.h"
David Turnerf7dd2202010-09-10 10:59:22 +020060#include "qemu_socket.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080061
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080062
David Turnerf7dd2202010-09-10 10:59:22 +020063
64/*
65 * Opens a file with FD_CLOEXEC set
66 */
67int qemu_open(const char *name, int flags, ...)
68{
69 int ret;
70 int mode = 0;
71
72 if (flags & O_CREAT) {
73 va_list ap;
74
75 va_start(ap, flags);
76 mode = va_arg(ap, int);
77 va_end(ap);
78 }
79
80#ifdef O_CLOEXEC
81 ret = open(name, flags | O_CLOEXEC, mode);
82#else
83 ret = open(name, flags, mode);
84 if (ret >= 0) {
85 qemu_set_cloexec(ret);
86 }
87#endif
88
89 return ret;
90}
91
92/*
93 * A variant of write(2) which handles partial write.
94 *
95 * Return the number of bytes transferred.
96 * Set errno if fewer than `count' bytes are written.
97 *
98 * This function don't work with non-blocking fd's.
99 * Any of the possibilities with non-bloking fd's is bad:
100 * - return a short write (then name is wrong)
101 * - busy wait adding (errno == EAGAIN) to the loop
102 */
103ssize_t qemu_write_full(int fd, const void *buf, size_t count)
104{
105 ssize_t ret = 0;
106 ssize_t total = 0;
107
108 while (count) {
109 ret = write(fd, buf, count);
110 if (ret < 0) {
111 if (errno == EINTR)
112 continue;
113 break;
114 }
115
116 count -= ret;
117 buf += ret;
118 total += ret;
119 }
120
121 return total;
122}
123
David Turnerf7dd2202010-09-10 10:59:22 +0200124/*
125 * Opens a socket with FD_CLOEXEC set
126 */
127int qemu_socket(int domain, int type, int protocol)
128{
129 int ret;
130
131#ifdef SOCK_CLOEXEC
132 ret = socket(domain, type | SOCK_CLOEXEC, protocol);
133 if (ret != -1 || errno != EINVAL) {
134 return ret;
135 }
136#endif
137 ret = socket(domain, type, protocol);
138 if (ret >= 0) {
139 qemu_set_cloexec(ret);
140 }
141
142 return ret;
143}
144
145/*
146 * Accept a connection and set FD_CLOEXEC
147 */
148int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
149{
150 int ret;
151
152#ifdef CONFIG_ACCEPT4
153 ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
154 if (ret != -1 || errno != ENOSYS) {
155 return ret;
156 }
157#endif
158 ret = accept(s, addr, addrlen);
159 if (ret >= 0) {
160 qemu_set_cloexec(ret);
161 }
162
163 return ret;
164}
David Turnerb9198052010-09-10 11:50:34 +0200165
166#ifdef WIN32
167int asprintf( char **, char *, ... );
168int vasprintf( char **, char *, va_list );
169
170int vasprintf( char **sptr, char *fmt, va_list argv )
171{
172 int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv );
173 if( (wanted > 0) && ((*sptr = malloc( 1 + wanted )) != NULL) )
174 return vsprintf( *sptr, fmt, argv );
175
176 return wanted;
177}
178
179int asprintf( char **sptr, char *fmt, ... )
180{
181 int retval;
182 va_list argv;
183 va_start( argv, fmt );
184 retval = vasprintf( sptr, fmt, argv );
185 va_end( argv );
186 return retval;
187}
188#endif