如何从标准FILE结构中获取文件名?

0x6*_*C74 1 c

我想要的是:

 void printFname(FILE * f)
    {    
        char buf[255];
        MagicFunction(f,buf);
        printf("File name: %s",buf);
    }
Run Code Online (Sandbox Code Playgroud)

所以,我需要的只是"MagicFunction",但不幸的是我没有找到这样的 ......

有没有办法使用OS库实现?(windows.h,cocoa.h,posix.h等)

Bri*_*ell 8

没有这样的功能.可能没有文件名,或者多个文件名对应的文件名FILE *.在Unix上,程序可以在重命名或删除文件后继续引用文件,这可能意味着您FILE *没有名称.或者可以对文件进行更多硬链接,这意味着文件可以有多个名称; 你会选哪一个?为了进一步混淆事物,可以通过在包含该文件的目录上安装文件系统来临时隐藏文件.该文件仍将位于磁盘上,位于其原始路径名,但该路径上的文件将无法访问,因为该装置会遮挡它.

它也可能FILE *根本不对应于文件系统上的文件; 虽然它们通常会这样做,但您可以使用任何文件描述符创建一个fdopen(),并且该文件描述符可以是管道,套接字或其他从未在磁盘上有路径的类文件对象.在C库的某些版本中,您可以打开字符串流(例如,fmemopen()在glibc中),因此FILE *实际上只对应于内存缓冲区.

如果您关心名称,最好只是跟踪打开文件时的名称.

有一些hacky方法来近似获取文件名; 如果你只是将它用于调试或信息目的,那么它们就足够了.其中大部分都需要对文件描述符进行操作而不是文件描述符FILE *,因为文件描述符是引用文件的低级方式.为了得到文件描述符,运行fileno()FILE *,并记得检查是否有错误的情况下,存在一个与该关联的文件描述符FILE *.

在Linux上,您可以readlink()在文件描述符的"/proc/self/fd/fileno"哪个fileno位置进行操作.这将显示文件打开时文件的文件名,或者表示其他类型的文件描述符的字符串,如套接字或inotify句柄.FreeBSD和NetBSD都有Linux仿真层,包括仿真Linux风格的procfs; 如果您安装与Linux兼容的procfs,您可以在这些上执行此操作,但我没有可用于测试.

在Mac OS X上,你没有/proc/self/fd.如果您不关心查找原始文件名,但引用该文件的其他文件名将起作用(这样您可以将其传递给另一个程序),您可以构造一个:/.vol/deviceid/inode.例如,/.vol/234881030/281363.要获得这些值,运行fstat()文件描述符,并使用st_devst_ino对所得到的struct stat.

在Windows上,文件和文件系统的工作方式与Unix完全不同.显然,可以在Windows上将文件映射回其名称.从Windows Vista开始,您只需拨打电话即可GetFinalPathNameByHandle().这需要一个HANDLE; 获得HANDLE从文件描述符,调用_get_osfhandle().在Windows Vista之前,您需要做更多的工作,如本文所述.请注意,在Windows fileno()上命名_fileno(),但前者可能会发出警告.

进一步深入到hacky领域,还有一些你可以使用的技术.您可以使用shell lsof,或者可以提取它用于解析路径名的代码.lsof实际上直接在内核内存中查找,从内核的名称缓存中提取信息.这样做有几个局限性,列出lsof常见问题.当然,您需要root或同等权限才能直接或使用suid/sgid二进制文件执行此操作.

最后,对于查找与打开文件匹配的一个或多个文件名的便携但缓慢的解决方案,您可以在文件描述符上找到设备和inode编号fstat(),然后以递归方式遍历stat()每个文件的文件系统,直到找到包含匹配设备和inode号.记住我上面提到的警告; 您可能找不到匹配的文件,多个匹配的文件,即使您找不到任何匹配的文件,该文件仍可能存在,但由挂载点隐藏.当然,可能存在竞争条件; 某些东西可能会重命名文件,以至于在遍历层次结构时您永远不会看到它.