1088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/* 2088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * os-posix-lib.c 3088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * 4088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard 5088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Copyright (c) 2010 Red Hat, Inc. 6088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * 7088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * QEMU library functions on POSIX which are shared between QEMU and 8088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * the QEMU tools. 9088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * 10088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy 11088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal 12088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * in the Software without restriction, including without limitation the rights 13088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is 15088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * furnished to do so, subject to the following conditions: 16088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * 17088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * The above copyright notice and this permission notice shall be included in 18088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * all copies or substantial portions of the Software. 19088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * 20088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * THE SOFTWARE. 27088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner */ 28088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 29088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "config-host.h" 30088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "sysemu.h" 31088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "trace.h" 32088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#include "qemu_socket.h" 33088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 34088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid *qemu_oom_check(void *ptr) 35088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 36088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (ptr == NULL) { 37088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); 38088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner abort(); 39088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 40088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return ptr; 41088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 42088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 43088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid *qemu_memalign(size_t alignment, size_t size) 44088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 45088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner void *ptr; 46088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if defined(_POSIX_C_SOURCE) && !defined(__sun__) 47088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int ret; 48088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ret = posix_memalign(&ptr, alignment, size); 49088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (ret != 0) { 50088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner fprintf(stderr, "Failed to allocate %zu B: %s\n", 51088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner size, strerror(ret)); 52088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner abort(); 53088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 54088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#elif defined(CONFIG_BSD) 55088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ptr = qemu_oom_check(valloc(size)); 56088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#else 57088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ptr = qemu_oom_check(memalign(alignment, size)); 58088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif 59088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner //trace_qemu_memalign(alignment, size, ptr); 60088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return ptr; 61088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 62088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 63088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/* alloc shared memory pages */ 64088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid *qemu_vmalloc(size_t size) 65088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 66088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return qemu_memalign(getpagesize(), size); 67088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 68088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 69088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid qemu_vfree(void *ptr) 70088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 71088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner //trace_qemu_vfree(ptr); 72088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner free(ptr); 73088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 74088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 75088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#if 0 /* in sockets.c */ 76088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid socket_set_nonblock(int fd) 77088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 78088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int f; 79088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner f = fcntl(fd, F_GETFL); 80088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner fcntl(fd, F_SETFL, f | O_NONBLOCK); 81088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 82088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif 83088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 84088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnervoid qemu_set_cloexec(int fd) 85088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 86088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int f; 87088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner f = fcntl(fd, F_GETFD); 88088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner fcntl(fd, F_SETFD, f | FD_CLOEXEC); 89088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 90088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 91088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner/* 92088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner * Creates a pipe with FD_CLOEXEC set on both file descriptors 93088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner */ 94088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerint qemu_pipe(int pipefd[2]) 95088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 96088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int ret; 97088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 98088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_PIPE2 99088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ret = pipe2(pipefd, O_CLOEXEC); 100088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (ret != -1 || errno != ENOSYS) { 101088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return ret; 102088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 103088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif 104088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ret = pipe(pipefd); 105088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (ret == 0) { 106088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner qemu_set_cloexec(pipefd[0]); 107088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner qemu_set_cloexec(pipefd[1]); 108088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 109088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 110088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return ret; 111088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 112088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 113088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turnerint qemu_utimensat(int dirfd, const char *path, const struct timespec *times, 114088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int flags) 115088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner{ 116088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner struct timeval tv[2], tv_now; 117088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner struct stat st; 118088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int i; 119088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#ifdef CONFIG_UTIMENSAT 120088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner int ret; 121088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 122088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner ret = utimensat(dirfd, path, times, flags); 123088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (ret != -1 || errno != ENOSYS) { 124088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return ret; 125088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 126088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner#endif 127088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner /* Fallback: use utimes() instead of utimensat() */ 128088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 129088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner /* happy if special cases */ 130088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) { 131088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return 0; 132088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 133088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) { 134088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return utimes(path, NULL); 135088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 136088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 137088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner /* prepare for hard cases */ 138088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) { 139088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner gettimeofday(&tv_now, NULL); 140088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 141088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) { 142088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner stat(path, &st); 143088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 144088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 145088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner for (i = 0; i < 2; i++) { 146088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner if (times[i].tv_nsec == UTIME_NOW) { 147088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_sec = tv_now.tv_sec; 148088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_usec = tv_now.tv_usec; 149088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } else if (times[i].tv_nsec == UTIME_OMIT) { 150088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime; 151088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_usec = 0; 152088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } else { 153088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_sec = times[i].tv_sec; 154088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner tv[i].tv_usec = times[i].tv_nsec / 1000; 155088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 156088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner } 157088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner 158088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner return utimes(path, &tv[0]); 159088edf82b3d34409ed9d9fd09ec1f7e9b933304fDavid 'Digit' Turner} 160