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