// SPDX-License-Identifier: ISC #include #include #include #include #include #include #include uint64_t iec_unit_post(uint64_t val, char **unit) { static const char unit_table[] = "kKmMgGtTpPeEzZyY"; char *match; size_t pos; match = strchr(unit_table, **unit); if (!match) return val; (*unit)++; pos = (match - unit_table) / 2 + 1; for (; pos; --pos) val *= 1024; return val; } int fd_set_block(int fd, bool block) { int fl; fl = fcntl(fd, F_GETFL, 0); if (fl == -1) return -1; if (block) fl = fl & ~O_NONBLOCK; else fl = fl | O_NONBLOCK; if (fcntl(fd, F_SETFL, fl) == -1) return -1; return 0; } ssize_t read_blocking(int fd, void *buf, size_t len) { struct pollfd pfd = { .fd = fd, .events = POLLIN }; ssize_t rv; for (;;) { rv = read(fd, buf, len); if (rv >= 0 || (rv < 0 && errno != EAGAIN)) return rv; if (poll(&pfd, 1, -1) < 0) return -1; } } ssize_t write_blocking(int fd, const void *buf, size_t len) { struct pollfd pfd = { .fd = fd, .events = POLLOUT }; ssize_t rv; for (;;) { rv = write(fd, buf, len); if (rv >= 0 || (rv < 0 && errno != EAGAIN)) return rv; if (poll(&pfd, 1, -1) < 0) return -1; }; } ssize_t read_all(int fd, void *buf, size_t len) { ssize_t r; size_t rem = len; while (rem) { r = read_blocking(fd, buf, rem); if (r < 0) return -1; else if (!r) return len - rem; buf += r; rem -= r; } return len; } ssize_t write_all(int fd, const void *buf, size_t len) { ssize_t r; size_t rem = len; while (rem) { r = write_blocking(fd, buf, rem); if (r < 0) return -1; buf += r; rem -= r; } return len; } int read_exact(int fd, void *buf, size_t len) { ssize_t r; r = read_all(fd, buf, len); if (r < 0) { return -1; } else if ((size_t)r != len) { errno = EPIPE; return -1; } return 0; } int openat_read_all_close(int dirfd, const char *name, void *buf, size_t len) { int fd, ret, errsv; fd = openat(dirfd, name, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; ret = read_all(fd, buf, len); if (ret < 0) errsv = errno; close(fd); if (ret < 0) errno = errsv; return ret; } int openat_write_all_close(int dirfd, const char *name, const void *buf, size_t len, bool append) { int fd, flags, ret, errsv; flags = O_WRONLY | O_CLOEXEC; if (append) flags |= O_APPEND; else flags |= O_TRUNC; fd = openat(dirfd, name, flags); if (fd < 0) return -1; ret = write_all(fd, buf, len); if (ret < 0) errsv = errno; close(fd); if (ret < 0) errno = errsv; return ret; } int openat_read_exact_close(int dirfd, const char *name, void *buf, size_t len) { int fd, ret, errsv; fd = openat(dirfd, name, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; ret = read_exact(fd, buf, len); if (ret < 0) errsv = errno; close(fd); if (ret < 0) errno = errsv; return ret; }