Wie kann ich eine gelöschte Datei wiederherstellen, während sie noch geöffnet ist?

Wie kann ich eine gelöschte Datei wiederherstellen, während sie noch geöffnet ist?

Ich habe es versucht

xtricman⚓ArchVirtual⏺️~

Antwort1

Eigentlich sollten Sie dazu nicht in der Lage sein (lesen Sie jedoch weiter unten, um mehr über eine interessante Ausnahme zu erfahren).

Wenn der Kernel dies zulassen würde, würde ein Aufruf wie dieser ausreichen:

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

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

wäre erfolgreich, selbst wenn der von referenzierte Inode fdeine Linkanzahl von 0 hätte, wenn dies von einem Prozess mit CAP_DAC_READ_SEARCHCaps durchgeführt wird.

Der Kernel verhindert dies jedoch aktiv, ohne Rücksicht auf die Fähigkeiten oder Privilegien des ausführenden Prozesses.

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;

Dies ist auch in der Manpage dokumentiert:

AT_EMPTY_PATH(seit Linux 2.6.39)

Wenn oldpathes sich um eine leere Zeichenfolge handelt, erstellen Sie einen Link zu der Datei, auf die verwiesen wird olddirfd(die möglicherweise mithilfe des Flags abgerufen wurde open(2) O_PATH). In diesem Fall olddirfdkann auf jeden Dateityp außer einem Verzeichnis verwiesen werden. Dies funktioniert im Allgemeinen nicht, wenn die Datei eine Linkanzahl von Null hat (Dateien, die mit O_TMPFILEund ohne erstellt wurden, O_EXCLsind eine Ausnahme).. Der Anrufer muss die CAP_DAC_READ_SEARCHBerechtigung haben, dieses Flag zu verwenden. Dieses Flag ist Linux-spezifisch; definieren Sie, _GNU_SOURCEum seine Definition zu erhalten.

basierend auf dem Kernel-Quellcode scheint es außer keine andere Ausnahme zu geben O_TMPFILE. O_TMPFILEist in der open(2)Manpage dokumentiert; unten ist ein kleines Beispiel, das darauf basiert:

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

Antwort2

Sie könnten einfach catdiesen Dateideskriptor verwenden:

$ 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

Sie können lnfür diese Datei keinen Hardlink erstellen, da sich Hardlinks nicht über Dateisysteme erstrecken können und /proces sich um ein virtuelles Dateisystem ( procfs) handelt und /procIhre Möglichkeiten sogar innerhalb von eingeschränkt sind (der Inhalt spiegelt den Zustand des Kernels wider, daher können Sie keine beliebigen Operationen durchführen).

verwandte Informationen