在Unix中,可以创建匿名文件的句柄,例如,使用creat()创建并打开它,然后使用unlink()删除目录链接 - 留下带有inode和存储的文件但是没有办法重新打开它。这些文件通常用作临时文件(通常这是tmpfile()返回给你的文件)。
我的问题:有没有办法将这样的文件重新附加到目录结构中?如果你能做到这一点意味着你可以这样做,例如实现文件写入,以便文件以原子方式显示并完全形成。这吸引了我强迫的整洁。 ;)
当浏览相关的系统调用函数时,我希望找到一个名为flink()的link()版本(与chmod()/ fchmod()比较)但是,至少在Linux上这不存在。
奖励点告诉我如何创建匿名文件,而不是简单地在磁盘的目录结构中公开文件名。
答案 0 :(得分:35)
flink()
system call,但是当Linus说"there is no way in HELL we can do this securely without major other incursions"时,这几乎结束了关于是否添加此内容的辩论。
更新:从Linux 3.11开始,现在可以使用带有O_TMPFILE
新标记的open()
创建一个没有目录条目的文件,并将其链接到文件系统一旦使用/proc/self/fd/
fd linkat()
与AT_SYMLINK_FOLLOW
标志完全形成。
以下示例在open()
手册页上提供:
char path[PATH_MAX];
fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
/* File I/O on 'fd'... */
snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW);
请注意,在使用linkat()
删除最后一个链接后,unlink()
将不允许重新附加打开的文件。
答案 1 :(得分:1)
我的问题:有没有办法将这样的文件重新附加到目录结构中?如果你能做到这一点意味着你可以这样做,例如实现文件写入,以便文件以原子方式显示并完全形成。这吸引了我强迫的整洁。 ;)
如果这是您唯一的目标,您可以通过更简单,更广泛使用的方式实现这一目标。如果您要输出到a.dat
:
a.dat.part
进行写作。a.dat.part
重命名为a.dat
。我可以理解想要整洁,但取消链接文件并重新链接只是为了“整洁”是有点傻。
This question on serverfault似乎表明这种重新链接不安全且不受支持。
答案 2 :(得分:1)
感谢关于linkat(2)
的@ mark4o帖子,请参阅他的回答了解详情。
我想尝试一下,当试图将匿名文件实际链接回存储在其中的文件系统时,看看实际发生了什么。 (通常是/tmp
,例如firefox正在播放的视频数据。)
从Linux 3.16开始,似乎仍无法取消删除仍保持打开状态的已删除文件。 AT_SYMLINK_FOLLOW
的{{1}}和AT_EMPTY_PATH
都不会为以前拥有名称的已删除文件执行操作,即使是root用户。
唯一的选择是linkat(2)
,它会生成一个单独的副本,你必须在完成后手动终止它。
这是我为测试准备的perl包装器。使用tail -c +1 -f /proc/19044/fd/1 > data.recov
验证您的系统仍然无法取消删除打开的文件。 (即使使用strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname
也是如此)。显然,您应该在运行之前阅读在Internet上找到的代码,或者使用沙盒帐户。
sudo
答案 3 :(得分:-1)
显然,这是可能的 - 例如fsck
就可以了。但是,fsck
使用主要的本地化文件系统mojo来执行此操作,并且显然不可移植,也不能作为非特权用户执行。它类似于上面的debugfs
评论。
写flink(2)
电话是一项有趣的练习。正如ijw所指出的,它将提供一些优于当前临时文件重命名的优势(重命名,注意,保证原子)。
答案 4 :(得分:-2)
有点迟到了,但我刚刚找到http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data 可以回答问题。我没有测试过,所以YMMV。看起来很健康。