Reputation: 55
I need to get a C-string, which contains fs name. There are a lot of commands to print fs name in terminal, but I can not find easy way to get it in C/C++ code.
Upvotes: 3
Views: 3359
Reputation: 4781
Linux C API has statfs()
(inspired by BSD, for other unix like OS have look into stat
from coreutils).
#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;
}
Example:
# 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
Upvotes: 4
Reputation: 39316
You parse /proc/mounts
.
If you have used one of the stat() family of functions, and have a filesystem identifier (st_dev
) in numerical form, you simply stat()
the mounted directory at each mount point listed in /proc/mounts
(append /./
to each mount point, so that you stat the mounted directory, and not the mount point in its parent filesystem), until you see one that matches. Using that entry (line) you obtain the type of the filesystem, as the kernel sees it.
Remember that /proc/
and /sys/
in Linux systems are not on disk, but are the proper interface for the kernel to expose certain details. Currently mounted filesystems (in /proc/mounts
) is one of these.
In posixc, this is very simple to implement using fopen()
, getline()
, fclose()
, free()
, and strtok()
or sscanf()
or your own line-splitting function. Remember that as a kernel interface, the contents of the files in /proc/
and /sys/
are never localized; they are always in the default C/POSIX locale.
Upvotes: 2