Commit 8d7253dc authored by Benjamin Gray's avatar Benjamin Gray Committed by Michael Ellerman

selftests/powerpc: Add automatically allocating read_file

A couple of tests roll their own auto-allocating file read logic.

Add a generic implementation and convert them to use it.
Signed-off-by: default avatarBenjamin Gray <bgray@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20230203003947.38033-6-bgray@linux.ibm.com
parent 5c20de57
...@@ -42,6 +42,7 @@ int parse_ulong(const char *buffer, size_t count, unsigned long *result, int bas ...@@ -42,6 +42,7 @@ int parse_ulong(const char *buffer, size_t count, unsigned long *result, int bas
int read_file(const char *path, char *buf, size_t count, size_t *len); 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 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 read_long(const char *path, long *result, int base);
int write_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); int read_ulong(const char *path, unsigned long *result, int base);
......
...@@ -143,42 +143,6 @@ int gzip_header_blank(char *buf) ...@@ -143,42 +143,6 @@ int gzip_header_blank(char *buf)
return i; 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. * Z_SYNC_FLUSH as described in zlib.h.
* Returns number of appended bytes * Returns number of appended bytes
...@@ -245,7 +209,7 @@ int compress_file(int argc, char **argv, void *handle) ...@@ -245,7 +209,7 @@ int compress_file(int argc, char **argv, void *handle)
fprintf(stderr, "usage: %s <fname>\n", argv[0]); fprintf(stderr, "usage: %s <fname>\n", argv[0]);
exit(-1); exit(-1);
} }
if (read_alloc_input_file(argv[1], &inbuf, &inlen)) if (read_file_alloc(argv[1], &inbuf, &inlen))
exit(-1); exit(-1);
fprintf(stderr, "file %s read, %ld bytes\n", argv[1], inlen); fprintf(stderr, "file %s read, %ld bytes\n", argv[1], inlen);
......
...@@ -6,4 +6,4 @@ CFLAGS += -I../../../../../usr/include ...@@ -6,4 +6,4 @@ CFLAGS += -I../../../../../usr/include
top_srcdir = ../../../../.. top_srcdir = ../../../../..
include ../../lib.mk include ../../lib.mk
$(TEST_GEN_PROGS): ../harness.c $(TEST_GEN_PROGS): ../harness.c ../utils.c
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <byteswap.h> #include <byteswap.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <linux/limits.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/syscall.h> #include <sys/syscall.h>
...@@ -50,70 +51,16 @@ struct region { ...@@ -50,70 +51,16 @@ struct region {
struct region *next; 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, static int get_property(const char *prop_path, const char *prop_name,
char **prop_val, size_t *prop_len) char **prop_val, size_t *prop_len)
{ {
int rc, fd; char path[PATH_MAX];
rc = open_prop_file(prop_path, prop_name, &fd);
if (rc)
return rc;
rc = read_entire_file(fd, prop_val, prop_len); int len = snprintf(path, sizeof(path), "%s/%s", prop_path, prop_name);
close(fd); 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) int rtas_token(const char *call_name)
...@@ -138,22 +85,14 @@ int rtas_token(const char *call_name) ...@@ -138,22 +85,14 @@ int rtas_token(const char *call_name)
static int read_kregion_bounds(struct region *kregion) static int read_kregion_bounds(struct region *kregion)
{ {
char *buf; char *buf;
int fd; int err;
int rc;
fd = open("/proc/ppc64/rtas/rmo_buffer", O_RDONLY); err = read_file_alloc("/proc/ppc64/rtas/rmo_buffer", &buf, NULL);
if (fd < 0) { if (err) {
printf("Could not open rmo_buffer file\n"); perror("Could not open rmo_buffer file");
return RTAS_IO_ASSERT; 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); sscanf(buf, "%" SCNx64 " %x", &kregion->addr, &kregion->size);
free(buf); free(buf);
......
...@@ -65,6 +65,64 @@ int read_file(const char *path, char *buf, size_t count, size_t *len) ...@@ -65,6 +65,64 @@ int read_file(const char *path, char *buf, size_t count, size_t *len)
return err; 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 write_file(const char *path, const char *buf, size_t count)
{ {
int fd; int fd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment