diff options
author | Pascal Rigaux <pixel@mandriva.com> | 2007-04-25 12:26:16 +0000 |
---|---|---|
committer | Pascal Rigaux <pixel@mandriva.com> | 2007-04-25 12:26:16 +0000 |
commit | 126777bc019a54afb4ec51299f2cf9d2841698aa (patch) | |
tree | 97f76e571902ead55ba138f1156a4b4f00b9b779 /perl-install/standalone/drakbackup | |
parent | f1f67448efc714873378dfeb8279fae68054a90a (diff) | |
download | drakx-126777bc019a54afb4ec51299f2cf9d2841698aa.tar drakx-126777bc019a54afb4ec51299f2cf9d2841698aa.tar.gz drakx-126777bc019a54afb4ec51299f2cf9d2841698aa.tar.bz2 drakx-126777bc019a54afb4ec51299f2cf9d2841698aa.tar.xz drakx-126777bc019a54afb4ec51299f2cf9d2841698aa.zip |
re-sync after the big svn loss
Diffstat (limited to 'perl-install/standalone/drakbackup')
-rwxr-xr-x | perl-install/standalone/drakbackup | 4580 |
1 files changed, 0 insertions, 4580 deletions
diff --git a/perl-install/standalone/drakbackup b/perl-install/standalone/drakbackup deleted file mode 100755 index f5365fd8a..000000000 --- a/perl-install/standalone/drakbackup +++ /dev/null @@ -1,4580 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (C) 2001,2002,2003,2004,2005 Mandriva by Sebastien DUPONT <dupont_s@epita.fr> -# Updated 2002-2005 by Stew Benedict <sbenedict@mandriva.com> -# Redistribution of this file is permitted under the terms of the GNU -# Public License (GPL) -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -use lib qw(/usr/lib/libDrakX); -use standalone; #- warning, standalone must be loaded very first, for 'explanations' -use strict; - -use interactive; -use common; -use detect_devices; -use POSIX; - -# Backend Options. -# make this global for status screen -my ($window1, $my_win); -my $central_widget; -my $previous_widget; -my $current_widget; -my $interactive; -my $up_box; -my $advanced_box; -my $box2; -my $cfg_file_exist = 0; -my @user_list_all; -my $DEBUG = 0; -my $restore_sys = 1; -my $restore_user = 1; -my $restore_other = 1; -my $restore_step_sys_date = ""; -my $restore_step_other_date = ""; -my @user_backuped; -my @sys_backuped; -my @other_backuped; -my @user_list_to_restore; -my @sys_list_to_restore; -my @other_list_to_restore; -my $button_box; -my $button_box_tmp; -my $next_widget; -my $system_state; -my $restore_state; -my $save_path_entry; -my $restore_find_path_entry; -my $new_path_entry; -my $pbar; -my $pbar1; -my $pbar2; -my $pbar3; -my $plabel; -my $plabel1; -my $plabel2; -my $plabel3; -my $stext; -my $list_model; -my $the_time; -my @user_list_to_restore2; -my $restore_path = "/"; -my $restore_other_path = 0; -my $restore_other_src; -my $path_to_find_restore; -my $other_media_hd; -my $backup_bef_restore = 0; -my $table; -my @user_list_backuped; -my @files_corrupted; -my %check_user_to_restore; -my $remove_user_before_restore = 0; -my @file_list_to_send_by_ftp; -my $results; -my @net_methods = ("ftp", "rsync", "ssh"); -my @media_types = ("hd", "cd", "tape"); -my %cd_devices; -my $std_device; -my @tape_devices; -my $in; -my @cron_entries; - -# config. FILES -> Default PATH & Global variables. -my @user_list; -my $cfg_dir = "/etc/drakxtools/drakbackup/"; -my $cfg_file = $cfg_dir . "drakbackup.conf"; -my $log_file = "/var/log/drakbackup"; -my $log_buff; -my $manual_user = 0; -my $backup_daemon = 0; -my $daemon = 0; -my $use_hd = 1; -my $custom_cron = 0; -my $session_offset = ''; -my $scp_port = 22; -my $user_home = $ENV{HOME}; -my $nonroot_user = 0; -my $media_problem = 0; -my $vol_name = 'Drakbackup'; -my $good_restore_path = 1; -my @no_devices = translate(N_("No device found")); -my %help; -my %conf; -my $time_string = "* * * * *"; -my $exec_string = "export USER=$ENV{USER}; /usr/sbin/drakbackup"; -my $profile_string; -my $redir_string = "--daemon > /dev/null 2>&1"; -my $ignore_files_list; -my @other_files; -my @sys_files = "/etc"; -my @files_for_direct_tape; -my $host_passwd; -my $index_cmd = "| tee "; - -# allow not-root user with own config -if ($ENV{USER} ne 'root' && $ENV{HOME} ne '/root') { - standalone::explanations("Running as $ENV{USER}..."); - #- does not get defined when run from cron - $user_home = "/home/$ENV{USER}" if $user_home eq ''; - @user_list = $ENV{USER}; - $cfg_dir = "$user_home/.drakbackup/"; - $conf{PATH_TO_SAVE} = $cfg_dir . "backups"; - $log_file = $cfg_dir . "drakbackup.log"; - $nonroot_user = 1; - $conf{NO_SYS_FILES} = 1; -} else { - $user_home = "/root"; - $conf{PATH_TO_SAVE} = "/var/lib/drakbackup"; -} -$cfg_file = $cfg_dir . "drakbackup.conf"; -my $backup_key = $user_home . "/.ssh/identity-drakbackup"; - -foreach (@ARGV) { - /--default/ and backend_mode(); - /--profile/ and set_profile($_); - /--daemon/ and daemon_mode(); - /--show-conf/ and show_conf(); - /--cd-info/ and get_cd_info(), exit(0); - /--debug/ and $DEBUG = 1, next; -} - -sub setup_tooltips() { - %help = ( - 'use_expect' => N("Expect is an extension to the TCL scripting language that allows interactive sessions without user intervention."), - 'remember_pass' => N("Store the password for this system in drakbackup configuration."), - 'erase_cdrw' => N("For a multisession CD, only the first session will erase the cdrw. Otherwise the cdrw is erased before each backup."), - 'use_incr_decr' => N("This option will save files that have changed. Exact behavior depends on whether incremental or differential mode is used."), - 'use_incremental' => N("Incremental backups only save files that have changed or are new since the last backup."), - 'use_differential' => N("Differential backups only save files that have changed or are new since the original 'base' backup."), - 'choose_archiver' => N("Star should be selected if you want to backup EA or ACLs, otherwise choose tar"), - 'send_mail_to' => N("This should be a local user or email address that you want the backup results sent to. You will need to define a functioning mail server. Multiple users can be in a comma seperated list"), - 'send_mail_from' => N("This should be the return address that you want the backup results sent from. Default is drakbackup."), - 'backupignore' => N("Files or wildcards listed in a .backupignore file at the top of a directory tree will not be backed up."), - 'delete_files' => N("For backups to other media, files are still created on the hard drive, then moved to the other media. Enabling this option will remove the hard drive tar files after the backup."), - 'view_log' => N("Selecting this option allows you to view the raw output from the restore process, after a file restore."), - 'dir_or_module' => N("Some protocols, like rsync, may be configured at the server end. Rather than using a directory path, you would use the 'module' name for the service path."), - 'when_space' => N("Custom allows you to specify your own day and time. The other options use run-parts in /etc/crontab."), - ); -} - -sub show_conf() { - print "DrakBackup configuration:\n\n"; - read_conf_file(); - system_state(); - print "$system_state\n"; - exit(0); -} - -sub backend_mode() { - build_backup_files(); - exit(0); -} - -sub set_profile { - my ($argn) = @_; - my $profile = $ARGV[$argn + 1]; - die "Usage: --profile <filename>...\n" if $profile =~ /^--/; - $profile .= ".conf" if $profile !~ /.conf/; - $cfg_file = $cfg_dir . $profile; - die "Profile $cfg_file not found...\n" if !-e $cfg_file; - return; -} - -sub daemon_mode() { - $daemon = 1; - build_backup_files(); - exit(0); -} - -if (check_for_xserver()) { - eval { require ugtk2 }; - die "Can not load ugtk2...\n" if $@; - ugtk2->import(qw(:create :dialogs :helpers :wrappers)); - interactive_mode(); -} else { - die "Can not run in console mode..."; -} - -sub set_help_tip { - my ($entry, $key) = @_; - gtkset_tip(Gtk2::Tooltips->new, $entry, formatAlaTeX($help{$key})); -} - -sub all_user_list() { - if ($nonroot_user) { - @user_list_all = $ENV{USER}; - return; - } - my $user; - my $uid; - @user_list_all = (); - - my @passwd = cat_("/etc/passwd"); - foreach (@passwd) { - ($user, $uid) = (split(/:/, $_))[0, 2]; - if ($uid >= 500 && $uid < 65000 || $uid == 0) { - push @user_list_all, $user; - } - } -} - -sub the_time() { - my ($sec, $min, $hour, $day, $month, $year) = localtime(time()); - sprintf("_%d%02d%02d_%02d%02d%02d", $year + 1900, $month + 1, $day, $hour, $min, $sec); -} - -sub get_tape_info() { - my @line_data; - my $info = "$ENV{HOME}/tmp/dmesg"; - @tape_devices = (); - system("dmesg -s 100000 | grep 'st[0-9] at' > $info"); - - my @info = cat_($info); - foreach (@info) { - @line_data = split(/[ \t,]+/, $_); - push @tape_devices, "/dev/" . $line_data[3]; - } - unlink($info); -} - -sub get_free_space { - my ($dir) = @_; - my $free = `df -P $dir | tail -1`; - my @line_data = split(/[ \t,]+/, $free); - my $free_space = int($line_data[3] / 1024); - return $free_space; -} - -sub check_storage_quota { - my ($dir) = @_; - my $used = `du -b $dir`; - my $used_space = $used / 1024 / 1024; - if ($used_space > $conf{MAX_SPACE}) { - return $used_space; - } else { - return 0; - } -} - -sub get_cd_info() { - my @line_data; - my @drive_names; - my $i; - # just trying load ide-cd, since it does not seem to be loaded by default - if (!-f "/proc/sys/dev/cdrom") { - $nonroot_user ? `cdrecord -scanbus -dev=ATA > /dev/null 2>&1` : `modprobe ide-cd`; - } - my @cd_info = cat_("/proc/sys/dev/cdrom/info"); - my %data = ( - "drive speed" => 'speed', - "Can change speed" => 'chg_speed', - "Can read multisession" => 'multisession', - "Can write CD-R" => 'cdr', - "Can write CD-RW" => 'cdrw', - "Can write DVD-R" => 'dvdr', - "Can write DVD-RAM" => 'dvdram' - ); - - my $cd_drives; - foreach (@cd_info) { - @line_data = split(/[:\t]+/, $_); - if ($line_data[0] =~ /drive name/) { - $cd_drives = @line_data-1; - chop($line_data[$cd_drives]); - @drive_names = @line_data; - print "drives: $cd_drives\n" unless $interactive; - } - chop($line_data[$cd_drives]) if $cd_drives; - foreach my $key (keys %data) { - if ($line_data[0] eq $key) { - for ($i = 1; $i <= $cd_drives; $i++) { - $cd_devices{$drive_names[$i]}{$data{$key}} = $line_data[$i]; - } - } - } - } - - #- now just report the data if we called --cd-info from the command line - foreach my $key (keys %cd_devices) { - my $rec_dev = $key; - my $prefix; - $rec_dev =~ s/sr/sg/; - $prefix = "ATAPI:" if $rec_dev =~ /hd/; - my $can_record = $cd_devices{$key}{cdr} || $cd_devices{$key}{cdrw} || $cd_devices{$key}{dvdr}; - $cd_devices{$key}{rec_dev} = $prefix . "/dev/" . $rec_dev if $can_record; - if (!$interactive) { - print "\n{$key}->{rec_dev} = $cd_devices{$key}{rec_dev}\n"; - print "{$key}->{speed} = $cd_devices{$key}{speed}\n"; - print "{$key}->{chg_speed} = $cd_devices{$key}{chg_speed}\n"; - print "{$key}->{multisession} = $cd_devices{$key}{multisession}\n"; - print "{$key}->{cdr} = $cd_devices{$key}{cdr}\n"; - print "{$key}->{cdrw} = $cd_devices{$key}{cdrw}\n"; - print "{$key}->{dvdr} = $cd_devices{$key}{dvdr}\n"; - print "{$key}->{dvdram} = $cd_devices{$key}{dvdram}\n"; - } else { - delete $cd_devices{$key} if $cd_devices{$key}{rec_dev} eq ''; - } - } -} - - -sub save_conf_file() { - write_password_file() if $conf{NET_PROTO} eq 'rsync' && $conf{PASSWD}; - return 1 if $conf{SEND_MAIL} && verify_mail_setup(); - #- do not save this, but retain it for this session - if ($conf{REMEMBER_PASS} != 1) { - $host_passwd = $conf{PASSWD}; - $conf{PASSWD} = undef; - } - if ($backup_daemon && $conf{DAEMON_MEDIA} eq '') { - show_warning("f", N("No media selected for cron operation.")); - return 1; - } - if ($backup_daemon && $conf{DAEMON_TIME_SPACE} eq '') { - show_warning("f", N("No interval selected for cron operation.")); - return 1; - } - if (!$backup_daemon) { - $conf{DAEMON_TIME_SPACE} = ""; - $conf{DAEMON_MEDIA} = ""; - } - $conf{NO_USER_FILES} = '' if @user_list == (); - $conf{OTHER_FILES} = list_to_conf(@other_files); - $conf{HOME_FILES} = list_to_conf(@user_list); - $conf{SYS_FILES} = list_to_conf(@sys_files); - mkdir_p($cfg_dir) if !-d $cfg_dir; - setVarsInSh($cfg_file, \%conf); - $conf{PASSWD} = $host_passwd if $conf{REMEMBER_PASS} != 1; - chmod(0600, $cfg_file); - save_cron_files(); - 0; -} - -sub read_cron_files() { - my $daemon_found = 0; - foreach (qw(hourly daily weekly monthly)) { - if (-f "/etc/cron.$_/drakbackup" && !$nonroot_user) { - $conf{DAEMON_TIME_SPACE} = $_; - $daemon_found = 1; - last; - } - } - if ($conf{DAEMON_TIME_SPACE} ne "custom") { - !$daemon_found and $backup_daemon = 0; - } else { - read_user_cron(); - } -} - -sub read_user_cron() { - @cron_entries = `crontab -l`; - chomp @cron_entries; -} - -sub save_cron_files() { - my $tmpcron = $ENV{HOME} . tmpnam() . ".tmp"; - my @cron_output; - - if ($nonroot_user && $conf{DAEMON_TIME_SPACE} ne "custom" && $conf{DAEMON_TIME_SPACE} ne '' && $backup_daemon) { - show_warning("w", N("Interval cron not available as non-root")); - $conf{DAEMON_TIME_SPACE} = 'custom'; - return 1; - } else { - foreach (qw(hourly daily weekly monthly)) { - -f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup") if !$nonroot_user; - } - } - my @cron_file = ("#!/bin/sh\n", "export USER=root\n", "/usr/sbin/drakbackup --daemon > /dev/null 2>&1\n"); - - if ($conf{DAEMON_TIME_SPACE} ne "custom" && $conf{DAEMON_TIME_SPACE} ne '' && $backup_daemon) { - output_p("/etc/cron.$conf{DAEMON_TIME_SPACE}/drakbackup", @cron_file); - system("chmod +x /etc/cron.$conf{DAEMON_TIME_SPACE}/drakbackup"); - } - - if ($conf{DAEMON_TIME_SPACE} eq "custom" && $backup_daemon) { - foreach (@cron_entries) { - next if /^#/; - push @cron_output, $_ . "\n"; - } - output($tmpcron, @cron_output); - system("crontab $tmpcron"); - unlink($tmpcron); - } -} - -sub upgrade_conf_file() { - my @new_conf; - $DEBUG and print "Old syntax...upgrading...\n"; - my @conf_data = cat_($cfg_file); - chop @conf_data; - foreach (@conf_data) { - push @new_conf, $_ . "=1\n" if !/=/; - if (/^OTHER_FILES/) { - my (@new_data) = split /=/; - my @new_args = split(" ", $new_data[1]); - push @new_conf, $new_data[0] . "=" . join(",", @new_args) . "\n"; - } elsif (/=/ && !/TAR.GZ/) { - my $has_arg = split /=/; - push @new_conf, "$_\n" if $has_arg > 1; - } elsif (/=/ && /TAR.GZ/) { - push @new_conf, "OPTION_COMP=tar.gz"; - } - } - output_p($cfg_file, @new_conf); -} - -sub read_conf_file() { - if (-e $cfg_file) { - my $conf_version = `grep USE_HD $cfg_file`; - upgrade_conf_file() if $conf_version !~ /^USE_HD=1/; - %conf = getVarsFromSh($cfg_file); - @other_files = conf_to_list($conf{OTHER_FILES}); - @user_list = conf_to_list($conf{HOME_FILES}) if exists($conf{HOME_FILES}); - @sys_files = conf_to_list($conf{SYS_FILES}) if exists($conf{SYS_FILES}); - $backup_daemon = 1 if exists($conf{DAEMON_TIME_SPACE}); - $conf{PASSWD} = $host_passwd if $conf{REMEMBER_PASS} != 1; - read_cron_files(); - $cfg_file_exist = 1; - } else { - $cfg_file_exist = 0; - #- these were 1 by default, but that made it so the user could never save the - #- inverse behavior. this allows incremental as the default if not configured - $conf{SYS_INCREMENTAL_BACKUPS} = 1; - $conf{USER_INCREMENTAL_BACKUPS} = 1; - } - # some basic defaults - $conf{SMTP_SERVER} = "localhost" if !exists($conf{SMTP_SERVER}); - $conf{MAX_SPACE} = 1000.0 if !exists($conf{MAX_SPACE}); - $conf{USE_HD} = 1 if !exists($conf{USE_HD}); - $conf{OPTION_COMP} = "tar.gz" if !exists($conf{OPTION_COMP}); - $conf{ARCHIVER} = "tar" if !exists($conf{ARCHIVER}); - $conf{FROM_MAIL} = "drakbackup" if !exists($conf{FROM_MAIL}); - $conf{DEL_OLD} = 0 if !exists($conf{DEL_OLD}); - # deal with users that may have been deleted from the system - check_valid_users() if $cfg_file_exist; - $use_hd = !($conf{USE_CD} || $conf{USE_TAPE} || $conf{USE_NET}); -} - -sub verify_mail_setup() { - all_user_list() if @user_list_all == (); - my @mlist = split(',', $conf{USER_MAIL}); - foreach (@mlist) { - if ($_ ne "root" && !/[\w.-]*\@[\w.-]/ && !member($_, @user_list_all)) { - show_warning("f", N("\"%s\" neither is a valid email nor is an existing local user!", $conf{USER_MAIL})); - return 1; - } - if (member($_, @user_list_all) && $conf{SMTP_SERVER} ne "localhost") { - show_warning("f", N("\"%s\" is a local user, but you did not select a local smtp, so you must use a complete email address!", $conf{USER_MAIL})); - return 1; - } - } -} - -sub check_valid_users() { - all_user_list(); - my @new_user_list = intersection(\@user_list, \@user_list_all); - if (@user_list != @new_user_list) { - log::l(N("Valid user list changed, rewriting config file.")); - if ($DEBUG) { - print N("Old user list:\n"); - print "@user_list\n"; - print N("New user list:\n"); - print "@new_user_list\n"; - } - @user_list = @new_user_list; - save_conf_file(); - } -} - -sub write_password_file() { - output_p("$cfg_dir/rsync.user", "$conf{PASSWD}\n"); - chmod(0600, "$cfg_dir/rsync.user"); -} - -sub show_warning { - my ($mode, $warning) = @_; - $mode = N("Warning") if $mode eq "w"; - $mode = N("Error") if $mode eq "f"; - $mode = N("Information") if $mode eq "i"; - if ($interactive) { - $in->ask_warn($mode, translate($warning)); - } else { - warn "$mode: $warning\n"; - } - $log_buff .= "\n$mode: $warning\n"; -} - -sub complete_results() { - system_state(); - $results .= "***********************************************************************\n\n"; - $daemon or $results .= N("\n DrakBackup Report \n"); - $daemon and $results .= N("\n DrakBackup Daemon Report\n"); - my $datem = `date`; - $results .= " $datem\n\n"; - $results .= "***********************************************************************\n\n"; - $results .= $system_state; - $results .= "\n\n***********************************************************************\n\n"; - $results .= N("\n DrakBackup Report Details\n\n\n"); - $results .= "***********************************************************************\n\n"; -} - -sub ftp_client() { - use Net::FTP; - my $ftp; - - foreach (1..5) { - $ftp = Net::FTP->new($conf{HOST_NAME}, Debug => 0) or return 1; - $ftp && $ftp->login($conf{LOGIN}, $conf{PASSWD}) and last; - log::l("ftp login failed, sleeping before trying again"); - sleep 5 * $_; - $ftp = 0; - } - return 1 if !$ftp; - $ftp->binary; - $ftp->cwd($conf{HOST_PATH}); - foreach (@file_list_to_send_by_ftp) { - $interactive and $pbar->set_fraction(0); - $interactive and progress($pbar, $plabel, 0.5, $_); - $interactive and $pbar->set_text($_); - $ftp->put($_, undef, undef); - $interactive and progress($pbar, $plabel, 0.5, $_); - $interactive and $pbar->set_text($_); - $interactive and progress($pbar3, $plabel3, 1/@file_list_to_send_by_ftp, N("Total progress")); - } - $ftp->quit; - return 0; -} - -sub do_expect { - - #- Sort of a general purpose expect routine, we use it to backup files to - #- a remote server, as well as transfer a key and restore. - #- Using the key after it is setup is preferred. - - my ($mode) = @_; - - eval { require Expect }; - - if ($@) { - #- should have already been installed during configuration - $log_buff .= "perl-Expect not installed!" if check_pkg_needs(); - return 1; - } - - #- for debugging set to 1 - $Expect::Exp_Internal = 0; - #- for debugging set to 1 - $Expect::Debug = 0; - $Expect::Log_Stdout = 0; - - my $spawn_ok; - my $no_perm; - my $bad_passwd; - my $bad_dir; - my $had_err; - my $timeout = 20; - - my $exp_command; - my @send_files = "$backup_key.pub"; - - #- just bypass progress for sendkey for now - my $no_prog = 1; - $no_prog = 0 if $mode eq "sendkey"; - - @send_files = @file_list_to_send_by_ftp if $mode eq "backup"; - - $interactive && $no_prog and $pbar->set_fraction(0); - $interactive && $no_prog and $pbar3->set_fraction(0); - $interactive && $no_prog and progress($pbar, $plabel, 0.5, "File Transfer..."); - - foreach (@send_files) { - $exp_command = "scp -P $scp_port $_ $conf{LOGIN}\@$conf{HOST_NAME}:$conf{HOST_PATH}" if $mode eq "backup"; - $exp_command = "ssh-copy-id -i $_ $conf{LOGIN}\@$conf{HOST_NAME}" if $mode eq "sendkey"; - - if (-e $backup_key && $mode eq "sendkey") { - if ($in->ask_yesorno(N("Warning"), N("%s exists, delete?\n\nIf you've already done this process you'll probably\n need to purge the entry from authorized_keys on the server.", $backup_key))) { - unlink($backup_key); - unlink($backup_key . '.pub'); - } else { - return 0; - } - } - - if (!(-e $backup_key) && $mode eq "sendkey") { - $in->ask_warn(N("Information"), N("This may take a moment to generate the keys.")); - gtkset_mousecursor_wait(); - #- not using a passphrase for the moment - system("ssh-keygen", "-P", "", "-t", "dsa", "-f", $backup_key); - gtkset_mousecursor_normal(); - } - - my $exp = Expect->spawn($exp_command) or $in->ask_warn(N("Error"), N("Cannot spawn %s.", $exp_command)); - - $interactive && $no_prog and progress($pbar3, $plabel3, 1/@send_files, N("Total progress")); - $interactive && $no_prog and $stext->set_text($_); - - #- run scp, look for some common errors and try to track successful progress for GUI - $exp->expect($timeout, - [ qr 'password: $', sub { - $spawn_ok = 1; - my $fh = shift; - $fh->send("$conf{PASSWD}\n"); - Expect::exp_continue() } ], - [ '-re', 'please try again', sub { $bad_passwd = 1; Expect::exp_continue() } ], - [ '-re', 'Permission denied', sub { $no_perm = 1; Expect::exp_continue() } ], - [ '-re', 'No such file or directory', sub { $bad_dir = 1; Expect::exp_continue() } ], -# [ '-re', '%', sub { update_scp_progress(); Expect::exp_continue(); } ], - [ eof => sub { - if (!$spawn_ok) { show_warning("f", N("No password prompt on %s at port %s", $conf{HOST_NAME}, $scp_port)) } - if ($bad_passwd) { show_warning("f", N("Bad password on %s", $conf{HOST_NAME})) } - if ($no_perm) { show_warning("f", N("Permission denied transferring %s to %s", $_, $conf{HOST_NAME})) } - if ($bad_dir) { show_warning("f", N("Can not find %s on %s", $conf{HOST_PATH}, $conf{HOST_NAME})) } - $had_err = !$spawn_ok || $bad_passwd || $no_perm || $bad_dir; - } - ], - [ timeout => sub { show_warning("f", N("%s not responding", $conf{HOST_NAME})) } ], - ); - - my $exit_stat = $exp->exitstatus; - $in->ask_warn(N("Information"), N("Transfer successful\nYou may want to verify you can login to the server with:\n\nssh -i %s %s\@%s\n\nwithout being prompted for a password.", $backup_key, $conf{LOGIN}, $conf{HOST_NAME})) if $exit_stat == 0 && !$had_err && $mode eq "sendkey"; - $log_buff .= "$_\n" if $exit_stat == 0 && $mode eq "backup"; - $exp->hard_close; - } - $interactive && $no_prog and progress($pbar, $plabel, 0.5, "Done..."); -} - -sub ssh_client() { - $DEBUG and print "file list to send: $_\n " foreach @file_list_to_send_by_ftp; - my $command; - my $value; - - foreach (@file_list_to_send_by_ftp) { - if ($conf{USER_KEYS}) { - $command = "scp -P $scp_port $_ $conf{LOGIN}\@$conf{HOST_NAME}:$conf{HOST_PATH}"; - } else { - $command = "scp -P $scp_port -i $backup_key $_ $conf{LOGIN}\@$conf{HOST_NAME}:$conf{HOST_PATH}"; - } - $interactive and $pbar->set_fraction(0); - $interactive and progress($pbar, $plabel, 0.5, "File Transfer..."); - $interactive and $stext->set_text($_); - $log_buff .= $command . "\n\n"; - my $TMP; - open $TMP, "$command 2>&1 |"; - while ($value = <$TMP>) { - $log_buff .= $value; - } - close $TMP; - $log_buff .= "\n"; - $interactive and progress($pbar, $plabel, 0.5, "Done..."); - $interactive and progress($pbar3, $plabel3, 1/@file_list_to_send_by_ftp, N("Total progress")); - } - return 0; -} - -sub rsync_client() { - $DEBUG and print "file list to send: $_\n " foreach @file_list_to_send_by_ftp; - my $rsync_cmd = "rsync -tv $conf{PATH_TO_SAVE}/* "; - $rsync_cmd = $rsync_cmd . "--password-file=$cfg_dir/rsync.user " if $conf{PASSWD}; - $rsync_cmd = $rsync_cmd . "$conf{LOGIN}\@" if $conf{LOGIN}; - $rsync_cmd = $rsync_cmd . $conf{HOST_NAME} . "::" . $conf{HOST_PATH}; - spawn_progress($rsync_cmd, "Running rsync"); - return 0; -} - -sub check_for_cd() { - #- check for a cd - my $command = "cdrecord dev=$conf{CD_DEVICE} -atip"; - spawn_progress($command, "Check for media in drive"); - if ($log_buff =~ /No disk/) { - show_warning("f", N("No CD-R/DVD-R in drive!")); - return 1; - } - if ($log_buff !~ /ATIP info from disk|ATIP start of lead in|Found DVD media/) { - show_warning("f", N("Does not appear to be recordable media!")); - return 1; - } - #- non-fatal, just disable erase - if (($log_buff =~ /Is not erasable/ || $log_buff =~ /Found DVD media/) && $conf{MEDIA_ERASE}) { - show_warning("w", N("Not erasable media!")); - $conf{MEDIA_ERASE} = 0; - save_conf_file(); - } - - if ($conf{MULTI_SESSION}) { - $command = "cdrecord -s dev=$conf{CD_DEVICE} -msinfo"; - spawn_progress($command, "Check for previous session status"); - #- if we do not find a previous session, start fresh - if ($log_buff =~ /Cannot read session offset/) { - $conf{MEDIA_ERASE} = 1; - return 0; - } else { - #- extract the session info from $log_buff - my $code_loc = rindex($log_buff, "msinfo") + 8; - if ($code_loc != -1) { - my $bufflen = length($log_buff); - $session_offset = substr($log_buff, $code_loc, $bufflen-$code_loc-1); - return 0; - } - return 1; - } - } -} - -sub write_on_cd() { - my $command = "cdrecord -v dev=$conf{CD_DEVICE} -data "; - # DVD+RW use -sao - $command .= "-sao " if $conf{DVDRW}; - #- only blank if it's the first session - $command .= "blank=fast " if $conf{MEDIA_ERASE} && $session_offset eq ''; - #- multi-session mode - $command .= "-multi -pad " if $conf{MULTI_SESSION}; - $command .= "$conf{PATH_TO_SAVE}/drakbackup.iso"; - - spawn_progress($command, "Running cdrecord"); - unlink("$conf{PATH_TO_SAVE}/drakbackup.iso"); -} - -sub erase_cdrw() { - #- we can only hit this via interactive - $interactive = 0; - $in->ask_warn(N("Information"), N("This may take a moment to erase the media.")); - gtkset_mousecursor_wait(); - my $command = "cdrecord dev=$conf{CD_DEVICE} -blank=fast"; - spawn_progress($command, "Erasing CDRW..."); - gtkset_mousecursor_normal(); - $interactive = 1; -} - -sub spawn_progress { - my ($command, $descr) = @_; - my $value; - my $timer; - $interactive and progress($pbar3, $plabel3, 0, translate($descr)); - $interactive and $pbar3->set_pulse_step(0.1); - $interactive and $timer = Glib::Timeout->add(20, sub { $pbar3->pulse }); - - $log_buff .= "\n" . $descr . ":\n"; - $log_buff .= $command . "\n\n"; - - standalone::explanations("Running $command"); - my $TMP; - open $TMP, "$command 2>&1 |"; - while ($value = <$TMP>) { - $log_buff .= $value; - if ($interactive) { - $stext->set_text($value); - gtkflush(); - } - } - close $TMP; - $interactive and Glib::Source->remove($timer); -} - -sub get_cd_volname() { - my $vol_device = $conf{CD_DEVICE}; - $vol_device =~ s/sg/scd/; - $vol_name = `volname $vol_device` if $conf{CD_DEVICE}; - $vol_name =~ s/[ \t]+\n$//; - $vol_name; -} - -sub build_iso() { - if ($conf{MULTI_SESSION} && $session_offset) { - $vol_name = get_cd_volname(); - } else { - $vol_name = "Drakbackup" . $the_time; - } - #this is safe to change the volname on rewrites, as is seems to get ignored anyway - my $command = "mkisofs -r -J -T -v -V '$vol_name' "; - $command .= "-C $session_offset -M $conf{CD_DEVICE} " if $conf{MULTI_SESSION} && $session_offset; - $command .= "-o $conf{PATH_TO_SAVE}/drakbackup.iso @file_list_to_send_by_ftp"; - spawn_progress($command, "Running mkisofs..."); -} - -sub build_cd() { - if (!check_for_cd()) { - build_iso(); - if ($log_buff =~ /Permission denied/) { - show_warning("f", N("Permission problem accessing CD.")); - $media_problem = 1; - return 1; - } else { - write_on_cd(); - } - } -} - -sub get_tape_label { - my ($device) = @_; - gtkset_mousecursor_wait(); - system("mt -f $device rewind"); - system("$conf{ARCHIVER} -C $cfg_dir -x -f $device"); - my @volname = cat_("$cfg_dir/drakbackup.label"); - unlink("$cfg_dir/drakbackup.label"); - $vol_name = $volname[0]; - gtkset_mousecursor_normal(); - $vol_name; -} - -sub build_tape() { - my $command; - my $dt_list; - #- do we have a tape? - $command = "mt -f $conf{TAPE_DEVICE} status"; - spawn_progress($command, "Checking for tape"); - if ($log_buff =~ /DR_OPEN/) { - show_warning("f", N("No tape in %s!", $conf{TAPE_DEVICE})); - return 1; - } - #- enable compression if configured - if ($conf{HDW_COMP}) { - $command = "mt -f $conf{TAPE_DEVICE} compression"; - spawn_progress($command, "Enabling compression"); - } - #- try to roll to the end of the data if we're not erasing - $command = "mt -f $conf{TAPE_DEVICE} rewind"; - # if we're using the rewinding device, change modes briefly - if (!$conf{TAPE_NOREWIND}) { - $conf{TAPE_DEVICE} =~ s|/st|/nst|; - } - if (!$conf{MEDIA_ERASE}) { - spawn_progress($command, "Rewind to find tape label"); - $command = "$conf{ARCHIVER} -t -f $conf{TAPE_DEVICE}"; - spawn_progress($command, "Check for label"); - if ($log_buff =~ /drakbackup.label/) { - $command = "mt -f $conf{TAPE_DEVICE} rewind"; - spawn_progress($command, "Rewind to get tape label"); - $command = "$conf{ARCHIVER} -C $cfg_dir -x -f $conf{TAPE_DEVICE}"; - spawn_progress($command, "Reading tape label"); - my @volname = cat_("$cfg_dir/drakbackup.label"); - unlink("$cfg_dir/drakbackup.label"); - $vol_name = $volname[0]; - } - $command = "mt -f $conf{TAPE_DEVICE} eod"; - spawn_progress($command, "Running mt to find eod"); - } else { - spawn_progress($command, "Running mt to rewind"); - # make a tape label for the catalog - $vol_name = "Drakbackup" . $the_time; - my $f = "$cfg_dir/drakbackup.label"; - output($f, $vol_name); - $command = "$conf{ARCHIVER} -C $cfg_dir -c -f $conf{TAPE_DEVICE} drakbackup.label;"; - spawn_progress($command, "Creating tape label"); - unlink $f; - } - # restore device setup - if (!$conf{TAPE_NOREWIND}) { - $conf{TAPE_DEVICE} =~ s|/nst|/st|; - } - - #- do the backup - $command = "$conf{ARCHIVER} -cv -f $conf{TAPE_DEVICE} "; - if ($conf{DIRECT_TAPE}) { - $command .= handle_ignores($command !~ /-V/, @files_for_direct_tape); - $command .= " @files_for_direct_tape"; - $dt_list = $conf{PATH_TO_SAVE} . "/list_direct_tape" . $the_time . ".txt"; - $command .= " $index_cmd $dt_list"; - } else { - $command .= " @file_list_to_send_by_ftp"; - } - spawn_progress($command, "Running tar to tape"); - gzip($dt_list); - - #- eject the tape? - if ($conf{MEDIA_EJECT}) { - $command = "mt -f $conf{TAPE_DEVICE} rewoff"; - spawn_progress($command, "Running mt to eject tape"); - } -} - -sub send_mail { - my ($result) = @_; - my $datem = `date`; - use Mail::Mailer; - my @mlist = split(',', $conf{USER_MAIL}); - my $mailer = Mail::Mailer->new('smtp', Server => $conf{SMTP_SERVER}); - foreach (@mlist) { - $mailer->open({ From => $conf{FROM_MAIL}, - To => $_, - Subject => "DrakBackup report on $datem" }) or return 1; - print $mailer $result; - $mailer->close; - } - 0; -} - -sub build_backup_files() { - my $path_name; - my $tar_cmd; - my $more_recent; - my $tar_cmd_sys; - my $tar_cmd_user; - my $tar_cmd_other; - my @dir_content; - my $incr; - my $base; - my $find_args = "! -type d -print"; - - local $_; - $results = ""; - $log_buff = ""; - #- flush these so if the user does 2 runs in a row we do not try to send the same files - @file_list_to_send_by_ftp = (); - @files_for_direct_tape = (); - - $interactive and gtkset_mousecursor_wait(); - check_archiver(); - read_conf_file(); - $the_time = the_time(); - $conf{SEND_MAIL} and complete_results(); - -d $conf{PATH_TO_SAVE} or mkdir_p($conf{PATH_TO_SAVE}); - - $tar_cmd = "$conf{ARCHIVER} -cv -p "; - $tar_cmd .= $conf{ARCHIVER} eq 'tar' ? "-P " : "-acl -xattr -tpath "; - $tar_cmd .= set_compression($conf{OPTION_COMP}); - - clean_old_backups(); - my $used_space = check_storage_quota($conf{PATH_TO_SAVE}); - if ($used_space) { - my $msg = N("Backup destination quota exceeded!\n%d MB used vs %d MB allocated.", $used_space, $conf{MAX_SPACE}); - show_warning("f", $msg); - $interactive and gtkset_mousecursor_normal(); - $results .= $msg; - $interactive and show_status(); - results_to_logfile(); - return 1; - } - $tar_cmd_sys = $tar_cmd; - $tar_cmd_user = $tar_cmd; - $tar_cmd_other = $tar_cmd; - my $exclude_cmd = $conf{ARCHIVER} eq 'tar' ? " --exclude=" : " pat=*/"; - my $invert_cmd = $conf{ARCHIVER} eq 'tar' ? "" : " -V"; - $conf{NO_CRITICAL_SYS} and $tar_cmd_sys .= $invert_cmd . $exclude_cmd . "passwd" . $exclude_cmd . "fstab" . $exclude_cmd . "group" . $exclude_cmd . "mtab"; - $conf{NO_BROWSER_CACHE} and $tar_cmd_user .= $invert_cmd . $exclude_cmd . "NewCache" . $exclude_cmd . "Cache" . $exclude_cmd . "cache"; - $nonroot_user and $tar_cmd_user .= $invert_cmd . $exclude_cmd . ".drakbackup"; - - -d $conf{PATH_TO_SAVE} and @dir_content = all($conf{PATH_TO_SAVE}); - - if ($conf{USE_HD} && !$daemon || $daemon) { - $interactive and progress($pbar, $plabel, 0.5, N("Backup system files...")); - unless ($conf{NO_SYS_FILES}) { - my $find_args_sys = $find_args; - my $first_done; - $ignore_files_list = ''; - $tar_cmd_sys .= handle_ignores($tar_cmd_sys !~ /-V/, "/etc"); - if ($conf{SYS_INCREMENTAL_BACKUPS}) { - $base = $incr = "incr_sys"; - ($base, $incr) = swap_prefix($base, $incr) if $conf{SYS_DIFFERENTIAL_BACKUPS}; - $base =~ s/incr/base/ if !any { /^list_incr_sys/ } @dir_content; - if (any { /^list_base_sys/ } @dir_content) { - $more_recent = get_more_recent($base, @dir_content); - my $list_file = name_list_file($incr); - do_find($more_recent, $find_args_sys, $list_file, @sys_files); - if (check_rm_list($list_file)) { - do_tar($tar_cmd_sys, "backup_$incr", $list_file, undef); - } - $first_done = 1; - } else { - $incr = "base_sys"; - } - } else { - $incr = "sys"; - clean_dest($incr); - } - if (!$first_done) { - my $list_file = name_list_file($incr); - do_tar($tar_cmd_sys, "backup_$incr", $list_file, @sys_files); - } - push_list("list_$incr") if $incr =~ /_sys/; - files_to_results($incr); - } - $interactive and progress($pbar, $plabel, 0.5, N("Backup system files...")); - $interactive and progress($pbar3, $plabel3, 0.3, N("Hard Disk Backup files...")); - - unless ($conf{NO_USER_FILES}) { - foreach (@user_list) { - my $user = $_; - my $tar_cmd_cuser = $tar_cmd_user; - $path_name = return_path($user); - $ignore_files_list = ''; - $tar_cmd_cuser .= handle_ignores($tar_cmd_cuser !~ /-V/, $path_name); - my $find_args_user = $find_args; - my $first_done; - if ($conf{USER_INCREMENTAL_BACKUPS}) { - $base = $incr = "incr_user_"; - ($base, $incr) = swap_prefix($base, $incr) if $conf{USER_DIFFERENTIAL_BACKUPS}; - $base =~ s/incr/base/ if !any { /^list_incr_user_$user/ } @dir_content; - if (any { /^list_base_user_$user/ } @dir_content) { - $more_recent = get_more_recent("$base$user", @dir_content); - my $list_file = name_list_file($incr . $user); - do_find($more_recent, $find_args_user, $list_file, $path_name); - if (check_rm_list($list_file)) { - do_tar($tar_cmd_cuser, "backup_$incr$user", $list_file, $path_name); - } - $first_done = 1; - } else { - $incr = "base_user_"; - } - } else { - $incr = "user_"; - clean_dest("$incr$user"); - } - if (!$first_done) { - my $list_file = name_list_file($incr . $user); - do_tar($tar_cmd_cuser, "backup_$incr$user", $list_file, $path_name); - } - push_list("list_$incr$user") if $incr =~ /_user/; - files_to_results("$incr$user"); - } - } - $interactive and progress($pbar1, $plabel1, 1, N("Backup User files...")); - $interactive and progress($pbar3, $plabel3, 0.4, N("Hard Disk Backup files...")); - - if ($conf{OTHER_FILES}) { - my $find_args_other = $find_args; - my $first_done; - $ignore_files_list = ''; - $tar_cmd_other .= handle_ignores($tar_cmd_other !~ /-V/, @other_files); - if ($conf{OTHER_INCREMENTAL_BACKUPS}) { - $base = $incr = "incr_other"; - ($base, $incr) = swap_prefix($base, $incr) if $conf{OTHER_DIFFERENTIAL_BACKUPS}; - $base =~ s/incr/base/ if !any { /^list_incr_other/ } @dir_content; - if (any { /^list_base_other/ } @dir_content) { - $more_recent = get_more_recent($base, @dir_content); - my $list_file = name_list_file($incr); - do_find($more_recent, $find_args_other, $list_file, @other_files); - if (check_rm_list($list_file)) { - do_tar($tar_cmd_other, "backup_$incr", $list_file, undef); - } - $first_done = 1; - } else { - $incr = "base_other"; - } - } else { - $incr = "other"; - clean_dest($incr); - } - if (!$first_done) { - my $list_file = name_list_file($incr); - do_tar($tar_cmd_other, "backup_$incr", $list_file, @other_files); - } - push_list("list_$incr") if $incr =~ /_other/; - files_to_results($incr); - } - $interactive and progress($pbar2, $plabel2, 1, N("Backup Other files...")); - $interactive and progress($pbar3, $plabel3, 0.3, N("Hard Disk Backup Progress...")); - } - - my $filecount = @file_list_to_send_by_ftp; - if (!$filecount && !$conf{DIRECT_TAPE}) { - my $msg = N("No changes to backup!"); - show_warning("w", $msg); - $interactive and gtkset_mousecursor_normal(); - $interactive and interactive_mode_box(); - results_to_logfile(); - return 1; - } - - #- should hit this block if running daemon mode only - if ($daemon && $conf{DAEMON_MEDIA}) { - rsync_client() if $conf{DAEMON_MEDIA} eq 'rsync'; - ssh_client() if $conf{DAEMON_MEDIA} eq 'ssh' && !$conf{USE_EXPECT}; - do_expect("backup") if $conf{DAEMON_MEDIA} eq 'ssh' && $conf{USE_EXPECT}; - build_cd() if $conf{DAEMON_MEDIA} eq 'cd'; - build_tape() if $conf{DAEMON_MEDIA} eq 'tape'; - - $results .= N("\nDrakbackup activities via %s:\n\n", $conf{DAEMON_MEDIA}) if $conf{DAEMON_MEDIA} ne 'hd'; - $results .= $log_buff; - } - - #- leave this one alone for now - works well - #- integrate with other methods later - if (($conf{USE_NET} && !$daemon && $conf{NET_PROTO} eq 'ftp') || $daemon && $conf{DAEMON_MEDIA} eq 'ftp') { - $interactive and build_backup_ftp_status(); - if (ftp_client()) { - $results .= N("\n FTP connection problem: It was not possible to send your backup files by FTP.\n"); - $interactive and $in->ask_warn(N("Error"), N("Error during sending file via FTP. Please correct your FTP configuration.")); - } else { - $results .= N("file list sent by FTP: %s\n", $_) foreach @file_list_to_send_by_ftp; - } - } - - #- consolidate all the other methods under here - interactive and --default should land here - if (!$daemon) { - if ($conf{USE_NET} && $conf{NET_PROTO} && $conf{NET_PROTO} ne 'ftp') { - rsync_client() if $conf{NET_PROTO} eq 'rsync'; - ssh_client() if $conf{NET_PROTO} eq 'ssh' && !$conf{USE_EXPECT}; - do_expect("backup") if $conf{NET_PROTO} eq 'ssh' && $conf{USE_EXPECT}; - $results .= N("\nDrakbackup activities via %s:\n\n", $conf{NET_PROTO}); - } - - if ($conf{USE_CD}) { - build_cd(); - $results .= N("\nDrakbackup activities via CD:\n\n"); - } - - if ($conf{USE_TAPE}) { - build_tape(); - $results .= N("\nDrakbackup activities via tape:\n\n"); - } - $results .= $log_buff; - } - - results_to_logfile(); - - if ($conf{SEND_MAIL}) { - if (send_mail($results)) { - $interactive and $in->ask_warn(N("Error"), N("Error sending mail. Your report mail was not sent.")); - $interactive or print N(" Error while sending mail. \n"); - } - } - - #- write our catalog file - if (!$media_problem) { - my $catalog = substr($the_time, 1); - my $direct_tape = ""; - $direct_tape = "Direct" if $conf{DIRECT_TAPE}; - if (!$conf{USE_NET} && !$conf{USE_TAPE} && !$conf{USE_CD}) { - $catalog .= ":HD:localhost:$conf{PATH_TO_SAVE}"; - $conf{NET_PROTO} = ''; - } - $catalog .= ":$conf{NET_PROTO}:$conf{LOGIN}\@$conf{HOST_NAME}:$conf{HOST_PATH}" if $conf{NET_PROTO}; - $catalog .= ":CD:$vol_name:$conf{CD_DEVICE}" if $conf{USE_CD}; - $catalog .= ":" . $direct_tape . "Tape:$vol_name:$conf{TAPE_DEVICE}" if $conf{USE_TAPE}; - $catalog .= ":System" unless $conf{NO_SYS_FILES}; - $catalog .= ":I" if $conf{SYS_INCREMENTAL_BACKUPS} && !$conf{NO_SYS_FILES} && !$conf{SYS_DIFFERENTIAL_BACKUPS}; - $catalog .= ":D" if $conf{SYS_INCREMENTAL_BACKUPS} && !$conf{NO_SYS_FILES} && $conf{SYS_DIFFERENTIAL_BACKUPS}; - $catalog .= ":F" if !$conf{SYS_INCREMENTAL_BACKUPS} && !$conf{NO_SYS_FILES}; - $catalog .= ":Users=(@user_list)" unless $conf{NO_USER_FILES}; - $catalog .= ":I" if $conf{USER_INCREMENTAL_BACKUPS} && !$conf{NO_USER_FILES} && !$conf{USER_DIFFERENTIAL_BACKUPS}; - $catalog .= ":D" if $conf{USER_INCREMENTAL_BACKUPS} && !$conf{NO_USER_FILES} && $conf{USER_DIFFERENTIAL_BACKUPS}; - $catalog .= ":F" if !$conf{USER_INCREMENTAL_BACKUPS} && !$conf{NO_USER_FILES}; - $catalog .= ":Other=(@other_files)" if $conf{OTHER_FILES}; - $catalog .= ":I" if $conf{OTHER_INCREMENTAL_BACKUPS} && $conf{OTHER_FILES} && !$conf{OTHER_DIFFERENTIAL_BACKUPS}; - $catalog .= ":D" if $conf{OTHER_INCREMENTAL_BACKUPS} && $conf{OTHER_FILES} && $conf{OTHER_DIFFERENTIAL_BACKUPS}; - $catalog .= ":F" if !$conf{OTHER_INCREMENTAL_BACKUPS} && $conf{OTHER_FILES}; - $catalog .= "\n"; - - append_to_file("$cfg_dir/drakbackup_catalog", $catalog) or show_warning("w", N("Can not create catalog!")); - } - - #- clean up HD files if del_hd_files and media is not hd - if ($conf{DEL_HD_FILES} && ($conf{USE_CD} || $conf{USE_TAPE} || $conf{USE_NET}) && $conf{DAEMON_MEDIA} ne 'hd') { - foreach (@file_list_to_send_by_ftp) { - unlink($_) if /$conf{OPTION_COMP}$/; - } - } - - #- if we had a media problem then get rid of the text log of the backed up files too - if ($media_problem) { - system("rm $conf{PATH_TO_SAVE}/list*$the_time.txt"); - } - - $interactive and gtkset_mousecursor_normal(); - $interactive and show_status(); -} - -sub swap_prefix { - my ($base, $incr) = @_; - $incr =~ s/incr/diff/; - $base =~ s/incr/base/; - return $base, $incr; -} - -sub name_list_file { - my ($suffix) = @_; - return $conf{PATH_TO_SAVE} . "/list_" . $suffix . $the_time . ".txt"; -} - -sub check_rm_list { - my ($list_file) = @_; - $list_file .= ".tmp"; - if (!catMaybeCompressed($list_file)) { - unlink($list_file); - return 0; - } else { - return 1; - } -} - -sub get_more_recent { - my ($match, @directory) = @_; - $match = "list_" . $match; - my @more_recent = grep { /^$match/ } sort @directory; - my $more_recent = pop @more_recent; - $DEBUG and print "more recent file: $more_recent\n"; - return $more_recent; -} - -sub clean_dest { - my ($wildcard) = @_; - system("cd $conf{PATH_TO_SAVE} && rm -f backup*$wildcard*"); -} - -sub clean_old_backups() { - if ($conf{DEL_OLD} && $conf{USE_HD}) { - foreach ('*_diff_*', '*_incr_*') { - system("find $conf{PATH_TO_SAVE} -name $_ -mtime +$conf{DEL_OLD} | xargs rm -f"); - } - } -} - -sub do_find { - my ($newer, $more_args, $into, @where) = @_; - #- $newer may be undef - if it's defined then "-cnewer $newer" - $newer = $conf{PATH_TO_SAVE} . "/" . $newer if defined($newer); - defined($newer) ? system("find @where -cnewer $newer $more_args > $into.tmp") : system("find @where $more_args > $into.tmp"); -} - -sub do_tar { - my ($tar_cmd, $dest_file, $list_file, @files) = @_; - my $full_dest_file = $conf{PATH_TO_SAVE} . "/" . $dest_file . $the_time . "." . $conf{OPTION_COMP}; - my $tmp_list = $list_file . ".tmp"; - if ($conf{DIRECT_TAPE}) { - log::explanations("Direct tape backup - tar deferred..."); - @files = cat_($tmp_list) and chomp @files if -e $tmp_list; - push @files_for_direct_tape, @files; - renamef($tmp_list, $list_file) if -e $tmp_list; - } else { - #- if $list_file is undefined, then use the @files list - my $list_cmd = $conf{ARCHIVER} eq "tar" ? "-T " : "list="; - #- FIXME? no --index-file equiv for star, use pipe to cat for now - -e $tmp_list ? system("$tar_cmd -f $full_dest_file $list_cmd$tmp_list $index_cmd $list_file") : system("$tar_cmd -f $full_dest_file @files $index_cmd $list_file"); - unlink($tmp_list) if -e $tmp_list; - } - gzip($list_file); - chmod(0600, $full_dest_file) if -e $full_dest_file; - push_list($dest_file); -} - -sub gzip { - my ($gz_file) = @_; - if (-e $gz_file) { - chmod(0600, $gz_file); - system("gzip $gz_file"); - } -} - -sub push_list { - my ($prefix) = @_; - my $filename = $conf{PATH_TO_SAVE} . "/" . $prefix . $the_time . "."; - $filename .= $conf{OPTION_COMP} if $prefix =~ /^backup/; - $filename .= "txt" if $prefix =~ /^list/; - push @file_list_to_send_by_ftp, $filename if -e $filename; -} - -sub files_to_results { - my ($basename) = @_; - if ($conf{DIRECT_TAPE}) { - $results .= "\nDirect to tape:\n\n"; - } else { - $results .= "\nfile: " . $conf{PATH_TO_SAVE} . "/backup_" . $basename . $the_time . "." . $conf{OPTION_COMP} . "\n\n"; - $results .= catMaybeCompressed("$conf{PATH_TO_SAVE}/list_" . $basename . $the_time . ".txt"); - } - $results .= "\nignored:\n" . $ignore_files_list . "\n" if $ignore_files_list; -} - -sub handle_ignores { - #- not quite the expected behavior for "other" files: .backupignore entries in one dir will affect others - my ($needs_V, @list) = @_; - return if !$conf{BACKUPIGNORE}; - my $tar_cmd; - foreach my $dir (@list) { - if (-d $dir) { - if (-f "$dir/.backupignore") { - my @ignores = cat_("$dir/.backupignore"); - $ignore_files_list .= join('',@ignores); - if ($conf{ARCHIVER} eq 'star') { - chomp @ignores; - my $ignore_args = $needs_V ? " -V" : ""; - foreach (@ignores) { - #- FIXME star -V pat= doesn't quite map to gnu tar behavior - next if $_ eq ''; - $ignore_args .= " pat="; - $ignore_args .= "*/" if !m,^/|^\*,; - $ignore_args .= -d "$dir/$_" ? $_ . "*" : $_; - } - $tar_cmd .= $ignore_args; - } else { - $tar_cmd .= " -X $dir/.backupignore"; - } - } - } - } - return $tar_cmd; -} - -sub check_pkg_needs() { - my @extra_pkg; - if ($conf{USE_NET}) { - @extra_pkg = "rsync" if $conf{NET_PROTO} eq 'rsync'; - @extra_pkg = "perl-Expect" if $conf{NET_PROTO} eq 'ssh' && ($conf{USE_EXPECT} || $conf{DRAK_KEYS}); - } - @extra_pkg = "mt-st" if $conf{USE_TAPE}; - @extra_pkg = ("mkisofs", "cdrecord") if $conf{USE_CD}; - push @extra_pkg, "star" if $conf{ARCHIVER} eq 'star'; - if (@extra_pkg) { - if (!$in->do_pkgs->install(@extra_pkg)) { - $in->ask_warn(N("Error"), N("Problem installing %s", join(', ', @extra_pkg))); - return 1; - } - } -} - -sub show_status() { - my $text = Gtk2::TextView->new; - destroy_widget(); - my $scrolled_window = Gtk2::ScrolledWindow->new; - $scrolled_window->set_border_width(10); - $scrolled_window->add_with_viewport($text); - gtktext_insert(gtkset_editable($text, 0), [ [ $results ] ]); - - gtkpack($advanced_box, - $table = gtkpack_(Gtk2::VBox->new(0,10), 1, $scrolled_window) - ); - $central_widget = \$table; - $table->show_all; -} - -sub results_to_logfile() { - output_p($log_file, $results); -} - -sub conf_to_list { - my ($config) = @_; - return split(",", $config); -} - -sub list_to_conf { - my (@list) = @_; - return join(",", @list); -} - -sub filedialog_generic { - #- a more generic file dialog - #- a title prompt, the widget to get updated - my ($prompt, $widget) = @_; - - my $file_dialog = Gtk2::FileChooserDialog->new($prompt, $my_win->{real_window}, 'select-folder', N("Cancel") => 'cancel', N("Ok") => 'ok'); - $file_dialog->show; - while (my $answer = $file_dialog->run) { - if (member($answer, qw(cancel delete-event))) { - $file_dialog->destroy; - return; - } elsif ($answer eq 'ok') { - if (defined($widget)) { - $$widget->set_text($file_dialog->get_filename); - } else { - my $file_name = $file_dialog->get_filename; - #- catch files and dirs with spaces - $file_name = '"' . $file_name . '"' if $file_name =~ / /; - if (!member($file_name, @other_files)) { - push(@other_files, $file_name); - $list_model->append_set(0, $file_name); - } - } - $file_dialog->destroy; - return; - } - } -} - -################################################ ADVANCED ################################################ - -sub check_list { - foreach (@_) { - my $ref = $_->[1]; - $_->[2] ? gtkset_active($_->[0], !$$ref) : gtkset_active($_->[0], $$ref); - gtksignal_connect($_->[0], toggled => sub { - invbool $ref; - destroy_widget(); - $current_widget->(); - }); - } -} - -sub fonction_env { - ($central_widget, $current_widget, $previous_widget, $next_widget) = @_; -} - -sub advanced_what_sys() { - my $box_what_sys; - - gtkpack($advanced_box, - $box_what_sys = gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 15), - 0, my $check_what_sys = Gtk2::CheckButton->new(N("Backup your System files. (/etc directory)")), - 0, my $check_what_versions = Gtk2::CheckButton->new(N("Use Incremental/Differential Backups (do not replace old backups)")), - 0, gtkpack__(Gtk2::HBox->new(0,0), - my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), - ), - 0, my $check_what_critical = Gtk2::CheckButton->new(N("Do not include critical files (passwd, group, fstab)")), - 1, Gtk2::VBox->new(0, 15), - ), - ); - check_list([$check_what_sys, \$conf{NO_SYS_FILES}, 1], [$check_what_critical, \$conf{NO_CRITICAL_SYS}]); - $check_what_versions->set_active($conf{SYS_INCREMENTAL_BACKUPS}); - $check_what_versions->signal_connect('toggled' => sub { - invbool \$conf{SYS_INCREMENTAL_BACKUPS}; - $mode_buttons[0]->set_sensitive($conf{SYS_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{SYS_INCREMENTAL_BACKUPS}); - - }); - $mode_buttons[1]->set_active($conf{SYS_DIFFERENTIAL_BACKUPS}); - $mode_buttons[0]->signal_connect('toggled' => sub { $conf{SYS_DIFFERENTIAL_BACKUPS} = $mode_buttons[1]->get_active }); - $mode_buttons[0]->set_sensitive($conf{SYS_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{SYS_INCREMENTAL_BACKUPS}); - set_help_tip($check_what_versions, 'use_incr_decr'); - set_help_tip($mode_buttons[0], 'use_incremental'); - set_help_tip($mode_buttons[1], 'use_differential'); - fonction_env(\$box_what_sys, \&advanced_what_sys, \&advanced_what); - $up_box->show_all; -} - -sub advanced_what_user { - my ($previous_function) = @_; - my $box_what_user; - my %check_what_user; - - all_user_list(); - gtkpack($advanced_box, - $box_what_user = gtkpack_(Gtk2::VBox->new(0, 15), - 0, N("Please check all users that you want to include in your backup."), - 0, Gtk2::HSeparator->new, - 1, create_scrolled_window( - gtkpack__(Gtk2::VBox->new(0,0), - map { my $name = $_; - my @user_list_tmp; - my $b = Gtk2::CheckButton->new($name); - if (any { /^$name$/ } @user_list) { - $check_what_user{$_}[1] = 1; - gtkset_active($b, 1); - } else { - $check_what_user{$_}[1] = 0; - gtkset_active($b, 0); - } - $b->signal_connect(toggled => sub { - if ($check_what_user{$name}[1]) { - $check_what_user{$name}[1] = 0; - @user_list_tmp = grep { !/^$name$/ } @user_list; - @user_list = @user_list_tmp; - } else { - $check_what_user{$name}[1] = 1; - if (!member($name, @user_list)) { push @user_list, $name } - } - }); - $b } (@user_list_all) - ), - ), - 0, my $check_what_browser = Gtk2::CheckButton->new(N("Do not include the browser cache")), - 0, my $check_what_user_versions = Gtk2::CheckButton->new(N("Use Incremental/Differential Backups (do not replace old backups)")), - 0, gtkpack__(Gtk2::HBox->new(0,0), - my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), - ), - ), - ); - check_list([$check_what_browser, \$conf{NO_BROWSER_CACHE}]); - $check_what_user_versions->set_active($conf{USER_INCREMENTAL_BACKUPS}); - $check_what_user_versions->signal_connect('toggled' => sub { - invbool \$conf{USER_INCREMENTAL_BACKUPS}; - $mode_buttons[0]->set_sensitive($conf{USER_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{USER_INCREMENTAL_BACKUPS}); - }); - $mode_buttons[1]->set_active($conf{USER_DIFFERENTIAL_BACKUPS}); - $mode_buttons[0]->signal_connect('toggled' => sub { $conf{USER_DIFFERENTIAL_BACKUPS} = $mode_buttons[1]->get_active }); - $mode_buttons[0]->set_sensitive($conf{USER_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{USER_INCREMENTAL_BACKUPS}); - set_help_tip($check_what_user_versions, 'use_incr_decr'); - set_help_tip($mode_buttons[0], 'use_incremental'); - set_help_tip($mode_buttons[1], 'use_differential'); - - if ($previous_function) { fonction_env(\$box_what_user, \&advanced_what_user, \&$previous_function, \&$previous_function) } - else { fonction_env(\$box_what_user, \&advanced_what_user, \&advanced_what) } - $up_box->show_all; -} - -sub advanced_what_other() { - my $box_what_other; - my $file_iter; - my $other_file; - - $list_model = Gtk2::ListStore->new("Glib::String"); - my $list_others = Gtk2::TreeView->new_with_model($list_model); - $list_others->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - $list_others->set_headers_visible(0); - - foreach (@other_files) { - $list_model->append_set(0, $_); - } - - $list_others->get_selection->signal_connect(changed => sub { - my ($model, $iter) = $_[0]->get_selected; - $model && $iter or return; - $other_file = $model->get($iter, 0); - $file_iter = $iter; - }); - - gtkpack($advanced_box, - $box_what_other = gtkpack_(Gtk2::VBox->new(0, 15), - 1, gtkpack_(Gtk2::HBox->new(0,4), - 1, create_scrolled_window($list_others), - ), - 0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'), - gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { filedialog_generic(N("Select the files or directories and click on 'OK'"), undef) }), - gtksignal_connect(Gtk2::Button->new(N("Remove Selected")), clicked => sub { - $list_model->remove($file_iter) if $file_iter; - my $iindex = 0; - foreach (@other_files) { - if ($other_files[$iindex] eq $other_file) { - splice(@other_files, $iindex, 1); - last; - } - $iindex++; - } - }), - ), - 0, my $check_what_other_versions = Gtk2::CheckButton->new(N("Use Incremental/Differential Backups (do not replace old backups)")), - 0, gtkpack__(Gtk2::HBox->new(0,0), - my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), - ), - ), - - ); - $check_what_other_versions->set_active($conf{OTHER_INCREMENTAL_BACKUPS}); - $check_what_other_versions->signal_connect('toggled' => sub { - invbool \$conf{OTHER_INCREMENTAL_BACKUPS}; - $mode_buttons[0]->set_sensitive($conf{OTHER_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{OTHER_INCREMENTAL_BACKUPS}); - }); - $mode_buttons[1]->set_active($conf{OTHER_DIFFERENTIAL_BACKUPS}); - $mode_buttons[0]->signal_connect('toggled' => sub { $conf{OTHER_DIFFERENTIAL_BACKUPS} = $mode_buttons[1]->get_active }); - $mode_buttons[0]->set_sensitive($conf{OTHER_INCREMENTAL_BACKUPS}); - $mode_buttons[1]->set_sensitive($conf{OTHER_INCREMENTAL_BACKUPS}); - set_help_tip($check_what_other_versions, 'use_incr_decr'); - set_help_tip($mode_buttons[0], 'use_incremental'); - set_help_tip($mode_buttons[1], 'use_differential'); - - fonction_env(\$box_what_other, \&advanced_what_other, \&advanced_what); - $up_box->show_all; -} - -sub advanced_what() { - my $box_what; - - gtkpack($advanced_box, - $box_what = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtksignal_connect(my $button_what_sys = Gtk2::Button->new, - clicked => sub { $box_what->destroy; advanced_what_sys() }), - 1, gtksignal_connect(my $button_what_user = Gtk2::Button->new, - clicked => sub { destroy_widget(); advanced_what_user(undef) }), - 1, gtksignal_connect(my $button_what_other = Gtk2::Button->new, - clicked => sub { destroy_widget(); advanced_what_other() }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - $button_what_sys->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-system-40"), - Gtk2::Label->new(N("System")), - Gtk2::HBox->new(0, 5) - )); - $button_what_user->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-users-40"), - Gtk2::Label->new(N("Users")), - Gtk2::HBox->new(0, 5) - )); - $button_what_other->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-others-40"), - Gtk2::Label->new(N("Other")), - Gtk2::HBox->new(0, 5) - )); - gtkset_sensitive($button_what_sys, !$nonroot_user); - fonction_env(\$box_what, \&advanced_what, \&advanced_box); - $up_box->show_all; -} - -sub advanced_where_net_types { - my ($previous_function) = @_; - my $box_where_net; - - gtkpack($advanced_box, - $box_where_net = gtkpack_(Gtk2::VBox->new(0, 10), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, my $check_where_use_net = Gtk2::CheckButton->new(N("Use network connection to backup")), - 1, Gtk2::HBox->new(0,10), - 0, Gtk2::Label->new(N("Net Method:")), - 0, gtkset_sensitive(my $entry_net_type = Gtk2::ComboBox->new_text, $conf{USE_NET}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,5), - 0, gtkset_sensitive(my $check_use_expect = Gtk2::CheckButton->new(N("Use Expect for SSH")), ($conf{USE_NET} && $conf{NET_PROTO} eq 'ssh')), - 0, gtkset_sensitive(my $check_xfer_keys = Gtk2::CheckButton->new(N("Create/Transfer backup keys for SSH")), ($conf{USE_NET} && $conf{NET_PROTO} eq 'ssh')), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $button_xfer_keys = Gtk2::Button->new(N("Transfer Now")), $conf{DRAK_KEYS}), - ), - 0, gtkset_sensitive(my $check_user_keys = Gtk2::CheckButton->new(N("Other (not drakbackup) keys in place already")), ($conf{USE_NET} && $conf{NET_PROTO} eq 'ssh')), - 0, Gtk2::HSeparator->new, - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Host name or IP.")), $conf{USE_NET}), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $host_name_entry = Gtk2::Entry->new, $conf{USE_NET}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Directory (or module) to put the backup on this host.")), $conf{USE_NET}), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $host_path_entry = Gtk2::Entry->new, $conf{USE_NET}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Login name")), $conf{USE_NET}), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $login_user_entry = Gtk2::Entry->new, $conf{USE_NET}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Password")), $conf{USE_NET}), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $check_remember_pass = Gtk2::CheckButton->new(N("Remember this password")), $conf{USE_NET}), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $passwd_user_entry = Gtk2::Entry->new, $conf{USE_NET}), - ), - ), - ); - $entry_net_type->set_popdown_strings('', @net_methods); - $entry_net_type->entry->set_text($conf{NET_PROTO}); - $button_xfer_keys->signal_connect('clicked', sub { - if ($conf{PASSWD} && $conf{LOGIN} && $conf{HOST_NAME}) { - do_expect("sendkey") unless check_pkg_needs(); - } else { - $in->ask_warn(N("Error"), N("Need hostname, username and password!")); - } - }); - $passwd_user_entry->set_visibility(0); - $passwd_user_entry->set_text($conf{PASSWD}); - $passwd_user_entry->signal_connect('changed', sub { $conf{PASSWD} = $passwd_user_entry->get_text }); - $host_path_entry->set_text($conf{HOST_PATH}); - $host_name_entry->set_text($conf{HOST_NAME}); - $login_user_entry->set_text($conf{LOGIN}); - $host_name_entry->signal_connect('changed', sub { $conf{HOST_NAME} = $host_name_entry->get_text }); - $host_path_entry->signal_connect('changed', sub { $conf{HOST_PATH} = $host_path_entry->get_text }); - $login_user_entry->signal_connect('changed', sub { $conf{LOGIN} = $login_user_entry->get_text }); - $entry_net_type->entry->signal_connect('changed', sub { - $conf{NET_PROTO} = $entry_net_type->entry->get_text; - my $sensitive = 0; - $sensitive = 1 if $conf{NET_PROTO} eq 'ssh'; - $check_use_expect->set_sensitive($sensitive); - $check_xfer_keys->set_sensitive($sensitive); - $button_xfer_keys->set_sensitive($sensitive); - $check_user_keys->set_sensitive($sensitive); - }); - check_list([$check_remember_pass, \$conf{REMEMBER_PASS}]); - gtksignal_connect(gtkset_active($check_where_use_net, $conf{USE_NET}), toggled => sub { - invbool \$conf{USE_NET}; - #- assure other methods disabled - if ($conf{USE_NET} == 1) { - $conf{USE_CD} = 0; - $conf{USE_TAPE} = 0; - } - $conf{NET_PROTO} = '' if $conf{USE_NET} == 0; - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_use_expect, $conf{USE_EXPECT}), toggled => sub { - invbool \$conf{USE_EXPECT}; - #- assure other methods disabled - if ($conf{USE_EXPECT} == 1) { - $conf{DRAK_KEYS} = 0; - $conf{USER_KEYS} = 0; - } - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_xfer_keys, $conf{DRAK_KEYS}), toggled => sub { - invbool \$conf{DRAK_KEYS}; - #- assure other methods disabled - if ($conf{DRAK_KEYS} == 1) { - $conf{USE_EXPECT} = 0; - $conf{USER_KEYS} = 0; - } - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_user_keys, $conf{USER_KEYS}), toggled => sub { - invbool \$conf{USER_KEYS}; - #- assure other methods disabled - if ($conf{USER_KEYS} == 1) { - $conf{DRAK_KEYS} = 0; - $conf{USE_EXPECT} = 0; - } - destroy_widget(); - $current_widget->($previous_function); - }); - set_help_tip($check_use_expect, 'use_expect'); - set_help_tip($check_remember_pass, 'remember_pass'); - set_help_tip($host_path_entry, 'dir_or_module'); - if ($previous_function) { - fonction_env(\$box_where_net, \&advanced_where_net_types, \&$previous_function, \&wizard_step3); - button_box_wizard(); - } else { - fonction_env(\$box_where_net, \&advanced_where_net_types, \&advanced_where); - } - $up_box->show_all; -} - -sub advanced_where_cd { - my ($previous_function) = @_; - my $box_where_cd; - my %dev_codes; - - get_cd_info(); - - foreach my $key (keys %cd_devices) { - $dev_codes{$cd_devices{$key}{rec_dev}} = $key; - } - - my $combo_where_cd_device = Gtk2::ComboBox->new_with_strings(%cd_devices ? [ sort keys %dev_codes ] : \@no_devices); - my $combo_where_cd_time = Gtk2::ComboBox->new_with_strings([ "650 MB", "700 MB", "750 MB", "800 MB", "4.7 GB" ]); - - gtkpack($advanced_box, - $box_where_cd = gtkpack_(Gtk2::VBox->new(0, 6), - 0, my $check_where_cd = Gtk2::CheckButton->new(N("Use CD-R/DVD-R to backup")), - 0, Gtk2::HSeparator->new, - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Choose your CD/DVD device")), $conf{USE_CD}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive($combo_where_cd_device, $conf{USE_CD}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Choose your CD/DVD media size")), $conf{USE_CD}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive($combo_where_cd_time, $conf{USE_CD}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Multisession CD")), $conf{USE_CD}), - 0, gtkset_sensitive(my $check_multisession = Gtk2::CheckButton->new, $conf{USE_CD}), - 0, gtkset_sensitive(Gtk2::Label->new(N("CDRW media")), $conf{USE_CD}), - 0, gtkset_sensitive(my $check_cdrw = Gtk2::CheckButton->new, $conf{USE_CD}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Erase your RW media (1st Session)")), $conf{CDRW} && $conf{USE_CD}), - 0, gtkset_sensitive(my $button_erase_now = Gtk2::Button->new(N(" Erase Now ")), $conf{CDRW}), - 0, gtkset_sensitive(my $check_cdrw_erase = Gtk2::CheckButton->new, $conf{CDRW} && $conf{USE_CD}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(Gtk2::Label->new(N("DVD+RW media")), $conf{USE_CD}), - 0, gtkset_sensitive(my $check_dvdrw = Gtk2::CheckButton->new, $conf{USE_CD}), - 0, gtkset_sensitive(Gtk2::Label->new(N("DVD-R media")), $conf{USE_CD}), - 0, gtkset_sensitive(my $check_dvdr = Gtk2::CheckButton->new, $conf{USE_CD}), - 0, gtkset_sensitive(Gtk2::Label->new(N("DVDRAM device")), $conf{USE_CD}), - 0, gtkset_sensitive(my $check_dvdram = Gtk2::CheckButton->new, $conf{USE_CD}), - ), - ), - ); - - foreach ([$check_cdrw_erase, \$conf{MEDIA_ERASE}], [$check_dvdrw, \$conf{DVDRW}], [$check_dvdr, \$conf{DVDR}], [$check_dvdram, \$conf{DVDRAM}], [$check_multisession, \$conf{MULTI_SESSION}]) { - my $ref = $_->[1]; - gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 }); - } - gtksignal_connect(gtkset_active($check_where_cd, $conf{USE_CD}), toggled => sub { - $conf{USE_CD} = $conf{USE_CD} ? 0 : 1; - #- toggle where_net, where_tape off - if ($conf{USE_CD} == 1) { - $conf{USE_NET} = 0; - $conf{USE_TAPE} = 0; - } - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_cdrw, $conf{CDRW}), toggled => sub { - $conf{CDRW} = $conf{CDRW} ? 0 : 1; - $conf{MEDIA_ERASE} = $conf{MEDIA_ERASE} ? 0 : 1; - $check_cdrw_erase->set_sensitive($conf{CDRW}); - destroy_widget(); - $current_widget->($previous_function); - }); - $button_erase_now->signal_connect('clicked', sub { - if ($conf{CD_DEVICE}) { - erase_cdrw(); - } else { - $in->ask_warn(N("Error"), N("No CD device defined!")); - } - }); - - $combo_where_cd_time->entry->set_text($conf{CD_TIME}) if $conf{CD_TIME}; - $combo_where_cd_time->entry->signal_connect('changed', sub { $conf{CD_TIME} = $combo_where_cd_time->entry->get_text }); - - $combo_where_cd_device->entry->set_text($conf{CD_DEVICE}) if $conf{CD_DEVICE}; - $combo_where_cd_device->entry->signal_connect('changed', sub { - $conf{CD_DEVICE} = $combo_where_cd_device->entry->get_text; - $std_device = $dev_codes{$conf{CD_DEVICE}}; - $check_dvdr->set_active($cd_devices{$std_device}{dvdr}); - $check_dvdrw->set_active($cd_devices{$std_device}{dvdr}); - $check_dvdram->set_active($cd_devices{$std_device}{dvdram}); - $check_cdrw->set_active($cd_devices{$std_device}{cdrw}); - }); - - set_help_tip($button_erase_now, 'erase_cdrw'); - - if ($previous_function) { - fonction_env(\$box_where_cd, \&advanced_where_cd, \&$previous_function, \&wizard_step3); - button_box_wizard(); - } else { - fonction_env(\$box_where_cd, \&advanced_where_cd, \&advanced_where); - } - $up_box->show_all; -} - -sub advanced_where_tape { - my ($previous_function) = @_; - - #- look for tape devices; - get_tape_info(); - - my $combo_where_tape_device = Gtk2::ComboBox->new_with_strings(@tape_devices ? \@tape_devices : \@no_devices); - - my $box_where_tape; - local $_; - - gtkpack($advanced_box, - $box_where_tape = gtkpack_(Gtk2::VBox->new(0, 6), - 0, Gtk2::HSeparator->new, - 0, my $check_where_tape = Gtk2::CheckButton->new(N("Use tape to backup")), - 0, Gtk2::HSeparator->new, - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Device name to use for backup")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 6), - 0, gtkset_sensitive($combo_where_tape_device, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Backup directly to tape")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(my $direct_to_tape = Gtk2::CheckButton->new, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Use tape hardware compression (EXPERIMENTAL)")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(my $hdw_compression = Gtk2::CheckButton->new, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Do not rewind tape after backup")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(my $check_tape_rewind = Gtk2::CheckButton->new, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Erase tape before backup")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(my $check_tape_erase = Gtk2::CheckButton->new, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Eject tape after the backup")), $conf{USE_TAPE}), - 1, Gtk2::VBox->new(0, 5), - 0, gtkset_sensitive(my $check_tape_eject = Gtk2::CheckButton->new, $conf{USE_TAPE}), - ), - 0, Gtk2::VBox->new(0, 6), - 0, gtkpack_(Gtk2::HBox->new(0,10),), - ), - ); - gtksignal_connect(gtkset_active($check_where_tape, $conf{USE_TAPE}), toggled => sub { - $conf{USE_TAPE} = $conf{USE_TAPE} ? 0 : 1; - #- assure other methods are off - if ($conf{USE_TAPE} == 1) { - $conf{USE_NET} = 0; - $conf{USE_CD} = 0; - } - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_tape_rewind, $conf{TAPE_NOREWIND}), toggled => sub { - $conf{TAPE_NOREWIND} = $conf{TAPE_NOREWIND} ? 0 : 1; - $_ = $conf{TAPE_DEVICE}; - if ($conf{TAPE_NOREWIND}) { - $conf{TAPE_DEVICE} =~ s|/st|/nst|; - } else { - $conf{TAPE_DEVICE} =~ s|/nst|/st|; - } - $combo_where_tape_device->entry->set_text($conf{TAPE_DEVICE}); - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($direct_to_tape, $conf{DIRECT_TAPE}), toggled => sub { - $conf{DIRECT_TAPE} = $conf{DIRECT_TAPE} ? 0 : 1; - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($hdw_compression, $conf{HDW_COMP}), toggled => sub { - $conf{HDW_COMP} = $conf{HDW_COMP} ? 0 : 1; - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_tape_erase, $conf{MEDIA_ERASE}), toggled => sub { - $conf{MEDIA_ERASE} = $conf{MEDIA_ERASE} ? 0 : 1; - destroy_widget(); - $current_widget->($previous_function); - }); - gtksignal_connect(gtkset_active($check_tape_eject, $conf{MEDIA_EJECT}), toggled => sub { - $conf{MEDIA_EJECT} = $conf{MEDIA_EJECT} ? 0 : 1; - destroy_widget(); - $current_widget->($previous_function); - }); - $combo_where_tape_device->entry->set_text($conf{TAPE_DEVICE}) if $conf{TAPE_DEVICE}; - $combo_where_tape_device->entry->signal_connect('changed', sub { - $conf{TAPE_DEVICE} = $combo_where_tape_device->entry->get_text; - }); - if ($previous_function) { - fonction_env(\$box_where_tape, \&advanced_where_tape, \&$previous_function, \&wizard_step3); - button_box_wizard(); - } else { - fonction_env(\$box_where_tape, \&advanced_where_tape, \&advanced_where); - } - $up_box->show_all; -} - -sub advanced_where_hd { - my ($previous_function) = @_; - my $box_where_hd; - my $button; - if ($conf{MAX_SPACE} == 1000.0) { - $conf{MAX_SPACE} = int(0.8 * get_free_space($conf{PATH_TO_SAVE})) if -d $conf{PATH_TO_SAVE}; - } - my $adj = Gtk2::Adjustment->new($conf{MAX_SPACE}, 0.0, $conf{MAX_SPACE}, 10.0, 5.0, 0.0); - my $adj2 = Gtk2::Adjustment->new($conf{DEL_OLD}, 0.0, 300.0, 1.0, 10.0, 0.0); - my $spinner; - my $spinner2; - - my $size_group = Gtk2::SizeGroup->new('horizontal'); - my $label_size_group = Gtk2::SizeGroup->new('horizontal'); - gtkpack($advanced_box, - $box_where_hd = gtkpack_(Gtk2::VBox->new(0, 6), - 0, Gtk2::HSeparator->new, - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $l1 = Gtk2::Label->new(N("Enter the directory to save to:")), $conf{USE_HD}), - 1, gtkpack_(my $select_box = Gtk2::HBox->new(0,10), - 1, gtkset_sensitive($save_path_entry = Gtk2::Entry->new, $conf{USE_HD}), - 0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new, clicked => sub { - filedialog_generic(N("Directory to save to"), \$save_path_entry); - }), $conf{USE_HD})), - ), - 0, Gtk2::VBox->new(0, 6), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $l2 = Gtk2::Label->new(N("Maximum disk space\n allocated for backups (MB)")), $conf{USE_HD}), - 1, gtkset_sensitive($spinner = Gtk2::SpinButton->new($adj, 0, 0), $conf{USE_HD}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $l3 = Gtk2::Label->new(N("Delete incremental or differential\n backups older than N days\n (0 is keep all backups) to save space")), $conf{USE_HD}), - 1, gtkset_sensitive($spinner2 = Gtk2::SpinButton->new($adj2, 0, 0), $conf{USE_HD}), - ), - ), - ); - $size_group->add_widget($_) foreach $select_box, $spinner, $spinner2; - $label_size_group->add_widget($_) foreach $l1, $l2, $l3; - - $button->add(gtkpack(Gtk2::HBox->new(0,10), gtkcreate_img("ic82-dossier-32"))); - $save_path_entry->set_text($conf{PATH_TO_SAVE}); - $spinner->signal_connect('changed', sub { $conf{MAX_SPACE} = $spinner->get_text }); - $spinner2->signal_connect('changed', sub { $conf{DEL_OLD} = $spinner2->get_text }); - $save_path_entry->signal_connect('changed', sub { - $conf{PATH_TO_SAVE} = $save_path_entry->get_text; - if (-d $conf{PATH_TO_SAVE}) { - $conf{MAX_SPACE} = int(0.8 * get_free_space($conf{PATH_TO_SAVE})); - # seems to be the easiest way to avoid the widgets fighting over values - # and getting garbage in $max_value - destroy_widget(); - $current_widget->($previous_function); - } - }); - if ($previous_function) { - fonction_env(\$box_where_hd, \&advanced_where_hd, \&$previous_function, \&wizard_step3); - button_box_wizard(); - } else { - fonction_env(\$box_where_hd, \&advanced_where_hd, \&advanced_where); - } - $up_box->show_all; -} - -sub advanced_where() { - my $box_where; - - gtkpack($advanced_box, - $box_where = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtksignal_connect(my $button_where_net = Gtk2::Button->new, clicked => sub { - destroy_widget(); - advanced_where_net_types(undef); - }), - 1, gtksignal_connect(my $button_where_cd = Gtk2::Button->new, clicked => sub { - destroy_widget(); - advanced_where_cd(undef); - }), - 1, gtksignal_connect(my $button_where_hd = Gtk2::Button->new, clicked => sub { - destroy_widget(); - advanced_where_hd(undef); - }), - 1, gtksignal_connect(my $button_where_tape = Gtk2::Button->new, clicked => sub { - destroy_widget(); - advanced_where_tape(undef); - }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - $button_where_net->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-network-40"), - Gtk2::Label->new(N("Network")), - Gtk2::HBox->new(0, 5) - )); - $button_where_cd->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-CD-40"), - Gtk2::Label->new(N("CD-R / DVD-R")), - Gtk2::HBox->new(0, 5) - )); - $button_where_hd->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-discdurwhat-40"), - Gtk2::Label->new(N("HardDrive / NFS")), - Gtk2::HBox->new(0, 5) - )); - $button_where_tape->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-tape-40"), - Gtk2::Label->new(N("Tape")), - Gtk2::HBox->new(0, 5) - )); - fonction_env(\$box_where, \&advanced_where, \&advanced_box); - $up_box->show_all; -} - -sub advanced_when() { - my $box_when; - my $allow_custom = $backup_daemon && $custom_cron; - my $combo_when_space = Gtk2::ComboBox->new_with_strings([ "", N("hourly"), N("daily"), N("weekly"), N("monthly"), N("custom") ]); - my %trans = (N("hourly") => 'hourly', - N("daily") => 'daily', - N("weekly") => 'weekly', - N("monthly") => 'monthly', - N("custom") => 'custom'); - my %trans2 = ('hourly' => N("hourly"), - 'daily' => N("daily"), - 'weekly' => N("weekly"), - 'monthly' => N("monthly"), - 'custom' => N("custom")); - set_help_tip($combo_when_space, 'when_space'); - - #- custom setup - let user specify month, day of month, day of week, hour, minute - my @months = ("*", N("January"), N("February"), N("March"), - N("April"), N("May"), N("June"), N("July"), N("August"), N("September"), - N("October"), N("November"), N("December")); - my $combo_month_when = Gtk2::ComboBox->new_with_strings(\@months); - my $combo_day_when = Gtk2::ComboBox->new_with_strings([ "*", (1..31) ]); - my @weekdays = ("*", N("Sunday"), N("Monday"), N("Tuesday"), - N("Wednesday"), N("Thursday"), N("Friday"), N("Saturday")); - my $combo_weekday_start = Gtk2::ComboBox->new_with_strings(\@weekdays); - my $combo_weekday_end = Gtk2::ComboBox->new_with_strings(\@weekdays); - my $combo_hour_when = Gtk2::ComboBox->new_with_strings([ "*", (0..23) ]); - my $combo_minute_when = Gtk2::ComboBox->new_with_strings([ "*", (0..59) ]); - my @profiles = glob_("$cfg_dir/*.conf"); - @profiles = map { basename($_) } @profiles; - @profiles = difference2(\@profiles, [ ("drakbackup.conf") ]); - unshift(@profiles, N("Default")); - my $combo_profile = Gtk2::ComboBox->new_with_strings(\@profiles); - - my $cron_model = Gtk2::ListStore->new("Glib::String"); - my $list_cron = Gtk2::TreeView->new_with_model($cron_model); - $list_cron->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - $list_cron->set_headers_visible(0); - my $cron_iter; - my $cron_entry; - - read_user_cron(); - foreach (@cron_entries) { - $cron_model->append_set(0, $_) if !/^#/; - } - - $list_cron->get_selection->signal_connect(changed => sub { - my ($model, $iter) = $_[0]->get_selected; - $model && $iter or return; - $cron_entry = $model->get($iter, 0); - $cron_iter = $iter; - }); - - my $del_button = Gtk2::Button->new(N("Delete cron entry")); - my $add_button = Gtk2::Button->new(N("Add cron entry")); - - $del_button->signal_connect(clicked => sub { - $cron_model->remove($cron_iter) if $cron_iter; - my $iindex = 0; - foreach (@cron_entries) { - if ($_ eq $cron_entry) { - splice(@cron_entries, $iindex, 1); - last; - } - $iindex++; - } - }); - - my $entry_crontab = Gtk2::Entry->new; - gtkset_editable($entry_crontab, 0); - - $add_button->signal_connect(clicked => sub { - my $entry = $entry_crontab->get_text; - $cron_model->append_set(0, $entry); - push @cron_entries, $entry; - }); - - my @time_list = split(" ", $time_string); - $combo_minute_when->entry->set_text($time_list[0]); - $combo_hour_when->entry->set_text($time_list[1]); - $combo_day_when->entry->set_text($time_list[2]); - if ($time_list[3] =~ /\*/) { - $combo_month_when->entry->set_text($time_list[3]); - } else { - $combo_month_when->entry->set_text($months[$time_list[3]]); - } - my $start; - my $end = "*"; - if ($time_list[4] =~ /\*/) { - $start = "*"; - } else { - if (length($time_list[4]) > 1) { - my @span = split("-", $time_list[4]); - $start = $weekdays[$span[0] + 1]; - $end = $weekdays[$span[1] + 1]; - } else { - $start = $weekdays[$time_list[4] + 1]; - } - } - $combo_weekday_start->entry->set_text($start); - $combo_weekday_end->entry->set_text($end); - - $combo_profile->entry->set_text(substr($profile_string, 10)) if $profile_string ne ""; - - #- drop down list of possible media - default to config value - my $combo_media_type = Gtk2::ComboBox->new_with_strings([ sort(@net_methods, @media_types) ], $conf{DAEMON_MEDIA}); - - gtkpack($advanced_box, - $box_when = gtkpack_(Gtk2::VBox->new(0, 5), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::HBox->new(0,10), - 1, gtkcreate_img("ic82-when-40"), - 0, my $check_when_daemon = Gtk2::CheckButton->new(N("Use daemon")), - 1, Gtk2::HBox->new(0,10), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Please choose the time interval between each backup")), $backup_daemon), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive($combo_when_space, $backup_daemon), - ), - 0, Gtk2::HSeparator->new, - 0, gtkset_sensitive($entry_crontab, $allow_custom), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Minute")), $allow_custom), - 0, gtkset_sensitive($combo_minute_when, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Hour")), $allow_custom), - 0, gtkset_sensitive($combo_hour_when, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Day")), $allow_custom), - 0, gtkset_sensitive($combo_day_when, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Month")), $allow_custom), - 0, gtkset_sensitive($combo_month_when, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Weekday (start)")), $allow_custom), - 0, gtkset_sensitive($combo_weekday_start, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Weekday (end)")), $allow_custom), - 0, gtkset_sensitive($combo_weekday_end, $allow_custom), - ), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(Gtk2::Label->new(N("Profile")), $allow_custom), - 0, gtkset_sensitive($combo_profile, $allow_custom), - ), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, gtkset_sensitive($del_button, $allow_custom), - 1, gtkset_sensitive(Gtk2::Label->new(N("Current crontab:")), $allow_custom), - 1, gtkset_sensitive($add_button, $allow_custom), - ), - 1, gtkpack_(Gtk2::HBox->new(0,4), - 1, create_scrolled_window(gtkset_sensitive($list_cron, $allow_custom)), - ), - 0, Gtk2::HSeparator->new, - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Please choose the media for backup.")), $backup_daemon), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive($combo_media_type, $backup_daemon), - ), - 0, gtkset_sensitive(Gtk2::Label->new(N("Please be sure that the cron daemon is included in your services.")), $backup_daemon), - 0, gtkset_sensitive(Gtk2::Label->new(N("If your machine is not on all the time, you might want to install anacron.")), $backup_daemon), - ), - ); - - gtksignal_connect(gtkset_active($check_when_daemon, $backup_daemon), toggled => sub { - $backup_daemon = $backup_daemon ? 0 : 1; - destroy_widget(); - advanced_when(); - }); - $combo_when_space->entry->set_text($trans2{$conf{DAEMON_TIME_SPACE}}); - $combo_when_space->entry->signal_connect('changed', sub { - $conf{DAEMON_TIME_SPACE} = $trans{$combo_when_space->entry->get_text}; - $custom_cron = $conf{DAEMON_TIME_SPACE} eq "custom" ? 1 : 0; - destroy_widget(); - advanced_when(); - }); - if ($custom_cron) { - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - } - - $combo_minute_when->entry->signal_connect('changed', sub { - combo_to_cron_string($combo_minute_when->get_text, 0); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_hour_when->entry->signal_connect('changed', sub { - combo_to_cron_string($combo_hour_when->get_text, 1); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_day_when->entry->signal_connect('changed', sub { - combo_to_cron_string($combo_day_when->get_text, 2); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_month_when->entry->signal_connect('changed', sub { - combo_to_cron_string($combo_month_when->get_active, 3); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_weekday_start->entry->signal_connect('changed', sub { - my $start = $combo_weekday_start->get_active - 1; - my $end = $combo_weekday_end->get_active - 1; - $start = $start . "-" . $end if $end > -1 && $start < $end; - combo_to_cron_string($start, 4); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_weekday_end->entry->signal_connect('changed', sub { - my $start = $combo_weekday_start->get_active - 1; - my $end = $combo_weekday_end->get_active - 1; - $start = $start . "-" . $end if $start > -1 && $start < $end; - combo_to_cron_string($start, 4); - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_profile->entry->signal_connect('changed', sub { - $profile_string = "--profile " . $combo_profile->get_text; - $profile_string = "" if $combo_profile->get_active == 0; - $entry_crontab->set_text("$time_string $exec_string $profile_string $redir_string"); - }); - $combo_media_type->entry->signal_connect('changed', sub { $conf{DAEMON_MEDIA} = $combo_media_type->entry->get_text }); - fonction_env(\$box_when, \&advanced_when, \&advanced_box); - $up_box->show_all; -} - -sub combo_to_cron_string { - my ($field, $location) = @_; - $field = "*" if $field == 0 && $location == 3; - $field = "*" if $field == -1 && $location == 4; - my @time_list = split(" ", $time_string); - splice(@time_list, $location, 1, $field); - $time_string = join(" ", @time_list); -} - -sub advanced_options() { - my $box_options; - my $entry_archiver = Gtk2::ComboBox->new_with_strings([ "tar", "star" ], $conf{ARCHIVER}); - my $entry_comp_mode = Gtk2::ComboBox->new_with_strings([ "tar", "tar.gz", "tar.bz2" ], $conf{OPTION_COMP}); - gtkpack($advanced_box, - $box_options = gtkpack_(Gtk2::VBox->new(0, 15), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, Gtk2::Label->new(N("Please choose the archive program")), - 1, Gtk2::HBox->new(0,10), - 0, $entry_archiver, - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, Gtk2::Label->new(N("Please choose the compression type")), - 1, Gtk2::HBox->new(0,10), - 0, $entry_comp_mode, - ), - 0, my $check_backupignore = Gtk2::CheckButton->new(N("Use .backupignore files")), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, my $check_mail = Gtk2::CheckButton->new(N("Send mail report after each backup to:")), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $mail_entry = Gtk2::Entry->new, $conf{SEND_MAIL}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::HBox->new(0,10), - 0, N("Return address for sent mail:"), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $from_entry = Gtk2::Entry->new, $conf{SEND_MAIL}), - ), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::HBox->new(0,10), - 0, N("SMTP server for mail:"), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(my $smtp_entry = Gtk2::Entry->new, $conf{SEND_MAIL}), - ), - 0, my $check_del_hd_files = Gtk2::CheckButton->new(N("Delete Hard Drive tar files after backup to other media.")), - 0, my $check_view_restore_log = Gtk2::CheckButton->new(N("View restore log after file restore.")), - ), - ); - check_list([$check_mail, \$conf{SEND_MAIL}], [$check_del_hd_files, \$conf{DEL_HD_FILES}], [$check_backupignore, \$conf{BACKUPIGNORE}], [$check_view_restore_log, \$conf{VIEW_RESTORE_LOG}]); - $mail_entry->set_text($conf{USER_MAIL}); - $mail_entry->signal_connect('changed', sub { $conf{USER_MAIL} = $mail_entry->get_text }); - $from_entry->set_text($conf{FROM_MAIL}); - $from_entry->signal_connect('changed', sub { $conf{FROM_MAIL} = $from_entry->get_text }); - $smtp_entry->set_text($conf{SMTP_SERVER}); - $smtp_entry->signal_connect('changed', sub { $conf{SMTP_SERVER} = $smtp_entry->get_text }); - $entry_archiver->entry->signal_connect('changed', sub { $conf{ARCHIVER} = $entry_archiver->entry->get_text }); - $entry_comp_mode->entry->signal_connect('changed', sub { $conf{OPTION_COMP} = $entry_comp_mode->entry->get_text }); - set_help_tip($entry_archiver, 'choose_archiver'); - set_help_tip($check_backupignore, 'backupignore'); - set_help_tip($check_mail, 'send_mail_to'); - set_help_tip($from_entry, 'send_mail_from'); - set_help_tip($check_del_hd_files, 'delete_files'); - set_help_tip($check_view_restore_log, 'view_log'); - fonction_env(\$box_options, \&advanced_options, \&advanced_box); - $up_box->show_all; -} - -sub advanced_box() { - my $box_adv; - - gtkpack($advanced_box, - $box_adv = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtksignal_connect(my $button_what = Gtk2::Button->new, clicked => sub { - destroy_widget(); advanced_what() }), - 1, gtksignal_connect(my $button_where = Gtk2::Button->new, clicked => sub { - destroy_widget(); advanced_where() }), - 1, gtksignal_connect(my $button_when = Gtk2::Button->new, clicked => sub { - destroy_widget(); advanced_when() }), - 1, gtksignal_connect(my $button_options = Gtk2::Button->new, clicked => sub { - destroy_widget(); advanced_options() }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - $button_what->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-discdurwhat-40"), - Gtk2::Label->new(N("What")), - Gtk2::HBox->new(0, 5) - )); - $button_where->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-where-40"), - Gtk2::Label->new(N("Where")), - Gtk2::HBox->new(0, 5) - )); - $button_when->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-when-40"), - Gtk2::Label->new(N("When")), - Gtk2::HBox->new(0, 5) - )); - $button_options->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-moreoption-40"), - Gtk2::Label->new(N("More Options")), - Gtk2::HBox->new(0, 5) - )); - fonction_env(\$box_adv, \&advanced_box, \&interactive_mode_box); - $up_box->show_all; -} - -################################################ WIZARD ################################################ - -sub wizard_step3() { - destroy_widget(); - my $no_device = $conf{USE_CD} && $conf{CD_DEVICE} eq '' || $conf{USE_TAPE} && $conf{TAPE_DEVICE} eq '' || $conf{USE_NET} && $conf{NET_PROTO} eq '' && 1; - if ($no_device) { - show_warning("f", N("Backup destination not configured...")); - advanced_where_net_types(\&wizard_step2) if $conf{USE_NET}; - advanced_where_cd(\&wizard_step2) if $conf{USE_CD}; - advanced_where_tape(\&wizard_step2) if $conf{USE_TAPE}; - return; - } - if (check_pkg_needs()) { - interactive_mode_box(); - return; - } - my $text = Gtk2::TextView->new; - save_conf_file(); - read_conf_file(); - system_state(); - gtktext_insert($text, [ [ $system_state ] ]); - button_box_restore_main(); - - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, gtkpack_(Gtk2::VBox->new(0,10), - 0, N("Drakbackup Configuration"), - 1, create_scrolled_window($text), - ), - ), - ); - fonction_env(\$box2, \&wizard_step3, \&wizard_step2); - button_box_wizard_end(); - $up_box->show_all; -} - -sub wizard_step2() { - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 0, N("Please choose where you want to backup"), - 0, gtkpack_(Gtk2::HBox->new(0, 15), - 0, gtkpack__(Gtk2::VBox->new(0, 10), - my @where_radio = gtkradio('', N("Hard Drive used to prepare backups for all media"), N("Across Network"), N("On CD-R"), N("On Tape Device")), - ), - 1, gtkpack_(Gtk2::HBox->new(0,5),), - 0, gtkpack_(Gtk2::VBox->new(0,5), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Configure")), clicked => sub { - destroy_widget(); - advanced_where_hd(\&wizard_step2); - }), $use_hd), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Configure")), clicked => sub { - destroy_widget(); - advanced_where_net_types(\&wizard_step2); - }), $conf{USE_NET}), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Configure")), clicked => sub { - destroy_widget(); - advanced_where_cd(\&wizard_step2); - }), $conf{USE_CD}), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Configure")), clicked => sub { - destroy_widget(); - advanced_where_tape(\&wizard_step2); - }), $conf{USE_TAPE}), - ), - ), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - my @wheres = ($use_hd, $conf{USE_NET}, $conf{USE_CD}, $conf{USE_TAPE}); - foreach my $i (0..3) { - $where_radio[$i]->set_active($wheres[$i]); - $where_radio[$i]->signal_connect(toggled => sub { - if ($where_radio[$i]->get_active) { - @wheres = (0, 0, 0, 0); - $wheres[$i] = 1; - ($use_hd, $conf{USE_NET}, $conf{USE_CD}, $conf{USE_TAPE}) = @wheres; - destroy_widget(); - wizard_step2(); - } - }); - } - fonction_env(\$box2, \&wizard_step2, \&wizard, undef); - button_box_wizard(); - $up_box->show_all; -} - -sub wizard() { - my $user_string = N("Backup Users"); - $user_string .= N(" (Default is all users)") if !$nonroot_user; - if (!$conf{NO_USER_FILES} && !$manual_user) { - all_user_list() if @user_list_all == (); - @user_list = @user_list_all; - } elsif (!$manual_user) { - @user_list = (); - } - - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 0, N("Please choose what you want to backup"), - 0, gtkset_sensitive(my $check_wizard_sys = Gtk2::CheckButton->new(N("Backup System")), !$nonroot_user), - 0, my $check_wizard_user = Gtk2::CheckButton->new($user_string), - 0, gtksignal_connect(Gtk2::Button->new(N("Select user manually")), clicked => sub { - $manual_user = 1; - destroy_widget(); - advanced_what_user(\&wizard); - }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - foreach ([$check_wizard_sys, \$conf{NO_SYS_FILES}], [$check_wizard_user, \$conf{NO_USER_FILES}]) { - my $ref = $_->[1]; - gtksignal_connect(gtkset_active($_->[0], !$$ref), toggled => sub { - $$ref = $$ref ? 0 : 1; - if (!$conf{NO_SYS_FILES} || !$conf{NO_USER_FILES} && @user_list) { - $next_widget = \&wizard_step2; - } else { - $next_widget = \&wizard; - } - if (!$conf{NO_USER_FILES}) { - @user_list = @user_list_all; - } else { - @user_list = (); - } - }); - } - if (!$conf{NO_SYS_FILES} || !$conf{NO_USER_FILES} && @user_list) { - fonction_env(\$box2, \&wizard, \&interactive_mode_box, \&wizard_step2); - } else { - $in->ask_warn(N("Error"), N("Please select data to backup...")); - fonction_env(\$box2, \&wizard, \&interactive_mode_box, \&wizard); - } - button_box_wizard(); - $up_box->show_all; -} - -################################################ RESTORE ################################################ - -sub find_backup_to_restore() { - my @list_backup; - my @list_backup_tmp2; - my $to_put; - my $nom; - @sys_backuped = (); - local $_; - - @user_backuped = (); - -d $path_to_find_restore and @list_backup_tmp2 = all($path_to_find_restore); - - foreach (@list_backup_tmp2) { - s/_base//gi; - s/_incr//gi; - push @list_backup , $_; - } - foreach (grep { /^backup_sys_/ } @list_backup) { - ($to_put, undef) = file_to_put($_, "sys"); - push @sys_backuped , $to_put; - } - $restore_step_sys_date = $to_put; - foreach (grep { /^backup_other_/ } @list_backup) { - ($to_put, undef) = file_to_put($_, "other"); - push @other_backuped , $to_put; - } - $restore_step_other_date = $to_put; - foreach (grep { /^backup_user_/ } @list_backup) { - ($to_put, $nom) = file_to_put($_, "user"); - push @user_backuped , $to_put; - any { /^$nom$/ } @user_list_backuped or push @user_list_backuped, $nom; - } -} - -sub file_to_put { - my ($name, $type) = @_; - my $to_put; - my ($nom, $date, $heure); - local $_ = $name; - chomp; - $name = "backup_" . $type . "_"; - s/^$name//gi; - s/.tar|.gz|.bz2$//gi; - if ($type eq "user") { - ($nom, $date, $heure) = /^(.*)_([^_]*)_([^_]*)$/; - } else { - ($date, $heure) = /^(.*)_([^_]*)$/; - } - my $year = substr($date, 0, 4); - my $month = substr($date, 4, 2); - my $day = substr($date, 6, 2); - my $hour = substr($heure, 0, 2); - my $min = substr($heure, 2, 2); - if ($type eq "user") { - $to_put = "$_ user: $nom, date: $day/$month/$year, hour: $hour:$min"; - return $to_put, $nom; - } else { - $to_put = "$day/$month/$year $hour:$min $_"; - return $to_put, undef; - } -} - -sub system_state() { - if ($cfg_file_exist) { - $system_state = N("\nBackup Sources: \n"); - $conf{NO_SYS_FILES} or $system_state .= N("\n- System Files:\n"); - $conf{NO_SYS_FILES} or $system_state .= "\t\t$_\n" foreach @sys_files; - $conf{NO_USER_FILES} or $system_state .= N("\n- User Files:\n"); - $conf{NO_USER_FILES} or $system_state .= "\t\t$_\n" foreach @user_list; - $conf{OTHER_FILES} and $system_state .= N("\n- Other Files:\n"); - $conf{OTHER_FILES} and $system_state .= "\t\t$_\n" foreach @other_files; - $conf{USE_HD} and $system_state .= N("\n- Save on Hard drive on path: %s\n", $conf{PATH_TO_SAVE}); - $conf{USE_HD} and $system_state .= N("\tLimit disk usage to %s MB\n", $conf{MAX_SPACE}); - $conf{DEL_OLD} and $system_state .= N("\tDelete backups older than %s day(s)\n", $conf{DEL_OLD}); - - if ($conf{DEL_HD_FILES} && ($conf{USE_CD} || $conf{USE_TAPE} || $conf{USE_NET}) && $conf{DAEMON_MEDIA} ne 'hd') { - $system_state .= N("\n- Delete hard drive tar files after backup.\n"); - } - - #- tape and CDRW share some features - my $erase_media = $conf{MEDIA_ERASE} && ($conf{USE_CD} || $conf{USE_TAPE}) ? N("Yes") : N("No"); - $conf{USE_CD} and $system_state .= N("\n- Burn to CD"); - $conf{USE_CD} and $conf{CDRW} and $system_state .= N("RW"); - $conf{USE_CD} and $system_state .= N(" on device: %s", $conf{CD_DEVICE}); - $conf{USE_CD} && $conf{MULTI_SESSION} and $system_state .= N(" (multi-session)"); - $conf{USE_TAPE} and $system_state .= N("\n- Save to Tape on device: %s", $conf{TAPE_DEVICE}); - (($conf{USE_CD} || $conf{USE_TAPE}) && $conf{MEDIA_ERASE}) and $system_state .= N("\t\tErase=%s", $erase_media); - $conf{USE_CD} || $conf{USE_TAPE} and $system_state .= "\n"; - $conf{USE_TAPE} && $conf{DIRECT_TAPE} and $system_state .= N("\tBackup directly to Tape\n"); - - $conf{USE_NET} and $system_state .= N("\n- Save via %s on host: %s\n", $conf{NET_PROTO}, $conf{HOST_NAME}); - $conf{USE_NET} and $system_state .= N("\t\t user name: %s\n\t\t on path: %s \n", $conf{LOGIN}, $conf{HOST_PATH}); - $system_state .= N("\n- Options:\n"); - $conf{NO_SYS_FILES} and $system_state .= N("\tDo not include System Files\n"); - - $system_state .= N("\tBackups use %s and bzip2\n", $conf{ARCHIVER}) if $conf{OPTION_COMP} eq "tar.bz2"; - $system_state .= N("\tBackups use %s and gzip\n", $conf{ARCHIVER}) if $conf{OPTION_COMP} eq "tar.gz"; - $system_state .= N("\tBackups use %s only\n", $conf{ARCHIVER}) if $conf{OPTION_COMP} eq "tar"; - - $system_state .= N("\tUse .backupignore files\n") if $conf{BACKUPIGNORE}; - $system_state .= N("\tSend mail to %s\n", $conf{USER_MAIL}) if $conf{SEND_MAIL}; - $system_state .= N("\tSend mail from %s\n", $conf{FROM_MAIL}) if $conf{SEND_MAIL}; - $system_state .= N("\tUsing SMTP server %s\n", $conf{SMTP_SERVER}) if $conf{SEND_MAIL}; - - $conf{DAEMON_MEDIA} and $system_state .= N("\n- Daemon, %s via:\n", $conf{DAEMON_TIME_SPACE}); - $conf{DAEMON_MEDIA} eq 'hd' and $system_state .= N("\t-Hard drive.\n"); - $conf{DAEMON_MEDIA} eq 'cd' and $system_state .= N("\t-CD-R.\n"); - $conf{DAEMON_MEDIA} eq 'tape' and $system_state .= N("\t-Tape \n"); - $conf{DAEMON_MEDIA} eq 'ftp' and $system_state .= N("\t-Network by FTP.\n"); - $conf{DAEMON_MEDIA} eq 'ssh' and $system_state .= N("\t-Network by SSH.\n"); - $conf{DAEMON_MEDIA} eq 'rsync' and $system_state .= N("\t-Network by rsync.\n"); - } else { - $system_state = N("No configuration, please click Wizard or Advanced.\n"); - } -} - -sub restore_state() { - $restore_state = N("List of data to restore:\n\n"); - if ($restore_sys) { - $restore_state .= N("- Restore System Files.\n"); - my @tmp = split(' ', $restore_step_sys_date); - $restore_state .= N(" - from date: %s %s\n", $tmp[0], $tmp[1]); - } - if ($restore_user) { - $restore_state .= N("- Restore User Files: \n"); - $restore_state .= "\t\t$_\n" foreach @user_list_to_restore2; - push @user_list_to_restore, (split(',', $_))[0] foreach @user_list_to_restore2; - } - if ($restore_other) { - $restore_state .= N("- Restore Other Files: \n"); - my @tmp = split(' ', $restore_step_other_date); - $restore_state .= N(" - from date: %s %s\n", $tmp[0], $tmp[1]); - } - if ($restore_other_path) { - $restore_state .= "- Path to Restore: $restore_path \n"; - } -} - -sub select_most_recent_selected_of { - my ($user_name) = @_; - my @tmp = sort @user_list_to_restore2; - my @list_tmp2 = grep { /$user_name/ } sort @tmp; - return pop @list_tmp2; -} - -sub select_user_data_to_restore() { - my $var_eq = 1; - my @list_backup; - my @list_tmp; - my @list_tmp2; - @user_list_to_restore = (); - local $_; - - my @list_backup_tmp2 = -d $path_to_find_restore && grep { /^backup/ } all($path_to_find_restore); - @list_tmp2 = @list_backup_tmp2; - foreach (@list_backup_tmp2) { - s/_base//gi; - s/_incr//gi; - push @list_backup , $_; - } - foreach my $var_tmp (@user_list_backuped) { - $var_eq = 1; - my $more_recent = (split(' ', select_most_recent_selected_of($var_tmp)))[0]; - foreach (grep { /^backup_user_$var_tmp/ } sort @list_backup) { - s/.$conf{OPTION_COMP}//gi; - if ($more_recent) { - if (/$more_recent/) { - push @list_tmp , $_; - $var_eq = 0; - } else { - #- only if user asked for it - previously this was restoring everything (SB) - my $tmp_name = $_; - s/backup_user_//gi; - foreach my $buff (@user_list_to_restore2) { - if (index($buff, $_) >= 0) { - $var_eq and push @list_tmp , $tmp_name; - } - } - } - } - } - } - foreach my $var_to_restore (@list_tmp) { - $var_to_restore =~ s/backup_//gi; - foreach my $var_exist (sort @list_tmp2) { - if ($var_exist =~ /$var_to_restore/) { - push @user_list_to_restore, $var_exist; - } - } - } - $DEBUG and print "real user list to restore: $_ \n" foreach @user_list_to_restore; -} - -sub select_sys_data_to_restore() { - my $var_eq = 1; - my @list_tmp; - local $_; - - -d $path_to_find_restore and @list_tmp = grep { /^backup/ } all($path_to_find_restore); - my @more_recent = split(' ', $restore_step_sys_date); - my $more_recent = pop @more_recent; - foreach my $var_exist (grep { /_sys_/ } sort @list_tmp) { - if ($var_exist =~ /$more_recent/) { - push @sys_list_to_restore, $var_exist; - $var_eq = 0; - } else { - $var_eq and push @sys_list_to_restore, $var_exist; - } - } - $DEBUG and print "sys list to restore: $_\n " foreach @sys_list_to_restore; -} - -sub select_other_data_to_restore() { - my $var_eq = 1; - my @list_tmp; - local $_; - @other_list_to_restore = (); - - -d $path_to_find_restore and @list_tmp = grep { /^backup/ } all($path_to_find_restore); - my @more_recent = split(' ', $restore_step_other_date); - my $more_recent = pop @more_recent; - foreach my $var_exist (grep { /_other_/ } sort @list_tmp) { - if ($var_exist =~ /$more_recent/) { - push @other_list_to_restore, $var_exist; - $var_eq = 0; - } else { - $var_eq and push @other_list_to_restore, $var_exist; - } - } - $DEBUG and print "other list to restore: $_\n " foreach @other_list_to_restore; -} - -sub show_backup_details { - my ($function, $mode, $name) = @_; - my $archive_file_detail; - my $value; - my $command2; - my $tarfile; - - if ($mode eq "user") { - #- we've only got a partial filename in this case - $tarfile = "$path_to_find_restore/backup_*" . $name . ".tar*"; - } - if ($mode eq "sys") { - #- funky string here we need to use to reconstruct the filename - my @flist = split(/[ \t,]+/, $name); - $tarfile = "$path_to_find_restore/backup_*" . $flist[2] . ".tar*"; - } - my @tarfiles = glob($tarfile); - if ($tarfiles[0] eq "") { - destroy_widget(); - $function->(); - } - $tarfile = $tarfiles[0]; - my $command1 = "stat " . $tarfile; - -### $command2 = "$conf{ARCHIVER} -t -v"; - $command2 = set_tar("list", $tarfile); - $command2 .= " $tarfile"; - - log::explanations("Running $command1"); - $archive_file_detail = `$command1 2>&1` . "\n\n"; - log::explanations("Running $command2"); - my $TMP; - open $TMP, "$command2 2>&1 |"; - while ($value = <$TMP>) { - #- drop the permissions display for the sake of readability - $archive_file_detail .= substr($value, 11); - } - close $TMP; - - my $text = Gtk2::TextView->new; - my $advanced_box_archive; - gtktext_insert(gtkset_editable($text, 0), $archive_file_detail); - gtkpack($advanced_box, - $advanced_box_archive = gtkpack_(Gtk2::VBox->new(0,10), - 1, gtkpack_(Gtk2::HBox->new(0,0), - 1, create_scrolled_window($text), - ), - 0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'spread'), - gtksignal_connect(Gtk2::Button->new(N("Done")), clicked => sub { - destroy_widget(); - $function->() }), - ), - ) - ); - $central_widget = \$advanced_box_archive; - $up_box->show_all; -} - -sub valid_backup_test { - my (@files_list) = @_; - @files_corrupted = (); - my $is_corrupted = 0; - my $comp_test; - foreach (@files_list) { - $comp_test = set_tar("list", $_); - if (system("$comp_test $path_to_find_restore/$_ > /dev/null 2>&1") > 1) { - push @files_corrupted, $_; - $is_corrupted = -1; - } - } - return $is_corrupted; -} - -sub restore_aff_backup_problems() { - my $do_restore; - my $text = Gtk2::TextView->new; - my $restore_pbs_state = N("List of data corrupted:\n\n"); - $restore_pbs_state .= "\t\t$_\n" foreach @files_corrupted; - $restore_pbs_state .= N("Please uncheck or remove it on next time."); - gtktext_insert($text, [ [ $restore_pbs_state ] ]); - button_box_restore_main(); - - gtkpack($advanced_box, - $do_restore = gtkpack_(Gtk2::VBox->new(0,10), - 0, Gtk2::VBox->new(0,10), - 1, gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 0, gtkcreate_img('warning'), - 0, N("Backup files are corrupted"), - 1, Gtk2::VBox->new(0, 5), - ), - 0, Gtk2::VBox->new(0,10), - 1, create_scrolled_window($text), - ), - ); - button_box_restore_pbs_end(); - fonction_env(\$do_restore, \&restore_aff_backup_problems, "restore_pbs"); - $up_box->show_all; -} - -sub restore_aff_result() { - my $do_restore; - my $text = Gtk2::TextView->new; - gtktext_insert($text, [ [ $restore_state ] ]); - button_box_restore_main(); - - gtkpack($advanced_box, - $do_restore = gtkpack_(Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 0, N(" All of your selected data have been "), - 0, N(" Successfully Restored on %s ", $restore_path), - 1, Gtk2::VBox->new(0,10), - ), - ); - button_box_ok_only(); - $central_widget = \$do_restore; - $up_box->show_all; -} - -sub return_path { - my ($username) = @_; - my $usr; - my $home_dir; - my @passwords = cat_("/etc/passwd"); - foreach my $line (@passwords) { - chomp($line); - ($usr, $home_dir) = (split(/:/, $line))[0,5]; - last if $usr eq $username; - } - return $home_dir; -} - -sub restore_backend() { - my $exist_problem = 0; - my $user_dir; - my $username; - local $_; - -d $restore_path or mkdir_p $restore_path; - - if ($restore_user) { - select_user_data_to_restore(); - if (valid_backup_test(@user_list_to_restore) == -1) { - $exist_problem = 1; - restore_aff_backup_problems(); - } else { - foreach (@user_list_to_restore) { - if ($conf{USER_INCREMENTAL_BACKUPS}) { - (undef, $username, undef) = /^(\w+_\w+_user_)(.*)_(\d+_\d+.*)$/; - } else { - (undef, $username, undef) = /^(\w+_user_)(.*)_(\d+_\d+.*)$/; - } - - $user_dir = return_path($username); - -d $user_dir and rm_rf($user_dir) if $remove_user_before_restore; - - my $user_untar = set_tar("restore", $_); - $DEBUG and print "user name to restore: $username, user directory: $user_dir\n"; - system("$user_untar $path_to_find_restore/$_ -C $restore_path"); - } - #- flush this out for another cycle (SB) - @user_list_to_restore2 = (); - } - } - - if ($restore_sys) { - select_sys_data_to_restore(); - if (valid_backup_test(@sys_list_to_restore) == -1) { - $exist_problem = 1; - restore_aff_backup_problems(); - } else { - foreach (@sys_list_to_restore) { - my $sys_untar = set_tar("restore", $_); - system("$sys_untar $path_to_find_restore/$_ -C $restore_path"); - } - } - } - if ($restore_other) { - if (valid_backup_test(@other_list_to_restore) == -1) { - $exist_problem = 1; - restore_aff_backup_problems(); - } else { - foreach (@other_list_to_restore) { - my $other_untar = set_tar("restore", $_); - system("$other_untar $path_to_find_restore/$_ -C $restore_path"); - } - } - } - $exist_problem or restore_aff_result(); -} - -sub set_tar { - my ($mode, $filename) = @_; - my $untar_cmd; - $untar_cmd = "$conf{ARCHIVER} -C $restore_path -x" if $mode eq "restore"; - $untar_cmd = "$conf{ARCHIVER} -t" if $mode eq "list"; - $untar_cmd .= " -acl -xattr" if $conf{ARCHIVER} eq "star"; - $untar_cmd .= set_compression($filename); - $untar_cmd .= " -f"; - return $untar_cmd; -} - -sub set_compression { - my ($extension) = @_; - return " -j" if $extension =~ /tar.bz2$/; - return " -z" if $extension =~ /tar.gz$/; -} - -sub check_archiver() { - if (!-x "/usr/bin/star") { - #- sane fallback, star is still in contrib - $conf{ARCHIVER} = "tar"; - show_warning("i", N("/usr/bin/star not found, using tar...")); - save_conf_file(); - } -} - -sub restore_do() { - if ($backup_bef_restore) { - if ($restore_sys) { - $conf{NO_SYS_FILES} = 0; - } else { - $conf{NO_SYS_FILES} = 1; - } - if ($restore_user) { - $conf{NO_USER_FILES} = 0; - @user_list = @user_list_to_restore; - } else { - $conf{NO_USER_FILES} = 1; - } - build_backup_status(); - read_conf_file(); - build_backup_files(); - $table->destroy; - } - restore_do2(); -} - -sub restore_do2() { - destroy_widget(); - my $do_restore; - my $text = Gtk2::TextView->new; - restore_state(); - gtktext_insert($text, [ [ $restore_state ] ]); - button_box_restore_main(); - - gtkpack($advanced_box, - $do_restore = gtkpack_(Gtk2::VBox->new(0,10), - 0, N(" Restore Configuration "), - 1, create_scrolled_window($text), - ), - ); - button_box_restore_end(); - fonction_env(\$do_restore, \&restore_do2, \&restore_box); - $up_box->show_all; -} - -sub restore_step_other() { - my $retore_step_other; - my $text = Gtk2::TextView->new; - my $untar_cmd = "$conf{ARCHIVER} -t -z -f"; - my $other_rest = ""; - select_other_data_to_restore(); - if ($restore_other) { - foreach (@other_list_to_restore) { - if (/tar.bz2$/) { - $untar_cmd = "$conf{ARCHIVER} -t -j -f"; - } - $other_rest .= "/" . `$untar_cmd $path_to_find_restore/$_ -C $restore_path`; - } - } - gtktext_insert($text, [ [ $other_rest ] ]); - gtkpack($advanced_box, - $retore_step_other = gtkpack_(Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 1, create_scrolled_window($text), - 0, my $check_restore_other_sure = Gtk2::CheckButton->new(N("OK to restore the other files.")), - 1, Gtk2::VBox->new(0,10), - ), - ); - check_list([$check_restore_other_sure, \$restore_other]); - fonction_env(\$retore_step_other, \&restore_step_other, \&restore_step2, \&restore_do); - $up_box->show_all; -} - -sub restore_step_user() { - my $retore_step_user; - my @tmp_list = sort @user_backuped; - @user_backuped = @tmp_list; - gtkpack($advanced_box, - $retore_step_user = gtkpack_(Gtk2::VBox->new(0,10), - 0, Gtk2::VBox->new(0,10), - 0, N("User list to restore (only the most recent date per user is important)"), - 1, create_scrolled_window(gtkpack__(Gtk2::VBox->new(0,0), - map { my $name; - my $var2; - my $name_complet = $_; - $name = (split(' ', $name_complet))[0]; - my @user_list_tmp; - my $restore_row = Gtk2::HBox->new(0,5); - my $b = Gtk2::CheckButton->new($name_complet); - my $details = Gtk2::Button->new(N("Details")); - - $restore_row->pack_start($b, 1, 1, 0); - $restore_row->pack_end(Gtk2::VBox->new(1,5), 0, 0, 0); - $restore_row->pack_end($details, 0, 0, 0); - - foreach (@user_list_to_restore2) { - if ($name_complet eq $_) { - gtkset_active($b, 1); - $check_user_to_restore{$name_complet}[1] = 1; - } else { - gtkset_active($b, 0); - $check_user_to_restore{$name_complet}[1] = 0; - } - } - $b->signal_connect(toggled => sub { - if (!$check_user_to_restore{$name_complet}[1]) { - $check_user_to_restore{$name_complet}[1] = 1; - if (!any { /$name/ } @user_list_to_restore2) { - push @user_list_to_restore2, $name_complet; - } - } else { - $check_user_to_restore{$name_complet}[1] = 0; - foreach (@user_list_to_restore2) { - $var2 = (split(' ', $_))[0]; - if ($name ne $var2) { - push @user_list_tmp, $_; - } - } - @user_list_to_restore2 = @user_list_tmp; - } - }); - $details->signal_connect('clicked', sub { - destroy_widget(); - show_backup_details(\&restore_step_user, "user", $name); - }); - $restore_row } (@user_backuped) - ), - ), - ), - ); - if ($restore_other) { - fonction_env(\$retore_step_user, \&restore_step_user, "", \&restore_step_other); - } elsif ($restore_sys) { - fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step_sys, \&restore_step_other); - } else { - fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step2, \&restore_do); - } - $up_box->show_all; -} - -sub restore_step_sys() { - my $restore_step_sys; - my $combo_restore_step_sys = Gtk2::ComboBox->new_with_strings(\@sys_backuped, $restore_step_sys_date); - gtkpack($advanced_box, - $restore_step_sys = gtkpack_(Gtk2::VBox->new(0,10), - 0, N("Please choose the date to restore:"), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, Gtk2::HBox->new(0,10), - 0, $combo_restore_step_sys, - 0, my $details = Gtk2::Button->new(N("Details")), - 1, Gtk2::HBox->new(0,10), - ), - ), - ); - $combo_restore_step_sys->entry->signal_connect('changed', sub { - $restore_step_sys_date = $combo_restore_step_sys->entry->get_text; - }); - $details->signal_connect('clicked', sub { - #- we're only passing a portion of the filename to - #- the subroutine so we need to let it know this - $restore_step_sys_date = $combo_restore_step_sys->entry->get_text; - destroy_widget(); - show_backup_details(\&restore_step_sys, "sys", $restore_step_sys_date); - }); - fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, "restore"); - if ($restore_user) { - fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, \&restore_step_user); - } elsif ($restore_other) { - fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, \&restore_step_other); - } else { - fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, \&restore_do); - } - $up_box->show_all; -} - -sub restore_other_media() { - my $box_find_restore; - my $button; - - gtkpack($advanced_box, - $box_find_restore = gtkpack_(Gtk2::VBox->new(0, 6), - 0, Gtk2::HSeparator->new, - 0, my $check_other_media_hd = Gtk2::CheckButton->new(N("Restore from Hard Disk.")), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(Gtk2::Label->new(N("Enter the directory where backups are stored")), $other_media_hd), - 1, Gtk2::VBox->new(0, 6), - 0, gtkset_size_request(gtkset_sensitive($restore_find_path_entry = Gtk2::Entry->new, $other_media_hd), 152, 20), - 0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new, clicked => sub { - filedialog_generic(N("Directory with backups"), \$restore_find_path_entry); - }), $other_media_hd), - ), - 1, Gtk2::VBox->new(0, 6), - 0, Gtk2::VBox->new(0, 6), - ), - ); - gtksignal_connect(gtkset_active($check_other_media_hd, $other_media_hd), toggled => sub { - $other_media_hd = $other_media_hd ? 0 : 1; - destroy_widget(); - $current_widget->(); - }); - $button->add(gtkpack(Gtk2::HBox->new(0,10), gtkcreate_img("ic82-dossier-32"))); - $restore_find_path_entry->set_text($path_to_find_restore); - $restore_find_path_entry->signal_connect('changed', sub { $path_to_find_restore = $restore_find_path_entry->get_text }); - fonction_env(\$box_find_restore, \&restore_other_media, \&restore_step2, \&restore_do); - $up_box->show_all; -} - -sub restore_step2() { - my $retore_step2; - my $other_exist; - my $sys_exist; - my $user_exist; - local $_; - destroy_widget(); - - my $restore_info_path = $conf{PATH_TO_SAVE}; - $restore_info_path = $path_to_find_restore if $conf{USE_HD} || $conf{USE_CD}; - my $info_prefix = "backup"; - $info_prefix = "list" if $conf{USE_NET} || $conf{USE_TAPE}; - - if (any { /_other_/ } grep { /^$info_prefix/ } all("$restore_info_path/")) { - $other_exist = 1; - } else { - $other_exist = 0; $restore_other = 0; - } - if (any { /_sys_/ } grep { /^$info_prefix/ } all("$restore_info_path/")) { - $sys_exist = 1; - } else { - $sys_exist = 0; $restore_sys = 0; - } - if (any { /_user_/ } grep { /^$info_prefix/ } all("$restore_info_path/")) { - $user_exist = 1; - } else { - $user_exist = 0; $restore_user = 0; - } - - my $restore_path_entry = Gtk2::Entry->new; - gtkpack($advanced_box, - $retore_step2 = gtkpack_(Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, my $check_restore_other_src = Gtk2::CheckButton->new(N("Select another media to restore from")), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Other Media")), clicked => sub { - destroy_widget(); - restore_other_media(); - }), $restore_other_src), - ), - 0, gtkset_sensitive(my $check_restore_sys = Gtk2::CheckButton->new(N("Restore system")), $sys_exist), - 0, gtkset_sensitive(my $check_restore_user = Gtk2::CheckButton->new(N("Restore Users")), $user_exist), - 0, gtkset_sensitive(my $check_restore_other = Gtk2::CheckButton->new(N("Restore Other")), $other_exist), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 0, my $check_restore_other_path = Gtk2::CheckButton->new(N("Select path to restore (instead of /)")), - 1, Gtk2::HBox->new(0,10), - 0, gtkset_sensitive($restore_path_entry, $restore_other_path), - 0, gtksignal_connect(my $button = Gtk2::Button->new->new, clicked => sub { - filedialog_generic(N("Path To Restore To"), \$restore_path_entry); - }), - ), - 0, gtkset_sensitive(my $check_backup_bef_restore = Gtk2::CheckButton->new(N("Do new backup before restore (only for incremental backups.)")), - $conf{SYS_INCREMENTAL_BACKUPS} || $conf{USER_INCREMENTAL_BACKUPS}), - 0, gtkset_sensitive(my $check_remove_user_dir = Gtk2::CheckButton->new(N("Remove user directories before restore.")), $user_exist), - 1, Gtk2::VBox->new(0,10), - ), - ); - - foreach ([$check_restore_sys, \$restore_sys], - [$check_backup_bef_restore, \$backup_bef_restore], - [$check_restore_user, \$restore_user], - [$check_remove_user_dir, \$remove_user_before_restore], - [$check_restore_other, \$restore_other]) { - my $ref = $_->[1]; - gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { - $$ref = $$ref ? 0 : 1; - if (!$restore_sys && !$restore_user && !$restore_other) { - $next_widget = \&message_norestore_box; - } elsif ($restore_sys && $conf{SYS_INCREMENTAL_BACKUPS}) { - $next_widget = \&restore_step_sys; - } elsif ($restore_user) { - $next_widget = \&restore_step_user; - } elsif ($restore_other) { - $next_widget = \&restore_step_other; - } else { - $next_widget = \&restore_do; - } - }); - } - gtksignal_connect(gtkset_active($check_restore_other_path, $restore_other_path), toggled => sub { - $restore_other_path = $restore_other_path ? 0 : 1; - destroy_widget(); - $current_widget->(); - }); - gtksignal_connect(gtkset_active($check_restore_other_src, $restore_other_src), toggled => sub { - $restore_other_src = $restore_other_src ? 0 : 1; - destroy_widget(); - $current_widget->(); - }); - $central_widget = \$retore_step2; - fonction_env(\$retore_step2, \&restore_step2, \&restore_box); - if (!$restore_sys && !$restore_user && !$restore_other) { - $next_widget = \&message_norestore_box; - } elsif ($restore_sys && $conf{SYS_INCREMENTAL_BACKUPS}) { - $next_widget = \&restore_step_sys; - } elsif ($restore_user) { - $next_widget = \&restore_step_user; - } elsif ($restore_other) { - $next_widget = \&restore_step_other; - } else { - $next_widget = \&restore_do; - } - $button->add(gtkpack(Gtk2::HBox->new(0,10), gtkcreate_img("ic82-dossier-32"))); - $restore_path_entry->set_text($restore_path); - $restore_path_entry->signal_connect('changed', sub { - $restore_path = $restore_path_entry->get_text; - }); - $up_box->show_all; -} - -sub find_files_to_restore() { - local $_; - my $file_restore; - my $start_restore; - my $files_selected = 0; - my @possible_sources; - my %catalog_entries; - my @files_to_restore; - my $cat_entry; - my @catalog = cat_("$cfg_dir/drakbackup_catalog"); - destroy_widget(); - - #- file info in tree view - my $model = Gtk2::TreeStore->new("Glib::String", "Gtk2::Gdk::Pixbuf", "Glib::Int"); - my $file_list = Gtk2::TreeView->new_with_model($model); - $file_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - $file_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererPixbuf->new, 'pixbuf' => 1)); - $file_list->append_column(my $valcolumn = Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 2)); - $file_list->set_headers_visible(0); - $file_list->get_selection->set_mode('browse'); - $valcolumn->set_visible(0); - my $unselected = gtkcreate_pixbuf('unselected'); - my $selected = gtkcreate_pixbuf('selected'); - my $file_wildcard_entry = Gtk2::Entry->new; - - gtkpack($advanced_box, - $file_restore = gtkpack_(Gtk2::VBox->new(0,10), - 0, Gtk2::Label->new(N("Filename text substring to search for (empty string matches all):")), - 0, gtkpack_(Gtk2::HBox->new(0,10), - 1, $file_wildcard_entry, - 0, gtksignal_connect(Gtk2::Button->new(N("Search Backups")), clicked => sub { - local $_ = $file_wildcard_entry->get_text; - s|^\*|\\*|g; - my $wildcard = $_; - @possible_sources = glob "$conf{PATH_TO_SAVE}/list*"; - $model->clear; - my $match = 0; - foreach my $list (@possible_sources) { - $list =~ s|.gz||; - my @matches = grep { /$wildcard/ } catMaybeCompressed($list); - if (@matches) { - my $list_entry = $model->append_set(undef, [ 0 => $list, 2 => '' ]); - foreach (@matches) { - chop; - $model->append_set($list_entry, [ 0 => $_, 1 => $unselected, 2 => 0 ]); - } - $match = 1; - } - } - show_warning("i", N("No matches found...")) if $match == 0; - }), - ), - 1, create_scrolled_window($file_list), - 0, gtkset_sensitive(gtksignal_connect($start_restore = Gtk2::Button->new(N("Restore Selected")), clicked => sub { - @files_to_restore = (); - my $last_entry = ''; - my $catalog_entry; - my $restore_file; - foreach (sort keys %catalog_entries) { - if ($catalog_entries{$_} == 1) { - ($catalog_entry, $restore_file) = split("###", $_); - $last_entry = $catalog_entry if $last_entry eq ''; - if ($catalog_entry ne $last_entry) { - restore_catalog_entry($cat_entry, @files_to_restore); - @files_to_restore = (); - push @files_to_restore, $restore_file; - } else { - push @files_to_restore, $restore_file; - } - $last_entry = $catalog_entry; - } - } - restore_catalog_entry($cat_entry, @files_to_restore); - destroy_widget(); - find_files_to_restore() if view_log_or(); - }), 0), - ), - ); - - $file_list->get_selection->signal_connect(changed => sub { - my ($lmodel, $iter) = $_[0]->get_selected; - $lmodel && $iter or return; - my ($s, $val) = $lmodel->get($iter, 0, 2); - if (! any { /$s/ } @possible_sources) { - my $parent_iter = Gtk2::TreeModel::iter_parent($lmodel, $iter); - my $parent_name = $lmodel->get($parent_iter, 0); - $cat_entry = substr($parent_name, -19, 15); - my @full_cat_entry = grep { /^$cat_entry/ } @catalog; - chop @full_cat_entry; - $cat_entry = $full_cat_entry[0]; - $val ? $lmodel->set($iter, 1, $unselected, 2, 0) : $lmodel->set($iter, 1, $selected, 2, 1); - $val ? $files_selected-- : $files_selected++; - $catalog_entries{$cat_entry . "###" . $s} = 1 - $val; - $files_selected ? gtkset_sensitive($start_restore, 1) : gtkset_sensitive($start_restore, 0); - } - }); - $central_widget = \$file_restore; -} - -sub catalog_restore { - my ($call_method) = @_; - my $catalog_box; - my $cat_entry; - my @restore_files; - my $restore_path_entry; - destroy_widget(); - - #- catalog info in tree view - my $model = Gtk2::TreeStore->new("Glib::String"); - my $tree_catalog = Gtk2::TreeView->new_with_model($model); - $tree_catalog->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - - $tree_catalog->set_headers_visible(0); - $tree_catalog->get_selection->set_mode('single'); - - # file details in list widget - my $lmodel = Gtk2::ListStore->new("Glib::String"); - my $tree_files = Gtk2::TreeView->new_with_model($lmodel); - $tree_files->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - - $tree_files->set_headers_visible(0); - $tree_files->get_selection->set_mode('multiple'); - - #- read the catalog - my @catalog = cat_("$cfg_dir/drakbackup_catalog"); - - foreach (@catalog) { - chop; - my @line_data = split(':', $_); - my $t = $line_data[0]; - - my $t_catalog = $model->append_set(undef, [ 0 => $t ]); - - my $indexer = 0; - foreach (@line_data) { - if ($indexer != 0) { - my $m; - $m = "Media: " if $indexer == 1; - $m = "Label or Host: " if $indexer == 2; - $m = "Device or Path: " if $indexer == 3; - $m = "Type: Incremental" if $_ eq "I"; - $m = "Type: Differential" if $_ eq "D"; - $m = "Type: Full" if $_ eq "F"; - $m .= $_ if $_ ne "I" && $_ ne "F" && $_ ne "D"; - $model->append_set($t_catalog, [ 0 => $m ]); - } - $indexer++; - } - } - - $tree_catalog->get_selection->signal_connect(changed => sub { - my ($model, $iter) = $_[0]->get_selected; - $model && $iter or return; - $cat_entry = $model->get($iter, 0); - my $parent_iter = Gtk2::TreeModel::iter_parent($model, $iter); - if ($parent_iter) { - $cat_entry = ''; - return; - } - gtkset_mousecursor_wait(); - @restore_files = (); - $lmodel->clear; - foreach my $filename (glob("$conf{PATH_TO_SAVE}/list*$cat_entry.txt*")) { - $filename =~ s|.gz||; - my @contents = catMaybeCompressed($filename); - foreach (@contents) { - chop; - my $s = $_; - $lmodel->append_set(0, $s); - } - } - gtkset_mousecursor_normal(); - my @full_cat_entry = grep { /^$cat_entry/ } @catalog; - $cat_entry = $full_cat_entry[0]; - }); - - $tree_files->get_selection->signal_connect(changed => sub { - my (@what) = $_[0]->get_selected_rows; - @restore_files = (); - foreach (@what) { - my $iter = $lmodel->get_iter($_); - my $s = $lmodel->get($iter, 0); - push @restore_files, $s; - } - }); - - gtkpack($advanced_box, - $catalog_box = gtkpack_(Gtk2::HBox->new(0,10), - 1, gtkpack_(Gtk2::VBox->new(0,5), - 0, N("Click date/time to see backup files.\nCtrl-Click files to select multiple files."), - 1, gtkpack_(Gtk2::VBox->new(0, 10), - 1, create_scrolled_window($tree_catalog), - 1, create_scrolled_window($tree_files), - ), - 0, gtkpack_(Gtk2::HBox->new(1, 10), - 1, gtksignal_connect(Gtk2::Button->new(N("Restore Selected\nCatalog Entry")), clicked => sub { - if ($cat_entry) { - my $media_check = restore_catalog_entry($cat_entry, ()); - if (! $media_check) { - destroy_widget(); - interactive_mode_box() if view_log_or(); - } - } - }), - 1, gtksignal_connect(Gtk2::Button->new(N("Restore Selected\nFiles")), clicked => sub { - my $files = @restore_files; - #- grab the array before the widget clears it - my @passed_files = @restore_files; - if ($cat_entry && $files) { - my $media_check = restore_catalog_entry($cat_entry, @passed_files); - if (! $media_check) { - destroy_widget(); - interactive_mode_box() if view_log_or(); - } - } - }), - 1, gtkpack_(Gtk2::VBox->new(0, 5), - 0, Gtk2::Label->new("Restore To Path"), - 0, $restore_path_entry = Gtk2::Entry->new, - ), - 0, gtksignal_connect(my $button = Gtk2::Button->new, clicked => sub { - filedialog_generic(N("Path To Restore To"), \$restore_path_entry); - }), - ), - 0, Gtk2::VBox->new(0,10), - ), - 0, Gtk2::VBox->new(0,10), - ), - ); - - $restore_path_entry->set_text($restore_path); - gtksignal_connect($restore_path_entry, changed => sub { - $restore_path = $restore_path_entry->get_text; - }); - $button->add(gtkpack(Gtk2::HBox->new(0,10), gtkcreate_img("ic82-dossier-32"))); - button_box_restore(); - fonction_env(\$catalog_box, \&catalog_restore, \&restore_find_media_box, \&catalog_restore) if $call_method eq "need media"; - fonction_env(\$catalog_box, \&catalog_restore, \&restore_box, \&catalog_restore) if $call_method eq "button"; - $central_widget = \$catalog_box; - $up_box->show_all; -} - -sub restore_catalog_entry { - restore_status(); - - my ($cat_entry, @restore_files) = @_; - my $username; - my $userpass = $conf{PASSWD}; - my $restore_result = 1; - $log_buff = ""; - - my @line_data = split(':', $cat_entry); - my $backup_time = $line_data[0]; - - #- use our own variables here so we do not trash a saved config accidentally - my $media = $line_data[1]; - - #- can be a volume name or a host name - my $vol_host = $line_data[2]; - - #- see if we have a username embedded in the host - if (index($vol_host, "@") != -1) { - my @user_host = split("@", $vol_host); - $username = $user_host[0]; - $vol_host = $user_host[1]; - } else { - $username = $conf{LOGIN}; - } - - #- create a restore work directory if we do not have one - -d "$cfg_dir/restores" or mkdir_p "$cfg_dir/restores"; - - #- can be a device name or a path - my $dev_path = $line_data[3]; - - if ($media eq 'HD') { - #- shouldn't really happen, should have just browsed - #- to the $conf{PATH_TO_SAVE} in the previous step - deal with it anyway - my @restore_tar_files = glob("$dev_path/*$backup_time*$conf{OPTION_COMP}"); - my $matches = @restore_tar_files; - if ($matches == 0) { - show_warning("f", N("Backup files not found at %s.", $dev_path)); - return 0; - } else { - my $save_path_org = $conf{PATH_TO_SAVE}; - $conf{PATH_TO_SAVE} = $dev_path; - $restore_result = restore_hd_or_cd($cat_entry, $dev_path, @restore_files); - $conf{PATH_TO_SAVE} = $save_path_org; - } - } - - if ($media eq 'CD') { - #- we know the cdrecord device, and the label - #- prompt the user for the right CD - $in->ask_okcancel(N("Restore From CD"), N("Insert the CD with volume label %s\n in the CD drive under mount point /mnt/cdrom", $vol_host) ,1) ? ($vol_name = get_cd_volname()) : return 0; - if ($vol_name ne $vol_host) { - show_warning("f", N("Not the correct CD label. Disk is labelled %s.", $vol_name)); - return 0; - } else { - $restore_result = restore_hd_or_cd($cat_entry, '/mnt/cdrom', @restore_files); - } - } - - if ($media =~ /^DirectTape|^Tape/) { - #- a little more complicated, we need to check if other backups - #- were done on this tape, and try to find the offset to this one - $in->ask_okcancel(N("Restore From Tape"), N("Insert the tape with volume label %s\n in the tape drive device %s", $vol_host, $dev_path) ,1) ? ($vol_name = get_tape_label($dev_path)) : return 0; - if ($vol_name ne $vol_host) { - show_warning("f", N("Not the correct tape label. Tape is labelled %s.", $vol_name)); - return 0; - } else { - $restore_result = restore_tape($media, $cat_entry, $dev_path, @restore_files); - } - } - - if ($media eq 'ftp' || $media eq 'ssh' || $media eq 'rsync') { - #- show the user what we know of the connection from the catalog - #- and the config file, let them override if necessary - - $in->ask_from(N("Restore Via Network"), N("Restore Via Network Protocol: %s", $media), - [ { label => N("Host Name"), val => \$vol_host }, - { label => N("Host Path or Module"), val => \$dev_path }, - { label => N("Username"), val => \$username }, - { label => N("Password"), val => \$userpass, hidden => 1 }, - ]) or goto return 0; - - if ($media eq 'ftp' || $media eq 'rsync') { - if ($userpass eq '') { - show_warning("f", N("Password required")); - return 0; - } - } - if ($media eq 'ftp' || $media eq 'rsync' || $media eq 'ssh') { - if ($username eq '') { - show_warning("f", N("Username required")); - return 0; - } elsif ($vol_host eq '') { - show_warning("f", N("Hostname required")); - return 0; - } - } - if ($dev_path eq '') { - show_warning("f", N("Path or Module required")); - return 0; - } - - $restore_result = restore_ftp($cat_entry, $vol_host, $dev_path, $username, $userpass, @restore_files) if $media eq 'ftp'; - $restore_result = restore_rsync_ssh($cat_entry, $vol_host, $dev_path, $username, $media, @restore_files) if $media eq 'rsync' || $media eq 'ssh'; - } - - # cleanup our restore dir - unlink fails here? - system("rm -fr $cfg_dir/restores/*"); - - if (!$restore_result) { - show_warning("i", N("Files Restored...")); - return 0; - } else { - show_warning("f", N("Restore Failed...")); - return 1; - } - -} - -sub view_log_or() { - if ($conf{VIEW_RESTORE_LOG}) { - button_box_ok_only(); - show_status(); - } else { - return 1; - } -} - -sub untar { - my ($cmd, $msg, $tarfile, $restorefile) = @_; - my $message = "Untarring from \n$tarfile \nto $restore_path."; - $message = "Untarring \n$restorefile from \n$tarfile \nto $restore_path." if $msg eq "files"; - my $untar_cmd = set_tar("restore", $tarfile); - my $command = "$untar_cmd $cmd"; - spawn_progress($command, $message); - $results = $log_buff; -} - -sub no_tarfile { - my ($tarfile) = @_; - if (!-e "$cfg_dir/restores/$tarfile") { - show_warning("f", N("%s not retrieved...", $tarfile)); - return 1; - } -} - -sub restore_hd_or_cd { - my ($cat_entry, $tarfile_dir, @restore_files) = @_; - my $indv_files = @restore_files; - my $wild_card = catalog_to_wildcard($cat_entry); - - if ($indv_files == 0) { - #- full catalog specified - foreach (wildcard_to_tarfile($wild_card)) { - untar("$tarfile_dir/$_", "all", $_, undef); - } - } else { - #- individual files - pull from appropriate catalog - foreach (@restore_files) { - my ($restorefile, $tarfile) = file_to_tarfile($_, $wild_card); - untar("$tarfile_dir/$tarfile $restorefile", "files", $tarfile, $restorefile); - } - } - return 0; -} - -sub restore_tape { - my ($media, $cat_entry, $dev_path, @restore_files) = @_; - my $indv_files = @restore_files; - my $wild_card = catalog_to_wildcard($cat_entry); - $dev_path =~ s|/st|/nst|; - my $command = "$conf{ARCHIVER} -C $restore_path -x -f $dev_path"; - - if ($media eq "DirectTape") { - position_tape($cat_entry, $dev_path); - if ($indv_files != 0) { - foreach (@restore_files) { - $command .= " " . substr($_, 1); - } - } - spawn_progress($command, "Restoring files from $dev_path to $restore_path."); - $results = $log_buff; - return 0; - } - - if ($indv_files == 0) { - #- full catalog specified - foreach (wildcard_to_tarfile($wild_card)) { - position_tape($cat_entry, $dev_path); - get_tarfile_from_tape($dev_path); - return 1 if no_tarfile("$conf{PATH_TO_SAVE}/$_"); - untar("$cfg_dir/restores/$conf{PATH_TO_SAVE}/$_", "all", $_, undef); - } - } else { - #- individual files - pull from appropriate catalog - foreach (@restore_files) { - my ($restorefile, $tarfile) = file_to_tarfile($_, $wild_card); - if (!-e "$cfg_dir/restores/$tarfile") { - position_tape($cat_entry, $dev_path); - get_tarfile_from_tape($dev_path); - } - return 1 if no_tarfile("$conf{PATH_TO_SAVE}/$tarfile"); - untar("$cfg_dir/restores/$conf{PATH_TO_SAVE}/$tarfile $restorefile", "files", $tarfile, $restorefile); - } - } - return 0; -} - -sub restore_ftp { - use Net::FTP; - my $ftp; - my ($cat_entry, $hostname, $hostpath, $username, $userpass, @restore_files) = @_; - my $indv_files = @restore_files; - - $DEBUG and print "file list to retrieve: $cat_entry\n "; - if ($DEBUG && $interactive) { $ftp = Net::FTP->new($hostname, Debug => 1) or return 1 } - elsif ($interactive) { $ftp = Net::FTP->new($hostname, Debug => 0) or return 1 } - else { $ftp = Net::FTP->new($hostname, Debug => 0) or return 1 } - $ftp->login($username, $userpass); - $ftp->cwd($hostpath); - $ftp->binary; - - my $wild_card = catalog_to_wildcard($cat_entry); - - if ($indv_files == 0) { - #- full catalog specified - foreach (wildcard_to_tarfile($wild_card)) { - $ftp->get($_, "$cfg_dir/restores/$_"); - return 1 if no_tarfile($_); - untar("$cfg_dir/restores/$_", "all", $_, undef); - } - } else { - #- individual files - pull from appropriate catalog - foreach (@restore_files) { - my ($restorefile, $tarfile) = file_to_tarfile($_, $wild_card); - if (!-e "$cfg_dir/restores/$tarfile") { - $ftp->get($tarfile, "$cfg_dir/restores/$tarfile"); - } - return 1 if no_tarfile($tarfile); - untar("$cfg_dir/restores/$tarfile $restorefile", "files", $tarfile, $restorefile); - } - } - $ftp->quit; - return 0; -} - -sub restore_rsync_ssh { - my ($cat_entry, $hostname, $hostpath, $username, $mode, @restore_files) = @_; - my $indv_files = @restore_files; - my $wild_card = catalog_to_wildcard($cat_entry); - if ($indv_files == 0) { - #- full catalog specified - foreach (wildcard_to_tarfile($wild_card)) { - get_file_from_net($mode, $_, $hostname, $hostpath, $username); - return 1 if no_tarfile($_); - untar("$cfg_dir/restores/$_", "all", $_, undef); - } - } else { - #- individual files - pull from appropriate catalog - foreach (@restore_files) { - my ($restorefile, $tarfile) = file_to_tarfile($_, $wild_card); - get_file_from_net($mode, $tarfile, $hostname, $hostpath, $username) if !-e "$cfg_dir/restores/$tarfile"; - return 1 if no_tarfile($tarfile); - untar("$cfg_dir/restores/$tarfile $restorefile", "files", $tarfile, $restorefile); - } - } - return 0; -} - -sub get_file_from_net { - my ($mode, $tarfile, $hostname, $hostpath, $username) = @_; - my $command; - if ($mode eq 'ssh') { - $command = "scp $username\@$hostname:$hostpath/$tarfile $cfg_dir/restores/"; - } elsif ($mode eq 'rsync') { - $command = "rsync --password-file=$cfg_dir/rsync.user $username\@$hostname" . "::" . "$hostpath/$tarfile $cfg_dir/restores/"; - } else { - $command = "wget http://$hostname/$hostpath/$tarfile -P $cfg_dir/restores/"; - } - spawn_progress($command, "Retrieving backup file \n$tarfile \nvia $mode."); -} - -sub catalog_to_wildcard { - my ($cat_entry) = @_; - my @line_data = split(':', $cat_entry); - my $wildcard = $line_data[0]; - $wildcard; -} - -sub wildcard_to_tarfile { - my ($wildcard) = @_; - my (@tarfile) = glob("$conf{PATH_TO_SAVE}/*$wildcard.txt*"); - foreach (@tarfile) { - $_ = basename($_); - s/txt/$conf{OPTION_COMP}/; - s/list/backup/; - } - @tarfile; -} - -sub file_to_tarfile { - my ($restore_file, $wildcard) = @_; - #- remove leading "/" - only when using star (behavior change from before, now tar uses -P to archive for consistancy) - check_archiver(); - $restore_file = substr($restore_file, 1) if $conf{ARCHIVER} eq 'star'; - #- filename with spaces - $restore_file = "'" . $restore_file . "'" if $restore_file =~ / /; - #- can be in more than one tarfile (misuse of "other") - my @tarfiles = `zgrep -l $restore_file $conf{PATH_TO_SAVE}/*$wildcard.txt*`; - chomp @tarfiles; - my $tarfile = $tarfiles[0]; - $tarfile = basename($tarfile); - $tarfile =~ s/.gz//; - $tarfile =~ s/txt/$conf{OPTION_COMP}/; - $tarfile =~ s/list/backup/; - $restore_file, $tarfile; -} - -sub find_tape_offset { - my ($cat_entry) = @_; - my @line_data = split(':', $cat_entry); - my $label = $line_data[2]; - my @catalog = cat_("$cfg_dir/drakbackup_catalog"); - #- always off by 1 for tape label. - my $offset = 1; - foreach (@catalog) { - chomp; - if (index($_, $label) > 0) { - if ($_ ne $cat_entry) { - $offset++; - } else { - return $offset; - } - } - } -} - -sub position_tape { - my ($cat_entry, $dev_path) = @_; - my $offset = find_tape_offset($cat_entry); - spawn_progress("mt -f $dev_path rewind", "Rewinding tape on $dev_path."); - spawn_progress("mt -f $dev_path fsf $offset", "Moving forward $offset file records."); -} - -sub get_tarfile_from_tape { - my ($dev_path) = @_; - spawn_progress("$conf{ARCHIVER} -C $cfg_dir/restores -x -f $dev_path", "Untarring from $dev_path to work directory."); -} - -sub restore_box() { - destroy_widget(); - - if ($good_restore_path) { - $path_to_find_restore = $conf{PATH_TO_SAVE} if $conf{USE_HD}; - $path_to_find_restore = "/mnt/cdrom" if $conf{USE_CD}; - } - - find_backup_to_restore(); - button_box_restore_main(); - - if (@other_backuped || @sys_backuped || @user_backuped) { - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0,1), - 1, Gtk2::VBox->new(0,10), - 1, gtkpack_(Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - 1, gtksignal_connect(Gtk2::Button->new(N("Search for files to restore")), clicked => sub { - button_box_file_restore(); - find_files_to_restore(); - }), - 1, gtksignal_connect(Gtk2::Button->new(N("Restore all backups")), clicked => sub { - button_box_restore(); - @user_list_to_restore2 = sort @user_backuped; - $restore_sys = 1; - $restore_other = 1; - $restore_user = 1; - restore_do(); - }), - 1, gtksignal_connect(Gtk2::Button->new(N("Custom Restore")), clicked => sub { - button_box_restore(); - restore_step2(); - }), - 1, gtksignal_connect(Gtk2::Button->new(N("Restore From Catalog")), clicked => sub { - catalog_restore("button"); - }), - 1, Gtk2::VBox->new(0,10), - 1, Gtk2::VBox->new(0,10), - ), - 1, Gtk2::HBox->new(0,10), - ), - ); - } else { - destroy_widget(); - restore_find_media_box(); - } - fonction_env(\$box2, \&restore_box, \&interactive_mode_box); - $central_widget = \$box2; - $up_box->show_all; -} - -sub restore_find_media_box() { - my $mount_media = 1; - $good_restore_path = 0; - my $message = N("Unable to find backups to restore...\n"); - $message .= N("Verify that %s is the correct path", $path_to_find_restore) if $conf{USE_HD} && $conf{USE_CD}; - $message .= N(" and the CD is in the drive") if $conf{USE_CD}; - if ($conf{USE_TAPE} || $conf{NET_PROTO}) { - $message .= N("Backups on unmountable media - Use Catalog to restore"); - $mount_media = 0; - } - $message .= "."; - - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::VBox->new(0, 5), - 1, gtkpack(Gtk2::HBox->new(0, 15), - Gtk2::VBox->new(0, 5), - gtkcreate_img('warning'), - translate($message), - Gtk2::VBox->new(0, 5), - ), - 1, gtkpack(Gtk2::HBox->new(0, 15), - Gtk2::VBox->new(0, 5), - gtkpack(Gtk2::VBox->new(0, 10), - gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("CD in place - continue.")), clicked => sub { - $good_restore_path = 1; - interactive_mode_box("restore"); - }), $mount_media), - $new_path_entry = gtkset_sensitive(Gtk2::Entry->new, $mount_media), - gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Browse to new restore repository.")), clicked => sub { - filedialog_generic(N("Directory To Restore From"), \$new_path_entry); - }), $mount_media), - gtksignal_connect(Gtk2::Button->new(N("Restore From Catalog")), clicked => sub { - $box2->destroy; - catalog_restore("need media"); - }), - gtksignal_connect(Gtk2::Button->new(N("Search for files to restore")), clicked => sub { - $box2->destroy; - button_box_file_restore(); - find_files_to_restore(); - }), - ), - Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - $new_path_entry->set_text($path_to_find_restore); - $new_path_entry->signal_connect('changed', sub { $path_to_find_restore = $new_path_entry->get_text }); - $central_widget = \$box2; - button_box_find_media($mount_media); - $up_box->show_all; -} - -sub restore_status() { - destroy_widget(); - $pbar3 = Gtk2::ProgressBar->new; - $stext = Gtk2::Label->new(""); - gtkpack($advanced_box, - $table = gtkpack(Gtk2::VBox->new(0, 5), - Gtk2::HBox->new(0,5), - create_packtable({ col_spacings => 10, row_spacings => 5 }, - [""], - [""], - [""], - [""], - [N("Restore Progress")], - [""], - [""], - [$pbar3], - [""], - [""], - [$plabel3 = Gtk2::Label->new(' ')], - [""], - ), - $stext, - ), - ); - $central_widget = \$table; - $up_box->show_all; - gtkflush(); -} - -################################################ BUTTON_BOX ################################################ - -sub hbutton() { - 0, gtksignal_connect(Gtk2::Button->new(N("Help")), clicked => \&adv_help); -} - -sub cbutton() { - 0, gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&interactive_mode_box); -} - -sub cbuttonr() { - 0, gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&restore_box); -} - -sub ibutton { - my ($msg) = @_; - 0, gtksignal_connect(Gtk2::Button->new($msg), clicked => \&interactive_mode_box); -} - -sub pbutton() { - 0, gtksignal_connect(Gtk2::Button->new(N("Previous")), clicked => sub { - destroy_widget(); - $previous_widget->(); - }); -} - -sub hspace() { - 1, Gtk2::HBox->new(0, 1); -} - -sub button_box_adv() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - pbutton(), - 0, gtksignal_connect(Gtk2::Button->new(N("Save")), clicked => sub { - return if check_pkg_needs(); - if (!save_conf_file()) { - destroy_widget(); - $previous_widget->(); - } - }), - ), - ); -} - -sub button_box_restore_main() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - ibutton(N("Previous")), - ibutton(N("Next")), - ), - ); -} - -sub button_box_file_restore() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - 0, gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&restore_box), - hbutton(), - hspace(), - ), - ); -} - -sub button_box_ok_only() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - hspace(), - ibutton(N("Ok")), - ), - ); -} - -sub button_box_backup_end() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - pbutton(), - 0, gtksignal_connect(Gtk2::Button->new(N("Build Backup")), clicked => sub { - destroy_widget(); - build_backup_status(); - build_backup_files(); - }), - ), - ); -} - -sub button_box_wizard_end() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - pbutton(), - 0, gtksignal_connect(Gtk2::Button->new(N("Save")), clicked => sub { - save_conf_file(); - interactive_mode_box(); - }), - ), - ); -} - -sub button_box_restore_end() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbuttonr(), - hbutton(), - hspace(), - pbutton(), - 0, gtksignal_connect(Gtk2::Button->new(N("Restore")), clicked => sub { - destroy_widget(); - restore_backend(); - }), - ), - ); -} - -sub button_box_restore_pbs_end() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - hspace(), - hbutton(), - ibutton(N("Ok")), - ), - ); -} - -sub button_box_restore() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbuttonr(), - hbutton(), - hspace(), - pbutton(), - 0, gtksignal_connect(Gtk2::Button->new(N("Next")), clicked => sub { - destroy_widget(); - $next_widget->(); - }), - ), - ); -} - -sub button_box_find_media { - my ($mount_media) = @_; - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - ibutton(N("Previous")), - 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new(N("Next")), clicked => sub { - interactive_mode_box("restore"); - }), $mount_media), - ), - ); -} - -sub button_box_wizard() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - cbutton(), - hbutton(), - hspace(), - 0, gtksignal_connect(Gtk2::Button->new($previous_widget ? N("Previous") : N("Ok")), clicked => sub { - destroy_widget(); - $previous_widget ? $previous_widget->() : $next_widget->(); - }), - if_($next_widget, 0, gtksignal_connect(Gtk2::Button->new(N("Next")), clicked => sub { - destroy_widget(); - $next_widget ? $next_widget->() : $previous_widget->(); - })), - ), - ); -} - -sub button_box_main() { - $button_box_tmp->destroy; - gtkpack($button_box, - $button_box_tmp = gtkpack_(Gtk2::HButtonBox->new, - hbutton(), - hspace(), - 0, gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { ugtk2->exit(0) }), - ), - ); -} - -################################################ MESSAGES ################################################ - -sub message_norestore_box() { - $box2->destroy; - - gtkadd($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack(Gtk2::HBox->new(0, 15), - Gtk2::VBox->new(0, 5), - gtkcreate_img('warning'), - N("Please select data to restore..."), - Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - button_box_restore_main(); - $central_widget = \$box2; - $up_box->show_all; -} - -################################################ BUILD_BACKUP ################################################ - -sub progress { - my ($progressbar, $plabel, $incr, $label_text) = @_; - my ($new_val) = $progressbar->get_fraction; - $new_val += $incr; - if ($new_val > 1) { $new_val = 1 } - $progressbar->set_fraction($new_val); - $plabel->set_text($label_text); - gtkflush(); -} - -sub build_backup_status() { - $pbar = Gtk2::ProgressBar->new; - $pbar1 = Gtk2::ProgressBar->new; - $pbar2 = Gtk2::ProgressBar->new; - $pbar3 = Gtk2::ProgressBar->new; - $plabel = Gtk2::Label->new(" "); - $plabel1 = Gtk2::Label->new(" "); - $plabel2 = Gtk2::Label->new(" "); - $plabel3 = Gtk2::Label->new(" "); - - $stext = Gtk2::Label->new(""); - button_box_ok_only(); - - my $table = Gtk2::Table->new(10, 2, 1); - $table->set_row_spacings(5); - $table->set_col_spacings(10); - - $table->attach_defaults(Gtk2::Label->new(N("Backup system files")), 0, 1, 0, 1); - $table->attach_defaults($pbar, 0, 1, 1, 2); - $table->attach_defaults($plabel, 1, 2, 1, 2); - $table->attach_defaults(Gtk2::Label->new(N("Backup user files")), 0, 1, 2, 3); - $table->attach_defaults($pbar1, 0, 1, 3, 4); - $table->attach_defaults($plabel1, 1, 2, 3, 4); - $table->attach_defaults(Gtk2::Label->new(N("Backup other files")), 0, 1, 4, 5); - $table->attach_defaults($pbar2, 0, 1, 5, 6); - $table->attach_defaults($plabel2, 1, 2, 5, 6); - $table->attach_defaults(Gtk2::Label->new(N("Total Progress")), 0, 1, 6, 7); - $table->attach_defaults($pbar3, 0, 1, 7, 8); - $table->attach_defaults($plabel3, 1, 2, 7, 8); - - gtkpack($advanced_box, - my $tbox = gtkpack(Gtk2::VBox->new(0, 5), - $table, - $stext, - ), - ); - - $central_widget = \$tbox; - $up_box->show_all; - gtkflush(); -} - -sub build_backup_ftp_status() { - $pbar = Gtk2::ProgressBar->new; - $pbar3 = Gtk2::ProgressBar->new; - destroy_widget(); - button_box_ok_only(); - $pbar->set_fraction(0); - $pbar3->set_fraction(0); - - gtkpack($advanced_box, - $table = gtkpack_(Gtk2::VBox->new(0, 15), - 1, N("Sending files by FTP"), - 1, Gtk2::VBox->new(0, 15), - 1, create_packtable({ col_spacings => 10, row_spacings => 5 }, - [N("Sending files...")], - [""], - [ $plabel = Gtk2::Label->new(' ') ], - [ $pbar ], - [""], - [N("Total Progress")], - [ $plabel3 = Gtk2::Label->new(' ') ], - [$pbar3], - ), - 1, Gtk2::VBox->new(0, 15), - ), - ); - $central_widget = \$table; - $up_box->show_all; - gtkflush(); -} - -sub build_backup_box_see_conf { - my ($caller) = @_; - my $text = Gtk2::TextView->new; - read_conf_file(); - system_state(); - gtktext_insert($text, [ [ $system_state ] ]); - button_box_restore_main(); - - gtkpack($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, gtkpack_(Gtk2::VBox->new(0,10), - 0, N("Drakbackup Configuration"), - 1, create_scrolled_window($text), - ), - ), - ); - button_box_backup_end(); - $central_widget = \$box2; - $current_widget = \&build_backup_box_see_conf; - if ($caller eq "interactive") { - $previous_widget = \&interactive_mode_box; - } else { - $previous_widget = \&build_backup_box; - } - $up_box->show_all; -} - -sub build_backup_box() { - destroy_widget(); - - gtkadd($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtksignal_connect(my $button_from_conf_file = Gtk2::Button->new, clicked => sub { - destroy_widget(); - build_backup_status(); - build_backup_files(); - }), - 0, Gtk2::VBox->new(0, 5), - 1, gtksignal_connect(my $button_see_conf = Gtk2::Button->new, clicked => sub { - destroy_widget(); - build_backup_box_see_conf(undef); - }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - - $button_from_conf_file->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-discdurwhat-40"), - Gtk2::Label->new(N("Backup Now from configuration file")), - Gtk2::HBox->new(0, 5) - )); - $button_see_conf->add(gtkpack(Gtk2::HBox->new(0,10), - gtkcreate_img("ic82-moreoption-40"), - Gtk2::Label->new(N("View Backup Configuration.")), - Gtk2::HBox->new(0, 5) - )); - - button_box_restore_main(); - fonction_env(\$box2, \&build_backup_box, \&interactive_mode_box); - $up_box->show_all; -} - -################################################ INTERACTIVE ################################################ - -sub interactive_mode_box { - - my ($o_mode) = @_; - if ($o_mode eq "restore") { - $central_widget = \$box2; - restore_box(); - return 0; - } - - destroy_widget(); - gtkadd($advanced_box, - $box2 = gtkpack_(Gtk2::HBox->new(0, 15), - 1, Gtk2::VBox->new(0, 5), - 1, gtkpack_(Gtk2::VBox->new(0, 5), - 1, Gtk2::VBox->new(0, 5), - 0, gtksignal_connect(Gtk2::Button->new(N("Wizard Configuration")), clicked => sub { - destroy_widget(); - read_conf_file(); - wizard(); - }), - 0, gtksignal_connect(Gtk2::Button->new(N("Advanced Configuration")), clicked => sub { - button_box_adv(); - destroy_widget(); - advanced_box(); - }), - 0, gtksignal_connect(Gtk2::Button->new(N("View Configuration")), clicked => sub { - destroy_widget(); - build_backup_box_see_conf("interactive"); - }), - 0, gtksignal_connect(Gtk2::Button->new(N("View Last Log")), clicked => sub { - $results = cat_($log_file); - button_box_ok_only(); - show_status(); - }), - 0, gtksignal_connect(Gtk2::Button->new(N("Backup Now")), clicked => sub { - if ($cfg_file_exist) { - build_backup_box(); - } else { - $in->ask_warn(N("Error"), N("No configuration file found \nplease click Wizard or Advanced.")); - } - }), - 0, gtksignal_connect(Gtk2::Button->new(N("Restore")), clicked => sub { - restore_box(); - }), - 1, Gtk2::VBox->new(0, 5), - ), - 1, Gtk2::VBox->new(0, 5), - ), - ); - $central_widget = \$box2; - button_box_main(); - $up_box->show_all; -} - -sub profile_chooser { - my ($mode, $prompt) = @_; - my $file_dialog = Gtk2::FileChooserDialog->new($prompt, $my_win->{real_window}, $mode, N("Cancel") => 'cancel', N("Ok") => 'ok'); - my $filter = Gtk2::FileFilter->new; - $filter->add_pattern("*.conf"); - $file_dialog->set_current_folder($cfg_dir); - $file_dialog->add_filter($filter); - $file_dialog->set('do-overwrite-confirmation', 1); - $file_dialog->show; - while (my $answer = $file_dialog->run) { - if (member($answer, qw(cancel delete-event))) { - $file_dialog->destroy; - return; - } elsif ($answer eq 'ok') { - my $file_name = $file_dialog->get_filename; - $file_dialog->destroy; - return $file_name; - } - } -} - -sub load_profile() { - my $profile = profile_chooser('open', N("Load profile")); - if ($profile =~ /.conf$/) { - $cfg_file = $profile; - read_conf_file(); - interactive_mode_box(); - } -} - -sub save_profile() { - my $profile = profile_chooser('save', N("Save profile as...")); - if ($profile =~ /.conf$/) { - $cfg_file = $profile; - save_conf_file(); - } -} - -sub get_items() { - my @items = ( - [ "/_File", undef, undef, undef, '<Branch>', ], - [ "/_File/_Load profile", undef, \&load_profile, 1, '<StockItem>', 'gtk-execute' ], - [ "/_File/_Save profile as...", undef, \&save_profile, 1, '<StockItem>', 'gtk-execute' ], - [ "/_File/_Exit", undef, sub { ugtk2->exit(0) }, 1, '<StockItem>', 'gtk-quit' ], - [ "/_Help/_Help", undef, \&adv_help, 1, '<StockItem>', 'gtk-help' ], - ); - return @items; -} - -sub interactive_mode() { - $interactive = 1; - - $in = 'interactive'->vnew; - $::Wizard_title = N("Drakbackup"); - $::Wizard_pix_up = "ic82-back-up-48.png"; - $in->isa('interactive::gtk') and $::isWizard = 0; - $my_win = ugtk2->new(N("Drakbackup")); - $window1 = $my_win->{window}; - $my_win->{rwindow}->set_size_request(600,440); - $my_win->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) }); - my @items = get_items(); - my $factory = Gtk2::ItemFactory->new('Gtk2::MenuBar', '<main>', undef); - $factory->create_items('menu', @items); - my $menu = $factory->get_widget('<main>'); - read_conf_file(); - - gtkadd($window1, - gtkpack(Gtk2::VBox->new(0,0), - gtkpack($up_box = Gtk2::VBox->new(0, 5), - gtkpack_(Gtk2::VBox->new(0, 3), - 0, $menu, - 1, gtkpack_(Gtk2::HBox->new(0, 3), - 1, $advanced_box = Gtk2::HBox->new(0, 15), - ), - 0, Gtk2::HSeparator->new, - 0, $button_box = gtkpack(Gtk2::VBox->new(0, 15), - $button_box_tmp = gtkpack(Gtk2::VBox->new(0, 0),), - ), - ), - ), - ), - ); - setup_tooltips(); - interactive_mode_box(); - button_box_main(); - $central_widget = \$box2; - $window1->realize; - $window1->show_all; - $my_win->main; - $my_win->exit(0); -} - -sub adv_help() { - exec("drakhelp --id drakbackup") unless fork(); -} - -sub destroy_widget() { - if ($central_widget ne '') { - $$central_widget->destroy; - $central_widget = ''; - } -} |