]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: add filesystem database
authorIago López Galeiras <iagol@microsoft.com>
Mon, 8 Feb 2021 18:54:24 +0000 (19:54 +0100)
committerIago Lopez Galeiras <iagol@microsoft.com>
Wed, 6 Oct 2021 08:52:10 +0000 (10:52 +0200)
Stores filesystem_name -> magic_number(s).

src/basic/check-filesystems.sh [new file with mode: 0755]
src/basic/filesystems-gperf.gperf [new file with mode: 0644]
src/basic/filesystems.c [new file with mode: 0644]
src/basic/filesystems.h [new file with mode: 0644]
src/basic/generate-filesystem-list.py [new file with mode: 0755]
src/basic/meson.build

diff --git a/src/basic/check-filesystems.sh b/src/basic/check-filesystems.sh
new file mode 100755 (executable)
index 0000000..0265746
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eu
+set -o pipefail
+
+cpp="$1"
+filesystems_gperf="$2"
+shift 2
+
+includes=""
+for i in "$@"; do
+    includes="$includes -include $i"
+done
+
+error=false
+
+# shellcheck disable=SC2086
+for fs in $($cpp -dM $includes - </dev/null | \
+            grep -E '_MAGIC' | \
+            grep -vE 'LINUX_MAGIC' | \
+            awk '/^#define[ \t]+[A-Z0-9_]+MAGIC[ \t]+/ { print $2; }'); do
+    if ! grep -E "\{.*$fs.*\}" "$filesystems_gperf" >/dev/null; then
+        # STACK_END_MAGIC doesn't refer to a filesystem
+        # mtd_inode was removed in 2015
+        # futexfs was removed in 2018
+        if [[ "$fs" =~ ^(STACK_END_MAGIC|MTD_INODE_FS_MAGIC|FUTEXFS_SUPER_MAGIC)$ ]]; then
+            continue
+        fi
+        echo "Filesystem found in kernel header but not in $(basename "$filesystems_gperf"): $fs";
+        error=true
+    fi
+done
+
+if $error; then
+    exit 1
+fi
diff --git a/src/basic/filesystems-gperf.gperf b/src/basic/filesystems-gperf.gperf
new file mode 100644 (file)
index 0000000..f31c9de
--- /dev/null
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+%{
+#include <linux/magic.h>
+
+#include "filesystems.h"
+#include "missing_magic.h"
+#include "stat-util.h"
+
+struct FilesystemMagic {
+        const char *name;
+        statfs_f_type_t magic[FILESYSTEM_MAGIC_MAX];
+};
+%}
+struct FilesystemMagic;
+%language=ANSI-C
+%define hash-function-name filesystems_gperf_hash
+%define lookup-function-name filesystems_gperf_lookup
+%define slot-name name
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+apparmorfs,      {AAFS_MAGIC}
+adfs,            {ADFS_SUPER_MAGIC}
+affs,            {AFFS_SUPER_MAGIC}
+afs,             {AFS_FS_MAGIC, AFS_SUPER_MAGIC}
+anon_inodefs,    {ANON_INODE_FS_MAGIC}
+autofs,          {AUTOFS_SUPER_MAGIC}
+balloon-kvm,     {BALLOON_KVM_MAGIC}
+bdev,            {BDEVFS_MAGIC}
+binder,          {BINDERFS_SUPER_MAGIC}
+binfmt_misc,     {BINFMTFS_MAGIC}
+bpf,             {BPF_FS_MAGIC}
+btrfs,           {BTRFS_SUPER_MAGIC}
+btrfs_test_fs,   {BTRFS_TEST_MAGIC}
+ceph,            {CEPH_SUPER_MAGIC}
+cgroup2,         {CGROUP2_SUPER_MAGIC}
+cgroup,          {CGROUP_SUPER_MAGIC}
+cifs,            {CIFS_MAGIC_NUMBER}
+coda,            {CODA_SUPER_MAGIC}
+configfs,        {CONFIGFS_MAGIC}
+cramfs,          {CRAMFS_MAGIC}
+dax,             {DAXFS_MAGIC}
+debugfs,         {DEBUGFS_MAGIC}
+devmem,          {DEVMEM_MAGIC}
+devpts,          {DEVPTS_SUPER_MAGIC}
+dmabuf,          {DMA_BUF_MAGIC}
+ecryptfs,        {ECRYPTFS_SUPER_MAGIC}
+efivarfs,        {EFIVARFS_MAGIC}
+efs,             {EFS_SUPER_MAGIC}
+erofs,           {EROFS_SUPER_MAGIC_V1}
+ext2,            {EXT2_SUPER_MAGIC}
+ext3,            {EXT3_SUPER_MAGIC}
+ext4,            {EXT4_SUPER_MAGIC}
+exfat,           {EXFAT_SUPER_MAGIC}
+f2fs,            {F2FS_SUPER_MAGIC}
+fuseblk,         {FUSE_SUPER_MAGIC}
+fuse,            {FUSE_SUPER_MAGIC}
+fusectl,         {FUSE_CTL_SUPER_MAGIC}
+gfs,             {GFS2_MAGIC}
+gfs2,            {GFS2_MAGIC}
+hostfs,          {HOSTFS_SUPER_MAGIC}
+hpfs,            {HPFS_SUPER_MAGIC}
+hugetlbfs,       {HUGETLBFS_MAGIC}
+iso9660,         {ISOFS_SUPER_MAGIC}
+jffs2,           {JFFS2_SUPER_MAGIC}
+minix,           {MINIX_SUPER_MAGIC, MINIX_SUPER_MAGIC2, MINIX2_SUPER_MAGIC, MINIX2_SUPER_MAGIC2, MINIX3_SUPER_MAGIC}
+mqueue,          {MQUEUE_MAGIC}
+msdos,           {MSDOS_SUPER_MAGIC}
+ncp,             {NCP_SUPER_MAGIC}
+ncpfs,           {NCP_SUPER_MAGIC}
+nfs,             {NFS_SUPER_MAGIC}
+nfs4,            {NFS_SUPER_MAGIC}
+nilfs2,          {NILFS_SUPER_MAGIC}
+nsfs,            {NSFS_MAGIC}
+ocfs2,           {OCFS2_SUPER_MAGIC}
+openpromfs,      {OPENPROM_SUPER_MAGIC}
+orangefs,        {ORANGEFS_DEVREQ_MAGIC}
+overlay,         {OVERLAYFS_SUPER_MAGIC}
+pipefs,          {PIPEFS_MAGIC}
+ppc-cmm,         {PPC_CMM_MAGIC}
+proc,            {PROC_SUPER_MAGIC}
+pstore,          {PSTOREFS_MAGIC}
+pvfs2,           {ORANGEFS_DEVREQ_MAGIC}
+qnx4,            {QNX4_SUPER_MAGIC}
+qnx6,            {QNX6_SUPER_MAGIC}
+ramfs,           {RAMFS_MAGIC}
+resctrl,         {RDTGROUP_SUPER_MAGIC}
+reiserfs,        {REISERFS_SUPER_MAGIC}
+secretmem,       {SECRETMEM_MAGIC}
+securityfs,      {SECURITYFS_MAGIC}
+selinuxfs,       {SELINUX_MAGIC}
+shiftfs,         {SHIFTFS_MAGIC}
+smackfs,         {SMACK_MAGIC}
+smb3,            {SMB_SUPER_MAGIC}
+smbfs,           {SMB_SUPER_MAGIC}
+sockfs,          {SOCKFS_MAGIC}
+squashfs,        {SQUASHFS_MAGIC}
+sysfs,           {SYSFS_MAGIC}
+tmpfs,           {TMPFS_MAGIC}
+tracefs,         {TRACEFS_MAGIC}
+udf,             {UDF_SUPER_MAGIC}
+usbdevfs,        {USBDEVICE_SUPER_MAGIC}
+vboxsf,          {VBOXSF_SUPER_MAGIC}
+vfat,            {MSDOS_SUPER_MAGIC}
+v9fs,            {V9FS_MAGIC}
+xenfs,           {XENFS_SUPER_MAGIC}
+xfs,             {XFS_SUPER_MAGIC}
+z3fold,          {Z3FOLD_MAGIC}
+zonefs,          {ZONEFS_MAGIC}
+zsmalloc,        {ZSMALLOC_MAGIC}
diff --git a/src/basic/filesystems.c b/src/basic/filesystems.c
new file mode 100644 (file)
index 0000000..9fccea2
--- /dev/null
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "filesystems-gperf.h"
+
+int fs_type_from_string(const char *name, const statfs_f_type_t **ret) {
+        const struct FilesystemMagic *fs_magic;
+
+        assert(name);
+        assert(ret);
+
+        fs_magic = filesystems_gperf_lookup(name, strlen(name));
+        if (!fs_magic)
+                return -EINVAL;
+
+        *ret = fs_magic->magic;
+
+        return 0;
+}
+
+int fs_in_group(const struct statfs *s, FilesystemGroups fs_group) {
+        const char *fs;
+        int r;
+
+        NULSTR_FOREACH(fs, filesystem_sets[fs_group].value) {
+                const statfs_f_type_t *magic;
+
+                r = fs_type_from_string(fs, &magic);
+                if (r == 0) {
+                        for (size_t i = 0; i < FILESYSTEM_MAGIC_MAX; i++) {
+                                if (magic[i] == 0)
+                                        break;
+
+                                if (is_fs_type(s, magic[i]))
+                                        return true;
+                        }
+                }
+        }
+
+        return false;
+}
+
+const FilesystemSet filesystem_sets[_FILESYSTEM_SET_MAX] = {
+        [FILESYSTEM_SET_BASIC_API] = {
+                .name = "@basic-api",
+                .help = "Basic filesystem API",
+                .value =
+                "cgroup\0"
+                "cgroup2\0"
+                "devpts\0"
+                "mqueue\0"
+                "proc\0"
+                "sysfs\0"
+        },
+        [FILESYSTEM_SET_AUXILIARY_API] = {
+                .name = "@auxiliary-api",
+                .help = "Auxiliary filesystem API",
+                .value =
+                "configfs\0"
+                "efivarfs\0"
+                "fusectl\0"
+                "hugetlbfs\0"
+                "securityfs\0"
+        },
+        [FILESYSTEM_SET_COMMON_BLOCK] = {
+                .name = "@common-block",
+                .help = "Common block device filesystems",
+                .value =
+                "btrfs\0"
+                "ext4\0"
+                "vfat\0"
+                "xfs\0"
+        },
+        [FILESYSTEM_SET_HISTORICAL_BLOCK] = {
+                .name = "@historical-block",
+                .help = "Historical block device filesystems",
+                .value =
+                "ext2\0"
+                "ext3\0"
+                "minix\0"
+        },
+        [FILESYSTEM_SET_NETWORK] = {
+                .name = "@network",
+                .help = "Well-known network filesystems",
+                .value =
+                "afs\0"
+                "cifs\0"
+                "gfs\0"
+                "gfs2\0"
+                "ncpfs\0"
+                "ncp\0"
+                "nfs\0"
+                "nfs4\0"
+                "ocfs2\0"
+                "pvfs2\0"
+                "smb3\0"
+                "smbfs\0"
+        },
+        [FILESYSTEM_SET_PRIVILEGED_API] = {
+                .name = "@privileged-api",
+                .help = "Privileged filesystem API",
+                .value =
+                "bpf\0"
+                "debugfs\0"
+                "pstore\0"
+                "tracefs\0"
+        },
+        [FILESYSTEM_SET_TEMPORARY] = {
+                .name = "@temporary",
+                .help = "Temporary filesystems",
+                .value =
+                "ramfs\0"
+                "tmpfs\0"
+        },
+        [FILESYSTEM_SET_KNOWN] = {
+                .name = "@known",
+                .help = "All known filesystems declared in the kernel",
+                .value =
+#include "filesystem-list.h"
+        },
+};
+
+const FilesystemSet *filesystem_set_find(const char *name) {
+        if (isempty(name) || name[0] != '@')
+                return NULL;
+
+        for (FilesystemGroups i = 0; i < _FILESYSTEM_SET_MAX; i++)
+                if (streq(filesystem_sets[i].name, name))
+                        return filesystem_sets + i;
+
+        return NULL;
+}
diff --git a/src/basic/filesystems.h b/src/basic/filesystems.h
new file mode 100644 (file)
index 0000000..a096447
--- /dev/null
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "nulstr-util.h"
+#include "stat-util.h"
+#include "string-util.h"
+
+#define FILESYSTEM_MAGIC_MAX 10
+
+typedef enum FilesystemGroups {
+        /* Please leave BASIC_API first and KNOWN last, but sort the rest alphabetically */
+        FILESYSTEM_SET_BASIC_API,
+        FILESYSTEM_SET_AUXILIARY_API,
+        FILESYSTEM_SET_COMMON_BLOCK,
+        FILESYSTEM_SET_HISTORICAL_BLOCK,
+        FILESYSTEM_SET_NETWORK,
+        FILESYSTEM_SET_PRIVILEGED_API,
+        FILESYSTEM_SET_TEMPORARY,
+        FILESYSTEM_SET_KNOWN,
+        _FILESYSTEM_SET_MAX,
+        _FILESYSTEM_SET_INVALID = -EINVAL,
+} FilesystemGroups;
+
+typedef struct FilesystemSet {
+        const char *name;
+        const char *help;
+        const char *value;
+} FilesystemSet;
+
+extern const FilesystemSet filesystem_sets[];
+
+const FilesystemSet *filesystem_set_find(const char *name);
+
+int fs_type_from_string(const char *name, const statfs_f_type_t **ret);
+int fs_in_group(const struct statfs *s, enum FilesystemGroups fs_group);
+
+/* gperf prototypes */
+const struct FilesystemMagic* filesystems_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
diff --git a/src/basic/generate-filesystem-list.py b/src/basic/generate-filesystem-list.py
new file mode 100755 (executable)
index 0000000..8271b3f
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import sys
+
+keywords_section = False
+
+for line in open(sys.argv[1]):
+    if keywords_section:
+        print('"{}\\0"'.format(line.split(',')[0].strip()))
+    elif line.startswith('%%'):
+        keywords_section = True
index ade45bdfc2da1b03477f4a17a074ce32030d9f20..4f172b48e93887baa93d6c637f6e8fd32fe4d6ef 100644 (file)
@@ -54,6 +54,8 @@ basic_sources = files('''
         fd-util.h
         fileio.c
         fileio.h
+        filesystems.c
+        filesystems.h
         format-util.c
         format-util.h
         fs-util.c