remove directories also
[BackupPC.git] / bin / BackupPC_burnArchiveCLI
index 4bf8489..d149834 100755 (executable)
@@ -1,8 +1,7 @@
 #!/usr/bin/perl
 
 use strict;
-#use lib "__INSTALLDIR__/lib";
-use lib "/data/backuppc-agi/lib";
+use lib "__INSTALLDIR__/lib";
 
 use DBI;
 use BackupPC::Lib;
@@ -16,6 +15,8 @@ use File::Path;
 use Data::Dumper;
 
 my $debug = 0;
+# set this to 1 to prompt for DVD removal for each selected item.
+my $prompt_for_delete = shift @ARGV;
 $|=1;
 
 # don't check for user
@@ -110,6 +111,8 @@ sub dumpArchive2XML($$$)
                        AND hosts.id=backups.hostid
                        AND shares.id=backups.shareid
                        AND archive_backup.archive_id = ?
+               ORDER BY
+                       hosts.name, shares.name, backups.num
        };
 
        my $sth = $dbh->prepare("SELECT dvd_nr, total_size, note, username, date,id FROM archive WHERE dvd_nr=?");
@@ -163,7 +166,7 @@ sub dumpArchive2XML($$$)
                        $writer->endTag("file");
                }
                $writer->endTag("backup");
-       }       
+       }
                         
        $writer->endTag("archive");
        $writer->end(); 
@@ -254,6 +257,44 @@ sub add_symlink($$) {
        symlink $from, $to || skip("can't symlink $from to $to: $!");
 }
 
+sub delete_dvd($) {
+       my $dvd_nr = shift || return;
+
+       print "Do you want to delete DVD #$dvd_nr now? [NO/yes]: ";
+       my $ok = <STDIN>;
+       chomp($ok);
+       if (lc($ok) eq 'yes') {
+               print "Deleting DVD #$dvd_nr from database...\n";
+
+               $dbh->begin_work;
+
+               my $sth_delete_dvd = $dbh->prepare( qq{
+                       delete from archive where dvd_nr = ?
+               } );
+               $sth_delete_dvd->execute( $dvd_nr );
+               $dbh->do( qq{
+                       select setval('dvd_nr', (select max(dvd_nr) from archive), true)
+               } );
+
+               # remove files for this DVD
+               map {
+                       if (-d $_) {
+                               print "\tremoving dir $_\n";
+                               rmtree($_) || die "can't rmtree $_: $!";
+                       } else {
+                               print "\tremoving $_\n";
+                               unlink($_) || die "can't rm $_: $!";
+                       }
+               } glob ( "/$iso_dir/$dvd_nr.*" );
+
+               $dbh->commit;
+
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 my $sth_archive_backup_parts = $dbh->prepare( qq{
        select
                archive_backup.backup_id,
@@ -276,6 +317,15 @@ my $sth_archive_backup_parts = $dbh->prepare( qq{
        order by archive_backup.backup_id, backup_parts.part_nr
 });
 
+my $sth_archive_backup_check = $dbh->prepare( qq{
+               SELECT
+                       count(backups.id)
+               FROM backups
+               JOIN archive_backup on archive_backup.backup_id = backups.id
+               JOIN archive on archive_id = archive.id
+               WHERE dvd_nr = ?
+});
+
 my $sth_archive_burned = $dbh->prepare( qq{
        insert into archive_burned
                (archive_id, iso_size, part, copy)
@@ -296,6 +346,27 @@ foreach my $arc (@archives_to_burn) {
 
        $sth_archive_backup_parts->execute($dvd_nr);
 
+       $sth_archive_backup_check->execute($dvd_nr);
+
+       my ($parts_nr, $check_nr) = ($sth_archive_backup_parts->rows, $sth_archive_backup_check->fetchrow_array);
+
+       if ($parts_nr != $check_nr) {
+               warn "ERROR: DVD #$dvd_nr is still not inconsistent state. Some backup parts are ",
+                       ($parts_nr < $check_nr) ? "missing ($parts_nr < $check_nr)" : "extra ($parts_nr > $check_nr)",
+                       " you should re-create this DVD after BackupPC_incPartsUpdate finish\n";
+               delete_dvd( $dvd_nr );
+               next;
+       }
+
+       if ($sth_archive_backup_parts->rows == 0) {
+               warn "ERROR: no backup parts found for $dvd_nr. You should re-create that DVD.\n";
+               next if delete_dvd( $dvd_nr );
+       }
+
+       if ($prompt_for_delete) {
+               next if delete_dvd( $dvd_nr );
+       }
+
        my @volumes;
        my $v;  # emtpy volume
        my $v_size = 0;
@@ -318,17 +389,19 @@ foreach my $arc (@archives_to_burn) {
        }
        push @volumes, $v if ($v);
 
+       #warn "# volumes: ",Dumper(\@volumes),"\n";
+
        my $volumes = $#volumes + 1;
        my $volume_nr = 1;
 
        foreach my $v (@volumes) {
 
-               print Dumper($v);
+               #print Dumper($v);
 
                my $iso_size = 0;
                my $disk_name = $dvd_nr;
                # suffix added to multi-volume archives
-               my $volume_suffix = $dvd_nr;
+               my $volume_suffix = '';
 
                if ($volumes > 1) {
                        $volume_suffix = '_' . $volume_nr;
@@ -369,8 +442,8 @@ foreach my $arc (@archives_to_burn) {
                                my $rel_path = $tar_file;
 
                                if (-d "$tar_dir/$rel_path") {
-                                       $rel_path .= '/' . $p->{part_nr};
                                        mkpath("$stage/$rel_path") unless (-d "$stage/$rel_path");
+                                       $rel_path .= '/' . $p->{part_nr};
                                }
                                $rel_path .= '.tar.gz';
 
@@ -379,7 +452,8 @@ foreach my $arc (@archives_to_burn) {
                                add_symlink("$tar_dir/$rel_path", "$stage/$rel_path");
 
                                my $md5sum = $p->{md5} || die "no md5 in part ", Dumper($p);
-                               print $md5 "$md5sum\s\s$rel_path\n" || die "can't write md5sum: $!";
+                               chomp($md5sum);
+                               print $md5 "$md5sum  $rel_path\n" || die "can't write md5sum: $!";
 
                                $parts_on_this_volume++;
                        }
@@ -409,8 +483,7 @@ foreach my $arc (@archives_to_burn) {
 
                        print "Created $iso_file [$iso_size bytes] in ", fmt_time(time() - $t), "\n";
 
-                       # FIXME
-                       #rmtree($stage) || warn "can't remove stage directory $stage: $!";
+                       rmtree($stage) || warn "can't remove stage directory $stage: $!";
 
                } else {
                        print "ISO $iso_file allready exists\n";
@@ -454,6 +527,8 @@ print "Recoding finished, exiting...\n";
 $sth->finish;
 $sth_archive_backup_parts->finish;
 $sth_archive_burned->finish;
+$sth_archive_backup_check->finish;
+$sth_archive_burned->finish;
 
 $dbh->disconnect;