diff options
author | Mattias Andrée <maandree@kth.se> | 2024-09-21 19:31:16 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-09-21 19:31:16 +0200 |
commit | 2e55bedc45e836899a18ea7f4a488f50597afad5 (patch) | |
tree | 5a9e3cc1465cfc711fb1f74580cb17f20a46212e /io.c | |
parent | Update documentation and adjust blocksize if larger than the device size (diff) | |
download | deadshred-2e55bedc45e836899a18ea7f4a488f50597afad5.tar.gz deadshred-2e55bedc45e836899a18ea7f4a488f50597afad5.tar.bz2 deadshred-2e55bedc45e836899a18ea7f4a488f50597afad5.tar.xz |
misc
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 127 |
1 files changed, 127 insertions, 0 deletions
@@ -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 |