X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=tools-util.c;h=3cc0de444cf95b32d2def2e16c476c6bd726bcb6;hb=8d86f9c15da65965c53e5264433730b20c6f79f9;hp=7c88c9d42a814e821b11d673857416d1e84848c8;hpb=bf8c59996b3fb2a940827d12438a9e18eca6db4c;p=bcachefs-tools-debian diff --git a/tools-util.c b/tools-util.c index 7c88c9d..3cc0de4 100644 --- a/tools-util.c +++ b/tools-util.c @@ -10,16 +10,17 @@ #include #include #include +#include #include #include #include #include -#include "bcachefs_ioctl.h" +#include "libbcachefs/bcachefs_ioctl.h" #include "linux/sort.h" #include "tools-util.h" -#include "util.h" +#include "libbcachefs/util.h" void die(const char *fmt, ...) { @@ -30,7 +31,7 @@ void die(const char *fmt, ...) va_end(args); fputc('\n', stderr); - exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } char *mprintf(const char *fmt, ...) @@ -70,12 +71,27 @@ void *xmalloc(size_t size) return p; } -void xpread(int fd, void *buf, size_t count, off_t offset) +void *xrealloc(void *p, size_t size) { - ssize_t r = pread(fd, buf, count, offset); + p = realloc(p, size); + if (!p) + die("insufficient memory"); - if (r != count) - die("read error (ret %zi)", r); + return p; +} + +void xpread(int fd, void *buf, size_t count, off_t offset) +{ + while (count) { + ssize_t r = pread(fd, buf, count, offset); + + if (r < 0) + die("read error: %m"); + if (!r) + die("pread error: unexpected eof"); + count -= r; + offset += r; + } } void xpwrite(int fd, const void *buf, size_t count, off_t offset) @@ -102,29 +118,59 @@ struct stat xfstat(int fd) return stat; } -/* Integer stuff: */ +struct stat xstat(const char *path) +{ + struct stat statbuf; + if (stat(path, &statbuf)) + die("stat error statting %s: %m", path); + return statbuf; +} + +/* Formatting: */ -struct units_buf __pr_units(u64 v, enum units units) +int printf_pad(unsigned pad, const char * fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = vprintf(fmt, args); + va_end(args); + + while (ret++ < pad) + putchar(' '); + + return ret; +} + +struct units_buf __pr_units(s64 _v, enum units units) { struct units_buf ret; + char *out = ret.b, *end = out + sizeof(ret.b); + u64 v = _v; + + if (_v < 0) { + out += scnprintf(out, end - out, "-"); + v = -_v; + } switch (units) { case BYTES: - snprintf(ret.b, sizeof(ret.b), "%llu", v << 9); + snprintf(out, end - out, "%llu", v << 9); break; case SECTORS: - snprintf(ret.b, sizeof(ret.b), "%llu", v); + snprintf(out, end - out, "%llu", v); break; case HUMAN_READABLE: v <<= 9; if (v >= 1024) { int exp = log(v) / log(1024); - snprintf(ret.b, sizeof(ret.b), "%.1f%c", + snprintf(out, end - out, "%.1f%c", v / pow(1024, exp), "KMGTPE"[exp-1]); } else { - snprintf(ret.b, sizeof(ret.b), "%llu", v); + snprintf(out, end - out, "%llu", v); } break; @@ -151,6 +197,10 @@ char *read_file_str(int dirfd, const char *path) buf[len] = '\0'; if (len && buf[len - 1] == '\n') buf[len - 1] = '\0'; + if (!strlen(buf)) { + free(buf); + buf = NULL; + } close(fd); @@ -172,7 +222,7 @@ u64 read_file_u64(int dirfd, const char *path) ssize_t read_string_list_or_die(const char *opt, const char * const list[], const char *msg) { - ssize_t v = bch2_read_string_list(opt, list); + ssize_t v = match_string(list, -1, opt); if (v < 0) die("Bad %s %s", msg, opt); @@ -239,57 +289,14 @@ int open_for_format(const char *dev, bool force) fputs("Proceed anyway?", stdout); if (!ask_yn()) exit(EXIT_FAILURE); + while (blkid_do_probe(pr) == 0) + blkid_do_wipe(pr, 0); } blkid_free_probe(pr); return fd; } -/* Global control device: */ -int bcachectl_open(void) -{ - return xopen("/dev/bcachefs-ctl", O_RDWR); -} - -/* Filesystem handles (ioctl, sysfs dir): */ - -#define SYSFS_BASE "/sys/fs/bcachefs/" - -struct bcache_handle bcache_fs_open(const char *path) -{ - struct bcache_handle ret; - uuid_t tmp; - - if (!uuid_parse(path, tmp)) { - /* It's a UUID, look it up in sysfs: */ - char *sysfs = mprintf("%s%s", SYSFS_BASE, path); - ret.sysfs_fd = xopen(sysfs, O_RDONLY); - - char *minor = read_file_str(ret.sysfs_fd, "minor"); - char *ctl = mprintf("/dev/bcachefs%s-ctl", minor); - ret.ioctl_fd = xopen(ctl, O_RDWR); - - free(sysfs); - free(minor); - free(ctl); - } else { - /* It's a path: */ - ret.ioctl_fd = xopen(path, O_RDONLY); - - struct bch_ioctl_query_uuid uuid; - xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid); - - char uuid_str[40]; - uuid_unparse(uuid.uuid.b, uuid_str); - - char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str); - ret.sysfs_fd = xopen(sysfs, O_RDONLY); - free(sysfs); - } - - return ret; -} - bool ask_yn(void) { const char *short_yes = "yY"; @@ -385,7 +392,7 @@ struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter) return e; } -const char *strcmp_prefix(const char *a, const char *a_prefix) +char *strcmp_prefix(char *a, const char *a_prefix) { while (*a_prefix && *a == *a_prefix) { a++; @@ -529,10 +536,10 @@ static u32 crc32c_sse42(u32 crc, const void *buf, size_t size) return crc; } +#endif + static void *resolve_crc32c(void) { - __builtin_cpu_init(); - #ifdef __x86_64__ if (__builtin_cpu_supports("sse4.2")) return crc32c_sse42; @@ -545,8 +552,15 @@ static void *resolve_crc32c(void) */ #ifdef HAVE_WORKING_IFUNC +static void *ifunc_resolve_crc32c(void) +{ + __builtin_cpu_init(); + + return resolve_crc32c +} + u32 crc32c(u32, const void *, size_t) - __attribute__((ifunc("resolve_crc32c"))); + __attribute__((ifunc("ifunc_resolve_crc32c"))); #else @@ -562,4 +576,111 @@ u32 crc32c(u32 crc, const void *buf, size_t size) #endif /* HAVE_WORKING_IFUNC */ -#endif +char *dev_to_name(dev_t dev) +{ + char *line = NULL, *name = NULL; + size_t n = 0; + + FILE *f = fopen("/proc/partitions", "r"); + if (!f) + die("error opening /proc/partitions: %m"); + + while (getline(&line, &n, f) != -1) { + unsigned ma, mi; + u64 sectors; + + name = realloc(name, n + 1); + + if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 && + ma == major(dev) && mi == minor(dev)) + goto found; + } + + free(name); + name = NULL; +found: + fclose(f); + free(line); + return name; +} + +char *dev_to_path(dev_t dev) +{ + char *name = dev_to_name(dev); + if (!name) + return NULL; + + char *path = mprintf("/dev/%s", name); + + free(name); + return path; +} + +struct mntent *dev_to_mount(char *dev) +{ + struct mntent *mnt, *ret = NULL; + FILE *f = setmntent("/proc/mounts", "r"); + if (!f) + die("error opening /proc/mounts: %m"); + + struct stat d1 = xstat(dev); + + while ((mnt = getmntent(f))) { + char *d, *p = mnt->mnt_fsname; + + while ((d = strsep(&p, ":"))) { + struct stat d2; + + if (stat(d, &d2)) + continue; + + if (S_ISBLK(d1.st_mode) != S_ISBLK(d2.st_mode)) + continue; + + if (S_ISBLK(d1.st_mode)) { + if (d1.st_rdev != d2.st_rdev) + continue; + } else { + if (d1.st_dev != d2.st_dev || + d1.st_ino != d2.st_ino) + continue; + } + + ret = mnt; + goto found; + } + } +found: + fclose(f); + return ret; +} + +int dev_mounted(char *dev) +{ + struct mntent *mnt = dev_to_mount(dev); + + if (!mnt) + return 0; + if (hasmntopt(mnt, "ro")) + return 1; + return 2; +} + +struct bpos bpos_parse(char *buf) +{ + char *s = buf, *field; + u64 inode_v = 0, offset_v = 0; + + if (!(field = strsep(&s, ":")) || + kstrtoull(field, 10, &inode_v)) + die("invalid bpos %s", buf); + + if ((field = strsep(&s, ":")) && + kstrtoull(field, 10, &offset_v)) + die("invalid bpos %s", buf); + + if (s) + die("invalid bpos %s", buf); + + return (struct bpos) { .inode = inode_v, .offset = offset_v }; +}