Home | History | Annotate | Download | only in qemu
      1 /*
      2  * os-posix-lib.c
      3  *
      4  * Copyright (c) 2003-2008 Fabrice Bellard
      5  * Copyright (c) 2010 Red Hat, Inc.
      6  *
      7  * QEMU library functions on POSIX which are shared between QEMU and
      8  * the QEMU tools.
      9  *
     10  * Permission is hereby granted, free of charge, to any person obtaining a copy
     11  * of this software and associated documentation files (the "Software"), to deal
     12  * in the Software without restriction, including without limitation the rights
     13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     14  * copies of the Software, and to permit persons to whom the Software is
     15  * furnished to do so, subject to the following conditions:
     16  *
     17  * The above copyright notice and this permission notice shall be included in
     18  * all copies or substantial portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     26  * THE SOFTWARE.
     27  */
     28 
     29 #include "config-host.h"
     30 #include "sysemu.h"
     31 #include "trace.h"
     32 #include "qemu_socket.h"
     33 
     34 void *qemu_oom_check(void *ptr)
     35 {
     36     if (ptr == NULL) {
     37         fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
     38         abort();
     39     }
     40     return ptr;
     41 }
     42 
     43 void *qemu_memalign(size_t alignment, size_t size)
     44 {
     45     void *ptr;
     46 #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
     47     int ret;
     48     ret = posix_memalign(&ptr, alignment, size);
     49     if (ret != 0) {
     50         fprintf(stderr, "Failed to allocate %zu B: %s\n",
     51                 size, strerror(ret));
     52         abort();
     53     }
     54 #elif defined(CONFIG_BSD)
     55     ptr = qemu_oom_check(valloc(size));
     56 #else
     57     ptr = qemu_oom_check(memalign(alignment, size));
     58 #endif
     59     //trace_qemu_memalign(alignment, size, ptr);
     60     return ptr;
     61 }
     62 
     63 /* alloc shared memory pages */
     64 void *qemu_vmalloc(size_t size)
     65 {
     66     return qemu_memalign(getpagesize(), size);
     67 }
     68 
     69 void qemu_vfree(void *ptr)
     70 {
     71     //trace_qemu_vfree(ptr);
     72     free(ptr);
     73 }
     74 
     75 #if 0 /* in sockets.c */
     76 void socket_set_nonblock(int fd)
     77 {
     78     int f;
     79     f = fcntl(fd, F_GETFL);
     80     fcntl(fd, F_SETFL, f | O_NONBLOCK);
     81 }
     82 #endif
     83 
     84 void qemu_set_cloexec(int fd)
     85 {
     86     int f;
     87     f = fcntl(fd, F_GETFD);
     88     fcntl(fd, F_SETFD, f | FD_CLOEXEC);
     89 }
     90 
     91 /*
     92  * Creates a pipe with FD_CLOEXEC set on both file descriptors
     93  */
     94 int qemu_pipe(int pipefd[2])
     95 {
     96     int ret;
     97 
     98 #ifdef CONFIG_PIPE2
     99     ret = pipe2(pipefd, O_CLOEXEC);
    100     if (ret != -1 || errno != ENOSYS) {
    101         return ret;
    102     }
    103 #endif
    104     ret = pipe(pipefd);
    105     if (ret == 0) {
    106         qemu_set_cloexec(pipefd[0]);
    107         qemu_set_cloexec(pipefd[1]);
    108     }
    109 
    110     return ret;
    111 }
    112 
    113 int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
    114                    int flags)
    115 {
    116     struct timeval tv[2], tv_now;
    117     struct stat st;
    118     int i;
    119 #ifdef CONFIG_UTIMENSAT
    120     int ret;
    121 
    122     ret = utimensat(dirfd, path, times, flags);
    123     if (ret != -1 || errno != ENOSYS) {
    124         return ret;
    125     }
    126 #endif
    127     /* Fallback: use utimes() instead of utimensat() */
    128 
    129     /* happy if special cases */
    130     if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
    131         return 0;
    132     }
    133     if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
    134         return utimes(path, NULL);
    135     }
    136 
    137     /* prepare for hard cases */
    138     if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
    139         gettimeofday(&tv_now, NULL);
    140     }
    141     if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
    142         stat(path, &st);
    143     }
    144 
    145     for (i = 0; i < 2; i++) {
    146         if (times[i].tv_nsec == UTIME_NOW) {
    147             tv[i].tv_sec = tv_now.tv_sec;
    148             tv[i].tv_usec = tv_now.tv_usec;
    149         } else if (times[i].tv_nsec == UTIME_OMIT) {
    150             tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
    151             tv[i].tv_usec = 0;
    152         } else {
    153             tv[i].tv_sec = times[i].tv_sec;
    154             tv[i].tv_usec = times[i].tv_nsec / 1000;
    155         }
    156     }
    157 
    158     return utimes(path, &tv[0]);
    159 }
    160