Frage

In Unix, ist es möglich, eine Verbindung zu einer anonymen Datei, zum Beispiel zu erstellen, erstellen und mit creat Öffnung () und dann mit unlink das Verzeichnis Link zu entfernen () - Sie mit einer Datei mit einem Inode und Lagerung zu verlassen, aber keine Möglichkeit, um wieder zu öffnen. Solche Dateien werden als temporäre Dateien häufig verwendet wird (und in der Regel das ist, was tmpfile () wieder zu Ihnen).

Meine Frage: Gibt es eine Möglichkeit, um wieder eine Datei anhängen wie dieser zurück in die Verzeichnisstruktur? Wenn Sie dies tun könnte, bedeutet es, dass Sie könnte z.B. Datei schreibt implementieren, so dass die Datei erscheint atomar und vollständig ausgebildet. Dies spricht meinen Zwang Ordentlichkeit. ;)

Wenn Stossen durch die entsprechenden Systemaufruf Funktionen ich eine Version von Link zu finden erwartet () aufgerufen flink () (Vergleich mit chmod () / fchmod ()), aber zumindest auf Linux diese nicht existieren.

Bonuspunkte für das Erklären Sie mir, wie die anonyme Datei zu erstellen, ohne kurz einen Dateinamen in der Festplatte des Verzeichnisstruktur freigelegt wird.

War es hilfreich?

Lösung

Ein Patch für Linux flink() Systemaufruf vorgeschlagen vor einigen Jahren vorgelegt wurde, aber wenn Linus „es gibt keinen Weg in die Hölle wir dies sicher ohne große andere Einfälle tun können“ , dass so ziemlich die Debatte über beendet, ob diese hinzuzufügen.

Update: Ab Linux 3.11 ist es nun möglich, eine Datei ohne Verzeichniseintrag erstellen mit linkat() auf /proc/self/fd/ fd mit der AT_SYMLINK_FOLLOW Flagge.

Im folgenden Beispiel wird auf der mitgelieferten open() Manpage :

    char path[PATH_MAX];
    fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);

    /* File I/O on 'fd'... */

    snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
    linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW);

Beachten Sie, dass linkat() nicht offen lassen werden die Dateien wieder an, nachdem die letzte Verbindung mit unlink() entfernt wird.

Andere Tipps

Meine Frage: Gibt es eine Möglichkeit, um wieder eine Datei anhängen wie dieser zurück in die Verzeichnisstruktur? Wenn Sie dies tun könnte, bedeutet es, dass Sie könnte z.B. Datei schreibt implementieren, so dass die Datei erscheint atomar und vollständig ausgebildet. Diese Appelle an dem meinem Zwang Ordentlichkeit. ;)

Wenn dies Ihr einziges Ziel ist es, können Sie dies in einem viel einfacher und breiter Weise verwendet erreichen. Wenn Sie a.dat ausgeben:

  1. Öffnen a.dat.part für Schreib.
  2. Schreiben Sie Ihre Daten.
  3. Rename a.dat.part zu a.dat.

Ich kann verstehen, will ordentlich sein, aber eine Datei Entkoppeln und erneutes Verknüpfen ihm nur „ordentlich“ zu sein ist irgendwie albern.

Diese Frage auf serverfault anzuzeigen scheint, dass diese Art der Wiedervernetzung ist unsicher und nicht unterstützt.

Dank @ mark4o Posting über linkat(2) findet seine Antwort für Details.

Ich wollte es ausprobieren, um zu sehen, was passiert eigentlich, wenn sie tatsächlich versuchen, verknüpfen eine anonyme Datei wieder in das Dateisystem auf gespeichert wird. (Oft /tmp, zum Beispiel für Videodaten, die firefox-Wiedergabe).


Wie von Linux 3.16, scheint es noch keine Möglichkeit, eine gelöschte Datei wiederherstellen, die noch offen gehalten wird. Weder AT_SYMLINK_FOLLOW noch AT_EMPTY_PATH für linkat(2) den Trick für gelöschte Dateien, die einen Namen haben verwendet, auch als root an.

Die einzige Alternative ist tail -c +1 -f /proc/19044/fd/1 > data.recov, die eine separate Kopie macht, und Sie haben es zu töten manuell, wenn es fertig ist.


