xref: /openbmc/qemu/util/osdep.c (revision 37b0b24e)
1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini  * QEMU low level functions
3baacf047SPaolo Bonzini  *
4baacf047SPaolo Bonzini  * Copyright (c) 2003 Fabrice Bellard
5baacf047SPaolo Bonzini  *
6baacf047SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
7baacf047SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
8baacf047SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
9baacf047SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10baacf047SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
11baacf047SPaolo Bonzini  * furnished to do so, subject to the following conditions:
12baacf047SPaolo Bonzini  *
13baacf047SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
14baacf047SPaolo Bonzini  * all copies or substantial portions of the Software.
15baacf047SPaolo Bonzini  *
16baacf047SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17baacf047SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18baacf047SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19baacf047SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20baacf047SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21baacf047SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22baacf047SPaolo Bonzini  * THE SOFTWARE.
23baacf047SPaolo Bonzini  */
24aafd7584SPeter Maydell #include "qemu/osdep.h"
25ebb3d49cSDaniel P. Berrangé #include "qapi/error.h"
26f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
27baacf047SPaolo Bonzini #include "qemu/sockets.h"
28d49b6836SMarkus Armbruster #include "qemu/error-report.h"
29b85ea5faSPeter Maydell #include "qemu/madvise.h"
30f2241d16SPeter Maydell #include "qemu/mprotect.h"
3115e09912SPeter Maydell #include "qemu/hw-version.h"
32baacf047SPaolo Bonzini #include "monitor/monitor.h"
33baacf047SPaolo Bonzini 
34d494352cSEduardo Habkost static const char *hw_version = QEMU_HW_VERSION;
35baacf047SPaolo Bonzini 
socket_set_cork(int fd,int v)36baacf047SPaolo Bonzini int socket_set_cork(int fd, int v)
37baacf047SPaolo Bonzini {
38baacf047SPaolo Bonzini #if defined(SOL_TCP) && defined(TCP_CORK)
39e7b79428SMarc-André Lureau     return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
40baacf047SPaolo Bonzini #else
41baacf047SPaolo Bonzini     return 0;
42baacf047SPaolo Bonzini #endif
43baacf047SPaolo Bonzini }
44baacf047SPaolo Bonzini 
socket_set_nodelay(int fd)45bf1c852aSMORITA Kazutaka int socket_set_nodelay(int fd)
46bf1c852aSMORITA Kazutaka {
47bf1c852aSMORITA Kazutaka     int v = 1;
48e7b79428SMarc-André Lureau     return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
49bf1c852aSMORITA Kazutaka }
50bf1c852aSMORITA Kazutaka 
qemu_madvise(void * addr,size_t len,int advice)51baacf047SPaolo Bonzini int qemu_madvise(void *addr, size_t len, int advice)
52baacf047SPaolo Bonzini {
53baacf047SPaolo Bonzini     if (advice == QEMU_MADV_INVALID) {
54baacf047SPaolo Bonzini         errno = EINVAL;
55baacf047SPaolo Bonzini         return -1;
56baacf047SPaolo Bonzini     }
57baacf047SPaolo Bonzini #if defined(CONFIG_MADVISE)
58baacf047SPaolo Bonzini     return madvise(addr, len, advice);
59baacf047SPaolo Bonzini #elif defined(CONFIG_POSIX_MADVISE)
60baacf047SPaolo Bonzini     return posix_madvise(addr, len, advice);
61baacf047SPaolo Bonzini #else
62baacf047SPaolo Bonzini     errno = EINVAL;
63baacf047SPaolo Bonzini     return -1;
64baacf047SPaolo Bonzini #endif
65baacf047SPaolo Bonzini }
66baacf047SPaolo Bonzini 
qemu_mprotect__osdep(void * addr,size_t size,int prot)675fa64b31SEmilio G. Cota static int qemu_mprotect__osdep(void *addr, size_t size, int prot)
685fa64b31SEmilio G. Cota {
698e3b0cbbSMarc-André Lureau     g_assert(!((uintptr_t)addr & ~qemu_real_host_page_mask()));
708e3b0cbbSMarc-André Lureau     g_assert(!(size & ~qemu_real_host_page_mask()));
715fa64b31SEmilio G. Cota 
725fa64b31SEmilio G. Cota #ifdef _WIN32
735fa64b31SEmilio G. Cota     DWORD old_protect;
745fa64b31SEmilio G. Cota 
755fa64b31SEmilio G. Cota     if (!VirtualProtect(addr, size, prot, &old_protect)) {
76cf0c76cdSPhilippe Mathieu-Daudé         g_autofree gchar *emsg = g_win32_error_message(GetLastError());
77cf0c76cdSPhilippe Mathieu-Daudé         error_report("%s: VirtualProtect failed: %s", __func__, emsg);
785fa64b31SEmilio G. Cota         return -1;
795fa64b31SEmilio G. Cota     }
805fa64b31SEmilio G. Cota     return 0;
815fa64b31SEmilio G. Cota #else
825fa64b31SEmilio G. Cota     if (mprotect(addr, size, prot)) {
835fa64b31SEmilio G. Cota         error_report("%s: mprotect failed: %s", __func__, strerror(errno));
845fa64b31SEmilio G. Cota         return -1;
855fa64b31SEmilio G. Cota     }
865fa64b31SEmilio G. Cota     return 0;
875fa64b31SEmilio G. Cota #endif
885fa64b31SEmilio G. Cota }
895fa64b31SEmilio G. Cota 
qemu_mprotect_rw(void * addr,size_t size)90d7107fc0SRichard Henderson int qemu_mprotect_rw(void *addr, size_t size)
91d7107fc0SRichard Henderson {
92d7107fc0SRichard Henderson #ifdef _WIN32
93d7107fc0SRichard Henderson     return qemu_mprotect__osdep(addr, size, PAGE_READWRITE);
94d7107fc0SRichard Henderson #else
95d7107fc0SRichard Henderson     return qemu_mprotect__osdep(addr, size, PROT_READ | PROT_WRITE);
96d7107fc0SRichard Henderson #endif
97d7107fc0SRichard Henderson }
98d7107fc0SRichard Henderson 
qemu_mprotect_rwx(void * addr,size_t size)995fa64b31SEmilio G. Cota int qemu_mprotect_rwx(void *addr, size_t size)
1005fa64b31SEmilio G. Cota {
1015fa64b31SEmilio G. Cota #ifdef _WIN32
1025fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PAGE_EXECUTE_READWRITE);
1035fa64b31SEmilio G. Cota #else
1045fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
1055fa64b31SEmilio G. Cota #endif
1065fa64b31SEmilio G. Cota }
1075fa64b31SEmilio G. Cota 
qemu_mprotect_none(void * addr,size_t size)1085fa64b31SEmilio G. Cota int qemu_mprotect_none(void *addr, size_t size)
1095fa64b31SEmilio G. Cota {
1105fa64b31SEmilio G. Cota #ifdef _WIN32
1115fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PAGE_NOACCESS);
1125fa64b31SEmilio G. Cota #else
1135fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PROT_NONE);
1145fa64b31SEmilio G. Cota #endif
1155fa64b31SEmilio G. Cota }
1165fa64b31SEmilio G. Cota 
117baacf047SPaolo Bonzini #ifndef _WIN32
118ca749954SFam Zheng 
119ca749954SFam Zheng static int fcntl_op_setlk = -1;
120ca749954SFam Zheng static int fcntl_op_getlk = -1;
121ca749954SFam Zheng 
122baacf047SPaolo Bonzini /*
123baacf047SPaolo Bonzini  * Dups an fd and sets the flags
124baacf047SPaolo Bonzini  */
qemu_dup_flags(int fd,int flags)12560efffa4SDaniel P. Berrangé int qemu_dup_flags(int fd, int flags)
126baacf047SPaolo Bonzini {
127baacf047SPaolo Bonzini     int ret;
128baacf047SPaolo Bonzini     int serrno;
129baacf047SPaolo Bonzini     int dup_flags;
130baacf047SPaolo Bonzini 
131761d1ddfSFam Zheng     ret = qemu_dup(fd);
132baacf047SPaolo Bonzini     if (ret == -1) {
133baacf047SPaolo Bonzini         goto fail;
134baacf047SPaolo Bonzini     }
135baacf047SPaolo Bonzini 
136baacf047SPaolo Bonzini     dup_flags = fcntl(ret, F_GETFL);
137baacf047SPaolo Bonzini     if (dup_flags == -1) {
138baacf047SPaolo Bonzini         goto fail;
139baacf047SPaolo Bonzini     }
140baacf047SPaolo Bonzini 
141baacf047SPaolo Bonzini     if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
142baacf047SPaolo Bonzini         errno = EINVAL;
143baacf047SPaolo Bonzini         goto fail;
144baacf047SPaolo Bonzini     }
145baacf047SPaolo Bonzini 
146baacf047SPaolo Bonzini     /* Set/unset flags that we can with fcntl */
147baacf047SPaolo Bonzini     if (fcntl(ret, F_SETFL, flags) == -1) {
148baacf047SPaolo Bonzini         goto fail;
149baacf047SPaolo Bonzini     }
150baacf047SPaolo Bonzini 
151baacf047SPaolo Bonzini     /* Truncate the file in the cases that open() would truncate it */
152baacf047SPaolo Bonzini     if (flags & O_TRUNC ||
153baacf047SPaolo Bonzini             ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
154baacf047SPaolo Bonzini         if (ftruncate(ret, 0) == -1) {
155baacf047SPaolo Bonzini             goto fail;
156baacf047SPaolo Bonzini         }
157baacf047SPaolo Bonzini     }
158baacf047SPaolo Bonzini 
159baacf047SPaolo Bonzini     return ret;
160baacf047SPaolo Bonzini 
161baacf047SPaolo Bonzini fail:
162baacf047SPaolo Bonzini     serrno = errno;
163baacf047SPaolo Bonzini     if (ret != -1) {
164baacf047SPaolo Bonzini         close(ret);
165baacf047SPaolo Bonzini     }
166baacf047SPaolo Bonzini     errno = serrno;
167baacf047SPaolo Bonzini     return -1;
168baacf047SPaolo Bonzini }
169baacf047SPaolo Bonzini 
qemu_dup(int fd)170761d1ddfSFam Zheng int qemu_dup(int fd)
171761d1ddfSFam Zheng {
172761d1ddfSFam Zheng     int ret;
173761d1ddfSFam Zheng #ifdef F_DUPFD_CLOEXEC
174761d1ddfSFam Zheng     ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
175761d1ddfSFam Zheng #else
176761d1ddfSFam Zheng     ret = dup(fd);
177761d1ddfSFam Zheng     if (ret != -1) {
178761d1ddfSFam Zheng         qemu_set_cloexec(ret);
179761d1ddfSFam Zheng     }
180761d1ddfSFam Zheng #endif
181761d1ddfSFam Zheng     return ret;
182761d1ddfSFam Zheng }
183761d1ddfSFam Zheng 
qemu_parse_fdset(const char * param)184baacf047SPaolo Bonzini static int qemu_parse_fdset(const char *param)
185baacf047SPaolo Bonzini {
186baacf047SPaolo Bonzini     return qemu_parse_fd(param);
187baacf047SPaolo Bonzini }
18813461fdbSFam Zheng 
qemu_probe_lock_ops(void)189ca749954SFam Zheng static void qemu_probe_lock_ops(void)
190ca749954SFam Zheng {
191ca749954SFam Zheng     if (fcntl_op_setlk == -1) {
192ca749954SFam Zheng #ifdef F_OFD_SETLK
193ca749954SFam Zheng         int fd;
194ca749954SFam Zheng         int ret;
195ca749954SFam Zheng         struct flock fl = {
196ca749954SFam Zheng             .l_whence = SEEK_SET,
197ca749954SFam Zheng             .l_start  = 0,
198ca749954SFam Zheng             .l_len    = 0,
199ca749954SFam Zheng             .l_type   = F_WRLCK,
200ca749954SFam Zheng         };
201ca749954SFam Zheng 
202ca749954SFam Zheng         fd = open("/dev/null", O_RDWR);
203ca749954SFam Zheng         if (fd < 0) {
204ca749954SFam Zheng             fprintf(stderr,
205ca749954SFam Zheng                     "Failed to open /dev/null for OFD lock probing: %s\n",
206ca749954SFam Zheng                     strerror(errno));
207ca749954SFam Zheng             fcntl_op_setlk = F_SETLK;
208ca749954SFam Zheng             fcntl_op_getlk = F_GETLK;
209ca749954SFam Zheng             return;
210ca749954SFam Zheng         }
211ca749954SFam Zheng         ret = fcntl(fd, F_OFD_GETLK, &fl);
212ca749954SFam Zheng         close(fd);
213ca749954SFam Zheng         if (!ret) {
214ca749954SFam Zheng             fcntl_op_setlk = F_OFD_SETLK;
215ca749954SFam Zheng             fcntl_op_getlk = F_OFD_GETLK;
216ca749954SFam Zheng         } else {
217ca749954SFam Zheng             fcntl_op_setlk = F_SETLK;
218ca749954SFam Zheng             fcntl_op_getlk = F_GETLK;
219ca749954SFam Zheng         }
220ca749954SFam Zheng #else
221ca749954SFam Zheng         fcntl_op_setlk = F_SETLK;
222ca749954SFam Zheng         fcntl_op_getlk = F_GETLK;
223ca749954SFam Zheng #endif
224ca749954SFam Zheng     }
225ca749954SFam Zheng }
226ca749954SFam Zheng 
qemu_has_ofd_lock(void)227ca749954SFam Zheng bool qemu_has_ofd_lock(void)
228ca749954SFam Zheng {
229ca749954SFam Zheng     qemu_probe_lock_ops();
230ca749954SFam Zheng #ifdef F_OFD_SETLK
231ca749954SFam Zheng     return fcntl_op_setlk == F_OFD_SETLK;
232ca749954SFam Zheng #else
233ca749954SFam Zheng     return false;
234ca749954SFam Zheng #endif
235ca749954SFam Zheng }
236ca749954SFam Zheng 
qemu_lock_fcntl(int fd,int64_t start,int64_t len,int fl_type)23713461fdbSFam Zheng static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
23813461fdbSFam Zheng {
23913461fdbSFam Zheng     int ret;
24013461fdbSFam Zheng     struct flock fl = {
24113461fdbSFam Zheng         .l_whence = SEEK_SET,
24213461fdbSFam Zheng         .l_start  = start,
24313461fdbSFam Zheng         .l_len    = len,
24413461fdbSFam Zheng         .l_type   = fl_type,
24513461fdbSFam Zheng     };
246ca749954SFam Zheng     qemu_probe_lock_ops();
247*37b0b24eSNikita Ivanov     ret = RETRY_ON_EINTR(fcntl(fd, fcntl_op_setlk, &fl));
24813461fdbSFam Zheng     return ret == -1 ? -errno : 0;
24913461fdbSFam Zheng }
25013461fdbSFam Zheng 
qemu_lock_fd(int fd,int64_t start,int64_t len,bool exclusive)25113461fdbSFam Zheng int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive)
25213461fdbSFam Zheng {
25313461fdbSFam Zheng     return qemu_lock_fcntl(fd, start, len, exclusive ? F_WRLCK : F_RDLCK);
25413461fdbSFam Zheng }
25513461fdbSFam Zheng 
qemu_unlock_fd(int fd,int64_t start,int64_t len)25613461fdbSFam Zheng int qemu_unlock_fd(int fd, int64_t start, int64_t len)
25713461fdbSFam Zheng {
25813461fdbSFam Zheng     return qemu_lock_fcntl(fd, start, len, F_UNLCK);
25913461fdbSFam Zheng }
26013461fdbSFam Zheng 
qemu_lock_fd_test(int fd,int64_t start,int64_t len,bool exclusive)26113461fdbSFam Zheng int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
26213461fdbSFam Zheng {
26313461fdbSFam Zheng     int ret;
26413461fdbSFam Zheng     struct flock fl = {
26513461fdbSFam Zheng         .l_whence = SEEK_SET,
26613461fdbSFam Zheng         .l_start  = start,
26713461fdbSFam Zheng         .l_len    = len,
26813461fdbSFam Zheng         .l_type   = exclusive ? F_WRLCK : F_RDLCK,
26913461fdbSFam Zheng     };
270ca749954SFam Zheng     qemu_probe_lock_ops();
271ca749954SFam Zheng     ret = fcntl(fd, fcntl_op_getlk, &fl);
27213461fdbSFam Zheng     if (ret == -1) {
27313461fdbSFam Zheng         return -errno;
27413461fdbSFam Zheng     } else {
27513461fdbSFam Zheng         return fl.l_type == F_UNLCK ? 0 : -EAGAIN;
27613461fdbSFam Zheng     }
27713461fdbSFam Zheng }
278baacf047SPaolo Bonzini #endif
279baacf047SPaolo Bonzini 
qemu_open_cloexec(const char * name,int flags,mode_t mode)280c2069ff6SDaniel P. Berrangé static int qemu_open_cloexec(const char *name, int flags, mode_t mode)
281c2069ff6SDaniel P. Berrangé {
282c2069ff6SDaniel P. Berrangé     int ret;
283c2069ff6SDaniel P. Berrangé #ifdef O_CLOEXEC
284c2069ff6SDaniel P. Berrangé     ret = open(name, flags | O_CLOEXEC, mode);
285c2069ff6SDaniel P. Berrangé #else
286c2069ff6SDaniel P. Berrangé     ret = open(name, flags, mode);
287c2069ff6SDaniel P. Berrangé     if (ret >= 0) {
288c2069ff6SDaniel P. Berrangé         qemu_set_cloexec(ret);
289c2069ff6SDaniel P. Berrangé     }
290c2069ff6SDaniel P. Berrangé #endif
291c2069ff6SDaniel P. Berrangé     return ret;
292c2069ff6SDaniel P. Berrangé }
293c2069ff6SDaniel P. Berrangé 
294baacf047SPaolo Bonzini /*
295baacf047SPaolo Bonzini  * Opens a file with FD_CLOEXEC set
296baacf047SPaolo Bonzini  */
297bf93d2adSDaniel P. Berrangé static int
qemu_open_internal(const char * name,int flags,mode_t mode,Error ** errp)298ebb3d49cSDaniel P. Berrangé qemu_open_internal(const char *name, int flags, mode_t mode, Error **errp)
299baacf047SPaolo Bonzini {
300baacf047SPaolo Bonzini     int ret;
301baacf047SPaolo Bonzini 
302baacf047SPaolo Bonzini #ifndef _WIN32
303baacf047SPaolo Bonzini     const char *fdset_id_str;
304baacf047SPaolo Bonzini 
305baacf047SPaolo Bonzini     /* Attempt dup of fd from fd set */
306baacf047SPaolo Bonzini     if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
307baacf047SPaolo Bonzini         int64_t fdset_id;
30860efffa4SDaniel P. Berrangé         int dupfd;
309baacf047SPaolo Bonzini 
310baacf047SPaolo Bonzini         fdset_id = qemu_parse_fdset(fdset_id_str);
311baacf047SPaolo Bonzini         if (fdset_id == -1) {
312ebb3d49cSDaniel P. Berrangé             error_setg(errp, "Could not parse fdset %s", name);
313baacf047SPaolo Bonzini             errno = EINVAL;
314baacf047SPaolo Bonzini             return -1;
315baacf047SPaolo Bonzini         }
316baacf047SPaolo Bonzini 
31760efffa4SDaniel P. Berrangé         dupfd = monitor_fdset_dup_fd_add(fdset_id, flags);
318baacf047SPaolo Bonzini         if (dupfd == -1) {
319ebb3d49cSDaniel P. Berrangé             error_setg_errno(errp, errno, "Could not dup FD for %s flags %x",
320ebb3d49cSDaniel P. Berrangé                              name, flags);
321baacf047SPaolo Bonzini             return -1;
322baacf047SPaolo Bonzini         }
323baacf047SPaolo Bonzini 
324baacf047SPaolo Bonzini         return dupfd;
325baacf047SPaolo Bonzini     }
326baacf047SPaolo Bonzini #endif
327baacf047SPaolo Bonzini 
328bf93d2adSDaniel P. Berrangé     ret = qemu_open_cloexec(name, flags, mode);
329baacf047SPaolo Bonzini 
330ebb3d49cSDaniel P. Berrangé     if (ret == -1) {
331ebb3d49cSDaniel P. Berrangé         const char *action = flags & O_CREAT ? "create" : "open";
332661b3e81SDaniel P. Berrangé #ifdef O_DIRECT
333661b3e81SDaniel P. Berrangé         /* Give more helpful error message for O_DIRECT */
334661b3e81SDaniel P. Berrangé         if (errno == EINVAL && (flags & O_DIRECT)) {
335661b3e81SDaniel P. Berrangé             ret = open(name, flags & ~O_DIRECT, mode);
336661b3e81SDaniel P. Berrangé             if (ret != -1) {
337661b3e81SDaniel P. Berrangé                 close(ret);
338661b3e81SDaniel P. Berrangé                 error_setg(errp, "Could not %s '%s': "
339661b3e81SDaniel P. Berrangé                            "filesystem does not support O_DIRECT",
340661b3e81SDaniel P. Berrangé                            action, name);
341661b3e81SDaniel P. Berrangé                 errno = EINVAL; /* restore first open()'s errno */
342661b3e81SDaniel P. Berrangé                 return -1;
343661b3e81SDaniel P. Berrangé             }
344661b3e81SDaniel P. Berrangé         }
345661b3e81SDaniel P. Berrangé #endif /* O_DIRECT */
346ebb3d49cSDaniel P. Berrangé         error_setg_errno(errp, errno, "Could not %s '%s'",
347ebb3d49cSDaniel P. Berrangé                          action, name);
348ebb3d49cSDaniel P. Berrangé     }
349ebb3d49cSDaniel P. Berrangé 
350bf93d2adSDaniel P. Berrangé     return ret;
351baacf047SPaolo Bonzini }
352baacf047SPaolo Bonzini 
353bf93d2adSDaniel P. Berrangé 
qemu_open(const char * name,int flags,Error ** errp)354c490af57SDaniel P. Berrangé int qemu_open(const char *name, int flags, Error **errp)
355c490af57SDaniel P. Berrangé {
356c490af57SDaniel P. Berrangé     assert(!(flags & O_CREAT));
357c490af57SDaniel P. Berrangé 
358c490af57SDaniel P. Berrangé     return qemu_open_internal(name, flags, 0, errp);
359c490af57SDaniel P. Berrangé }
360c490af57SDaniel P. Berrangé 
361c490af57SDaniel P. Berrangé 
qemu_create(const char * name,int flags,mode_t mode,Error ** errp)362c490af57SDaniel P. Berrangé int qemu_create(const char *name, int flags, mode_t mode, Error **errp)
363c490af57SDaniel P. Berrangé {
364c490af57SDaniel P. Berrangé     assert(!(flags & O_CREAT));
365c490af57SDaniel P. Berrangé 
366c490af57SDaniel P. Berrangé     return qemu_open_internal(name, flags | O_CREAT, mode, errp);
367c490af57SDaniel P. Berrangé }
368c490af57SDaniel P. Berrangé 
369c490af57SDaniel P. Berrangé 
qemu_open_old(const char * name,int flags,...)370bf93d2adSDaniel P. Berrangé int qemu_open_old(const char *name, int flags, ...)
371bf93d2adSDaniel P. Berrangé {
372bf93d2adSDaniel P. Berrangé     va_list ap;
373bf93d2adSDaniel P. Berrangé     mode_t mode = 0;
374bf93d2adSDaniel P. Berrangé     int ret;
375bf93d2adSDaniel P. Berrangé 
376bf93d2adSDaniel P. Berrangé     va_start(ap, flags);
377bf93d2adSDaniel P. Berrangé     if (flags & O_CREAT) {
378bf93d2adSDaniel P. Berrangé         mode = va_arg(ap, int);
379bf93d2adSDaniel P. Berrangé     }
380bf93d2adSDaniel P. Berrangé     va_end(ap);
381bf93d2adSDaniel P. Berrangé 
382ebb3d49cSDaniel P. Berrangé     ret = qemu_open_internal(name, flags, mode, NULL);
383baacf047SPaolo Bonzini 
384a5813077SStefan Hajnoczi #ifdef O_DIRECT
385a5813077SStefan Hajnoczi     if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
386a5813077SStefan Hajnoczi         error_report("file system may not support O_DIRECT");
387a5813077SStefan Hajnoczi         errno = EINVAL; /* in case it was clobbered */
388a5813077SStefan Hajnoczi     }
389a5813077SStefan Hajnoczi #endif /* O_DIRECT */
390a5813077SStefan Hajnoczi 
391baacf047SPaolo Bonzini     return ret;
392baacf047SPaolo Bonzini }
393baacf047SPaolo Bonzini 
qemu_close(int fd)394baacf047SPaolo Bonzini int qemu_close(int fd)
395baacf047SPaolo Bonzini {
396baacf047SPaolo Bonzini     int64_t fdset_id;
397baacf047SPaolo Bonzini 
398baacf047SPaolo Bonzini     /* Close fd that was dup'd from an fdset */
399baacf047SPaolo Bonzini     fdset_id = monitor_fdset_dup_fd_find(fd);
400baacf047SPaolo Bonzini     if (fdset_id != -1) {
401baacf047SPaolo Bonzini         int ret;
402baacf047SPaolo Bonzini 
403baacf047SPaolo Bonzini         ret = close(fd);
404baacf047SPaolo Bonzini         if (ret == 0) {
405baacf047SPaolo Bonzini             monitor_fdset_dup_fd_remove(fd);
406baacf047SPaolo Bonzini         }
407baacf047SPaolo Bonzini 
408baacf047SPaolo Bonzini         return ret;
409baacf047SPaolo Bonzini     }
410baacf047SPaolo Bonzini 
411baacf047SPaolo Bonzini     return close(fd);
412baacf047SPaolo Bonzini }
413baacf047SPaolo Bonzini 
414baacf047SPaolo Bonzini /*
415ee13240eSMarc-André Lureau  * Delete a file from the filesystem, unless the filename is /dev/fdset/...
416ee13240eSMarc-André Lureau  *
417ee13240eSMarc-André Lureau  * Returns: On success, zero is returned.  On error, -1 is returned,
418ee13240eSMarc-André Lureau  * and errno is set appropriately.
419ee13240eSMarc-André Lureau  */
qemu_unlink(const char * name)420ee13240eSMarc-André Lureau int qemu_unlink(const char *name)
421ee13240eSMarc-André Lureau {
422ee13240eSMarc-André Lureau     if (g_str_has_prefix(name, "/dev/fdset/")) {
423ee13240eSMarc-André Lureau         return 0;
424ee13240eSMarc-André Lureau     }
425ee13240eSMarc-André Lureau 
426ee13240eSMarc-André Lureau     return unlink(name);
427ee13240eSMarc-André Lureau }
428ee13240eSMarc-André Lureau 
429ee13240eSMarc-André Lureau /*
430baacf047SPaolo Bonzini  * A variant of write(2) which handles partial write.
431baacf047SPaolo Bonzini  *
432baacf047SPaolo Bonzini  * Return the number of bytes transferred.
433baacf047SPaolo Bonzini  * Set errno if fewer than `count' bytes are written.
434baacf047SPaolo Bonzini  *
435baacf047SPaolo Bonzini  * This function don't work with non-blocking fd's.
4368cc360b9Szhaolichang  * Any of the possibilities with non-blocking fd's is bad:
437baacf047SPaolo Bonzini  *   - return a short write (then name is wrong)
438baacf047SPaolo Bonzini  *   - busy wait adding (errno == EAGAIN) to the loop
439baacf047SPaolo Bonzini  */
qemu_write_full(int fd,const void * buf,size_t count)440baacf047SPaolo Bonzini ssize_t qemu_write_full(int fd, const void *buf, size_t count)
441baacf047SPaolo Bonzini {
442baacf047SPaolo Bonzini     ssize_t ret = 0;
443baacf047SPaolo Bonzini     ssize_t total = 0;
444baacf047SPaolo Bonzini 
445baacf047SPaolo Bonzini     while (count) {
446baacf047SPaolo Bonzini         ret = write(fd, buf, count);
447baacf047SPaolo Bonzini         if (ret < 0) {
448baacf047SPaolo Bonzini             if (errno == EINTR)
449baacf047SPaolo Bonzini                 continue;
450baacf047SPaolo Bonzini             break;
451baacf047SPaolo Bonzini         }
452baacf047SPaolo Bonzini 
453baacf047SPaolo Bonzini         count -= ret;
454baacf047SPaolo Bonzini         buf += ret;
455baacf047SPaolo Bonzini         total += ret;
456baacf047SPaolo Bonzini     }
457baacf047SPaolo Bonzini 
458baacf047SPaolo Bonzini     return total;
459baacf047SPaolo Bonzini }
460baacf047SPaolo Bonzini 
461baacf047SPaolo Bonzini /*
462baacf047SPaolo Bonzini  * Opens a socket with FD_CLOEXEC set
463baacf047SPaolo Bonzini  */
qemu_socket(int domain,int type,int protocol)464baacf047SPaolo Bonzini int qemu_socket(int domain, int type, int protocol)
465baacf047SPaolo Bonzini {
466baacf047SPaolo Bonzini     int ret;
467baacf047SPaolo Bonzini 
468baacf047SPaolo Bonzini #ifdef SOCK_CLOEXEC
469baacf047SPaolo Bonzini     ret = socket(domain, type | SOCK_CLOEXEC, protocol);
470baacf047SPaolo Bonzini     if (ret != -1 || errno != EINVAL) {
471baacf047SPaolo Bonzini         return ret;
472baacf047SPaolo Bonzini     }
473baacf047SPaolo Bonzini #endif
474baacf047SPaolo Bonzini     ret = socket(domain, type, protocol);
475baacf047SPaolo Bonzini     if (ret >= 0) {
476baacf047SPaolo Bonzini         qemu_set_cloexec(ret);
477baacf047SPaolo Bonzini     }
478baacf047SPaolo Bonzini 
479baacf047SPaolo Bonzini     return ret;
480baacf047SPaolo Bonzini }
481baacf047SPaolo Bonzini 
482baacf047SPaolo Bonzini /*
483baacf047SPaolo Bonzini  * Accept a connection and set FD_CLOEXEC
484baacf047SPaolo Bonzini  */
qemu_accept(int s,struct sockaddr * addr,socklen_t * addrlen)485baacf047SPaolo Bonzini int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
486baacf047SPaolo Bonzini {
487baacf047SPaolo Bonzini     int ret;
488baacf047SPaolo Bonzini 
489baacf047SPaolo Bonzini #ifdef CONFIG_ACCEPT4
490baacf047SPaolo Bonzini     ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
491baacf047SPaolo Bonzini     if (ret != -1 || errno != ENOSYS) {
492baacf047SPaolo Bonzini         return ret;
493baacf047SPaolo Bonzini     }
494baacf047SPaolo Bonzini #endif
495baacf047SPaolo Bonzini     ret = accept(s, addr, addrlen);
496baacf047SPaolo Bonzini     if (ret >= 0) {
497baacf047SPaolo Bonzini         qemu_set_cloexec(ret);
498baacf047SPaolo Bonzini     }
499baacf047SPaolo Bonzini 
500baacf047SPaolo Bonzini     return ret;
501baacf047SPaolo Bonzini }
502baacf047SPaolo Bonzini 
qemu_send_full(int s,const void * buf,size_t count)50384c662d2SXuzhou Cheng ssize_t qemu_send_full(int s, const void *buf, size_t count)
50484c662d2SXuzhou Cheng {
50584c662d2SXuzhou Cheng     ssize_t ret = 0;
50684c662d2SXuzhou Cheng     ssize_t total = 0;
50784c662d2SXuzhou Cheng 
50884c662d2SXuzhou Cheng     while (count) {
50984c662d2SXuzhou Cheng         ret = send(s, buf, count, 0);
51084c662d2SXuzhou Cheng         if (ret < 0) {
51184c662d2SXuzhou Cheng             if (errno == EINTR) {
51284c662d2SXuzhou Cheng                 continue;
51384c662d2SXuzhou Cheng             }
51484c662d2SXuzhou Cheng             break;
51584c662d2SXuzhou Cheng         }
51684c662d2SXuzhou Cheng 
51784c662d2SXuzhou Cheng         count -= ret;
51884c662d2SXuzhou Cheng         buf += ret;
51984c662d2SXuzhou Cheng         total += ret;
52084c662d2SXuzhou Cheng     }
52184c662d2SXuzhou Cheng 
52284c662d2SXuzhou Cheng     return total;
52384c662d2SXuzhou Cheng }
52484c662d2SXuzhou Cheng 
qemu_set_hw_version(const char * version)52535c2c8dcSEduardo Habkost void qemu_set_hw_version(const char *version)
526baacf047SPaolo Bonzini {
52735c2c8dcSEduardo Habkost     hw_version = version;
528baacf047SPaolo Bonzini }
529baacf047SPaolo Bonzini 
qemu_hw_version(void)53035c2c8dcSEduardo Habkost const char *qemu_hw_version(void)
531baacf047SPaolo Bonzini {
53235c2c8dcSEduardo Habkost     return hw_version;
533baacf047SPaolo Bonzini }
534baacf047SPaolo Bonzini 
535d3bf825eSMarc-André Lureau #ifdef _WIN32
socket_cleanup(void)536d3bf825eSMarc-André Lureau static void socket_cleanup(void)
537d3bf825eSMarc-André Lureau {
538d3bf825eSMarc-André Lureau     WSACleanup();
539d3bf825eSMarc-André Lureau }
540d3bf825eSMarc-André Lureau #endif
541d3bf825eSMarc-André Lureau 
socket_init(void)542d3bf825eSMarc-André Lureau int socket_init(void)
543d3bf825eSMarc-André Lureau {
544d3bf825eSMarc-André Lureau #ifdef _WIN32
545d3bf825eSMarc-André Lureau     WSADATA Data;
546d3bf825eSMarc-André Lureau     int ret, err;
547d3bf825eSMarc-André Lureau 
548d3bf825eSMarc-André Lureau     ret = WSAStartup(MAKEWORD(2, 2), &Data);
549d3bf825eSMarc-André Lureau     if (ret != 0) {
550d3bf825eSMarc-André Lureau         err = WSAGetLastError();
551d3bf825eSMarc-André Lureau         fprintf(stderr, "WSAStartup: %d\n", err);
552d3bf825eSMarc-André Lureau         return -1;
553d3bf825eSMarc-André Lureau     }
554d3bf825eSMarc-André Lureau     atexit(socket_cleanup);
555d3bf825eSMarc-André Lureau #endif
556d3bf825eSMarc-André Lureau     return 0;
557d3bf825eSMarc-André Lureau }
5589adea5f7SPaolo Bonzini 
559ae2990c2SStefan Hajnoczi 
5609adea5f7SPaolo Bonzini #ifndef CONFIG_IOVEC
5619adea5f7SPaolo Bonzini static ssize_t
readv_writev(int fd,const struct iovec * iov,int iov_cnt,bool do_write)5629adea5f7SPaolo Bonzini readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
5639adea5f7SPaolo Bonzini {
5649adea5f7SPaolo Bonzini     unsigned i = 0;
5659adea5f7SPaolo Bonzini     ssize_t ret = 0;
566c1f79809SMarc-André Lureau     ssize_t off = 0;
5679adea5f7SPaolo Bonzini     while (i < iov_cnt) {
5689adea5f7SPaolo Bonzini         ssize_t r = do_write
569c1f79809SMarc-André Lureau             ? write(fd, iov[i].iov_base + off, iov[i].iov_len - off)
570c1f79809SMarc-André Lureau             : read(fd, iov[i].iov_base + off, iov[i].iov_len - off);
5719adea5f7SPaolo Bonzini         if (r > 0) {
5729adea5f7SPaolo Bonzini             ret += r;
573c1f79809SMarc-André Lureau             off += r;
574c1f79809SMarc-André Lureau             if (off < iov[i].iov_len) {
575c1f79809SMarc-André Lureau                 continue;
576c1f79809SMarc-André Lureau             }
5779adea5f7SPaolo Bonzini         } else if (!r) {
5789adea5f7SPaolo Bonzini             break;
5799adea5f7SPaolo Bonzini         } else if (errno == EINTR) {
5809adea5f7SPaolo Bonzini             continue;
5819adea5f7SPaolo Bonzini         } else {
5829adea5f7SPaolo Bonzini             /* else it is some "other" error,
5839adea5f7SPaolo Bonzini              * only return if there was no data processed. */
5849adea5f7SPaolo Bonzini             if (ret == 0) {
5859adea5f7SPaolo Bonzini                 ret = -1;
5869adea5f7SPaolo Bonzini             }
5879adea5f7SPaolo Bonzini             break;
5889adea5f7SPaolo Bonzini         }
589c1f79809SMarc-André Lureau         off = 0;
5909adea5f7SPaolo Bonzini         i++;
5919adea5f7SPaolo Bonzini     }
5929adea5f7SPaolo Bonzini     return ret;
5939adea5f7SPaolo Bonzini }
5949adea5f7SPaolo Bonzini 
5959adea5f7SPaolo Bonzini ssize_t
readv(int fd,const struct iovec * iov,int iov_cnt)5969adea5f7SPaolo Bonzini readv(int fd, const struct iovec *iov, int iov_cnt)
5979adea5f7SPaolo Bonzini {
5989adea5f7SPaolo Bonzini     return readv_writev(fd, iov, iov_cnt, false);
5999adea5f7SPaolo Bonzini }
6009adea5f7SPaolo Bonzini 
6019adea5f7SPaolo Bonzini ssize_t
writev(int fd,const struct iovec * iov,int iov_cnt)6029adea5f7SPaolo Bonzini writev(int fd, const struct iovec *iov, int iov_cnt)
6039adea5f7SPaolo Bonzini {
6049adea5f7SPaolo Bonzini     return readv_writev(fd, iov, iov_cnt, true);
6059adea5f7SPaolo Bonzini }
6069adea5f7SPaolo Bonzini #endif
607282468c7SMarc-André Lureau 
608282468c7SMarc-André Lureau /*
609282468c7SMarc-André Lureau  * Make sure data goes on disk, but if possible do not bother to
610282468c7SMarc-André Lureau  * write out the inode just for timestamp updates.
611282468c7SMarc-André Lureau  *
612282468c7SMarc-André Lureau  * Unfortunately even in 2009 many operating systems do not support
613282468c7SMarc-André Lureau  * fdatasync and have to fall back to fsync.
614282468c7SMarc-André Lureau  */
qemu_fdatasync(int fd)615282468c7SMarc-André Lureau int qemu_fdatasync(int fd)
616282468c7SMarc-André Lureau {
617282468c7SMarc-André Lureau #ifdef CONFIG_FDATASYNC
618282468c7SMarc-André Lureau     return fdatasync(fd);
619282468c7SMarc-André Lureau #else
620282468c7SMarc-André Lureau     return fsync(fd);
621282468c7SMarc-André Lureau #endif
622282468c7SMarc-André Lureau }
623