削除したファイルを開いたまま復元するにはどうすればいいですか?

削除したファイルを開いたまま復元するにはどうすればいいですか?

私は試した

xtricman⚓ArchVirtual⏺️~

答え1

そんなことはできないはずです (ただし、興味深い例外については以下をお読みください)。

カーネルがこれを許可した場合、次のような呼び出しが行われます。

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

しかし、カーネルは、それを実行するプロセスの機能や権限に関係なく、それが起こるのを積極的に防止します。

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;

これは man ページにも記載されています:

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は man ページに記載されています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実行できることは制限されています (コンテンツはカーネルの状態を反映するため、任意の操作を実行することはできません)。

関連情報