]> sourceware.org Git - lvm2.git/commitdiff
libdm: introduce dm_mountinfo_read
authorZdenek Kabelac <zkabelac@redhat.com>
Thu, 16 May 2013 09:34:26 +0000 (11:34 +0200)
committerZdenek Kabelac <zkabelac@redhat.com>
Mon, 20 May 2013 14:28:30 +0000 (16:28 +0200)
Add function for parsing /proc/self/mountinfo entries.
This can be used to detected mounted device.

WHATS_NEW_DM
libdm/libdevmapper.h
libdm/libdm-common.c

index 39ebcb2e96ad79b2aabbefc94a913cab5caaca5a..8bdbfabcf876337bec7fded92896a6a35a74640c 100644 (file)
@@ -1,5 +1,6 @@
 Version 1.02.78 - 
 ===================================
+  Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
   Report error for nonexisting devices in dmeventd communication.
   Prevent double free error after dmeventd call of _fill_device_data().
   Update dmevent structure message_data to simplify/fix error path handling.
index b729846cc06f33ce8ece8d823e9fc61d25f946b4..d9cd280a11e01e94f0855ce10a118cefbc923b1c 100644 (file)
@@ -416,6 +416,19 @@ int dm_device_has_holders(uint32_t major, uint32_t minor);
 int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
 
 
+/*
+ * Callback is invoked for individal mountinfo lines,
+ * minor, major and mount target are parsed and unmangled.
+ */
+typedef int (*dm_mountinfo_line_callback_fn) (char *line, unsigned maj, unsigned min,
+                                             char *target, void *cb_data);
+
+/*
+ * Read all lines from /proc/self/mountinfo,
+ * for each line calls read_fn callback.
+ */
+int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data);
+
 /*
  * Initialise library
  */
index 4736b59a641609dbaad9ab851f093e3a22c39526..9e8ca258318fa95c6e96d5a753a13996b8dd86e4 100644 (file)
@@ -62,6 +62,7 @@ union semun
 static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
 static char _sysfs_dir[PATH_MAX] = "/sys/";
 static char _path0[PATH_MAX];           /* path buffer, safe 4kB on stack */
+static const char _mountinfo[] = "/proc/self/mountinfo";
 
 #define DM_MAX_UUID_PREFIX_LEN 15
 static char _default_uuid_prefix[DM_MAX_UUID_PREFIX_LEN + 1] = "LVM-";
@@ -1571,6 +1572,82 @@ const char *dm_uuid_prefix(void)
        return _default_uuid_prefix;
 }
 
+static int _is_octal(int a)
+{
+       return (((a) & ~7) == '0');
+}
+
+/* Convert mangled mountinfo into normal ASCII string */
+static void _unmangle_mountinfo_string(const char *src, char *buf)
+{
+       while (*src) {
+               if ((*src == '\\') &&
+                   _is_octal(src[1]) && _is_octal(src[2]) && _is_octal(src[3])) {
+                       *buf++ = 64 * (src[1] & 7) + 8 * (src[2] & 7) + (src[3] & 7);
+                       src += 4;
+               } else
+                       *buf++ = *src++;
+       }
+       *buf = '\0';
+}
+
+/* Macros to make string defines */
+#define TO_STRING_EXP(A) #A
+#define TO_STRING(A) TO_STRING_EXP(A)
+
+/* Parse one line of mountinfo and unmangled target line */
+static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
+{
+       char root[PATH_MAX + 1];
+       char target[PATH_MAX + 1];
+
+       /* TODO: maybe detect availability of  %ms  glib support ? */
+       if (sscanf(line, "%*u %*u %u:%u %" TO_STRING(PATH_MAX)
+                  "s %" TO_STRING(PATH_MAX) "s",
+                  maj, min, root, target) < 4) {
+               log_error("Failed to parse mountinfo line.");
+               return 0;
+       }
+
+       _unmangle_mountinfo_string(target, buf);
+
+       return 1;
+}
+
+/*
+ * Function to operate on individal mountinfo line,
+ * minor, major and mount target are parsed and unmangled
+ */
+int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
+{
+       FILE *minfo;
+       char buffer[2 * PATH_MAX];
+       char target[PATH_MAX];
+       unsigned maj, min;
+       int r = 1;
+
+       if (!(minfo = fopen(_mountinfo, "r"))) {
+               if (errno != ENOENT)
+                       log_sys_error("fopen", _mountinfo);
+               else
+                       log_sys_debug("fopen", _mountinfo);
+               return 0;
+       }
+
+       while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
+               if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
+                   !read_fn(buffer, maj, min, target, cb_data)) {
+                       stack;
+                       r = 0;
+                       break;
+               }
+
+       if (fclose(minfo))
+               log_sys_error("fclose", _mountinfo);
+
+       return r;
+}
+
 static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
 {
        char *sysfs_path, *temp_buf = NULL;
This page took 0.043585 seconds and 5 git commands to generate.