Brackup
view release on metacpan or search on metacpan
lib/Brackup/Backup.pm view on Meta::CPAN
# Reopen $metafh to reset file pointer (no backward seek with IO::Compress::Gzip)
open($store_fh, $backup_file) or die "Failed to open metafile '$backup_file': $!\n";
$store_filename = $backup_file;
}
# store it on the target
$self->debug("Storing metafile to " . ref($target));
my $name = $self->{root}->publicname . "-" . $self->backup_time;
$target->store_backup_meta($name, $store_fh, { filename => $store_filename, is_encrypted => $is_encrypted });
$stats->timestamp('Metafile Storage');
# cleanup encrypted metafile
if ($is_encrypted) {
close $store_fh or die "Close on encrypted metafile failed: $!";
unlink $store_filename;
}
}
$self->report_progress(100, "Backup complete.");
return $stats;
}
sub default_file_mode {
my $self = shift;
return $self->{_def_file_mode} ||= $self->_default_mode('f');
}
sub default_directory_mode {
my $self = shift;
return $self->{_def_dir_mode} ||= $self->_default_mode('d');
}
sub _default_mode {
my ($self, $type) = @_;
my $map = $self->{modecounts}{$type} || {};
return (sort { $map->{$b} <=> $map->{$a} } keys %$map)[0];
}
sub default_uid {
my $self = shift;
return $self->{_def_uid} ||= $self->_default_id('u');
}
sub default_gid {
my $self = shift;
return $self->{_def_gid} ||= $self->_default_id('g');
}
sub _default_id {
my ($self, $type) = @_;
my $map = $self->{idcounts}{$type} || {};
return (sort { $map->{$b} <=> $map->{$a} } keys %$map)[0];
}
# space-separated list of local uid:username mappings
sub uid_map {
my $self = shift;
my @map;
my $uidcounts = $self->{idcounts}{u};
for my $uid (sort { $a <=> $b } keys %$uidcounts) {
if (my $name = getpwuid($uid)) {
push @map, "$uid:$name";
}
}
return join(' ', @map);
}
# space-separated list of local gid:group mappings
sub gid_map {
my $self = shift;
my @map;
my $gidcounts = $self->{idcounts}{g};
for my $gid (sort { $a <=> $b } keys %$gidcounts) {
if (my $name = getgrgid($gid)) {
push @map, "$gid:$name";
}
}
return join(' ', @map);
}
sub backup_time {
my $self = shift;
return $self->{backup_time} ||= time();
}
sub backup_header {
my $self = shift;
my $ret = "";
my $now = $self->backup_time;
$ret .= "BackupTime: " . $now . " (" . localtime($now) . ")\n";
$ret .= "BackupDriver: " . ref($self->{target}) . "\n";
if (my $fields = $self->{target}->backup_header) {
foreach my $k (sort keys %$fields) {
die "Bogus header field from driver" unless $k =~ /^\w+$/;
my $val = $fields->{$k};
next if ! defined $val || $val eq ''; # skip keys with empty values
die "Bogus header value from driver" if $val =~ /[\r\n]/;
$ret .= "Driver-$k: $val\n";
}
}
$ret .= "RootName: " . $self->{root}->name . "\n";
$ret .= "RootPath: " . $self->{root}->path . "\n";
$ret .= "TargetName: " . $self->{target}->name . "\n";
$ret .= "DefaultFileMode: " . $self->default_file_mode . "\n";
$ret .= "DefaultDirMode: " . $self->default_directory_mode . "\n";
$ret .= "DefaultUID: " . $self->default_uid . "\n";
$ret .= "DefaultGID: " . $self->default_gid . "\n";
$ret .= "UIDMap: " . $self->uid_map . "\n";
$ret .= "GIDMap: " . $self->gid_map . "\n";
$ret .= "GPG-Recipient: $_\n" for $self->{root}->gpg_rcpts;
$ret .= "\n";
return $ret;
}
sub record_mode_ids {
my ($self, $file) = @_;
$self->{modecounts}{$file->type}{$file->mode}++;
$self->{idcounts}{u}{$file->uid}++;
$self->{idcounts}{g}{$file->gid}++;
}
( run in 1.735 second using v1.01-cache-2.11-cpan-99c4e6809bf )