]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - tools-util.c
Merge https://github.com/YellowOnion/bcachefs-tools
[bcachefs-tools-debian] / tools-util.c
index d545049552ced523a80c20e8d86262a1b48f0320..3cc0de444cf95b32d2def2e16c476c6bd726bcb6 100644 (file)
@@ -31,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, ...)
@@ -82,10 +82,16 @@ void *xrealloc(void *p, size_t size)
 
 void xpread(int fd, void *buf, size_t count, off_t offset)
 {
-       ssize_t r = pread(fd, buf, count, offset);
-
-       if (r != count)
-               die("read error (ret %zi)", r);
+       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)
@@ -112,7 +118,30 @@ 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: */
+
+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)
 {
@@ -168,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);
 
@@ -189,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);
 
@@ -256,6 +289,8 @@ 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);
@@ -357,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++;
@@ -501,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;
@@ -517,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
 
@@ -574,34 +616,71 @@ char *dev_to_path(dev_t dev)
        return path;
 }
 
-char *dev_to_mount(char *dev)
+struct mntent *dev_to_mount(char *dev)
 {
-       char *line = NULL, *ret = NULL;
-       size_t n = 0;
-
-       FILE *f = fopen("/proc/mounts", "r");
+       struct mntent *mnt, *ret = NULL;
+       FILE *f = setmntent("/proc/mounts", "r");
        if (!f)
                die("error opening /proc/mounts: %m");
 
-       while (getline(&line, &n, f) != -1) {
-               char *d, *p = line;
-               char *devs = strsep(&p, " ");
-               char *mount = strsep(&p, " ");
-
-               if (!devs || !mount)
-                       continue;
-
-               p = devs;
-               while ((d = strsep(&p, ":")))
-                       if (!strcmp(d, dev)) {
-                               ret = strdup(mount);
-                               goto found;
+       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);
-       free(line);
        return ret;
 }
 
-#endif
+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 };
+}