#!/usr/local/bin/perl -w $| = 1; use strict; use DBI; use lib "__INSTALLDIR__/lib"; use BackupPC::Lib; use BackupPC::View; use Data::Dumper; use Getopt::Std; use constant BPC_FTYPE_DIR => 5; my $hosts; my $bpc = BackupPC::Lib->new || die; my %Conf = $bpc->Conf(); my $TopDir = $bpc->TopDir(); my @beenThere = (); print Dumper(\%Conf); my $dbh = DBI->connect("dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}", "", "", { RaiseError => 1, AutoCommit => 0 }); my %opt; if ( !getopts("cdu", \%opt ) ) { print STDERR <do( q{ create table hosts ( ID INTEGER PRIMARY KEY, name VARCHAR(30) NOT NULL, IP VARCHAR(20) NOT NULL ); } ); $dbh->do( q{ create table shares ( ID INTEGER PRIMARY KEY, hostID INTEGER NOT NULL, name VARCHAR(30) NOT NULL, share VARCHAR(200) NOT NULL, localpath VARCHAR(200) ); } ); $dbh->do( q{ create table backups ( hostID INTEGER NOT NULL, num INTEGER NOT NULL, date DATE, type CHAR(1), PRIMARY KEY(hostID, num) ); } ); $dbh->do( q{ create table dvds ( ID INTEGER PRIMARY KEY, num INTEGER NOT NULL, name VARCHAR(255) NOT NULL, mjesto VARCHAR(255) ); } ); $dbh->do( q{ create table files ( ID INTEGER NOT NULL PRIMARY KEY, shareID INTEGER NOT NULL, backupNum INTEGER NOT NULL, name VARCHAR(255) NOT NULL, path VARCHAR(255) NOT NULL, fullpath VARCHAR(255) NOT NULL, date TIMESTAMP NOT NULL, type INTEGER NOT NULL, size INTEGER NOT NULL, dvdid INTEGER ); } ); print "done\n"; } if ($opt{d}) { print("deleting db first...\n"); $dbh->do( q{ DELETE FROM hosts; } ); $dbh->do( q{ DELETE FROM shares; } ); $dbh->do( q{ DELETE FROM files;} ); $dbh->do( q{ DELETE FROM dvds;} ); $dbh->do( q{ DELETE FROM backups; } ); } #################################INSERT VALUES############################# # get hosts $hosts = $bpc->HostInfoRead("localhost"); my $host_key; my $hostID; my $shareID; foreach $host_key (keys %{$hosts}) { my $hostname = $hosts->{$host_key}->{'host'}; my $backups; my $sql; $sql = q{ SELECT ID FROM hosts WHERE name=? }; my $st = $dbh->prepare($sql); $st->bind_param(1,$hosts->{$host_key}->{'host'}); $st->execute(); my $tmp = $st->fetchrow_hashref(); if ($tmp->{'ID'} ne "") { $hostID = $tmp->{'ID'}; } else { $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}. $hosts->{$host_key}->{'host'}."\", \"". $hosts->{$host_key}->{'ip'}."\");"; $dbh->do($sql); $hostID = $dbh->func('last_insert_rowid'); } $st->finish(); print("processing host ".$hosts->{$host_key}->{'host'}.":\n"); # get backups for a host my @backups = $bpc->BackupInfoRead($hostname); foreach my $backup (@backups) { my $backupNum = $backup->{'num'}; my @backupShares = (); if ($opt{u}) { my $sql = q{ SELECT COUNT(*) AS broj FROM backups WHERE hostID=? AND num=? }; my $st = $dbh->prepare($sql); $st->bind_param(1,$hostID); $st->bind_param(2,$backupNum); $st->execute(); my $tmp = $st->fetchrow_hashref(); $st->finish(); if ($tmp->{'broj'} > 0) { next; } } print "\tprocessing backup no. $backupNum..."; my $sql = q{ INSERT INTO backups (hostID, num, date, type) VALUES (}.$hostID.",". $backupNum.q{, }.$backup->{'endTime'}.",\"". $backup->{'type'}.q{"); }; $dbh->do($sql); my $files = BackupPC::View->new($bpc, $hostname, \@backups); @backupShares = $files->shareList($backupNum); foreach my $share (@backupShares) { my @flattenedFiles = (); clearBeenThereCache(); print "\n\t\tprocessing share ".$share."..."; $shareID = getShareID($share, $hostID, $hostname); @flattenedFiles = recurseDir($bpc, $hostname, \@backups, $backupNum, $share, ""); print "done\n"; print "\t\tinserting data into db..."; foreach my $file (@flattenedFiles) { $dbh->do("INSERT INTO files(ID, shareID, backupNum, name, path, fullpath, date, type, size) VALUES " ."( NULL, $shareID, " .$backupNum.", \"" .$file->{'fileName'}."\", \"" .$file->{'relPath'}. "\", \"" .$file->{'fullPath'}."\", " .$file->{'mtime'}.", " .$file->{'type'}.", " .$file->{'size'}.")" ); } print "done\n"; } } print "done.\n"; } $dbh->commit(); $dbh->disconnect(); sub haveBeenThere { my ($where) = @_; foreach my $st (@beenThere) { if ($where eq $st) { return 1; } } push(@beenThere, $where); return 0; } sub clearBeenThereCache { @beenThere = (); } sub getShareID() { my ($share, $hostID, $hostname) = @_; my $tmp; my $st = $dbh -> prepare(" SELECT shares.ID AS ID FROM shares WHERE hostID=? AND name=?"); $st -> execute($hostID,$share); my $tmp = $st->fetchrow_hashref(); $st->finish(); if ($tmp) { return $tmp->{'ID'}; } my $sql = q{ INSERT INTO shares(ID,hostID,name,share,localpath) VALUES (NULL,}. "$hostID,\"$share\",\"//$hostname$share\",NULL);"; $dbh->do($sql); return $dbh->func('last_insert_rowid'); } #################################################### # recursing through filesystem structure and # # and returning flattened files list # #################################################### sub recurseDir { my ($bpc, $hostname, $backups, $backupNo, $share, $dir) = @_; my @ret = (); my $files = BackupPC::View->new($bpc, $hostname, $backups); my $filesInBackup = $files->dirAttrib($backupNo, $share, $dir); my $file_key = ""; # first, add all the entries in current directory foreach $file_key (keys %{$filesInBackup}) { push(@ret, { 'fileName' => $file_key, 'relPath' => $filesInBackup->{$file_key}->{'relPath'}, 'fullPath' => $filesInBackup->{$file_key}->{'fullPath'}, 'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'}, 'size' => $filesInBackup->{$file_key}->{'size'}, 'mtime' => $filesInBackup->{$file_key}->{'mtime'}, 'type' => $filesInBackup->{$file_key}->{'type'} }); } # then, recurse thru subfolders foreach my $fold (@ret) { if ($fold->{'type'} == BPC_FTYPE_DIR && haveBeenThere($fold->{'relPath'}) != 1 ) { push(@ret, recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'}) ); } } return @ret; }