Linux 解决方案
首先,您需要找到挂载目录的文件系统。
除非你想通过路径解析,你可以使用来自the statfs() call的文件系统ID:
概要
#include <sys/vfs.h> /* or <sys/statfs.h> */
int statfs(const char *path, struct statfs *buf);
int fstatfs(int fd, struct statfs *buf);
描述
statfs() 系统调用返回有关已挂载的信息
文件系统。 path 是挂载中任何文件的路径名
文件系统。 buf 是一个指向已定义的 statfs 结构的指针
大致如下:
struct statfs {
__fsword_t f_type; /* Type of filesystem (see below) */
__fsword_t f_bsize; /* Optimal transfer block size */
fsblkcnt_t f_blocks; /* Total data blocks in filesystem */
fsblkcnt_t f_bfree; /* Free blocks in filesystem */
fsblkcnt_t f_bavail; /* Free blocks available to
unprivileged user */
fsfilcnt_t f_files; /* Total file nodes in filesystem */
fsfilcnt_t f_ffree; /* Free file nodes in filesystem */
fsid_t f_fsid; /* Filesystem ID */
__fsword_t f_namelen; /* Maximum length of filenames */
__fsword_t f_frsize; /* Fragment size (since Linux 2.6) */
__fsword_t f_flags; /* Mount flags of filesystem
(since Linux 2.6.36) */
__fsword_t f_spare[xxx];
/* Padding bytes reserved for future use */
};
f_type 中可能出现以下文件系统类型:
...
这可能足以满足您的目的 - f_type 中的数据可能足以通知您该文件位于本地或远程磁盘上(只要您忽略了NFS 挂载从本地计算机导出的本地文件系统,以及下面提到的其他问题。)
对于更便携的解决方案,您可以使用POSIX-standardized available-on-Linux statvfs() call 作为给定路径的文件系统 ID:
概要
#include <sys/statvfs.h>
int statvfs(const char *path, struct statvfs *buf);
int fstatvfs(int fd, struct statvfs *buf);
描述
函数statvfs() 返回有关已挂载的信息
文件系统。 path 是挂载的任何文件的路径名
文件系统。 buf 是指向已定义的statvfs 结构的指针
大致如下:
struct statvfs {
unsigned long f_bsize; /* Filesystem block size */
unsigned long f_frsize; /* Fragment size */
fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */
fsblkcnt_t f_bfree; /* Number of free blocks */
fsblkcnt_t f_bavail; /* Number of free blocks for
unprivileged users */
fsfilcnt_t f_files; /* Number of inodes */
fsfilcnt_t f_ffree; /* Number of free inodes */
fsfilcnt_t f_favail; /* Number of free inodes for
unprivileged users */
unsigned long f_fsid; /* Filesystem ID */
unsigned long f_flag; /* Mount flags */
unsigned long f_namemax; /* Maximum filename length */
};
一旦您获得目录的f_fsid 值,您需要找到该文件系统的挂载点。
Linux provides getmntent() et al for this purpose:
概要
#include <stdio.h>
#include <mntent.h>
FILE *setmntent(const char *filename, const char *type);
struct mntent *getmntent(FILE *stream);
int addmntent(FILE *stream, const struct mntent *mnt);
int endmntent(FILE *streamp);
char *hasmntopt(const struct mntent *mnt, const char *opt);
/* GNU extension */
#include <mntent.h>
struct mntent *getmntent_r(FILE *streamp, struct mntent *mntbuf,
char *buf, int buflen);
glibc 的功能测试宏要求(请参阅
feature_test_macros(7)):
getmntent_r():
Since glibc 2.19:
_DEFAULT_SOURCE
Glibc 2.19 and earlier:
_BSD_SOURCE || _SVID_SOURCE
描述
这些例程用于访问文件系统描述文件
/etc/fstab 和挂载的文件系统描述文件/etc/mtab。
setmntent()函数打开文件系统描述文件
文件名并返回一个可以被getmntent() 使用的文件指针。
参数类型是所需的访问类型,可以采用
与fopen(3) 的模式参数相同的值。返回的流
应使用endmntent() 而不是fclose(3) 关闭。
getmntent() 函数读取文件系统的下一行
来自流的描述文件并返回指向结构的指针
包含文件中某一行的细分字段。这
指针指向被覆盖的内存的静态区域
随后调用getmntent()。
addmntent() 函数将mntent 结构mnt 添加到
结束
开放的流。
endmntent() 函数关闭与
文件系统描述文件。
hasmntopt() 函数扫描
mntent 结构 mnt 用于匹配 opt 的子字符串。看
<mntent.h> 和 mount(8) 获取有效的挂载选项。
可重入getmntent_r()函数类似于getmntent(),
但
将struct mount 存储在提供的*mntbuf 中并存储
提供的该结构中的条目所指向的字符串
数组buf,大小为buflen。
mntent结构在中定义如下:
struct mntent {
char *mnt_fsname; /* name of mounted filesystem */
char *mnt_dir; /* filesystem path prefix */
char *mnt_type; /* mount type (see mntent.h) */
char *mnt_opts; /* mount options (see mntent.h) */
int mnt_freq; /* dump frequency in days */
int mnt_passno; /* pass number on parallel fsck */
};
有关一些代码示例,请参阅Linux function to get mount points。
在您的情况下,您将在 struct mntent 的 mnt_dir 字段中保存的路径上调用 statfs() 或 statvfs() 并获取该文件系统的文件系统 ID,并且当它与您的文件系统 ID 匹配时目录,您将拥有挂载点 - 以及文件系统的所有详细信息。
您还可以解析文件路径并在从getmntent() 返回的已挂载文件系统中找到与您的目录的规范路径匹配的最长mnt_dir。但在这种情况下,您需要处理跨越文件系统边界的软链接。而且我不确定是否仍然严格禁止指向目录的硬链接 - 如果没有,使用路径名永远无法确定。
关于回送设备的注意事项
loopback device 是一种将文件挂载为文件系统的方法。您必须决定是否将安装在环回设备上的文件或目录视为本地文件,或者是否将其追溯到用作环回文件系统的实际文件并使用它来确定您的原始目录是否是本地或远程。
关于 bind 挂载的注意事项
Linux 提供了执行bind mounts 的功能,其中一个目录可以“挂载”到另一个位置。这是另一种情况,您必须决定是否需要通过挂载回溯以确定您的原始目录是本地目录还是远程目录。