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