【问题标题】:Getting real path from file handle [duplicate]从文件句柄获取真实路径[重复]
【发布时间】:2014-12-22 20:00:26
【问题描述】:

有没有办法从文件句柄中获取真实路径(即没有任何“/../”、“/./”序列、符号链接等的绝对路径)?我知道 POSIX 有 realpath() 函数,但这不接受文件句柄。它改为使用文件名(字符串)。我需要一个函数来接受由fopen() 分配的stdio FILE* 句柄或由open() 分配的文件描述符,并返回该文件的真实路径。

这样的东西存在吗?或者有没有其他方法可以从 FILE* 句柄或 POSIX 文件描述符中获取完全限定的路径?

【问题讨论】:

  • 嗯,我怀疑,因为文件不需要有路径或只有一个路径......
  • 所有你想要的都是文件系统实现的一部分,而不是 POSIX C。虽然你可以使用 C 编写它。这意味着如何做到这一点是平台特定的,像 lsof 和 fuser 这样的程序是为特定的操作系统。如果你想要一些便携的东西,你有很多工作要做。如果文件仍然存在并且不是普通文件。
  • FILE *”变体将通过使用fileno(fp) 调用文件描述符变体来处理。但由于文件描述符可能用于套接字、已删除文件、普通管道或其他此类无名“文件”,frealpath() 函数并不是一个真正的选项——这就是它没有提供的原因。请注意,即使系统被要求记录与open()creat() 一起使用的名称,但在您尝试访问它时,该名称可能已被重用。至少,您必须使用 fstat()stat() 并比较 inode 编号和持有设备编号。
  • 有什么理由你不能只跟踪你用来打开文件的文件名并使用它?

标签: c posix stdio


【解决方案1】:

通常,一个文件可能有多个名称(硬链接),根本没有名称(未链接的文件),并且文件描述符可能连接到文件系统中未表示的东西(例如管道或套接字) .

在Linux下,你可以这样做

snprintf(buf, bufsize, "/proc/self/fd/%d", fd);
rc = readlink(buf, filename, filename_size);

如果readlink 成功,并且filename 是绝对路径(它以斜杠/ 开头),那么它可能包含@987654325 所在文件的文件名(但不一定是唯一的) @ 已连接 — 但它也可能包含其他内容(例如文件名后跟 (deleted))。如果filename 没有以斜线开头,那么你就不走运了。

据我所知,没有可移植的方式来做这样的事情。

【讨论】:

  • 我认为这个答案并不完全正确。 readlink 的结果可能以斜杠开头,但不是打开文件的有效路径名。这总是在文件被删除时发生;内核只是将" (deleted)" 添加到路径名的末尾。我不知道有什么方法可以将这种情况与以该字符串结尾的真实姓名区分开来。 :(
  • @R.. 已编辑。现在好点了吗?
  • 如果文件名不以斜杠开头,您可以将realpath() 应用于给定名称;实际上,要确保名称中没有符号链接等,您需要使用realpath()。 (至少,您不能通过简单地编辑它以删除 /..//./ 符号来可靠地规范化名称 - 如果涉及符号链接,它可能会产生完全错误的路径名。)主要问题是如果文件在当前工作目录为/some/where 时打开,但该进程已将工作目录更改为/another/place/altogether
  • @JonathanLeffler 如果它不以斜杠开头,它可能是“socket:12345”的形式。 realpath 无济于事。
  • 好的;我想我需要看看/dev/fd 中的链接实际发生了什么。如果在文件具有绝对名称时将名称转换为绝对名称,即使使用相对路径名打开文件,应用realpath() 也不会整理出相对名称。您必须知道内核是否也将“realpath()”转换应用于绝对名称。它可能只是“按需”完成,当有人读到名字时——否则,对于程序运行时没有人读链接的常见情况来说,这是不必要的成本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 2020-02-28
  • 2014-07-27
  • 1970-01-01
相关资源
最近更新 更多