121 lines
4.0 KiB
Diff
121 lines
4.0 KiB
Diff
From 57d7cc602d14c6b50e2826e427a5de124e479f95 Mon Sep 17 00:00:00 2001
|
|
From: Daniel P. Berrange <berrange@redhat.com>
|
|
Date: Mon, 12 Oct 2009 20:32:33 +0100
|
|
Subject: [PATCH] Fix virFileReadLimFD/virFileReadAll to handle EINTR
|
|
|
|
The fread_file_lim() function uses fread() but never handles
|
|
EINTR results, causing unexpected failures when reading QEMU
|
|
help arg info. It was unneccessarily using FILE * instead
|
|
of plain UNIX file handles, which prevented use of saferead()
|
|
|
|
* src/util/util.c: Switch fread_file_lim over to use saferead
|
|
instead of fread, remove FILE * use, and rename
|
|
|
|
(cherry picked from commit 11a36d956cb8a5e439e535bff3e0cfce50a64bca)
|
|
|
|
Fedora-patch: libvirt-fix-qemu-restore-from-raw2.patch
|
|
---
|
|
src/util.c | 45 ++++++++++++---------------------------------
|
|
1 files changed, 12 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/src/util.c b/src/util.c
|
|
index 1878e33..7bc3a66 100644
|
|
--- a/src/util.c
|
|
+++ b/src/util.c
|
|
@@ -887,7 +887,7 @@ virExec(virConnectPtr conn,
|
|
number of bytes. If the length of the input is <= max_len, and
|
|
upon error while reading that data, it works just like fread_file. */
|
|
static char *
|
|
-fread_file_lim (FILE *stream, size_t max_len, size_t *length)
|
|
+saferead_lim (int fd, size_t max_len, size_t *length)
|
|
{
|
|
char *buf = NULL;
|
|
size_t alloc = 0;
|
|
@@ -895,8 +895,8 @@ fread_file_lim (FILE *stream, size_t max_len, size_t *length)
|
|
int save_errno;
|
|
|
|
for (;;) {
|
|
- size_t count;
|
|
- size_t requested;
|
|
+ int count;
|
|
+ int requested;
|
|
|
|
if (size + BUFSIZ + 1 > alloc) {
|
|
alloc += alloc / 2;
|
|
@@ -912,12 +912,12 @@ fread_file_lim (FILE *stream, size_t max_len, size_t *length)
|
|
/* Ensure that (size + requested <= max_len); */
|
|
requested = MIN (size < max_len ? max_len - size : 0,
|
|
alloc - size - 1);
|
|
- count = fread (buf + size, 1, requested, stream);
|
|
+ count = saferead (fd, buf + size, requested);
|
|
size += count;
|
|
|
|
if (count != requested || requested == 0) {
|
|
save_errno = errno;
|
|
- if (ferror (stream))
|
|
+ if (count < 0)
|
|
break;
|
|
buf[size] = '\0';
|
|
*length = size;
|
|
@@ -930,12 +930,12 @@ fread_file_lim (FILE *stream, size_t max_len, size_t *length)
|
|
return NULL;
|
|
}
|
|
|
|
-/* A wrapper around fread_file_lim that maps a failure due to
|
|
+/* A wrapper around saferead_lim that maps a failure due to
|
|
exceeding the maximum size limitation to EOVERFLOW. */
|
|
-static int virFileReadLimFP(FILE *fp, int maxlen, char **buf)
|
|
+int virFileReadLimFD(int fd, int maxlen, char **buf)
|
|
{
|
|
size_t len;
|
|
- char *s = fread_file_lim (fp, maxlen+1, &len);
|
|
+ char *s = saferead_lim (fd, maxlen+1, &len);
|
|
if (s == NULL)
|
|
return -1;
|
|
if (len > maxlen || (int)len != len) {
|
|
@@ -949,37 +949,16 @@ static int virFileReadLimFP(FILE *fp, int maxlen, char **buf)
|
|
return len;
|
|
}
|
|
|
|
-/* Like virFileReadLimFP, but use a file descriptor rather than a FILE*. */
|
|
-int virFileReadLimFD(int fd_arg, int maxlen, char **buf)
|
|
-{
|
|
- int fd = dup (fd_arg);
|
|
- if (fd >= 0) {
|
|
- FILE *fp = fdopen (fd, "r");
|
|
- if (fp) {
|
|
- int len = virFileReadLimFP (fp, maxlen, buf);
|
|
- int saved_errno = errno;
|
|
- fclose (fp);
|
|
- errno = saved_errno;
|
|
- return len;
|
|
- } else {
|
|
- int saved_errno = errno;
|
|
- close (fd);
|
|
- errno = saved_errno;
|
|
- }
|
|
- }
|
|
- return -1;
|
|
-}
|
|
-
|
|
int virFileReadAll(const char *path, int maxlen, char **buf)
|
|
{
|
|
- FILE *fh = fopen(path, "r");
|
|
- if (fh == NULL) {
|
|
+ int fd = open(path, O_RDONLY);
|
|
+ if (fd < 0) {
|
|
virReportSystemError(NULL, errno, _("Failed to open file '%s'"), path);
|
|
return -1;
|
|
}
|
|
|
|
- int len = virFileReadLimFP (fh, maxlen, buf);
|
|
- fclose(fh);
|
|
+ int len = virFileReadLimFD(fd, maxlen, buf);
|
|
+ close(fd);
|
|
if (len < 0) {
|
|
virReportSystemError(NULL, errno, _("Failed to read file '%s'"), path);
|
|
return -1;
|
|
--
|
|
1.6.2.5
|
|
|