root / osdep.c @ dc786bc9
History | View | Annotate | Download (5 kB)
1 | ea88812f | bellard | /*
|
---|---|---|---|
2 | ea88812f | bellard | * QEMU low level functions
|
3 | 5fafdf24 | ths | *
|
4 | ea88812f | bellard | * Copyright (c) 2003 Fabrice Bellard
|
5 | 5fafdf24 | ths | *
|
6 | ea88812f | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | ea88812f | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | ea88812f | bellard | * in the Software without restriction, including without limitation the rights
|
9 | ea88812f | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | ea88812f | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | ea88812f | bellard | * furnished to do so, subject to the following conditions:
|
12 | ea88812f | bellard | *
|
13 | ea88812f | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | ea88812f | bellard | * all copies or substantial portions of the Software.
|
15 | ea88812f | bellard | *
|
16 | ea88812f | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | ea88812f | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | ea88812f | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | ea88812f | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | ea88812f | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | ea88812f | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | ea88812f | bellard | * THE SOFTWARE.
|
23 | ea88812f | bellard | */
|
24 | ea88812f | bellard | #include <stdlib.h> |
25 | ea88812f | bellard | #include <stdio.h> |
26 | ea88812f | bellard | #include <stdarg.h> |
27 | ea88812f | bellard | #include <string.h> |
28 | ea88812f | bellard | #include <errno.h> |
29 | ea88812f | bellard | #include <unistd.h> |
30 | aa26bb2d | ths | #include <fcntl.h> |
31 | f582af58 | Paolo Bonzini | |
32 | f582af58 | Paolo Bonzini | /* Needed early for CONFIG_BSD etc. */
|
33 | f582af58 | Paolo Bonzini | #include "config-host.h" |
34 | f582af58 | Paolo Bonzini | |
35 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
|
36 | e78815a5 | Andreas Färber | #include <sys/mman.h> |
37 | e78815a5 | Andreas Färber | #endif
|
38 | e78815a5 | Andreas Färber | |
39 | dfe5fff3 | Juan Quintela | #ifdef CONFIG_SOLARIS
|
40 | 605686cd | ths | #include <sys/types.h> |
41 | 605686cd | ths | #include <sys/statvfs.h> |
42 | e78815a5 | Andreas Färber | /* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
|
43 | e78815a5 | Andreas Färber | discussion about Solaris header problems */
|
44 | e78815a5 | Andreas Färber | extern int madvise(caddr_t, size_t, int); |
45 | 605686cd | ths | #endif
|
46 | ea88812f | bellard | |
47 | 6e4255f6 | bellard | #ifdef _WIN32
|
48 | 6e4255f6 | bellard | #include <windows.h> |
49 | 71e72a19 | Juan Quintela | #elif defined(CONFIG_BSD)
|
50 | 194884dd | bellard | #include <stdlib.h> |
51 | 194884dd | bellard | #else
|
52 | 49b470eb | bellard | #include <malloc.h> |
53 | 194884dd | bellard | #endif
|
54 | 49b470eb | bellard | |
55 | 511d2b14 | blueswir1 | #include "qemu-common.h" |
56 | cd245a19 | Stefan Hajnoczi | #include "trace.h" |
57 | 511d2b14 | blueswir1 | #include "sysemu.h" |
58 | 03ff3ca3 | aliguori | #include "qemu_socket.h" |
59 | 03ff3ca3 | aliguori | |
60 | e78815a5 | Andreas Färber | int qemu_madvise(void *addr, size_t len, int advice) |
61 | e78815a5 | Andreas Färber | { |
62 | e78815a5 | Andreas Färber | if (advice == QEMU_MADV_INVALID) {
|
63 | e78815a5 | Andreas Färber | errno = EINVAL; |
64 | e78815a5 | Andreas Färber | return -1; |
65 | e78815a5 | Andreas Färber | } |
66 | e78815a5 | Andreas Färber | #if defined(CONFIG_MADVISE)
|
67 | e78815a5 | Andreas Färber | return madvise(addr, len, advice);
|
68 | e78815a5 | Andreas Färber | #elif defined(CONFIG_POSIX_MADVISE)
|
69 | e78815a5 | Andreas Färber | return posix_madvise(addr, len, advice);
|
70 | e78815a5 | Andreas Färber | #else
|
71 | e78815a5 | Andreas Färber | errno = EINVAL; |
72 | e78815a5 | Andreas Färber | return -1; |
73 | e78815a5 | Andreas Färber | #endif
|
74 | e78815a5 | Andreas Färber | } |
75 | e78815a5 | Andreas Färber | |
76 | aa26bb2d | ths | int qemu_create_pidfile(const char *filename) |
77 | aa26bb2d | ths | { |
78 | aa26bb2d | ths | char buffer[128]; |
79 | aa26bb2d | ths | int len;
|
80 | aa26bb2d | ths | #ifndef _WIN32
|
81 | aa26bb2d | ths | int fd;
|
82 | aa26bb2d | ths | |
83 | 40ff6d7e | Kevin Wolf | fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
|
84 | aa26bb2d | ths | if (fd == -1) |
85 | aa26bb2d | ths | return -1; |
86 | aa26bb2d | ths | |
87 | aa26bb2d | ths | if (lockf(fd, F_TLOCK, 0) == -1) |
88 | aa26bb2d | ths | return -1; |
89 | aa26bb2d | ths | |
90 | aa26bb2d | ths | len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); |
91 | aa26bb2d | ths | if (write(fd, buffer, len) != len)
|
92 | aa26bb2d | ths | return -1; |
93 | aa26bb2d | ths | #else
|
94 | aa26bb2d | ths | HANDLE file; |
95 | aa26bb2d | ths | OVERLAPPED overlap; |
96 | aa26bb2d | ths | BOOL ret; |
97 | 099fe236 | Juha Riihimäki | memset(&overlap, 0, sizeof(overlap)); |
98 | aa26bb2d | ths | |
99 | 099fe236 | Juha Riihimäki | file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
100 | aa26bb2d | ths | OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
101 | aa26bb2d | ths | |
102 | aa26bb2d | ths | if (file == INVALID_HANDLE_VALUE)
|
103 | aa26bb2d | ths | return -1; |
104 | aa26bb2d | ths | |
105 | aa26bb2d | ths | len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); |
106 | 5fafdf24 | ths | ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, |
107 | aa26bb2d | ths | &overlap, NULL);
|
108 | aa26bb2d | ths | if (ret == 0) |
109 | aa26bb2d | ths | return -1; |
110 | aa26bb2d | ths | #endif
|
111 | aa26bb2d | ths | return 0; |
112 | aa26bb2d | ths | } |
113 | 29b3a662 | pbrook | |
114 | 03ff3ca3 | aliguori | |
115 | 40ff6d7e | Kevin Wolf | /*
|
116 | 40ff6d7e | Kevin Wolf | * Opens a file with FD_CLOEXEC set
|
117 | 40ff6d7e | Kevin Wolf | */
|
118 | 40ff6d7e | Kevin Wolf | int qemu_open(const char *name, int flags, ...) |
119 | 40ff6d7e | Kevin Wolf | { |
120 | 40ff6d7e | Kevin Wolf | int ret;
|
121 | 40ff6d7e | Kevin Wolf | int mode = 0; |
122 | 40ff6d7e | Kevin Wolf | |
123 | 40ff6d7e | Kevin Wolf | if (flags & O_CREAT) {
|
124 | 40ff6d7e | Kevin Wolf | va_list ap; |
125 | 40ff6d7e | Kevin Wolf | |
126 | 40ff6d7e | Kevin Wolf | va_start(ap, flags); |
127 | 40ff6d7e | Kevin Wolf | mode = va_arg(ap, int);
|
128 | 40ff6d7e | Kevin Wolf | va_end(ap); |
129 | 40ff6d7e | Kevin Wolf | } |
130 | 40ff6d7e | Kevin Wolf | |
131 | 40ff6d7e | Kevin Wolf | #ifdef O_CLOEXEC
|
132 | 40ff6d7e | Kevin Wolf | ret = open(name, flags | O_CLOEXEC, mode); |
133 | 40ff6d7e | Kevin Wolf | #else
|
134 | 40ff6d7e | Kevin Wolf | ret = open(name, flags, mode); |
135 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
136 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
137 | 40ff6d7e | Kevin Wolf | } |
138 | 03ff3ca3 | aliguori | #endif
|
139 | 40ff6d7e | Kevin Wolf | |
140 | 40ff6d7e | Kevin Wolf | return ret;
|
141 | 40ff6d7e | Kevin Wolf | } |
142 | 40ff6d7e | Kevin Wolf | |
143 | 7b5f699d | Kirill A. Shutemov | /*
|
144 | 7b5f699d | Kirill A. Shutemov | * A variant of write(2) which handles partial write.
|
145 | 7b5f699d | Kirill A. Shutemov | *
|
146 | 7b5f699d | Kirill A. Shutemov | * Return the number of bytes transferred.
|
147 | 7b5f699d | Kirill A. Shutemov | * Set errno if fewer than `count' bytes are written.
|
148 | 1298cb68 | Juan Quintela | *
|
149 | 1298cb68 | Juan Quintela | * This function don't work with non-blocking fd's.
|
150 | 1298cb68 | Juan Quintela | * Any of the possibilities with non-bloking fd's is bad:
|
151 | 1298cb68 | Juan Quintela | * - return a short write (then name is wrong)
|
152 | 1298cb68 | Juan Quintela | * - busy wait adding (errno == EAGAIN) to the loop
|
153 | 7b5f699d | Kirill A. Shutemov | */
|
154 | 7b5f699d | Kirill A. Shutemov | ssize_t qemu_write_full(int fd, const void *buf, size_t count) |
155 | 7b5f699d | Kirill A. Shutemov | { |
156 | 7b5f699d | Kirill A. Shutemov | ssize_t ret = 0;
|
157 | 7b5f699d | Kirill A. Shutemov | ssize_t total = 0;
|
158 | 7b5f699d | Kirill A. Shutemov | |
159 | 7b5f699d | Kirill A. Shutemov | while (count) {
|
160 | 7b5f699d | Kirill A. Shutemov | ret = write(fd, buf, count); |
161 | 7b5f699d | Kirill A. Shutemov | if (ret < 0) { |
162 | 7b5f699d | Kirill A. Shutemov | if (errno == EINTR)
|
163 | 7b5f699d | Kirill A. Shutemov | continue;
|
164 | 7b5f699d | Kirill A. Shutemov | break;
|
165 | 7b5f699d | Kirill A. Shutemov | } |
166 | 7b5f699d | Kirill A. Shutemov | |
167 | 7b5f699d | Kirill A. Shutemov | count -= ret; |
168 | 7b5f699d | Kirill A. Shutemov | buf += ret; |
169 | 7b5f699d | Kirill A. Shutemov | total += ret; |
170 | 7b5f699d | Kirill A. Shutemov | } |
171 | 7b5f699d | Kirill A. Shutemov | |
172 | 7b5f699d | Kirill A. Shutemov | return total;
|
173 | 7b5f699d | Kirill A. Shutemov | } |
174 | 7b5f699d | Kirill A. Shutemov | |
175 | 40ff6d7e | Kevin Wolf | /*
|
176 | 40ff6d7e | Kevin Wolf | * Opens a socket with FD_CLOEXEC set
|
177 | 40ff6d7e | Kevin Wolf | */
|
178 | 40ff6d7e | Kevin Wolf | int qemu_socket(int domain, int type, int protocol) |
179 | 40ff6d7e | Kevin Wolf | { |
180 | 40ff6d7e | Kevin Wolf | int ret;
|
181 | 40ff6d7e | Kevin Wolf | |
182 | 40ff6d7e | Kevin Wolf | #ifdef SOCK_CLOEXEC
|
183 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type | SOCK_CLOEXEC, protocol); |
184 | 3a03bfa5 | Andre Przywara | if (ret != -1 || errno != EINVAL) { |
185 | 3a03bfa5 | Andre Przywara | return ret;
|
186 | 3a03bfa5 | Andre Przywara | } |
187 | 3a03bfa5 | Andre Przywara | #endif
|
188 | 40ff6d7e | Kevin Wolf | ret = socket(domain, type, protocol); |
189 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
190 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
191 | 40ff6d7e | Kevin Wolf | } |
192 | 40ff6d7e | Kevin Wolf | |
193 | 40ff6d7e | Kevin Wolf | return ret;
|
194 | 40ff6d7e | Kevin Wolf | } |
195 | 40ff6d7e | Kevin Wolf | |
196 | 40ff6d7e | Kevin Wolf | /*
|
197 | 40ff6d7e | Kevin Wolf | * Accept a connection and set FD_CLOEXEC
|
198 | 40ff6d7e | Kevin Wolf | */
|
199 | 40ff6d7e | Kevin Wolf | int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) |
200 | 40ff6d7e | Kevin Wolf | { |
201 | 40ff6d7e | Kevin Wolf | int ret;
|
202 | 40ff6d7e | Kevin Wolf | |
203 | 40ff6d7e | Kevin Wolf | #ifdef CONFIG_ACCEPT4
|
204 | 40ff6d7e | Kevin Wolf | ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); |
205 | 347ed55c | Kevin Wolf | if (ret != -1 || errno != ENOSYS) { |
206 | 3a03bfa5 | Andre Przywara | return ret;
|
207 | 3a03bfa5 | Andre Przywara | } |
208 | 3a03bfa5 | Andre Przywara | #endif
|
209 | 40ff6d7e | Kevin Wolf | ret = accept(s, addr, addrlen); |
210 | 40ff6d7e | Kevin Wolf | if (ret >= 0) { |
211 | 40ff6d7e | Kevin Wolf | qemu_set_cloexec(ret); |
212 | 40ff6d7e | Kevin Wolf | } |
213 | 40ff6d7e | Kevin Wolf | |
214 | 40ff6d7e | Kevin Wolf | return ret;
|
215 | 40ff6d7e | Kevin Wolf | } |