[libvirt] [PATCH] Fix virFileReadLimFD/virFileReadAll to handle EINTR

Mark McLoughlin markmc at redhat.com
Tue Oct 13 09:23:27 UTC 2009


On Mon, 2009-10-12 at 20:37 +0100, Daniel P. Berrange wrote:
> 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()

Looks like the same thing Charles Duffy reported here:

  http://www.redhat.com/archives/libvir-list/2009-September/msg00662.html

> * src/util/util.c: Switch fread_file_lim over to use saferead
>   instead of fread, remove FILE * use, and rename
> ---
>  src/util/util.c |   45 ++++++++++++---------------------------------
>  1 files changed, 12 insertions(+), 33 deletions(-)
> 
> diff --git a/src/util/util.c b/src/util/util.c
> index e5135fc..98f8a14 100644
> --- a/src/util/util.c
> +++ b/src/util/util.c
> @@ -898,7 +898,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;
> @@ -906,8 +906,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;
> @@ -923,12 +923,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;

Perhaps you should move the save_errno assignment under this condition
too, but not a big deal

>              buf[size] = '\0';
>              *length = size;
> @@ -941,12 +941,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) {
> @@ -960,37 +960,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;

Looks good to me, ACK

Cheers,
Mark.




More information about the libvir-list mailing list