X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=lib%2FBackupPC%2FLib.pm;h=faa66b187698a482988ae7df56fa01a472925a54;hp=1e430cae0451d9bee8867f1e39987ed66669543e;hb=e4bf7ab080e172b74b3d64c196a72d0ff5d315c5;hpb=17dcbbebb871212f90b81bb97f8d1feb528bdc43 diff --git a/lib/BackupPC/Lib.pm b/lib/BackupPC/Lib.pm index 1e430ca..faa66b1 100644 --- a/lib/BackupPC/Lib.pm +++ b/lib/BackupPC/Lib.pm @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 2.1.0, released 20 Jun 2004. +# Version 3.0.0beta3, released 3 Dec 2006. # # See http://backuppc.sourceforge.net. # @@ -54,23 +54,51 @@ use Config; sub new { my $class = shift; - my($topDir, $installDir, $noUserCheck) = @_; + my($topDir, $installDir, $confDir, $noUserCheck) = @_; - my $paths = { - TopDir => $topDir || '/data/BackupPC', - BinDir => $installDir || '/usr/local/BackupPC', - LibDir => $installDir || '/usr/local/BackupPC', - }; - $paths->{BinDir} .= "/bin"; - $paths->{LibDir} .= "/lib"; + # + # Whether to use filesystem hierarchy standard for file layout. + # If set, text config files are below /etc/BackupPC. + # + my $useFHS = 0; + my $paths; - $paths->{storage} = BackupPC::Storage->new($paths); + # + # Set defaults for $topDir and $installDir. + # + $topDir = '/tera0/backup/BackupPC' if ( $topDir eq "" ); + $installDir = '/usr/local/BackupPC' if ( $installDir eq "" ); + + # + # Pick some initial defaults. For FHS the only critical + # path is the ConfDir, since we get everything else out + # of the main config file. + # + if ( $useFHS ) { + $paths = { + useFHS => $useFHS, + TopDir => $topDir, + InstallDir => $installDir, + ConfDir => $confDir eq "" ? '/etc/BackupPC' : $confDir, + LogDir => '/var/log/BackupPC', + }; + } else { + $paths = { + useFHS => $useFHS, + TopDir => $topDir, + InstallDir => $installDir, + ConfDir => $confDir eq "" ? "$topDir/conf" : $confDir, + LogDir => "$topDir/log", + }; + } my $bpc = bless { %$paths, - Version => '2.1.0', + Version => '3.0.0beta3', }, $class; + $bpc->{storage} = BackupPC::Storage->new($paths); + # # Clean up %ENV and setup other variables. # @@ -82,14 +110,24 @@ sub new return; } + # + # Update the paths based on the config file + # + foreach my $dir ( qw(TopDir ConfDir InstallDir LogDir) ) { + next if ( $bpc->{Conf}{$dir} eq "" ); + $paths->{$dir} = $bpc->{$dir} = $bpc->{Conf}{$dir}; + } + $bpc->{storage}->setPaths($paths); + # # Verify we are running as the correct user # if ( !$noUserCheck && $bpc->{Conf}{BackupPCUserVerify} && $> != (my $uid = (getpwnam($bpc->{Conf}{BackupPCUser}))[2]) ) { - print(STDERR "Wrong user: my userid is $>, instead of $uid" + print(STDERR "$0: Wrong user: my userid is $>, instead of $uid" . " ($bpc->{Conf}{BackupPCUser})\n"); + print(STDERR "Please su $bpc->{Conf}{BackupPCUser} first\n"); return; } return $bpc; @@ -104,7 +142,37 @@ sub TopDir sub BinDir { my($bpc) = @_; - return $bpc->{BinDir}; + return "$bpc->{InstallDir}/bin"; +} + +sub LogDir +{ + my($bpc) = @_; + return $bpc->{LogDir}; +} + +sub ConfDir +{ + my($bpc) = @_; + return $bpc->{ConfDir}; +} + +sub LibDir +{ + my($bpc) = @_; + return "$bpc->{InstallDir}/lib"; +} + +sub InstallDir +{ + my($bpc) = @_; + return $bpc->{InstallDir}; +} + +sub useFHS +{ + my($bpc) = @_; + return $bpc->{useFHS}; } sub Version @@ -284,7 +352,7 @@ sub ConfigRead # Load language file # return "No language setting" if ( !defined($bpc->{Conf}{Language}) ); - my $langFile = "$bpc->{LibDir}/BackupPC/Lang/$bpc->{Conf}{Language}.pm"; + my $langFile = "$bpc->{InstallDir}/lib/BackupPC/Lang/$bpc->{Conf}{Language}.pm"; if ( !defined($ret = do $langFile) && ($! || $@) ) { $mesg = "Couldn't open language file $langFile: $!" if ( $! ); $mesg = "Couldn't execute language file $langFile: $@" if ( $@ ); @@ -319,6 +387,13 @@ sub HostInfoRead return $bpc->{storage}->HostInfoRead($host); } +sub HostInfoWrite +{ + my($bpc, $host) = @_; + + return $bpc->{storage}->HostInfoWrite($host); +} + # # Return the mtime of the hosts file # @@ -441,7 +516,7 @@ sub ServerConnect # # First try the unix-domain socket # - my $sockFile = "$bpc->{TopDir}/log/BackupPC.sock"; + my $sockFile = "$bpc->{LogDir}/BackupPC.sock"; socket(*FH, PF_UNIX, SOCK_STREAM, 0) || return "unix socket: $!"; if ( !connect(*FH, sockaddr_un($sockFile)) ) { my $err = "unix connect: $!"; @@ -1033,6 +1108,7 @@ sub cmdSystemOrEvalLong my($pid, $out, $allOut); local(*CHILD); + $? = 0; if ( (ref($cmd) eq "ARRAY" ? $cmd->[0] : $cmd) =~ /^\&/ ) { $cmd = join(" ", $cmd) if ( ref($cmd) eq "ARRAY" ); print(STDERR "cmdSystemOrEval: about to eval perl code $cmd\n") @@ -1111,10 +1187,9 @@ sub cmdSystemOrEval return $bpc->cmdSystemOrEvalLong($cmd, $stdoutCB, 0, undef, @args); } - # # Promotes $conf->{BackupFilesOnly}, $conf->{BackupFilesExclude} -# to hashes and $conf->{$shareName} to an array +# to hashes and $conf->{$shareName} to an array. # sub backupFileConfFix { @@ -1123,11 +1198,87 @@ sub backupFileConfFix $conf->{$shareName} = [ $conf->{$shareName} ] if ( ref($conf->{$shareName}) ne "ARRAY" ); foreach my $param qw(BackupFilesOnly BackupFilesExclude) { - next if ( !defined($conf->{$param}) || ref($conf->{$param}) eq "HASH" ); - $conf->{$param} = [ $conf->{$param} ] - if ( ref($conf->{$param}) ne "ARRAY" ); - $conf->{$param} = { map { $_ => $conf->{$param} } @{$conf->{$shareName}} }; + next if ( !defined($conf->{$param}) ); + if ( ref($conf->{$param}) eq "HASH" ) { + # + # A "*" entry means wildcard - it is the default for + # all shares. Replicate the "*" entry for all shares, + # but still allow override of specific entries. + # + next if ( !defined($conf->{$param}{"*"}) ); + $conf->{$param} = { + map({ $_ => $conf->{$param}{"*"} } + @{$conf->{$shareName}}), + %{$conf->{$param}} + }; + } else { + $conf->{$param} = [ $conf->{$param} ] + if ( ref($conf->{$param}) ne "ARRAY" ); + $conf->{$param} = { map { $_ => $conf->{$param} } + @{$conf->{$shareName}} }; + } + } +} + +# +# This is sort() compare function, used below. +# +# New client LOG names are LOG.MMYYYY. Old style names are +# LOG, LOG.0, LOG.1 etc. Sort them so new names are +# first, and newest to oldest. +# +sub compareLOGName +{ + my $na = $1 if ( $a =~ /LOG\.(\d+)(\.z)?$/ ); + my $nb = $1 if ( $b =~ /LOG\.(\d+)(\.z)?$/ ); + + $na = -1 if ( !defined($na) ); + $nb = -1 if ( !defined($nb) ); + + if ( length($na) >= 5 && length($nb) >= 5 ) { + # + # Both new style: format is MMYYYY. Bigger dates are + # more recent. + # + my $ma = $2 * 12 + $1 if ( $na =~ /(\d+)(\d{4})/ ); + my $mb = $2 * 12 + $1 if ( $nb =~ /(\d+)(\d{4})/ ); + return $mb - $ma; + } elsif ( length($na) >= 5 && length($nb) < 5 ) { + return -1; + } elsif ( length($na) < 5 && length($nb) >= 5 ) { + return 1; + } else { + # + # Both old style. Smaller numbers are more recent. + # + return $na - $nb; + } +} + +# +# Returns list of paths to a clients's (or main) LOG files, +# most recent first. +# +sub sortedPCLogFiles +{ + my($bpc, $host) = @_; + + my(@files, $dir); + + if ( $host ne "" ) { + $dir = "$bpc->{TopDir}/pc/$host"; + } else { + $dir = "$bpc->{LogDir}"; + } + if ( opendir(DIR, $dir) ) { + foreach my $file ( readdir(DIR) ) { + next if ( !-f "$dir/$file" ); + next if ( $file ne "LOG" && $file !~ /^LOG\.\d/ ); + push(@files, "$dir/$file"); + } + closedir(DIR); } + return sort(compareLOGName @files); } 1;