aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/osdep.c104
-rw-r--r--util/oslib-posix.c2
2 files changed, 75 insertions, 31 deletions
diff --git a/util/osdep.c b/util/osdep.c
index 4829c07ff6..8ea7a807c1 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
/* Needed early for CONFIG_BSD etc. */
@@ -122,7 +123,7 @@ static int fcntl_op_getlk = -1;
/*
* Dups an fd and sets the flags
*/
-static int qemu_dup_flags(int fd, int flags)
+int qemu_dup_flags(int fd, int flags)
{
int ret;
int serrno;
@@ -279,13 +280,27 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
}
#endif
+static int qemu_open_cloexec(const char *name, int flags, mode_t mode)
+{
+ int ret;
+#ifdef O_CLOEXEC
+ ret = open(name, flags | O_CLOEXEC, mode);
+#else
+ ret = open(name, flags, mode);
+ if (ret >= 0) {
+ qemu_set_cloexec(ret);
+ }
+#endif
+ return ret;
+}
+
/*
* Opens a file with FD_CLOEXEC set
*/
-int qemu_open(const char *name, int flags, ...)
+static int
+qemu_open_internal(const char *name, int flags, mode_t mode, Error **errp)
{
int ret;
- int mode = 0;
#ifndef _WIN32
const char *fdset_id_str;
@@ -293,29 +308,19 @@ int qemu_open(const char *name, int flags, ...)
/* Attempt dup of fd from fd set */
if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
int64_t fdset_id;
- int fd, dupfd;
+ int dupfd;
fdset_id = qemu_parse_fdset(fdset_id_str);
if (fdset_id == -1) {
+ error_setg(errp, "Could not parse fdset %s", name);
errno = EINVAL;
return -1;
}
- fd = monitor_fdset_get_fd(fdset_id, flags);
- if (fd < 0) {
- errno = -fd;
- return -1;
- }
-
- dupfd = qemu_dup_flags(fd, flags);
+ dupfd = monitor_fdset_dup_fd_add(fdset_id, flags);
if (dupfd == -1) {
- return -1;
- }
-
- ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
- if (ret == -1) {
- close(dupfd);
- errno = EINVAL;
+ error_setg_errno(errp, errno, "Could not dup FD for %s flags %x",
+ name, flags);
return -1;
}
@@ -323,22 +328,61 @@ int qemu_open(const char *name, int flags, ...)
}
#endif
- if (flags & O_CREAT) {
- va_list ap;
+ ret = qemu_open_cloexec(name, flags, mode);
- va_start(ap, flags);
- mode = va_arg(ap, int);
- va_end(ap);
+ if (ret == -1) {
+ const char *action = flags & O_CREAT ? "create" : "open";
+#ifdef O_DIRECT
+ /* Give more helpful error message for O_DIRECT */
+ if (errno == EINVAL && (flags & O_DIRECT)) {
+ ret = open(name, flags & ~O_DIRECT, mode);
+ if (ret != -1) {
+ close(ret);
+ error_setg(errp, "Could not %s '%s': "
+ "filesystem does not support O_DIRECT",
+ action, name);
+ errno = EINVAL; /* restore first open()'s errno */
+ return -1;
+ }
+ }
+#endif /* O_DIRECT */
+ error_setg_errno(errp, errno, "Could not %s '%s'",
+ action, name);
}
-#ifdef O_CLOEXEC
- ret = open(name, flags | O_CLOEXEC, mode);
-#else
- ret = open(name, flags, mode);
- if (ret >= 0) {
- qemu_set_cloexec(ret);
+ return ret;
+}
+
+
+int qemu_open(const char *name, int flags, Error **errp)
+{
+ assert(!(flags & O_CREAT));
+
+ return qemu_open_internal(name, flags, 0, errp);
+}
+
+
+int qemu_create(const char *name, int flags, mode_t mode, Error **errp)
+{
+ assert(!(flags & O_CREAT));
+
+ return qemu_open_internal(name, flags | O_CREAT, mode, errp);
+}
+
+
+int qemu_open_old(const char *name, int flags, ...)
+{
+ va_list ap;
+ mode_t mode = 0;
+ int ret;
+
+ va_start(ap, flags);
+ if (flags & O_CREAT) {
+ mode = va_arg(ap, int);
}
-#endif
+ va_end(ap);
+
+ ret = qemu_open_internal(name, flags, mode, NULL);
#ifdef O_DIRECT
if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index ad8001a4ad..f5f676f079 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -125,7 +125,7 @@ bool qemu_write_pidfile(const char *path, Error **errp)
.l_len = 0,
};
- fd = qemu_open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+ fd = qemu_open_old(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd == -1) {
error_setg_errno(errp, errno, "Cannot open pid file");
return false;