Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Undo unlink with file open

Tags:

file

unlink

perl

unlink does not delete a file, if it is open; it just removes the name and the link to the name. Can unlink be undone?

open(my $fh, ">", undef) || die;
print $fh "foo";
# This does not work
link($fh,"/tmp/bar") || die;

Can an open file handle to an unlinked file be linked to a file?

like image 614
Ole Tange Avatar asked Oct 18 '22 02:10

Ole Tange


1 Answers

If feasible, you can change the open mode ('>') to be read/write instead. Then, when you need to recover the file you can use the filehandle to print it out to a newly opened file, even with the same name if needed.

open my $fh, '+>', $file;
say $fh "line 1";
unlink $file;
say $fh "more lines";

seek $fh, 0, 0;
open my $fh_rec, '>', $file   or die "Can't open $file (again): $!";
print $fh_rec $_ while <$fh>;

This isn't exactly what is asked but it recovers the file content and access to it. Further prints to $fh would leave the new $file out of sync, so this can be done when writing's done (to restore the file) or to switch the printing to $fh_rec (then also close $fh).


Another way to recover a file is by using the OS, if it uses /proc and exposes file handles. Then the data can be copied from /proc/PID/fd/N. To identify N one can scan all links that are in fd/ (a few) with ls -l, since the deleted file should have (deleted) after its name.

Also, lsof -p PID lists all open file descriptors for the given process. The ones for deleted files have (deleted) with them. (The lsof +L1 -p PID outputs only deleted entries, still quite a few.) From this output we can read off that file descriptor and then copy the data from /proc/PID/fd/N. This way we also get the inode number, which can also be used to recover the file.

like image 81
zdim Avatar answered Nov 15 '22 12:11

zdim