summaryrefslogtreecommitdiffstats
path: root/misc-utils/findmnt-verify.c
diff options
context:
space:
mode:
authorKarel Zak2016-09-22 13:40:24 +0200
committerKarel Zak2016-09-23 13:21:02 +0200
commit5f1608e068d5987df1f305c514500e2e12e6960c (patch)
tree67595b7be8a8b08da79edc366a395121548879bf /misc-utils/findmnt-verify.c
parentfindmnt: (verify) add swaparea verification (diff)
downloadkernel-qcow2-util-linux-5f1608e068d5987df1f305c514500e2e12e6960c.tar.gz
kernel-qcow2-util-linux-5f1608e068d5987df1f305c514500e2e12e6960c.tar.xz
kernel-qcow2-util-linux-5f1608e068d5987df1f305c514500e2e12e6960c.zip
findmnt: (verify) check filesystem type
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/findmnt-verify.c')
-rw-r--r--misc-utils/findmnt-verify.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/misc-utils/findmnt-verify.c b/misc-utils/findmnt-verify.c
index 1cdd9697b..3a76bb078 100644
--- a/misc-utils/findmnt-verify.c
+++ b/misc-utils/findmnt-verify.c
@@ -9,6 +9,7 @@
#include <unistd.h>
#include <libmount.h>
#include <blkid.h>
+#include <sys/utsname.h>
#include "nls.h"
#include "c.h"
@@ -21,6 +22,10 @@ struct verify_context {
struct libmnt_fs *fs;
struct libmnt_table *tb;
+ char **fs_ary;
+ size_t fs_num;
+ size_t fs_alloc;
+
int nwarnings;
int nerrors;
@@ -261,6 +266,187 @@ static int verify_swaparea(struct verify_context *vfy)
return 0;
}
+static int is_supported_filesystem(struct verify_context *vfy, const char *name)
+{
+ size_t n;
+
+ if (!vfy->fs_num)
+ return 0;
+
+ for (n = 0; n < vfy->fs_num; n++ ) {
+ if (strcmp(vfy->fs_ary[n], name) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int add_filesystem(struct verify_context *vfy, const char *name)
+{
+ #define MYCHUNK 16
+
+ if (is_supported_filesystem(vfy, name))
+ return 0;
+
+ if (vfy->fs_alloc == 0 || vfy->fs_num + 1 <= vfy->fs_alloc) {
+ vfy->fs_alloc = ((vfy->fs_alloc + 1 + MYCHUNK) / MYCHUNK) * MYCHUNK;
+ vfy->fs_ary = xrealloc(vfy->fs_ary, vfy->fs_alloc * sizeof(char *));
+ }
+
+ vfy->fs_ary[vfy->fs_num] = xstrdup(name);
+ vfy->fs_num++;
+
+ return 0;
+}
+
+static int read_proc_filesystems(struct verify_context *vfy)
+{
+ int rc = 0;
+ FILE *f;
+ char buf[80], *cp, *t;
+
+ f = fopen("/proc/filesystems", "r");
+ if (!f)
+ return -errno;
+
+ while (!feof(f)) {
+ if (!fgets(buf, sizeof(buf), f))
+ break;
+ cp = buf;
+ if (!isspace(*cp)) {
+ while (*cp && !isspace(*cp))
+ cp++;
+ }
+ while (*cp && isspace(*cp))
+ cp++;
+ if ((t = strchr(cp, '\n')) != NULL)
+ *t = 0;
+ if ((t = strchr(cp, '\t')) != NULL)
+ *t = 0;
+ if ((t = strchr(cp, ' ')) != NULL)
+ *t = 0;
+
+ rc = add_filesystem(vfy, cp);
+ if (rc)
+ return rc;
+ }
+ fclose(f);
+ return 0;
+}
+
+static int read_kernel_filesystems(struct verify_context *vfy)
+{
+#ifdef __linux__
+ struct utsname uts;
+ FILE *f;
+ char buf[1024];
+
+ if (uname(&uts))
+ return 0;
+ snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
+
+ f = fopen(buf, "r");
+ if (!f)
+ return 0;
+
+ while (!feof(f)) {
+ char *p, *name;
+ int rc;
+
+ if (!fgets(buf, sizeof(buf), f))
+ break;
+
+ if (strncmp("kernel/fs/", buf, 10) != 0 ||
+ strncmp("kernel/fs/nls/", buf, 14) == 0)
+ continue;
+
+ p = strchr(buf, ':');
+ if (!p)
+ continue;
+ *p = '\0';
+
+ name = strrchr(buf, '/');
+ if (!name)
+ continue;
+ name++;
+
+ p = strstr(name, ".ko");
+ if (!p)
+ continue;
+ *p = '\0';
+
+ rc = add_filesystem(vfy, name);
+ if (rc)
+ return rc;
+ }
+ fclose(f);
+#endif /* __linux__ */
+ return 0;
+}
+
+static int verify_fstype(struct verify_context *vfy)
+{
+ const char *src = mnt_resolve_spec(mnt_fs_get_source(vfy->fs), cache);
+ const char *type, *realtype;
+ int ambi = 0, isauto = 0, isswap = 0;
+
+ if (!src)
+ return 0;
+ if (mnt_fs_is_pseudofs(vfy->fs) || mnt_fs_is_netfs(vfy->fs))
+ return verify_ok(vfy, _("do not check %s FS type (pseudo/net filesystem)"), src);
+
+ type = mnt_fs_get_fstype(vfy->fs);
+
+ if (type) {
+ int none = strcmp(type, "none") == 0;
+
+ if (none
+ && mnt_fs_get_option(vfy->fs, "bind", NULL, NULL) == 1
+ && mnt_fs_get_option(vfy->fs, "move", NULL, NULL) == 1)
+ return verify_warn(vfy, _("\"none\" FS type is recommended for bind or move oprations only"));
+
+ else if (strcmp(type, "auto") == 0)
+ isauto = 1;
+ else if (strcmp(type, "swap") == 0)
+ isswap = 1;
+
+ if (!isswap && !isauto && !none && !is_supported_filesystem(vfy, type))
+ verify_warn(vfy, _("%s seems unspported by the current kernel"), type);
+ }
+ realtype = mnt_get_fstype(src, &ambi, cache);
+
+ if (!realtype) {
+ if (isauto)
+ return verify_err(vfy, _("cannot detect on-disk filesystem type"));
+ return verify_warn(vfy, _("cannot detect on-disk filesystem type"));
+ }
+
+ if (realtype) {
+ isswap = strcmp(realtype, "swap") == 0;
+
+ if (type && !isauto && strcmp(type, realtype) != 0)
+ return verify_err(vfy, _("%s does not match with on-disk %s"), type, realtype);
+
+ if (!isswap && !is_supported_filesystem(vfy, realtype))
+ return verify_err(vfy, _("on-disk %s seems unspported by the current kernel"), realtype);
+
+ verify_ok(vfy, _("FS type is %s"), realtype);
+ }
+
+ return 0;
+}
+
+static int verify_passno(struct verify_context *vfy)
+{
+ int passno = mnt_fs_get_passno(vfy->fs);
+ const char *tgt = mnt_fs_get_target(vfy->fs);
+
+ if (tgt && strcmp("/", tgt) == 0 && passno != 1)
+ return verify_warn(vfy, _("recommended root FS passno is 1 (current %d)"), passno);
+
+ return 0;
+}
+
static int verify_filesystem(struct verify_context *vfy)
{
int rc = 0;
@@ -272,8 +458,13 @@ static int verify_filesystem(struct verify_context *vfy)
if (!rc)
rc = verify_options(vfy);
}
+
if (!rc)
rc = verify_source(vfy);
+ if (!rc)
+ rc = verify_fstype(vfy);
+ if (!rc)
+ rc = verify_passno(vfy);
return rc;
}
@@ -284,6 +475,7 @@ int verify_table(struct libmnt_table *tb)
struct libmnt_iter *itr = NULL;
int rc = 0; /* overall return code (alloc errors, etc.) */
int check_order = is_listall_mode();
+ static int has_read_fs = 0;
itr = mnt_new_iter(MNT_ITER_FORWARD);
if (!itr) {
@@ -293,6 +485,12 @@ int verify_table(struct libmnt_table *tb)
vfy.tb = tb;
+ if (has_read_fs == 0) {
+ read_proc_filesystems(&vfy);
+ read_kernel_filesystems(&vfy);
+ has_read_fs = 1;
+ }
+
while (rc == 0 && (vfy.fs = get_next_fs(tb, itr))) {
vfy.target_printed = 0;
if (check_order)