#!/usr/bin/perl

# archive2iso - Takes a directory tree and randomizes the files in the tree to
#               stripe the files across several ISO files that can be archived
#               or burned off to a CD.
#
# By Kirk Waingrow @ July/2007
# 
# Version 1.0

use File::Find;
use CDiso;

$TMP="/usr/tmp";
$idx="$TMP/archive.idx";
$MKISOFS="/usr/local/bin/mkisofs.exe";

system("rm -f $idx");
system("rm -f $TMP/disk_*.lst");

#
# Randomization function
#
sub fisher_yates_shuffle {
    $rc=0;
    my $array = shift;
    my $i;
    for ($i = @$array; --$i; ) {
 	$rc++;
        my $j = int rand ($i+1);
        next if $i == $j;
        @$array[$i,$j] = @$array[$j,$i];
    }
}

#
# Enter Initial Data
#
print "\nEnter Directory: ";
chomp($dir = <STDIN>);


#
# Find size of all files in dirs
#
$dirsize=0;
find (sub {$dirsize += -s ;}, $dir); 
print "\n";

#
# Build an index of all the files to archive
#
$tc=0;
open(IDX, "> $idx");
open (FND, "find $dir -type f| " );
while (<FND>)
{
  print IDX "$_";
  $tc++;
}
close(FND); close(IDX);


print "- Files to archive     = $tc\n";


$megsize=int($dirsize/1000000);
print "- Estimated total Size = $megsize MB\n";

print "\nEnter Max megabyte Size for the ISO/CD/DVD (1-4700): ";
chomp($msize = <STDIN>);

$msize=$msize*1000000;
$tdisks=int($dirsize/$msize)+1;
print "\n- Estimated Num Disks  = $tdisks\n";



#print "\nHit [ENTER] to continue...";
#chomp($dummy = <STDIN>); 


#
# Build Array of files
#
@array="";
open(IN, "$idx"); chomp; @array=<IN>; close(IN);
#
print "\n";
$c=0;

$ans="n";
while ( "$ans" eq "n" )
{
  # Randomize Array
  #
  fisher_yates_shuffle( \@array );    # permutes @array in place
  
  
  #
  # Write Disk Files
  #
  $fs=0; $disk=0; $disk++; $cnt=0;
  open (DSK, "> $TMP/disk_${disk}.lst");
  for $i (@array)
  { 
      chomp($i);
      my $filesize = -s "$i";
      $TEMP_fs=$fs;
      $fs=$filesize+$fs;
      if ( $fs < $msize ) 
      { 
            print DSK "$i\n";
            $cnt++;
      }
      else
      {
	    $TEMP_fs=($TEMP_fs/1000000);
	    $TEMP_fs= sprintf("%.1f", $TEMP_fs);
            print "$TMP/disk_${disk}.iso - $cnt files at ${TEMP_fs} MB\n";
	    #print "$fs - $TEMP_fs = msize=$msize - $cnt\n";
	    $fs=$filesize; 
	    close(DSK);
	    $disk++; $cnt=1;
            close(DSK);
	    open (DSK, "> $TMP/disk_${disk}.lst");
            print DSK "$i\n";
      }
      #print "$fs - $i\n";
  }
  close(DSK);
  $TEMP_fs=($TEMP_fs/1000000);
  $TEMP_fs= sprintf("%.1f", $TEMP_fs);
  print "$TMP/disk_${disk}.iso - $cnt files at ${TEMP_fs} MB\n";

  #print "$disk\n";
  # Check for balance number
  print "\nIs the above disk configuration okay?\n";
  #system("wc -l $TMP/disk_*.lst");
  print "\n Answer y or n: ";
  chomp($ans = <STDIN>);
  print "\n";
}



print "ROOT Dir = $dir\n";
print "\n\n- Building ISO images\n";
for ($d = 1; $d <= $disk; $d++) 
{
      @files="";
      open(IN, "$TMP/disk_${d}.lst" ); 
      while  (<IN>)
      {
 	chomp;
 	push(@files, "$_");
      }
      close(IN);

	my $iso = new CDiso("$dir");

	$iso->mkisofsPath('/usr/local/bin/mkisofs.exe');

	$iso->addFiles(@files);
	$iso->printFiles();
	print "making iso...";
	$iso->makeISO("$TMP/disk_${d}.iso");
	#print "verison = " . $iso->version() . "\n";
}


exit;

=head1 NAME

B<archive2iso> - Takes a directory tree and randomizes the files in the tree to stripe the files across several ISO files that can be archived or burned off to a CD's.

=head1 SYNOPSIS use archive2iso;

Type: ./archive2iso

=head1 DESCRIPTION

The intended use is to stripe files across multiple CD/DVD randomly so if one disc is damaged
all the images that were in the same directory will not be lost since files are spread across
multiple disks. The actual files themselves are not split, all files remain in their
original state.

An example of an intended use is where you have a series of valuable vacation photos that
could span 6 CD for all your photos in your collection. archive2iso would spread them out
across the 6 CD's so if 1 of the 6 cd's is lost, you only loose 1/6th of your images.
Which is better than loosing all of them!

=head1 PREREQUISITE

The following perl modules are required:
	File::Find - CPAN
	CDiso.pm - 

=head1 METHOD

=head2 Example()

Enter Directory: /absolute/path   <-- Enther the absolute path of the tree you wish to archive.

- Files to archive     = 8489
- Estimated total Size = 1135 MB

Enter Max megabyte Size for ISO/CD/DVD (1-4700): 650   <- Enter size of ISO to fit on a CD/DVD).

- Estimated Num Disks  = 2

/usr/tmp/disk_1.iso - 4609 files at 650.0 MB
/usr/tmp/disk_2.iso - 3880 files at 485.1 MB

Is the above disk configuration okay?

 Answer y or n: y

The ISO images are created.... 


=head1 AUTHOR 

Kirk Waingrow C<< <wkrik at yahoo dot com> >>

=head1 BUGS

Please report any bugs or feature requests to C<wkrik AT yahoo DOT com>.

=head1 TODO

Let me know...

If you want something added, email me a request at (jsnby AT hotmail DOT com).

=head1 COPYRIGHT & LICENSE

Copyright (C) 2007 Jason Hancock (wkrik AT yahoo DOT com)
http://www.ugu.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

=cut
