From 2e55bedc45e836899a18ea7f4a488f50597afad5 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 21 Sep 2024 19:31:16 +0200 Subject: misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- io.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 6ee9e29..98afe53 100644 --- a/io.c +++ b/io.c @@ -2,6 +2,61 @@ #include "common.h" +void +writeall(int fd, const void *data, size_t n, const char *fname) +{ + const char *text = data; + ssize_t r; + + while (n) { + r = write(fd, text, n); + if (r < 0) { + if (errno == EINTR) + continue; + eprintf("write %s:", fname); + } + text = &text[r]; + n -= (size_t)r; + } +} + + +void +filecpy(int fd, off_t src, off_t len, const char *fname) +{ + char buf[8UL << 10]; + ssize_t r; + size_t n; + size_t off; + + while (len) { + read_again: + r = pread(fd, buf, sizeof(buf), src); + if (r <= 0) { + if (!r) + eprintf("%s: unexpected end of file", fname); + if (errno == EINTR) + goto read_again; + eprintf("pread %s:", fname); + } + src += (off_t)r; + len -= (off_t)r; + n = (size_t)r; + + for (off = 0; off < n;) { + write_again: + r = write(fd, &buf[off], n - off); + if (r < 0) { + if (errno == EINTR) + goto write_again; + eprintf("write %s:", fname); + } + off += (size_t)r; + } + } +} + + off_t filesize(int fd, const char *fname) { @@ -23,3 +78,75 @@ filesize(int fd, const char *fname) return st.st_size; } + + +#if defined(__linux__) + +char * +get_device_name(unsigned int devmajor, unsigned int devminor) +{ + char dev[2 * 3 * sizeof(int) + 3]; + size_t devlen; + char buf[PATH_MAX]; + struct dirent *f; + DIR *dir; + int dfd, fd; + ssize_t r; + size_t off; + + devlen = (size_t)sprintf(dev, "%u:%u\n", devmajor, devminor); + + dir = opendir("/sys/class/block"); + if (!dir) { + weprintf("opendir /sys/class/block:"); + return NULL; + } + dfd = dirfd(dir); + if (dfd < 0) { + weprintf("dirfd /sys/class/block:"); + goto fail; + } + + while ((errno = 0, f = readdir(dir))) { + if (f->d_name[0] == '.') + continue; + if (strlen(f->d_name) > sizeof(buf) - sizeof("/dev")) + continue; + stpcpy(stpcpy(buf, f->d_name), "/dev"); + fd = openat(dfd, buf, O_RDONLY); + if (fd < 0) + continue; + + off = 0; + while (off < sizeof(buf)) { + r = read(fd, &buf[off], sizeof(buf) - off); + if (!r) + goto complete; + if (r < 0) { + if (errno == EINTR) + continue; + goto next; + } + off += (size_t)r; + } + goto next; + + complete: + if (off == devlen && !memcmp(dev, buf, devlen)) { + close(fd); + closedir(dir); + return strdup(f->d_name); + } + + next: + close(fd); + } + + if (errno) + weprintf("readdir /sys/class/block:"); +fail: + closedir(dir); + return NULL; +} + +#endif -- cgit v1.2.3-70-g09d2