Nasıl rm -rf dirçalışır:
- Açılır
dirve içeriğini listeler.
- Her giriş için, eğer bir dizinse, aynı işlemi tekrarlayın, eğer değilse, çağırın
unlink.
Dizin listeleme için önce özel bir dosya adı döndürdüyseniz ve unlinkbu dosya üzerinde bir işlem yaparak ölüme neden olabilirseniz , bu sorunu çözecektir. Bu bir sigorta dosya sistemi kullanılarak yapılabilir.
Örneğin, adapte olabilir loopback.plörnek gelen perl Fuse modülü şöyle bir gerçek dosya sistemi ve alt kısımda geçiyorsa geçiş sadece sadece bir kukla dosya sistemini uygulayan (ayrıca aşağıda yama bakın):
- bir dizini listelerken, adında bir girdi içeriyorsa
.{{do-not-delete}}., iki dosya içeren girdilerin başına ekleyin: .{{do-not-delete}}!errorve.{{do-not-delete}}!kill
unlinkbirincisine çalışırken , bir hata mesajı görüntüleyecek şekilde EPERMkodu rmdöndürün
unlinkikincisine çalışırken , süreç öldürülür.
$ ls -Ff dir/test
./ .{{do-not-delete}}. foo/ ../ bar
$ ./rm-rf-killer dir
$ ls -Ff dir/test
.{{do-not-delete}}!error .{{do-not-delete}}!kill ./ .{{do-not-delete}}. foo/ ../ bar
$ rm -rf dir/test
rm: cannot remove `dir/test/.{{do-not-delete}}!error': Operation not permitted
zsh: terminated rm -rf dir/test
$ ls -Ff dir/test
.{{do-not-delete}}!error .{{do-not-delete}}!kill ./ .{{do-not-delete}}. foo/ ../ bar
İşte bir kavram kanıtı olarak bu loopback.plörneğin üstüne uygulanacak bir yama :
--- loopback.pl 2013-06-03 22:35:00.577316063 +0100
+++ rm-rf-killer 2013-06-03 22:33:41.523328427 +0100
@@ -7,2 +7,4 @@
my $has_threads = 0;
+my $flag = ".{{do-not-delete}}";
+
eval {
@@ -42,3 +44,4 @@
-use blib;
+#use blib;
+use File::Basename;
use Fuse;
@@ -49,3 +52,3 @@
-my %extraopts = ( 'threaded' => 0, 'debug' => 0 );
+my %extraopts = ( 'threaded' => 0, 'debug' => 0, 'mountopts' => 'nonempty' );
my($use_real_statfs, $pidfile);
@@ -64,3 +67,7 @@
-sub fixup { return "/tmp/fusetest-" . $ENV{LOGNAME} . shift }
+sub fixup {
+ my $f = shift;
+ $f =~ s#(/\Q$flag\E)!(error|kill)$#$1.#s;
+ return ".$f";
+}
@@ -78,3 +85,9 @@
}
- my (@files) = readdir(DIRHANDLE);
+ my @files;
+
+ while (my $f = readdir(DIRHANDLE)) {
+ unshift @files, "$flag!error", "$flag!kill"
+ if ($f eq "$flag.");
+ push @files, $f;
+ }
closedir(DIRHANDLE);
@@ -121,3 +134,12 @@
sub x_readlink { return readlink(fixup(shift)); }
-sub x_unlink { return unlink(fixup(shift)) ? 0 : -$!; }
+sub x_unlink {
+ my $f = shift;
+ if (basename($f) eq "$flag!error") {return -EPERM()}
+ if (basename($f) eq "$flag!kill") {
+ my $caller_pid = Fuse::fuse_get_context()->{"pid"};
+ kill("TERM", $caller_pid);
+ return -EPERM();
+ }
+ return unlink(".$f") ? 0 : -$!;
+}
@@ -203,3 +225,2 @@
sub daemonize {
- chdir("/") || die "can't chdir to /: $!";
open(STDIN, "< /dev/null") || die "can't read /dev/null: $!";
@@ -236,2 +257,3 @@
+chdir($mountpoint) or die("chdir: $!");
daemonize();
@@ -239,3 +261,3 @@
Fuse::main(
- 'mountpoint' => $mountpoint,
+ 'mountpoint' => '.',
'getattr' => 'main::x_getattr',
rmhiçrm -i:> -i istemi önce her kaldırma veya> -I üçten fazla dosyaları kaldırarak veya yinelemeli çıkartırken önce bir kez istemi. Çoğu hataya karşı koruma sağlarken -i'den daha az müdahaleci olabilir. Başka bayraklara sahip olanları istediğiniz zaman yazabilirsiniz.