package Storage::Bundle; use strict; use POSIX; use Logging; use Symbol; sub new { my $self = {}; bless($self, shift); return $self if $self->_init(@_); } # # Common options: # # 'user' - absence implies 'root' # sub _init { my ($self, %options) = @_; $self->{user} = $options{user} if defined $options{user}; $self->{sysuser} = $options{sysuser} if defined $options{sysuser}; $self->{srcdir} = $options{directory} if $options{directory}; return 1; } # # Returns the file handle object producing the bundle' data # sub run { my ($self) = @_; chdir $self->{srcdir}; my $cmd = $self->commandLine(); Logging::info("Executing bundle producer: '" . $cmd . "' in " . $self->{srcdir}); if ($self->{user}) { my $from_child = gensym(); my $to_parent = gensym(); pipe($from_child, $to_parent); my $pid = fork(); if ($pid) { close($to_parent); $self->{pid} = $pid; $self->{channel} = $from_child; waitpid($self->{pid}, 0); return ($from_child, $? >> 8); } else { close($from_child); local $SIG{'PIPE'} = 'DEFAULT' if !$SIG{'PIPE'} or $SIG{'PIPE'} eq 'IGNORE'; my $cmd_handle = gensym(); open($cmd_handle, "$cmd |"); while (<$cmd_handle>) { print $to_parent $_; } close($cmd_handle); close($to_parent); POSIX::_exit($? >> 8); } } else { local $SIG{'PIPE'} = 'DEFAULT' if !$SIG{'PIPE'} or $SIG{'PIPE'} eq 'IGNORE'; my $cmd_handle = gensym(); open($cmd_handle, "$cmd |"); $self->{channel} = $cmd_handle; return ($cmd_handle, $? >> 8); } } # # Cleans up all leftovers after run() # sub cleanup { my ($self) = @_; close($self->{channel}) if exists $self->{channel}; waitpid($self->{pid}, 0) if exists $self->{pid}; } # -- Factory -- # # Additional options: # # 'directory' - directory to archive - mandatory # 'follow_symlinks' - archive the files symlink pointed to, not the symlinks # 'include' - list of files to include in archive. # 'exclude' - list of files to exclude from archive. # sub createTarBundle { require Storage::TarBundle; return Storage::TarBundle->new(@_); } # # Additional options: see Db::Connection::getConnection() # sub createDbBundle { my %options = @_; if ($options{'type'} eq 'postgresql') { require Storage::PostgresqlDbBundle; return Storage::PostgresqlDbBundle->new(@_); } else { require Storage::DbBundle; return Storage::DbBundle->new(@_); } } 1;