// SPDX-License-Identifier: GPL-2.0 #include #include #include #include #include #include #include "file_utils.h" int read_file(const char *path, char *buf, size_t buflen) { int fd, err; ssize_t numread; fd = open(path, O_RDONLY); if (fd == -1) return -errno; numread = read(fd, buf, buflen - 1); if (numread < 1) { err = numread ? errno : ENODATA; close(fd); return -err; } buf[numread] = '\0'; close(fd); return 0; } int write_file(const char *path, const char *buf, size_t buflen) { int fd, saved_errno; ssize_t numwritten; if (buflen < 2) return -EINVAL; fd = open(path, O_WRONLY); if (fd == -1) return -errno; numwritten = write(fd, buf, buflen - 1); saved_errno = errno; close(fd); if (numwritten < 0) return -saved_errno; if (numwritten != (ssize_t)(buflen - 1)) return -EIO; return 0; } int read_num(const char *path, unsigned long *num) { unsigned long val; int ret; char buf[21]; char *end; if (!num) return -EINVAL; ret = read_file(path, buf, sizeof(buf)); if (ret) return ret; /* Reject signs and leading whitespace that are accepted by strtoul() */ if (buf[0] < '0' || buf[0] > '9') return -EINVAL; errno = 0; val = strtoul(buf, &end, 10); if (errno) return -errno; /* Only allow a newline after the number */ if (*end == '\n') end++; if (*end != '\0') return -EINVAL; *num = val; return 0; } int write_num(const char *path, unsigned long num) { char buf[21]; sprintf(buf, "%lu", num); return write_file(path, buf, strlen(buf) + 1); } int write_num_ignore_einval(const char *path, unsigned long num) { int ret; ret = write_num(path, num); return ret == -EINVAL ? 0 : ret; }