X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=libfstools%2Ffind.c;h=190fa81ad564d75c56ba39b48df33f2729283789;hb=7d78836dac9e0ece57c51ab06589efa524276b9d;hp=9fd83c9d3396e04d4eb7572958e3e5b573cbe40e;hpb=bf4f08af9b8fe991216023a906182744eb1e4645;p=project%2Ffstools.git diff --git a/libfstools/find.c b/libfstools/find.c index 9fd83c9..190fa81 100644 --- a/libfstools/find.c +++ b/libfstools/find.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "libfstools.h" @@ -76,40 +78,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 mtd_only) +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 (mtd_only && - strncmp(t, "jffs2", 5) && - strncmp(t, "ubifs", 5) && - strncmp(t, "ext4", 4)) { - 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; } }