如何在檔案仍處於開啟狀態時恢復已刪除的檔案?

如何在檔案仍處於開啟狀態時恢復已刪除的檔案?

我試過

xtricman⚓ArchVirtual⏺️~

答案1

你不應該能夠做到這一點(但請閱讀下面的一個有趣的例外)。

如果核心允許這種情況發生,那麼呼叫如下:

fd = open(filename, O_CREAT|O_RDWR, 0666);
unlink(filename);

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

fd當由具有 caps 的進程完成時,即使引用的 inode 的連結計數為 0,也會成功CAP_DAC_READ_SEARCH

但核心正在積極阻止這種情況的發生,而不考慮執行此操作的程序的功能或特權。

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(自 Linux 2.6.39 起)

如果oldpath是空字串,則建立指向 引用的檔案的連結 olddirfd(可能已使用該open(2) O_PATH標誌取得)。在這種情況下,olddirfd可以引用目錄以外的任何類型的檔案。 如果文件的連結計數為零,這通常不起作用(使用 O_TMPFILE和不使用建立的文件O_EXCL除外)。呼叫者必須具有CAP_DAC_READ_SEARCH使用此標誌的能力。該標誌是 Linux 特定的;定義_GNU_SOURCE以獲得其定義。

根據內核源碼,除了 之外似乎沒有其他異常O_TMPFILEO_TMPFILE記錄在線上open(2)說明頁;以下是一個基於此的小例子:

#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;
}

答案2

您可以簡單地使用cat該文件描述符:

$ echo foo > bar
$ sleep 10m < bar & rm bar 
[1] 15743
$ ls -l /proc/15743/fd 
total 0
lr-x------ 1 olorin olorin 64 Jan 16 17:49 0 -> /tmp/bar (deleted)
lrwx------ 1 olorin olorin 64 Jan 16 17:49 1 -> /dev/pts/6
lrwx------ 1 olorin olorin 64 Jan 16 17:49 2 -> /dev/pts/6
$ cat /proc/15743/fd/0
foo
$ cat /proc/15743/fd/0 > bar
$ cat bar
foo

你不能ln對該文件進行硬鏈接,因為硬鏈接不能跨越文件系統,並且/proc是一個虛擬文件系統(procfs),即使在 中/proc,你可以做的事情也是有限的(內容反映了內核的狀態,所以你不能執行任意操作)。

相關內容