11

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

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

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

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

4

2 回答 2

6

如果问题是关于 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);

注意事项:

  • 您需要定义_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);
于 2014-08-06T07:25:06.223 回答
5

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

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

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

于 2012-12-13T22:16:23.637 回答