Đây là cách rm -rf dirhoạt động:
- Nó mở
dir , và liệt kê nội dung của nó.
- Đối với mỗi mục, nếu đó là một thư mục, hãy lặp lại quy trình tương tự cho nó, nếu không, hãy gọi
unlinknó.
Nếu bạn có thể, đối với danh sách thư mục, trước tiên hãy trả lại tên tệp đặc biệt và nếu bạn có thể gây ra quá trình thực hiện unlink trên tệp đó bị chết, điều đó sẽ giải quyết vấn đề. Điều đó có thể được thực hiện bằng cách sử dụng một hệ thống tập tin cầu chì.
Chẳng hạn, bạn có thể điều chỉnh loopback.plví dụ từ mô-đun Fuse perl , chỉ thực hiện một hệ thống tập tin giả chỉ là một hệ thống tập tin thực bên dưới như vậy (xem thêm bản vá bên dưới):
- khi liệt kê một thư mục, nếu nó chứa một mục có tên
.{{do-not-delete}}., hãy thêm vào danh sách các mục có hai tệp: .{{do-not-delete}}!errorvà.{{do-not-delete}}!kill
- Khi cố gắng
unlinkđầu tiên, trả lại EPERMmã đểrm hiển thị thông báo lỗi
- Khi cố gắng đến
unlinkcái thứ hai, quá trình bị giết.
$ 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
Đây là một bản vá để áp dụng trên loopback.plví dụ đó như một bằng chứng về khái niệm:
--- 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',
rmđểrm -i:> -i nhắc trước mỗi loại bỏ hoặc> -Tôi nhắc một lần trước khi tháo hơn ba tác phẩm, hoặc khi loại bỏ đệ quy. Ít xâm phạm hơn -i, trong khi vẫn bảo vệ chống lại hầu hết các lỗi Bạn có thể ghi lại những điều đó bằng các cờ khác bất cứ lúc nào.