From 57d7cc602d14c6b50e2826e427a5de124e479f95 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange 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