#!/usr/bin/perl -w
use strict;

#
# Partimage Is Not Ghost / rc.ping
#
# Copyright(c) 2005-2006-2007 Windowsdream.com, GNU Licence
# Home page: PING (Partimage Is Not Ghost) http://ping.windowsdream.com/
#
# This script is intended to run on a PING Linux-live image. As for PING,
# Linux, GNU/GPL tools, etc. refer to specific licences.
# This script (rc.ping) has been written by Natan Scemama (the Author),
# from Windowsdream.com. Email: natan@windowsdream.com .
#
# * Use it at your own risk. No warranty, no damage accountability.
# * Please, refer any bug / feature request to the Author.
#

my $VERSION = "1.12";
my $VERSION_DATE = "2007-06-19";

my %P = ();

my $TIP_SLEEP = 0;


# Preliminaries
#
LOG("\n* Starting rc.ping $VERSION $VERSION_DATE\n*\n");

unless(-d "/tmp")
{
    mkdir("/tmp", 1777);
}
if(-e "/tmp/x.log")
{
    unlink("/tmp/x.log");
}


# See whether we've got Captive-NTFS or NTFS-3G.
# Captive-NTFS is to be preferred, because it can handle compressed folders,
# but new releases of PING might deliver NTFS-3G only.
#
LOG("* How will we mount NTFS partitions in read/write mode ?\n");

my $NTFS_CAP = "";
my $NTFS_MNT = "";
my $NTFS_MNT_TYPE = "";

if(-d "/var/lib/captive")
{
    $NTFS_CAP = "echo d|captive-install-acquire >/dev/null 2>&1";
    $NTFS_MNT = "echo d|captive-install-acquire >/dev/null 2>&1; mount -t captive-ntfs";
    $NTFS_MNT_TYPE = "captive-ntfs";
    LOG("  With Captive-NTFS!\n");
}
else
{
    $NTFS_MNT = "mount -t ntfs-3g";
    $NTFS_MNT_TYPE = "ntfs-3g";
    LOG("  With NTFS-3G!\n");
}


# Get info from a config file, if any.
#
LOG("* Looking for a possible /etc/ping.conf file...\n");

