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:
parent
b505063910
commit
a974f0c131
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user