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

时间:2012-12-05 03:21:25

标签: c

我想要的是什么:

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

所以,我需要的只是“MagicFunction”,但是unfortunatelly I haven't found such ......

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

4 个答案:

答案 0 :(得分:8)

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

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

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

有一些hacky方法可以近似获取文件名;如果您只是将其用于调试或信息目的,那么它们就足够了。其中大多数都需要对文件描述符而不是FILE *进行操作,因为文件描述符是引用文件的较低级别方式。要获取文件描述符,请在FILE *上运行fileno(),并记住在没有与FILE *关联的文件描述符的情况下检查错误。

在Linux上,您可以在readlink()"/proc/self/fd/fileno"执行fileno,其中/proc/self/fd是文件描述符。这将显示文件打开时文件的文件名,或者表示其他类型的文件描述符的字符串,如套接字或inotify句柄。 FreeBSD和NetBSD都有Linux仿真层,包括仿真Linux风格的procfs;如果你安装了兼容Linux的procfs,你可以对它们做这些,虽然我没有它们可用于测试。

在Mac OS X上,您没有/.vol/deviceid/inode。如果您不关心查找原始文件名,但引用该文件的其他文件名将起作用(这样您可以将其传递给另一个程序),您可以构建一个:/.vol/234881030/281363。例如,st_dev。要获取这些值,请在文件描述符上运行fstat(),并在生成的st_ino上使用struct statHANDLE

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

进一步深入到hacky领域,还有一些你可以使用的技术。你可以发送到lsof,或者你可以提取它用来解析路径名的代码。 fstat()实际上直接查看内核内存,从内核的名称缓存中提取信息。这有一些限制,在the lsof FAQ中列出。当然,您需要root或同等权限才能直接或使用suid / sgid二进制文件执行此操作。

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

答案 1 :(得分:2)

没有这样的标准功能。

答案 2 :(得分:0)

你自己fopen()吗?如果那时,自己将FILE *维护到文件名哈希表。

否则,一般情况下都不可能。

答案 3 :(得分:0)

我认为即使在windows.h,coca.h或unistd.h中也没有这样的功能。 很可能是你自己写的。只是做一个

struct myFile {
FILE *fh;
char *filename;
}

并将此类结构保存到数组struct myFileMagicFunction(f,b)数组中,寻找等于f的地址。