-
Notifications
You must be signed in to change notification settings - Fork 13
/
harden-ln
executable file
·75 lines (59 loc) · 1.62 KB
/
harden-ln
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/perl
#
# Reads symlinks from @ARGV and/or STDIN
# and converts them to hard links.
#
use strict;
use warnings;
use Cwd;
use File::Basename;
use File::Copy;
use Getopt::Long;
(my $me = $0) =~ s,.*/,,;
my %opts;
GetOptions(\%opts, 'help|h', 'test|t', 'copy|c') or usage();
usage() if $opts{help};
sub usage {
die <<EOUSAGE;
Usage: $me [options] [symlink1 [symlink 2 ...] | [ < symlink-file ] ]
Options:
-t, --test See what would have happened.
-c, --copy Make copies instead of hard links.
Takes a list of symlinks from arguments and/or STDIN (one per line)
and converts them to hard links or copies.
EOUSAGE
}
my @links = @ARGV;
if (! @ARGV && ! -t 0) {
while (<STDIN>) {
chomp;
s/^\s+//;
s/\s+$//;
push @links, $_;
}
}
my $start_dir = cwd();
harden($_) foreach @links;
sub harden {
my ($link) = @_;
chdir($start_dir) or die "chdir($start_dir) failed: $!\n";
unless (-l $link) {
warn "$link not a symlink; skipping.\n";
return;
}
my $dest = readlink $link or die "$me: readlink($link): $!\n";
if ($opts{test}) {
print "Would ", $opts{copy} ? 'copy' : 'harden', " $link\n";
return;
}
unlink $link or die "$me: unlink($link): $!\n";
my $link_dir = dirname($link);
my $link_file = basename($link);
chdir($link_dir) or die "chdir($link_dir) failed: $!\n";
return if $opts{copy} ? copy($dest, $link_file) : link($dest, $link_file);
warn "$me: ", $opts{copy} ? 'copy' : 'link',
"($dest, $link) failed: $!\n";
symlink($dest, $link_file)
or warn "$me: WARNING! Couldn't restore symlink $link -> $dest ",
"after hardening failed ($!)\n";
}