侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 239 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

ftw函数用法详解

noerror
2022-10-04 / 0 评论 / 0 点赞 / 156 阅读 / 2,191 字 / 正在检测是否收录...

ftw函数用法详解

ftw函数简介

  • 头文件包含
#include <ftw.h>
#include <ftw.h>
  • 函数定义
int nftw(const char * dirpath ,
        int (* fn ) (const char * fpath , const struct stat * sb ,
                   int  typeflag , struct FTW * ftwbuf ),
        int  nopenfd , int  flags );
int ftw(const char * dirpath ,
        int (* fn ) (const char * fpath , const struct stat * sb ,
                   int  typeflag ),
        int  nopenfd );

ftw函数常见使用错误

  • 编译错误
    warning: implicit declaration of function ‘ftw’ [-Wimplicit-function-declaration]
    解决办法:包含头文件
#include <ftw.h>
#include <ftw.h>

ftw函数详细描述

nftw ()遍历位于目录dirpath下的目录树,并对树中的每个条目调用一次fn()。默认情况下,在目录包含的文件和子目录之前处理目录(预序遍历)。
为了避免用完调用进程的所有文件描述符,nopenfd指定nftw ()同时打开的最大目录数。当搜索深度超过这个时,nftw ()将变得更慢,因为目录必须关闭和重新打开。nftw ()对目录树中的每个级别最多使用一个文件描述符。
对于在树中找到的每个条目,nftw ()用四个参数调用fpath 3():fpath sb typeflag 和ftwbuf fpath是条目的路径名,如果dirpath表示为相对路径名,则表示为在调用nftw ()时相对于调用进程当前工作目录的路径名;如果dirpath表示为绝对路径名,则表示为绝对路径名。sb是对fpath 调用stat (2)返回的stat结构的指针
传递给fn ()的typeflag参数是一个整数,它具有以下值之一:

  • FTW_F fpath是一个常规文件。
  • FTW_D fpath是一个目录。
  • FTW_DNR fpath是一个不能读取的目录。
  • FTW_DP fpath是一个目录,FTW_DEPTH是在pflags中指定的。(如果flags 中没有指定 FTW_DEPTH ,那么将始终访问目录,将typeflag设置为FTW_D ),所有fpath中的文件和子目录都已处理。
  • FTW_NS 在不是符号链接的fpath 上的stat (2)调用失败。可能的原因是调用方对父目录具有读取权限,因此可以看到文件名fpath,但没有执行权限,因此无法访问stat (2)。sb指向的缓冲区内容未定义。
  • FTW_SL fpath是符号链接,FTW_PHYS是在pflags中设置的。
  • FTW_SLN fpath是指向不存在文件的符号链接。(只有在未设置FTW_PHYS的情况下才会发生这种情况。)在本例中,传递给fn ()的sb参数包含通过对“悬空”符号链接执行lstat (2)而返回的信息。(但请参阅bugs。)

nftw ()在调用fn()时提供的第四个参数。ri(ftwbuf)是指向pFTW类型结构的指针:

struct FTW {
   int base;
   int level;
};

base是fpath 中给出的路径名中的文件名(即basename组件)的偏移量level是fpath在目录树中相对于树的根的深度。ri(dirpath,其深度为0)。
为了停止树遍历,fn()返回一个非零值;只要PPPP3()返回0,这个值就会变成nftw ()的返回值,nftw ()将继续下去,直到它遍历了整个树,在这种情况下它将返回零,或者直到它遇到错误(如malloc (3)失败),在这种情况下它将返回-1。
因为nftw ()使用动态数据结构,所以退出树遍历的唯一安全方法是从fn()返回一个非零值。为了允许一个信号终止遍历而不会导致内存泄漏,让处理程序设置一个由PPPP2()检查的全局标志。Don't使用longjmp (3),除非程序要终止。
nftw ()的flags参数由以下零个或多个标志组成:

  • 如果设置了这个特定于glibc的标志,那么nftw ()将以不同的方式处理来自fn ()的返回值。fn ()应该返回以下值之一:.rs
  • FTW_CONTINUE 指示nftw ()正常继续。
  • 如果fn()返回此值,则将跳过当前项的兄弟姐妹,并在父项中继续处理。
  • 如果fn()被调用的条目是一个目录(typeflag是FTW_D),这个返回值将防止该目录中的对象作为参数传递给PPPP2()。nftw ()继续处理该目录的下一个同级目录。
  • FTW_STOP 使nftw ()立即返回,返回值为pFTW_STOP。

