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