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: Benjamin Gray <bgray@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20230203003947.38033-6-bgray@linux.ibm.com
This commit is contained in:
committed by
Michael Ellerman
parent
5c20de5788
commit
8d7253dc44
@@ -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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
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);
|
int len = snprintf(path, sizeof(path), "%s/%s", prop_path, prop_name);
|
||||||
if (rc)
|
if (len < 0 || len >= sizeof(path))
|
||||||
return rc;
|
return -ENOMEM;
|
||||||
|
|
||||||
rc = read_entire_file(fd, prop_val, prop_len);
|
return read_file_alloc(path, prop_val, prop_len);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtas_token(const char *call_name)
|
int rtas_token(const char *call_name)
|
||||||
@@ -138,22 +85,14 @@ err:
|
|||||||
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 @@ out:
|
|||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user