blob: d88307eaecc0d3248e7b7ec8fa2df7f10fbda966 (
plain)
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
76
77
78
79
80
81
82
83
84
85
|
#!/usr/bin/perl -w
use strict;
use File::Path qw(rmtree);
use POSIX ();
sub _untaint_path
{
my ($path) = @_;
if ($path =~ /^(.*)$/) {
return $1;
}
die "bad path";
}
sub _create_snapshot
{
my ($base_path) = _untaint_path(shift);
my $time_str = POSIX::strftime("%Y.%m.%d-%H.%M.%S" , localtime());
my $snap_path = $base_path . "/.snapshots/\@GMT-" . $time_str;
my $ret;
delete @ENV{'BASH_ENV'};
$ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH
POSIX::mkdir($base_path . "/.snapshots", 0755);
# add trailing slash to src path to ensure that only contents is copied
$ret = system("rsync", "-a", "--exclude=.snapshots/", "${base_path}/",
$snap_path);
if ($ret != 0) {
print STDERR "rsync failed with $ret\n";
} else {
print "$snap_path\n";
}
return $ret;
}
sub _delete_snapshot
{
my $base_path = _untaint_path(shift);
my $snap_path = _untaint_path(shift);
# we're doing a recursive delete, so do some sanity checks
if ((index($snap_path, $base_path) != 0) || (index($snap_path, ".snapshots") == -1)) {
print STDERR "invalid snap_path: $snap_path\n";
return -1;
}
$ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH
rmtree($snap_path, {error => \my $err});
if (@$err) {
for my $diag (@$err) {
my ($file, $message) = %$diag;
if ($file eq '') {
print STDERR "rmtree error: $message\n";
} else {
print STDERR "rmtree error $file: $message\n";
}
}
return -1;
}
return 0;
}
my $ret;
my $num_args = $#ARGV + 1;
my $cmd = shift;
if (($num_args == 2) && ($cmd eq "--check")) {
$ret = 0;
} elsif (($num_args == 2) && ($cmd eq "--create")) {
$ret = _create_snapshot($ARGV[0]);
} elsif (($num_args == 3) && ($cmd eq "--delete")) {
$ret = _delete_snapshot($ARGV[0], $ARGV[1]);
} else {
print STDERR "invalid script argument\n";
$ret = -1;
}
exit $ret;
|