其他返回值可以与未来的新操作相关联;fn()不应返回上面列出的值以外的值。
为了从获得FTW_ACTIONRETVAL的定义,必须定义特性测试宏 _GNU_SOURCE (在包含any头文件之前)。.Re

  • 如果设置了 FTW_CHDIR ,则在处理每个目录的内容之前对其执行chdir (2)。如果程序需要在fpath所在的目录中执行某些操作,这将非常有用。(指定此标志对在fn )的fpath参数中传递的路径名没有影响)
  • 如果设置了 FTW_DEPTH ,则执行后序遍历,即为目录本身调用fn(),处理目录及其子目录的内容。(默认情况下,每个目录都处理before其内容。)
  • 如果设置了 FTW_MOUNT ,则保持在相同的文件系统中(即,不要跨越挂载点)。
  • 如果设置了 FTW_PHYS ,则不要遵循符号链接。(这就是你想要的。)如果未设置,则会遵循符号链接,但不会报告两次文件。.ip如果没有设置FTW_PHYS,而是设置了FTW_DEPTH,那么函数fn ()将永远不会被调用给它自己的子代目录。ftw() ftw ()是一个较老的函数,它提供了nftw ()功能的一个子集,显著的区别如下:
  • ftw ()没有flags参数。它的行为与调用nftw ()时的行为相同,flags指定为零。
  • 回调函数fn ()没有提供第四个参数。
  • 通过提供给fn ()的typeflag参数传递的值范围较小:只有FTW_F 、FTW_D 、FTW_DNR 、FTW_NS 和(可能)FTW_SL

ftw函数返回值

这些函数在成功时返回0,在发生错误时返回-1。
如果fn()返回非零,则终止树遍历,并将ppp2()返回的值作为ftw ()或nftw ()的结果返回
如果使用FTW_ACTIONRETVAL标志调用nftw (),那么fn()终止树遍历时应该使用的唯一非零值是FTW_STOP,该值将作为nftw ()的结果返回

ftw函数其他说明

POSIX.1-2008注意到,如果fn不保留当前工作目录,结果是未指定的。
在susv1中介绍了nftw ()函数以及FTW_SL与ftw ()的使用。
在一些实现中(例如,glibc),ftw ()将永远不会使用FTW_SL,在其他系统中,ppp6只用于不指向现有文件的符号链接,在其他系统中,ftw ()将对每个符号链接使用ppp6。如果fpath是一个符号链接,并且stat (2)失败,POSIX.1-2008声明在typeflag 中传递FTW_NS或FTW_SL以获得可预测的结果是未定义的,则使用nftw ()

ftw函数使用举例

下面的程序遍历第一个命令行参数中命名的路径下的目录树,如果没有提供参数,则遍历当前目录下的目录树。它显示关于每个文件的各种信息。第二个命令行参数可用于指定字符,这些字符在调用nftw () Program source时控制分配给flags参数的值&

#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

static int
display_info(const char *fpath, const struct stat *sb,
            int tflag, struct FTW *ftwbuf)
{
   printf("%\-3s %2d ",
           (tflag == FTW_D) ?   "d"   : (tflag == FTW_DNR) ? "dnr" :
           (tflag == FTW_DP) ?  "dp"  : (tflag == FTW_F) ?   "f" :
           (tflag == FTW_NS) ?  "ns"  : (tflag == FTW_SL) ?  "sl" :
           (tflag == FTW_SLN) ? "sln" : "???",
           ftwbuf\->level);

   if (tflag == FTW_NS)
       printf("\-\-\-\-\-\-\-");
   else
       printf("%7jd", (intmax_t) sb\->st_size);

   printf("   %\-40s %d %s\en",
           fpath, ftwbuf\->base, fpath + ftwbuf\->base);

   return 0;           /* To tell nftw() to continue */
}

int
main(int argc, char *argv[])
{
   int flags = 0;

   if (argc > 2 && strchr(argv[2], \(aqd\(aq) != NULL)
       flags |= FTW_DEPTH;
   if (argc > 2 && strchr(argv[2], \(aqp\(aq) != NULL)
       flags |= FTW_PHYS;

   if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags)
           == \-1) {
       perror("nftw");
       exit(EXIT_FAILURE);
   }

   exit(EXIT_SUCCESS);
}
0

评论区