int read_file(const char *path, char *buf, size_t count, size_t *len);
 int write_file(const char *path, const char *buf, size_t count);
+int read_file_alloc(const char *path, char **buf, size_t *len);
 int read_long(const char *path, long *result, int base);
 int write_long(const char *path, long result, int base);
 int read_ulong(const char *path, unsigned long *result, int base);
 
        return i;
 }
 
-/* Caller must free the allocated buffer return nonzero on error. */
-int read_alloc_input_file(char *fname, char **buf, size_t *bufsize)
-{
-       int err;
-       struct stat statbuf;
-       char *p;
-       size_t num_bytes;
-
-       if (stat(fname, &statbuf)) {
-               perror(fname);
-               return -1;
-       }
-
-       assert(NULL != (p = (char *) malloc(statbuf.st_size)));
-
-       err = read_file(fname, p, statbuf.st_size, &num_bytes);
-       if (err) {
-               perror(fname);
-               goto fail;
-       }
-
-       if (num_bytes != statbuf.st_size) {
-               fprintf(stderr, "Actual bytes != expected bytes\n");
-               err = -1;
-               goto fail;
-       }
-
-       *buf = p;
-       *bufsize = num_bytes;
-       return 0;
-
-fail:
-       free(p);
-       return err;
-}
-
 /*
  * Z_SYNC_FLUSH as described in zlib.h.
  * Returns number of appended bytes
                fprintf(stderr, "usage: %s <fname>\n", argv[0]);
                exit(-1);
        }
-       if (read_alloc_input_file(argv[1], &inbuf, &inlen))
+       if (read_file_alloc(argv[1], &inbuf, &inlen))
                exit(-1);
        fprintf(stderr, "file %s read, %ld bytes\n", argv[1], inlen);
 
 
 top_srcdir = ../../../../..
 include ../../lib.mk
 
-$(TEST_GEN_PROGS): ../harness.c
+$(TEST_GEN_PROGS): ../harness.c ../utils.c
 
 #include <byteswap.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <linux/limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/syscall.h>
        struct region *next;
 };
 
-int read_entire_file(int fd, char **buf, size_t *len)
-{
-       size_t buf_size = 0;
-       size_t off = 0;
-       int rc;
-
-       *buf = NULL;
-       do {
-               buf_size += BLOCK_SIZE;
-               if (*buf == NULL)
-                       *buf = malloc(buf_size);
-               else
-                       *buf = realloc(*buf, buf_size);
-
-               if (*buf == NULL)
-                       return -ENOMEM;
-
-               rc = read(fd, *buf + off, BLOCK_SIZE);
-               if (rc < 0)
-                       return -EIO;
-
-               off += rc;
-       } while (rc == BLOCK_SIZE);
-
-       if (len)
-               *len = off;
-
-       return 0;
-}
-
-static int open_prop_file(const char *prop_path, const char *prop_name, int *fd)
-{
-       char *path;
-       int len;
-
-       /* allocate enough for two string, a slash and trailing NULL */
-       len = strlen(prop_path) + strlen(prop_name) + 1 + 1;
-       path = malloc(len);
-       if (path == NULL)
-               return -ENOMEM;
-
-       snprintf(path, len, "%s/%s", prop_path, prop_name);
-
-       *fd = open(path, O_RDONLY);
-       free(path);
-       if (*fd < 0)
-               return -errno;
-
-       return 0;
-}
-
 static int get_property(const char *prop_path, const char *prop_name,
                        char **prop_val, size_t *prop_len)
 {
-       int rc, fd;
-
-       rc = open_prop_file(prop_path, prop_name, &fd);
-       if (rc)
-               return rc;
+       char path[PATH_MAX];
 
-       rc = read_entire_file(fd, prop_val, prop_len);
-       close(fd);
+       int len = snprintf(path, sizeof(path), "%s/%s", prop_path, prop_name);
+       if (len < 0 || len >= sizeof(path))
+               return -ENOMEM;
 
-       return rc;
+       return read_file_alloc(path, prop_val, prop_len);
 }
 
 int rtas_token(const char *call_name)
 static int read_kregion_bounds(struct region *kregion)
 {
        char *buf;
-       int fd;
-       int rc;
+       int err;
 
-       fd = open("/proc/ppc64/rtas/rmo_buffer", O_RDONLY);
-       if (fd < 0) {
-               printf("Could not open rmo_buffer file\n");
+       err = read_file_alloc("/proc/ppc64/rtas/rmo_buffer", &buf, NULL);
+       if (err) {
+               perror("Could not open rmo_buffer file");
                return RTAS_IO_ASSERT;
        }
 
-       rc = read_entire_file(fd, &buf, NULL);
-       close(fd);
-       if (rc) {
-               free(buf);
-               return rc;
-       }
-
        sscanf(buf, "%" SCNx64 " %x", &kregion->addr, &kregion->size);
        free(buf);
 
 
        return err;
 }
 
+int read_file_alloc(const char *path, char **buf, size_t *len)
+{
+       size_t read_offset = 0;
+       size_t buffer_len = 0;
+       char *buffer = NULL;
+       int err;
+       int fd;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return -errno;
+
+       /*
+        * We don't use stat & preallocate st_size because some non-files
+        * report 0 file size. Instead just dynamically grow the buffer
+        * as needed.
+        */
+       while (1) {
+               ssize_t rc;
+
+               if (read_offset >= buffer_len / 2) {
+                       char *next_buffer;
+
+                       buffer_len = buffer_len ? buffer_len * 2 : 4096;
+                       next_buffer = realloc(buffer, buffer_len);
+                       if (!next_buffer) {
+                               err = -errno;
+                               goto out;
+                       }
+                       buffer = next_buffer;
+               }
+
+               rc = read(fd, buffer + read_offset, buffer_len - read_offset);
+               if (rc < 0) {
+                       err = -errno;
+                       goto out;
+               }
+
+               if (rc == 0)
+                       break;
+
+               read_offset += rc;
+       }
+
+       *buf = buffer;
+       if (len)
+               *len = read_offset;
+
+       err = 0;
+
+out:
+       close(fd);
+       if (err)
+               free(buffer);
+       errno = -err;
+       return err;
+}
+
 int write_file(const char *path, const char *buf, size_t count)
 {
        int fd;