无竞赛目录步行(C)

无竞赛目录步行(C),第1张

概述我需要走一个目录树并获取每个文件的stat值.我想在修改文件系统时安全地执行此 *** 作. 在Python中,最好的选项是os.fwalk,它允许访问被遍历目录的fd;然后我可以使用dir_fd(fstatat)os.stat并获取当前的stat值.这是可以在Linux上进行的无竞争(如果正在修改此目录的内容,我可能需要重新扫描它).在C中,有nftw,它是类似地实现的,而fts,在glibc中使用pl 我需要走一个目录树并获取每个文件的stat值.我想在修改文件系统时安全地执行此 *** 作.

在Python中,最好的选项是os.fwalk,它允许访问被遍历目录的fd;然后我可以使用dir_fd(fstatat)os.stat并获取当前的stat值.这是可以在linux上进行的无竞争(如果正在修改此目录的内容,我可能需要重新扫描它).在C中,有nftw,它是类似地实现的,而fts,在glibc中使用plain(l)stat,因此是racy(它通过改变目录来减少竞争窗口,这是不方便的).

C有一个新的filesystem API graduated from boost,它缓存了stat值但是doesn’t expose them(我需要访问st_dev).这不仅仅是一个头库,所以我无法解决这个问题.

我错过了一个不错的C选项,它使用fstatat并且不受Boost理想的不暴露特定于平台的调用的约束?或者是我最好的选择包裹nftw(甚至找到)?

解决方法 事实证明它很容易实现.

我从干项目中使用了libposix.

#include <posix++.h>class Walker {public:    voID walk(posix::directory dir) {        dir.for_each([this,dir](auto& dirent) {            if (dirent.name == "." or dirent.name == "..")                    return;            if (!handle_dirent(dirent))                return;            struct stat stat;            if (dirent.type == DT_DIR || dirent.type == DT_UNKNowN) {                int fd = openat(                    dir.fd(),dirent.name.c_str(),O_DIRECTORY|O_nofollow|O_NOATIME);                if (fd < 0) {                    // ELOOP when O_nofollow is used on a symlink                    if (errno == ENOTDIR || errno == ELOOP)                        goto enotdir;                    if (errno == ENOENT)                        goto enoent;                    posix::throw_error(                        "openat","%d,\"%s\"",dir.fd(),dirent.name);                }                posix::directory dir1(fd);                fstat(fd,&stat);                if (handle_directory(dirent,fd,stat))                    walk(dir1);                close(fd);                return;            }enotdir:            try {                dir.stat(dirent.name.c_str(),stat,AT_SYMlink_nofollow);            } catch (const posix::runtime_error &error) {                if (error.number() == ENOENT)                    goto enoent;                throw;            }            handle_file(dirent,stat);            return;enoent:            handle_missing(dirent);        });    }protected:    /* return value: whether to stat */    virtual bool handle_dirent(const posix::directory::entry&) { return true; }    /* return value: whether to recurse     * stat will refer to a directory,dirent info may be obsolete */    virtual bool handle_directory(            const posix::directory::entry &dirent,const int fd,const struct stat&) { return true; }    /* stat might refer to a directory in case of a race;     * it still won't be recursed into.  dirent may be obsolete. */    virtual voID handle_file(            const posix::directory::entry &dirent,const struct stat&) {}    /* in case of a race */    virtual voID handle_missing(            const posix::directory::entry &dirent) {}};

性能与GNU find相同(当与基类进行比较时,使用-size $RANDOM来抑制输出并强制查找统计所有文件,而不仅仅是DT_DIR候选者).

总结

以上是内存溢出为你收集整理的无竞赛目录步行(C)全部内容,希望文章能够帮你解决无竞赛目录步行(C)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1227845.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存