if(-e "/etc/ping.conf")
{
    LOG("  Found a /etc/ping.conf file.\n");
    open(DB, "/etc/ping.conf");
    while(<DB>)
    {
	s/^\s*//;
	next if(m/^\#/);
	my(@f) = split(/\=/, $_);
	my $V = "";
	if(defined($f[1]))
	{
	    $V = $f[1];
	}
	foreach(2..($#f - 1))
	{
	    if(defined($f[$_]))
	    {
		$V .= "=$f[$_]";
	    }
	}
	foreach($f[0], $V)
	{
	    s/^\s*//;
	    s/\s*$//;
	    s/^\"//;
	    s/\"$//;
	}
	foreach("IP", "Netmask", "Gateway",
		"Server", "Share", "User", "Passwd", "Directory",
		"Repart", "After_Completion")
	{
	    if(lc($_) eq lc($f[0]))
	    {
		$P{$_} = $V;
	    }
	}
    }
    close(DB);

    foreach("IP", "Netmask", "Gateway",
	    "Server", "Share", "User", "Passwd", "Directory", "Repart",
	    "After_Completion")
    {
	if(defined($P{$_}))
	{
	    LOG("  Found: [$_] = [".((m/^Passwd$/) ? "xxx":$P{$_})."]\n");
	}
    }
}
else
{
    LOG("  No ping.conf file was found. Not a problem.\n\n");
    LOG("  TIP: by adding a ping.conf to the linux image, you can\n");
    LOG("       avoid having to type again and again the same net/smb settings.\n");
    LOG("       Go to the forum for more information.\n\n");
    sleep($TIP_SLEEP);
}


# The source.
#
my $SRC = "";


# Try to mount the CDRom and find there an image.
#
LOG("* Looking for a possible CD/DVD...\n");

my $CD_Dev = '';
{
    my $nb = 0;
    foreach my $d ("hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sr0")
    {
        system("umount /mnt/cdrom >/dev/null 2>&1");
        system("mount /dev/$d /mnt/cdrom >/dev/null 2>&1");
        my $nb = `df|grep cdrom|wc -l`;
        if($nb > 0)
	{
            LOG("  Found and mounted a CDRom\n");
            opendir(DIR, "/mnt/cdrom");
            my(@Files) = readdir(DIR);
            closedir(DIR);
            foreach my $F (@Files)
	    {
                if($F =~/^[hs]d[abcde]$/)
		{
                    LOG("  Found a [/mnt/cdrom/$F] file\n");
		    $CD_Dev = $d;
                    $SRC = "/mnt/cdrom";
                }
            }
            sleep(5);   # Blink & start up.
            last;
        }
    }
    unless($nb)
    {
        LOG("  No CDRom device or media was found.\n");
    }
}


# If no cdrom has been found, maybe the user has booted a USB device.
# Maybe the user does not want to restore an image from the USB device,
# but to write one on it.
#
# Note: USB devices have SCSI-like device names... better have a look
# at kernel's messages or, even better, at /proc/bus/usb/devices ,
# since a device can be hot-plugged.
#
LOG("* Looking for a possible USB mass storage device...\n");

{
    #::: To do.
    1;
}


# Give a last tip if a CD/DVD with an image on it has been found.
#
if($SRC =~/cdrom/i)
{
    LOG("  TIP: by adding an empty \\AUTO file to your CD/DVD, you can\n");
    LOG("       avoid have the restoration process go with strictly no\n");
    LOG("       user interaction. Go to the forum for more information.\n\n");
    sleep($TIP_SLEEP);
}


# Give the user a chance to avoid this script.
#
system("clear");
print "\n".`uname -a`;
print "\n\n***      PING (Partimage Is Not Ghost) -- version $VERSION      ***\n";
print "***        Get doc and latest release on PING website       ***\n";
print "***              http://ping.windowsdream.com/              ***\n";
if($VERSION_DATE)
{
    print "***                                                         ***\n";
    print "***           Still a beta release -- $VERSION_DATE            ***\n";
}
print "\n";
print "Type [ENTER] to go on, x to get a shell (RIP-like Distribution).\n\n";
print "The shell has every tool you need to modify or format partitions,\n";
print "or to access data on a local hard disk. Most filesystems are\n";
print "currently supported, NTFS included ($NTFS_MNT_TYPE).\n";
print "To mount a NTFS volume: mount -t $NTFS_MNT_TYPE /dev/sda1 /mnt/dos\n";
if($NTFS_MNT_TYPE =~/captive/i)
{
    print "  Note: You'll have to type the mount command twice.\n";
}
print "\n>>";

# If a CD/DVD/USB device has been booted, raise no question if a file
# called 'AUTO' (case-sensitive) is found on the root of the CD/DVD/USB dev.
#
if($SRC =~/cdrom/ && -e "/mnt/cdrom/AUTO")
{
    LOG("* /cdrom/AUTO file found! No exit possibility given to the user.\n");
}
else
{
    my $Grab = <STDIN>;
    if($Grab =~/^x/i)
    {
        exit;
    }
}


# Try to find all HDD devices / will be useful or not, according
# to the user's choice, but it's (almost) costless to explore.
#
LOG("* Exploring local disk drives\n");

my @Dev = ();
{
    my @AllDevices = ('hda', 'hdb', 'sda', 'sdb', 'hdc', 'hdd', 'sdc', 'sdd');
    #
    # Generate all possible cciss hard disk device names and push them into AllDevices
    # (Compaq HP SmartArray). Same for RAID devices (ida and rd).
    #
    for(my $i = 0; $i <= 7; $i++) 
    {
	for(my $j = 0; $j <= 15; $j++)
	{
	    push(@AllDevices, "cciss/c".$i."d".$j);
	    push(@AllDevices, "ida/c".$i."d".$j);
	    push(@AllDevices, "rd/c".$i."d".$j);
	}
    }

    foreach(@AllDevices)
    {
	# At least thanks to udev, we won't have too many tries!
	#
	if(-e "/dev/$_")
	{
#	    LOG("  - Checking [/dev/$_]...\n");
	    my $out = `echo |fdisk /dev/$_ 2>&1`;
	    $out =~s/^\s*//;
	    $out =~s/\s*$//;
#	    LOG("    [$out]\n");
	    #
	    # Either not a partition at all, either is a CDRom = bad cases
	    #
	    if($out !~/^unable to open/i && $out !~/you will not be able to write/i)
	    {
		push(@Dev, $_);
	    }
	} 
    }
}
foreach(@Dev)
{
    LOG("  => HDD device found: [$_]\n");
    sleep(1);
}
if($#Dev < 0)
{
    LOG("  !!! No HDD device could be found. Will do nothing.\n");
    sleep(5);
    Quit();
}

# And now, exploring each device for parts and parts' types
#
LOG("* Exploring each hdd for parts and types\n");

my(@Dev_Rich) = ();

foreach my $D (@Dev)
{
    LOG("  Device [$D]\n");

    my(@Parts) = ();
    my(@Types) = ();

    `fdisk -l /dev/$D >/tmp/bla`;
    open(DB, "/tmp/bla");
    while(<DB>)
    {
	if(m/^\/dev\/$D/i)
	{
	    s/^\s*//;
	    s/\s*$//;
	    s/\*//g;    # Boot flag
	    s/  / /g while(m/  /);
	    s/^\s*\/dev\///i;
	    my(@F) = split(/ /, $_);
	    push(@Parts, $F[0]);
	    push(@Types, $F[4]);
	}
    }
    close(DB);
    unlink("/tmp/bla");
    for(my $i = 0; $i <= $#Parts; $i++)
    {
	LOG("    Local part: [$Parts[$i]]; type: [$Types[$i]]\n");
    }

    # Storage!
    #
    my(%Rich) = ();
    $Rich{Dev} = $D;
    $Rich{Parts} = \@Parts;
    $Rich{Types} = \@Types;
    push(@Dev_Rich, \%Rich);
}

#print "\n\n";
#foreach my $D (@Dev_Rich)
#{
#    print $D->{Dev}."\n";
#    for(my $i = 0; $i <= $#{$D->{Parts}}; $i++)
#    {
#	print "  ".$D->{Parts}->[$i]." -- ".$D->{Types}->[$i]."\n";
#    }
#}


# Give a warm welcome to the user...
#
if($SRC =~/cdrom/ && -e "/mnt/cdrom/AUTO")
{
    LOG("* /cdrom/AUTO file found! No warm welcome.\n");
}
else
{
    my $cmd = 'dialog --colors --msgbox "\Zb\Z7Welcome to PING (Partimage Is'
        .' Not Ghost)!\n\n\n'
        .'\ZnThis tool can be used both to backup a Ghost-like image of'
        .' your hard disk and to restore your hard disk from such an image.'
        .' Please, be aware that if you choose to restore your hard disk,'
        .' ALL the data contained on this computer might be '
        .'lost during the restoration. You may choose to abort now, by '
        .'stopping the computer now.\n\n\n" 22 73';
    system($cmd);
}


# Not everyone would like an automatic reboot to occur at the end of the
# operations... ask before, do later.
#
my $After_Completion = '';

if(defined($P{After_Completion}) && $P{After_Completion} =~/reboot/i)
{
    $After_Completion = "Reboot";
}
elsif(defined($P{After_Completion}) && $P{After_Completion} =~/shell/i)
{
    $After_Completion = "Shell";
}
elsif(defined($P{After_Completion}) && $P{After_Completion} =~/shutdown/i)
{
    $After_Completion = "Shutdown";
}

unless($After_Completion)
{
    if($SRC =~/cdrom/ && -e "/mnt/cdrom/AUTO")
    {
	LOG("* /cdrom/AUTO file found! Won't offer not to reboot.\n");
    }
    else
    {
	LOG("* Ask whether we'll reboot or exit at the end of the job\n");

	my $cmd = 'dialog --colors --menu "\Zb\Z7PING Partimage Is Not Ghost\n\n'
	    .'\ZnWhen the job is completed, do you want to...\n\n" 15 40 3 '
	    .' "Reboot the system" "" "Get a shell (root)" ""'
	    .' "Shutdown" "" 2>/tmp/checklist.tmp';
	system($cmd);

	if(-z "/tmp/checklist.tmp")
	{
	    $After_Completion = "Shell";
	    Quit();
	}

	open(DB, "/tmp/checklist.tmp");
	while(<DB>)
	{
	    if(m/shell/i)
	    {
		$After_Completion = "Shell";
		LOG("  Shell!\n");
		last;
	    }
	    elsif(m/shutdown/i)
	    {
		$After_Completion = "Shutdown";
		LOG("  Shutdown!\n");
		last;
	    }
	    elsif(m/reboot/i)
	    {
		$After_Completion = "Reboot";
		LOG("  Reboot!\n");
		last;
	    }
	}
	close(DB);
	`rm -f /tmp/checklist.tmp`;
    }
}

LOG("* After Completion: [$After_Completion]\n");


# As no CD/DVD is involved, the user may choose whether she wants
# to save/restore to a local part or to the network.
#
unless($SRC)
{
    LOG("* Ask whether operations will be local or network\n");

    my $cmd = 'dialog --colors --menu "\Zb\Z7PING Partimage Is Not Ghost\n\n'
	    .'\ZnWhere do you want to save/restore your images to/from ?\n\n" 15 40 2 '
	    .' "Network share" "" "Local disk/partition" "" 2>/tmp/checklist.tmp';
    system($cmd);

    if(-z "/tmp/checklist.tmp")
    {
	Quit();
    }

    open(DB, "/tmp/checklist.tmp");
    while(<DB>)
    {
	LOG("[$_]!!!\n");
        if(m/local/i || m/^l/i)
	{
	    $SRC = "local";
	    LOG("  Local!\n");
	}
    }
    close(DB);
    `rm -f /tmp/checklist.tmp`;
}


# If there's no CD or CD but no image within the CD and if this is not
# a local backup / restoration, then try the network.
#
unless($SRC)
{
    my $out = `ifconfig |grep ^eth |wc -l 2>&1`;
    $out =~s/\D//g;
    if($out == 0)
    {
        LOG("\n* Getting a DHCP IP address...\n");
        `dhcpcd eth0`;
    }
    $out = `ifconfig |grep ^eth |wc -l 2>&1`;
    $out =~s/\D//g;
    if($out == 0)
    {
        LOG("\n!!! Could not find a network device and connect it to DHCP.\n");
        #
	# Let's ask the user for help...
	#
        my $Tries = 1;

        while($Tries)
	{
	    # Use ping.conf's parameters if defined.
	    #
	    unless($Tries == 1)
	    {
		foreach("IP", "Netmask", "Gateway")
		{
		    $P{$_} = "";
		}
	    }

	    unless(defined($P{IP}) && $P{IP})
	    {
		my $cmd = 'dialog --inputbox "Enter your IP address '
		    .'(eg. 192.168.0.10)" 8 51 2>/tmp/BLA';
		system($cmd);
		open(DB, "/tmp/BLA");
		while(<DB>)
		{
		    $P{IP} .= $_;
		}
		close(DB);
	    }

	    unless(defined($P{Netmask}) && $P{Netmask})
	    {
		my $cmd = 'dialog --inputbox "Enter your netmask '
		    .'(eg. 255.255.255.0)" 8 51 2>/tmp/BLA';
		system($cmd);
		open(DB, "/tmp/BLA");
		while(<DB>)
		{
		    $P{Netmask} .= $_;
		}
		close(DB);
	    }

	    unless(defined($P{Gateway}) && $P{Gateway})
	    {
		my $cmd = 'dialog --inputbox "Enter your gateway '
		    .'(eg. 192.168.0.1)" 8 51 2>/tmp/BLA';
		system($cmd);
		open(DB, "/tmp/BLA");
		while(<DB>)
		{
		    $P{Gateway} .= $_;
		}
		close(DB);
	    }

            foreach("IP", "Netmask", "Gateway")
	    {
		$P{$_} =~s/^\s*//;
		$P{$_} =~s/\s*$//;
		$P{$_} =~s/[^0-9.]//g;
            }

	    LOG("* Connecting to the network\n");
	    system("ifconfig eth0 down; ifconfig eth0 $P{IP} netmask $P{Netmask} up;"
		   ." route add default gw $P{Gateway}; ifconfig eth0 >/tmp/out 2>&1");

            ++ $Tries;

	    my $out = "";
            if(-e "/tmp/out")
	    {
                open(DB, "/tmp/out");
                while(<DB>)
		{
		    $out .= $_;
                    if(m/$P{IP}/)
		    {
			$Tries = 0;
                    }
                }
                close(DB);
                unlink("/tmp/out");
            }
	    if($Tries)
	    {
		LOG("\n* Command output: [$out]\n");
		LOG("\n* BAD network parameters or device/driver pb. TRY AGAIN.\n");
		sleep(3);
	    }
        }
    }

    $SRC = "/mnt/smbfs";
}


# Mount partimages' network share.
#
if($SRC =~/smbfs$/)
{
    #
    # Let's find this directory...
    #
    my $Tries = 1;

    while($Tries)
    {
	unless($Tries == 1)
	{
	    foreach("Server", "Share", "User", "Passwd", "Directory")
	    {
		$P{$_} = "";
	    }
	}

	unless(defined($P{Server}) && $P{Server})
	{
	    my $cmd = 'dialog --inputbox "Enter a valid SMB Server IP '
		.'(eg. 192.168.0.10)" 8 51 2>/tmp/BLA';
	    system($cmd);
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$P{Server} .= $_;
	    }
	    close(DB);
	    $P{Server} =~s/^\/*//;
	    $P{Server} =~s/^\\*//;
	}

	unless(defined($P{Share}) && $P{Share})
	{
	    my $cmd = 'dialog --inputbox "Enter a valid SMB Share Name '
		.'(eg. MyShare)" 8 51 2>/tmp/BLA';
	    system($cmd);
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$P{Share} .= $_;
	    }
	    close(DB);
	    $P{Share} =~s/^\/*//;
	    $P{Share} =~s/^\\*//;
	    $P{Share} =~s/\$/\\\$/g;
	}

	unless(defined($P{User}) && $P{User})
	{
	    my $cmd = 'dialog --inputbox "Enter a valid username '
		.'(eg. mydomain\johndoe)" 8 51 2>/tmp/BLA';
	    system($cmd);
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$P{User} .= $_;
	    }
	    close(DB);
	    $P{User} =~s/\//\\\\/g;
	    $P{User} =~s/\\/\\\\/g;
	}

	unless(defined($P{Passwd}) && $P{Passwd})
	{
	    my $cmd = 'dialog --passwordbox "Enter a valid password '
		.'(eg. secret)" 8 51 2>/tmp/BLA';
	    system($cmd);
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$P{Passwd} .= $_;
	    }
	    close(DB);
	    $P{Passwd} =~s/\\/\//;
	}

	foreach("Server", "Share", "User", "Passwd")
	{
	    $P{$_} =~s/^\s*//;
	    $P{$_} =~s/\s*$//;
	}

	LOG("* Unmounting /mnt/smbfs\n");
	system("umount /mnt/smbfs >/dev/null 2>&1");
	LOG("* Trying to mount //$P{Server}/$P{Share} (smbfs)\n");
	system("smbmount //$P{Server}/$P{Share} /mnt/smbfs -o"
	       ." username=$P{User},password=\"$P{Passwd}\" >/tmp/out 2>&1");

	my $out = "";
	if(-e "/tmp/out")
	{
	    open(DB, "/tmp/out");
	    while(<DB>)
	    {
		$out .= $_;
	    }
	    close(DB);
	    unlink("/tmp/out");
	    LOG("\n* SMB mount output: [$out]\n"); 

	    if($out =~/failed/i)
	    {
		# Another chance
		my $tmp = `df |grep smbfs |wc -l`;
		$tmp =~s/\D//g;
		unless($tmp)
		{
		    ++ $Tries;
		    LOG("\n* BAD Server, Share, User or Passwd. Try CIFS, or all again.\n");
		    sleep(3);
		}
	    }
	    else
	    {
		$Tries = 1;
	    }
	}

	# Sometimes, cifs must be preferred to smbfs (Windows Server cases ? AD ?)
	# Let's give it a chance.
	#
	if($Tries != 1)
	{
	    LOG("* Second chance! (CIFS)\n");
	    LOG("* Unmounting /mnt/smbfs\n");
	    system("umount /mnt/smbfs >/dev/null 2>&1");
	    LOG("* Trying to mount //$P{Server}/$P{Share} (cifs)\n");
	    system("mount -t cifs //$P{Server}/$P{Share} /mnt/smbfs -o"
		   ." username=$P{User},password=\"$P{Passwd}\" >/tmp/out 2>&1");

	    $out = "";
	    if(-e "/tmp/out")
	    {
		open(DB, "/tmp/out");
		while(<DB>)
		{
		    $out .= $_;
		}
		close(DB);
		unlink("/tmp/out");
		LOG("\n* SMB mount output: [$out]\n"); 

		if($out =~/failed/i)
		{
		    # Another chance
		    my $tmp = `df |grep smbfs |wc -l`;
		    $tmp =~s/\D//g;
		    unless($tmp)
		    {
			++ $Tries;
			LOG("\n* Well, BAD Server, Share, User or Passwd. TRY AGAIN.\n");
			sleep(5);
		    }
		}
		else
		{
		    $Tries = 1;
		}
	    }
	}

	if($Tries == 1)
	{
	    my $cnt = 0;

	    my $Mounted = 0;
            opendir(DIR, "/mnt/smbfs/$P{Directory}");
            my(@Files) = readdir(DIR);
            closedir(DIR);
            foreach my $F (@Files)
	    {
		next if($F =~/^\.{1,2}$/);
		++ $Mounted;
		$Tries = 0;
            }
	    if($Mounted)
	    {
		LOG("* Found subdirs in [/mnt/smbfs/$P{Directory}]. Seems mounted.\n");
	    }

	    while(! $cnt && ! $Mounted)
	    {
		$P{Directory} = "";
		my $cmd = 'dialog --inputbox "Enter a possible subdirectory '
		    .'containing your data '
		    .'(eg. \mydir\Partimage)" 8 51 2>/tmp/BLA';
		system($cmd);
		$P{Directory} = '';
		open(DB, "/tmp/BLA");
		while(<DB>)
		{
		    $P{Directory} .= $_;
		}
		close(DB);
		$P{Directory} =~s/^\s*//;
		$P{Directory} =~s/\s*$//;
		$P{Directory} =~s/\\/\//g;
		$P{Directory} =~s/^\/*//;
		++ $cnt;
	    }
	    $SRC = "/mnt/smbfs/$P{Directory}";
	    LOG("* Found SRC: [$SRC]\n");
	}
    }
}


# If the source is local, we've got to mount the partition where
# images are stored. The user might have several hdds... if so,
# give the possibility to choose which one to use.
#
# Currently, we only handle one device: no cross-device backup.
# Maybe in the future.
#
my $Local_Device = '';
my @Local_Parts = ();
my $Local_SRC_Part = '';
my $Local_DST_Part = '';

my $New_Second_Part = 0;
my $Only_One_Part = 0;

if($SRC eq "local")
{
    LOG("* Images are local. Find out which device.\n");

    if($#Dev > 0)
    {
	my $cmd = 'dialog --colors --menu "\Zb\Z7Locally saving / restoring\n\n'
	    .'\ZnSeveral HDDs have been detected. Which one will we use ?\n\n" 15 40 5 '
	    .' ';
	foreach(@Dev)
	{
	    $cmd .= '"/dev/'.$_.'" "" ';
	}
	$cmd .= '2>/tmp/checklist.tmp';

	system($cmd);

	open(DB, "/tmp/checklist.tmp");
	while(<DB>)
	{
	    $Local_Device .= $_;
	}
	close(DB);
	`rm -f /tmp/checklist.tmp`;
	$Local_Device =~s/\s*$//;
	$Local_Device =~s/^\/dev\///;

	LOG("  Chosen device: [$Local_Device]\n");
    }
    else
    {
	$Local_Device = $Dev[0];
	LOG("  Only one detected device: [$Dev[0]]\n");
    }

    LOG("* Now, find out which parts are available on [/dev/$Local_Device]\n");

    `fdisk -l /dev/$Local_Device >/tmp/bla`;
    open(DB, "/tmp/bla");
    while(<DB>)
    {
	if(m/^\/dev\/$Local_Device/i)
	{
	    s/\s.*$//;
	    s/^\s*\/dev\///i;
	    s/\s*$//;
	    push(@Local_Parts, $_);
	}
    }
    close(DB);
    unlink("/tmp/bla");
    foreach(@Local_Parts)
    {
	LOG("  Local part: [$_]\n");
    }

    LOG("* Find out which part will be the src, which one will be the dest.\n");

    if($#Local_Parts == 0)
    {
	LOG("  Only one part. Obviously both src and dest.\n");
	$Local_DST_Part = $Local_Parts[0];
	$Local_SRC_Part = $Local_Parts[0];
	++ $Only_One_Part;

	LOG("  Only one partition. Let's investigate...\n");

	my $Dev_Size = 0;
	my $Dev_Type = 0;

	`fdisk -l /dev/$Local_Device >/tmp/bla`;
	open(DB, "/tmp/bla");
	while(<DB>)
	{
	    if(m/^\/dev\/$Local_SRC_Part/i && ! $Dev_Size)
	    {
		$Dev_Size = $_;
		$Dev_Size =~s/\*//g;
		$Dev_Size =~s/\+//g;
		$Dev_Size =~s/\s+/ /g;
		$Dev_Size = (split(/ /, $Dev_Size))[3] * 1024;
	    }
	    if(m/^\/dev\/$Local_SRC_Part/i && ! $Dev_Type)
	    {
		$Dev_Type = $_;
		$Dev_Type =~s/\*//g;
		$Dev_Type =~s/\s+/ /g;
		$Dev_Type = (split(/ /, $Dev_Type))[4];
	    }
	}
	close(DB);
	unlink("/tmp/bla");

	LOG("  - Size of the device: [$Dev_Size]\n");
	LOG("  - Type of the unique part: [$Dev_Type]\n");

	system("umount /mnt/dos >/dev/null 2>&1; "
	       ."mount /dev/$Local_SRC_Part /mnt/dos >/dev/null 2>&1");

	my $Used_Space = 0;
	my $out = `df 2>&1 | grep -i \/dev\/$Local_SRC_Part`;
	$out =~s/\s+/ /g;
	$Used_Space = (split(/ /, $out))[2] * 1024;
	LOG("  - Space used by [$Local_SRC_Part]: [$Used_Space]\n");

	my $Avail_Space = $Dev_Size - $Used_Space;
	LOG("  - Available space on [$Local_SRC_Part]: [$Avail_Space]\n");

	my $Useless_Space = 0;

	if($Avail_Space < .5 * $Dev_Size)
	{
	    LOG("  - Let's see if we can delete useless files...\n");

	    foreach my $file ("pagefile.sys", "hiberfil.sys")
	    {
		if(-e "/mnt/dos/$file")
		{
		    $Useless_Space += (stat("/mnt/dos/$file"))[7];
		}
	    }
	    if($Useless_Space)
	    {
		$Avail_Space += $Useless_Space;
		$Used_Space -= $Useless_Space;
		LOG("    Yep. Can win [$Useless_Space] bytes more.\n");
		LOG("    After removing them, avail. space'd be: [$Avail_Space]\n");
		LOG("    and used space should be: [$Used_Space]\n");
	    }
	    else
	    {
		LOG("    Nope. No useless space.\n");
	    }
	}

	if($Avail_Space >= .5 * $Dev_Size)
	{
	    LOG("  - Turns out we could resize the unique partition...\n");

	    my $Resize = 0;

	    if(defined($P{Repart}) && $P{Repart} =~/^(y|1)$/i)
	    {
		LOG("    Config file says we can repart!\n");
		$Resize = 1;
	    }
	    else
	    {
		my $cmd = 'dialog --colors --menu "\Zb\ZnYou only have one partition'
		    .' on your hard disk drive ('.$Local_Device.'), and PING needs'
		    .' a second partition to write to or restore from saved images.'
		    .'\n\nNevertheless, it seems that there is enough free space for'
		    .' me to dynamically repart your HDD. Do you want me to do so ?'
		    .'\n\n(You definitely SHOULD have a backup of any valuable data'
		    .' before saying Yes here.)\n\n" 19 50 2 '
		    .' "Yes" "" "No" "" 2>/tmp/checklist.tmp';
		system($cmd);

		if(-z "/tmp/checklist.tmp")
		{
		    Quit();
		}

		open(DB, "/tmp/checklist.tmp");
		while(<DB>)
		{
		    if(m/Y/i)
		    {
			++ $Resize;
			last;
		    }
		}
		close(DB);
		unlink("/tmp/checklist.tmp");
	    }

	    unless($Resize)
	    {
		LOG("  Wisdom has been chosen... exit is the only choice.\n");
		sleep(5);
		Quit();
	    }

	    LOG("  So, we can repart the device [$Local_Device]\n");

	    if($Useless_Space)
	    {
		LOG("  - Removing useless files on [/dev/$Local_SRC_Part]\n");

		if($Dev_Type eq "7")
		{
		    LOG("    Mounting with Captive-NTFS [/dev/$Local_SRC_Part]\n");
		    system("umount /mnt/dos >/dev/null 2>&1; $NTFS_MNT /dev/$Local_SRC_Part /mnt/dos >/dev/null 2>&1; umount /mnt/dos >/dev/null 2>&1; mount -t captive-ntfs /dev/$Local_SRC_Part /mnt/dos");
		}

		foreach my $file ("pagefile.sys", "hiberfil.sys")
		{
		    if(-e "/mnt/dos/$file")
		    {
			system("cd /mnt/dos; chmod 666 $file >/dev/null 2>&1;"
			       ."rm -f $file >/dev/null 2>&1; sync");
			LOG("    Deleting [/mnt/dos/$file]\n");
		    }
		}
	    }

	    LOG("  - Estimating [/dev/$Local_SRC_Part] future size\n");

	    my $New_Size = 0;
	    {
		system("umount /mnt/dos >/dev/null 2>&1;"
		       ."ntfsresize -i -f /dev/$Local_SRC_Part >/tmp/bla 2>&1");
		if(-e "/tmp/bla")
		{
		    open(DB, "/tmp/bla");
		    while(<DB>)
		    {
			if(m/^You might resize at/i)
			{
			    $New_Size = $_;
			    $New_Size =~s/^\D+([0-9]+)\sbytes.*$/$1/;
			    $New_Size =~s/\D//g;
			    LOG("    We can reduce to [$New_Size]\n");
			    last;
			}
		    }
		    close(DB);
		    unlink("/tmp/bla");
		}

		# Not too much, yet.
		#
		if($New_Size < .5 * $Dev_Size)
		{
		    $New_Size = int($Dev_Size / 2);
		    LOG("    Reducing to [$New_Size] will be enough.\n");
		}

		# mkfs.vfat won't operate if the volume is too small
		# (who knows what data there is on the C: drive after all)
		#
		if(($Dev_Size - $New_Size) < 40000000)
		{
		    $New_Size = $Dev_Size - 40000000;
		    LOG("    New part would be too small; reducing to [$New_Size]\n");
		}

		if($Used_Space > $New_Size || $New_Size == 0)
		{
		    LOG("    !!! Space problem. Aborting now.\n");
		    sleep(5);
		    Quit();
		}
	    }
	    
	    LOG("  - Resizing to [$New_Size] !!\n");

	    {
		my $cmd = "ntfsresize -f -s $New_Size /dev/$Local_SRC_Part "
		    .">/tmp/bla 2>&1";
		LOG("    [$cmd]\n");
		my(@tmp) = ('d', 'n', 'p', '1', '1', '+'.int($New_Size / 1024).'K',
			    'a', '1', 't', $Dev_Type, 'w');
		$cmd = 'echo -e "';
		foreach(@tmp)
		{
		    $cmd .= $_.'\n';
		}
		$cmd .= '" | fdisk /dev/'.$Local_Device.' 2>&1';
		LOG("    [$cmd]\n");
		system("$cmd >>/tmp/x.log 2>&1");
	    }

	    # Now, we'll write images on the second part.
	    #
	    $Local_DST_Part =~s/1$/2/;
	    push(@Local_Parts, $Local_DST_Part);
	    ++ $New_Second_Part;   # So we won't ask silly questions...

	    LOG("  - Creating a second partition on [/dev/$Local_DST_Part] (FAT32)\n");

	    {
		my(@tmp) = ('n', 'p', '2', '', '', 't', '2', 'c', 'w');
		my $cmd = 'echo -e "';
		foreach(@tmp)
		{
		    $cmd .= $_.'\n';
		}
		$cmd .= '" | fdisk /dev/'.$Local_Device.' 2>&1';
		LOG("    [$cmd]\n");
		system("$cmd >>/tmp/x.log 2>&1");
	    }

	    LOG("  - Formating the new partition [/dev/$Local_DST_Part] (FAT32)\n");

	    {
		my $cmd = "mkfs.vfat -F 32 /dev/$Local_DST_Part";
		LOG("    [$cmd]\n");
		system("$cmd >>/tmp/x.log 2>&1");
	    }
	}
	else
	{
	    LOG("  - Aie. The only present part occupies more than half disk space.\n");
	    LOG("    There's nothing we can do. Better exit now.\n");
	    sleep(5);
	    Quit();
	}
    }

    {
	my $Mounted = 0;

	unless($New_Second_Part || $Only_One_Part)
	{
	    my $cmd = 'dialog --colors --menu "\Zb\Z7Locally saving / restoring\n\n'
		.'\ZnSeveral partitions have been detected on /dev/'
		.$Local_Device.'. Which one does contain the SYSTEM '
		.'to backup / restore ?\n\n" 15 40 5 ';
	    foreach(@Local_Parts)
	    {
		$cmd .= '"/dev/'.$_.'" "" ';
	    }
	    $cmd .= '2>/tmp/checklist.tmp';

	    system($cmd);

	    $Local_SRC_Part = '';
	    open(DB, "/tmp/checklist.tmp");
	    while(<DB>)
	    {
		$Local_SRC_Part .= $_;
	    }
	    close(DB);
	    `rm -f /tmp/checklist.tmp`;
	    $Local_SRC_Part =~s/\s*$//;
	    $Local_SRC_Part =~s/^\/dev\///;
	}

	LOG("  Chosen local SRC partition: [$Local_SRC_Part]\n");

	while(! $Mounted)
	{
	    unless($New_Second_Part || $Only_One_Part)
	    {
		my $cmd = 'dialog --colors --menu "\Zb\Z7Locally saving / restoring\n\n'
		    .'\ZnSeveral partitions have been detected on /dev/'
		    .$Local_Device.'. Which one does/will contain PING'."'"
		    .'s generated images ?\n\n" 15 40 5 ';

		foreach(@Local_Parts)
		{
		    next if(m/$Local_SRC_Part/);
		    $cmd .= '"/dev/'.$_.'" "" ';
		}
		$cmd .= '2>/tmp/checklist.tmp';

		system($cmd);

		$Local_DST_Part = '';
		open(DB, "/tmp/checklist.tmp");
		while(<DB>)
		{
		    $Local_DST_Part .= $_;
		}
		close(DB);
		`rm -f /tmp/checklist.tmp`;
		$Local_DST_Part =~s/\s*$//;
		$Local_DST_Part =~s/^\/dev\///;
	    }

	    LOG("  Chosen local DST partition: [$Local_DST_Part]\n");

	    LOG("  Mounting /dev/$Local_DST_Part...\n");
	    my $cmd = "umount /mnt/dos >/dev/null 2>&1; "
		."mount /dev/$Local_DST_Part /mnt/dos >/dev/null 2>&1";
	    system($cmd);

	    my $tmp = `df |grep dos |wc -l`;
	    $tmp =~s/\D//g;
	    if($tmp)
	    {
		LOG("  Mounted !\n");
		++ $Mounted;
	    }
	    else
	    {
		LOG("  ! Could not mount the device at all. TRY AGAIN.\n");
		sleep(5);
	    }
	}
    }
}

if($SRC eq "local")
{
    $SRC = "/mnt/dos";
}

my $Found = 0;

if($SRC =~/cdrom/)
{
    $P{Directory} = '';
}
else
{
    if($New_Second_Part)
    {
	LOG("  The dest part is new. Creating a /Partimage directory on it.\n");

	my $cmd = "umount $SRC >/dev/null 2>&1;".
	    "mount /dev/$Local_DST_Part $SRC >/dev/null 2>&1;".
	    "mkdir $SRC/Partimage";
	LOG("    Cmd: [$cmd]\n");
	system($cmd);

	$P{Directory} = "/Partimage";
    }
    else
    {
	while(! $Found)
	{
	    $P{Directory} = "";
	    my $cmd = 'dialog --inputbox "Enter a root directory '
		.'containing your data '
		.'(eg. \mydir\Partimage)" 8 51 2>/tmp/BLA';
	    system($cmd);
	    $P{Directory} = '';
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$P{Directory} .= $_;
	    }
	    close(DB);
	    $P{Directory} =~s/^\s*//;
	    $P{Directory} =~s/\s*$//;
	    $P{Directory} =~s/\\/\//g;
	    $P{Directory} =~s/^\/*//;

	    LOG("  Chosen root subdir: [$P{Directory}]\n");

	    if(-d "$SRC/$P{Directory}")
	    {
		LOG("  Found !\n");
		++ $Found;
	    }
	    else
	    {
		LOG("  ! The [$SRC/$P{Directory}] could not be found. Try again.\n");
	    }
	}
    }
}

$SRC = "$SRC/$P{Directory}";
LOG("* Found SRC: [$SRC]\n");


# Get the list of all partimaged Entries.
# Listing the share's directories gives it. And so there's no need
# to modify this script every time a new entry is added...
#
my @Entities = ();

if($SRC =~/smbfs/ || $SRC =~/dos/)
{
    opendir(DIR, $SRC);
    my @F = readdir(DIR);
    closedir(DIR);
    foreach(@F)
    {
        next if m/^\.{1,2}$/;
        next unless(-d "$SRC/$_");
        push(@Entities, $_);
    }
    if($#Entities < 0 && $SRC =~/smbfs/)
    {
        LOG("!!! No Entity could be found.\n");
	sleep 5;
        Quit();
    }
}


# If the user has chosen a local copy, he obviously wants to be
# able to create a new image etc. So, let's add the special directories
# if he has forgotten to create them.
#
if($SRC =~/dos/)
{
    foreach my $S ("Blank_Local_Admin_Passwd", "Create_New_Image")
    {
	my $flag = 0;
	foreach(@Entities)
	{
	    if(m/^$S$/i)
	    {
		++ $flag;
		last;
	    }
	}
	unless($flag)
	{
	    push(@Entities, $S);
	}
    }
}


# Which entry will we install ?
#
my $Entity = '/';

if($SRC =~/smbfs/ || $SRC =~/dos/)
{
    my $cmd = 'dialog --colors --menu "\Zb\Z7Should we install...\n\n" 15 60 8 '
	.' ';
    foreach(@Entities)
    {
	$cmd .= '"'.$_.'" "" ';
    }
    $cmd .= ' 2>/tmp/BLA';
    system($cmd);
    open(DB, "/tmp/BLA");
    while(<DB>)
    {
        $Entity .= $_;
    }
    close(DB);
    unlink("/tmp/BLA");
    $Entity =~s/^\s+//g;
    $Entity =~s/\s+$//g;
    $Entity =~s/^\///g;
}


# Restore partitions.
# Naming convention: files sda1.000 sda1.001 etc. => /dev/sda1.
# File sda contains partitionning information and must be dumped first.
#
my $Have_Restored = 0;

if($Entity =~/Partition_and_Format_ANY_Computer/i
   || $Entity =~/Backup_Local_Hard_Disk/i
   || $Entity =~/Blank_Local_Admin_Passwd/i
   || $Entity =~/Create_New_Image/i)
{
    my $Dev = '';
    if($SRC =~/smbfs/i)
    {
	$Dev = (defined($Dev[0])) ? $Dev[0]:'';
    }
    elsif($SRC =~/dos/i)
    {
	$Dev = $Local_Device;
    }

    if($SRC =~/dos/i && $Dev && $Entity =~/Partition_and_Format_ANY_Computer/i)
    {
        LOG("* Found a HDD device: /dev/$Dev\n");

        # Do the partitions job... argh :=-
        #
	LOG("* Create partitions as specified\n");
	opendir(DIR, "$SRC/$Entity");
	my(@files) = readdir(DIR);
	closedir(DIR);
	foreach my $F (@files)
	{
	    if($F =~/^.*\.part$/i)
	    {
		my $Dev = $F;
		$Dev =~s/\.part$//i;
		my $CMD_Label = '';

		LOG("  * Found [$F] => partitioning instructions.\n");
		my @fdisk = ('d', 1, 'd', 2, 'd', 3, 'd', 4, 'd', 5, 'd', 6);
		my $cnt = 0;
		open(DB, "$SRC/$Entity/$F");
		while(<DB>)
		{
		    s/^\s*//;
		    s/\s*$//;
		    s/\s/ /g;
		    while(m/  /)
		    {
			s/  / /g;
		    }
		    next if(m/^\;/);
		    my @fields = split(/ /, $_);
		    next unless($#fields >= 2);
		    my($PNumber, $PSize, $PType, $PLabel, $PBoot) = @fields;

		    push(@fdisk, 'n', 'p', $PNumber, '');
		    if($PSize eq "+")
		    {
			push(@fdisk, '');
		    }
		    else
		    {
			push(@fdisk, "+$PSize");
		    }
		    push(@fdisk, 't');
		    if($cnt > 0)
		    {
			push(@fdisk, $PNumber);
		    }
		    push(@fdisk, $PType);
		    if($PBoot eq "*")
		    {
			push(@fdisk, 'a', $PNumber);
		    }
		    if($PLabel)
		    {
			$CMD_Label .= ";ntfslabel -f /dev/$Dev$PNumber $PLabel";
		    }
		    ++ $cnt;
		}
		close(DB);
		push(@fdisk, 'w');

		my $cmd = 'echo -e "';
		foreach(@fdisk)
		{
		    $cmd .= $_.'\n';
		}
		$cmd .= '" | fdisk /dev/'.$Dev.' 2>&1';
		LOG("    * [$cmd]\n");
		system($cmd);
		LOG("    * [$CMD_Label]\n");
		system($CMD_Label);

		last;
	    }
        }
        LOG("* Make C: a RAW unformated partition\n");
        system("dd if=/dev/zero of=/dev/$Dev"."1 count=1000 bs=1000");
        #
        # Better not! Decision is easier for windows setup if partition is seen as RAW.
        # print "* Format C: (NTFS)\n";
        # system("mkntfs -L SYSTEM /dev/$Dev"."1");
        #
        LOG("* Format D: (NTFS)\n");
        system("mkntfs -Q -L DATA /dev/$Dev"."2");
        {
            LOG("* Write the partition table again\n");
            my @Do = ('w');
            my $cmd = 'echo -e "';
            foreach(@Do)
	    {
                $cmd .= $_.'\n';
            }
            $cmd .= '" | fdisk /dev/'.$Dev.' 2>&1';
            my $out = `$cmd`;
        }
        system("ntfsfix /dev/$Dev"."2");
        system("ntfslabel -f /dev/$Dev"."2 DATA");
        LOG("* You may safely download a RIS image (unattended setup)!\n");
    }

    elsif($Dev && $Entity =~/Create_New_Image/i)
    {
	my $New_Image = '';
	while(length($New_Image) < 1)
	{
	    my $cmd = 'dialog --inputbox "Enter the name of the '
		.'new image :" 8 51 2>/tmp/BLA';
	    system($cmd);
	    open(DB, "/tmp/BLA");
	    while(<DB>)
	    {
		$New_Image .= $_;
	    }
	    close(DB);
	    $New_Image =~s/^\s*//;
	    $New_Image =~s/\s*$//;
	    $New_Image =~s/\s/_/g;
	}
	LOG("* Name of future image: [$New_Image]\n");

	# Give the user the possibility to choose between gzip and bzip2
	#
	my $Compression_Type = 'gzip';
	{
	    my $cmd = 'dialog --colors --menu "\Zb\ZnDo you want gzip (faster)'
		.' or bzip2 (less used space) to be used ?\n\n" 12 50 2 '
		.' "gzip" "" "bzip2" "" 2>/tmp/checklist.tmp';
	    system($cmd);

	    if(-z "/tmp/checklist.tmp")
	    {
		Quit();
	    }

	    open(DB, "/tmp/checklist.tmp");
	    while(<DB>)
	    {
		if(m/bzip2/i)
		{
		    $Compression_Type = 'bzip2';
		    last;
		}
	    }
	    close(DB);
	    unlink("/tmp/checklist.tmp");
	}
	LOG("* Chosen compression type: [$Compression_Type]\n");

	# If the user has asked for a local image to be done, then we
	# might have to mount the dest part with Captive NTFS, for it
	# to be writable. By default, we did not, as reading is faster
	# with native kernel NTFS read-only drivers.
	#
	if($SRC =~/dos/i)
	{
	    LOG("* A local image was asked. Checking /dev/$Local_DST_Part FS...\n");
	    my $FS = '';
	    system("fdisk -l /dev/$Dev | grep -i $Local_DST_Part >/tmp/bla 2>&1");
	    if(-e "/tmp/bla")
	    {
		open(DB, "/tmp/bla");
		while(<DB>)
		{
		    s/^\s*//;
		    s/\s*$//;
		    s/\*//g;    # Boot flag
		    s/\+//g;    # Blocks addon
		    while(m/\s\s/)
		    {
			s/\s\s/ /g;
		    }
		    $FS = (split(/ /, $_))[4];
		}
		close(DB);
		unlink("/tmp/bla");
	    }
	    LOG("  Filesystem ID found: [$FS]\n");

	    if($FS eq "7")
	    {
		LOG("  This means NTFS. Remounting it with Captive.\n");
		system("umount /mnt/dos >/dev/null 2>&1; $NTFS_MNT /dev/$Local_DST_Part /mnt/dos >/dev/null 2>&1; umount /mnt/dos >/dev/null 2>&1; mount -t captive-ntfs /dev/$Local_DST_Part /mnt/dos");

		LOG("  Checking the mounting...\n");
		my $tmp = `df |grep dos |wc -l`;
		$tmp =~s/\D//g;
		if($tmp)
		{
		    LOG("  Mounted !\n");
		    LOG("  **TIP** saving an image is MUCH faster on a FAT32 part.\n\n");
		    sleep($TIP_SLEEP);
		}
		else
		{
		    LOG("  ! Could not mount the device at all. Exit.\n");
		    sleep(5);
		    Quit();
		}
	    }
	}

	if(-d "$SRC/$New_Image")
	{
	    LOG("* Renaming old [$SRC/$New_Image]"
		." to [(...).OLD.$$]\n");
	    rename("$SRC/$New_Image",
		   "$SRC/$New_Image.OLD.$$");
	}
	LOG("* Creating dir [$SRC/$New_Image]\n");
	mkdir("$SRC/$New_Image", 0755);
	#
	# Handling the case of a $Dev being worth cciss/c0d0 (HP SmartArray)... + rd + ida.
	# We need a $SRC/$New_Image/cciss/ directory.
	#
	if($Dev =~/\//)
	{
	    my $tmp = $Dev;
	    $tmp =~s/\/[^\/]+$//;
	    LOG("* Creating dir [$SRC/$New_Image/$tmp]\n");
	    mkdir("$SRC/$New_Image/$tmp", 0755);
	}
	LOG("* Backuping bios\n");
	system("cmospwd -w $SRC/$New_Image/bios");
	LOG("* Backuping first sectors of $Dev\n");
	system("dd if=/dev/$Dev of=$SRC/$New_Image/$Dev"
	       ." count=20 bs=512");
	LOG("* Listing partitions to be stored\n");
	#
        # HP SmartArray => there will be a /dev/cciss/c0d0 device,
        # and /dev/cciss/c0d1 etc. filesystems. The last digit must
        # be removed for the parsing of the fdisk command to succeed.
        # Disk /dev/cciss/c0d0: 73.3 GB, 73372631040 bytes
	# Idem for ida and rd (RAID).
        #
	my $Dev_Fdisk = $Dev;
	if($Dev_Fdisk =~/(cciss|rd|ida)/i)
	{
	    $Dev_Fdisk =~s/\d$//;
	}
	system("fdisk -l /dev/$Dev >/tmp/BLA");
	my @P = ();
	open(DB, "/tmp/BLA");
	while(<DB>)
	{
	    if(m/^\/dev\/$Dev_Fdisk/i && ! m/Extended/i)
	    {
		my $tmp = (split(/ /, $_))[0];
                $tmp =~s/^\/dev\///i;
                push(@P, $tmp);
	    }
	}
	close(DB);
	foreach(@P)
	{
	    LOG("* Checking /dev/$_ for pagefile.sys and hiberfil.sys (to remove)\n");
	    system("$NTFS_MNT /dev/$_ /mnt/win >/dev/null 2>&1; umount /mnt/win >/dev/null 2>&1; mount -t captive-ntfs /dev/$_ /mnt/win");
	    foreach my $file ("pagefile.sys", "hiberfil.sys")
	    {
		if(-e "/mnt/win/$file")
		{
		    LOG("  * Removing [$file]\n");
		    system("chmod 0666 /mnt/win/$file; rm -f /mnt/win/$file");
		}
	    }
	    system("umount /mnt/win");
	    LOG("* Storing /dev/$_\n");
	    system("partimage -f3 -z".($Compression_Type eq 'gzip' ? "1":"2")." -b -c -d -V630 -o"
		   ." save /dev/$_ $SRC/$New_Image/$_");
	}
	LOG("* Unmounting /mnt/smbfs\n");
	system("umount /mnt/smbfs >/dev/null 2>&1");
    }

    elsif($Dev && $Entity =~/Blank_Local_Admin_Passwd/i)
    {
	LOG("* Blanking local admin's password!\n");
	LOG("* Mounting /dev/$Dev"."1\n");
	system("umount /mnt/dos >/dev/null 2>&1");
	system("$NTFS_MNT /dev/$Dev"."1 /mnt/dos >/dev/null 2>&1; umount /mnt/dos >/dev/null 2>&1; mount -t captive-ntfs /dev/$Dev"."1 /mnt/dos");

	my $SAM = "/mnt/dos";
	opendir(DIR, $SAM);
	my @files = readdir(DIR);
	closedir(DIR);
	foreach(@files)
	{
	    if(m/^windows$/i)
	    {
		$SAM .= "/$_";
		last;
	    }
	}
	opendir(DIR, $SAM);
	@files = readdir(DIR);
	closedir(DIR);
	foreach(@files)
	{
	    if(m/^system32$/i)
	    {
		$SAM .= "/$_";
		last;
	    }
	}
	opendir(DIR, $SAM);
	@files = readdir(DIR);
	closedir(DIR);
	foreach(@files)
	{
	    if(m/^config$/i)
	    {
		$SAM .= "/$_";
		last;
	    }
	}
	opendir(DIR, $SAM);
	@files = readdir(DIR);
	closedir(DIR);
	foreach(@files)
	{
	    if(m/^SAM$/i)
	    {
		$SAM .= "/$_";
		last;
	    }
	}
	LOG("* Addressing SAM file [$SAM]\n");
	LOG("* Is local admin locked ?\n");
	system("chntpw -l $SAM >/tmp/BLA");
	my $Status = 0;
	open(DB, "/tmp/BLA");
	while(<DB>)
	{
	    if(m/\<Administrator\>/i && m/locked/i)
	    {
		++ $Status;
		last;
	    }
	}
	close(DB);
	my $Unlock = "";
	if($Status)
	{
	    $Unlock = "y\n";
	    LOG("* It was locked.\n");
	}
	system("echo -e \"$Unlock*\ny\ny\n\"|chntpw -u Administrator $SAM");
	LOG("* Unmounting /mnt/dos\n");
	system("umount /mnt/dos >/dev/null 2>&1");
    }

    elsif($Dev && $Entity =~/Backup_Local_Hard_Disk/i)
    {
        my %SMB = ();
        my $Try_Again = 1;

        while($Try_Again)
	{
            foreach("Server", "Share", "User", "Passwd", "Directory")
	    {
                $SMB{$_} = "";
            }

            my $cmd = 'dialog --inputbox "Enter a valid SMB Server IP '
                .'(eg. 192.168.0.10)" 8 51 2>/tmp/BLA';
            system($cmd);
            open(DB, "/tmp/BLA");
            while(<DB>)
	    {
                $SMB{Server} .= $_;
            }
            close(DB);
            $SMB{Server} =~s/^\/*//;
            $SMB{Server} =~s/^\\*//;

            $cmd = 'dialog --inputbox "Enter a valid SMB Share Name '
                .'(eg. myshare)" 8 51 2>/tmp/BLA';
            system($cmd);
            open(DB, "/tmp/BLA");
            while(<DB>)
	    {
                $SMB{Share} .= $_;
            }
            close(DB);
            $SMB{Share} =~s/^\/*//;
            $SMB{Share} =~s/^\\*//;
            $SMB{Share} =~s/\$/\\\$/g;

            $cmd = 'dialog --inputbox "Enter a valid username '
                .'(eg. mydomain\runner)" 8 51 2>/tmp/BLA';
            system($cmd);
            open(DB, "/tmp/BLA");
            while(<DB>)
	    {
                $SMB{User} .= $_;
            }
            close(DB);
            $SMB{User} =~s/\//\\\\/g;
            $SMB{User} =~s/\\/\\\\/g;

            $cmd = 'dialog --inputbox "Enter a valid password '
                .'(eg. runner)" 8 51 2>/tmp/BLA';
            system($cmd);
            open(DB, "/tmp/BLA");
            while(<DB>)
	    {
                $SMB{Passwd} .= $_;
            }
            close(DB);
            $SMB{Passwd} =~s/\\/\//;

            foreach("Server", "Share", "User", "Passwd")
	    {
                $SMB{$_} =~s/^\s*//;
                $SMB{$_} =~s/\s*$//;
            }

            LOG("* Unmounting /mnt/smbfs\n");
            system("umount /mnt/smbfs >/dev/null 2>&1");
            LOG("* Trying to mount //$SMB{Server}/$SMB{Share} (SMBFS)\n");
            system("smbmount //$SMB{Server}/$SMB{Share} /mnt/smbfs -o"
                   ." username=$SMB{User},password=\"$SMB{Passwd}\" >/tmp/out 2>&1");

            $Try_Again = 0;
            if(-e "/tmp/out")
	    {
                open(DB, "/tmp/out");
                while(<DB>)
		{
                    if(m/failed/i)
		    {
                        # 2nd chance (NAS sends false failures)
                        my $tmp = `df |grep smbfs |wc -l`;
                        $tmp =~s/\D//g;
                        unless($tmp)
			{
                            $Try_Again = 1;
                            LOG("\n* BAD Server, Share, User or Passwd. Try CIFS, or all again.\n");
                            sleep(3);
                        }
                    }
                }
                close(DB);
                unlink("/tmp/out");
            }

	    if($Try_Again)
	    {
		LOG("* Unmounting /mnt/smbfs\n");
		system("umount /mnt/smbfs >/dev/null 2>&1");
		LOG("* Trying to mount //$SMB{Server}/$SMB{Share} (CIFS)\n");
		system("mount -t cifs //$SMB{Server}/$SMB{Share} /mnt/smbfs -o"
		       ." username=$SMB{User},password=\"$SMB{Passwd}\" >/tmp/out 2>&1");

		$Try_Again = 0;
		if(-e "/tmp/out")
		{
		    open(DB, "/tmp/out");
		    while(<DB>)
		    {
			if(m/failed/i)
			{
			    # 2nd chance (NAS sends false failures)
			    my $tmp = `df |grep smbfs |wc -l`;
			    $tmp =~s/\D//g;
			    unless($tmp)
			    {
				$Try_Again = 1;
				LOG("\n* BAD Server, Share, User or Passwd. TRY AGAIN.\n");
				sleep(3);
			    }
			}
		    }
		    close(DB);
		    unlink("/tmp/out");
		}
	    }

            if(! $Try_Again)
	    {
                my $cmd = 'dialog --inputbox "Enter a directory where to save data '
                    .'(eg. \MyBackup\MyPC-20060601)" 8 51 2>/tmp/BLA';
                system($cmd);
		$SMB{Directory} = '';
                open(DB, "/tmp/BLA");
                while(<DB>)
		{
                    $SMB{Directory} .= $_;
                }
                close(DB);
                $SMB{Directory} =~s/^\s*//;
                $SMB{Directory} =~s/\s*$//;
                $SMB{Directory} =~s/\\/\//g;
                $SMB{Directory} =~s/^\/*//;
            }
        }

        unless(-d "/mnt/smbfs/$SMB{Directory}")
	{
            LOG("* Making directory //$SMB{Server}/$SMB{Share}/$SMB{Directory}\n");
            system("mkdir -p \"/mnt/smbfs/$SMB{Directory}\"");
        }

        my(@Partitions) = ();
        {
            my @Do = ('p', 'q');
            my $cmd = 'echo -e "';
            foreach(@Do)
	    {
                $cmd .= $_.'\n';
            }
            $cmd .= '" | fdisk /dev/'.$Dev.' 2>&1';
            my $out = `$cmd`;

            my(@lines) = split(/\n/, $out);
            foreach my $L (@lines)
	    {
                $L =~s/^\s*//;
                $L =~s/\s*$//;
                next unless($L =~/^\/dev/i);
                $L =~s/  / /g;
                $L =~s/  / /g;
                $L =~s/  / /g;
                $L =~s/  / /g;
                $L =~s/  / /g;
                my(@fields) = split(/ /, $L);
                next if($fields[$#fields] =~/extended/i);
                push(@Partitions, $fields[0]);
            }
        }

        foreach my $P (@Partitions)
	{
            my $devname = (split(/\//, $P))[2];
            LOG("\n* Saving partition [$P] to"
                ." [//$SMB{Server}/$SMB{Share}/$SMB{Directory}/$devname]\n");

            LOG("  * Unmounting /mnt/dos\n");
            system("umount /mnt/dos >/dev/null 2>&1");

            LOG("  * Mounting $P on /mnt/dos\n");
            system("mount $P /mnt/dos");

            LOG("  * Tarball-making\n");
            my $cmd = "cd /mnt/dos; tar --exclude=pagefile.sys --exclude="
		."\"System Volume Information\" --exclude=hiberfile.sys"
		." -cvf - *|gzip -1 - |split -b 2000000000 -"
		." \"/mnt/smbfs/$SMB{Directory}/$devname.tar.gz.x\"";
            LOG("    [$cmd]\a\a\n");
            unless(-e "/mnt/smbfs/$SMB{Directory}/$devname.tar.gz.xab")
	    {
                rename("/mnt/smbfs/$SMB{Directory}/$devname.tar.gz.xaa",
                       "/mnt/smbfs/$SMB{Directory}/$devname.tar.gz");
            }
            sleep(3);
            system($cmd);

            LOG("  * Unmounting /mnt/dos\n");
            system("umount /mnt/dos >/dev/null 2>&1");
        }

        LOG("\n* BACKUP has been done.\n");
        LOG("* Unmounting /mnt/smbfs\n");
        system("umount /mnt/smbfs >/dev/null 2>&1");
    }
}
else
{
    my @Label_CMD = ();

    opendir(DIR, "$SRC/$Entity");
    my @F = readdir(DIR);
    closedir(DIR);

    # Resolving symlinks
    #
    LOG("* Resolving possible symlinks\n");
    LOG("  * Before:\n");
    foreach(@F)
    {
        LOG("    * [$_]\n");
    }
    my @FF = ();
    foreach my $F (@F)
    {
        next if($F =~/^\.{1,2}/);
        if($F =~/\.symlink/i)
	{
            my $Link = "";
            open(DB, "$SRC/$Entity/$F");
            while(<DB>)
	    {
                $Link .= $_;
            }
            close(DB);
            $Link =~s/^\s*//;
            $Link =~s/\s*$//;
            $Link =~s/\\/\//g;
            LOG("  * Symlink. Points to [$Link]\n");
            if(-e "$SRC/$Entity/$Link")
            {
                push(@FF, "$SRC/$Entity/$Link");
            }
            else
            {
                LOG("    * [$SRC/$Entity/$Link] can't be found!!!\n");
                sleep(5);
                next;
            }
        }
	else
	{
	    # Added for cciss compatabililty (HP SmartArray). Idem for ida and rd.
	    #
            if($F =~/(cciss|ida|rd)/i)
	    {
		opendir(DIR, "$SRC/$Entity/$F");
		my(@tmp) = readdir(DIR);
		closedir(DIR);
		foreach(@tmp)
		{
		    next if(m/^\.{1,2}$/);
		    push(@FF, "$SRC/$Entity/$F/$_");
		}
		closedir(DIR);
	    }
	    #
	    # All non-CCISS/rd/ida cases
	    #
	    else
	    {
		push(@FF, "$SRC/$Entity/$F");
            }
	}
    }
    LOG("  * After:\n");
    foreach(@FF)
    {
        LOG("    * [$_]\n");
    }

    # Several possible scenarii to tackle.
    #
    my $Action = "Ghost";
    foreach(@FF)
    {
        my @fields = split(/\//, $_);
        my $F = $fields[-1];

	# Section added for cciss compatability (HP SmartArray). Same for ida and rd.
	#
	if($fields[-2] =~/(cciss|ida|rd)/i)
	{
	    $F = $fields[-2]."/".$fields[-1];
	    chomp($F);
	}

	# Search for both standard linux devices and cciss/rd/ida devices to restore
	#
	if($F =~/^[hs]d[abcde]$/ || $F =~/^(cciss|rd|ida)\/c\d{1}d\d{1,2}$/)
	{
            $Action = "Mixed";
            last;
        }
    }

    if($Action eq "Ghost")
    {
        LOG("* Classical Ghost-like image!\n");
    }
    elsif($Action eq "Mixed")
    {
        LOG("* Mixed image!\n");
    }

    if($Action eq "Ghost" || $Action eq "Mixed")
    {
        foreach my $FF (@FF)
	{
            my @fields = split(/\//, $FF);
            my $F = $fields[-1];
	    #
	    # Section added for cciss compatability (HP SmartArray), + rd + ida.
	    #
	    if($fields[-2] =~/(cciss|rd|ida)/i)
	    {
		$F = $fields[-2]."/".$fields[-1];
		chomp($F);
	    }
	    #
	    # Search for both standard linux devices and cciss/rd/ida devices to restore
	    #
            if($F =~/^[hs]d[abcde]$/ || $F =~/^(cciss|ida|rd)\/c\d{1}d\d{1,2}$/)
	    {
                LOG("  * Restore /dev/$F\n");
                my $cmd = "dd if=$FF of=/dev/$F";
                system($cmd);
                $cmd = 'echo -e "w\n" | fdisk /dev/'.$F.' 2>&1';  # Write dd's action
                my $out = `$cmd`;
                LOG("[$out]\n");
		++ $Have_Restored;
                last;
            }
            elsif($F =~/^bios$/i)
	    {
                LOG("  * Restoring CMOS => bios");
                system("echo 2|cmospwd -r $FF");
            }
        }
    }

    # The mixed case. Must:
    # - Partition according to instructions
    # - Apply either partimages, either untarrings (next scope)
    #
    if($Action eq "Mixed")
    {
        foreach my $FF (@FF)
        {
            my @fields = split(/\//, $FF);
            my $F = $fields[-1];
	    #
	    # Section added for cciss compatability (HP SmartArray), + rd and ida.
	    #
	    if($fields[-2] =~/(cciss|rd|ida)/i)
	    {
		$F = $fields[-2]."/".$fields[-1];
		chomp($F);
	    }
	    #
	    # Search for both standard linux devices and cciss/rd/ida devices to restore
	    #
            if($F =~/^[hs]d[abcde]\.part$/i || $F =~/^(cciss|rd|ida)\/c\d{1}d\d{1,2}\.part$/)
            {
                my $Dev = $F;
                $Dev =~s/\.part$//i;

                LOG("  * Found [$F] => partitioning instructions.\n");
                my @fdisk = ('d', 1, 'd', 2, 'd', 3, 'd', 4, 'd', 5, 'd', 6);
                my $cnt = 0;
                open(DB, $FF);
                while(<DB>)
		{
                    s/^\s*//;
                    s/\s*$//;
                    s/\s/ /g;
                    while(m/  /)
		    {
                        s/  / /g;
                    }
                    next if(m/^\;/);
                    my @fields = split(/ /, $_);
                    next unless($#fields >= 2);
                    my($PNumber, $PSize, $PType, $PLabel, $PBoot) = @fields;

                    push(@fdisk, 'n', 'p', $PNumber, '');
                    if($PSize eq "+")
		    {
                        push(@fdisk, '');
                    }
		    else
		    {
                        push(@fdisk, "+$PSize");
                    }
                    push(@fdisk, 't');
                    if($cnt > 0)
		    {
                        push(@fdisk, $PNumber);
                    }
                    push(@fdisk, $PType);
                    if($PBoot eq "*")
		    {
                        push(@fdisk, 'a', $PNumber);
                    }

                    if($PLabel)
		    {
                        push(@Label_CMD, "ntfslabel -f /dev/$Dev$PNumber $PLabel");
                    }

                    ++ $cnt;
                }
                close(DB);
                push(@fdisk, 'w');

                my $cmd = 'echo -e "';
                foreach(@fdisk)
		{
                    $cmd .= $_.'\n';
                }
                $cmd .= '" | fdisk /dev/'.$Dev.' 2>&1';
                LOG("    * [$cmd]\n");
                system($cmd);
            }
        }
    }

    if($Action eq "Ghost" || $Action eq "Mixed")
    {
        foreach my $FF (@FF)
        {
            my @fields = split(/\//, $FF);
            my $F = $fields[-1];
            my $Node = $F;

            unless($F =~/\.000$/ || $F =~/\.zip$/i)
            {
                next;
            }

            LOG("  * Restore [/dev/?? from $F] with [$FF]\n");

            if($FF =~/\.000$/)
            {
                my $Dev = $F;
                $Dev =~s/\.\d{3}$//;
                system("umount /dev/$Dev >/dev/null 2>&1");
                my $cmd = "partimage -f3 -b -c -d -o restore /dev/$Dev $FF";
                LOG("    * [$cmd]\n");
                system($cmd);
            }
            elsif($FF =~/\.zip$/i)
            {
                my $Dev = "";
                {
                    my @f1 = split(/\./, $F);
                    $Dev = $f1[0];
                }
                my $TType = "";
                {
                    my $tmp = $Dev;
                    $tmp =~s/\d+$//;
                    my $out = `fdisk -l /dev/$tmp | grep \"^/dev/$Dev\"`;
                    $out =~s/\+//g;
                    $out =~s/\*//g;
                    $out =~s/^\s*//;
                    $out =~s/\s*$//;
                    while($out =~/  /)
		    {
                        $out =~s/  / /g;
                    }
                    my @fields = split(/ /, $out);
                    if($fields[4] eq "7")
		    {
                        $TType = "-t $NTFS_MNT_TYPE";
                    }
                }

                foreach("umount /mnt/dos",
                        "mkntfs -Q -F /dev/$Dev",
                        "ntfsfix /dev/$Dev")
                {
                    LOG("    * [$_]\n");
                    system($_);
                }

                # The tarball might be empty. Then, save time.
                unless(-z $FF)
		{
                    foreach("$NTFS_CAP; mount $TType /dev/$Dev /mnt/dos >/dev/null 2>&1; umount /mnt/dos >/dev/null 2>&1; mount $TType /dev/$Dev /mnt/dos",
                            "cd /mnt/dos; unzip $FF; sleep 2",
                            "cd /; umount /mnt/dos; sleep 2")
                    {
                        LOG("    * [$_]\n");
                        system($_);
                    }
                }
            }
            else
            {
                LOG("    * Dunno what to do with [$FF]. Probably safe.\n");
            }
        }
    }

    if($Action eq "Mixed")
    {
        foreach(@Label_CMD)
	{
            LOG("    * [$_]\n");
            system($_);
        }
    }
}


# Unmount the stuff.
#
LOG("* Unmounting [$SRC]\n");
system("umount $SRC >/dev/null 2>&1");


# Sometimes, users might create images with a small hdd-equipped station,
# and restore it on stations with bigger hdds. They might use a hda.part
# file to specify bigger parts. As a result, we can end up with 10-GB
# filesystems in a 40-GB partition... We can handle this easily. Yet,
# we'll help only as far as NTFS filesystems are involved.
#
# Note: after testing, not so sure NTFS needs it... doing it anyway.
#
if($Have_Restored)
{
    LOG("* There has been a restoration... let's make sure no partition\n");
    LOG("  is bigger than the filesystem it contains (NTFS only)\n");

    my(@NTFS_Devs_To_Check) = ();

    my $out = `fdisk -l /dev/$Dev[0]`;
    my(@L) = split(/\n/, $out);
    foreach my $Line (@L)
    {
	next unless($Line =~/^\//);
	$Line =~s/\*//g;
	$Line =~s/\+//g;
	$Line =~s/\s+/ /g;
	my(@Fields) = split(/ /, $Line);
	if($Fields[4] eq "7")
	{
	    push(@NTFS_Devs_To_Check, $Fields[0]);
	}
    }

    foreach my $D (@NTFS_Devs_To_Check)
    {
	LOG("  - NTFS part to check: [$D]\n");
	my $out = `ntfsresize -i -f $D`;
	my(@Lines) = split(/\n/, $out);
	my $CurVol = 0;
	my $CurDev = 0;
	foreach(@Lines)
	{
	    if(m/Current volume size/i)
	    {
		$CurVol = $_;
	    }
	    elsif(m/Current device size/i)
	    {
		$CurDev = $_;
	    }
	}
	foreach($CurVol, $CurDev)
	{
	    s/^.* ([0-9]+) bytes.*$/$1/;
	}
	LOG("    Current volume size: [$CurVol]\n");
	LOG("    Current device size: [$CurDev]\n");

	if($CurVol < $CurDev)
	{
	    LOG("    We can augment the volume size!\n");
	    my $cmd = "ntfsresize -f -s $CurDev $D >>/tmp/x.log 2>&1";
	    LOG("    Cmd: [$cmd]\n");
	    system($cmd);
	}
    }
}



# The End
#
Quit();



sub LOG
{
    my $Say = shift;
    print $Say;
    open(LOG, ">>/tmp/x.log");
    print LOG $Say;
    close(LOG);
}



sub ID_To_Type
{
    my($ID) = shift;
    return unless($ID);

    my %Corr = (
	"0" => "Empty",
	"1e" => "Hidden W95 FAT1",
	"80" => "Old Minix",
	"be" => "Solaris boot",
	"1" => "FAT12",
	"24" => "NEC DOS",
	"81" => "Minix / old Lin",
	"bf" => "Solaris",
	"2" => "XENIX root",
	"39" => "Plan 9",
	"82" => "Linux swap / So",
	"c1" => "DRDOS/sec (FAT-",
	"3" => "XENIX usr",
	"3c" => "PartitionMagic",
	"83" => "Linux",
	"c4" => "DRDOS/sec (FAT-",
	"4" => "FAT16 <32M",
	"40" => "Venix 80286",
	"84" => "OS/2 hidden C:",
	"c6" => "DRDOS/sec (FAT-",
	"5" => "Extended",
	"41" => "PPC PReP Boot",
	"85" => "Linux extended c7 Syrinx",
	"6" => "FAT16",
	"42" => "SFS",
	"86" => "NTFS volume set",
	"da" => "Non-FS data",
	"7" => "HPFS/NTFS",
	"4d" => "QNX4.x",
	"87" => "NTFS volume set",
	"db" => "CP/M / CTOS / .",
	"8" => "AIX",
	"4e" => "QNX4.x 2nd part",
	"88" => "Linux plaintext",
	"de" => "Dell Utility",
	"9" => "AIX bootable",
	"4f" => "QNX4.x 3rd part",
	"8e" => "Linux LVM",
	"df" => "BootIt",
	"a" => "OS/2 Boot Manag",
	"50" => "OnTrack DM",
	"93" => "Amoeba",
	"e1" => "DOS access",
	"b" => "W95 FAT32",
	"51" => "OnTrack DM6 Aux",
	"94" => "Amoeba BBT",
	"e3" => "DOS R/O",
	"c" => "W95 FAT32 (LBA)",
	"52" => "CP/M",
	"9f" => "BSD/OS",
	"e4" => "SpeedStor",
	"e" => "W95 FAT16 (LBA)",
	"53" => "OnTrack DM6 Aux",
	"a0" => "IBM Thinkpad hi",
	"eb" => "BeOS fs",
	"f" => "W95 Ext'd (LBA)",
	"54" => "OnTrackDM6",
	"a5" => "FreeBSD",
	"ee" => "EFI GPT",
	"10" => "OPUS",
	"55" => "EZ-Drive",
	"a6" => "OpenBSD",
	"ef" => "EFI (FAT-12/16/",
	"11" => "Hidden FAT12",
	"56" => "Golden Bow",
	"a7" => "NeXTSTEP",
	"f0" => "Linux/PA-RISC b",
	"12" => "Compaq diagnost",
	"5c" => "Priam Edisk",
	"a8" => "Darwin UFS",
	"f1" => "SpeedStor",
	"14" => "Hidden FAT16 <3",
	"61" => "SpeedStor",
	"a9" => "NetBSD",
	"f4" => "SpeedStor",
	"16" => "Hidden FAT16",
	"63" => "GNU HURD or Sys",
	"ab" => "Darwin boot",
	"f2" => "DOS secondary",
	"17" => "Hidden HPFS/NTF",
	"64" => "Novell Netware",
	"b7" => "BSDI fs",
	"fd" => "Linux raid auto",
	"18" => "AST SmartSleep",
	"65" => "Novell Netware",
	"b8" => "BSDI swap",
	"fe" => "LANstep",
	"1b" => "Hidden W95 FAT3",
	"70" => "DiskSecure Mult",
	"bb" => "Boot Wizard hid",
	"ff" => "BBT",
	"1c" => "Hidden W95 FAT3",
	"75" => "PC/IX"
    );
    if(defined($Corr{$ID}))
    {
	return($Corr{$ID});
    }
    else
    {
	return("Not found");
    }
}



sub Quit
{
    LOG("* Quitting...\n");

    # Reboot.
    #
    if($After_Completion =~/reboot/i)
    {
	LOG("  Reboot within 10 seconds !!\a\a\a\n\n");
    }
    elsif($After_Completion =~/shutdown/i)
    {
	LOG("  Shutdown within 10 seconds !!\a\a\a\n\n");
    }
    else
    {
	LOG("  Give the user a shell.\a\a\a\n\n");
    }
    if($SRC =~/cdrom/i)
    {
	LOG("  Hey! Don't forget thy DVD!\a\a\a\n\n");
	system("eject /dev/$CD_Dev >/dev/null 2>&1");
	system("eject /mnt/cdrom >/dev/null 2>&1");
    }
    if($After_Completion =~/reboot/i)
    {
	sleep(10);
	system("shutdown -r now");
    }
    elsif($After_Completion =~/shutdown/i)
    {
	sleep(10);
	system("shutdown -h now");
    }
    else
    {
	system("reset; clear");
	print "\nYou are now given the possibility to login to the shell.\n";
	print "Please, be aware that PING log is stored in /tmp/x.log.\n";
	print "Log in as root, hit ENTER when asked for the password.\n\n\a\a\a";
	exit;
    }
}




__END__

* 1.12
  - Added a possibility to make the backup/image to another local drive.
    Not to the same drive the backup/image is taken from (another part).
    Should be feasible in a future version (by resizing & parting).
    Means right now that we try to inventory hda, hdb, hdc, sda, sdb, sdc.
    Maybe not exhaustive; this is first try.
  - No more need to hit space then enter. Modified the menu...
  - If the manual network connection went wrong, give the ifconfig output.
  - Give smbmount output too.
  - smbmount now passes a "password" (with quotes) -- thx Gedatsu.
  - Share's password is now hidden (new dialog installed, thx Fredz).
  - Looks for a /etc/ping.conf file to find network and smb parameters.
    If not found, then ask.
  - Partimage now generates 630 MB files. Better if a DVD is the target
    (7x630 = 4551 < 4.7 GB), and better for Captive-NTFS which fails for
    some reason creating files bigger than 1 GB.
  - After restoring, check if an image was smaller than disk capacity,
    and maximize. ping.conf keyword to add. NTFS only -- others need no help.
  - Stop discovering local hdd  'src', 'srd', 'sgc', 'sgd',
    'sra', 'srb', 'sga', 'sgb'. It has been reported that fdisk /dev/sga
    was hanging the system sometimes (thanks Sigurdi).
  - Proposes to choose between gzip and bzip2.
  - Ejects the CD when used (thx, Curtis).
  - Added support for HP SmartArray (/dev/cciss/c0d0 device)
    fdisk => Disk /dev/cciss/c0d0: 73.3 GB, 73372631040 bytes
    (thanks, Codd)
  - Fully automatic if /AUTO file found on the root of a CD/DVD.
  - When smbmount fails, try mount -t cifs (Windows Server 2003 case, related
    to AD security) -- thx, Arckane.
    => mount -t cifs //server/share /mnt/point -o user=$username,domain=$domain,password=$password
  - Now the user can specify the behaviour at the completion of the job.
    Can either reboot, either give the user a bash shell. Or shutdown.
    A new entry in /etc/ping.conf is supported concerning the feature:
    After_Completion = reboot|shell|shutdown
  - Bug correction: we were looking for a /mnt/cdrom/^.da$ file, and in one specific case,
    a user built an image with hdc.001, 002... files. Replacing with ^[hs]d[abcde]$ :)
  - Added support for more RAID devices (/dev/ida/cXdY and /dev/rd/cXdY).

  - TODO: propose to generate a ping.conf file according to filled forms,
    and propose to regenerate a new initrd.gz and iso file.
  - TODO: propose to record a hda.part file, and only restore part from it (no hda file).
  - TODO: linux => dont try to record swap parts!
  - TODO: if part type not handled, use dd
  - TODO: if LVM, use dd
  - TODO: spare-cd/dvd :

 Directory of C:\Partimage\T1

16/03/2007  11:36    <DIR>          .
16/03/2007  11:36    <DIR>          ..
07/03/2007  16:35               384 bios
07/03/2007  16:35            10 240 hda
07/03/2007  16:39       660 608 577 hda1.000
07/03/2007  16:45       660 658 687 hda1.001
07/03/2007  16:50       660 575 171 hda1.002
07/03/2007  16:54       660 627 998 hda1.003
07/03/2007  16:57       432 885 573 hda1.004
               7 File(s)  3 075 366 630 bytes
               2 Dir(s)  46 649 544 704 bytes free

C:\Partimage\T1>perl -e "print 660600000 * 5"
3303000000
C:\Partimage\T1>perl -e "print 660600000 * 6"
3963600000
C:\Partimage\T1>perl -e "print 660600000 * 7"
4624200000

  - TODO:
We could stop using partimage, and make use of tar+gz, then many things would be possible, like exploring the backups, etc. BUT, and this is a big but, ACLs and file attributes would be lost, unless a windows tool like icacls.exe being used before and after the linux step. Maybe an idea for later, but I dislike the idea of having things done under Windows. (Note that there would be no such problem when backing up and restoring linux systems, for example; so, the choice could be proposed to the user when Creating a new image, someday.)

Another way could be to give the user the possibility to have the system partition resized to the maximum before being partimaged. Thus, it could be easily restored to almost any partition afterwards. We could even restore the size of the partition to its original size after backing it up. I like this idea...

Right now, you could, A_Null, ntfsresize + fdisk, and backup, your partition manually. The 1.12 presently knows that if a partition has been restored to a bigger space, it has to use ntfsresize afterwards so to exploit all available space. So, only the backup stage would be manual, and not the restoring.








	my $cmd = 'dialog --colors --checklist "\Zb\Z7Choose your future'
	    .' available languages\n\n'
	    .'\ZnDepending on the version of Windows you are going to'
	    .' install, several languages (MUI Packs) might be available.'
	    .' You can choose now what languages you want us to schedule'
	    .' for installation. And, even if your Windows version is'
            .' localized and not MUI-capable, make your choice, so at'
            .' least we'."'".'ll try to install software in the right languages.\n\n"'
	    .' 20 70 7 "English (Mandatory for'
	    .' all MUI Windows versions.)" "" on "French" "" off'
	    .' "Spanish" "" off "Italian" "" off "Japanese" "" off'
	    .' "German" "" off "Hebrew" "" off "Simplified Chinese" "" off'
	    .' "Traditional Chinese" "" off "Korean" "" off'
	    .' "Arabic" "" off 2>/tmp/checklist.tmp';


    system($cmd);

    my $tmp = "";
    open(DB, "/tmp/checklist.tmp");
    while(<DB>) {
        $tmp .= $_;
    }
    close(DB);
    unlink("/tmp/checklist.tmp");

    $tmp =~s/\s*$//;
    $tmp =~s/^\s*//;
    my @fields = split(/\//, $tmp);
    foreach(@fields) {
        $MUI{"$_"} = 1;
        LOG("  * Wanted MUI pack: [$_]\n");
    }
