#!/usr/bin/perl -w
#
# mediatool -- Tool for generating disk images, CD's, etc.
# 
# Copyright (C) 2001, Michael Jennings
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies of the Software, its documentation and marketing & publicity
# materials, and acknowledgment shall be given in the documentation, materials
# and software packages that this Software was used.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# $Id: mediatool,v 1.11 2004/06/04 17:16:40 mej Exp $
#

# Include the Perl Modules we need
require POSIX;
require Getopt::Long;
use Mezzanine::Util;

# Print usage information
sub
print_usage_info
{
    print "\n";
    $leader = "$progname $version Usage Information";
    $underbar = $leader;
    $underbar =~ s/./-/g;
    print "$leader\n$underbar\n";
    print "\n";
    print "  Syntax:   mediatool [ options ]\n";
    print "\n";
    print "    -h --help                        Show this usage information\n";
    print "    -d --debug                       Turn on debugging\n";
    print "    -v --version                     Show version and copyright\n";
    print "    -i --iso <filename>              Create an ISO file by this name\n";
    print "    -D --dir --directory <dir>       Specify the source directory\n";
    print "    -t --tar --tarball <tarball>     Create a tarball by this name\n";
    print "    -x --exclude --ignore <file>     Exclude a file/wildcard\n";
    print "    -c --cmd --command <command>     Specify an alternative command\n";
    print "       --boot <image>                Specify a boot image (for an ISO)\n";
    print "\n";
    exit(MEZZANINE_SUCCESS);
}

# Create a tarball from a directory
sub
create_tarball
{
    my ($tarball, $imagedir) = @_;
    my ($line, $cmd, $prog, $cwd, $f);
    local *CMD;

    chomp($cwd = `pwd`);
    chdir($imagedir);
    if ($tarball !~ /^\//) {
        $tarball = "$cwd/$tarball";
    }
    if ($command) {
        $cmd = $command . " $tarball";
    } else {
        $cmd = "tar --numeric-owner";
        foreach my $f (@excludes) {
            $cmd .= " --exclude='$f'";
        }
        if ($tarball =~ /\.(tar\.|t)(gz|Z)$/) {
            $cmd .= " --use-compress-program=gzip";
        } elsif ($tarball =~ /\.(tar\.|t)\.bz2?$/) {
            $cmd .= " --use-compress-program=bzip2";
        }
        $cmd .= " -Pcf $tarball .";
    }

    open(CMD, "$cmd 2>&1 |") || &fatal_error("Unable to execute \"$cmd\" -- $!\n");
    print "Creating tarball $tarball from $imagedir....\n";
    dprint "\nExecuting:  $cmd\n";
    while (<CMD>) {
        chomp($line = $_);
        if ($line =~ /^tar:/) {
            eprint "$line\n";
        }
    }
    close(CMD);
    chdir($cwd);
    if ($?) {
        &fatal_error("Creation of archive file failed.\n");
    }
}

# Create an ISO file from a directory
sub
create_iso
{
    my ($iso, $imagedir) = @_;
    my ($cmd, $ignore, $bootimg, $line, $err);
    local *MKISOFS;

    $ignore = "-m CVS -m RCS -m BitKeeper -m SCCS -m .cvsignore -m '.mezz.*'";
    if ($isolinux_dir) {
        $bootimg = "-b $isolinux_dir/isolinux.bin -c $isolinux_dir/boot.cat";
        $cmd = "mkisofs -o $iso $ignore $bootimg -no-emul-boot -boot-load-size 4 -boot-info-table -l -T -r -R -J -v $imagedir";
    } else {
        $bootimg = ($boot_image ? "-b $boot_image -c boot.cat" : "");
        $cmd = "mkisofs -o $iso $ignore $bootimg -T -r -R -J -v $imagedir";
    }
    print "Creating ISO image $iso from $imagedir....\n";
    if (!open(MKISOFS, "$cmd </dev/null 2>&1 |")) {
        &fatal_error("Execution of \"$cmd\" failed -- $!\n");
    }
    $err = 0;
    while (<MKISOFS>) {
        chomp($line = $_);
        if (&debug_get()) {
            dprint "$line\n";
        } elsif ($line =~ /^\s*Size of boot image is \d+ sectors -> Emulating a (.*) floppy$/) {
            print "ISO will contain $1 boot floppy image.\n";
        } elsif ($line =~ /^(.*) done, estimate finish/) {
            print "\r$1 complete.";
        } elsif ($line =~ /^\d+ extents written \((.*)\)$/) {
            print "\rISO creation complete, total size $1.\n";
        }
    }
    close(MKISOFS);
    if ($? != 0 && $err == 0) {
        dprint "\"$cmd\" returned $?\n";
        &fatal_error("mkisofs failed [$line]\n");
    }
}

