summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Golle <daniel@makrotopia.org>2016-09-11 16:52:52 +0200
committerDaniel Golle <daniel@makrotopia.org>2016-09-12 02:50:52 +0200
commit7874d580ff965bebbe19ea157353749d9f007b39 (patch)
tree46e49ab2228055b9c98ffb29c36c1b0461e1ef86
parentfe514c9a20365ba00232c2c981463f43a4a41a7d (diff)
downloadfstools-7874d580ff965bebbe19ea157353749d9f007b39.tar.gz
libfstools: gather mountpoints from /proc/self/mountinfo
This allows identifying /dev/root by its major:minor number which are part of /proc/self/mountinfo but aren't contained in /proc/mounts. Also fix jffs2reset when using an ext4 overlay by adding it to the list of filesystems allowed if the root_only parameter of find_mount_point is set. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-rw-r--r--libfstools/find.c144
1 files changed, 120 insertions, 24 deletions
diff --git a/libfstools/find.c b/libfstools/find.c
index 72a2b4c..52bc51f 100644
--- a/libfstools/find.c
+++ b/libfstools/find.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
#include "libfstools.h"
@@ -76,40 +77,135 @@ find_mount(char *mp)
return point;
}
+/*
+ * Match filesystem type against a bunch of valid types
+ *
+ * jffs2reset may ask if the filesystem type is actually ready for use
+ * with overlayfs before wiping it...
+ */
+static int fs_rootfs_only(char *fstype)
+{
+ if (strncmp(fstype, "ext4", 4) &&
+ strncmp(fstype, "f2fs", 4) &&
+ strncmp(fstype, "jffs2", 5) &&
+ strncmp(fstype, "ubifs", 5)) {
+ ULOG_ERR("block is mounted with wrong fs\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check if a given device is mounted and return its mountpoint
+ */
char*
find_mount_point(char *block, int root_only)
{
- FILE *fp = fopen("/proc/mounts", "r");
+ FILE *fp = fopen("/proc/self/mountinfo", "r");
static char line[256];
int len = strlen(block);
- char *point = NULL;
+ char *point = NULL, *pos, *tmp, *cpoint, *devname, *fstype;
+ struct stat s;
+ int rstat;
+ unsigned int minor, major;
- if(!fp)
+ if (!fp)
return NULL;
+ rstat = stat(block, &s);
+
while (fgets(line, sizeof(line), fp)) {
- if (!strncmp(line, block, len)) {
- char *p = &line[len + 1];
- char *t = strstr(p, " ");
-
- if (!t) {
- fclose(fp);
- return NULL;
- }
-
- *t = '\0';
- t++;
-
- if (root_only &&
- strncmp(t, "f2fs", 4) &&
- strncmp(t, "jffs2", 5) &&
- strncmp(t, "ubifs", 5)) {
- fclose(fp);
- ULOG_ERR("block is mounted with wrong fs\n");
- return NULL;
- }
- point = p;
+ /* skip first two columns */
+ pos = strchr(line, ' ');
+ if (!pos)
+ continue;
+
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ /* extract block device major:minor */
+ tmp = ++pos;
+ pos = strchr(pos, ':');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ major = atoi(tmp);
+
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ minor = atoi(tmp);
+
+ /* skip another column */
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ /* get mountpoint */
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ cpoint = tmp;
+
+ /* skip another two columns */
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ pos = strchr(pos + 1, ' ');
+ if (!pos)
+ continue;
+
+ /* get fstype */
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ fstype = tmp;
+
+ /* get device name */
+ tmp = ++pos;
+ pos = strchr(pos, ' ');
+ if (!pos)
+ continue;
+
+ *pos = '\0';
+ devname = tmp;
+
+ /* if device name matches */
+ if (!strncmp(block, devname, len)) {
+ if (root_only && fs_rootfs_only(fstype))
+ break;
+
+ /* found, return mountpoint */
+ point = strdup(cpoint);
+ break;
+ }
+
+ /* last chance: check if major:minor of block device match */
+ if (rstat)
+ continue;
+
+ if (!S_ISBLK(s.st_mode))
+ continue;
+
+ if (major == major(s.st_rdev) &&
+ minor == minor(s.st_rdev)) {
+ if (root_only && fs_rootfs_only(fstype))
+ break;
+ /* found, return mountpoint */
+ point = strdup(cpoint);
break;
}
}