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