提交 69556215 编写于 作者: J John Ferlan

storage: On error unlink created file in virFileOpen{As|Forked}

After a successful creation of a file, if some other call results
in returning a failure, let's unlink the file we created to prevent
another round trip or confusion in the caller. In particular, this
function can be called during a storage backend buildVol, so in order
to ensure that caller doesn't need to distinguish between failed create
or some other failure after create, just remove the volume we created.
Signed-off-by: NJohn Ferlan <jferlan@redhat.com>
上级 c4dd2a1f
...@@ -2057,7 +2057,12 @@ virFileOpenForceOwnerMode(const char *path, int fd, mode_t mode, ...@@ -2057,7 +2057,12 @@ virFileOpenForceOwnerMode(const char *path, int fd, mode_t mode,
* virFileOpenAs(). It forks, then the child does setuid+setgid to * virFileOpenAs(). It forks, then the child does setuid+setgid to
* given uid:gid and attempts to open the file, while the parent just * given uid:gid and attempts to open the file, while the parent just
* calls recvfd to get the open fd back from the child. returns the * calls recvfd to get the open fd back from the child. returns the
* fd, or -errno if there is an error. */ * fd, or -errno if there is an error. Additionally, to avoid another
* round-trip to unlink the file in a forked process; on error if this
* function created the file, but failed to perform some action after
* creation, then perform the unlink of the file. The storage driver
* buildVol backend function expects the file to be deleted on error.
*/
static int static int
virFileOpenForked(const char *path, int openflags, mode_t mode, virFileOpenForked(const char *path, int openflags, mode_t mode,
uid_t uid, gid_t gid, unsigned int flags) uid_t uid, gid_t gid, unsigned int flags)
...@@ -2069,6 +2074,7 @@ virFileOpenForked(const char *path, int openflags, mode_t mode, ...@@ -2069,6 +2074,7 @@ virFileOpenForked(const char *path, int openflags, mode_t mode,
int pair[2] = { -1, -1 }; int pair[2] = { -1, -1 };
gid_t *groups; gid_t *groups;
int ngroups; int ngroups;
bool created = false;
/* parent is running as root, but caller requested that the /* parent is running as root, but caller requested that the
* file be opened as some other user and/or group). The * file be opened as some other user and/or group). The
...@@ -2113,6 +2119,8 @@ virFileOpenForked(const char *path, int openflags, mode_t mode, ...@@ -2113,6 +2119,8 @@ virFileOpenForked(const char *path, int openflags, mode_t mode,
path); path);
goto childerror; goto childerror;
} }
if (openflags & O_CREAT)
created = true;
/* File is successfully open. Set permissions if requested. */ /* File is successfully open. Set permissions if requested. */
ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags); ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
...@@ -2141,8 +2149,11 @@ virFileOpenForked(const char *path, int openflags, mode_t mode, ...@@ -2141,8 +2149,11 @@ virFileOpenForked(const char *path, int openflags, mode_t mode,
/* XXX This makes assumptions about errno being < 255, which is /* XXX This makes assumptions about errno being < 255, which is
* not true on Hurd. */ * not true on Hurd. */
VIR_FORCE_CLOSE(pair[1]); VIR_FORCE_CLOSE(pair[1]);
if (ret < 0) if (ret < 0) {
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
if (created)
unlink(path);
}
ret = -ret; ret = -ret;
if ((ret & 0xff) != ret) { if ((ret & 0xff) != ret) {
VIR_WARN("unable to pass desired return value %d", ret); VIR_WARN("unable to pass desired return value %d", ret);
...@@ -2218,13 +2229,18 @@ virFileOpenForked(const char *path, int openflags, mode_t mode, ...@@ -2218,13 +2229,18 @@ virFileOpenForked(const char *path, int openflags, mode_t mode,
* the file already existed with different permissions). * the file already existed with different permissions).
* *
* The return value (if non-negative) is the file descriptor, left * The return value (if non-negative) is the file descriptor, left
* open. Returns -errno on failure. * open. Returns -errno on failure. Additionally, to avoid another
* round-trip to unlink the file; on error if this function created the
* file, but failed to perform some action after creation, then perform
* the unlink of the file. The storage driver buildVol backend function
* expects the file to be deleted on error.
*/ */
int int
virFileOpenAs(const char *path, int openflags, mode_t mode, virFileOpenAs(const char *path, int openflags, mode_t mode,
uid_t uid, gid_t gid, unsigned int flags) uid_t uid, gid_t gid, unsigned int flags)
{ {
int ret = 0, fd = -1; int ret = 0, fd = -1;
bool created = false;
/* allow using -1 to mean "current value" */ /* allow using -1 to mean "current value" */
if (uid == (uid_t) -1) if (uid == (uid_t) -1)
...@@ -2246,6 +2262,8 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, ...@@ -2246,6 +2262,8 @@ virFileOpenAs(const char *path, int openflags, mode_t mode,
if (!(flags & VIR_FILE_OPEN_FORK)) if (!(flags & VIR_FILE_OPEN_FORK))
goto error; goto error;
} else { } else {
if (openflags & O_CREAT)
created = true;
ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags); ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
if (ret < 0) if (ret < 0)
goto error; goto error;
...@@ -2288,6 +2306,8 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, ...@@ -2288,6 +2306,8 @@ virFileOpenAs(const char *path, int openflags, mode_t mode,
if (fd >= 0) { if (fd >= 0) {
/* some other failure after the open succeeded */ /* some other failure after the open succeeded */
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
if (created)
unlink(path);
} }
/* whoever failed the open last has already set ret = -errno */ /* whoever failed the open last has already set ret = -errno */
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册