selftests/powerpc: Add generic read/write file util

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
This commit is contained in:
Benjamin Gray 2023-02-03 11:39:43 +11:00 committed by Michael Ellerman
parent b505063910
commit a974f0c131
7 changed files with 122 additions and 162 deletions

View 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)

View File

@ -12,24 +12,13 @@
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_file(file, buf, sizeof(buf) - 1, NULL);
if (rc)
return rc;
rc = read(fd, buf, sizeof(buf));
if (rc == -1) {
perror("read() failed");
close(fd);
return 1;
}
close(fd);
buf[rc] = '\0';
if (strtol(buf, NULL, 16) != val) {
printf("DSCR match failed: %ld (system) %ld (cpu)\n",
val, strtol(buf, NULL, 16));

View 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);

View 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);
}

View 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;
char *end;
char buf[16] = {0};
rc = false;
f = fopen(PARANOID_PATH, "r");
if (!f) {
perror("fopen");
goto out;
}
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;
}

View 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"))

View File

@ -26,34 +26,83 @@
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;
}
num = read(fd, buf, buf_size);
if (num < 0) {
perror("read");
rc = -EIO;
rc = read(fd, buf, count);
if (rc < 0) {
err = -errno;
goto out;
}
if (num > buf_size) {
printf("overflowed auxv buffer\n");
rc = -EOVERFLOW;
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;
}
}
rc = 0;
err = 0;
out:
close(fd);
return rc;
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 (rc != count) {
err = -EOVERFLOW;
goto out;
}
err = 0;
out:
close(fd);
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;
err = read_file(path, value, sizeof(value) - 1, NULL);
if (err)
return err;
if ((rc = read(fd, value, sizeof(value))) < 0)
return rc;
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,