Home | History | Annotate | Download | only in qemu
      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 */
     44 extern 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>
     59 typedef 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 
     69 int 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  */
     89 int 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  */
    125 ssize_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  */
    149 int 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  */
    170 int 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
    189 int asprintf( char **, char *, ... );
    190 int vasprintf( char **, char *, va_list );
    191 
    192 int 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 
    201 int 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