Hier ist die Perl-Wrapper ich zum Testen gekocht. Verwenden strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname, um zu überprüfen, dass Ihr System kann immer noch nicht undelete geöffnete Dateien. (Gleiches gilt auch bei sudo). Offensichtlich sollten Sie Code lesen Sie im Internet finden, bevor es ausgeführt wird, oder ein Sandbox-Konto verwenden.

#!/usr/bin/perl -w
# 2015 Peter Cordes <peter@cordes.ca>
# public domain.  If it breaks, you get to keep both pieces.  Share and enjoy

# Linux-only linkat(2) wrapper (opens "." to get a directory FD for relative paths)
if ($#ARGV != 1) {
    print "wrong number of args.  Usage:\n";
    print "linkat old new    \t# will use AT_SYMLINK_FOLLOW\n";
    print "linkat - <old  new\t# to use the AT_EMPTY_PATH flag (requires root, and still doesn't re-link arbitrary files)\n";
    exit(1);
}

# use POSIX qw(linkat AT_EMPTY_PATH AT_SYMLINK_FOLLOW);  #nope, not even POSIX linkat is there

require 'syscall.ph';
use Errno;
# /usr/include/linux/fcntl.h
# #define AT_SYMLINK_NOFOLLOW   0x100   /* Do not follow symbolic links.  */
# #define AT_SYMLINK_FOLLOW 0x400   /* Follow symbolic links.  */
# #define AT_EMPTY_PATH     0x1000  /* Allow empty relative pathname */
unless (defined &AT_SYMLINK_NOFOLLOW) { sub AT_SYMLINK_NOFOLLOW() { 0x0100 } }
unless (defined &AT_SYMLINK_FOLLOW  ) { sub AT_SYMLINK_FOLLOW  () { 0x0400 } }
unless (defined &AT_EMPTY_PATH      ) { sub AT_EMPTY_PATH      () { 0x1000 } }


sub my_linkat ($$$$$) {
    # tmp copies: perl doesn't know that the string args won't be modified.
    my ($oldp, $newp, $flags) = ($_[1], $_[3], $_[4]);
    return !syscall(&SYS_linkat, fileno($_[0]), $oldp, fileno($_[2]), $newp, $flags);
}

sub linkat_dotpaths ($$$) {
    open(DOTFD, ".") or die "open . $!";
    my $ret = my_linkat(DOTFD, $_[0], DOTFD, $_[1], $_[2]);
    close DOTFD;
    return $ret;
}

sub link_stdin ($) {
    my ($newp, ) = @_;
    open(DOTFD, ".") or die "open . $!";
    my $ret = my_linkat(0, "", DOTFD, $newp, &AT_EMPTY_PATH);
    close DOTFD;
    return $ret;
}

sub linkat_follow_dotpaths ($$) {
    return linkat_dotpaths($_[0], $_[1], &AT_SYMLINK_FOLLOW);
}


## main
my $oldp = $ARGV[0];
my $newp = $ARGV[1];

# link($oldp, $newp) or die "$!";
# my_linkat(fileno(DIRFD), $oldp, fileno(DIRFD), $newp, AT_SYMLINK_FOLLOW) or die "$!";

if ($oldp eq '-') {
    print "linking stdin to '$newp'.  You will get ENOENT without root (or CAP_DAC_READ_SEARCH).  Even then doesn't work when links=0\n";
    $ret = link_stdin( $newp );
} else {
    $ret = linkat_follow_dotpaths($oldp, $newp);
}
# either way, you still can't re-link deleted files (tested Linux 3.16 and 4.2).

# print STDERR 
die "error: linkat: $!.\n" . ($!{ENOENT} ? "ENOENT is the error you get when trying to re-link a deleted file\n" : '') unless $ret;

# if you want to see exactly what happened, run
# strace -eopen,linkat  linkat.pl

Das ist natürlich möglich - fsck es tut, zum Beispiel. Allerdings fsck tut es mit großen lokalen Dateisystem mojo und eindeutig nicht tragbar sein, noch die ausführbare Datei als nicht privilegierter Benutzer. Es ist ähnlich wie der debugfs Kommentar oben.

, dass flink(2) Anruf Schreiben wäre eine interessante Übung sein. Wie IJW weist darauf hin, würde es einige Vorteile gegenüber der derzeitigen Praxis der temporären Dateiumbenennung bieten (Umbenennungs, hinweis, ist garantiert atomar).

Art spät, um das Spiel, aber ich gerade gefunden http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data die em <> können beantworte die Frage. Ich habe es nicht getestet, obwohl, so YMMV. Es sieht Klang.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top