1/*
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>
31
32/* Needed early for CONFIG_BSD etc. */
33#include "config-host.h"
34
35#if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
36#include <sys/mman.h>
37#endif
38
39#ifdef CONFIG_SOLARIS
40#include <sys/types.h>
41#include <sys/statvfs.h>
42/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
43   discussion about Solaris header problems */
44extern int madvise(caddr_t, size_t, int);
45#endif
46
47#ifdef _WIN32
48#include <windows.h>
49#elif defined(CONFIG_BSD)
50#include <stdlib.h>
51#else
52#include <malloc.h>
53#endif
54
55#ifdef CONFIG_ANDROID
56#ifdef WIN32
57#include <winsock2.h>
58#include <stdint.h>
59typedef int32_t socklen_t;
60#else
61#include <sys/socket.h>
62#endif
63#endif /* CONFIG_ANDROID */
64
65#include "qemu-common.h"
66#include "sysemu.h"
67#include "qemu_socket.h"
68
69int qemu_madvise(void *addr, size_t len, int advice)
70{
71    if (advice == QEMU_MADV_INVALID) {
72        errno = EINVAL;
73        return -1;
74    }
75#if defined(CONFIG_MADVISE)
76    return madvise(addr, len, advice);
77#elif defined(CONFIG_POSIX_MADVISE)
78    return posix_madvise(addr, len, advice);
79#else
80    errno = EINVAL;
81    return -1;
82#endif
83}
84
85
86/*
87 * Opens a file with FD_CLOEXEC set
88 */
89int qemu_open(const char *name, int flags, ...)
90{
91    int ret;
92    int mode = 0;
93
94    if (flags & O_CREAT) {
95        va_list ap;
96
97        va_start(ap, flags);
98        mode = va_arg(ap, int);
99        va_end(ap);
100    }
101
102#ifdef O_CLOEXEC
103    ret = open(name, flags | O_CLOEXEC, mode);
104#else
105    ret = open(name, flags, mode);
106    if (ret >= 0) {
107        qemu_set_cloexec(ret);
108    }
109#endif
110
111    return ret;
112}
113
114/*
115 * A variant of write(2) which handles partial write.
116 *
117 * Return the number of bytes transferred.
118 * Set errno if fewer than `count' bytes are written.
119 *
120 * This function don't work with non-blocking fd's.
121 * Any of the possibilities with non-bloking fd's is bad:
122 *   - return a short write (then name is wrong)
123 *   - busy wait adding (errno == EAGAIN) to the loop
124 */
125ssize_t qemu_write_full(int fd, const void *buf, size_t count)
126{
127    ssize_t ret = 0;
128    ssize_t total = 0;
129
130    while (count) {
131        ret = write(fd, buf, count);
132        if (ret < 0) {
133            if (errno == EINTR)
134                continue;
135            break;
136        }
137
138        count -= ret;
139        buf += ret;
140        total += ret;
141    }
142
143    return total;
144}
145
146/*
147 * Opens a socket with FD_CLOEXEC set
148 */
149int qemu_socket(int domain, int type, int protocol)
150{
151    int ret;
152
153#ifdef SOCK_CLOEXEC
154    ret = socket(domain, type | SOCK_CLOEXEC, protocol);
155    if (ret != -1 || errno != EINVAL) {
156        return ret;
157    }
158#endif
159    ret = socket(domain, type, protocol);
160    if (ret >= 0) {
161        qemu_set_cloexec(ret);
162    }
163
164    return ret;
165}
166
167/*
168 * Accept a connection and set FD_CLOEXEC
169 */
170int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
171{
172    int ret;
173
174#ifdef CONFIG_ACCEPT4
175    ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
176    if (ret != -1 || errno != ENOSYS) {
177        return ret;
178    }
179#endif
180    ret = accept(s, addr, addrlen);
181    if (ret >= 0) {
182        qemu_set_cloexec(ret);
183    }
184
185    return ret;
186}
187
188#ifdef WIN32
189int asprintf( char **, char *, ... );
190int vasprintf( char **, char *, va_list );
191
192int vasprintf( char **sptr, char *fmt, va_list argv )
193{
194    int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv );
195    if( (wanted > 0) && ((*sptr = malloc( 1 + wanted )) != NULL) )
196        return vsprintf( *sptr, fmt, argv );
197
198    return wanted;
199}
200
201int asprintf( char **sptr, char *fmt, ... )
202{
203    int retval;
204    va_list argv;
205    va_start( argv, fmt );
206    retval = vasprintf( sptr, fmt, argv );
207    va_end( argv );
208    return retval;
209}
210#endif
211