The Android Open Source Project | 8b23a6c | 2009-03-03 19:30:32 -0800 | [diff] [blame] | 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> |
David Turner | f7dd220 | 2010-09-10 10:59:22 +0200 | [diff] [blame] | 31 | |
| 32 | /* Needed early for CONFIG_BSD etc. */ |
| 33 | #include "config-host.h" |
| 34 | |
David 'Digit' Turner | 2c538c8 | 2010-05-10 16:48:20 -0700 | [diff] [blame] | 35 | #ifdef CONFIG_SOLARIS |
The Android Open Source Project | 8b23a6c | 2009-03-03 19:30:32 -0800 | [diff] [blame] | 36 | #include <sys/types.h> |
| 37 | #include <sys/statvfs.h> |
| 38 | #endif |
| 39 | |
David 'Digit' Turner | 2910f18 | 2010-05-10 18:48:35 -0700 | [diff] [blame] | 40 | #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 Turner | 315ceb8 | 2010-09-10 14:15:17 +0200 | [diff] [blame] | 48 | #ifdef CONFIG_ANDROID |
| 49 | #ifdef WIN32 |
| 50 | #include <winsock2.h> |
David 'Digit' Turner | 37a43dc | 2010-09-13 00:15:41 -0700 | [diff] [blame] | 51 | #include <stdint.h> |
David Turner | 315ceb8 | 2010-09-10 14:15:17 +0200 | [diff] [blame] | 52 | typedef int32_t socklen_t; |
| 53 | #else |
| 54 | #include <sys/socket.h> |
| 55 | #endif |
| 56 | #endif /* CONFIG_ANDROID */ |
| 57 | |
The Android Open Source Project | 8b23a6c | 2009-03-03 19:30:32 -0800 | [diff] [blame] | 58 | #include "qemu-common.h" |
| 59 | #include "sysemu.h" |
David Turner | f7dd220 | 2010-09-10 10:59:22 +0200 | [diff] [blame] | 60 | #include "qemu_socket.h" |
The Android Open Source Project | 8b23a6c | 2009-03-03 19:30:32 -0800 | [diff] [blame] | 61 | |
The Android Open Source Project | 8b23a6c | 2009-03-03 19:30:32 -0800 | [diff] [blame] | 62 | |
David Turner | f7dd220 | 2010-09-10 10:59:22 +0200 | [diff] [blame] | 63 | |
| 64 | /* |
| 65 | * Opens a file with FD_CLOEXEC set |
| 66 | */ |
| 67 | int 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 | */ |
| 103 | ssize_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 Turner | f7dd220 | 2010-09-10 10:59:22 +0200 | [diff] [blame] | 124 | /* |
| 125 | * Opens a socket with FD_CLOEXEC set |
| 126 | */ |
| 127 | int 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 | */ |
| 148 | int 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 Turner | b919805 | 2010-09-10 11:50:34 +0200 | [diff] [blame] | 165 | |
| 166 | #ifdef WIN32 |
| 167 | int asprintf( char **, char *, ... ); |
| 168 | int vasprintf( char **, char *, va_list ); |
| 169 | |
| 170 | int 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 | |
| 179 | int 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 |