#!/usr/bin/perl -w

#
# "SystemImager" - Copyright (C) 1999-2001 Brian Elliott Finley <brian@systemimager.org>
#
#   Others who have contributed to this code (in alphabetical order):
#
# This file is: mvimage
#

# set some variables
$version_number="2.0.1";
$program_name="mvimage";
$get_help = "         Try \"$program_name -help\" for more options.";

# declare modules
use lib "/usr/local/lib/systemimager/perl";
use lib "/usr/lib/systemimager/perl";
use SystemImager::Server;
use SystemImager::Common;
use Getopt::Long;
use File::Copy;
use File::Path;
use AppConfig;

### BEGIN parse the config file ###

my $config = AppConfig->new(
			    'autoinstall_script_dir' => { ARGCOUNT => 1 },
			    'autoinstall_boot_dir' => { ARGCOUNT => 1 },
			    'default_imagedir' => { ARGCOUNT => 1 },
			    'rsyncd_conf' => { ARGCOUNT => 1 },
			    'config_dir' => { ARGCOUNT => 1 },
			    );
$config->file('/etc/systemimager/systemimager.conf');

my $autoinstall_script_dir = $config->autoinstall_script_dir();
my $rsyncd_conf = $config->rsyncd_conf();

if (!$autoinstall_script_dir) {
    die "AUTOINSTALL_SCRIPT_DIR not defined in the config file.";
}
if (!$rsyncd_conf) { die "RSYNCD_CONF not defined in the config file."; }
### END parse the config file ###

### BEGIN functions ###
sub trim {
  my @out = @_;
  for (@out) {
    s/^\s+//;
    s/\s+$//;
  }
  return wantarray ? @out : $out[0];
}

### END functions ###

# set version information
$version_info = <<"EOF";
$program_name (part of SystemImager) version $version_number

Copyright (C) 1999-2001 Brian Elliott Finley <brian\@systemimager.org>
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
EOF

# set help information
$help_info = $version_info . <<"EOF";

Usage: $program_name [OPTION]... SOURCE_IMAGE DESTINATION_IMAGE

Options: (options can be presented in any order)

 -help                    Display this output.

 -version                 Display version and copyright information.

 -verbose                 Explain what is being done.

 -force                   Don\'t ask for confirmation before 
                          overwriting the destination image or master
			  autoinstall script (if they exist).

 -directory PATH          The full path and directory name where you want
                          this image to be stored.  The directory bearing
                          the image name itself will be placed inside the
                          directory specified here.


Download, report bugs, and make suggestions at:
http://systemimager.org/
EOF

# interpret command line options
GetOptions( 
  "help" => \$help,
  "version" => \$version,
  "directory=s" => \$destination_path,
  "force" => \$force,
  "verbose" => \$verbose
) or die qq($help_info);

# if requested, print help information
if($help) {
  print qq($help_info);
  exit 0;
}

# if requested, print version and copyright information
if($version) {
  print qq($version_info);
  exit 0;
}

# Take the arguments left after Getopt::Long parses it's stuff out 
# as the source and destination image names.
$source_image=$ARGV[0];
$destination_image=$ARGV[1];

unless(($source_image) and ($destination_image)) {
  die "\n$program_name: Must specify both SOURCE_IMAGE and DESTINATION_IMAGE.\n$get_help\n\n";
}

# be sure program is run by root
SystemImager::Common->check_if_root();

# get full path to image from $rsyncd_conf
$source_path=SystemImager::Server->get_full_path_to_image_from_rsyncd_conf( $rsyncd_conf, $source_image );

unless($source_path) { 
  print "FATAL: Can't get path to image $source_image from $rsyncd_conf!\n";
  die   "       Nothing has been done.\n";
}

unless($destination_path) { $destination_path = $source_path; }

# remove any trailing slash
$destination_path =~ s/\/$//;

$source="$source_path/$source_image";
$destination="$destination_path/$destination_image";

# check for existence of destination path
$file=$destination_path;
unless(-e $file) {
  if($force) {
    mkpath($file, 0, 0750) or die "FATAL: Can't create $file!\n";
  } else {
    die "FATAL: Destination path \"$file\" doesn't exist!\n";
  }
}

# check for existence of destination image
$file=$destination;
if(-e $file) {
  if($force) {
    rmtree($file, 0, 0) or die "FATAL: Can't remove $file!\n";
  } else {
    die "FATAL: Destination image \"$file\" already exists!\n";
  }
}

# check for existence of destination master autoinstall script
$file="$autoinstall_script_dir/$destination_image.master";
if(-e $file) {
  if($force) {
    unlink($file) or die "FATAL: Can't remove $file!\n";
  } else {
    die "FATAL: Destination master autoinstall script \"$file\" already exists!\n";
  }
}

# move the actual image
if($verbose) {print "  Moving image $source_image to $destination_image.\n";}
move($source, $destination)
  or die "FATAL: Failed to move $source to $destination.\n";

### BEGIN Change entries in $rsyncd_conf ###
$file=$rsyncd_conf;
if($verbose) {print "  Updating entries in $file.\n";}
open (FILE, "<$file") or die "FATAL: Couldn't open $file for reading!\n";

$tmp_file="/tmp/tmp_file.$$";
open (TMP_FILE, ">$tmp_file") or die "FATAL: Couldn't open $tmp_file for writing!\n";
  while (<FILE>) {
    if (/\[$source_image\]/) {
      print TMP_FILE "[$destination_image]\n";
    }
    elsif (/^\s*path\s*=.*$source_image/) { 
      print TMP_FILE "    path = $destination\n";
    }
    else {
      print TMP_FILE;
    }
  }
close TMP_FILE or die "FATAL: Can't close $tmp_file: $!";
close FILE or die "FATAL: Can't close $file: $!";

move($file, "$file.orig") or die "FATAL: Can't move $file to $file.orig: $!";
move($tmp_file, $file) or die "FATAL: Can't move $tmp_file to $file: $!";
### END Change entries in $rsyncd_conf ###

### BEGIN Change entries in master autoinstall script ###
# move master autoinstall script
if($verbose) {print "  Moving $source_image.master to $destination_image.master.\n";}
$old="$autoinstall_script_dir/$source_image.master";
$new="$autoinstall_script_dir/$destination_image.master";
move($old, $new) or die "FATAL: Can't move $old to $new: $!";


# update new master autoinstall script
$file=$new;
if($verbose) {print "  Updating entries in $destination_image.master.\n";}
open (FILE, "<$file") or die "FATAL: couldn't open $file for reading!\n";

$tmp_file="/tmp/tmp_file.$$";
open (TMP_FILE, ">$tmp_file") or die "FATAL: couldn't open $tmp_file for writing!\n";
  while (<FILE>) {
    s/^IMAGENAME=$source_image$/IMAGENAME=$destination_image/;
    print TMP_FILE;
  }
close TMP_FILE or die "FATAL: Can't close $tmp_file: $!";
close FILE or die "FATAL: Can't close $file: $!";

move($tmp_file, $file) or die "FATAL: Can't move $tmp_file to $file: $!";


# re-create soft links
if($verbose) {print "  Re-creating softlinks to point to $destination_image.master.\n";}
$cmd="cd $autoinstall_script_dir; find . -lname $source_image.master -exec ln -sf $destination_image.master \\{\\} \\;";
system($cmd);
if($? != 0) { die "FATAL: couldn't re-create softlinks pointing to $destination_image.master!"; }

### END Change entries in $rsyncd_conf ###

exit 0;
