#!/usr/bin/perl #H# This script calculates how much space would be left on a disc and it generates #H# PAR2 blocks to fill whatever space is left. #H# Then it makes an md5 file of everything including the par2 files. #H# It gets the basename of the par2 and md5 files from the current directory name. #H# The only parameter is what type of disc is to be used. -cd, -dvd, -dvd2, or -dds3 #H# Note that unlike the -cd and -dvd params the -dds3 param is intended for data #H# sets that span multiple tapes. Par2 blocks will be generated to fill only the #H# last tape in the set. #H# #H# Requirements: #H# Standard UNIX tools #H# cfv (http://cfv.sourceforge.net/) (can be replaced with md5sum -b but slower) #H# par2cmdline (http://parchive.sourceforge.net/) # print out help info if requested if ($ARGV[0] eq "-h" || $ARGV[0] eq "--help" || $ARGV[0] eq "help" || $ARGV[0] eq "") { open (SELF, $0); while () { if ($_ =~ /^#H# /) { $_ =~ s/^#H# //; print $_; } } exit; } # This is how many MB of RAM par2 will use while calculating par2 blocks. Note that # this is how much data it will hold in RAM between writes and has nothing to do with # the actual calculations. That means that this number can't make the calculations # go faster but it can make the disk cache more usefull. If you set it too small you # will be writing all the time and if you set it too large you will not have any # read cache and you may even end up swapping. I use 64MB even though I have 1GB of # RAM because that seems to make the best use of the cache. $Par2RAM=32; # Determine the capacity of the media and the charactaristics of the par2 blocks based # on the command line params. # There are some options that can be tweaked here to match user prefs. The main thing # is the par2 block size. I use 100KB for CDR media and 10MB for DVDR media. I find # that to be a good balance between making plenty of blocks and a reasonably fast # par2 generation/recovery. The smaller you make the blocks the more redundancy you # have but the longer it takes to compute. Note that if you change the block size # you should also change the overhead values to match proportionally. if ($ARGV[0] eq "-cd") { $Disc="CDR"; $Par2BlockSize=100*1024; # Note that 10 will fit on a CDR but requires overburning. $Par2Overhead=16; $DiscCapacity=703*1024*1024; $BlocksPerParFile=9999999; } elsif ($ARGV[0] eq "-bigcd") { $Disc="CDR"; $Par2BlockSize=1024*1024; # Note that 10 will fit on a CDR but requires overburning. $Par2Overhead=1; $DiscCapacity=703*1024*1024; $BlocksPerParFile=9999999; } elsif ($ARGV[0] eq "-dvd") { $Disc="DVDR"; $Par2BlockSize=10*1024*1024; $Par2Overhead=.9; # Note that DVD-R is 4489MB while DVD+R is 4482MB $DiscCapacity=4482*1024*1024; $BlocksPerParFile=100; } elsif ($ARGV[0] eq "-dvd2") { $Disc="DVD2"; $Par2BlockSize=10*1024*1024; $Par2Overhead=.9; $DiscCapacity=8540000000; $BlocksPerParFile=100; } elsif ($ARGV[0] eq "-dds3") { $Disc="DDS3"; $Par2BlockSize=100*1024*1024; $Par2Overhead=1; $DiscCapacity=12*1024*1024*1024; $BlocksPerParFile=10; } else { die "Must specify -cd, -dvd, -dvd2, or -dds3\n"; } # You shouldn't need to tweak anything else here unless you are changing my basic # design concept. # figure out what to call the par2 and md5 files... $Dir=`pwd`; chomp $Dir; @Paths=split (/\//,$Dir); foreach $Path (@Paths) { $FileBase=$Path; } $ParFile="$FileBase" . ".par2"; $MD5File="$FileBase" . ".md5"; # find out how much space is used in the current dir. $FileSize=`du -sc * | tail -n 1 | awk '{print $1}'`; chomp $FileSize; $FileSize=$FileSize*1024; # If doing a tape set figure out how many tapes are needed... if ($Disc eq "DDS3") { $RawNumTapes=($FileSize/$DiscCapacity)+1; ($NumTapes,$Junk)=split(/\./,$RawNumTapes,2); $DiscCapacity=$DiscCapacity*$NumTapes; print "This is going to take $NumTapes $Disc tapes.\n"; } # calculate the number of par2 blocks to be generated $ParRealSize=(($DiscCapacity-$FileSize)/$Par2BlockSize)-$Par2Overhead; # must make a whole number of blocks so drop off the decimal. ($Par2Blocks,$Junk)=split (/\./,$ParRealSize,2); # Figure out how many par2 files are needed... if ($Par2Blocks <= $BlocksPerParFile) { $Par2Files=1; } else { $Par2FilesRaw=($Par2Blocks/$BlocksPerParFile)+1; ($Par2Files,$Junk)=split (/\./,$Par2FilesRaw,2); } # build and execute the par2 command line. $ParParams=qq[-s$Par2BlockSize -m$Par2RAM -u -n$Par2Files -c$Par2Blocks "${ParFile}" *]; print "par2create $ParParams...\n"; system "par2create $ParParams"; # make md5sums of all the files... print "Calculating md5sums for $MD5File...\n"; system qq[cfv -C -f"$MD5File" *];