From: marcandre.lureau@redhat.com
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
"Thomas Huth" <thuth@redhat.com>, "Stefan Weil" <sw@weilnetz.de>,
"Qiuhao Li" <Qiuhao.Li@outlook.com>,
"Laurent Vivier" <lvivier@redhat.com>,
"Stefan Hajnoczi" <stefanha@redhat.com>,
"Hanna Reitz" <hreitz@redhat.com>,
"Kevin Wolf" <kwolf@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
qemu-block@nongnu.org, "Konstantin Kostiuk" <kkostiuk@redhat.com>,
"Bandan Das" <bsd@redhat.com>,
"Michael Roth" <michael.roth@amd.com>,
"Darren Kenny" <darren.kenny@oracle.com>,
"Alexander Bulekov" <alxndr@bu.edu>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PATCH 07/16] qga: flatten safe_open_or_create()
Date: Wed, 4 May 2022 21:30:16 +0400 [thread overview]
Message-ID: <20220504173025.650167-8-marcandre.lureau@redhat.com> (raw)
In-Reply-To: <20220504173025.650167-1-marcandre.lureau@redhat.com>
From: Marc-André Lureau <marcandre.lureau@redhat.com>
There is a bit too much branching in the function, this can be
simplified a bit, and have a common exit point thanks to ERRP_PROPAGATE.
This also helps with the following error handling changes.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qga/commands-posix.c | 126 ++++++++++++++++++++++---------------------
1 file changed, 65 insertions(+), 61 deletions(-)
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 69f209af87e6..98d481a58485 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -339,73 +339,77 @@ find_open_flag(const char *mode_str, Error **errp)
static FILE *
safe_open_or_create(const char *path, const char *mode, Error **errp)
{
- Error *local_err = NULL;
- int oflag;
-
- oflag = find_open_flag(mode, &local_err);
- if (local_err == NULL) {
- int fd;
+ ERRP_GUARD();
+ int oflag, fd = -1;
+ FILE *f = NULL;
+
+ oflag = find_open_flag(mode, errp);
+ if (*errp) {
+ goto end;
+ }
+
+ /* If the caller wants / allows creation of a new file, we implement it
+ * with a two step process: open() + (open() / fchmod()).
+ *
+ * First we insist on creating the file exclusively as a new file. If
+ * that succeeds, we're free to set any file-mode bits on it. (The
+ * motivation is that we want to set those file-mode bits independently
+ * of the current umask.)
+ *
+ * If the exclusive creation fails because the file already exists
+ * (EEXIST is not possible for any other reason), we just attempt to
+ * open the file, but in this case we won't be allowed to change the
+ * file-mode bits on the preexistent file.
+ *
+ * The pathname should never disappear between the two open()s in
+ * practice. If it happens, then someone very likely tried to race us.
+ * In this case just go ahead and report the ENOENT from the second
+ * open() to the caller.
+ *
+ * If the caller wants to open a preexistent file, then the first
+ * open() is decisive and its third argument is ignored, and the second
+ * open() and the fchmod() are never called.
+ */
+ fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0);
+ if (fd == -1 && errno == EEXIST) {
+ oflag &= ~(unsigned)O_CREAT;
+ fd = open(path, oflag);
+ }
+ if (fd == -1) {
+ error_setg_errno(errp, errno,
+ "failed to open file '%s' "
+ "(mode: '%s')",
+ path, mode);
+ goto end;
+ }
- /* If the caller wants / allows creation of a new file, we implement it
- * with a two step process: open() + (open() / fchmod()).
- *
- * First we insist on creating the file exclusively as a new file. If
- * that succeeds, we're free to set any file-mode bits on it. (The
- * motivation is that we want to set those file-mode bits independently
- * of the current umask.)
- *
- * If the exclusive creation fails because the file already exists
- * (EEXIST is not possible for any other reason), we just attempt to
- * open the file, but in this case we won't be allowed to change the
- * file-mode bits on the preexistent file.
- *
- * The pathname should never disappear between the two open()s in
- * practice. If it happens, then someone very likely tried to race us.
- * In this case just go ahead and report the ENOENT from the second
- * open() to the caller.
- *
- * If the caller wants to open a preexistent file, then the first
- * open() is decisive and its third argument is ignored, and the second
- * open() and the fchmod() are never called.
- */
- fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0);
- if (fd == -1 && errno == EEXIST) {
- oflag &= ~(unsigned)O_CREAT;
- fd = open(path, oflag);
- }
+ qemu_set_cloexec(fd);
- if (fd == -1) {
- error_setg_errno(&local_err, errno, "failed to open file '%s' "
- "(mode: '%s')", path, mode);
- } else {
- qemu_set_cloexec(fd);
+ if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) {
+ error_setg_errno(errp, errno,
+ "failed to set permission "
+ "0%03o on new file '%s' (mode: '%s')",
+ (unsigned)DEFAULT_NEW_FILE_MODE, path, mode);
+ goto end;
+ }
- if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) {
- error_setg_errno(&local_err, errno, "failed to set permission "
- "0%03o on new file '%s' (mode: '%s')",
- (unsigned)DEFAULT_NEW_FILE_MODE, path, mode);
- } else {
- FILE *f;
-
- f = fdopen(fd, mode);
- if (f == NULL) {
- error_setg_errno(&local_err, errno, "failed to associate "
- "stdio stream with file descriptor %d, "
- "file '%s' (mode: '%s')", fd, path, mode);
- } else {
- return f;
- }
- }
+ f = fdopen(fd, mode);
+ if (f == NULL) {
+ error_setg_errno(errp, errno,
+ "failed to associate "
+ "stdio stream with file descriptor %d, "
+ "file '%s' (mode: '%s')",
+ fd, path, mode);
+ }
- close(fd);
- if (oflag & O_CREAT) {
- unlink(path);
- }
+end:
+ if (f == NULL && fd != -1) {
+ close(fd);
+ if (oflag & O_CREAT) {
+ unlink(path);
}
}
-
- error_propagate(errp, local_err);
- return NULL;
+ return f;
}
int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode,
--
2.36.0.44.g0f828332d5ac
next prev parent reply other threads:[~2022-05-04 17:41 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-04 17:30 [PATCH 00/16] Misc cleanups marcandre.lureau
2022-05-04 17:30 ` [PATCH 01/16] include: move qemu_*_exec_dir() to cutils marcandre.lureau
2022-05-04 17:30 ` [PATCH 02/16] util/win32: simplify qemu_get_local_state_dir() marcandre.lureau
2022-05-04 18:07 ` Stefan Weil via
2022-05-04 17:30 ` [PATCH 03/16] tests: make libqmp buildable for win32 marcandre.lureau
2022-05-04 18:18 ` Thomas Huth
2022-05-04 17:30 ` [PATCH 04/16] compiler.h: add QEMU_{BEGIN, END}_IGNORE_INITIALIZER_OVERRIDES marcandre.lureau
2022-05-04 18:41 ` Peter Maydell
2022-05-05 6:55 ` Paolo Bonzini
2022-05-04 17:30 ` [PATCH 05/16] qobject/json-lexer: disable -Winitializer-overrides warnings marcandre.lureau
2022-05-04 17:30 ` [PATCH 06/16] include: adjust header guards after renaming marcandre.lureau
2022-05-04 18:10 ` Stefan Weil via
2022-05-04 17:30 ` marcandre.lureau [this message]
2022-05-04 17:30 ` [PATCH 08/16] osdep: export qemu_open_cloexec() marcandre.lureau
2022-05-04 17:30 ` [PATCH 09/16] qga: use qemu_open_cloexec() for safe_open_or_create() marcandre.lureau
2022-05-04 17:30 ` [PATCH 10/16] qapi/error: add g_autoptr(Error) support marcandre.lureau
2022-05-05 6:53 ` Paolo Bonzini
2022-05-04 17:30 ` [PATCH 11/16] qga: replace qemu_open_old() with qemu_open_cloexec() marcandre.lureau
2022-05-04 17:30 ` [PATCH 12/16] test/qga: use G_TEST_DIR to locate os-release test file marcandre.lureau
2022-05-04 17:30 ` [PATCH 13/16] qga/wixl: prefer variables over environment marcandre.lureau
2022-05-04 17:30 ` [PATCH 14/16] qga/wixl: require Mingw_bin marcandre.lureau
2022-05-04 17:30 ` [PATCH 15/16] qga/wixl: simplify some pre-processing marcandre.lureau
2022-05-04 17:30 ` [PATCH 16/16] qga/wixl: replace QEMU_GA_MSI_MINGW_BIN_PATH with glib bindir marcandre.lureau
2022-05-05 6:56 ` [PATCH 00/16] Misc cleanups Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220504173025.650167-8-marcandre.lureau@redhat.com \
--to=marcandre.lureau@redhat.com \
--cc=Qiuhao.Li@outlook.com \
--cc=alxndr@bu.edu \
--cc=armbru@redhat.com \
--cc=bsd@redhat.com \
--cc=darren.kenny@oracle.com \
--cc=hreitz@redhat.com \
--cc=kkostiuk@redhat.com \
--cc=kwolf@redhat.com \
--cc=lvivier@redhat.com \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=sw@weilnetz.de \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).