从C中的文件描述符获取文件名

adk*_*adk 97 c linux file file-descriptor

是否有可能在C中获取文件描述符(Linux)的文件名?

bdo*_*lan 111

您可以使用readlink/proc/self/fd/NNN其中NNN是文件描述符.这将为您提供文件的名称,就像它打开时一样 - 但是,如果从那时起移动或删除文件,它可能不再准确(尽管Linux可以在某些情况下跟踪重命名).要验证,stat给出的文件名和fstat你拥有的fd,并确保st_devst_ino相同.

当然,并非所有文件描述符都引用文件,对于那些文档描述符,您会看到一些奇怪的文本字符串,例如pipe:[1538488].由于所有真实文件名都是绝对路径,因此您可以轻松确定哪些文件名.此外,正如其他人所指出的那样,文件可以有多个指向它们的硬链接 - 这只会报告它打开的链接.如果要查找给定文件的所有名称,则只需遍历整个文件系统.

  • 只要原始文件仍然引用它(打开的`fd`就是这样的引用),就不能重用inode号*.任何在关闭文件后或打开文件之前使用inode编号的软件本身都会受到竞争条件的影响. (8认同)
  • 威尔罗宾逊,危险!这不会_always_工作 - 如果你做`setuid()`技巧,你的进程可能无法访问`/ proc/self/fd`.见:http://permalink.gmane.org/gmane.linux.kernel/1302546 (3认同)
  • @bdonlan:并且在/ proc没有挂载的情况下? (2认同)

zne*_*eak 82

我在Mac OS X上遇到了这个问题.我们没有/proc虚拟文件系统,因此接受的解决方案无效.

相反,我们有一个F_GETPATH命令fcntl:

 F_GETPATH          Get the path of the file descriptor Fildes.  The argu-
                    ment must be a buffer of size MAXPATHLEN or greater.
Run Code Online (Sandbox Code Playgroud)

因此,要获取与文件描述符关联的文件,您可以使用以下代码段:

#include <sys/syslimits.h>
#include <fcntl.h>

char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
    // do something with the file path
}
Run Code Online (Sandbox Code Playgroud)

因为我永远不记得在哪里MAXPATHLEN定义,我认为PATH_MAX从syslimits会很好.

  • 在<sys/param.h>中:#define MAXPATHLEN PATH_MAX (7认同)
  • 你能指望什么?除非它是UNIX套接字,否则它没有关联的文件. (2认同)
  • @uchuugaka是的,所有内容都是文件,但并非所有内容都是_directory entry_,其名称和位置在文件系统树中。文件由索引节点表示,它可以存在而无需任何目录条目引用。 (2认同)
  • 我刚刚对此进行了测试,如果移动文件并再次调用它,它仍然正确(意思是:您获得了文件的新路径)。但是,这在 linux 上不受支持(在 Ubuntu 14.04 上测试 - F_GETPATH 未定义)。 (2认同)

Mar*_*wis 23

在Windows中,使用GetFileInformationByHandleEx传递FileNameInfo,您可以检索文件名.

  • 就像我讨厌窗户一样,窗户等同于总是很好 (14认同)

Ale*_*lli 15

正如泰勒指出的那样,没有办法"直接可靠地"做你需要的东西,因为给定的FD可能对应于0个文件名(在各种情况下)或> 1(多个"硬链接"是后者的情况通常如何描述).如果你仍然需要具有所有限制的功能(关于速度和获得0,2,......结果而不是1的可能性),这里是你如何做到的:首先,fstat FD - 这告诉你,结果struct stat,文件所依赖的设备,它有多少硬链接,是否是特殊文件等.这可能已经回答了你的问题 - 例如,如果有0个硬链接你会知道实际上没有相应的文件名在磁盘上.

如果统计数据给你带来希望,那么你必须在相关设备上"走树"目录,直到找到所有硬链接(或者只是第一个,如果你不需要多个硬链接,任何一个都会做).为此,你使用readdir(当然还有opendir&c)以递归的方式打开子目录,直到你找到一个struct dirent你原来的同一个inode号struct stat(如果你想要整个路径,而不仅仅是名字,那么)你需要向后走一段目录才能重建它.

如果这种一般方法是可以接受的,但是你需要更详细的C代码,让我们知道,它写起来并不难(尽管如果它没用,我宁愿不写它,也就是说你无法承受不可避免的缓慢性能或者得到的可能性!= 1为您的申请目的的结果;-).


Duc*_*uck 8

在将此文章写为不可能之前,我建议您查看lsof命令的源代码.

可能存在限制,但lsof似乎能够确定文件描述符和文件名.这些信息存在于/ proc文件系统中,因此应该可以从您的程序中获取.


Pet*_*osB 6

您可以使用fstat()通过struct stat获取文件的inode.然后,使用readdir(),您可以将找到的inode与目录中存在的inode(struct dirent)进行比较(假设您知道目录,否则您将不得不搜索整个文件系统)并找到相应的文件名.讨厌?