selftests/powerpc: Add generic read/write file util
authorBenjamin Gray <bgray@linux.ibm.com>
Fri, 3 Feb 2023 00:39:43 +0000 (11:39 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 9 Feb 2023 12:56:45 +0000 (23:56 +1100)
File read/write is reimplemented in about 5 different ways in the
various PowerPC selftests. This indicates it should be a common util.

Add a common read_file / write_file implementation and convert users
to it where (easily) possible.

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-2-bgray@linux.ibm.com
tools/testing/selftests/powerpc/dscr/dscr.h
tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
tools/testing/selftests/powerpc/include/utils.h
tools/testing/selftests/powerpc/nx-gzip/gzfht_test.c
tools/testing/selftests/powerpc/pmu/lib.c
tools/testing/selftests/powerpc/ptrace/core-pkey.c
tools/testing/selftests/powerpc/utils.c

index b703714..aaa2b0d 100644 (file)
@@ -64,48 +64,31 @@ inline void set_dscr_usr(unsigned long val)
 /* Default DSCR access */
 unsigned long get_default_dscr(void)
 {
-       int fd = -1, ret;
-       char buf[16];
+       int err;
+       char buf[16] = {0};
        unsigned long val;
 
-       if (fd == -1) {
-               fd = open(DSCR_DEFAULT, O_RDONLY);
-               if (fd == -1) {
-                       perror("open() failed");
-                       exit(1);
-               }
-       }
-       memset(buf, 0, sizeof(buf));
-       lseek(fd, 0, SEEK_SET);
-       ret = read(fd, buf, sizeof(buf));
-       if (ret == -1) {
+       err = read_file(DSCR_DEFAULT, buf, sizeof(buf) - 1, NULL);
+       if (err) {
                perror("read() failed");
                exit(1);
        }
        sscanf(buf, "%lx", &val);
-       close(fd);
        return val;
 }
 
 void set_default_dscr(unsigned long val)
 {
-       int fd = -1, ret;
+       int err;
        char buf[16];
 
-       if (fd == -1) {
-               fd = open(DSCR_DEFAULT, O_RDWR);
-               if (fd == -1) {
-                       perror("open() failed");
-                       exit(1);
-               }
-       }
        sprintf(buf, "%lx\n", val);
-       ret = write(fd, buf, strlen(buf));
-       if (ret == -1) {
+
+       err = write_file(DSCR_DEFAULT, buf, strlen(buf));
+       if (err) {
                perror("write() failed");
                exit(1);
        }
-       close(fd);
 }
 
 double uniform_deviate(int seed)
index f20d1c1..c350f19 100644 (file)
 
 static int check_cpu_dscr_default(char *file, unsigned long val)
 {
-       char buf[10];
-       int fd, rc;
+       char buf[10] = {0};
+       int rc;
 
-       fd = open(file, O_RDWR);
-       if (fd == -1) {
-               perror("open() failed");
-               return 1;
-       }
-
-       rc = read(fd, buf, sizeof(buf));
-       if (rc == -1) {
-               perror("read() failed");
-               close(fd);
-               return 1;
-       }
-       close(fd);
+       rc = read_file(file, buf, sizeof(buf) - 1, NULL);
+       if (rc)
+               return rc;
 
-       buf[rc] = '\0';
        if (strtol(buf, NULL, 16) != val) {
                printf("DSCR match failed: %ld (system) %ld (cpu)\n",
                                        val, strtol(buf, NULL, 16));
index e222a58..70885e5 100644 (file)
@@ -33,6 +33,8 @@ void *get_auxv_entry(int type);
 
 int pick_online_cpu(void);
 
+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_debugfs_file(char *debugfs_file, int *result);
 int write_debugfs_file(char *debugfs_file, int result);
 int read_sysfs_file(char *debugfs_file, char *result, size_t result_size);
index 095195a..fbc3d26 100644 (file)
@@ -146,49 +146,37 @@ int gzip_header_blank(char *buf)
 /* 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;
-       FILE *fp;
        char *p;
        size_t num_bytes;
 
        if (stat(fname, &statbuf)) {
                perror(fname);
-               return(-1);
-       }
-       fp = fopen(fname, "r");
-       if (fp == NULL) {
-               perror(fname);
-               return(-1);
+               return -1;
        }
+
        assert(NULL != (p = (char *) malloc(statbuf.st_size)));
-       num_bytes = fread(p, 1, statbuf.st_size, fp);
-       if (ferror(fp) || (num_bytes != statbuf.st_size)) {
+
+       err = read_file(fname, p, statbuf.st_size, &num_bytes);
+       if (err) {
                perror(fname);
-               return(-1);
+               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;
-}
 
-/* Returns nonzero on error */
-int write_output_file(char *fname, char *buf, size_t bufsize)
-{
-       FILE *fp;
-       size_t num_bytes;
-
-       fp = fopen(fname, "w");
-       if (fp == NULL) {
-               perror(fname);
-               return(-1);
-       }
-       num_bytes = fwrite(buf, 1, bufsize, fp);
-       if (ferror(fp) || (num_bytes != bufsize)) {
-               perror(fname);
-               return(-1);
-       }
-       fclose(fp);
-       return 0;
+fail:
+       free(p);
+       return err;
 }
 
 /*
@@ -399,7 +387,7 @@ int compress_file(int argc, char **argv, void *handle)
        assert(FNAME_MAX > (strlen(argv[1]) + strlen(FEXT)));
        strcpy(outname, argv[1]);
        strcat(outname, FEXT);
-       if (write_output_file(outname, outbuf, dsttotlen)) {
+       if (write_file(outname, outbuf, dsttotlen)) {
                fprintf(stderr, "write error: %s\n", outname);
                exit(-1);
        }
index 88690b9..9609153 100644 (file)
@@ -190,38 +190,23 @@ int parse_proc_maps(void)
 
 bool require_paranoia_below(int level)
 {
+       int err;
        long current;
-       char *end, buf[16];
-       FILE *f;
-       bool rc;
-
-       rc = false;
-
-       f = fopen(PARANOID_PATH, "r");
-       if (!f) {
-               perror("fopen");
-               goto out;
-       }
+       char *end;
+       char buf[16] = {0};
 
-       if (!fgets(buf, sizeof(buf), f)) {
+       err = read_file(PARANOID_PATH, buf, sizeof(buf) - 1, NULL);
+       if (err) {
                printf("Couldn't read " PARANOID_PATH "?\n");
-               goto out_close;
+               return false;
        }
 
        current = strtol(buf, &end, 10);
 
        if (end == buf) {
                printf("Couldn't parse " PARANOID_PATH "?\n");
-               goto out_close;
+               return false;
        }
 
-       if (current >= level)
-               goto out_close;
-
-       rc = true;
-out_close:
-       fclose(f);
-out:
-       return rc;
+       return current < level;
 }
-
index 4e8d0ce..f6f8596 100644 (file)
@@ -348,15 +348,11 @@ static int parent(struct shared_info *info, pid_t pid)
 
 static int write_core_pattern(const char *core_pattern)
 {
-       size_t len = strlen(core_pattern), ret;
-       FILE *f;
+       int err;
 
-       f = fopen(core_pattern_file, "w");
-       SKIP_IF_MSG(!f, "Try with root privileges");
-
-       ret = fwrite(core_pattern, 1, len, f);
-       fclose(f);
-       if (ret != len) {
+       err = write_file(core_pattern_file, core_pattern, strlen(core_pattern));
+       if (err) {
+               SKIP_IF_MSG(err == -EPERM, "Try with root privileges");
                perror("Error writing to core_pattern file");
                return TEST_FAIL;
        }
@@ -366,8 +362,8 @@ static int write_core_pattern(const char *core_pattern)
 
 static int setup_core_pattern(char **core_pattern_, bool *changed_)
 {
-       FILE *f;
        char *core_pattern;
+       size_t len;
        int ret;
 
        core_pattern = malloc(PATH_MAX);
@@ -376,22 +372,14 @@ static int setup_core_pattern(char **core_pattern_, bool *changed_)
                return TEST_FAIL;
        }
 
-       f = fopen(core_pattern_file, "r");
-       if (!f) {
-               perror("Error opening core_pattern file");
-               ret = TEST_FAIL;
-               goto out;
-       }
-
-       ret = fread(core_pattern, 1, PATH_MAX - 1, f);
-       fclose(f);
-       if (!ret) {
+       ret = read_file(core_pattern_file, core_pattern, PATH_MAX - 1, &len);
+       if (ret) {
                perror("Error reading core_pattern file");
                ret = TEST_FAIL;
                goto out;
        }
 
-       core_pattern[ret] = '\0';
+       core_pattern[len] = '\0';
 
        /* Check whether we can predict the name of the core file. */
        if (!strcmp(core_pattern, "core") || !strcmp(core_pattern, "core.%p"))
index 1f36ee1..22ba134 100644 (file)
 
 static char auxv[4096];
 
-int read_auxv(char *buf, ssize_t buf_size)
+int read_file(const char *path, char *buf, size_t count, size_t *len)
 {
-       ssize_t num;
-       int rc, fd;
+       ssize_t rc;
+       int fd;
+       int err;
+       char eof;
 
-       fd = open("/proc/self/auxv", O_RDONLY);
-       if (fd == -1) {
-               perror("open");
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
                return -errno;
+
+       rc = read(fd, buf, count);
+       if (rc < 0) {
+               err = -errno;
+               goto out;
+       }
+
+       if (len)
+               *len = rc;
+
+       /* Overflow if there are still more bytes after filling the buffer */
+       if (rc == count) {
+               rc = read(fd, &eof, 1);
+               if (rc != 0) {
+                       err = -EOVERFLOW;
+                       goto out;
+               }
        }
 
-       num = read(fd, buf, buf_size);
-       if (num < 0) {
-               perror("read");
-               rc = -EIO;
+       err = 0;
+
+out:
+       close(fd);
+       errno = -err;
+       return err;
+}
+
+int write_file(const char *path, const char *buf, size_t count)
+{
+       int fd;
+       int err;
+       ssize_t rc;
+
+       fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+       if (fd < 0)
+               return -errno;
+
+       rc = write(fd, buf, count);
+       if (rc < 0) {
+               err = -errno;
                goto out;
        }
 
-       if (num > buf_size) {
-               printf("overflowed auxv buffer\n");
-               rc = -EOVERFLOW;
+       if (rc != count) {
+               err = -EOVERFLOW;
                goto out;
        }
 
-       rc = 0;
+       err = 0;
+
 out:
        close(fd);
-       return rc;
+       errno = -err;
+       return err;
+}
+
+int read_auxv(char *buf, ssize_t buf_size)
+{
+       int err;
+
+       err = read_file("/proc/self/auxv", buf, buf_size, NULL);
+       if (err) {
+               perror("Error reading /proc/self/auxv");
+               return err;
+       }
+
+       return 0;
 }
 
 void *find_auxv_entry(int type, char *auxv)
@@ -142,65 +191,41 @@ bool is_ppc64le(void)
 int read_sysfs_file(char *fpath, char *result, size_t result_size)
 {
        char path[PATH_MAX] = "/sys/";
-       int rc = -1, fd;
 
        strncat(path, fpath, PATH_MAX - strlen(path) - 1);
 
-       if ((fd = open(path, O_RDONLY)) < 0)
-               return rc;
-
-       rc = read(fd, result, result_size);
-
-       close(fd);
-
-       if (rc < 0)
-               return rc;
-
-       return 0;
+       return read_file(path, result, result_size, NULL);
 }
 
 int read_debugfs_file(char *debugfs_file, int *result)
 {
-       int rc = -1, fd;
+       int err;
        char path[PATH_MAX];
-       char value[16];
+       char value[16] = {0};
 
        strcpy(path, "/sys/kernel/debug/");
        strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
 
-       if ((fd = open(path, O_RDONLY)) < 0)
-               return rc;
-
-       if ((rc = read(fd, value, sizeof(value))) < 0)
-               return rc;
+       err = read_file(path, value, sizeof(value) - 1, NULL);
+       if (err)
+               return err;
 
-       value[15] = 0;
        *result = atoi(value);
-       close(fd);
 
        return 0;
 }
 
 int write_debugfs_file(char *debugfs_file, int result)
 {
-       int rc = -1, fd;
        char path[PATH_MAX];
        char value[16];
 
        strcpy(path, "/sys/kernel/debug/");
        strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1);
 
-       if ((fd = open(path, O_WRONLY)) < 0)
-               return rc;
-
        snprintf(value, 16, "%d", result);
 
-       if ((rc = write(fd, value, strlen(value))) < 0)
-               return rc;
-
-       close(fd);
-
-       return 0;
+       return write_file(path, value, strlen(value));
 }
 
 static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,