Dank @ Mark4o Posting über linkat(2)
, finden Sie in seiner Antwort für Details.
Ich wollte versuchen zu sehen, was tatsächlich passiert ist, als ich versuchte, eine anonyme Datei wieder in das Dateisystem zu verlinken, auf dem sie gespeichert ist. (oft /tmp
, beispielsweise für Videodaten, die Firefox spielt).
Ab Linux 3.16 scheint es immer noch keine Möglichkeit zu geben, eine gelöschte Datei wiederherzustellen, die noch offen ist. Weder AT_SYMLINK_FOLLOW
noch AT_EMPTY_PATH
für linkat(2)
machen Sie den Trick für gelöschte Dateien, die einen Namen hatten, auch als root.
Die einzige Alternative ist tail -c +1 -f /proc/19044/fd/1 > data.recov
, die eine separate Kopie macht, und Sie müssen es manuell beenden, wenn es fertig ist.
Hier ist die Perl-Wrapper ich zum Testen gekocht. Verwenden Sie strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname
, um zu überprüfen, ob das System geöffnete Dateien nicht wiederherstellen kann. (Gleiches gilt auch für sudo
). Offensichtlich sollten Sie den Code lesen, den Sie im Internet finden, bevor Sie ihn ausführen, oder ein Sandbox-Konto verwenden.
#!/usr/bin/perl -w
# 2015 Peter Cordes <[email protected]>
# 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
Ta. Er schlägt eine Lösung vor, die auch funktionieren sollte, wohlgemerkt. Für eine zwanghafte Ordentlichkeit brauchen Sie wahrscheinlich auch einen Weg, creat() in einem Verzeichnis anzurufen, so dass es die Datei und den Inode erstellt, aber nicht den Verzeichniseintrag, so dass es nie an erster Stelle verlinkt ist. – ijw
Das Update ist voller Gewinn. Ich kann dich nicht +2 aber ich würde wenn ich könnte. – ijw
Verwirrend, 'linkat()' gibt 'ENOENT' bei Versuchen, eine normale offene aber nicht verknüpfte Datei erneut anzuhängen. (mit entweder 'AT_SYMLINK_FOLLOW' oder' AT_EMPTY_PATH') –