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
 | |
| 
 |