#!/usr/bin/perl # # Copyright (C) 2001-2002 MandrakeSoft by Sebastien DUPONT # Updated 2002 by Stew Benedict # 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. # #________________________________________________________________ # # Description: # # Drakbackup is used to backup your system. # During the configuration you can select # - System files, # - Users files, # - Other files. # or All your system ... and Other (like windows Partitions) # # Drakbackup allows you to backup your system on: # - Harddrive. # - NFS. # - CDROM (CDRW), DVDROM (with autoboot, rescue and autoinstall.). # - FTP. # - Rsync. # - Webdav. # - Tape. # # Drakbackup allows you to Restore your system on # choosen directory. # # Per default all backup will be stored on your # /var/lib/drakbackup directory # # Configuration file: # /etc/drakconf/drakbackup/drakbackup.conf # #________________________________________________________________ # # Backup files formats: # # no incremental backup: # backup_sys_date_hour.tar.* # backup_user_toto_date_hour.tar.* # backup_other_date_hour.tar.* # # first incremental backup: (if backup_base* does not exist) # # backup_base_sys_date_hour.tar.* # backup_base_user_toto_date_hour.tar.* # backup_base_other_date_hour.tar.* # # other incremental backup: (if backup_base* already exist) # # backup_incr_sys_date_hour.tar.* # backup_incr_user_toto_date_hour.tar.* # backup_incr_other_date_hour.tar.* # # all backup runs will generate: # # drakbackup_date_hour.txt # # this will contain media & hostname #________________________________________________________________ # # REQUIRE: cron if daemon # cdrecord & mkisofs # perl Net::FTP # ssh-askpass # sitecopy - for webdav # rsync # perl Expect # BUGS: #DONE restore->other_media->next->previous => crash ... #DONE selection des sources a inclure dans le backup cd. #DONE help -> ok after install_rpm # sort of fixed - doesn't always land where you would expect # but at least it doesn't die # # TODO: # 1 - print ftp problem for user. # 2 - calcul disk space. # use quota. #WHY? - Apple can read Joliet - would you really be restoring on MacOS? #Or for bootable - PPC is being deprecated anyway ;( # 4 - write on cd --> ! change Joliet to HFS for Apple # 6 - total backup.( all partitions wanted, windows partitions for example!) # dump use for total backup. # 7 - custom deamon # 10- backend: --resore_all, --restore_sys, --restore_users #WHAT IS THIS? # --build_cd_autoinst # 12- cpio use !! # 13- boot floppy disk (with dialog) # 14- build autoboot with backup and install cd #DONE 15- use .backupignore like on CVS # 16- afficher les modif dans un fichier texte du meme nom # pour afficher durant le restore. # 17- futur: could be possible to restore a specific file # or directory at specific date. # 18- possible all files each time from directory. # # DONE TODAY: #________________________________________________________________ use lib qw(/usr/lib/libDrakX); use standalone; #- warning, standalone must be loaded very first, for 'explanations' use strict; use interactive; use common; use Time::localtime; use detect_devices; # 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 @all_user_list; my $list_other; my $DEBUG = 0; my $restore_sys = 1; my $restore_user = 1; my $restore_other = 1; my $restore_step_sys_date = ""; my @user_backuped; my @sys_backuped; my $sys_backuped = 0; my $other_backuped = 0; my @user_list_to_restore; my @sys_list_to_restore; my $cd_device_entry; my $custom_help; my $button_box; my $button_box_tmp; my $next_widget; my $sav_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 $iter; my $the_time; my @user_list_to_restore2; my @data_backuped; my $label_tail; my @list_to_build_on_cd; 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; #- ack - not a great default - changed 20020814 (SB) my $remove_user_before_restore = 0; my @file_list_to_send_by_ftp; my $results; my @net_methods = ("ftp", "rsync", "ssh", "webdav"); my @media_types = ("cd", "hd", "tape"); my %cd_devices; my $std_device; my @tape_devices; my $tar_ext = "tar.gz"; # config. FILES -> Default PATH & Global variables. my %config; my @sys_files = "/etc"; my @user_list; my @list_other; my $cfg_dir = "/etc/drakxtools/drakbackup/"; my $cfg_file = $cfg_dir . "drakbackup.conf"; my $save_path = "/var/lib/drakbackup"; my $log_file = "/var/log/drakbackup"; my $log_buff; my $comp_mode = 0; my $backup_sys = 1; my $backup_user = 1; my $backup_daemon = 1; my $backup_sys_versions = 0; my $backup_user_versions = 0; my $backup_other_versions = 0; my $sys_diff_mode = 0; my $user_diff_mode = 0; my $other_diff_mode = 0; my $what_no_browser = 1; my $cdrw = 0; my $dvdr = 0; my $dvdram = 0; my $net_proto = ''; my $host_path = ''; my $login_user = ''; my $daemon = 0; my $backend_only = 0; my $daemon_media = ''; my $hd_quota = 0; #- 7/4/2002 SB - consolidate net methods my $where_use_net = 0; my $where_net = 0; my $where_hd = 1; my $del_hd_files = 0; my $where_cd = 0; my $where_tape = 0; my $cd_time = 650; my $when_space; my $cd_with_install_boot = 0; my $cd_device = ''; my $host_name = ''; my $backupignore = 0; my $remember_pass = 0; my $passwd_user = ''; my $tape_device; my $media_erase = 0; my $media_eject = 0; my $multi_session = 0; my $session_offset = ''; my $tape_norewind = 0; my $no_critical_sys = 1; my $send_mail = 0; my $user_mail; my $scp_port = 22; my $use_expect = 0; my $xfer_keys = 0; my $user_keys = 1; my $user_home = $ENV{HOME}; my $backup_key = $user_home . "/.ssh/identity-drakbackup"; my $nonroot_user = 0; my $not_warned = 0; my $media_problem = 0; my $vol_name = 'Drakbackup'; my $good_restore_path = 1; my $max_space = 1000.0; my @no_devices = translate("No devices found"); foreach (@ARGV) { /--default/ and backend_mode(); /--daemon/ and daemon_mode(); /--show-conf/ and show_conf(); /--config-info/ and explain_conf(); /--cd-info/ and get_cd_info(), exit(0); /--debug/ and $DEBUG = 1, next; } # allow not-root user with own config if ($ENV{HOME} ne '/root') { standalone::explanations("Running as $ENV{USER}..."); $cfg_dir = "$user_home/.drakbackup/"; $save_path = $cfg_dir . "backups"; $log_file = $cfg_dir . "drakbackup.log"; -d $save_path or mkdir_p $save_path; $nonroot_user = 1; $not_warned = 1; $backup_sys = 0; $backup_daemon = 0; $daemon = 0; @user_list = $ENV{USER}; } $cfg_file = $cfg_dir . "drakbackup.conf"; sub show_conf() { print "DrakBackup configuration:\n\n"; read_conf_file(); system_state(); print "$system_state\n"; exit(0); } sub explain_conf() { print "\nConfiguration File Options: \n\n"; print "Configuration file is located in:\n"; print " Root Mode: /etc/drakxtools/drakbackup/drakbackup.conf.\n"; print " User Mode: ~/.drakbackup/drakbackup.conf.\n\n"; print "SYS_FILES= Space seperated list of system directories to backup.\n"; print "HOME_FILES= Space seperated list of user home directories to backup.\n"; print "OTHER_FILES= Space seperated list of other files to backup.\n"; print "PATH_TO_SAVE= Default Hard Drive path to create backup files in.\n"; print " Root Mode: default is /var/lib/drakbackup.\n"; print " User Mode: default is ~/.drakbackup/backups.\n"; print "NO_SYS_FILES Don't backup system files.\n"; print "NO_USER_FILES Don't backup user files.\n"; print "BACKUPIGNORE Honor .backupignore files in backup directories\n"; print "OPTION_COMP Compression option - TAR.GZ or TAR.BZ2 (tar.gz is default).\n"; print "BROWSER_CACHE Backup web browser cache also.\n"; print "CDRW Backup media is re-writable CD.\n"; print "DVDR Backup media is recordable DVD (not fully supported yet).\n"; print "DVDRAM Backup media is DVDRAM (not fully supported yet).\n"; print "NET_PROTO= Network protocol to use for remote backups: \n"; print " ftp, rsync, ssh, or webdav.\n"; print "HOST_NAME= Remote backup host.\n"; print "HOST_PATH= Backup storage path or module on remote host.\n"; print "REMEMBER_PASS Remember password on remote host in config file.\n"; print "USER_KEYS Ssh keys are already setup for communicating with remote host.\n"; print "DRAK_KEYS Use special drakbackup generated host keys.\n"; print " (requires perl-Expect).\n"; print "USE_EXPECT Use expect to do the whole scp transfer, without keys.\n"; print " (requires perl-Expect).\n"; print "LOGIN= Remote host login name.\n"; print "PASSWD= Password on remote host (if REMEMBER_PASS is enabled).\n"; print "DAEMON_MEDIA= Daemon mode backup via given media.\n"; print " (hd, cd, tape, ftp, rsync, ssh, or webdav).\n"; print "HD_QUOTA Use quota to limit hard drive space used for backups.\n"; print " (not supported yet).\n"; print "USE_HD Use Hard Drive for backups (currently all modes use HD also).\n"; print "MAX_SPACE= Maximum Hard Drive Space(Mb) to consume for backups. \n"; print "USE_CD Use CD for backups.\n"; print "USE_NET Use network for backups (driven by NET_PROTO).\n"; print "USE_TAPE Use tape for backup.\n"; print "DEL_HD_FILES Delete local hard drive tar files after backup to other media.\n"; print "TAPE_NOREWIND Use non-rewinding tape device.\n"; print "CD_TIME= Length of CD media (not currently utilized).\n"; print "DAEMON_TIME_SPACE= Interval between daemon backup runs (hourly, daily, weekly)..\n"; print "CD_WITH_INSTALL_BOOT Build a bootable restore CD (currently not utilized).\n"; print "CD_DEVICE= Cdrecord style CD device name (ie: 1,3,0).\n"; print "USER_MAIL= User to send backup results to via email.\n"; print "SEND_MAIL Do send backup results via email.\n"; print "TAPE_DEVICE Device to use for tape backup (ie: /dev/st0).\n"; print "MEDIA_ERASE Erase media before new backup (applies to tape, CD).\n"; print "MEDIA_EJECT Eject media after backup completes.\n"; print "MULTI_SESSION Allow muliple sessions to be written to CD media.\n"; print "SYS_INCREMENTAL_BACKUPS Do incremental or differential backups of system files.\n"; print "USER_INCREMENTAL_BACKUPS Do incremental or differential backups of user files.\n"; print "OTHER_INCREMENTAL_BACKUPS Do incremental or differential backups if other files.\n"; print "SYS_DIFFERENTIAL_BACKUPS Do differential backups of system files.\n"; print "USER_DIFFERENTIAL_BACKUPS Do differential backups of user files.\n"; print "OTHER_DIFFERENTIAL_BACKUPS Do differential backups if other files.\n"; print "NO_CRITICAL_SYS Do not backup critical system files:\n"; print " passwd, fstab, group, mtab\n"; print "CRITICAL_SYS Do backup above system files.\n"; exit(0); } sub backend_mode() { $backend_only = 1; build_backup_files(); exit(0); } sub daemon_mode() { $daemon = 1; build_backup_files(); exit(0); } if (check_for_xserver()) { # I give up, if I don't wrap this somehow, it never comes back when run in # console or daemon mode - just pegs cpu to 100% # perl_checker has fits though eval { require ugtk2 }; die "Can't load ugtk2...\n" if $@; ugtk2->import(qw(:helpers :wrappers :create)); interactive_mode(); } else { die "Can't run in console mode..."; } sub all_user_list() { my $passwdfile = "/etc/passwd"; my $user; my $uid; @all_user_list = (); local *PASSWD; open(PASSWD, $passwdfile) or exit 1; while (defined(my $line = )) { chomp($line); ($user, $uid) = (split(/:/, $line))[0, 2]; if ($uid >= 500 || $uid == 0) { push @all_user_list, $user; } } close(PASSWD); if ($DEBUG) { print "/-- User list --/ \n"; print " -> $_\n" foreach @all_user_list; print "\n"; } } sub the_time() { $the_time = "_"; $the_time .= localtime->year + 1900; if (localtime->mon < 9) { $the_time .= "0" } $the_time .= localtime->mon + 1; if (localtime->mday < 10) { $the_time .= "0" } $the_time .= localtime->mday; $the_time .= "_"; if (localtime->hour < 10) { $the_time .= "0" } $the_time .= localtime->hour; if (localtime->min < 10) { $the_time .= "0" } $the_time .= localtime->min; if (localtime->sec < 10) { $the_time .= "0" } $the_time .= localtime->sec; } sub get_tape_info() { my @line_data; my $info = "/tmp/dmesg"; @tape_devices = (); system("dmesg | grep 'st[0-9] at' > $info"); local *INFO; open INFO, $info or warn("Can't open $info\n"); local $_; while () { @line_data = split(/[ \t,]+/, $_); push @tape_devices, "/dev/" . $line_data[3]; } close INFO; unlink($info); } sub get_free_space { my ($dir) = @_; my @line_data; my $free = "/tmp/free_space"; system("df -P $dir | tail -1 > $free"); local *FREE; open FREE, $free or warn("Can't open $free\n"); local $_; while () { @line_data = split(/[ \t,]+/, $_); } close FREE; # unlink($free); my $free_space = int($line_data[3] / 1024); return $free_space; } sub check_storage_quota { my ($dir) = @_; my $used = "/tmp/used_space"; my $used_space; system("du $dir > $used"); local *USED; open USED, $used or warn("Can't open $used\n"); local $_; while () { $used_space = $_ / 1024; } close USED; unlink($used); if ($used_space > $max_space) { return $used_space; } else { return 0; } } sub get_cd_info() { my @cd_info = cat_("/proc/sys/dev/cdrom/info"); my @line_data; my @drive_names; my $i; my $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' ); #- kind of ugly - I'm sure Pixel could improve this, but it works #- parse /proc/sys/dev/cdrom/info and get all the cd device capabilities 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] =~ $key) { for ($i = 1; $i <= $cd_drives; $i++) { $cd_devices{$drive_names[$i]}{$data{$key}} = $line_data[$i]; } } } } #- now we know all the capabilities, we need the cdrecord device id #- this is scsi-channel, id, lun from /dev/scsi/host* #- oops - can't count on devfs - use dmesg $info = "/tmp/dmesg"; system("dmesg | grep sr[0-9] > $info"); local *INFO; open INFO, $info or warn("Can't open $info\n"); local $_; while () { if (/sr[0-9] at/) { @line_data = split(/[ \t,]+/, $_); chop($line_data[11]); $line_data[5] =~ s/scsi//; $cd_devices{$line_data[3]}{rec_dev} = $line_data[5] . "," . $line_data[9] . "," . $line_data[11]; } } close INFO; unlink($info); #- should we also try to get the human readable name for display purposes? #- now just report the data if we called --cd-info from the command line if (!$interactive) { foreach my $key (keys %cd_devices) { 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 { #- in non-interactive mode we just let all the devices through #- as a general purpose probe - in reality we want only burners foreach my $key (keys %cd_devices) { delete $cd_devices{$key} if $cd_devices{$key}{rec_dev} eq '' } } } sub save_conf_file() { write_sitecopyrc() if $net_proto eq 'webdav'; write_password_file() if $net_proto eq 'rsync' && $passwd_user; my @cfg_list = ("SYS_FILES=@sys_files\n", "HOME_FILES=@user_list\n", "OTHER_FILES=@list_other\n", "PATH_TO_SAVE=$save_path\n", "HOST_PATH=$host_path\n", "NET_PROTO=$net_proto\n", "CD_TIME=$cd_time\n", "USER_MAIL=$user_mail\n", "DAEMON_TIME_SPACE=$when_space\n", "CD_DEVICE=$cd_device\n", "LOGIN=$login_user\n", "TAPE_DEVICE=$tape_device\n", "HOST_NAME=$host_name\n" ); $no_critical_sys and push @cfg_list, "NO_CRITICAL_SYS\n"; $no_critical_sys or push @cfg_list, "CRITICAL_SYS\n"; $backupignore and push @cfg_list, "BACKUPIGNORE\n"; $send_mail and push @cfg_list, "SEND_MAIL\n"; $backup_sys_versions and push @cfg_list, "SYS_INCREMENTAL_BACKUPS\n"; $backup_user_versions and push @cfg_list, "USER_INCREMENTAL_BACKUPS\n"; $backup_other_versions and push @cfg_list, "OTHER_INCREMENTAL_BACKUPS\n"; $sys_diff_mode and $backup_sys_versions and push @cfg_list, "SYS_DIFFERENTIAL_BACKUPS\n"; $user_diff_mode and $backup_user_versions and push @cfg_list, "USER_DIFFERENTIAL_BACKUPS\n"; $other_diff_mode and $backup_other_versions and push @cfg_list, "OTHER_DIFFERENTIAL_BACKUPS\n"; $media_erase and push @cfg_list, "MEDIA_ERASE\n"; $media_eject and push @cfg_list, "MEDIA_EJECT\n"; $multi_session and push @cfg_list, "MULTI_SESSION\n"; $remember_pass and push @cfg_list, "LOGIN=$login_user\n"; $remember_pass and push @cfg_list, "PASSWD=$passwd_user\n"; $remember_pass and push @cfg_list, "REMEMBER_PASS\n"; $user_keys and push @cfg_list, "USER_KEYS\n"; $xfer_keys and push @cfg_list, "DRAK_KEYS\n"; $use_expect and push @cfg_list, "USE_EXPECT\n"; $cd_with_install_boot and push @cfg_list, "CD_WITH_INSTALL_BOOT\n"; $daemon_media eq 'ssh' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=ssh\n"; $daemon_media eq 'ftp' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=ftp\n"; $daemon_media eq 'hd' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=hd\n"; $daemon_media eq 'cd' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=cd\n"; $daemon_media eq 'tape' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=tape\n"; $daemon_media eq 'webdav' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=webdav\n"; $daemon_media eq 'rsync' and $backup_daemon and push @cfg_list, "DAEMON_MEDIA=rsync\n"; $hd_quota and push @cfg_list, "HD_QUOTA\n"; $where_hd and push @cfg_list, "USE_HD\n"; $where_hd and push @cfg_list, "MAX_SPACE=$max_space\n"; $where_cd and push @cfg_list, "USE_CD\n"; $where_tape and push @cfg_list, "USE_TAPE\n"; $tape_norewind and push @cfg_list, "TAPE_NOREWIND\n"; $where_net and push @cfg_list, "USE_NET\n"; $cdrw and push @cfg_list, "CDRW\n"; $dvdr and push @cfg_list, "DVDR\n"; $dvdram and push @cfg_list, "DVDRAM\n"; $what_no_browser or push @cfg_list, "BROWSER_CACHE\n"; $backup_sys or push @cfg_list, "NO_SYS_FILES\n"; if ($comp_mode) { push @cfg_list, "OPTION_COMP=TAR.BZ2\n"; } else { push @cfg_list, "OPTION_COMP=TAR.GZ\n"; } $del_hd_files and push @cfg_list, "DEL_HD_FILES\n"; output_p($cfg_file, @cfg_list); chmod(0600, $cfg_file); save_cron_files(); } sub read_cron_files() { my $daemon_found = 0; foreach (qw(hourly daily weekly monthly)) { if (-f "/etc/cron.$_/drakbackup") { $when_space = $_; $daemon_found = 1; last; } } !$daemon_found and $backup_daemon = 0; } sub save_cron_files() { if ($nonroot_user) { show_warning("w", N("Cron not available yet as non-root")) if $not_warned; $not_warned = 0; $backup_daemon = 0; return 1; } my @cron_file = ("#!/bin/sh\n", "export USER=root\n", "/usr/sbin/drakbackup --daemon > /dev/null 2>&1\n"); if ($backup_daemon) { foreach (qw(hourly daily weekly monthly)) { -f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup"); } output_p("/etc/cron.$when_space/drakbackup", @cron_file); system("chmod +x /etc/cron.$when_space/drakbackup"); } else { foreach (qw(hourly daily weekly monthly)) { -f "/etc/cron.$_/drakbackup" and rm_rf("/etc/cron.$_/drakbackup"); } } } sub read_conf_file() { if (-e $cfg_file) { # %config = getVarsFromSh($cfg_file) || print "You must be root to read configuration file. \n"; local *CONF_FILE; open(CONF_FILE, "<" . $cfg_file) || print "You must be root to read configuration file. \n"; local $_; while () { next unless /\S/; next if /^#/; chomp; if (/^SYS_FILES/) { s/^SYS_FILES=//gi; @sys_files = split(' ', $_) } if (/^HOME_FILES/) { s/^HOME_FILES=//gi; @user_list = split(' ', $_) } if (/^OTHER_FILES/) { s/^OTHER_FILES=//gi; @list_other = split(' ', $_) } if (/^PATH_TO_SAVE/) { s/^PATH_TO_SAVE=//gi; $save_path = $_ } if (/^NO_SYS_FILES/) { $backup_sys = 0 } if (/^NO_USER_FILES/) { $backup_user = 0 } if (/^OPTION_COMP/) { s/^OPTION_COMP=//gi; /TAR.GZ/ and $comp_mode = 0; /TAR.BZ2/ and $comp_mode = 1 } if (/^BROWSER_CACHE/) { $what_no_browser = 0 } if (/^CDRW/) { $cdrw = 1 } if (/^DVDR/) { $dvdr = 1 } if (/^DVDRAM/) { $dvdram = 1 } if (/^NET_PROTO/) { s/^NET_PROTO=//gi; $net_proto = $_ } if (/^HOST_PATH/) { s/^HOST_PATH=//gi; $host_path = $_ } if (/^DAEMON_MEDIA/) { s/^DAEMON_MEDIA=//gi; $daemon_media = $_ } if (/^HD_QUOTA/) { $hd_quota = 1 } if (/^USE_HD/) { $where_hd = 1 } if (/^MAX_SPACE/) { s/^MAX_SPACE=//gi; $max_space = $_ } if (/^USE_CD/) { $where_cd = 1 } if (/^USE_NET/) { $where_net = 1 } if (/^USE_TAPE/) { $where_tape = 1 } if (/^TAPE_NOREWIND/) { $tape_norewind = 1 } if (/^CD_TIME/) { s/^CD_TIME=//gi; $cd_time = $_ } if (/^DAEMON_TIME_SPACE/) { s/^DAEMON_TIME_SPACE=//gi; $when_space = $_ } if (/^CD_WITH_INSTALL_BOOT/) { $cd_with_install_boot = 1 } if (/^CD_DEVICE/) { s/^CD_DEVICE=//gi; $cd_device = $_ } if (/^HOST_NAME/) { s/^HOST_NAME=//gi; $host_name = $_ } if (/^REMEMBER_PASS/) { $remember_pass = 1 } if (/^USER_KEYS/) { $user_keys = 1 } if (/^DRAK_KEYS/) { $xfer_keys = 1; $user_keys = 0 } if (/^USE_EXPECT/) { $use_expect = 1; $user_keys = 0 } if (/^LOGIN/) { s/^LOGIN=//gi; $login_user = $_ } if (/^PASSWD/) { s/^PASSWD=//gi; $passwd_user = $_; $remember_pass = 1 } if (/^USER_MAIL/) { s/^USER_MAIL=//gi; $user_mail = $_ } if (/^SEND_MAIL/) { $send_mail = 1 } if (/^TAPE_DEVICE/) { s/TAPE_DEVICE=//gi; $tape_device = $_ } if (/^MEDIA_ERASE/) { $media_erase = 1 } if (/^MEDIA_EJECT/) { $media_eject = 1 } if (/^MULTI_SESSION/) { $multi_session = 1 } if (/^SYS_INCREMENTAL_BACKUPS/) { $backup_sys_versions = 1 } if (/^USER_INCREMENTAL_BACKUPS/) { $backup_user_versions = 1 } if (/^OTHER_INCREMENTAL_BACKUPS/) { $backup_other_versions = 1 } if (/^SYS_DIFFERENTIAL_BACKUPS/) { $sys_diff_mode = 1 } if (/^USER_DIFFERENTIAL_BACKUPS/) { $user_diff_mode = 1 } if (/^OTHER_DIFFERENTIAL_BACKUPS/) { $other_diff_mode = 1 } if (/^NO_CRITICAL_SYS/) { $no_critical_sys = 1 } if (/^CRITICAL_SYS/) { $no_critical_sys = 0 } if (/^BACKUPIGNORE/) { $backupignore = 1 } if (/^DEL_HD_FILES/) { $del_hd_files = 1 } } close(CONF_FILE); 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 $backup_sys_versions = 1; $backup_user_versions = 1; } } sub write_sitecopyrc() { #- FIXME - how to deal with existing sitecopyrc my @cfg_list = ("site drakbackup\n", "\tserver $host_name\n", "\tremote /$host_path\n", "\tlocal $save_path\n", "\tusername $login_user\n", "\tpassword $passwd_user\n", "\tprotocol webdav\n" ); output_p("$user_home/.sitecopyrc", @cfg_list); chmod(0600, "$user_home/.sitecopyrc"); -d "$user_home/.sitecopy" or mkdir_p("$user_home/.sitecopy"); chmod(0700, "$user_home/.sitecopy"); } sub write_password_file() { output_p("$cfg_dir/rsync.user", "$passwd_user\n"); chmod(0600, "$cfg_dir/rsync.user"); } my $in; sub show_warning { my ($mode, $warning) = @_; $mode = N("WARNING") if $mode eq "w"; $mode = N("FATAL") if $mode eq "f"; $mode = N("INFO") if $mode eq "i"; if ($interactive) { $in->ask_warn('', translate($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; $DEBUG and print "file list to send: $_\n " foreach @file_list_to_send_by_ftp; if ($DEBUG && $interactive) { $ftp = Net::FTP->new($host_name, Debug => 1) or return 1 } elsif ($interactive) { $ftp = Net::FTP->new($host_name, Debug => 0) or return 1 } else { $ftp = Net::FTP->new($host_name, Debug => 0) or return 1 } $ftp->login($login_user, $passwd_user); $ftp->cwd($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($_); #- make perl_checker happy... $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 progess")); } $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 ($@) { if ($mode eq 'sendkey') { destroy_widget(); check_pkg_needs(); } else { $log_buff .= "perl-Expect not installed!", } 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 $timeout = 20; my $exp_command; my @send_files = "$backup_key.pub"; #- just bypass progress for sendkey for now $interactive = 0 if $mode eq "sendkey"; @send_files = @file_list_to_send_by_ftp if $mode eq "backup"; $interactive and $pbar->set_fraction(0); $interactive and $pbar3->set_fraction(0); $interactive and progress($pbar, $plabel, 0.5, "File Transfer..."); foreach (@send_files) { $exp_command = "scp -P $scp_port $_ $login_user\@$host_name:$host_path" if $mode eq "backup"; $exp_command = "ssh-copy-id -i $_ $login_user\@$host_name" if $mode eq "sendkey"; if (-e $backup_key && $mode eq "sendkey") { if ($in->ask_yesorno('', N("%s exists, delete?\n\nWarning: If 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("This may take a moment to generate the keys.")); cursor_wait(); #- not using a passphrase for the moment system("ssh-keygen -P '' -t dsa -f $backup_key"); cursor_norm(); } my $exp = Expect->spawn($exp_command) or $in->ask_warn('', N("ERROR: Cannot spawn %s.", $exp_command)); $interactive and progress($pbar3, $plabel3, 1/@send_files, N("Total progess")); $interactive 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("$passwd_user\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", $host_name, $scp_port)) } if ($bad_passwd) { show_warning("f", N("Bad password on %s", $host_name)) } if ($no_perm) { show_warning("f", N("Permission denied transferring %s to %s", $_, $host_name)) } if ($bad_dir) { show_warning("f", N("Can't find %s on %s", $host_path, $host_name)) } } ], [ timeout => sub { show_warning("f", N("%s not responding", $host_name)) } ], ); my $exit_stat = $exp->exitstatus; $in->ask_warn('', 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, $login_user, $host_name)) if $exit_stat == 0 && $mode eq "sendkey"; $log_buff .= "$_\n" if $exit_stat == 0 && $mode eq "backup"; $exp->hard_close; } $interactive and progress($pbar, $plabel, 0.5, "Done..."); $interactive = 1 if $mode eq "sendkey"; } 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 ($user_keys) { $command = "scp -P $scp_port $_ $login_user\@$host_name:$host_path"; } else { $command = "scp -P $scp_port -i $backup_key $_ $login_user\@$host_name:$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"; local *TMP; open TMP, "$command 2>&1 |"; while ($value = ) { $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 progess")); } return 0; } sub webdav_client() { $DEBUG and print "file list to send: $_\n " foreach @file_list_to_send_by_ftp; if (!(-e "$user_home/.sitecopy/drakbackup")) { my $command = "sitecopy -f $host_path"; spawn_progress($command, "Initializing sitecopy"); } my $command = "sitecopy -u drakbackup"; spawn_progress($command, "Running sitecopy..."); if ($log_buff =~ /Nothing to do - no changes found/) { show_warning("w", N("WebDAV remote site already in sync!")); return 1; } if ($log_buff !~ /Update completed successfully/) { show_warning("f", N("WebDAV transfer failed!")); return 1; } 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 $save_path/* "; $rsync_cmd = $rsync_cmd . "--password-file=$cfg_dir/rsync.user " if $passwd_user; $rsync_cmd = $rsync_cmd . "$login_user\@" if $login_user; $rsync_cmd = $rsync_cmd . $host_name . "::" . $host_path; spawn_progress($rsync_cmd, "Running rsync"); return 0; } sub check_for_cd() { #- check for a cd my $command = "cdrecord dev=$cd_device -atip"; spawn_progress($command, "Check for media in drive"); if ($log_buff =~ /No disk/) { show_warning("f", N("No CDR/DVDR in drive!")); return 1; } if ($log_buff !~ /ATIP info from disk/) { show_warning("f", N("Does not appear to be recordable media!")); return 1; } if ($log_buff =~ /Is not erasable/ && $media_erase) { show_warning("f", N("Not erasable media!")); return 1; } if ($multi_session) { $command = "cdrecord dev=$cd_device -msinfo"; spawn_progress($command, "Check for previous session status"); #- if we don't find a previous session, start fresh if ($log_buff =~ /Cannot read session offset/) { $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=$cd_device -data "; #- only blank if it's the first session $command .= "blank=fast " if $media_erase && $session_offset eq ''; #- multi-session mode $command .= "-multi -pad " if $multi_session; $command .= "$save_path/drakbackup.iso"; spawn_progress($command, "Running cdrecord"); unlink("$save_path/drakbackup.iso"); } sub erase_cdrw() { #- we can only hit this via interactive $interactive = 0; $in->ask_warn('', N("This may take a moment to erase the media.")); cursor_wait(); my $command = "cdrecord dev=$cd_device -blank=fast"; spawn_progress($command, "Erasing CDRW..."); cursor_norm(); $interactive = 1; } sub spawn_progress { my ($command, $descr) = @_; my $value; my $timer; print "$descr\n"; $interactive and progress($pbar3, $plabel3, 0, translate($descr)); $interactive and $pbar3->set_fraction(0); $interactive and $timer = Glib::Timeout->add(2, \&progress_timeout); $log_buff .= "\n" . $descr . ":\n"; $log_buff .= $command . "\n\n"; local *TMP; open TMP, "$command 2>&1 |"; while ($value = ) { $log_buff .= $value; if ($interactive) { $stext->set_text($value); gtkflush(); } } close TMP; $interactive and Glib::Source->remove($timer); } sub progress_timeout() { my $new_val; $new_val = $pbar3->get_fraction + 0.1; if ($new_val > 1) { $new_val = 0 } $pbar3->set_fraction($new_val); return 1; } sub get_cd_device() { my $check_device = "/dev/cdrom"; get_cd_info(); foreach (keys %cd_devices) { if ($cd_devices{$_}{rec_dev} eq $cd_device) { s/sr/scd/; $check_device = "/dev/" . $_; } } $check_device; } sub get_cd_volname() { #- we want the volname for the catalog my $check_device = get_cd_device(); local *TMP; open TMP, "volname $check_device 2>&1 |"; local $_; while () { $vol_name = $_; } close TMP; $vol_name =~ s/[ \t]+\n$//; $vol_name; } sub build_iso() { if ($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 $cd_device " if $multi_session && $session_offset; $command .= "-o $save_path/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) = @_; cursor_wait(); system("mt -f $device rewind"); system("tar -C $cfg_dir -xf $device"); my @volname = cat_("$cfg_dir/drakbackup.label"); unlink("$cfg_dir/drakbackup.label"); $vol_name = $volname[0]; cursor_norm(); $vol_name; } sub build_tape() { my $command; #- do we have a tape? $command = "mt -f $tape_device status"; spawn_progress($command, "Checking for tape"); if ($log_buff =~ /DR_OPEN/) { show_warning("f", N("No tape in %s!", $tape_device)); return 1; } #- try to roll to the end of the data if we're not erasing if (!$media_erase) { $command = "mt -f $tape_device rewind"; spawn_progress($command, "Rewind to find tape label"); $command = "tar -tf $tape_device"; spawn_progress($command, "Check for label"); if ($log_buff =~ /drakbackup.label/) { if ($tape_norewind) { $command = "mt -f $tape_device rewind"; spawn_progress($command, "Rewind to get tape label"); } $command = "tar -C $cfg_dir -xf $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 $tape_device eod"; spawn_progress($command, "Running mt to find eod"); } else { $command = "mt -f $tape_device rewind"; spawn_progress($command, "Running mt to rewind"); # make a tape label for the catalog # if we're using the rewinding device, change modes briefly if (!$tape_norewind) { $tape_device =~ s|/st|/nst|; } $vol_name = "Drakbackup" . $the_time; my $f = "$cfg_dir/drakbackup.label"; output($f, $vol_name); $command = "tar -C $cfg_dir -cf $tape_device drakbackup.label;"; spawn_progress($command, "Creating tape label"); unlink $f; if (!$tape_norewind) { $tape_device =~ s|/nst|/st|; } } #- do the backup $command = "tar -cvf $tape_device @file_list_to_send_by_ftp"; spawn_progress($command, "Running tar to tape"); #- eject the tape? if ($media_eject) { $command = "mt -f $tape_device rewoff"; spawn_progress($command, "Running mt to eject tape"); } } # share this with logdrake sub send_mail { my ($result) = @_; my $datem = `date`; local *F; open F, "|/usr/sbin/sendmail -f$user_mail $user_mail" or return 1; print F "From: drakbackup\n"; print F "To: $user_mail \n"; print F "Subject: DrakBackup report on $datem \n"; print F "\n"; print F "$result\n"; close F or return 1; return 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 $base_sys_exist = 0; my @dir_content; my $incr; local $_; $results = ""; $log_buff = ""; #- flush this so if the user does 2 runs in a row we don't try to send the same files @file_list_to_send_by_ftp = (); $interactive and cursor_wait(); read_conf_file(); the_time(); $send_mail and complete_results(); -d $save_path or mkdir_p($save_path); if ($comp_mode) { $DEBUG and $tar_cmd = "tar cv --use-compress-program /usr/bin/bzip2 "; $DEBUG or $tar_cmd = "tar c --use-compress-program /usr/bin/bzip2 "; $tar_ext = "tar.bz2"; } else { $DEBUG and $tar_cmd = "tar cvpz "; $DEBUG or $tar_cmd = "tar cpz "; $tar_ext = "tar.gz" } my $used_space = check_storage_quota($save_path); if ($used_space) { my $msg = N("Backup quota exceeded!\n%d Mb used vs %d Mb allocated.", $used_space, $max_space); show_warning("f", $msg); $interactive and cursor_norm(); $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; $no_critical_sys and $tar_cmd_sys .= "--exclude passwd --exclude fstab --exclude group --exclude mtab"; $what_no_browser and $tar_cmd_user .= "--exclude NewCache --exclude Cache --exclude cache"; $nonroot_user and $tar_cmd_user .= " --exclude .drakbackup"; -d $save_path and @dir_content = all($save_path); any { /^backup_base_sys/ } @dir_content and $base_sys_exist = 1; if ($where_hd && !$daemon || $daemon) { $interactive and progress($pbar, $plabel, 0.5, N("Backup system files...")); if ($backup_sys) { if ($backup_sys_versions) { $incr = "incr_sys"; $incr =~ s/incr/diff/ if $sys_diff_mode; #- 8/19/2002 - changed these greps to look at the list, rather than the tar file #- we retain the list for other media backups, but the tar file goes away, potentially if ((any { /^list_incr_sys/ } @dir_content) && !$sys_diff_mode) { my @more_recent = grep { /^list_incr_sys/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find @sys_files -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_sys$the_time.txt"); if (!cat_("$save_path/list_incr_sys$the_time.txt")) { system("rm $save_path/list_incr_sys$the_time.txt"); } else { system("$tar_cmd_sys -f $save_path/backup_incr_sys$the_time.$tar_ext -T $save_path/list_incr_sys$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_incr_sys$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_incr_sys$the_time.txt"; $results .= "\nfile: $save_path/backup_incr_sys$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_incr_sys$the_time.txt"); } } elsif (any { /^list_base_sys/ } @dir_content) { my @more_recent = grep { /^list_base_sys/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find @sys_files -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$the_time.txt"); if (!cat_("$save_path/list_$incr$the_time.txt")) { system("rm $save_path/list_$incr$the_time.txt"); } else { system("$tar_cmd_sys -f $save_path/backup_$incr$the_time.$tar_ext -T $save_path/list_$incr$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_$incr$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_$incr$the_time.txt"; $results .= "\nfile: $save_path/backup_$incr$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_$incr$the_time.txt"); } } else { #- need this for the first pass too, if we're offloading the backups to other media (sb) system("find @sys_files ! -type d -print > $save_path/list_base_sys$the_time.txt"); system("$tar_cmd_sys -f $save_path/backup_base_sys$the_time.$tar_ext @sys_files"); push @file_list_to_send_by_ftp, "$save_path/backup_base_sys$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_base_sys$the_time.txt"; $results .= "\nfile: $save_path/backup_base_sys$the_time.$tar_ext\n"; } } else { system("cd $save_path && rm -f backup_sys* backup_base_sys* backup_incr_sys*"); system("$tar_cmd_sys -f $save_path/backup_sys$the_time.$tar_ext @sys_files"); push @file_list_to_send_by_ftp, "$save_path/backup_sys$the_time.$tar_ext"; $results .= "\nfile: $save_path/backup_sys$the_time.$tar_ext\n"; } } $interactive and progress($pbar, $plabel, 0.5, N("Backup system files...")); $interactive and progress($pbar3, $plabel3, 0.3, N("Hard Disk Backup files...")); if ($backup_user) { foreach (@user_list) { my $user = $_; $path_name = return_path($user); if ($backup_user_versions) { $incr = "incr_user_"; $incr =~ s/incr/diff/ if $user_diff_mode; #- 8/19/2002 - changed these greps to look at the list, rather than the tar file #- we retain the list for other media backups, but the tar file goes away, potentially if ((any { /^list_incr_user_$user/ } @dir_content) && !$user_diff_mode) { my @more_recent = grep { /^list_incr_user_$user/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find $path_name -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_user_$user$the_time.txt"); if (!cat_("$save_path/list_incr_user_$user$the_time.txt")) { system("rm $save_path/list_incr_user_$user$the_time.txt"); } else { system("$tar_cmd_user -f $save_path/backup_incr_user_$user$the_time.$tar_ext -T $save_path/list_incr_user_$user$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_incr_user_$user$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_incr_user_$user$the_time.txt"; $results .= " \nfile: $save_path/backup_incr_user_$user$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_incr_user_$user$the_time.txt"); } } elsif (any { /^list_base_user_$user/ } @dir_content) { my @more_recent = grep { /^list_base_user_$user/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find $path_name -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$user$the_time.txt"); if (!cat_("$save_path/list_$incr$user$the_time.txt")) { system("rm $save_path/list_$incr$user$the_time.txt"); } else { system("$tar_cmd_user -f $save_path/backup_$incr$user$the_time.$tar_ext -T $save_path/list_$incr$user$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_$incr$user$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_$incr$user$the_time.txt"; $results .= "\nfile: $save_path/backup_$incr$user$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_$incr$user$the_time.txt"); } } else { #- need this for the first pass too, if we're offloading the backups to other media (sb) system("find $path_name ! -type d -print > $save_path/list_base_user_$user$the_time.txt"); system("$tar_cmd_user -f $save_path/backup_base_user_$user$the_time.$tar_ext $path_name"); push @file_list_to_send_by_ftp, "$save_path/backup_base_user_$user$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_base_user_$user$the_time.txt"; $results .= "\nfile: $save_path/backup_base_user_$user$the_time.$tar_ext\n"; } } else { system("cd $save_path && rm -f backup_user_$_* backup_base_user_$_* backup_incr_user_$_*"); system("$tar_cmd_user -f $save_path/backup_user_$_$the_time.$tar_ext $path_name"); push @file_list_to_send_by_ftp, "$save_path/backup_user_$_$the_time.$tar_ext"; $results .= "\nfile: $save_path/backup_user_$user$the_time.$tar_ext\n"; } } } $interactive and progress($pbar2, $plabel1, 1, N("Backup User files...")); $interactive and progress($pbar3, $plabel3, 0.4, N("Hard Disk Backup files...")); if (@list_other) { if ($backup_other_versions) { $incr = "incr_other"; $incr =~ s/incr/diff/ if $other_diff_mode; if ((any { /^list_incr_other/ } @dir_content) && !$user_diff_mode) { my @more_recent = grep { /^list_incr_other/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find @list_other -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_incr_other$the_time.txt"); if (!cat_("$save_path/list_incr_other$the_time.txt")) { system("rm $save_path/list_incr_other$the_time.txt"); } else { system("$tar_cmd_other -f $save_path/backup_incr_other$the_time.$tar_ext -T $save_path/list_incr_other$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_incr_other$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_incr_other$the_time.txt"; $results .= "\nfile: $save_path/backup_incr_other$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_incr_other$the_time.txt"); } } elsif (any { /^list_base_other/ } @dir_content) { my @more_recent = grep { /^list_base_other/ } sort @dir_content; $more_recent = pop @more_recent; $DEBUG and print "more recent file: $more_recent\n"; system("find @list_other -cnewer $save_path/$more_recent ! -type d -print > $save_path/list_$incr$the_time.txt"); if (!cat_("$save_path/list_$incr$the_time.txt")) { system("rm $save_path/list_$incr$the_time.txt"); } else { system("$tar_cmd_other -f $save_path/backup_$incr$the_time.$tar_ext -T $save_path/list_$incr$the_time.txt"); push @file_list_to_send_by_ftp, "$save_path/backup_$incr$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_$incr$the_time.txt"; $results .= "\nfile: $save_path/backup_$incr$the_time.$tar_ext\n"; $results .= cat_("$save_path/list_$incr$the_time.txt"); } } else { #- need this for the first pass too, if we're offloading the backups to other media (sb) system("find @list_other ! -type d -print > $save_path/list_base_other$the_time.txt"); system("$tar_cmd_other -f $save_path/backup_base_other$the_time.$tar_ext @list_other"); push @file_list_to_send_by_ftp, "$save_path/backup_base_other$the_time.$tar_ext"; push @file_list_to_send_by_ftp, "$save_path/list_base_other$the_time.txt"; $results .= "\nfile: $save_path/backup_base_other$the_time.$tar_ext\n"; } } else { system("cd $save_path && rm -f backup_other* backup_base_other* backup_incr_other*"); system("$tar_cmd_other -f $save_path/backup_other$the_time.$tar_ext @list_other"); push @file_list_to_send_by_ftp, "$save_path/backup_other$the_time.$tar_ext"; $results .= "\nfile: $save_path/backup_other$the_time.$tar_ext\n"; } } $interactive and progress($pbar1, $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) { my $msg = N("No changes to backup!"); show_warning("w", $msg); $interactive and cursor_norm(); $interactive and interactive_mode(); results_to_logfile(); return 1; } #- should hit this block if running daemon mode only if ($daemon && $daemon_media) { # ftp_client() if $ftp_daemon; rsync_client() if $daemon_media eq 'rsync'; ssh_client() if $daemon_media eq 'ssh' && !$use_expect; do_expect("backup") if $daemon_media eq 'ssh' && $use_expect; webdav_client() if $daemon_media eq 'webdav'; build_cd() if $daemon_media eq 'cd'; build_tape() if $daemon_media eq 'tape'; $results .= N("\nDrakbackup activities via %s:\n\n", $daemon_media); $results .= $log_buff; } #- leave this one alone for now - works well #- integrate with other methods later if (($where_net && !$daemon && $net_proto eq 'ftp') || $daemon && $daemon_media eq 'ftp') { $results .= N("file list sent by FTP: %s\n ", $_) foreach @file_list_to_send_by_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 client_ftp_pb(); } } #- consolidate all the other methods under here - interactive and --default should land here if (!$daemon) { if ($where_net && $net_proto && $net_proto ne 'ftp') { rsync_client() if $net_proto eq 'rsync'; ssh_client() if $net_proto eq 'ssh' && !$use_expect; do_expect("backup") if $net_proto eq 'ssh' && $use_expect; webdav_client() if $net_proto eq 'webdav'; $results .= N("\nDrakbackup activities via %s:\n\n", $net_proto); } if ($where_cd) { build_cd(); $results .= N("\nDrakbackup activities via CD:\n\n"); } if ($where_tape) { build_tape(); $results .= N("\nDrakbackup activities via tape:\n\n"); } $results .= $log_buff; results_to_logfile(); } if ($send_mail) { if (send_mail($results)) { $interactive and send_mail_pb(); $interactive or print N(" Error while sending mail. \n"); } } #- write our catalog file if (!$media_problem) { my $catalog = substr($the_time, 1); if (!$where_net && !$where_tape && !$where_cd) { $catalog .= ":HD:localhost:$save_path"; $net_proto = ''; } $catalog .= ":$net_proto:$login_user\@$host_name:$host_path" if $net_proto; $catalog .= ":CD:$vol_name:$cd_device" if $where_cd; $catalog .= ":Tape:$vol_name:$tape_device" if $where_tape; $catalog .= ":System" if $backup_sys; $catalog .= ":I" if $backup_sys_versions && $backup_sys && !$sys_diff_mode; $catalog .= ":D" if $backup_sys_versions && $backup_sys && $sys_diff_mode; $catalog .= ":F" if !$backup_sys_versions && $backup_sys; $catalog .= ":Users=(@user_list)" if $backup_user; $catalog .= ":I" if $backup_user_versions && $backup_user && !$user_diff_mode; $catalog .= ":D" if $backup_user_versions && $backup_user && $user_diff_mode; $catalog .= ":F" if !$backup_user_versions && $backup_user;; $catalog .= ":Other=(@list_other)" if @list_other; $catalog .= ":I" if $backup_other_versions && @list_other && !$other_diff_mode; $catalog .= ":D" if $backup_other_versions && @list_other && $other_diff_mode; $catalog .= ":F" if !$backup_other_versions && @list_other; $catalog .= "\n"; local *CATALOG; open CATALOG, ">> $cfg_dir/drakbackup_catalog" or show_warning("w", N("Can't create catalog!")); print CATALOG $catalog; close CATALOG; } #- clean up HD files if del_hd_files and media isn't hd if ($del_hd_files && ($where_cd || $where_tape || $where_net) && $daemon_media ne 'hd') { foreach (@file_list_to_send_by_ftp) { # unlink($_) if (/$tar_ext$/) && (!/backup_base/); unlink($_) if /$tar_ext$/; } } #- if we had a media problem then get rid of the text log of the backed up files too if ($media_problem) { system("rm $save_path/list*$the_time.txt"); } $interactive and cursor_norm(); $interactive and show_status(); } my @list_of_rpm_to_install; sub require_rpm { my $all_rpms_found = 1; my $res; # my @file_cache = cat_("/var/log/rpmpkgs"); @list_of_rpm_to_install = (); #- reverted to old method - /var/log/rpmpkgs is not always accurate # my($pkg) = @_; foreach my $pkg (@_) { # $res = grep /$pkg/, @file_cache; $res = system("rpm -q $pkg > /dev/null"); if ($res == 256) { $all_rpms_found = 0; push @list_of_rpm_to_install, $pkg; } } return $all_rpms_found; } sub check_pkg_needs() { my $extra_pkg = ''; if ($where_net) { $extra_pkg = 'rsync' if $net_proto eq 'rsync'; $extra_pkg = 'sitecopy wget' if $net_proto eq 'webdav'; $extra_pkg = 'perl-Expect' if $net_proto eq 'ssh' && ($use_expect || $xfer_keys); } $extra_pkg = 'mt-st' if $where_tape; if ($extra_pkg) { if (require_rpm($extra_pkg)) { return 0; } else { #- this isn't entirely good, but it's the only way we get here currently #- was getting strange return behavior before #- still a problem, we can also get here from the cron screen install_rpm(\&advanced_where); return 1; } } } sub cursor_wait() { # turn the cursor to a watch $window1->window->set_cursor(new Gtk2::Gdk::Cursor("GDK_WATCH")); gtkflush(); } sub cursor_norm() { # restore normal cursor $window1->window->set_cursor(new Gtk2::Gdk::Cursor("GDK_LEFT_PTR")); gtkflush(); } sub show_status() { my $text = new Gtk2::TextView; 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_(new Gtk2::VBox(0,10), 1, $scrolled_window) ); $central_widget = \$table; $table->show_all; } sub results_to_logfile() { local *LOG; open LOG, "> $log_file" or show_warning("w", N("Can't create log file!")); print LOG "$results\n"; close LOG; } sub file_ok_sel { my ($file_selection) = @_; my $file_name = $file_selection->get_filename; if (!member($file_name, @list_other)) { push(@list_other, $file_name); $list_model->append($iter); $list_model->set($iter, [ 0 => $file_name ]); } } sub filedialog_where_hd() { my $file_dialog; $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("File Selection")), destroy => sub { $file_dialog->destroy }); $file_dialog->ok_button->signal_connect(clicked => sub { $save_path_entry->set_text($file_dialog->get_filename); $file_dialog->destroy }); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy }); $file_dialog->show; } sub filedialog_restore_find_path() { my $file_dialog; $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("File Selection")), destroy => sub { $file_dialog->destroy }); $file_dialog->ok_button->signal_connect(clicked => sub { $restore_find_path_entry->set_text($file_dialog->get_filename); $file_dialog->destroy; }); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy }); $file_dialog->show; } sub filedialog_generic { #- a more generic file dialog #- a title prompt, the widget to get updated and the variable to update my ($prompt, $widget, $set_var) = @_; my $file_dialog; $file_dialog = gtksignal_connect(new Gtk2::FileSelection(translate($prompt)), destroy => sub { $file_dialog->destroy }); $file_dialog->ok_button->signal_connect(clicked => sub { $$set_var = $file_dialog->get_filename; $$widget->set_text($$set_var); $file_dialog->destroy; }); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy }); $file_dialog->show; } sub filedialog() { my $file_dialog; $file_dialog = gtksignal_connect(new Gtk2::FileSelection(N("Select the files or directories and click on 'OK'")), destroy => sub { $file_dialog->destroy }); $file_dialog->ok_button->signal_connect(clicked => sub { file_ok_sel($file_dialog) }); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy }); $file_dialog->show; } ################################################ ADVANCED ################################################ sub check_list { foreach (@_) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { invbool $ref; destroy_widget(); $current_widget->(); }); } } sub fonction_env { ($central_widget, $current_widget, $previous_widget, $custom_help, $next_widget) = @_; } sub advanced_what_sys() { my $box_what_sys; gtkpack($advanced_box, $box_what_sys = gtkpack_(new Gtk2::VBox(0, 15), 1, N("\nPlease check all options that you need.\n"), 1, N("These options can backup and restore all files in your /etc directory.\n"), 0, my $check_what_sys = new Gtk2::CheckButton(N("Backup your System files. (/etc directory)")), 0, my $check_what_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups (do not replace old backups)")), 0, gtkpack__(new Gtk2::HBox(0,0), my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), ), 0, my $check_what_critical = new Gtk2::CheckButton(N("Do not include critical files (passwd, group, fstab)")), 0, N("With this option you will be able to restore any version\n of your /etc directory."), 1, new Gtk2::VBox(0, 15), ), ); check_list([$check_what_sys, \$backup_sys], [$check_what_critical, \$no_critical_sys]); $check_what_versions->set_active($backup_sys_versions); $check_what_versions->signal_connect('toggled' => sub { invbool \$backup_sys_versions; $mode_buttons[0]->set_sensitive($backup_sys_versions); $mode_buttons[1]->set_sensitive($backup_sys_versions); }); $mode_buttons[1]->set_active($sys_diff_mode); $mode_buttons[0]->signal_connect('toggled' => sub { $sys_diff_mode = $mode_buttons[1]->get_active }); $mode_buttons[0]->set_sensitive($backup_sys_versions); $mode_buttons[1]->set_sensitive($backup_sys_versions); fonction_env(\$box_what_sys, \&advanced_what_sys, \&advanced_what, "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_(new Gtk2::VBox(0, 15), 0, N("Please check all users that you want to include in your backup."), 0, new Gtk2::HSeparator, 1, create_scrolled_window( gtkpack__(new Gtk2::VBox(0,0), map { my $name = $_; my @user_list_tmp; my $b = new Gtk2::CheckButton($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 } (@all_user_list) ), ), 0, my $check_what_browser = new Gtk2::CheckButton(N("Do not include the browser cache")), 0, my $check_what_user_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups (do not replace old backups)")), 0, gtkpack__(new Gtk2::HBox(0,0), my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), ), ), ); check_list([$check_what_browser, \$what_no_browser]); $check_what_user_versions->set_active($backup_user_versions); $check_what_user_versions->signal_connect('toggled' => sub { invbool \$backup_user_versions; $mode_buttons[0]->set_sensitive($backup_user_versions); $mode_buttons[1]->set_sensitive($backup_user_versions); }); $mode_buttons[1]->set_active($user_diff_mode); $mode_buttons[0]->signal_connect('toggled' => sub { $user_diff_mode = $mode_buttons[1]->get_active }); $mode_buttons[0]->set_sensitive($backup_user_versions); $mode_buttons[1]->set_sensitive($backup_user_versions); if ($previous_function) { fonction_env(\$box_what_user, \&advanced_what_user, \&$previous_function, "what", \&$previous_function) } else { fonction_env(\$box_what_user, \&advanced_what_user, \&advanced_what, "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 (@list_other) { $list_model->append_set(undef, $_); } $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_(new Gtk2::VBox(0, 15), 1, gtkpack_(new Gtk2::HBox(0,4), 1, create_scrolled_window($list_others), ), 0, gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'), gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { filedialog() }), gtksignal_connect(Gtk2::Button->new(N("Remove Selected")), clicked => sub { $list_model->remove($file_iter); my $iindex = 0; foreach (@list_other) { if ($list_other[$iindex] eq $other_file) { splice(@list_other, $iindex, 1); last; } $iindex++; } }), ), 0, my $check_what_other_versions = new Gtk2::CheckButton(N("Use Incremental/Differential Backups (do not replace old backups)")), 0, gtkpack__(new Gtk2::HBox(0,0), my @mode_buttons = gtkradio((N("Use Incremental Backups")) x 2, N("Use Differential Backups")), ), ), ); $check_what_other_versions->set_active($backup_other_versions); $check_what_other_versions->signal_connect('toggled' => sub { invbool \$backup_other_versions; $mode_buttons[0]->set_sensitive($backup_other_versions); $mode_buttons[1]->set_sensitive($backup_other_versions); }); $mode_buttons[1]->set_active($other_diff_mode); $mode_buttons[0]->signal_connect('toggled' => sub { $other_diff_mode = $mode_buttons[1]->get_active }); $mode_buttons[0]->set_sensitive($backup_other_versions); $mode_buttons[1]->set_sensitive($backup_other_versions); fonction_env(\$box_what_other, \&advanced_what_other, \&advanced_what, "what"); $up_box->show_all; } sub advanced_what_entire_sys() { my $box_what; gtkpack($advanced_box, $box_what = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtksignal_connect(my $button_what_other = Gtk2::Button->new, clicked => sub { destroy_widget(); message_underdevel() }), 1, gtksignal_connect(my $button_what_all = Gtk2::Button->new, clicked => sub { destroy_widget(); message_underdevel() }), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $button_what_other->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("bootloader"), new Gtk2::Label(N("Linux")), new Gtk2::HBox(0, 5) )); $button_what_all->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("user"), new Gtk2::Label(N("Windows (FAT32)")), new Gtk2::HBox(0, 5) )); fonction_env(\$box_what, \&advanced_what_entire_sys, \&advanced_what, ""); $up_box->show_all; } sub advanced_what() { my $box_what; gtkpack($advanced_box, $box_what = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(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() }), 1, gtksignal_connect(my $button_what_other = Gtk2::Button->new, clicked => sub { destroy_widget(); advanced_what_other() }), # 1, gtksignal_connect(my $button_what_all = Gtk2::Button->new, # clicked => sub { destroy_widget(); advanced_what_entire_sys(); }), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $button_what_sys->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-system-40"), new Gtk2::Label(N("System")), new Gtk2::HBox(0, 5) )); $button_what_user->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-users-40"), new Gtk2::Label(N("Users")), new Gtk2::HBox(0, 5) )); $button_what_other->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-others-40"), new Gtk2::Label(N("Other")), new Gtk2::HBox(0, 5) )); # $button_what_all->add(gtkpack(new Gtk2::HBox(0,10), # gtkcreate_img("ic82-systemeplus-40"), # new Gtk2::Label(N("An Entire System")), # new Gtk2::HBox(0, 5) # )); 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_(new Gtk2::VBox(0, 10), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, my $check_where_use_net = new Gtk2::CheckButton(N("Use network connection to backup")), 1, new Gtk2::HBox(0,10), 0, new Gtk2::Label(N("Net Method:")), 0, gtkset_sensitive(my $entry_net_type = new Gtk2::OptionMenu(), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0,5), 0, gtkset_sensitive(my $check_use_expect = new Gtk2::CheckButton(N("Use Expect for SSH")), ($where_net && $net_proto eq 'ssh')), 0, gtkset_sensitive(my $check_xfer_keys = new Gtk2::CheckButton(N("Create/Transfer\nbackup keys for SSH")), ($where_net && $net_proto eq 'ssh')), 0, gtkset_sensitive(my $button_xfer_keys = Gtk2::Button->new_from_stock(N(" Transfer \nNow")), $xfer_keys), 0, gtkset_sensitive(my $check_user_keys = new Gtk2::CheckButton(N("Other (not drakbackup)\nkeys in place already")), ($where_net && $net_proto eq 'ssh')), ), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Host name or IP.")), $where_net), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $host_name_entry = new Gtk2::Entry(), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Directory (or module) to\n put the backup on this host.")), $where_net), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $host_path_entry = new Gtk2::Entry(), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Login name")), $where_net), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $login_user_entry = new Gtk2::Entry(), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Password")), $where_net), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $passwd_user_entry = new Gtk2::Entry(), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0,10), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $check_remember_pass = new Gtk2::CheckButton(N("Remember this password")), $where_net), ), ), ); $entry_net_type->set_popdown_strings(@net_methods); $entry_net_type->entry->set_text($net_proto); $button_xfer_keys->signal_connect('clicked', sub { if ($passwd_user && $login_user && $host_name) { do_expect("sendkey"); } else { $in->ask_warn('', N("Need hostname, username and password!")); } }); $passwd_user_entry->set_visibility(0); $passwd_user_entry->set_text($passwd_user); $passwd_user_entry->signal_connect('changed', sub { $passwd_user = $passwd_user_entry->get_text }); $host_path_entry->set_text($host_path); $host_name_entry->set_text($host_name); $login_user_entry->set_text($login_user); $host_name_entry->signal_connect('changed', sub { $host_name = $host_name_entry->get_text }); $host_path_entry->signal_connect('changed', sub { $host_path = $host_path_entry->get_text }); $login_user_entry->signal_connect('changed', sub { $login_user = $login_user_entry->get_text }); $entry_net_type->entry->signal_connect('changed', sub { $net_proto = $entry_net_type->entry->get_text; my $sensitive = 0; $sensitive = 1 if $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, \$remember_pass]); gtksignal_connect(gtkset_active($check_where_use_net, $where_net), toggled => sub { invbool \$where_net; #- assure other methods disabled if ($where_net == 1) { $where_cd = 0; $where_tape = 0; } $net_proto = '' if $where_net == 0; destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_use_expect, $use_expect), toggled => sub { invbool \$use_expect; #- assure other methods disabled if ($use_expect == 1) { $xfer_keys = 0; $user_keys = 0; } destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_xfer_keys, $xfer_keys), toggled => sub { invbool \$xfer_keys; #- assure other methods disabled if ($xfer_keys == 1) { $use_expect = 0; $user_keys = 0; } destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_user_keys, $user_keys), toggled => sub { invbool \$user_keys; #- assure other methods disabled if ($user_keys == 1) { $xfer_keys = 0; $use_expect = 0; } destroy_widget(); $current_widget->(); }); if ($previous_function) { fonction_env(\$box_where_net, \&advanced_where_net_types, \&$previous_function, "net"); } else { fonction_env(\$box_where_net, \&advanced_where_net_types, \&advanced_where, "net"); } $up_box->show_all; } sub advanced_where_cd { my ($previous_function) = @_; my $box_where_cd; get_cd_info(); my $combo_where_cd_device = new Gtk2::OptionMenu(); if (keys %cd_devices) { $combo_where_cd_device->set_popdown_strings(sort keys %cd_devices); } else { $combo_where_cd_device->set_popdown_strings(@no_devices); } my $combo_where_cd_time = new Gtk2::OptionMenu(); $combo_where_cd_time->set_popdown_strings("650 Mb", "700 Mb", "750 Mb", "800 Mb"); my $combo_where_cdrecord_device = new Gtk2::Combo(); my @dev_codes; foreach my $key (keys %cd_devices) { push(@dev_codes, $cd_devices{$key}{rec_dev}); } $combo_where_cdrecord_device->set_popdown_strings(@dev_codes) if keys %cd_devices; gtkpack($advanced_box, $box_where_cd = gtkpack_(new Gtk2::VBox(0, 6), 0, my $check_where_cd = new Gtk2::CheckButton(N("Use CD/DVDROM to backup")), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Choose your CD/DVD device")), $where_cd), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive($combo_where_cd_device, $where_cd), ), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Choose your CD/DVD media size (Mb)")), $where_cd), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive($combo_where_cd_time, $where_cd), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(new Gtk2::Label(N("Multisession CD")), $where_cd), 0, gtkset_sensitive(my $check_multisession = new Gtk2::CheckButton(), $where_cd), 0, gtkset_sensitive(new Gtk2::Label(N("CDRW media")), $where_cd), 0, gtkset_sensitive(my $check_cdrw = new Gtk2::CheckButton(), $where_cd), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Erase your RW media (1st Session)")), $cdrw && $where_cd), 0, gtkset_sensitive(my $button_erase_now = Gtk2::Button->new_from_stock(N(" Erase Now ")), $cdrw), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(my $check_cdrw_erase = new Gtk2::CheckButton(), $cdrw && $where_cd), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(new Gtk2::Label(N("DVDR device")), $where_cd), 0, gtkset_sensitive(my $check_dvdr = new Gtk2::CheckButton(), $where_cd), 0, gtkset_sensitive(new Gtk2::Label(N("DVDRAM device")), $where_cd), 0, gtkset_sensitive(my $check_dvdram = new Gtk2::CheckButton(), $where_cd), ), # don't know what this is about - hold off for now (SB) # 0, new Gtk2::VBox(0, 5), # 0, gtkpack_(new Gtk2::HBox(0,10), # 0, gtkset_sensitive(new Gtk2::Label(N("Please check if you want to include\n install boot on your CD.")), $where_cd), # 1, new Gtk2::VBox(0, 5), # 0, gtkset_sensitive(my $check_cd_with_install_boot = new Gtk2::CheckButton(), $where_cd), # ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Enter your CD Writer device name\n ex: 0,1,0")), $where_cd), 1, new Gtk2::VBox(0, 5), # 0, gtkset_size_request(gtkset_sensitive($cd_device_entry = new Gtk2::Entry(), $where_cd), 200, 20), 0, gtkset_sensitive(gtkset_size_request($combo_where_cdrecord_device, 200, 20), $where_cd), ), ), ); # foreach ([$check_cdrw_erase, \$media_erase], [$check_cd_with_install_boot, \$cd_with_install_boot ]) { foreach ([$check_cdrw_erase, \$media_erase], [$check_dvdr, \$dvdr], [$check_dvdram, \$dvdram], [$check_multisession, \$multi_session]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 }) } gtksignal_connect(gtkset_active($check_where_cd, $where_cd), toggled => sub { $where_cd = $where_cd ? 0 : 1; #- toggle where_net, where_tape off if ($where_cd == 1) { $where_net = 0; $where_tape = 0; } destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_cdrw, $cdrw), toggled => sub { $cdrw = $cdrw ? 0 : 1; $check_cdrw_erase->set_sensitive($cdrw); destroy_widget(); $current_widget->(); }); $button_erase_now->signal_connect('clicked', sub { if ($cd_device) { erase_cdrw(); } else { $in->ask_warn('', N("No CD device defined!")); } }); $combo_where_cdrecord_device->entry->set_text($cd_device); $combo_where_cdrecord_device->entry->signal_connect('changed', sub { $cd_device = $combo_where_cdrecord_device->entry->get_text }); $combo_where_cd_time->entry->set_text($cd_time); $combo_where_cd_time->entry->signal_connect('changed', sub { $cd_time = $combo_where_cd_time->entry->get_text }); #- this one drives changes in the other entries #- still not getting quite the desired behavior, but combo box signals seem to be limited #- tried to trigger from the selection, but it either does nothing or crashes! #- $combo_where_cd_device->entry->set_text($std_device); $combo_where_cd_device->entry->signal_connect('activate', sub { $std_device = $combo_where_cd_device->entry->get_text; $combo_where_cdrecord_device->entry->set_text($cd_devices{$std_device}{rec_dev}); $check_dvdr->set_active($cd_devices{$std_device}{dvdr}); $check_dvdram->set_active($cd_devices{$std_device}{dvdram}); #- do this one last or the widget destory mucks up the others $check_cdrw->set_active($cd_devices{$std_device}{cdrw}); }); if ($previous_function) { fonction_env(\$box_where_cd, \&advanced_where_cd, \&$previous_function, ""); } 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 = new Gtk2::OptionMenu(); if (@tape_devices) { $combo_where_tape_device->set_popdown_strings(@tape_devices) } else { $combo_where_tape_device->set_popdown_strings(@no_devices); } my $box_where_tape; local $_; gtkpack($advanced_box, $box_where_tape = gtkpack_(new Gtk2::VBox(0, 6), 0, new Gtk2::HSeparator, 0, my $check_where_tape = new Gtk2::CheckButton(N("Use tape to backup")), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Device name to use for backup")), $where_tape), 1, new Gtk2::VBox(0, 6), #0, gtkset_sensitive(gtkset_size_request($combo_where_tape_device, 200, 20), $where_tape), 0, gtkset_sensitive($combo_where_tape_device, $where_tape), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Don't rewind tape after backup")), $where_tape), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(my $check_tape_rewind = new Gtk2::CheckButton(), $where_tape), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Erase tape before backup")), $where_tape), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(my $check_tape_erase = new Gtk2::CheckButton(), $where_tape), ), 0, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Eject tape after the backup")), $where_tape), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(my $check_tape_eject = new Gtk2::CheckButton(), $where_tape), ), 0, new Gtk2::VBox(0, 6), # not appropriate - disable # 0, gtkpack_(new Gtk2::HBox(0,10), # 0, gtkset_sensitive(new Gtk2::Label(N("Please enter the maximum size\n allowed for Drakbackup (Mb)")), $where_tape), # 1, new Gtk2::VBox(0, 6), # 0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_tape), 200, 20), # ), 0, gtkpack_(new Gtk2::HBox(0,10),), ), ); gtksignal_connect(gtkset_active($check_where_tape, $where_tape), toggled => sub { $where_tape = $where_tape ? 0 : 1; #- assure other methods are off if ($where_tape == 1) { $where_net = 0; $where_cd = 0; } destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_tape_rewind, $tape_norewind), toggled => sub { $tape_norewind = $tape_norewind ? 0 : 1; $_ = $tape_device; if ($tape_norewind) { $tape_device =~ s|/st|/nst|; } else { $tape_device =~ s|/nst|/st|; } $combo_where_tape_device->entry->set_text($tape_device); destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_tape_erase, $media_erase), toggled => sub { $media_erase = $media_erase ? 0 : 1; destroy_widget(); $current_widget->(); }); gtksignal_connect(gtkset_active($check_tape_eject, $media_eject), toggled => sub { $media_eject = $media_eject ? 0 : 1; destroy_widget(); $current_widget->(); }); $combo_where_tape_device->entry->set_text($tape_device); $combo_where_tape_device->entry->signal_connect('changed', sub { $tape_device = $combo_where_tape_device->entry->get_text; }); if ($previous_function) { fonction_env(\$box_where_tape, \&advanced_where_tape, \&$previous_function, ""); } 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 ($max_space == 1000.0) { $max_space = int(0.8 * get_free_space($save_path)) if -d $save_path; } my $adj = new Gtk2::Adjustment($max_space, 0.0, $max_space, 10.0, 5.0, 0.0); my $spinner; gtkpack($advanced_box, $box_where_hd = gtkpack_(new Gtk2::VBox(0, 6), 0, new Gtk2::HSeparator, # 0, my $check_where_hd = new Gtk2::CheckButton( N("Use Hard Disk to backup")), # 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory to save to:")), $where_hd), 1, new Gtk2::VBox(0, 6), 0, gtkset_size_request(gtkset_sensitive($save_path_entry = new Gtk2::Entry(), $where_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new, clicked => sub { filedialog_where_hd() }), $where_hd), ), 0, new Gtk2::VBox(0, 6), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Maximum size\n allowed for Drakbackup (Mb)")), $where_hd), 1, new Gtk2::VBox(0, 6), 0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_hd), 200, 20), ), # just disable for now - doesn't do anything anyway (sb) # 0, gtkpack_(new Gtk2::HBox(0,10), # 1, new Gtk2::VBox(0, 6), # 0, gtkset_sensitive(my $check_where_hd_quota = new Gtk2::CheckButton(N("Use quota for backup files.")), $where_hd), # 0, new Gtk2::VBox(0, 6), # ), ), ); # foreach ([$check_where_hd_quota, \$hd_quota]) { # my $ref = $_->[1]; # gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 }) # } $button->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-dossier-32"))); $save_path_entry->set_text($save_path); $spinner->signal_connect('changed', sub { $max_space = $spinner->get_text }); $save_path_entry->signal_connect('changed', sub { $save_path = $save_path_entry->get_text; if (-d $save_path) { $max_space = int(0.8 * get_free_space($save_path)); # seems to be the easiest way to avoid the widgets fighting over values # and getting grabage in $max_value destroy_widget(); advanced_where_hd(); } }); if ($previous_function) { fonction_env(\$box_where_hd, \&advanced_where_hd, \&$previous_function, ""); } 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_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtksignal_connect(my $button_where_net = Gtk2::Button->new, clicked => sub { destroy_widget(); advanced_where_net_types(); }), 1, gtksignal_connect(my $button_where_cd = Gtk2::Button->new, clicked => sub { destroy_widget(); if (require_rpm("mkisofs", "cdrecord")) { advanced_where_cd(); } else { destroy_widget(); install_rpm(\&advanced_where); } }), 1, gtksignal_connect(my $button_where_hd = Gtk2::Button->new, clicked => sub { destroy_widget(); advanced_where_hd(); }), 1, gtksignal_connect(my $button_where_tape = Gtk2::Button->new, clicked => sub { destroy_widget(); advanced_where_tape() }), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $button_where_net->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-network-40"), new Gtk2::Label(N("Network")), new Gtk2::HBox(0, 5) )); $button_where_cd->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-CD-40"), new Gtk2::Label(N("CDROM / DVDROM")), new Gtk2::HBox(0, 5) )); $button_where_hd->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-discdurwhat-40"), new Gtk2::Label(N("HardDrive / NFS")), new Gtk2::HBox(0, 5) )); $button_where_tape->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-tape-40"), new Gtk2::Label(N("Tape")), new Gtk2::HBox(0, 5) )); fonction_env(\$box_where, \&advanced_where, \&advanced_box, ""); $up_box->show_all; } #- 7/7/2002 - S.Benedict reworked when - drop all the checkboxes and use a list #- chances that we want to do backups via multiple medias in cron are slim sub advanced_when() { my $box_when; # $daemon_media = ''; my $combo_when_space = new Gtk2::OptionMenu(); my %trans = (N("hourly") => 'hourly', N("daily") => 'daily', N("weekly") => 'weekly', N("monthly") => 'monthly'); my %trans2 = ('hourly' => N("hourly"), 'daily' => N("daily"), 'weekly' => N("weekly"), 'monthly' => N("monthly")); $combo_when_space->set_popdown_strings(N("hourly"), N("daily"), N("weekly"), N("monthly")); #- drop down list of possible medias - default to config value my $entry_media_type = new Gtk2::OptionMenu(); $entry_media_type->set_popdown_strings(@media_types, @net_methods); $entry_media_type->entry->set_text($daemon_media); gtkpack($advanced_box, $box_when = gtkpack_(new Gtk2::VBox(0, 15), 0, gtkpack_(new Gtk2::HBox(0,10), 1, new Gtk2::HBox(0,10), 1, gtkcreate_img("ic82-when-40"), 0, my $check_when_daemon = new Gtk2::CheckButton(N("Use daemon")), 1, new Gtk2::HBox(0,10), ), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Please choose the time \ninterval between each backup")), $backup_daemon), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive($combo_when_space, $backup_daemon), ), 0, new Gtk2::HBox(0,10), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Please choose the\nmedia for backup.")), $backup_daemon), 1, new Gtk2::HBox(0,10), 0, gtkpack_(new Gtk2::VBox(0,10), 0, gtkset_sensitive($entry_media_type, $backup_daemon), ), ), 0, new Gtk2::HSeparator, 1, gtkset_sensitive(new Gtk2::Label(N("Please be sure that the cron daemon is included in your services. \nNote that currently all 'net' medias also use the hard drive.")), $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{$when_space}); $combo_when_space->entry->signal_connect('changed', sub { $when_space = $trans{$combo_when_space->entry->get_text} }); $entry_media_type->entry->signal_connect('changed', sub { $daemon_media = $entry_media_type->entry->get_text; }); fonction_env(\$box_when, \&advanced_when, \&advanced_box, ""); $up_box->show_all; } sub advanced_options() { my $box_options; gtkpack($advanced_box, $box_options = gtkpack_(new Gtk2::VBox(0, 15), # 0, gtkpack_(new Gtk2::HBox(0,10), # 1, new Gtk2::VBox(0,10), # 1, gtkcreate_img("ic82-moreoption-40"), # 1, N("Please choose correct options to backup."), # 1, new Gtk2::VBox(0,10), # ), # 0, new Gtk2::HSeparator, # 0, gtkpack_(new Gtk2::VBox(0,10), # 0, gtkset_sensitive(my $check_tar_bz2 = new Gtk2::CheckButton( N("Use Tar and bzip2 (very slow) [Please be careful if you\n (un)select this option, as all your old backups will be deleted.]")), 0), 0, my $check_backupignore = new Gtk2::CheckButton(N("Use .backupignore files")), # 0, new Gtk2::VBox(0,10), 0, gtkpack_(new Gtk2::HBox(0,10), 0, my $check_mail = new Gtk2::CheckButton(N("Send mail report after each backup to:")), 1, new Gtk2::HBox(0,10), 0, my $mail_entry = new Gtk2::Entry(), ), # ), 0, gtkpack_(new Gtk2::HBox(0,10), 0, my $check_del_hd_files = new Gtk2::CheckButton(N("Delete Hard Drive tar files after backup to other media.")), ), ), ); check_list([$check_mail, \$send_mail], [$check_del_hd_files, \$del_hd_files], [$check_backupignore, \$backupignore]); # check_list([$check_mail, \$send_mail], [$check_tar_bz2, \$comp_mode], [$check_backupignore, \$backupignore]); $mail_entry->set_text($user_mail); $mail_entry->signal_connect('changed', sub { $user_mail = $mail_entry->get_text }); fonction_env(\$box_options, \&advanced_options, \&advanced_box, "options"); $up_box->show_all; } sub advanced_box() { my $box_adv; gtkpack($advanced_box, $box_adv = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(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, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $button_what->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-discdurwhat-40"), new Gtk2::Label(N("What")), new Gtk2::HBox(0, 5) )); $button_where->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-where-40"), new Gtk2::Label(N("Where")), new Gtk2::HBox(0, 5) )); $button_when->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-when-40"), new Gtk2::Label(N("When")), new Gtk2::HBox(0, 5) )); $button_options->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-moreoption-40"), new Gtk2::Label(N("More Options")), new Gtk2::HBox(0, 5) )); fonction_env(\$box_adv, \&advanced_box, \&interactive_mode_box, ""); $up_box->show_all; } ################################################ WIZARD ################################################ sub wizard_step3() { my $box2; my $text = new Gtk2::TextView; save_conf_file(); read_conf_file(); system_state(); gtktext_insert($text, [ [ $system_state ] ]); button_box_restore_main(); gtkpack($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, gtkpack_(new Gtk2::VBox(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() { my $box2; gtkpack($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(0, 5), 0, N("Please choose where you want to backup"), 0, gtkpack_(new Gtk2::HBox(0, 15), 0, my $check_wizard_hd = new Gtk2::CheckButton(N("on Hard Drive")), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub { destroy_widget(); to_ok(); advanced_where_hd(\&wizard_step2); to_normal(); }), $where_hd), ), 0, gtkpack_(new Gtk2::HBox(0, 15), 0, my $check_wizard_net = new Gtk2::CheckButton(N("across Network")), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub { destroy_widget(); to_ok(); advanced_where_net_types(\&wizard_step2); to_normal(); }), $where_net), ), 0, gtkpack_(new Gtk2::HBox(0, 15), 0, my $check_wizard_cd = new Gtk2::CheckButton(N("on CDROM")), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub { destroy_widget(); advanced_where_cd(\&wizard_step2); }), $where_cd), ), 0, gtkpack_(new Gtk2::HBox(0, 15), 0, my $check_wizard_tape = new Gtk2::CheckButton(N("on Tape Device")), 1, new Gtk2::VBox(0, 5), 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Configure")), clicked => sub { destroy_widget(); advanced_where_tape(\&wizard_step2); }), $where_tape), ), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); foreach ([$check_wizard_hd, \$where_hd], [$check_wizard_cd, \$where_cd], [$check_wizard_tape, \$where_tape], [$check_wizard_net, \$where_net]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1; $where_hd = 1; if (!$where_hd && !$where_cd && !$where_net) { $next_widget = \&message_noselect_box } else { $next_widget = \&wizard_step3 } destroy_widget(); wizard_step2(); }) } if (!$where_hd && !$where_cd && !$where_net) { fonction_env(\$box2, \&wizard_step2, \&wizard, "", \&message_noselect_box) } else { fonction_env(\$box2, \&wizard_step2, \&wizard, "", \&wizard_step3) } button_box_wizard(); $up_box->show_all; } sub wizard() { my $box2; gtkpack($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(0, 5), 0, N("Please choose what you want to backup"), 0, my $check_wizard_sys = new Gtk2::CheckButton(N("Backup system")), 0, my $check_wizard_user = new Gtk2::CheckButton(N("Backup Users")), 0, gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Select user manually")), clicked => sub { destroy_widget(); advanced_what_user(\&wizard); }), ), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); foreach ([$check_wizard_sys, \$backup_sys], [$check_wizard_user, \$backup_user]) { my $ref = $_->[1]; gtksignal_connect(gtkset_active($_->[0], $$ref), toggled => sub { $$ref = $$ref ? 0 : 1; if ($backup_sys || $backup_user && @user_list) { $next_widget = \&wizard_step2 } else { $next_widget = \&message_noselect_what_box } }) } if ($backup_sys || $backup_user && @user_list) { fonction_env(\$box2, \&wizard, \&interactive_mode_box, "", \&wizard_step2) } else { fonction_env(\$box2, \&wizard, \&interactive_mode_box, "", \&message_noselect_what_box) } button_box_wizard(); $up_box->show_all; } ################################################ RESTORE ################################################ sub find_backup_to_restore() { my @list_backup; my @list_backup_tmp2; my $to_put; @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 , $_; } if (any { /^backup_other/ } @list_backup) { $other_backuped = 1 } if (any { /^backup_sys/ } @list_backup) { $sys_backuped = 1 } foreach (grep { /^backup_sys_/ } @list_backup) { chomp; s/^backup_sys_//gi; s/.tar.gz$//gi; s/.tar.bz2$//gi; my ($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); $to_put = "$day/$month/$year $hour:$min $_"; push @sys_backuped , $to_put; } $restore_step_sys_date = $to_put; foreach (grep { /^backup_user_/ } @list_backup) { chomp; s/^backup_user_//gi; s/.tar.gz$//gi; s/.tar.bz2$//gi; my ($nom, $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); # my $to_put = " $nom, (date: $date, hour: $heure)"; $to_put = "$_ user: $nom, date: $day/$month/$year, hour: $hour:$min"; push @user_backuped , $to_put; any { /^$nom$/ } @user_list_backuped or push @user_list_backuped, $nom; } } sub system_state() { # $system_state; if ($cfg_file_exist) { $system_state = N("\nBackup Sources: \n"); $backup_sys and $system_state .= N("\n- System Files:\n"); $backup_sys and $system_state .= "\t\t$_\n" foreach @sys_files; $backup_user and $system_state .= N("\n- User Files:\n"); $backup_user and $system_state .= "\t\t$_\n" foreach @user_list; @list_other and $system_state .= N("\n- Other Files:\n"); @list_other and $system_state .= "\t\t$_\n" foreach @list_other; $where_hd and $system_state .= N("\n- Save on Hard drive on path: %s\n", $save_path); $where_hd and $system_state .= N("\tLimit disk usage to %s Mb\n", $max_space); if ($del_hd_files && ($where_cd || $where_tape || $where_net) && $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 = 'NO'; $erase_media = 'YES' if $media_erase && ($where_cd || $where_tape); $where_cd and $system_state .= N("\n- Burn to CD"); $where_cd and $cdrw and $system_state .= N("RW"); $where_cd and $system_state .= N(" on device: %s", $cd_device); $where_cd and $multi_session and $system_state .= N(" (multi-session)"); $where_tape and $system_state .= N("\n- Save to Tape on device: %s", $tape_device); (($where_cd || $where_tape) && $media_erase) and $system_state .= N("\t\tErase=%s", $erase_media); $where_cd || $where_tape and $system_state .= "\n"; $where_net and $system_state .= N("\n- Save via %s on host: %s\n", $net_proto, $host_name); $where_net and $system_state .= N("\t\t user name: %s\n\t\t on path: %s \n", $login_user, $host_path); $system_state .= N("\n- Options:\n"); $backup_sys or $system_state .= N("\tDo not include System Files\n"); if ($comp_mode) { $system_state .= N("\tBackups use tar and bzip2\n"); } else { $system_state .= N("\tBackups use tar and gzip\n"); } $daemon_media and $system_state .= N("\n- Daemon (%s) include:\n", $when_space); $daemon_media eq 'hd' and $system_state .= N("\t-Hard drive.\n"); $daemon_media eq 'cd' and $system_state .= N("\t-CDROM.\n"); $daemon_media eq 'tape' and $system_state .= N("\t-Tape \n"); $daemon_media eq 'ftp' and $system_state .= N("\t-Network by FTP.\n"); $daemon_media eq 'ssh' and $system_state .= N("\t-Network by SSH.\n"); $daemon_media eq 'rsync' and $system_state .= N("\t-Network by rsync.\n"); $daemon_media eq 'webdav' and $system_state .= N("\t-Network by webdav.\n"); } else { $system_state = N("No configuration, please click Wizard or Advanced.\n"); } } sub restore_state() { my @tmp = split(' ', $restore_step_sys_date); $restore_state = N("List of data to restore:\n\n"); if ($restore_sys) { $restore_state .= "- Restore System Files.\n"; $restore_state .= " - from date: $tmp[0] $tmp[1]\n"; } if ($restore_user) { $restore_state .= "- 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 .= "- Restore Other Files: \n"; -f "$path_to_find_restore/list_other" and $restore_state .= "\t\t$_\n" foreach split("\n", cat_("$path_to_find_restore/list_other")); } if ($restore_other_path) { $restore_state .= "- Path to Restore: $restore_path \n"; } } sub select_most_recent_selected_of { my ($user_name) = @_; my @list_tmp2; local $_; my @tmp = sort @user_list_to_restore2; foreach (grep { /$user_name/ } sort @tmp) { push @list_tmp2 , $_ } 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 $_; -d $path_to_find_restore and my @list_backup_tmp2 = 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/.tar.gz//gi; s/.tar.bz2//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 show_backup_details { my ($function, $mode, $name) = @_; my $archive_file_detail; my $value; # dies in gtk2 # my $fixed_font = Gtk2::Gdk::Font->load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*"); my $command2; my $tarfile; # FIXME - only tar.gz at the moment my $extension = ".tar.gz"; if ($mode eq "user") { #- we've only got a partial filename in this case $tarfile = "$path_to_find_restore/backup_*" . $name . $extension; } 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] . $extension; } my $command1 = "stat " . $tarfile; $command2 = "tar -tzvf " . $tarfile; local *TMP; open TMP, "$command1 2>&1 |"; while ($value = ) { $archive_file_detail .= $value; } close TMP; $archive_file_detail .= "\n\n"; open TMP, "$command2 2>&1 |"; while ($value = ) { #- drop the permissions display for the sake of readability $archive_file_detail .= substr($value, 11); } close TMP; my $text = new Gtk2::TextView; my $advanced_box_archive; gtktext_insert(gtkset_editable($text, 0), $archive_file_detail); gtkpack($advanced_box, $advanced_box_archive = gtkpack_(new Gtk2::VBox(0,10), 1, gtkpack_(new Gtk2::HBox(0,0), 1, create_scrolled_window($text), ), 0, gtkadd(gtkset_layout(new Gtk2::HButtonBox, 'spread'), gtksignal_connect(Gtk2::Button->new_from_stock(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; foreach (@files_list) { #- let's quiet this down (SB) if (system("gzip -l $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 = new Gtk2::TextView; 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_(new Gtk2::VBox(0,10), 0, new Gtk2::VBox(0,10), 1, gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 0, gtkcreate_img('warning'), 0, N("Backup files are corrupted"), 1, new Gtk2::VBox(0, 5), ), 0, new Gtk2::VBox(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 = new Gtk2::TextView; gtktext_insert($text, [ [ $restore_state ] ]); button_box_restore_main(); gtkpack($advanced_box, $do_restore = gtkpack_(new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 0, N(" All of your selected data have been "), 0, N(" Successfuly Restored on %s ", $restore_path), 1, new Gtk2::VBox(0,10), ), ); button_box_build_backup_end(); $central_widget = \$do_restore; $up_box->show_all; } sub return_path { my ($username) = @_; my $usr; my $home_dir; my $passwdfile = "/etc/passwd"; local *PASSWD; open(PASSWD, $passwdfile) or exit 1; while (defined(my $line = )) { chomp($line); ($usr, $home_dir) = (split(/:/, $line))[0,5]; last if $usr eq $username; } close(PASSWD); return $home_dir; } sub restore_backend() { my $untar_cmd; my $exist_problem = 0; my $user_dir; my $tnom; my $username; my $theure2; local $_; -d $restore_path or mkdir_p $restore_path; if (any { /tar.gz$/ } all($path_to_find_restore)) { $untar_cmd = 0; } else { $untar_cmd = 1; } 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 ($backup_user_versions) { ($tnom, $username, $theure2) = /^(\w+_\w+_user_)(.*)_(\d+_\d+.*)$/; } else { ($tnom, $username, $theure2) = /^(\w+_user_)(.*)_(\d+_\d+.*)$/; } $user_dir = return_path($username); -d $user_dir and rm_rf($user_dir) if $remove_user_before_restore; $DEBUG and print "user name to restore: $username, user directory: $user_dir\n"; $untar_cmd or system(" tar xfz $path_to_find_restore/$_ -C $restore_path"); $untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/$_ | tar xf -C $restore_path "); } #- flush this out for another cycle (SB) @user_list_to_restore2 = (); } } if ($restore_sys) { if ($backup_sys_versions) { select_sys_data_to_restore(); if (valid_backup_test(@sys_list_to_restore) == -1) { $exist_problem = 1; restore_aff_backup_problems(); } else { $untar_cmd or system("tar xfz $path_to_find_restore/$_ -C $restore_path ") foreach @sys_list_to_restore; $untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/$_ | tar xf -C $restore_path ") foreach @sys_list_to_restore; } } else { $untar_cmd or system("tar xfz $path_to_find_restore/backup_sys.tar.gz -C $restore_path "); $untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/backup_sys.tar.bz2 | tar xf -C $restore_path "); } } if ($restore_other) { $untar_cmd or system("tar xfz $path_to_find_restore/backup_other.tar.gz -C $restore_path "); $untar_cmd and system("/usr/bin/bzip2 -cd $path_to_find_restore/backup_other.tar.bz2 | tar xf -C $restore_path "); } $exist_problem or restore_aff_result(); } sub restore_do() { if ($backup_bef_restore) { if ($restore_sys) { $backup_sys = 1; } else { $backup_sys = 0; } if ($restore_user) { $backup_user = 1; @user_list = @user_list_to_restore; } else { $backup_user = 0; } build_backup_status(); read_conf_file(); build_backup_files(); $table->destroy; } restore_do2(); } sub restore_do2() { my $do_restore; my $text = new Gtk2::TextView; restore_state(); gtktext_insert($text, [ [ $restore_state ] ]); button_box_restore_main(); gtkpack($advanced_box, $do_restore = gtkpack_(new Gtk2::VBox(0,10), 0, N(" Restore Configuration "), 1, create_scrolled_window($text), ), ); button_box_restore_end(); fonction_env(\$do_restore, \&restore_do2, \&restore_box, "restore"); $up_box->show_all; } sub restore_step_other() { my $retore_step_other; my $text = new Gtk2::TextView; my $other_rest = cat_("$path_to_find_restore/list_other"); gtktext_insert($text, [ [ $other_rest ] ]); gtkpack($advanced_box, $retore_step_other = gtkpack_(new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 1, create_scrolled_window($text), 0, my $check_restore_other_sure = new Gtk2::CheckButton(N("OK to restore the other files.")), 1, new Gtk2::VBox(0,10), ), ); check_list([$check_restore_other_sure, \$restore_other]); fonction_env(\$retore_step_other, \&restore_step_other, \&restore_step2, "restore", \&restore_do); $up_box->show_all; } my %check_user_to_restore; 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_(new Gtk2::VBox(0,10), 0, new Gtk2::VBox(0,10), 0, N("User list to restore (only the most recent date per user is important)"), 1, create_scrolled_window(gtkpack__(new Gtk2::VBox(0,0), map { my $name; my $var2; my $name_complet = $_; $name = (split(' ', $name_complet))[0]; my @user_list_tmp; my $restore_row = new Gtk2::HBox(0,5); my $b = new Gtk2::CheckButton($name_complet); my $details = Gtk2::Button->new_from_stock(" Details "); $restore_row->pack_start($b, 1, 1, 0); $restore_row->pack_end(new Gtk2::VBox(1,5), 0, 0, 0); $restore_row->pack_end($details, 0, 0, 0); # this doesn't work - I don't understand why - but you end up with # everything selected when you hit the screen a second time, after selecting one # if (grep $name_complet, @user_list_to_restore2) { # 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; # } # this doesn't work right either - returning to the screen only 1 is selected # yet several are scheduled to be restored 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 { #- we're only passing a portion of the filename to #- the subroutine so we need to let it know this 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", \&restore_step_other) } elsif ($restore_sys) { fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step_sys, "restore", \&restore_step_other) } else { fonction_env(\$retore_step_user, \&restore_step_user, \&restore_step2, "restore", \&restore_do) } $up_box->show_all; } sub restore_step_sys() { my $restore_step_sys; my $check_backup_before; my $combo_restore_step_sys = new Gtk2::OptionMenu(); $combo_restore_step_sys->set_popdown_strings(@sys_backuped); gtkpack($advanced_box, $restore_step_sys = gtkpack_(new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 0, $check_backup_before = new Gtk2::CheckButton(N("Backup the system files before:")), 0, gtkpack_(new Gtk2::HBox(0,10), 1, N("please choose the date to restore"), 0, $combo_restore_step_sys, 0, my $details = Gtk2::Button->new_from_stock(" Details "), 0, new Gtk2::HBox(0,10), ), 1, new Gtk2::VBox(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 my $backup_date = $combo_restore_step_sys->entry->get_text; destroy_widget(); show_backup_details(\&restore_step_sys, "sys", $backup_date); }); $combo_restore_step_sys->entry->set_text($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", \&restore_step_user) } elsif ($restore_other) { fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, "restore", \&restore_step_other) } else { fonction_env(\$restore_step_sys, \&restore_step_sys, \&restore_step2, "restore", \&restore_do) } $up_box->show_all; } sub restore_other_media_hd { my ($previous_function) = @_; my $box_where_hd; my $button; my $adj = new Gtk2::Adjustment(550.0, 10.0, 10000.0, 10.0, 5.0, 0.0); my $spinner; gtkpack($advanced_box, $box_where_hd = gtkpack_(new Gtk2::VBox(0, 6), 0, new Gtk2::HSeparator, 0, my $check_where_hd = new Gtk2::CheckButton(N("Use Hard Disk to backup")), 0, new Gtk2::HSeparator, 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory to save:")), $where_hd), 1, new Gtk2::VBox(0, 6), 0, gtkset_size_request(gtkset_sensitive($save_path_entry = new Gtk2::Entry(), $where_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new, clicked => sub { filedialog_where_hd() }), $where_hd), ), 0, new Gtk2::VBox(0, 6), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Enter the maximum size\n allowed for Drakbackup (Mb)")), $where_hd), 1, new Gtk2::VBox(0, 6), 0, gtkset_size_request(gtkset_sensitive($spinner = new Gtk2::SpinButton($adj, 0, 0), $where_hd), 200, 20), ), 0, gtkpack_(new Gtk2::HBox(0,10), 1, new Gtk2::VBox(0, 6), 0, gtkset_sensitive(my $check_where_hd_quota = new Gtk2::CheckButton(N("Use quota for backup files.")), $where_hd), 0, new Gtk2::VBox(0, 6), ), ), ); check_list([$check_where_hd_quota, \$hd_quota]); gtksignal_connect(gtkset_active($check_where_hd, $where_hd), toggled => sub { $where_hd = $where_hd ? 0 : 1; destroy_widget(); $current_widget->(); }); $button->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-dossier-32"))); $save_path_entry->set_text($save_path); $save_path_entry->signal_connect('changed', sub { $save_path = $save_path_entry->get_text }); if ($previous_function) { fonction_env(\$box_where_hd, \&advanced_where_hd, \&$previous_function, "") } else { fonction_env(\$box_where_hd, \&advanced_where_hd, \&advanced_where, "") } $up_box->show_all; } sub restore_other_media() { my $box_find_restore; my $button; gtkpack($advanced_box, $box_find_restore = gtkpack_(new Gtk2::VBox(0, 6), 0, new Gtk2::HSeparator, 0, my $check_other_media_hd = new Gtk2::CheckButton(N("Restore from Hard Disk.")), 0, gtkpack_(new Gtk2::HBox(0,10), 0, gtkset_sensitive(new Gtk2::Label(N("Enter the directory where backups are stored")), $other_media_hd), 1, new Gtk2::VBox(0, 6), 0, gtkset_size_request(gtkset_sensitive($restore_find_path_entry = new Gtk2::Entry(), $other_media_hd), 152, 20), 0, gtkset_sensitive($button = gtksignal_connect(Gtk2::Button->new, clicked => sub { filedialog_restore_find_path(); }), $other_media_hd), ), 1, new Gtk2::VBox(0, 6), # 0, new Gtk2::HSeparator, # 0, my $check_other_media_net = new Gtk2::CheckButton( N("Restore from Network")), # 0, new Gtk2::VBox(0, 6), # 1, gtkpack(new Gtk2::HBox(0,10), # new Gtk2::VBox(0, 6), # gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock("Network"), clicked => sub { # destroy_widget(); # restore_find_net(\&restore_other_media);}), !$other_media_hd), # new Gtk2::VBox(0, 6), # ), # 1, new Gtk2::VBox(0, 6), # 0, new Gtk2::HSeparator, 0, new Gtk2::VBox(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->(); }); # gtksignal_connect(gtkset_active($check_other_media_net, !$other_media_hd), toggled => sub { # $other_media_hd = $other_media_hd ? 0 : 1; # destroy_widget(); # $current_widget->(); # }); $button->add(gtkpack(new Gtk2::HBox(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 }); #- not sure if this was the original intent - address the crash at "Next" fonction_env(\$box_find_restore, \&restore_other_media, \&restore_step2, "other_media", \&restore_do); $up_box->show_all; } sub restore_step2() { my $retore_step2; my $other_exist; my $sys_exist; my $user_exist; local $_; my $restore_info_path = $save_path; $restore_info_path = $path_to_find_restore if $where_hd || $where_cd; my $info_prefix = "backup"; $info_prefix = "list" if $where_net || $where_tape; if (-f "$restore_info_path/$info_prefix" . "_other*") { $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 } # disabling this (sb) - very nicely wipes out your backup media if the user isn't very careful # cycling through the GUI turns it back on for you!!! # $backup_sys_versions || $backup_user_versions and $backup_bef_restore = 1; gtkpack($advanced_box, $retore_step2 = gtkpack_(new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 0, gtkpack_(new Gtk2::HBox(0,10), 0, my $check_restore_other_src = new Gtk2::CheckButton(N("Select another media to restore from")), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Other Media")), clicked => sub { destroy_widget(); restore_other_media(); }), $restore_other_src), ), 0, gtkset_sensitive(my $check_restore_sys = new Gtk2::CheckButton(N("Restore system")), $sys_exist), 0, gtkset_sensitive(my $check_restore_user = new Gtk2::CheckButton(N("Restore Users")), $user_exist), 0, gtkset_sensitive(my $check_restore_other = new Gtk2::CheckButton(N("Restore Other")), $other_exist), 0, gtkpack_(new Gtk2::HBox(0,10), 0, my $check_restore_other_path = new Gtk2::CheckButton(N("select path to restore (instead of /)")), 1, new Gtk2::HBox(0,10), 0, gtkset_sensitive(my $restore_path_entry = new Gtk2::Entry(), $restore_other_path), ), 0, gtkset_sensitive(my $check_backup_bef_restore = new Gtk2::CheckButton(N("Do new backup before restore (only for incremental backups.)")), $backup_sys_versions || $backup_user_versions), 0, gtkset_sensitive(my $check_remove_user_dir = new Gtk2::CheckButton(N("Remove user directories before restore.")), $user_exist), 1, new Gtk2::VBox(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 && $backup_sys_versions) { $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, "restore"); if (!$restore_sys && !$restore_user && !$restore_other) { $next_widget = \&message_norestore_box } elsif ($restore_sys && $backup_sys_versions) { $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 } $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; #- file info in tree view my $model = Gtk2::TreeStore->new("Glib::String"); my $file_list = Gtk2::TreeView->new_with_model($model); my $file_wildcard_entry = new Gtk2::Entry(); gtkpack($advanced_box, $file_restore = gtkpack_(new Gtk2::VBox(0,10), 0, new Gtk2::Label(N("Filename to search for (wildcards allowed):")), 0, gtkpack_(new Gtk2::HBox(0,10), 1, $file_wildcard_entry, 0, gtksignal_connect(new Gtk2::Button(N("Search Backups")), clicked => sub { # FIXME - search the file listings and offer a list of possible matches my $wildcard = $file_wildcard_entry->get_text; show_warning("w", N("Search For...\n%s", $wildcard)); gtkset_sensitive($start_restore, 1); }), ), 1, create_scrolled_window($file_list), 0, gtkset_sensitive(gtksignal_connect($start_restore = new Gtk2::Button(N("Restore Selected")), clicked => sub { # FIXME - search the file listings and offer a list of possible matches show_warning("w", N("Start Search...")); }), 0), ), ); $central_widget = \$file_restore; } sub catalog_restore() { my $catalog_box; my $cat_entry; my @restore_files; my $restore_path_entry; #- 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"); my %full_cat_entry; foreach (@catalog) { chop; my @line_data = split(':', $_); my $t = $line_data[0]; $full_cat_entry{$t} = $_; my $t_catalog = $model->append_set(undef, [ 0 => $t ]); $tree_catalog->get_selection->signal_connect(changed => sub { my ($model, $iter) = $_[0]->get_selected; $model && $iter or return; $cat_entry = $model->get($iter, 0); if ($cat_entry != $t) { $cat_entry = ''; return; } cursor_wait(); @restore_files = (); $lmodel->clear; foreach my $filename (glob("$save_path/list*$cat_entry.txt")) { my @contents = cat_($filename); foreach (@contents) { chop; my $s = $_; $lmodel->append_set(undef, $s); $tree_files->get_selection->signal_connect(changed => sub { my (@what) = $_[0]->get_selected_rows; @restore_files = (); foreach (@what) { my $iter = $lmodel->get_iter($_); $s = $lmodel->get($iter, 0); push @restore_files, $s; } }); } } cursor_norm(); $cat_entry = $full_cat_entry{$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++; } } gtkpack($advanced_box, $catalog_box = gtkpack_(new Gtk2::HBox(0,10), 0, new Gtk2::VBox(0,10), 1, gtkpack_(new Gtk2::VBox(0,5), 1, gtkpack_(new Gtk2::VBox(0, 10), 1, create_scrolled_window($tree_catalog), 1, create_scrolled_window($tree_files), ), 0, gtkpack_(new Gtk2::HBox(1, 10), 1, gtksignal_connect(Gtk2::Button->new_from_stock(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(); } } }), 1, gtksignal_connect(Gtk2::Button->new_from_stock(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(); } } }), 1, gtkpack_(new Gtk2::VBox(0, 5), 0, new Gtk2::Label("Restore To Path"), 0, $restore_path_entry = new Gtk2::Entry(), ), 1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Change\nRestore Path")), clicked => sub { filedialog_generic("Path To Restore To", \$restore_path_entry, \$restore_path); }), ), 0, new Gtk2::VBox(0,10), ), 0, new Gtk2::VBox(0,10), ), ); $restore_path_entry->set_text($restore_path); gtksignal_connect($restore_path_entry, changed => sub { $restore_path = $restore_path_entry->get_text }); button_box_restore(); fonction_env(\$catalog_box, \&catalog_restore, \&restore_find_media_box, "restore", \&catalog_restore); $central_widget = \$catalog_box; $up_box->show_all; } sub restore_catalog_entry { #FIXME # we're working from a catalog entry, which means we know the # the tar file wildcards and some info on where the backup was stored # if it's a local device (HD, tape, CD) - prompt for the media # for tape, find how many other catalog entries had the same # label and calculate the record offset # if it's remote storage, display what we know of the connection # parameters and get the user's verification, then connect restore_status(); my ($cat_entry, @restore_files) = @_; my $username; my $userpass = $passwd_user; my $restore_result = 1; my @line_data = split(':', $cat_entry); my $backup_time = $line_data[0]; #- use our own variables here so we don't 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, "@")) { my @user_host = split("@", $vol_host); $username = $user_host[0]; $vol_host = $user_host[1]; } else { $username = $login_user; } #- create a restore work directory if we don't 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 $save_path in the previous step - deal with it anyway my @restore_tar_files = glob("$dev_path/*$backup_time*$tar_ext"); 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 = $save_path; $save_path = $dev_path; $restore_result = restore_hd_or_cd($cat_entry, $dev_path, @restore_files); $save_path = $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 eq '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($cat_entry, $dev_path, @restore_files); } } if ($media eq 'ftp' || $media eq 'webdav' || $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 #- the various protocols are going to have different requirements #- webdav - it should already be in sitecopyrc - compare it? #- ssh - the only method we have enabled at the moment is with keys #- - no passwd needed #- - if we use expect, it is needed #- - if we use drackbackup keys, then a different ssh call is needed #- rsync - uses a config file with username - rsync.user #- ftp needs all parameters entered $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_webdav($cat_entry, $vol_host, $dev_path, $username, $media, @restore_files) if $media eq 'rsync' || $media eq 'ssh' || $media eq 'webdav'; } # cleanup our restore dir - unlink fails here? system("rm -f $cfg_dir/restores/*"); if (!$restore_result) { show_warning("i", N("Files Restored...")); return 0; } else { show_warning("f", N("Restore Failed...")); return 1; } } sub restore_hd_or_cd { my ($cat_entry, $tarfile_dir, @restore_files) = @_; my $indv_files = @restore_files; my $command; my $wild_card = catalog_to_wildcard($cat_entry); if ($indv_files == 0) { #- full catalog specified foreach (wildcard_to_tarfile($wild_card)) { $command = "tar -C $restore_path -xzf $tarfile_dir/$_"; spawn_progress($command, "Untarring from \n$_ \nto $restore_path."); } } else { #- individual files - pull from appropriate catalog foreach (@restore_files) { my $tarfile = file_to_tarfile($_, $wild_card); $_ = substr($_, 1); $command = "tar -C $restore_path -xzf $tarfile_dir/$tarfile $_"; spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path."); } } return 0; } sub restore_tape { my ($cat_entry, $dev_path, @restore_files) = @_; my $indv_files = @restore_files; my $command; my $wild_card = catalog_to_wildcard($cat_entry); $dev_path =~ s|/st|/nst|; if ($indv_files == 0) { #- full catalog specified foreach (wildcard_to_tarfile($wild_card)) { my $offset = find_tape_offset($cat_entry); $command = "mt -f $dev_path rewind"; spawn_progress($command, "Rewinding tape on $dev_path."); $command = "mt -f $dev_path fsf $offset"; spawn_progress($command, "Moving forward $offset file records."); $command = "tar -C cfg_dir/restores -xf $dev_path"; spawn_progress($command, "Untarring from $dev_path to work directory."); if (-e "$cfg_dir/restores/$_") { $command = "tar -C $restore_path -xzf $cfg_dir/restores/$_"; spawn_progress($command, "Untarring \n$_ \nto $restore_path."); } else { return 1; } } } else { #- individual files - pull from appropriate catalog foreach (@restore_files) { my $tarfile = file_to_tarfile($_, $wild_card); $_ = substr($_, 1); if (!-e "$cfg_dir/restores/$tarfile") { my $offset = find_tape_offset($cat_entry); $command = "mt -f $dev_path rewind"; spawn_progress($command, "Rewinding tape on $dev_path."); $command = "mt -f $dev_path fsf $offset"; spawn_progress($command, "Moving forward $offset file records."); $command = "tar -C cfg_dir/restores -xf $dev_path"; spawn_progress($command, "Untarring from $dev_path to work directory."); } if (-e "$cfg_dir/restores/$tarfile") { $command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_"; spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path."); } else { return 1; } } } return 0; } sub restore_ftp { use Net::FTP; my $ftp; my ($cat_entry, $hostname, $hostpath, $username, $userpass, @restore_files) = @_; my $indv_files = @restore_files; my $command; $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); 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/$_"); $command = "tar -C $restore_path -xzf $cfg_dir/restores/$_"; spawn_progress($command, "Untarring \n$_ \nto $restore_path."); } } else { #- individual files - pull from appropriate catalog foreach (@restore_files) { my $tarfile = file_to_tarfile($_, $wild_card); $_ = substr($_, 1); if (!-e "$cfg_dir/restores/$tarfile") { $ftp->get($tarfile, "$cfg_dir/restores/$tarfile"); } $command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_"; spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path."); } } $ftp->quit; return 0; } sub restore_rsync_ssh_webdav { my ($cat_entry, $hostname, $hostpath, $username, $mode, @restore_files) = @_; my $indv_files = @restore_files; my $command; my $wild_card = catalog_to_wildcard($cat_entry); if ($indv_files == 0) { #- full catalog specified foreach (wildcard_to_tarfile($wild_card)) { if ($mode eq 'ssh') { $command = "scp $username\@$hostname:$hostpath/$_ $cfg_dir/restores/"; } elsif ($mode eq 'rsync') { $command = "rsync --password-file=$cfg_dir/rsync.user $username\@$hostname" . "::" . "$hostpath/$_ $cfg_dir/restores/"; } else { $command = "wget http://$hostname/$hostpath/$_ -P $cfg_dir/restores/"; } spawn_progress($command, "Retrieving backup file \n$_ \nvia $mode."); if (-e "$cfg_dir/restores/$_") { $command = "tar -C $restore_path -xzf $cfg_dir/restores/$_"; spawn_progress($command, "Untarring \n$_ \nto $restore_path."); } else { return 1; } } } else { #- individual files - pull from appropriate catalog foreach (@restore_files) { my $tarfile = file_to_tarfile($_, $wild_card); $_ = substr($_, 1); if (!-e "$cfg_dir/restores/$tarfile") { 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."); } if (-e "$cfg_dir/restores/$tarfile") { $command = "tar -C $restore_path -xzf $cfg_dir/restores/$tarfile $_"; spawn_progress($command, "Untarring \n$_ from \n$tarfile \nto $restore_path."); } else { return 1; } } } return 0; } 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("$save_path/*$wildcard.txt"); foreach (@tarfile) { $_ = basename($_); s/txt/$tar_ext/; s/list/backup/; } @tarfile; } sub file_to_tarfile { my ($restore_file, $wildcard) = @_; my $tarfile = `grep -l $restore_file $save_path/*$wildcard.txt`; chop $tarfile; $tarfile = basename($tarfile); $tarfile =~ s/txt/$tar_ext/; $tarfile =~ s/list/backup/; $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) { if (index($_, $label)) { if (!index($_, $cat_entry)) { # tar seems to need 2 of these to get located $offset++; $offset++; } else { return $offset; } } } } sub restore_box() { my $retore_box; if ($good_restore_path) { $path_to_find_restore = $save_path if $where_hd; $path_to_find_restore = "/mnt/cdrom" if $where_cd; } find_backup_to_restore(); button_box_restore_main(); if ($other_backuped || $sys_backuped || @user_backuped) { gtkpack($advanced_box, $retore_box = gtkpack_(new Gtk2::HBox(0,1), 1, new Gtk2::VBox(0,10), 1, gtkpack_(new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), 1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Search for files to restore")), clicked => sub { $retore_box->destroy; button_box_file_restore(); find_files_to_restore() }), 1, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore all backups")), clicked => sub { $retore_box->destroy; 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_from_stock(N("Custom Restore")), clicked => sub { $retore_box->destroy; button_box_restore(); restore_step2(); }), 1, new Gtk2::VBox(0,10), 1, new Gtk2::VBox(0,10), ), 1, new Gtk2::HBox(0,10), ), ); } else { destroy_widget(); restore_find_media_box(), } fonction_env(\$retore_box, \&restore_box, \&interactive_mode_box, "restore"); $central_widget = \$retore_box; $up_box->show_all; } sub restore_find_media_box() { my $mount_media = 1; $good_restore_path = 0; my $message = "Unable to find backups to restore...\n"; $message .= "Verify that $path_to_find_restore is the correct path" if $where_hd && $where_cd; $message .= " and the CD is in the drive" if $where_cd; if ($where_tape || $net_proto) { $message .= "Backups on unmountable media - Use Catalog to restore"; $mount_media = 0; } $message .= "."; gtkpack($advanced_box, $box2 = gtkpack_(new Gtk2::VBox(0, 5), 1, gtkpack(new Gtk2::HBox(0, 15), new Gtk2::VBox(0, 5), gtkcreate_img('warning'), translate($message), new Gtk2::VBox(0, 5), ), 1, gtkpack(new Gtk2::HBox(0, 15), new Gtk2::VBox(0, 5), gtkpack(new Gtk2::VBox(0, 10), gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("CD in place - continue.")), clicked => sub { $good_restore_path = 1; interactive_mode_box("restore"); }), $mount_media), $new_path_entry = gtkset_sensitive(new Gtk2::Entry(), $mount_media), gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock(N("Browse to new restore repository.")), clicked => sub { filedialog_generic("Directory To Restore From", \$new_path_entry, \$path_to_find_restore); }), $mount_media), gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore From Catalog")), clicked => sub { $box2->destroy; catalog_restore(); }), ), new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $new_path_entry->set_text($path_to_find_restore); $central_widget = \$box2; button_box_find_media($mount_media); $up_box->show_all; } sub restore_status() { destroy_widget(); $pbar3 = new Gtk2::ProgressBar; $stext = new Gtk2::Label(""); gtkpack($advanced_box, $table = gtkpack(new Gtk2::VBox(0, 5), new Gtk2::HBox(0,5), create_packtable({ col_spacings => 10, row_spacings => 5 }, [""], [""], [""], [""], [N("Restore Progress")], [""], [""], [$pbar3], [""], [""], [$plabel3 = new Gtk2::Label(' ')], [""], ), $stext, ), ); $custom_help = "options"; $central_widget = \$table; $up_box->show_all; gtkflush(); } ################################################ BUTTON_BOX ################################################ sub button_box_adv() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { interactive_mode_box(); }), 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-save'), clicked => sub { destroy_widget(); unless (check_pkg_needs()) { save_conf_file(); $previous_widget->(); } }), ), ); } sub button_box_restore_main() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box(); }), 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); interactive_mode_box() }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { destroy_widget(); interactive_mode_box() }), ), ), ); } sub button_box_file_restore() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); restore_box(); }), 1, new Gtk2::HBox(0, 1), ), ), ); } sub button_box_log_main() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(gtkpack_(new Gtk2::HButtonBox, 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { destroy_widget(); interactive_mode_box() }), ), ), ); } sub button_box_backup_end() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help() }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box() }), 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->() }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(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_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box(); }), 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-save'), clicked => sub { destroy_widget(); save_conf_file(); interactive_mode_box(); }), ), ); } sub button_box_restore_end() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box(); }), 1, new Gtk2::HBox(0, 1), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->(); }), 0, gtksignal_connect(Gtk2::Button->new(N("Restore")), clicked => sub { destroy_widget(); restore_backend(); }), ), ); } sub button_box_build_backup_end() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, new Gtk2::HBox(0, 5), 1, new Gtk2::HBox(0, 5), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { # destroy_widget(); interactive_mode_box(); }), ), ); } sub button_box_restore_pbs_end() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, new Gtk2::HBox(0, 5), 1, new Gtk2::HBox(0, 5), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-ok'), clicked => sub { destroy_widget(); interactive_mode_box(); }), ), ); } sub button_box_build_backup() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box(); }), 1, new Gtk2::HBox(0, 0), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->(); }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub { destroy_widget(); $next_widget->(); }), ), ); } sub button_box_restore() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help(); }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box(); }), 1, new Gtk2::HBox(0, 0), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { destroy_widget(); $previous_widget->(); }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub { destroy_widget(); $next_widget->(); }), ), ); } sub button_box_find_media { my ($mount_media) = @_; #- $central_widget is not known yet? $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { $central_widget = \$box2; adv_help(); }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { $central_widget = \$box2; interactive_mode_box(); }), 1, new Gtk2::HBox(0, 0), 0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-back'), clicked => sub { $central_widget = \$box2; interactive_mode_box(); }), 1, gtkset_sensitive(gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), clicked => sub { interactive_mode_box("restore"); }), $mount_media), ), ); } sub button_box_wizard() { $button_box_tmp->destroy; gtkpack($button_box, $button_box_tmp = gtkpack_(new Gtk2::HButtonBox, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help() }), 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-cancel'), clicked => sub { destroy_widget(); interactive_mode_box() }), 1, new Gtk2::HBox(0, 0), 0, gtksignal_connect(Gtk2::Button->new_from_stock($next_widget ? 'gtk-go-back' : 'gtk-ok'), clicked => sub { destroy_widget(); $previous_widget ? $previous_widget->() : $next_widget->(); }), if_($next_widget, 1, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-go-forward'), 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, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'), clicked => sub { adv_help() }), gtksignal_connect(Gtk2::Button->new_from_stock('gtk-close'), clicked => sub { ugtk2->exit(0) }), ), ); } ################################################ MESSAGES ################################################ sub dialog_one { destroy_widget(); my ($label) = @_; gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 0, gtkpack_(new Gtk2::HBox(0, 15), 0, new Gtk2::VBox(0, 5), 0, gtkcreate_img('warning'), 0, $label), 0, new Gtk2::VBox(0, 5), 1, new Gtk2::VBox(0, 5), ), ); button_box_restore_main(); $custom_help = "mail_pb"; $central_widget = \$box2; $up_box->show_all; } sub send_mail_pb() { dialog_one(N("Error during sendmail. Your report mail was not sent. Please configure sendmail")); } sub client_ftp_pb() { dialog_one(N("Error during sending file via FTP. Please correct your FTP configuration.")); } sub install_rpm { my ($previous_function) = @_; #- catch a crash when calling help #- this GUI control technique is kind of funky if ($previous_function eq '') { $previous_function = \&advanced_where; } my $box_what_user; gtkpack($advanced_box, $box_what_user = gtkpack_(new Gtk2::VBox(0, 15), 0, N("The following packages need to be installed:\n") . join(' ', @list_of_rpm_to_install), 0, new Gtk2::HSeparator, 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Install")), clicked => sub { system("/usr/sbin/urpmi --X @list_of_rpm_to_install"); destroy_widget(); $previous_widget->(); }), ), ); fonction_env(\$box_what_user, \&install_rpm, \&$previous_function, "what"); $up_box->show_all; } sub message_norestore_box() { $box2->destroy; gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack(new Gtk2::HBox(0, 15), new Gtk2::VBox(0, 5), gtkcreate_img('warning'), N("Please select data to restore..."), new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); button_box_restore_main(); $central_widget = \$box2; $up_box->show_all; } sub message_common_box { $box2->destroy; my ($label) = @_; gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack(new Gtk2::HBox(0, 15), new Gtk2::VBox(0, 5), gtkcreate_img('warning'), $label, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $previous_widget = \&wizard; $next_widget = \&wizard; $central_widget = \$box2; $up_box->show_all; } sub message_noselect_box() { message_common_box(N("Please select media for backup...")); $previous_widget = \&wizard_step2; $next_widget = \&wizard_step2; $central_widget = \$box2; $up_box->show_all; } sub message_noselect_what_box() { message_common_box(N("Please select data to backup...")); $previous_widget = \&wizard; $next_widget = \&wizard; $central_widget = \$box2; $up_box->show_all; } sub message_common_box_2 { my ($label, $restore_main) = @_; $box2->destroy; gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack(new Gtk2::HBox(0, 15), new Gtk2::VBox(0, 5), gtkcreate_img('warning'), N("%s", $label), new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); button_box_restore_main() if $restore_main; $central_widget = \$box2; $up_box->show_all; } sub message_noconf_box() { message_common_box_2(N("No configuration file found \nplease click Wizard or Advanced."), 1); } sub message_underdevel() { message_common_box_2(N("Under Devel ... please wait."), 1); } ################################################ 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 find_backup_to_put_on_cd() { @data_backuped = (); local $_; -d $save_path and my @list_backup = all($save_path); foreach (grep { /^backup_other/ } @list_backup) { $other_backuped = 1; chomp; my $tail = (split(' ', `du $save_path/$_`))[0]; s/^backup_other//gi; s/.tar.gz$//gi; s/.tar.bz2$//gi; my @user_date = split /_20/; my @user_date2 = split(/_/, $user_date[1]); my $to_put = " other_data, (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])"; push @data_backuped , $to_put; } foreach (grep { /_sys_/ } @list_backup) { $sys_backuped = 1; chomp; my $tail = (split(' ', `du $save_path/$_`))[0]; s/^backup_other//gi; s/.tar.gz$//gi; s/.tar.bz2$//gi; my @user_date = split /_20/; my @user_date2 = split(/_/, $user_date[1]); my $to_put = " system, (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])"; push @data_backuped , $to_put; } foreach (grep { /user_/ } @list_backup) { chomp; my $tail = (split(' ', `du $save_path/$_`))[0]; s/^backup_user_//gi; s/.tar.gz$//gi; s/.tar.bz2$//gi; my @user_date = split /_20/; my @user_date2 = split(/_/, $user_date[1]); my $to_put = " $user_date[0], (tail: $tail ko, date: 20$user_date2[0], hour: $user_date2[1])"; push @data_backuped , $to_put; } } sub build_backup_status() { $pbar = new Gtk2::ProgressBar; $pbar1 = new Gtk2::ProgressBar; $pbar2 = new Gtk2::ProgressBar; $pbar3 = new Gtk2::ProgressBar; $plabel = new Gtk2::Label(" "); $plabel1 = new Gtk2::Label(" "); $plabel2 = new Gtk2::Label(" "); $plabel3 = new Gtk2::Label(" "); $stext = new Gtk2::Label(""); button_box_build_backup_end(); my $table = Gtk2::Table->new(10, 2, 1); $table->set_row_spacings(5); $table->set_col_spacings(10); $table->attach_defaults(new Gtk2::Label(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(new Gtk2::Label(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(new Gtk2::Label(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(new Gtk2::Label(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(new Gtk2::VBox(0, 5), $table, $stext, ), ); $custom_help = "options"; $central_widget = \$tbox; $up_box->show_all; gtkflush(); } sub build_backup_ftp_status() { $pbar = new Gtk2::ProgressBar; $pbar3 = new Gtk2::ProgressBar; destroy_widget(); button_box_build_backup_end(); $pbar->set_fraction(0); $pbar3->set_fraction(0); gtkpack($advanced_box, $table = gtkpack_(new Gtk2::VBox(0, 15), 1, N("Sending files by FTP"), 1, new Gtk2::VBox(0, 15), 1, create_packtable ({ col_spacings => 10, row_spacings => 5 }, [N("Sending files...")], [""], [ $plabel = new Gtk2::Label(' ') ], [ $pbar ], [""], [N("Total Progress")], [ $plabel3 = new Gtk2::Label(' ') ], [$pbar3], ), 1, new Gtk2::VBox(0, 15), ), ); $custom_help = "options"; $central_widget = \$table; $up_box->show_all; gtkflush(); } sub build_backup_box_see_conf { my ($caller) = @_; my $box2; my $text = new Gtk2::TextView; system_state(); gtktext_insert($text, [ [ $system_state ] ]); button_box_restore_main(); gtkpack($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, gtkpack_(new Gtk2::VBox(0,10), 0, N("Drakbackup Configuration"), 1, create_scrolled_window($text), ), ), ); button_box_backup_end(); $custom_help = ""; $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_progress() { # build_backup_files(); } sub aff_total_tail() { my @toto; my $total = 0; push @toto, (split(",", $_))[1] foreach @list_to_build_on_cd; foreach (@toto) { s/\s+\(tail://gi; s/\s+//gi; s/ko//gi; $total += $_; } $label_tail->set("total tail: $total ko"); } sub build_backup_box() { destroy_widget(); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtksignal_connect(my $button_from_conf_file = Gtk2::Button->new, clicked => sub { destroy_widget(); build_backup_box_see_conf(); }), 0, new Gtk2::VBox(0, 5), 1, gtksignal_connect(my $button_see_conf = Gtk2::Button->new, clicked => sub { destroy_widget(); build_backup_box_see_conf(); }), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $button_from_conf_file->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-discdurwhat-40"), new Gtk2::Label(N("Backup Now from configuration file")), new Gtk2::HBox(0, 5) )); $button_see_conf->add(gtkpack(new Gtk2::HBox(0,10), gtkcreate_img("ic82-moreoption-40"), new Gtk2::Label(N("View Backup Configuration.")), new Gtk2::HBox(0, 5) )); button_box_restore_main(); fonction_env(\$box2, \&build_backup_box, \&interactive_mode_box, "options"); $up_box->show_all; } ################################################ INTERACTIVE ################################################ sub interactive_mode_box { my ($mode) = @_; if ($mode eq "restore") { $central_widget = \$box2; restore_box(); return 0; } destroy_widget(); gtkadd($advanced_box, $box2 = gtkpack_(new Gtk2::HBox(0, 15), 1, new Gtk2::VBox(0, 5), 1, gtkpack_(new Gtk2::VBox(0, 5), 1, new Gtk2::VBox(0, 5), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Wizard Configuration")), clicked => sub { destroy_widget(); read_conf_file(); wizard(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Advanced Configuration")), clicked => sub { button_box_adv(); destroy_widget(); advanced_box(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("View Configuration")), clicked => sub { destroy_widget(); build_backup_box_see_conf("interactive"); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("View Last Log")), clicked => sub { $results = cat_($log_file); button_box_log_main(); show_status(); }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Backup Now")), clicked => sub { if ($cfg_file_exist) { build_backup_box(); } else { message_noconf_box(); } }), 0, gtksignal_connect(Gtk2::Button->new_from_stock(N("Restore")), clicked => sub { destroy_widget(); restore_box(); }), 1, new Gtk2::VBox(0, 5), ), 1, new Gtk2::VBox(0, 5), ), ); $central_widget = \$box2; button_box_main(); $custom_help = "main"; $up_box->show_all; } sub interactive_mode() { $interactive = 1; $in = 'interactive'->vnew; my $box; my $winht = 400; $winht = 320 if $::isEmbedded; $my_win = ugtk2->new('drakbackup'); $window1 = $my_win->{window}; unless ($::isEmbedded) { $my_win->{rwindow}->set_position('center'); $my_win->{rwindow}->set_title(N("Drakbackup")); $window1->set_size_request(600, 500); } $my_win->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) }); read_conf_file(); gtkadd($window1, gtkpack(new Gtk2::VBox(0,0), gtkpack(gtkset_size_request($up_box = new Gtk2::VBox(0, 5), 540, $winht), $box = gtkpack_(new Gtk2::VBox(0, 3), if_(!$::isEmbedded, 0, gtkcreate_img("drakbackup.540x57")), 1, gtkpack_(new Gtk2::HBox(0, 3), 1, gtkpack_(new Gtk2::HBox(0, 15), 0, new Gtk2::HBox(0, 5), 1, $advanced_box = gtkpack_(new Gtk2::HBox(0, 15), ), 0, new Gtk2::HBox(0, 5), ), ), 0, new Gtk2::HSeparator, 0, $button_box = gtkpack(new Gtk2::VBox(0, 15), $button_box_tmp = gtkpack(new Gtk2::VBox(0, 0),), ), ), ), ), ); interactive_mode_box(); $custom_help = "main"; button_box_main(); $central_widget = \$box2; $window1->show_all; $window1->realize; $window1->show_all; $my_win->main; $my_win->exit(0); } ################################################ HELP & ABOUT ################################################ sub adv_help() { exec("drakhelp Drakxtools-Guide.html/drakbackup.html") unless fork(); } sub to_ok() { $sav_next_widget = $next_widget; $next_widget = undef; button_box_wizard(); } sub to_normal() { $next_widget = $sav_next_widget; } sub destroy_widget() { if ($central_widget ne '') { $$central_widget->destroy; $central_widget = ''; } }