从文件描述符重命名?

Arm*_*igo 11 posix rename

从C中的文件描述符获取文件名的问题的变体.这是关于Linux的.

如果我有一个引用常规文件的文件描述符,我可以通过给它一个新的文件名"保存"文件描述符(当然,它在同一设备上的某个地方)?我正在寻找类似于重命名(2)或链接(2)的东西,但是它会接受文件描述符作为输入而不是文件名.

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

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

Cel*_*ada 5

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

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

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

  • `flink()` 确实很不错。这是唯一可以重新连接具有 0 个链接但仍然存在的文件的方法。但是是的......它在我知道的任何操作系统下都不存在。 (2认同)

pqn*_*net 5

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

linkat(fd,"",destdirfd,"filename",AT_EMPTY_PATH);
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 您需要定义_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);
Run Code Online (Sandbox Code Playgroud)