首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在文件仍在打开时恢复已删除的文件?

如何在文件仍在打开时恢复已删除的文件?
EN

Unix & Linux用户
提问于 2019-01-16 08:38:34
回答 1查看 655关注 0票数 4

我试过了

代码语言:javascript
复制
xtricman⚓ArchVirtual⏺️~ls /proc/self/fd/ -l
Total 0
lrwx------ 1 xtricman users 64 1月  16 16:34 0 -> /dev/pts/0
lrwx------ 1 xtricman users 64 1月  16 16:34 1 -> /dev/pts/0
lrwx------ 1 xtricman users 64 1月  16 16:34 2 -> /dev/pts/0
lrwx------ 1 xtricman users 64 1月  16 16:34 3 -> '/home/xtricman/a (deleted)'
lr-x------ 1 xtricman users 64 1月  16 16:34 4 -> /proc/1273/fd
xtricman⚓ArchVirtual⏺️~ln /proc/self/fd/3 b
ln: failed to create hard link 'b' => '/proc/self/fd/3': Invalid cross-device link

由于inode仍然在磁盘上,我如何为它重新创建一个名称?如果没有指向该inode但指向inode的打开文件描述,怎么办?在这种情况下我该如何恢复呢?

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2019-02-10 11:30:20

您不应该能够做到这一点(但是下面是一个有趣的例外)。

如果内核允许这种情况发生,那么调用如下:

代码语言:javascript
复制
fd = open(filename, O_CREAT|O_RDWR, 0666);
unlink(filename);

linkat(fd, "", 0, "/new/path", AT_EMPTY_PATH);

即使fd引用的inode的链接计数为0,如果由具有CAP_DAC_READ_SEARCH上限的进程完成,也会成功。

但是内核正在积极地阻止它的发生,而不考虑进程的能力或特权。

代码语言:javascript
复制
int vfs_link(struct dentry *old_dentry, ...
{
        ...
        /* Make sure we don't allow creating hardlink to an unlinked file */
        if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
                error =  -ENOENT;

这一点在手册中也有记载:

AT_EMPTY_PATH (因为Linux2.6.39)如果oldpath是一个空字符串,则创建一个指向olddirfd引用的文件的链接(该链接可能是使用open(2) O_PATH标志获得的)。在这种情况下,olddirfd可以引用除目录之外的任何类型的文件。如果文件的链接计数为零(使用O_TMPFILE创建的文件和没有O_EXCL的文件都是例外),则这通常无法工作。调用方必须具有CAP_DAC_READ_SEARCH功能才能使用此标志。此标志是Linux特有的;定义_GNU_SOURCE以获得其定义。

基于内核源代码,除了O_TMPFILE之外,似乎没有其他异常。O_TMPFILE记录在open(2)手册中;下面是基于此的一个小示例:

代码语言:javascript
复制
#define _GNU_SOURCE 1
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <err.h>

int main(int ac, char **av){
        char path[64]; int fd;
        if(ac < 3) errx(1, "usage: %s dir newpath", av[0]);

        if((fd = open(av[1], O_TMPFILE|O_RDWR, 0666)) == -1) err(1, "open");

        /*
         * ...
         * write stuff to fd and only "realize" the file at the end if
         * everything has succeeded
         */

        /* the following line only works with CAP_DAC_READ_SEARCH */
        /* if(linkat(fd, "", 0, av[2], AT_EMPTY_PATH)) err(1, "linkat"); */

        snprintf(path, sizeof path, "/proc/self/fd/%d", fd);
        if(linkat(AT_FDCWD, path, AT_FDCWD, av[2], AT_SYMLINK_FOLLOW))
                err(1, "linkat");
        return 0;
}
票数 7
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/494760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档