文件安装在哪里?

Joh*_*ica 22 c++ linux mount

给定文件或目录的路径,如何确定该文件的安装点?例如,如果/tmp作为tmpfs文件系统挂载,那么给定文件名/tmp/foo/bar我想知道它存储在以tmpfsroot为中/tmp.

这将是在C++中,我想避免通过调用外部命令system().代码应该是健壮的 - 不一定是针对故意篡改,但绝对面对嵌套的挂载点,符号链接等.

我无法找到一个简单的系统调用来执行此操作.看起来我必须自己写支票.这是我正在计划的大致轮廓.

  1. 将文件名规范化为readlinkshell命令.怎么样?
  2. 阅读/etc/mtabgetmntent()&CO.
  3. 确定文件的相应安装条目.怎么样?

对于#1是一个简单的系统调用还是我需要读取路径的每个目录组件并解决它们,readlink(2)如果它们是符号链接?处理...我自己?好像很痛苦.

对于#3,我对如何做到这一点有各种各样的想法.不确定哪个最好.

  1. open()文件,其父级,父级的父级等使用,openat(fd, "..")直到我到达其中一个/etc/mtab条目.(我怎么知道我什么时候做?fstat()并比较inode数字?)
  2. 在mount表中找到最长的目录名,它是我文件名的子字符串.

我倾向于第一个选项,但在我编码之前,我想确保我不会忽略任何东西 - 理想情况下,内置函数已经完成了!

Joh*_*ica 18

这就是我想出来的.事实证明,通常不需要遍历父目录.您所要做的就是获取文件的设备编号,然后找到具有相同设备编号的相应安装条目.

struct mntent *mountpoint(char *filename, struct mntent *mnt, char *buf, size_t buflen)
{
    struct stat s;
    FILE *      fp;
    dev_t       dev;

    if (stat(filename, &s) != 0) {
        return NULL;
    }

    dev = s.st_dev;

    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
        return NULL;
    }

    while (getmntent_r(fp, mnt, buf, buflen)) {
        if (stat(mnt->mnt_dir, &s) != 0) {
            continue;
        }

        if (s.st_dev == dev) {
            endmntent(fp);
            return mnt;
        }
    }

    endmntent(fp);

    // Should never reach here.
    errno = EINVAL;
    return NULL;
}
Run Code Online (Sandbox Code Playgroud)

感谢@RichardPennington提出的建议realpath(),以及比较设备编号而不是inode编号.

  • 这甚至应该适用于设备专用文件,而不需要最后的特殊情况(`stat.st_dev`*总是*包含该文件的设备的ID,即使对于设备专用文件也是如此). (2认同)