diff options
author | Benjamin Gray <bgray@linux.ibm.com> | 2023-02-03 01:39:47 +0100 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2023-02-09 13:56:45 +0100 |
commit | 8d7253dc447473dfcf3f09fb0fa2bd6f7d05b43b (patch) | |
tree | cbf5ab6fd7a01894b5482ba47c5d6d95dfded4e4 /tools/testing/selftests | |
parent | selftests/powerpc: Add {read,write}_{long,ulong} (diff) | |
download | linux-8d7253dc447473dfcf3f09fb0fa2bd6f7d05b43b.tar.xz linux-8d7253dc447473dfcf3f09fb0fa2bd6f7d05b43b.zip |
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
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r-- | tools/testing/selftests/powerpc/include/utils.h | 1 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c | 38 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/syscalls/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/syscalls/rtas_filter.c | 81 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/utils.c | 58 |
5 files changed, 71 insertions, 109 deletions
diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h index 311ddc124ebc..eed7dd7582b2 100644 --- a/tools/testing/selftests/powerpc/include/utils.h +++ b/tools/testing/selftests/powerpc/include/utils.h @@ -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 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); diff --git a/tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c b/tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c index fbc3d265155b..4de079923ccb 100644 --- a/tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c +++ b/tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c @@ -143,42 +143,6 @@ int gzip_header_blank(char *buf) 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 @@ -245,7 +209,7 @@ int compress_file(int argc, char **argv, void *handle) 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); diff --git a/tools/testing/selftests/powerpc/syscalls/Makefile b/tools/testing/selftests/powerpc/syscalls/Makefile index b63f8459c704..54ff5cfffc63 100644 --- a/tools/testing/selftests/powerpc/syscalls/Makefile +++ b/tools/testing/selftests/powerpc/syscalls/Makefile @@ -6,4 +6,4 @@ CFLAGS += -I../../../../../usr/include top_srcdir = ../../../../.. include ../../lib.mk -$(TEST_GEN_PROGS): ../harness.c +$(TEST_GEN_PROGS): ../harness.c ../utils.c diff --git a/tools/testing/selftests/powerpc/syscalls/rtas_filter.c b/tools/testing/selftests/powerpc/syscalls/rtas_filter.c index 03b487f18d00..9b17780f0b18 100644 --- a/tools/testing/selftests/powerpc/syscalls/rtas_filter.c +++ b/tools/testing/selftests/powerpc/syscalls/rtas_filter.c @@ -8,6 +8,7 @@ #include <byteswap.h> #include <stdint.h> #include <inttypes.h> +#include <linux/limits.h> #include <stdio.h> #include <string.h> #include <sys/syscall.h> @@ -50,70 +51,16 @@ struct region { 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) @@ -138,22 +85,14 @@ err: 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); diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c index 1017f1738619..7c8cfedb012a 100644 --- a/tools/testing/selftests/powerpc/utils.c +++ b/tools/testing/selftests/powerpc/utils.c @@ -65,6 +65,64 @@ out: 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; |