এখানে কীভাবে rm -rf dir
কাজ করে:
- এটি খোলে
dir
এবং এর সামগ্রী তালিকাভুক্ত করে।
- প্রতিটি প্রবেশের জন্য, যদি এটি ডিরেক্টরি থাকে তবে এর জন্য একই প্রক্রিয়াটি পুনরাবৃত্তি করুন, যদি তা না হয় তবে এটিতে কল
unlink
করুন।
যদি আপনি, ডিরেক্টরি তালিকার জন্য, প্রথমে একটি বিশেষ ফাইলের নামটি ফিরিয়ে দিতে পারেন, এবং যদি আপনি unlink
সেই ফাইলটিতে কোনও প্রক্রিয়াটি মারা যাওয়ার কারণ হতে পারেন তবে সমস্যার সমাধান হবে। এটি একটি ফিউজ ফাইল সিস্টেম ব্যবহার করে করা যেতে পারে।
উদাহরণস্বরূপ, আপনি পার্ল ফিউজ মডিউল থেকে loopback.pl
উদাহরণটি রূপান্তর করতে পারেন যা কেবল মাত্র একটি ডামি ফাইল সিস্টেম প্রয়োগ করে যা নীচের একটি বাস্তব ফাইল সিস্টেমের কাছে কেবল একটি পাস-থ্রো (নীচে প্যাচও দেখুন):
- ডিরেক্টরি তালিকাভুক্ত করার সময়, যদি এতে একটি এনট্রি নামের অন্তর্ভুক্ত থাকে তবে
.{{do-not-delete}}.
দুটি ফাইল সহ এন্ট্রিগুলির তালিকাটি পূর্বে যুক্ত করুন: .{{do-not-delete}}!error
এবং.{{do-not-delete}}!kill
unlink
প্রথমটির চেষ্টা করার সময়, EPERM
কোডটি ফিরিয়ে দিন যাতে rm
কোনও ত্রুটি বার্তা প্রদর্শিত হয়
unlink
দ্বিতীয়টির চেষ্টা করার পরে, প্রক্রিয়াটি মারা যায়।
$ 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
ধারণার প্রমাণ হিসাবে সেই loopback.pl
উদাহরণের উপরে প্রয়োগ করার জন্য এখানে একটি প্যাচ রয়েছে :
--- 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 এর চেয়ে কম কন্ট্রোসিভ, তবুও বেশিরভাগ ভুলের বিরুদ্ধে সুরক্ষা দেওয়ার সময় আপনি যে কোনও সময় অন্য পতাকাগুলি দিয়ে চালিত করতে পারেন।