如果我有一个打开文件的句柄,是否可以创建一个硬链接到该文件,所有引用它已经从文件系统中删除?
例如,这样的东西:
fd = fopen("/tmp/foo","w"); unlink("/tmp/foo"); fwrite(fd,"Hello,world!\n"); create_link_from_fd(fd,"/tmp/hello"); fclose(fd);
具体来说,我想这样做,以便我可以安全地写入大型数据文件,然后将它们原子地移动到原位,而不用担心如果我的程序在编写文件时被杀死,我自己之后要清理.
解决方法
不一般,不. [编辑:自Linux 3.11以来现在有linkat;请参见
safsaf32’s answer.这一般不适用于POSIX系统,因为POSIX linkat仅限于目录.]这里有一些安全注意事项:有人可以传递一个您通常不能自己打开的打开的文件描述符,例如:
mkdir lock; chmod 700 lock echo secret contents > lock/in sudoish cmd < lock/in
这里,cmd以用户身份运行,该用户没有权限通过名称打开输入文件(lock / in),但仍然可以从中读取.如果cmd可以在同一个文件系统上创建一个新的名称,那么它可以将文件内容传递给后一个进程. (显然可以复制这些内容,所以这个问题更多的是“通过错误的内容”,而不是“按目的传递内容”.)
也就是说,人们已经提出了在内部使用inode / vnode“重新链接”文件的方式(在大多数文件系统中很容易做到这一点),所以你可以为自己的专用系统调用它.当然,描述符必须在适当的安装点上引用一个真实的文件 – 没有办法将管道或套接字或设备“重新链接”成为常规文件.
否则,你会陷入“捕获信号,清理和希望最好”,或者类似的技巧,“分叉子进程,运行它,如果成功/失败,采取适当的移动/清理操作”.
编辑添加历史记录:上面的锁定示例不是特别好,但是在V6 Unix的日子里,MDQS使用了这个技巧的一个优点. MDQS的位和片段今天以各种形式生存.