probe: add full libblkid support
authorJo-Philipp Wich <jo@mein.io>
Sun, 16 Oct 2016 22:05:15 +0000 (00:05 +0200)
committerJo-Philipp Wich <jo@mein.io>
Mon, 17 Oct 2016 09:45:18 +0000 (11:45 +0200)
Attempt to dlopen() libblkid.so at runtime and use it for proping
filesystems if available.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
CMakeLists.txt
probe-libblkid.c [new file with mode: 0644]
probe.c
probe.h

index 0d4c763cdea44a3e3845691090cea5c343a8c66a..e7a97db4f8d155b7c4e4d75ac667733264655457 100644 (file)
@@ -56,12 +56,12 @@ INSTALL(TARGETS mount_root RUNTIME DESTINATION sbin)
 
 find_library(json NAMES json-c json)
 
-ADD_EXECUTABLE(block block.c probe.c)
+ADD_EXECUTABLE(block block.c probe.c probe-libblkid.c)
 IF(DEFINED CMAKE_UBIFS_EXTROOT)
        ADD_DEFINITIONS(-DUBIFS_EXTROOT)
-       TARGET_LINK_LIBRARIES(block blkid-tiny uci ubox blobmsg_json ubi-utils ${json})
+       TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox blobmsg_json ubi-utils ${json})
 ELSE(DEFINED CMAKE_UBIFS_EXTROOT)
-       TARGET_LINK_LIBRARIES(block blkid-tiny uci ubox blobmsg_json ${json})
+       TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox blobmsg_json ${json})
 ENDIF(DEFINED CMAKE_UBIFS_EXTROOT)
 INSTALL(TARGETS block RUNTIME DESTINATION sbin)
 
diff --git a/probe-libblkid.c b/probe-libblkid.c
new file mode 100644 (file)
index 0000000..c448888
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 Jo-Philipp Wich <jo@mein.io>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dlfcn.h>
+#include <string.h>
+#include <stdbool.h>
+#include <blkid/blkid.h>
+#include <libubox/utils.h>
+
+#include "probe.h"
+
+
+static struct {
+       bool loaded;
+       blkid_probe (*alloc)(const char *);
+       int (*probe)(blkid_probe);
+       int (*lookup)(blkid_probe, const char *, const char **, size_t *);
+       void (*free)(blkid_probe);
+} libblkid = { };
+
+
+static bool
+load_libblkid(void)
+{
+       void *lib;
+
+       if (!libblkid.loaded) {
+               lib = dlopen("libblkid.so", RTLD_GLOBAL);
+
+               if (lib) {
+                       libblkid.alloc  = dlsym(lib, "blkid_new_probe_from_filename");
+                       libblkid.probe  = dlsym(lib, "blkid_do_probe");
+                       libblkid.lookup = dlsym(lib, "blkid_probe_lookup_value");
+                       libblkid.free   = dlsym(lib, "blkid_free_probe");
+               }
+
+               libblkid.loaded = true;
+       }
+
+       return (libblkid.alloc && libblkid.probe && libblkid.lookup && libblkid.free);
+}
+
+struct probe_info *
+probe_path_libblkid(const char *path)
+{
+       blkid_probe pr;
+       struct probe_info *info = NULL;
+       size_t type_len, uuid_len, label_len, name_len, version_len;
+       char *dev_ptr, *type_ptr, *uuid_ptr, *label_ptr, *name_ptr, *version_ptr;
+       const char *type_val, *uuid_val, *label_val, *name_val, *version_val;
+
+       if (!load_libblkid())
+               return NULL;
+
+       pr = libblkid.alloc(path);
+
+       if (!pr)
+               return NULL;
+
+       if (libblkid.probe(pr) == 0) {
+               if (libblkid.lookup(pr, "TYPE", &type_val, &type_len))
+                       type_len = 0;
+
+               if (libblkid.lookup(pr, "UUID", &uuid_val, &uuid_len))
+                       uuid_len = 0;
+
+               if (libblkid.lookup(pr, "LABEL", &label_val, &label_len))
+                       label_len = 0;
+
+               if (libblkid.lookup(pr, "NAME", &name_val, &name_len))
+                       name_len = 0;
+
+               if (libblkid.lookup(pr, "VERSION", &version_val, &version_len))
+                       version_len = 0;
+
+               if (type_len) {
+                       info = calloc_a(sizeof(*info),
+                                       &dev_ptr,     strlen(path) + 1,
+                                       &type_ptr,    type_len,
+                                       &uuid_ptr,    uuid_len,
+                                       &label_ptr,   label_len,
+                                       &name_ptr,    name_len,
+                                       &version_ptr, version_len);
+
+                       if (info) {
+                               info->dev = strcpy(dev_ptr, path);
+                               info->type = strcpy(type_ptr, type_val);
+
+                               if (uuid_len)
+                                       info->uuid = strcpy(uuid_ptr, uuid_val);
+
+                               if (label_len)
+                                       info->label = strcpy(label_ptr, label_val);
+
+                               if (name_len)
+                                       info->name = strcpy(name_ptr, name_val);
+
+                               if (version_len)
+                                       info->version = strcpy(version_ptr, version_val);
+                       }
+               }
+       }
+
+       libblkid.free(pr);
+
+       return info;
+}
diff --git a/probe.c b/probe.c
index 9983a723d5e6ea73375f1803b35d51a34c603661..1117044898b6abae11c29f5f1b0abab95c1edcd1 100644 (file)
--- a/probe.c
+++ b/probe.c
@@ -35,7 +35,7 @@ probe_path_tiny(const char *path)
 
                if (info) {
                        info->type = strcpy(type, pr.id->name);
-                       
+
                        if (pr.dev[0])
                                info->dev = strcpy(dev, pr.dev);
 
@@ -56,10 +56,17 @@ probe_path_tiny(const char *path)
        return info;
 }
 
-struct probe_info * 
+struct probe_info *
 probe_path(const char *path)
 {
-       return probe_path_tiny(path);
+       struct probe_info *info;
+
+       info = probe_path_tiny(path);
+
+       if (!info)
+               info = probe_path_libblkid(path);
+
+       return info;
 }
 
 int
diff --git a/probe.h b/probe.h
index bcee3a81149de27d1d28ffad81d6ad4fbf531197..b8557a4dbea35021c9d5bc85ad5125057b05dbf0 100644 (file)
--- a/probe.h
+++ b/probe.h
@@ -28,6 +28,7 @@ struct probe_info {
 };
 
 struct probe_info * probe_path(const char *path);
+struct probe_info * probe_path_libblkid(const char *path);
 
 int make_devs(void);