[Bps-public-commit] brackup branch, master, updated. 5445cb3c0d21c9555b579fd929eef3043e3c1418
Alex Vandiver
alexmv at bestpractical.com
Tue Jul 13 12:11:03 EDT 2010
The branch, master has been updated
via 5445cb3c0d21c9555b579fd929eef3043e3c1418 (commit)
via 7ace239840d42d2dbeffc58637b6717c7823a918 (commit)
via 22041bee9cf6de030e7142410079ed225620b86d (commit)
via 3702e3fe92e6d4e27b072226b722bd2f897f6cc7 (commit)
via ea7fbbee27340493436bd062f3a7110be92bcf35 (commit)
from 46ed50e51fe0ece61e30b79d68d11fa073388f10 (commit)
Summary of changes:
Changes | 3 ++
brackup | 20 +++++++++++++
lib/Brackup/Backup.pm | 56 +++++++++++++++++++++++++++++++++++-
lib/Brackup/Config.pm | 10 ++++++
lib/Brackup/File.pm | 19 ++++++++++++
lib/Brackup/Restore.pm | 74 ++++++++++++++++++++++++++++++++++++++++++++++--
6 files changed, 177 insertions(+), 5 deletions(-)
- Log -----------------------------------------------------------------
commit ea7fbbee27340493436bd062f3a7110be92bcf35
Author: gavin at openfusion.com.au <gavin at openfusion.com.au@c3152786-d43a-0410-8499-09eb43983aed>
Date: Tue Jun 1 19:11:38 2010 +0000
Add --list-sources and --list-targets options to brackup.
git-svn-id: http://brackup.googlecode.com/svn/trunk@314 c3152786-d43a-0410-8499-09eb43983aed
diff --git a/brackup b/brackup
index 03501dc..45e0274 100755
--- a/brackup
+++ b/brackup
@@ -58,6 +58,14 @@ Produces output suitable for piping into C<zenity --progress> to get a
pretty GUI progress bar while running a backup. This option is
incompatable with C<--verbose>, as both print to STDOUT.
+=item --list-sources
+
+List the names of the sources defined in your configuration file.
+
+=item --list-targets
+
+List the names of the targets defined in your configuration file.
+
=back
=head1 WARRANTY
@@ -104,6 +112,7 @@ my $opt_dryrun;
my $opt_verbose;
my $opt_du_stats;
my $opt_zenityprogress;
+my ($opt_list_sources, $opt_list_targets);
my $config_file = Brackup::Config->default_config_file_name;
my $arguments = join(' ', @ARGV);
@@ -120,6 +129,8 @@ usage() unless
'dry-run' => \$opt_dryrun,
'du-stats' => \$opt_du_stats,
'config=s' => \$config_file,
+ 'list-sources' => \$opt_list_sources,
+ 'list-targets' => \$opt_list_targets,
);
usage() if @ARGV;
@@ -143,6 +154,15 @@ if ($opt_du_stats && $src_name) {
exit 0;
}
+if ($opt_list_sources) {
+ print join("\n", $config->list_sources), "\n";
+ exit 0;
+}
+if ($opt_list_targets) {
+ print join("\n", $config->list_targets), "\n";
+ exit 0;
+}
+
usage() unless $src_name && $target_name;
my $cwd = getcwd();
diff --git a/lib/Brackup/Config.pm b/lib/Brackup/Config.pm
index dc80f1f..d7486d8 100644
--- a/lib/Brackup/Config.pm
+++ b/lib/Brackup/Config.pm
@@ -164,6 +164,16 @@ sub load_root {
return $root;
}
+sub list_sources {
+ my ($self) = @_;
+ return sort map { s/^SOURCE://; $_ } grep(/^SOURCE:/, keys %$self);
+}
+
+sub list_targets {
+ my ($self) = @_;
+ return sort map { s/^TARGET://; $_ } grep(/^TARGET:/, keys %$self);
+}
+
sub load_target {
my ($self, $name) = @_;
my $confsec = $self->{"TARGET:$name"} or
commit 3702e3fe92e6d4e27b072226b722bd2f897f6cc7
Author: gavin at openfusion.com.au <gavin at openfusion.com.au@c3152786-d43a-0410-8499-09eb43983aed>
Date: Fri Jun 4 16:03:25 2010 +0000
Update Brackup::Backup and Brackup::File to capture user/group info in metafile.
git-svn-id: http://brackup.googlecode.com/svn/trunk@315 c3152786-d43a-0410-8499-09eb43983aed
diff --git a/lib/Brackup/Backup.pm b/lib/Brackup/Backup.pm
index f6c78a8..3f8fe22 100644
--- a/lib/Brackup/Backup.pm
+++ b/lib/Brackup/Backup.pm
@@ -22,6 +22,10 @@ sub new {
$self->{zenityprogress} = delete $opts{zenityprogress}; # bool
$self->{modecounts} = {}; # type -> mode(octal) -> count
+ $self->{idcounts} = {}; # type -> uid/gid -> count
+
+ $self->{_uid_map} = {}; # uid -> username
+ $self->{_gid_map} = {}; # gid -> group
$self->{saved_files} = []; # list of Brackup::File objects backed up
$self->{unflushed_files} = []; # list of Brackup::File objects not in backup_file
@@ -60,7 +64,7 @@ sub backup {
$root->foreach_file(sub {
my ($file) = @_; # a Brackup::File
push @files, $file;
- $self->record_mode($file);
+ $self->record_mode_ids($file);
$n_files++;
$n_kb += $file->size / 1024;
});
@@ -342,6 +346,48 @@ sub _default_mode {
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();
@@ -367,14 +413,20 @@ sub backup_header {
$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 {
+sub record_mode_ids {
my ($self, $file) = @_;
$self->{modecounts}{$file->type}{$file->mode}++;
+ $self->{idcounts}{u}{$file->uid}++;
+ $self->{idcounts}{g}{$file->gid}++;
}
sub add_unflushed_file {
diff --git a/lib/Brackup/File.pm b/lib/Brackup/File.pm
index 196a2c8..a6ad2de 100644
--- a/lib/Brackup/File.pm
+++ b/lib/Brackup/File.pm
@@ -188,6 +188,16 @@ sub mode {
return sprintf('%#o', $self->stat->mode & 0777);
}
+sub uid {
+ my $self = shift;
+ return $self->stat->uid;
+}
+
+sub gid {
+ my $self = shift;
+ return $self->stat->gid;
+}
+
sub as_rfc822 {
my ($self, $schunk_list, $backup) = @_;
my $ret = "";
@@ -223,6 +233,15 @@ sub as_rfc822 {
}
}
+ my $uid = $self->uid;
+ unless ($uid eq $backup->default_uid) {
+ $set->("UID", $uid);
+ }
+ my $gid = $self->gid;
+ unless ($gid eq $backup->default_gid) {
+ $set->("GID", $gid);
+ }
+
return $ret . "\n";
}
commit 22041bee9cf6de030e7142410079ed225620b86d
Author: gavin at openfusion.com.au <gavin at openfusion.com.au@c3152786-d43a-0410-8499-09eb43983aed>
Date: Fri Jun 4 16:06:22 2010 +0000
Update Brackup::Restore to chown restored files using metafile user/group info.
git-svn-id: http://brackup.googlecode.com/svn/trunk@316 c3152786-d43a-0410-8499-09eb43983aed
diff --git a/lib/Brackup/Restore.pm b/lib/Brackup/Restore.pm
index c51cbdc..3b8ab48 100644
--- a/lib/Brackup/Restore.pm
+++ b/lib/Brackup/Restore.pm
@@ -19,6 +19,9 @@ sub new {
$self->{config} = delete $opts{config}; # brackup config (if available)
$self->{verbose} = delete $opts{verbose};
+ $self->{_local_uid_map} = {}; # remote/metafile uid -> local uid
+ $self->{_local_gid_map} = {}; # remote/metafile gid -> local gid
+
$self->{prefix} =~ s/\/$// if $self->{prefix};
$self->{_stats_to_run} = []; # stack (push/pop) of subrefs to reset stat info on
@@ -120,15 +123,18 @@ sub restore {
my $full = $self->{to} . "/" . $path;
my $full_escaped = $self->{to} . "/" . $path_escaped_stripped;
- # restore default modes from header
- $it->{Mode} ||= $meta->{DefaultFileMode} if $type eq "f";
- $it->{Mode} ||= $meta->{DefaultDirMode} if $type eq "d";
+ # restore default modes/user/group from header
+ $it->{Mode} ||= ($type eq 'd' ? $meta->{DefaultDirMode} : $meta->{DefaultFileMode});
+ $it->{UID} ||= $meta->{DefaultUID};
+ $it->{GID} ||= $meta->{DefaultGID};
warn " * restoring $path_escaped to $full_escaped\n" if $self->{verbose};
$self->_restore_link ($full, $it) if $type eq "l";
$self->_restore_directory($full, $it) if $type eq "d";
$self->_restore_fifo ($full, $it) if $type eq "p";
$self->_restore_file ($full, $it) if $type eq "f";
+
+ $self->_chown($full, $it, $type, $meta) if $it->{UID} || $it->{GID};
}
# clear chunk cached by _restore_file
@@ -146,6 +152,68 @@ sub restore {
}
}
+sub _lookup_remote_uid {
+ my ($self, $remote_uid, $meta) = @_;
+
+ return $self->{_local_uid_map}->{$remote_uid}
+ if defined $self->{_local_uid_map}->{$remote_uid};
+
+ # meta remote user map - remote_uid => remote username
+ $self->{_remote_user_map} ||= { map { split /:/, $_, 2 } split /\s+/, $meta->{UIDMap} };
+
+ # try and lookup local uid using remote username
+ if (my $remote_user = $self->{_remote_user_map}->{$remote_uid}) {
+ my $local_uid = getpwnam($remote_user);
+ return $self->{_local_uid_map}->{$remote_uid} = $local_uid
+ if defined $local_uid;
+ }
+
+ # if remote username missing locally, fallback to $remote_uid
+ return $self->{_local_uid_map}->{$remote_uid} = $remote_uid;
+}
+
+sub _lookup_remote_gid {
+ my ($self, $remote_gid, $meta) = @_;
+
+ return $self->{_local_gid_map}->{$remote_gid}
+ if defined $self->{_local_gid_map}->{$remote_gid};
+
+ # meta remote group map - remote_gid => remote group
+ $self->{_remote_group_map} ||= { map { split /:/, $_, 2 } split /\s+/, $meta->{GIDMap} };
+
+ # try and lookup local gid using remote group
+ if (my $remote_group = $self->{_remote_group_map}->{$remote_gid}) {
+ my $local_gid = getgrnam($remote_group);
+ return $self->{_local_gid_map}->{$remote_gid} = $local_gid
+ if defined $local_gid;
+ }
+
+ # if remote group missing locally, fallback to $remote_gid
+ return $self->{_local_gid_map}->{$remote_gid} = $remote_gid;
+}
+
+sub _chown {
+ my ($self, $full, $it, $type, $meta) = @_;
+
+ my $uid = $self->_lookup_remote_uid($it->{UID}, $meta) if $it->{UID};
+ my $gid = $self->_lookup_remote_gid($it->{GID}, $meta) if $it->{GID};
+
+ if ($type eq 'l') {
+ if (! defined $self->{_lchown}) {
+ no strict 'subs';
+ $self->{_lchown} = eval { require Lchown } && Lchown::LCHOWN_AVAILABLE;
+ }
+ if ($self->{_lchown}) {
+ Lchown::lchown($uid, -1, $full) if defined $uid;
+ Lchown::lchown(-1, $gid, $full) if defined $gid;
+ }
+ } else {
+ # ignore errors, but change uid and gid separately to sidestep unprivileged failures
+ chown $uid, -1, $full if defined $uid;
+ chown -1, $gid, $full if defined $gid;
+ }
+}
+
sub _update_statinfo {
my ($self, $full, $it) = @_;
commit 7ace239840d42d2dbeffc58637b6717c7823a918
Author: gavin at openfusion.com.au <gavin at openfusion.com.au@c3152786-d43a-0410-8499-09eb43983aed>
Date: Fri Jun 4 16:08:09 2010 +0000
Add ownership entry to Changes.
git-svn-id: http://brackup.googlecode.com/svn/trunk@317 c3152786-d43a-0410-8499-09eb43983aed
diff --git a/Changes b/Changes
index 1b49102..33df2f3 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,6 @@
+ - add uid/gid info to metafile, and use in restores (where possible)
+ (Gavin Carr)
+
- allow multiple gpg recipients to be specified, any can restore (Alex
Vandiver)
commit 5445cb3c0d21c9555b579fd929eef3043e3c1418
Merge: 46ed50e 7ace239
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Tue Jul 13 12:04:29 2010 -0400
Merge remote branch 'trunk'
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list