xref: /openbmc/qemu/util/osdep.c (revision ffeddb979400b1580ad28acbee09b6f971c3912d)
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)
60bfb8c79fSMichal Privoznik     int rc = posix_madvise(addr, len, advice);
61bfb8c79fSMichal Privoznik     if (rc) {
62bfb8c79fSMichal Privoznik         errno = rc;
63bfb8c79fSMichal Privoznik         return -1;
64bfb8c79fSMichal Privoznik     }
65bfb8c79fSMichal Privoznik     return 0;
66baacf047SPaolo Bonzini #else
67210b7b2bSMichal Privoznik     errno = ENOSYS;
68baacf047SPaolo Bonzini     return -1;
69baacf047SPaolo Bonzini #endif
70baacf047SPaolo Bonzini }
71baacf047SPaolo Bonzini 
qemu_mprotect__osdep(void * addr,size_t size,int prot)725fa64b31SEmilio G. Cota static int qemu_mprotect__osdep(void *addr, size_t size, int prot)
735fa64b31SEmilio G. Cota {
748e3b0cbbSMarc-André Lureau     g_assert(!((uintptr_t)addr & ~qemu_real_host_page_mask()));
758e3b0cbbSMarc-André Lureau     g_assert(!(size & ~qemu_real_host_page_mask()));
765fa64b31SEmilio G. Cota 
775fa64b31SEmilio G. Cota #ifdef _WIN32
785fa64b31SEmilio G. Cota     DWORD old_protect;
795fa64b31SEmilio G. Cota 
805fa64b31SEmilio G. Cota     if (!VirtualProtect(addr, size, prot, &old_protect)) {
81cf0c76cdSPhilippe Mathieu-Daudé         g_autofree gchar *emsg = g_win32_error_message(GetLastError());
82cf0c76cdSPhilippe Mathieu-Daudé         error_report("%s: VirtualProtect failed: %s", __func__, emsg);
835fa64b31SEmilio G. Cota         return -1;
845fa64b31SEmilio G. Cota     }
855fa64b31SEmilio G. Cota     return 0;
865fa64b31SEmilio G. Cota #else
875fa64b31SEmilio G. Cota     if (mprotect(addr, size, prot)) {
885fa64b31SEmilio G. Cota         error_report("%s: mprotect failed: %s", __func__, strerror(errno));
895fa64b31SEmilio G. Cota         return -1;
905fa64b31SEmilio G. Cota     }
915fa64b31SEmilio G. Cota     return 0;
925fa64b31SEmilio G. Cota #endif
935fa64b31SEmilio G. Cota }
945fa64b31SEmilio G. Cota 
qemu_mprotect_rw(void * addr,size_t size)95d7107fc0SRichard Henderson int qemu_mprotect_rw(void *addr, size_t size)
96d7107fc0SRichard Henderson {
97d7107fc0SRichard Henderson #ifdef _WIN32
98d7107fc0SRichard Henderson     return qemu_mprotect__osdep(addr, size, PAGE_READWRITE);
99d7107fc0SRichard Henderson #else
100d7107fc0SRichard Henderson     return qemu_mprotect__osdep(addr, size, PROT_READ | PROT_WRITE);
101d7107fc0SRichard Henderson #endif
102d7107fc0SRichard Henderson }
103d7107fc0SRichard Henderson 
qemu_mprotect_rwx(void * addr,size_t size)1045fa64b31SEmilio G. Cota int qemu_mprotect_rwx(void *addr, size_t size)
1055fa64b31SEmilio G. Cota {
1065fa64b31SEmilio G. Cota #ifdef _WIN32
1075fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PAGE_EXECUTE_READWRITE);
1085fa64b31SEmilio G. Cota #else
1095fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
1105fa64b31SEmilio G. Cota #endif
1115fa64b31SEmilio G. Cota }
1125fa64b31SEmilio G. Cota 
qemu_mprotect_none(void * addr,size_t size)1135fa64b31SEmilio G. Cota int qemu_mprotect_none(void *addr, size_t size)
1145fa64b31SEmilio G. Cota {
1155fa64b31SEmilio G. Cota #ifdef _WIN32
1165fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PAGE_NOACCESS);
1175fa64b31SEmilio G. Cota #else
1185fa64b31SEmilio G. Cota     return qemu_mprotect__osdep(addr, size, PROT_NONE);
1195fa64b31SEmilio G. Cota #endif
1205fa64b31SEmilio G. Cota }
1215fa64b31SEmilio G. Cota 
122baacf047SPaolo Bonzini #ifndef _WIN32
123ca749954SFam Zheng 
124ca749954SFam Zheng static int fcntl_op_setlk = -1;
125ca749954SFam Zheng static int fcntl_op_getlk = -1;
126ca749954SFam Zheng 
127baacf047SPaolo Bonzini /*
128baacf047SPaolo Bonzini  * Dups an fd and sets the flags
129baacf047SPaolo Bonzini  */
qemu_dup_flags(int fd,int flags)13060efffa4SDaniel P. Berrangé int qemu_dup_flags(int fd, int flags)
131baacf047SPaolo Bonzini {
132baacf047SPaolo Bonzini     int ret;
133baacf047SPaolo Bonzini     int serrno;
134baacf047SPaolo Bonzini     int dup_flags;
135baacf047SPaolo Bonzini 
136761d1ddfSFam Zheng     ret = qemu_dup(fd);
137baacf047SPaolo Bonzini     if (ret == -1) {
138baacf047SPaolo Bonzini         goto fail;
139baacf047SPaolo Bonzini     }
140baacf047SPaolo Bonzini 
141baacf047SPaolo Bonzini     dup_flags = fcntl(ret, F_GETFL);
142baacf047SPaolo Bonzini     if (dup_flags == -1) {
143baacf047SPaolo Bonzini         goto fail;
144baacf047SPaolo Bonzini     }
145baacf047SPaolo Bonzini 
146baacf047SPaolo Bonzini     if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
147baacf047SPaolo Bonzini         errno = EINVAL;
148baacf047SPaolo Bonzini         goto fail;
149baacf047SPaolo Bonzini     }
150baacf047SPaolo Bonzini 
151baacf047SPaolo Bonzini     /* Set/unset flags that we can with fcntl */
152baacf047SPaolo Bonzini     if (fcntl(ret, F_SETFL, flags) == -1) {
153baacf047SPaolo Bonzini         goto fail;
154baacf047SPaolo Bonzini     }
155baacf047SPaolo Bonzini 
156baacf047SPaolo Bonzini     /* Truncate the file in the cases that open() would truncate it */
157baacf047SPaolo Bonzini     if (flags & O_TRUNC ||
158baacf047SPaolo Bonzini             ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
159baacf047SPaolo Bonzini         if (ftruncate(ret, 0) == -1) {
160baacf047SPaolo Bonzini             goto fail;
161baacf047SPaolo Bonzini         }
162baacf047SPaolo Bonzini     }
163baacf047SPaolo Bonzini 
164baacf047SPaolo Bonzini     return ret;
165baacf047SPaolo Bonzini 
166baacf047SPaolo Bonzini fail:
167baacf047SPaolo Bonzini     serrno = errno;
168baacf047SPaolo Bonzini     if (ret != -1) {
169baacf047SPaolo Bonzini         close(ret);
170baacf047SPaolo Bonzini     }
171baacf047SPaolo Bonzini     errno = serrno;
172baacf047SPaolo Bonzini     return -1;
173baacf047SPaolo Bonzini }
174baacf047SPaolo Bonzini 
qemu_dup(int fd)175761d1ddfSFam Zheng int qemu_dup(int fd)
176761d1ddfSFam Zheng {
177761d1ddfSFam Zheng     int ret;
178761d1ddfSFam Zheng #ifdef F_DUPFD_CLOEXEC
179761d1ddfSFam Zheng     ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
180761d1ddfSFam Zheng #else
181761d1ddfSFam Zheng     ret = dup(fd);
182761d1ddfSFam Zheng     if (ret != -1) {
183761d1ddfSFam Zheng         qemu_set_cloexec(ret);
184761d1ddfSFam Zheng     }
185761d1ddfSFam Zheng #endif
186761d1ddfSFam Zheng     return ret;
187761d1ddfSFam Zheng }
188761d1ddfSFam Zheng 
qemu_parse_fdset(const char * param)189baacf047SPaolo Bonzini static int qemu_parse_fdset(const char *param)
190baacf047SPaolo Bonzini {
191baacf047SPaolo Bonzini     return qemu_parse_fd(param);
192baacf047SPaolo Bonzini }
19313461fdbSFam Zheng 
qemu_probe_lock_ops(void)194ca749954SFam Zheng static void qemu_probe_lock_ops(void)
195ca749954SFam Zheng {
196ca749954SFam Zheng     if (fcntl_op_setlk == -1) {
197ca749954SFam Zheng #ifdef F_OFD_SETLK
198ca749954SFam Zheng         int fd;
199ca749954SFam Zheng         int ret;
200ca749954SFam Zheng         struct flock fl = {
201ca749954SFam Zheng             .l_whence = SEEK_SET,
202ca749954SFam Zheng             .l_start  = 0,
203ca749954SFam Zheng             .l_len    = 0,
204ca749954SFam Zheng             .l_type   = F_WRLCK,
205ca749954SFam Zheng         };
206ca749954SFam Zheng 
207ca749954SFam Zheng         fd = open("/dev/null", O_RDWR);
208ca749954SFam Zheng         if (fd < 0) {
209ca749954SFam Zheng             fprintf(stderr,
210ca749954SFam Zheng                     "Failed to open /dev/null for OFD lock probing: %s\n",
211ca749954SFam Zheng                     strerror(errno));
212ca749954SFam Zheng             fcntl_op_setlk = F_SETLK;
213ca749954SFam Zheng             fcntl_op_getlk = F_GETLK;
214ca749954SFam Zheng             return;
215ca749954SFam Zheng         }
216ca749954SFam Zheng         ret = fcntl(fd, F_OFD_GETLK, &fl);
217ca749954SFam Zheng         close(fd);
218ca749954SFam Zheng         if (!ret) {
219ca749954SFam Zheng             fcntl_op_setlk = F_OFD_SETLK;
220ca749954SFam Zheng             fcntl_op_getlk = F_OFD_GETLK;
221ca749954SFam Zheng         } else {
222ca749954SFam Zheng             fcntl_op_setlk = F_SETLK;
223ca749954SFam Zheng             fcntl_op_getlk = F_GETLK;
224ca749954SFam Zheng         }
225ca749954SFam Zheng #else
226ca749954SFam Zheng         fcntl_op_setlk = F_SETLK;
227ca749954SFam Zheng         fcntl_op_getlk = F_GETLK;
228ca749954SFam Zheng #endif
229ca749954SFam Zheng     }
230ca749954SFam Zheng }
231ca749954SFam Zheng 
qemu_has_ofd_lock(void)232ca749954SFam Zheng bool qemu_has_ofd_lock(void)
233ca749954SFam Zheng {
234ca749954SFam Zheng     qemu_probe_lock_ops();
235ca749954SFam Zheng #ifdef F_OFD_SETLK
236ca749954SFam Zheng     return fcntl_op_setlk == F_OFD_SETLK;
237ca749954SFam Zheng #else
238ca749954SFam Zheng     return false;
239ca749954SFam Zheng #endif
240ca749954SFam Zheng }
241ca749954SFam Zheng 
qemu_lock_fcntl(int fd,int64_t start,int64_t len,int fl_type)24213461fdbSFam Zheng static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
24313461fdbSFam Zheng {
24413461fdbSFam Zheng     int ret;
24513461fdbSFam Zheng     struct flock fl = {
24613461fdbSFam Zheng         .l_whence = SEEK_SET,
24713461fdbSFam Zheng         .l_start  = start,
24813461fdbSFam Zheng         .l_len    = len,
24913461fdbSFam Zheng         .l_type   = fl_type,
25013461fdbSFam Zheng     };
251ca749954SFam Zheng     qemu_probe_lock_ops();
25237b0b24eSNikita Ivanov     ret = RETRY_ON_EINTR(fcntl(fd, fcntl_op_setlk, &fl));
25313461fdbSFam Zheng     return ret == -1 ? -errno : 0;
25413461fdbSFam Zheng }
25513461fdbSFam Zheng 
qemu_lock_fd(int fd,int64_t start,int64_t len,bool exclusive)25613461fdbSFam Zheng int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive)
25713461fdbSFam Zheng {
25813461fdbSFam Zheng     return qemu_lock_fcntl(fd, start, len, exclusive ? F_WRLCK : F_RDLCK);
25913461fdbSFam Zheng }
26013461fdbSFam Zheng 
qemu_unlock_fd(int fd,int64_t start,int64_t len)26113461fdbSFam Zheng int qemu_unlock_fd(int fd, int64_t start, int64_t len)
26213461fdbSFam Zheng {
26313461fdbSFam Zheng     return qemu_lock_fcntl(fd, start, len, F_UNLCK);
26413461fdbSFam Zheng }
26513461fdbSFam Zheng 
qemu_lock_fd_test(int fd,int64_t start,int64_t len,bool exclusive)26613461fdbSFam Zheng int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
26713461fdbSFam Zheng {
26813461fdbSFam Zheng     int ret;
26913461fdbSFam Zheng     struct flock fl = {
27013461fdbSFam Zheng         .l_whence = SEEK_SET,
27113461fdbSFam Zheng         .l_start  = start,
27213461fdbSFam Zheng         .l_len    = len,
27313461fdbSFam Zheng         .l_type   = exclusive ? F_WRLCK : F_RDLCK,
27413461fdbSFam Zheng     };
275ca749954SFam Zheng     qemu_probe_lock_ops();
276ca749954SFam Zheng     ret = fcntl(fd, fcntl_op_getlk, &fl);
27713461fdbSFam Zheng     if (ret == -1) {
27813461fdbSFam Zheng         return -errno;
27913461fdbSFam Zheng     } else {
28013461fdbSFam Zheng         return fl.l_type == F_UNLCK ? 0 : -EAGAIN;
28113461fdbSFam Zheng     }
28213461fdbSFam Zheng }
283baacf047SPaolo Bonzini #endif
284baacf047SPaolo Bonzini 
qemu_has_direct_io(void)285*b43b61d5SFabiano Rosas bool qemu_has_direct_io(void)
286*b43b61d5SFabiano Rosas {
287*b43b61d5SFabiano Rosas #ifdef O_DIRECT
288*b43b61d5SFabiano Rosas     return true;
289*b43b61d5SFabiano Rosas #else
290*b43b61d5SFabiano Rosas     return false;
291*b43b61d5SFabiano Rosas #endif
292*b43b61d5SFabiano Rosas }
293*b43b61d5SFabiano Rosas 
qemu_open_cloexec(const char * name,int flags,mode_t mode)294c2069ff6SDaniel P. Berrangé static int qemu_open_cloexec(const char *name, int flags, mode_t mode)
295c2069ff6SDaniel P. Berrangé {
296c2069ff6SDaniel P. Berrangé     int ret;
297c2069ff6SDaniel P. Berrangé #ifdef O_CLOEXEC
298c2069ff6SDaniel P. Berrangé     ret = open(name, flags | O_CLOEXEC, mode);
299c2069ff6SDaniel P. Berrangé #else
300c2069ff6SDaniel P. Berrangé     ret = open(name, flags, mode);
301c2069ff6SDaniel P. Berrangé     if (ret >= 0) {
302c2069ff6SDaniel P. Berrangé         qemu_set_cloexec(ret);
303c2069ff6SDaniel P. Berrangé     }
304c2069ff6SDaniel P. Berrangé #endif
305c2069ff6SDaniel P. Berrangé     return ret;
306c2069ff6SDaniel P. Berrangé }
307c2069ff6SDaniel P. Berrangé 
308baacf047SPaolo Bonzini /*
309baacf047SPaolo Bonzini  * Opens a file with FD_CLOEXEC set
310baacf047SPaolo Bonzini  */
311bf93d2adSDaniel P. Berrangé static int
qemu_open_internal(const char * name,int flags,mode_t mode,Error ** errp)312ebb3d49cSDaniel P. Berrangé qemu_open_internal(const char *name, int flags, mode_t mode, Error **errp)
313baacf047SPaolo Bonzini {
314baacf047SPaolo Bonzini     int ret;
315baacf047SPaolo Bonzini 
316baacf047SPaolo Bonzini #ifndef _WIN32
317baacf047SPaolo Bonzini     const char *fdset_id_str;
318baacf047SPaolo Bonzini 
319baacf047SPaolo Bonzini     /* Attempt dup of fd from fd set */
320baacf047SPaolo Bonzini     if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
321baacf047SPaolo Bonzini         int64_t fdset_id;
322baacf047SPaolo Bonzini 
323baacf047SPaolo Bonzini         fdset_id = qemu_parse_fdset(fdset_id_str);
324baacf047SPaolo Bonzini         if (fdset_id == -1) {
325ebb3d49cSDaniel P. Berrangé             error_setg(errp, "Could not parse fdset %s", name);
326baacf047SPaolo Bonzini             errno = EINVAL;
327baacf047SPaolo Bonzini             return -1;
328baacf047SPaolo Bonzini         }
329baacf047SPaolo Bonzini 
330960f29b3SFabiano Rosas         return monitor_fdset_dup_fd_add(fdset_id, flags, errp);
331baacf047SPaolo Bonzini     }
332baacf047SPaolo Bonzini #endif
333baacf047SPaolo Bonzini 
334bf93d2adSDaniel P. Berrangé     ret = qemu_open_cloexec(name, flags, mode);
335baacf047SPaolo Bonzini 
336ebb3d49cSDaniel P. Berrangé     if (ret == -1) {
337ebb3d49cSDaniel P. Berrangé         const char *action = flags & O_CREAT ? "create" : "open";
338661b3e81SDaniel P. Berrangé #ifdef O_DIRECT
339661b3e81SDaniel P. Berrangé         /* Give more helpful error message for O_DIRECT */
340661b3e81SDaniel P. Berrangé         if (errno == EINVAL && (flags & O_DIRECT)) {
341661b3e81SDaniel P. Berrangé             ret = open(name, flags & ~O_DIRECT, mode);
342661b3e81SDaniel P. Berrangé             if (ret != -1) {
343661b3e81SDaniel P. Berrangé                 close(ret);
344661b3e81SDaniel P. Berrangé                 error_setg(errp, "Could not %s '%s': "
345661b3e81SDaniel P. Berrangé                            "filesystem does not support O_DIRECT",
346661b3e81SDaniel P. Berrangé                            action, name);
347661b3e81SDaniel P. Berrangé                 errno = EINVAL; /* restore first open()'s errno */
348661b3e81SDaniel P. Berrangé                 return -1;
349661b3e81SDaniel P. Berrangé             }
350661b3e81SDaniel P. Berrangé         }
351661b3e81SDaniel P. Berrangé #endif /* O_DIRECT */
352ebb3d49cSDaniel P. Berrangé         error_setg_errno(errp, errno, "Could not %s '%s'",
353ebb3d49cSDaniel P. Berrangé                          action, name);
354ebb3d49cSDaniel P. Berrangé     }
355ebb3d49cSDaniel P. Berrangé 
356bf93d2adSDaniel P. Berrangé     return ret;
357baacf047SPaolo Bonzini }
358baacf047SPaolo Bonzini 
359bf93d2adSDaniel P. Berrangé 
qemu_open(const char * name,int flags,Error ** errp)360c490af57SDaniel P. Berrangé int qemu_open(const char *name, int flags, Error **errp)
361c490af57SDaniel P. Berrangé {
362c490af57SDaniel P. Berrangé     assert(!(flags & O_CREAT));
363c490af57SDaniel P. Berrangé 
364c490af57SDaniel P. Berrangé     return qemu_open_internal(name, flags, 0, errp);
365c490af57SDaniel P. Berrangé }
366c490af57SDaniel P. Berrangé 
367c490af57SDaniel P. Berrangé 
qemu_create(const char * name,int flags,mode_t mode,Error ** errp)368c490af57SDaniel P. Berrangé int qemu_create(const char *name, int flags, mode_t mode, Error **errp)
369c490af57SDaniel P. Berrangé {
370c490af57SDaniel P. Berrangé     assert(!(flags & O_CREAT));
371c490af57SDaniel P. Berrangé 
372c490af57SDaniel P. Berrangé     return qemu_open_internal(name, flags | O_CREAT, mode, errp);
373c490af57SDaniel P. Berrangé }
374c490af57SDaniel P. Berrangé 
375c490af57SDaniel P. Berrangé 
qemu_open_old(const char * name,int flags,...)376bf93d2adSDaniel P. Berrangé int qemu_open_old(const char *name, int flags, ...)
377bf93d2adSDaniel P. Berrangé {
378bf93d2adSDaniel P. Berrangé     va_list ap;
379bf93d2adSDaniel P. Berrangé     mode_t mode = 0;
380bf93d2adSDaniel P. Berrangé     int ret;
381bf93d2adSDaniel P. Berrangé 
382bf93d2adSDaniel P. Berrangé     va_start(ap, flags);
383bf93d2adSDaniel P. Berrangé     if (flags & O_CREAT) {
384bf93d2adSDaniel P. Berrangé         mode = va_arg(ap, int);
385bf93d2adSDaniel P. Berrangé     }
386bf93d2adSDaniel P. Berrangé     va_end(ap);
387bf93d2adSDaniel P. Berrangé 
388ebb3d49cSDaniel P. Berrangé     ret = qemu_open_internal(name, flags, mode, NULL);
389baacf047SPaolo Bonzini 
390a5813077SStefan Hajnoczi #ifdef O_DIRECT
391a5813077SStefan Hajnoczi     if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
392a5813077SStefan Hajnoczi         error_report("file system may not support O_DIRECT");
393a5813077SStefan Hajnoczi         errno = EINVAL; /* in case it was clobbered */
394a5813077SStefan Hajnoczi     }
395a5813077SStefan Hajnoczi #endif /* O_DIRECT */
396a5813077SStefan Hajnoczi 
397baacf047SPaolo Bonzini     return ret;
398baacf047SPaolo Bonzini }
399baacf047SPaolo Bonzini 
qemu_close(int fd)400baacf047SPaolo Bonzini int qemu_close(int fd)
401baacf047SPaolo Bonzini {
402baacf047SPaolo Bonzini     /* Close fd that was dup'd from an fdset */
403baacf047SPaolo Bonzini     monitor_fdset_dup_fd_remove(fd);
404baacf047SPaolo Bonzini     return close(fd);
405baacf047SPaolo Bonzini }
406baacf047SPaolo Bonzini 
407baacf047SPaolo Bonzini /*
408ee13240eSMarc-André Lureau  * Delete a file from the filesystem, unless the filename is /dev/fdset/...
409ee13240eSMarc-André Lureau  *
410ee13240eSMarc-André Lureau  * Returns: On success, zero is returned.  On error, -1 is returned,
411ee13240eSMarc-André Lureau  * and errno is set appropriately.
412ee13240eSMarc-André Lureau  */
qemu_unlink(const char * name)413ee13240eSMarc-André Lureau int qemu_unlink(const char *name)
414ee13240eSMarc-André Lureau {
415ee13240eSMarc-André Lureau     if (g_str_has_prefix(name, "/dev/fdset/")) {
416ee13240eSMarc-André Lureau         return 0;
417ee13240eSMarc-André Lureau     }
418ee13240eSMarc-André Lureau 
419ee13240eSMarc-André Lureau     return unlink(name);
420ee13240eSMarc-André Lureau }
421ee13240eSMarc-André Lureau 
422ee13240eSMarc-André Lureau /*
423baacf047SPaolo Bonzini  * A variant of write(2) which handles partial write.
424baacf047SPaolo Bonzini  *
425baacf047SPaolo Bonzini  * Return the number of bytes transferred.
426baacf047SPaolo Bonzini  * Set errno if fewer than `count' bytes are written.
427baacf047SPaolo Bonzini  *
428baacf047SPaolo Bonzini  * This function don't work with non-blocking fd's.
4298cc360b9Szhaolichang  * Any of the possibilities with non-blocking fd's is bad:
430baacf047SPaolo Bonzini  *   - return a short write (then name is wrong)
431baacf047SPaolo Bonzini  *   - busy wait adding (errno == EAGAIN) to the loop
432baacf047SPaolo Bonzini  */
qemu_write_full(int fd,const void * buf,size_t count)433baacf047SPaolo Bonzini ssize_t qemu_write_full(int fd, const void *buf, size_t count)
434baacf047SPaolo Bonzini {
435baacf047SPaolo Bonzini     ssize_t ret = 0;
436baacf047SPaolo Bonzini     ssize_t total = 0;
437baacf047SPaolo Bonzini 
438baacf047SPaolo Bonzini     while (count) {
439baacf047SPaolo Bonzini         ret = write(fd, buf, count);
440baacf047SPaolo Bonzini         if (ret < 0) {
441baacf047SPaolo Bonzini             if (errno == EINTR)
442baacf047SPaolo Bonzini                 continue;
443baacf047SPaolo Bonzini             break;
444baacf047SPaolo Bonzini         }
445baacf047SPaolo Bonzini 
446baacf047SPaolo Bonzini         count -= ret;
447baacf047SPaolo Bonzini         buf += ret;
448baacf047SPaolo Bonzini         total += ret;
449baacf047SPaolo Bonzini     }
450baacf047SPaolo Bonzini 
451baacf047SPaolo Bonzini     return total;
452baacf047SPaolo Bonzini }
453baacf047SPaolo Bonzini 
454baacf047SPaolo Bonzini /*
455baacf047SPaolo Bonzini  * Opens a socket with FD_CLOEXEC set
456baacf047SPaolo Bonzini  */
qemu_socket(int domain,int type,int protocol)457baacf047SPaolo Bonzini int qemu_socket(int domain, int type, int protocol)
458baacf047SPaolo Bonzini {
459baacf047SPaolo Bonzini     int ret;
460baacf047SPaolo Bonzini 
461baacf047SPaolo Bonzini #ifdef SOCK_CLOEXEC
462baacf047SPaolo Bonzini     ret = socket(domain, type | SOCK_CLOEXEC, protocol);
463baacf047SPaolo Bonzini     if (ret != -1 || errno != EINVAL) {
464baacf047SPaolo Bonzini         return ret;
465baacf047SPaolo Bonzini     }
466baacf047SPaolo Bonzini #endif
467baacf047SPaolo Bonzini     ret = socket(domain, type, protocol);
468baacf047SPaolo Bonzini     if (ret >= 0) {
469baacf047SPaolo Bonzini         qemu_set_cloexec(ret);
470baacf047SPaolo Bonzini     }
471baacf047SPaolo Bonzini 
472baacf047SPaolo Bonzini     return ret;
473baacf047SPaolo Bonzini }
474baacf047SPaolo Bonzini 
475baacf047SPaolo Bonzini /*
476baacf047SPaolo Bonzini  * Accept a connection and set FD_CLOEXEC
477baacf047SPaolo Bonzini  */
qemu_accept(int s,struct sockaddr * addr,socklen_t * addrlen)478baacf047SPaolo Bonzini int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
479baacf047SPaolo Bonzini {
480baacf047SPaolo Bonzini     int ret;
481baacf047SPaolo Bonzini 
482baacf047SPaolo Bonzini #ifdef CONFIG_ACCEPT4
483baacf047SPaolo Bonzini     ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
484baacf047SPaolo Bonzini     if (ret != -1 || errno != ENOSYS) {
485baacf047SPaolo Bonzini         return ret;
486baacf047SPaolo Bonzini     }
487baacf047SPaolo Bonzini #endif
488baacf047SPaolo Bonzini     ret = accept(s, addr, addrlen);
489baacf047SPaolo Bonzini     if (ret >= 0) {
490baacf047SPaolo Bonzini         qemu_set_cloexec(ret);
491baacf047SPaolo Bonzini     }
492baacf047SPaolo Bonzini 
493baacf047SPaolo Bonzini     return ret;
494baacf047SPaolo Bonzini }
495baacf047SPaolo Bonzini 
qemu_send_full(int s,const void * buf,size_t count)49684c662d2SXuzhou Cheng ssize_t qemu_send_full(int s, const void *buf, size_t count)
49784c662d2SXuzhou Cheng {
49884c662d2SXuzhou Cheng     ssize_t ret = 0;
49984c662d2SXuzhou Cheng     ssize_t total = 0;
50084c662d2SXuzhou Cheng 
50184c662d2SXuzhou Cheng     while (count) {
50284c662d2SXuzhou Cheng         ret = send(s, buf, count, 0);
50384c662d2SXuzhou Cheng         if (ret < 0) {
50484c662d2SXuzhou Cheng             if (errno == EINTR) {
50584c662d2SXuzhou Cheng                 continue;
50684c662d2SXuzhou Cheng             }
50784c662d2SXuzhou Cheng             break;
50884c662d2SXuzhou Cheng         }
50984c662d2SXuzhou Cheng 
51084c662d2SXuzhou Cheng         count -= ret;
51184c662d2SXuzhou Cheng         buf += ret;
51284c662d2SXuzhou Cheng         total += ret;
51384c662d2SXuzhou Cheng     }
51484c662d2SXuzhou Cheng 
51584c662d2SXuzhou Cheng     return total;
51684c662d2SXuzhou Cheng }
51784c662d2SXuzhou Cheng 
qemu_set_hw_version(const char * version)51835c2c8dcSEduardo Habkost void qemu_set_hw_version(const char *version)
519baacf047SPaolo Bonzini {
52035c2c8dcSEduardo Habkost     hw_version = version;
521baacf047SPaolo Bonzini }
522baacf047SPaolo Bonzini 
qemu_hw_version(void)52335c2c8dcSEduardo Habkost const char *qemu_hw_version(void)
524baacf047SPaolo Bonzini {
52535c2c8dcSEduardo Habkost     return hw_version;
526baacf047SPaolo Bonzini }
527baacf047SPaolo Bonzini 
528d3bf825eSMarc-André Lureau #ifdef _WIN32
socket_cleanup(void)529d3bf825eSMarc-André Lureau static void socket_cleanup(void)
530d3bf825eSMarc-André Lureau {
531d3bf825eSMarc-André Lureau     WSACleanup();
532d3bf825eSMarc-André Lureau }
533d3bf825eSMarc-André Lureau #endif
534d3bf825eSMarc-André Lureau 
socket_init(void)535d3bf825eSMarc-André Lureau int socket_init(void)
536d3bf825eSMarc-André Lureau {
537d3bf825eSMarc-André Lureau #ifdef _WIN32
538d3bf825eSMarc-André Lureau     WSADATA Data;
539d3bf825eSMarc-André Lureau     int ret, err;
540d3bf825eSMarc-André Lureau 
541d3bf825eSMarc-André Lureau     ret = WSAStartup(MAKEWORD(2, 2), &Data);
542d3bf825eSMarc-André Lureau     if (ret != 0) {
543d3bf825eSMarc-André Lureau         err = WSAGetLastError();
544d3bf825eSMarc-André Lureau         fprintf(stderr, "WSAStartup: %d\n", err);
545d3bf825eSMarc-André Lureau         return -1;
546d3bf825eSMarc-André Lureau     }
547d3bf825eSMarc-André Lureau     atexit(socket_cleanup);
548d3bf825eSMarc-André Lureau #endif
549d3bf825eSMarc-André Lureau     return 0;
550d3bf825eSMarc-André Lureau }
5519adea5f7SPaolo Bonzini 
552ae2990c2SStefan Hajnoczi 
5539adea5f7SPaolo Bonzini #ifndef CONFIG_IOVEC
5549adea5f7SPaolo Bonzini static ssize_t
readv_writev(int fd,const struct iovec * iov,int iov_cnt,bool do_write)5559adea5f7SPaolo Bonzini readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
5569adea5f7SPaolo Bonzini {
5579adea5f7SPaolo Bonzini     unsigned i = 0;
5589adea5f7SPaolo Bonzini     ssize_t ret = 0;
559c1f79809SMarc-André Lureau     ssize_t off = 0;
5609adea5f7SPaolo Bonzini     while (i < iov_cnt) {
5619adea5f7SPaolo Bonzini         ssize_t r = do_write
562c1f79809SMarc-André Lureau             ? write(fd, iov[i].iov_base + off, iov[i].iov_len - off)
563c1f79809SMarc-André Lureau             : read(fd, iov[i].iov_base + off, iov[i].iov_len - off);
5649adea5f7SPaolo Bonzini         if (r > 0) {
5659adea5f7SPaolo Bonzini             ret += r;
566c1f79809SMarc-André Lureau             off += r;
567c1f79809SMarc-André Lureau             if (off < iov[i].iov_len) {
568c1f79809SMarc-André Lureau                 continue;
569c1f79809SMarc-André Lureau             }
5709adea5f7SPaolo Bonzini         } else if (!r) {
5719adea5f7SPaolo Bonzini             break;
5729adea5f7SPaolo Bonzini         } else if (errno == EINTR) {
5739adea5f7SPaolo Bonzini             continue;
5749adea5f7SPaolo Bonzini         } else {
5759adea5f7SPaolo Bonzini             /* else it is some "other" error,
5769adea5f7SPaolo Bonzini              * only return if there was no data processed. */
5779adea5f7SPaolo Bonzini             if (ret == 0) {
5789adea5f7SPaolo Bonzini                 ret = -1;
5799adea5f7SPaolo Bonzini             }
5809adea5f7SPaolo Bonzini             break;
5819adea5f7SPaolo Bonzini         }
582c1f79809SMarc-André Lureau         off = 0;
5839adea5f7SPaolo Bonzini         i++;
5849adea5f7SPaolo Bonzini     }
5859adea5f7SPaolo Bonzini     return ret;
5869adea5f7SPaolo Bonzini }
5879adea5f7SPaolo Bonzini 
5889adea5f7SPaolo Bonzini ssize_t
readv(int fd,const struct iovec * iov,int iov_cnt)5899adea5f7SPaolo Bonzini readv(int fd, const struct iovec *iov, int iov_cnt)
5909adea5f7SPaolo Bonzini {
5919adea5f7SPaolo Bonzini     return readv_writev(fd, iov, iov_cnt, false);
5929adea5f7SPaolo Bonzini }
5939adea5f7SPaolo Bonzini 
5949adea5f7SPaolo Bonzini ssize_t
writev(int fd,const struct iovec * iov,int iov_cnt)5959adea5f7SPaolo Bonzini writev(int fd, const struct iovec *iov, int iov_cnt)
5969adea5f7SPaolo Bonzini {
5979adea5f7SPaolo Bonzini     return readv_writev(fd, iov, iov_cnt, true);
5989adea5f7SPaolo Bonzini }
5999adea5f7SPaolo Bonzini #endif
600282468c7SMarc-André Lureau 
601282468c7SMarc-André Lureau /*
602282468c7SMarc-André Lureau  * Make sure data goes on disk, but if possible do not bother to
603282468c7SMarc-André Lureau  * write out the inode just for timestamp updates.
604282468c7SMarc-André Lureau  *
605282468c7SMarc-André Lureau  * Unfortunately even in 2009 many operating systems do not support
606282468c7SMarc-André Lureau  * fdatasync and have to fall back to fsync.
607282468c7SMarc-André Lureau  */
qemu_fdatasync(int fd)608282468c7SMarc-André Lureau int qemu_fdatasync(int fd)
609282468c7SMarc-André Lureau {
610282468c7SMarc-André Lureau #ifdef CONFIG_FDATASYNC
611282468c7SMarc-André Lureau     return fdatasync(fd);
612282468c7SMarc-André Lureau #else
613282468c7SMarc-André Lureau     return fsync(fd);
614282468c7SMarc-André Lureau #endif
615282468c7SMarc-André Lureau }
616