如何使用readdir_r遍历目录树时跳过已挂载的文件

时间:2014-01-26 12:28:21

标签: c mount readdir

我正在编写一个递归删除目录树中所有文件和子目录的函数,这个函数将在多线程环境中使用,所以我希望opendir / readdir_r比{{{ 1}}(代码适用于Linux / Mac OSX / Solaris,而nftw在某些平台上不是线程安全的。)

由于该功能正在删除文件,因此安全性非常重要。如果有指向敏感位置的链接(例如,nftw系统目录),我不希望我的函数尝试删除该目录下的文件。对于符号/硬链接文件,/usr/lib然后lstat将完成这项工作。但是,如果有一个挂载点,S_ISLNK只会返回true。

也许S_ISDIR / setmntent会有所帮助,但我在Linux上的实验发现它无法处理以下情况:

  1. mount //192.168.0.1/share at~/ work / share(需要root权限)
  2. mv~ / work / tmp / work(不需要root权限)
  3. 现在getmntent仍然报告〜/ work / share作为挂载点
  4. 我想要的是getmntent的{​​{1}}标志:

    FTW_MOUNT

    我不确定来自nftw的{​​{1}}字段对此是否有用,我不知道开发号码是否总是超出挂载点。

    man nftw: ... FTW_MOUNT If set, stay within the same file system. 有没有办法找出装点?

    谢谢!

1 个答案:

答案 0 :(得分:1)

来自Single Unix Specification - Issue 7

  

3.228挂载点

     

系统根目录或 st_dev 字段的目录   结构 stat 与其父目录的结构不同。

     

注意:    stat 结构在<sys/stat.h>

中详细定义

换句话说,是的,您可以依靠设备ID来确定您是否处于挂载点。了解挂载点的关键在于理解如果/ usr与/在同一文件系统中,您将永远不会键入 mount device / usr

/ home,/ tmp,/ usr和/ usr / src都在不同设备上的简单示例:

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <sys/stat.h>

int main(int argc, char *argv[])
{
    struct stat stbuf;

    if (stat(".", &stbuf) == -1) {
        perror("couldn't get working directory");
        return 1;
    }

    printf("Device ID for directory .: %lX\n", stbuf.st_dev);

    /* Loop through the command line arguments. */
    while (*++argv) {
        if (stat(*argv, &stbuf) == -1) {
            fprintf(stderr, "error: couldn't get device ID for directory '%s': %s\n", *argv, strerror(error));
            continue;
        }

        printf("Device ID for directory %s: %lX\n", *argv, stbuf.st_dev);
    }

    return 0;
}

示例运行:

sh$ ./a.out /usr ~/misc\ files /nonexistent/path /usr/src /tmp
Device ID for directory .: 807
Device ID for directory /usr: 803
Device ID for directory /home/kit/misc files: 807
error: couldn't get device ID for directory '/nonexistent/path': No such file or directory
Device ID for directory /usr/src: 805
Device ID for directory /tmp: 802