# main() here is basically the same as main() in C
sub
main
{
    # Set up the basic variables
    $progname = "mediatool";
    $version = "1.0";
    &print_usage_info() if (!scalar(@ARGV));
    umask 022;

    # See the Getopt::Long man page for details on the syntax of this line
    @valid_opts = ("h|help", "v|version", "d|debug", "i|iso=s", "I|isolinux:s", "t|tar|tarball=s",
                   "x|exclude|ignore=s@", "boot=s", "c|cmd|command=s", "D|dir|directory=s@");
    Getopt::Long::Configure("no_getopt_compat", "bundling", "no_ignore_case");
    Getopt::Long::GetOptions(@valid_opts);

    # Post-parse the options stuff
    select STDOUT; $| = 1;
    if ($opt_v) {
        # Do not edit this variable.  It is updated automatically by CVS when you commit
        my $rcs_info = 'CVS Revision $Revision: 1.11 $ created on $Date: 2004/06/04 17:16:40 $ by $Author: mej $ ';

        $rcs_info =~ s/\$\s*Revision: (\S+) \$/$1/;
        $rcs_info =~ s/\$\s*Date: (\S+) (\S+) \$/$1 at $2/;
        $rcs_info =~ s/\$\s*Author: (\S+) \$ /$1/;
        print "\n";
	print "$progname $version by Michael Jennings <mej\@eterm.org>\n";
        print "Copyright (c) 2001, Michael Jennings\n";
        print "  ($rcs_info)\n";
        print "\n";
	return MEZZANINE_SUCCESS;
    } elsif ($opt_h) {
	&print_usage_info();   # Never returns
    }

    &debug_set($opt_d);
    if (scalar(@opt_D)) {
        @dirs = @opt_D;
    } else {
        &fatal_error("No source directories specified.\n");
    }
    $iso = ($opt_i ? $opt_i : 0);
    $tarball = ($opt_t ? $opt_t : 0);
    @excludes = (scalar(@opt_x) ? @opt_x : (".mezz.*", "*.mezz", "CVS", "RCS", "SCCS", "BitKeeper", ".cvsignore"));
    $boot_image = ($opt_boot ? $opt_boot : 0);
    $command = ($opt_c ? $opt_c : 0);
    if (defined($opt_I)) {
        if ($opt_I) {
            $isolinux_dir = $opt_I;
        } else {
            $isolinux_dir = "boot";
        }
    }

    # Signal handling
    $SIG{HUP} = 'IGNORE';
    $SIG{INT} = \&handle_signal;
    $SIG{TERM} = \&handle_signal;
    $SIG{QUIT} = \&handle_fatal_signal;
    $SIG{ILL} = \&handle_fatal_signal;
    $SIG{ABRT} = \&handle_fatal_signal;
    $SIG{FPE} = \&handle_fatal_signal;
    $SIG{SEGV} = \&handle_fatal_signal;
    $SIG{BUS} = \&handle_fatal_signal;
    $SIG{TSTP} = \&handle_fatal_signal;
    $SIG{TTIN} = \&handle_fatal_signal;
    $SIG{TTOU} = \&handle_fatal_signal;

    if ($iso) {
        &create_iso($iso, $dirs[0]);
    }
    if ($tarball) {
        &create_tarball($tarball, $dirs[0]);
    }

    return MEZZANINE_SUCCESS;
}

exit &main();
