aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'io.c')
-rw-r--r--io.c127
1 files changed, 127 insertions, 0 deletions
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