【问题标题】:Rename from a file descriptor?从文件描述符重命名?
【发布时间】:2012-12-01 10:25:48
【问题描述】:

问题Getting Filename from file descriptor in C 的变体。这是关于 Linux 的。

如果我有一个引用常规文件的文件描述符,我可以通过给它一个新的文件名来“保存”文件描述符(当然,在它所在的同一设备上)?我正在寻找类似于 rename(2) 或 link(2) 的东西,但它会接受文件描述符作为输入而不是文件名。

rename(2) 和 link(2) 的问题在于,即使您可以尝试从文件描述符转到文件名,这也可能会失败。我正在更准确地考虑打开的文件描述符引用已经取消链接的文件的情况——在这种情况下,文件没有更多的名称。当我们 close() 文件描述符时,似乎没有办法阻止文件被删除。但我错了吗?我们可以使用 Posix 甚至 Linux API 重新命名吗?

更新:我们实际上可以在/proc/<pid>/fd/<fd> 中看到 Linux 上已删除文件的内容,尽管它看起来像是一个损坏的符号链接。但是,我们不能使用 link(2) 或 ln(1) 重新实现这样的文件,因为它认为我们正在尝试进行跨设备链接。

【问题讨论】:

  • 但是您可以将内容从 fd/ 文件中复制出来。愚蠢的是你不能重新链接它。
  • 这里的答案基本相同:stackoverflow.com/q/4171713/4421

标签: posix rename


【解决方案1】:

如果问题是关于 linux 并且关于 linux > 2.6.39,您可以使用带有AT_EMPTY_PATH 标志的linkat 命令来为文件描述符命名。请参阅手册页 (http://man7.org/linux/man-pages/man2/link.2.html)

linkat(fd,"",destdirfd,"filename",AT_EMPTY_PATH);

注意事项:

  • 你需要定义_GNU_SOURCE来得到AT_EMPTY_PATH的定义,
  • 对于链接计数为零的文件,这不能保证有效。我不确定我是否理解手册页对此的说明。我的猜测是,当文件的链接计数为零时,文件系统上的 inode 已被删除,以避免文件系统崩溃时出现不一致。
  • 当然,如果旧文件不在目标目录的同一文件系统上,我当然不希望它工作。

如果这失败了,您只能创建一个新文件并使用sendfile 将内容复制到上面(省略了错误检查,请参阅每个函数的手册页以了解可能的错误值):

struct stat s;
off_t offset = 0;
int targetfd = open("target/filename", O_WRONLY | O_CREAT | O_EXCL);
fstat(fd,&s);
sendfile(targetfd,fd,&offset, s.st_size);

【讨论】:

  • 谢谢!它仍然不是完全通用的,但它是朝着“正确”方向迈出的一步——我并不是在暗示我所要求的东西真的是正确的,甚至是需要的。 (我最初的问题只是出于好奇。)
  • 我认为linux真的会帮助“给这个文件描述符命名”通用api,只有当文件描述符不引用普通文件或引用另一个分区中的文件时才会失败.此外,这样做时应该有原子替换现有文件的方法,现在可以使用rename,但前提是源文件具有文件系统名称。
【解决方案2】:

问题:假设存在一个采用文件描述符的系统调用frename,如果一个文件有多个名称(硬链接),当此系统调用用于文件描述符时,其中哪些名称会被移动/重命名指的是这个文件?

这个问题没有很好的答案,这也是这个系统调用不存在的原因之一。

rename 处理目录条目,它们是指向文件(inode)的指针。打开的文件描述符不与任何特定的目录条目相关联,仅与文件本身(inode)相关联。从这个角度来看,您要求的系统调用实际上没有意义。没有可移植的方式来跟随一个 inode 回到指向它的目录条目(同样,它们可能不止一个)。某些操作系统可能会提供各种非便携式方法来查找此反向链接,这些方法可能会或可能不会保证总是提供结果(通常不保证),但这些方法不能回答返回哪个目录条目的问题当有多个时,据我所知,它们都没有像您正在寻找的那样扩展到系统调用。

【讨论】:

  • 很抱歉给您带来了困惑。这对我来说很清楚,这就是为什么我也建议flink()。我不应该提到frename()
  • flink() 确实不错。这是唯一可以重新连接具有 0 个链接但仍然存在的文件的方法。但是,是的......它在我所知道的任何操作系统下都不存在。
猜你喜欢
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
相关资源
最近更新 更多