如何使用 Linux API for C 确定文件系统类型(名称)?

问题描述 投票:0回答:2

我需要获取一个 C 字符串,其中包含 fs 名称。 有很多命令可以在终端中打印 fs 名称,但我找不到在 C/C++ 代码中获取它的简单方法。

c++ c linux system-calls
2个回答
2
投票

Linux C API 具有

statfs()
(受 BSD 启发,对于其他类似 UNIX 的操作系统,请查看 coreutils 中的
stat
)。

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/vfs.h>

/*
 * https://github.com/linux-test-project/ltp/tree/master/include/tst_fs.h
 * mostly man 2 statfs or kernel-source/include/linux/magic.h
 */

/* kernel-source/fs/bcachefs/bcachefs_format.h */
#define TST_BCACHE_MAGIC   0xca451a4e
#define TST_BTRFS_MAGIC    0x9123683E
#define TST_NFS_MAGIC      0x6969
#define TST_RAMFS_MAGIC    0x858458f6
#define TST_TMPFS_MAGIC    0x01021994
#define TST_V9FS_MAGIC     0x01021997
#define TST_XFS_MAGIC      0x58465342
#define TST_EXT2_OLD_MAGIC 0xEF51
/* ext2, ext3, ext4 have the same magic number */
#define TST_EXT234_MAGIC   0xEF53
#define TST_MINIX_MAGIC    0x137F
#define TST_MINIX_MAGIC2   0x138F
#define TST_MINIX2_MAGIC   0x2468
#define TST_MINIX2_MAGIC2  0x2478
#define TST_MINIX3_MAGIC   0x4D5A
#define TST_UDF_MAGIC      0x15013346
#define TST_SYSV2_MAGIC    0x012FF7B6
#define TST_SYSV4_MAGIC    0x012FF7B5
#define TST_UFS_MAGIC      0x00011954
#define TST_UFS2_MAGIC     0x19540119
#define TST_F2FS_MAGIC     0xF2F52010
#define TST_NILFS_MAGIC    0x3434
#define TST_EXOFS_MAGIC    0x5DF5
#define TST_OVERLAYFS_MAGIC 0x794c7630
#define TST_FUSE_MAGIC     0x65735546

/* https://github.com/linux-test-project/ltp/tree/master/lib/tst_fs_type.c */
const char *tst_fs_type_name(long f_type) {
    switch (f_type) {
    case TST_TMPFS_MAGIC:
        return "tmpfs";
    case TST_NFS_MAGIC:
        return "nfs";
    case TST_V9FS_MAGIC:
        return "9p";
    case TST_RAMFS_MAGIC:
        return "ramfs";
    case TST_BCACHE_MAGIC:
        return "bcachefs";
    case TST_BTRFS_MAGIC:
        return "btrfs";
    case TST_XFS_MAGIC:
        return "xfs";
    case TST_EXT2_OLD_MAGIC:
        return "ext2";
    case TST_EXT234_MAGIC:
        return "ext2/ext3/ext4";
    case TST_MINIX_MAGIC:
    case TST_MINIX_MAGIC2:
    case TST_MINIX2_MAGIC:
    case TST_MINIX2_MAGIC2:
    case TST_MINIX3_MAGIC:
        return "minix";
    case TST_UDF_MAGIC:
        return "udf";
    case TST_SYSV2_MAGIC:
    case TST_SYSV4_MAGIC:
        return "sysv";
    case TST_UFS_MAGIC:
    case TST_UFS2_MAGIC:
        return "ufs";
    case TST_F2FS_MAGIC:
        return "f2fs";
    case TST_NILFS_MAGIC:
        return "nilfs";
    case TST_EXOFS_MAGIC:
        return "exofs";
    case TST_OVERLAYFS_MAGIC:
        return "overlayfs";
    case TST_FUSE_MAGIC:
        return "fuse";
    default:
        return "unknown";
    }
}

void print_filesystem(const char* path) {
    if (path == NULL)
        return;

    struct statfs s;

    if (statfs(path, &s)) {
        fprintf(stderr, "statfs(%s) failed: %s\n", path, strerror(errno));
        return;
    }

    printf("'%s' filesystem: %s\n", path, tst_fs_type_name(s.f_type));
}

int main(int argc, char *argv[]) {
    print_filesystem("/");
    print_filesystem("/tmp");
    print_filesystem("/tmp/foo");

    return 0;
}

示例:

# create bcachefs on loop
$ dd if=/dev/zero of=test_file bs=100M count=1
$ mkdir /tmp/foo
$ mkfs.bcachefs test_file
# mount -o loop test_file /tmp/foo

$ gcc -Wall filesystem.c -o filesystem && ./filesystem
'/' filesystem: ext2/ext3/ext4
'/tmp' filesystem: tmpfs
'/tmp/foo' filesystem: bcachefs

1
投票

你解析

/proc/mounts

如果您使用了 stat() 系列函数之一,并且具有数字形式的文件系统标识符 (

st_dev
),则只需
stat()
/proc/mounts
中列出的每个挂载点处的挂载目录(附加
/./
到每个挂载点,以便您统计挂载的目录,而不是其父文件系统中的挂载点),直到看到匹配的目录。使用该条目(行)您可以获得文件系统的类型,正如内核所看到的那样。

请记住,Linux 系统中的

/proc/
/sys/
不在磁盘上,而是内核公开某些细节的正确接口。当前安装的文件系统(在
/proc/mounts
中)就是其中之一。

中,使用

fopen()
getline()
fclose()
free()
strtok()
sscanf()
或您自己的线分割函数来实现非常简单。请记住,作为内核接口,
/proc/
/sys/
中的文件内容永远不会本地化;它们始终位于默认的 C/POSIX 语言环境中。

© www.soinside.com 2019 - 2024. All rights reserved.