print STDERR wrap("\nUnable to find the system wide VMware installation file. You may want to re-install VMware on your computer.\n");
exit(1);
}
$vmware_loop = "";
open(VMCONF, $vmware_config);
while (defined($line = <VMCONF>)) {
chop $line;
if ($line =~ /^[ \t]*loop\.fullpath[ \t]*=[ \t]*/) {
@parts = split(/\"/, $line);
$vmware_loop = $parts[1];
}
}
close(VMCONF);
if ($vmware_loop eq "") {
print STDERR wrap("\nThis script can not find a correctly formatted loop.fullpath entry in the " . $vmware_config . " file. You may want to re-install VMware on your computer.\n");
print wrap("\nUnable to unmount the Network Block Device on the " . $mount_pt . " mount point. Please make sure that no process uses " . $mount_pt . " as its current directory or is accessing a file under this directory.\n\nUsing another terminal, you can continue to browse your Virtual Hard Disk partition in " . $mount_pt . ". Hit Control-C again in this terminal when done.\n");
return;
}
} else {
print STDERR wrap("\nIt seems like somebody unmounted the " . $mount_pt . " mount point in my back. I was about to do it anyway.\n");
}
forward_kill();
}
# Retrieve the filesystem of the partition from the partition type and Id
sub get_partition_fs {
my $tmpfile = $_[0];
my $part_nb = $_[1];
my $line;
my @parts;
my $offset;
my $part_type;
my $part_id;
if (not open(OUTPUT, $tmpfile)) {
printf STDERR wrap("\nUnable to open the temporary file containing the partition table.\n");
return "";
}
$part_type = "";
$part_id = "";
$line = <OUTPUT>;
$line = <OUTPUT>;
$line = <OUTPUT>;
while(defined($line = <OUTPUT>)) {
chop $line;
@parts = split(/[ \t]+/, $line);
# In case the line begins with a whitespace
if ($parts[0] eq "") {
$offset = 1;
} else {
$offset = 0;
}
if ($part_nb == $parts[$offset]) {
$part_type = $parts[$offset + 3];
$part_id = $parts[$offset + 4];
last;
}
}
close(OUTPUT);
if (($part_type eq "") || ($part_id eq "")) {
printf STDERR wrap("\nUnable to retrieve the partition in the partition table.\n");
print STDERR wrap("\nUnable to retrieve the filesystem of the partition (the partition type is " . $part_type . " and the partition Id is " . $part_id . "). Please file an incident with VMware at http://www.vmware.com/forms/Incident_Login.cfm by copying this error message.\n");
print wrap("\nTrying to load the Network Block Device driver kernel module... ");
if (system(shell_string($modprobe) . " nbd > /dev/null")) {
print "Failure.\n";
print STDERR wrap("\nIf you are not an experimented Linux user, you may want to upgrade your Linux distribution and re-run this script.\n\nIf you are an experimented Linux user, you may want to re-compile your kernel. Use a kernel version 2.1.101 or higher, and set the CONFIG_BLK_DEV_NBD option (which you can find under \"Block devices\"->\"Network block device support\") to \"y\" or \"m\". If you don't want to mess with kmod (the kernel module loader formerly known as kerneld), we recommend to use \"y\". Once you have rebooted your new kernel, re-run this script.\n");
exit(1);
}
print "Success.\n";
}
# Output the partition table in a temporary file (so that it doesn't
# interfere with user interaction). Do that before mapping the
# virtual hard disk partition to an nbd to avoid the deadlock
# Second, try to deduce the type from the partition table
print wrap("\nIf you know the filesystem of the partition you want to mount, you can provide it using the -t command line option. Since you haven't done so, this script is going to try to determine the filesystem of the partition based on the partition type and id.\n");
print wrap("\nUnable to mount the Network Block Device on the " . $mount_pt . " mount point. Please make sure that nothing is currently using the mount point and that your kernel supports the partition type you want to mount before re-running this script.\n");
forward_kill();
close(LOOP);
exit(1);
}
# Install the SIGINT handler
$SIG{INT} = \&sigint_handler;
print wrap("\nUsing another terminal, you can now browse your Virtual Hard Disk partition in " . $mount_pt . ". Hit Control-C in this terminal when done.\n");
for (;;) {
$char = getc(LOOP);
if (not defined ($char)) {
# EOF
last;
}
# Display the output of the program so that the user can interact with
# the hints
print $char;
}
# Child has exited (perhaps because we killed it)
close(LOOP);
# Reset the handler
$SIG{INT} = 'DEFAULT';
}
# Display the partition table of a virtual disk
sub show_partition_table {
my $vhd = $_[0];
if (system(shell_string($vmware_loop) . " -q -p " . shell_string($vhd))) {
print STDERR wrap("\nUnable to invoke " . $vmware_loop . ". You may want to re-install VMware.\n");
exit(1);
}
}
# Display a usage string on stderr, and exit
sub usage {
print STDERR "\nUsage: " . $0 . "\n" .
"\t-p : Print the partition table\n" .
"\tdisk : Name of the Virtual Hard Disk file\n" .
"or\n" .
"\tdisk : Name of the Virtual Hard Disk file\n" .
"\tpartition : Number of the partition\n" .
"\t[-t type] : Partition type\n" .
"\t[-o options]: Partition mount options(s)\n" .
"\tmount-point : Directory where to mount the partition\n";
exit(1);
}
# Where the real work is done
sub main {
# print partition table
my $print_mode;
# filesystem type
my $type_value;
# mount options
my $options_value;
# mandatory arguments
my @arguments;
my $i;
my $nb;
# Scan the command line
@arguments = ();
$print_mode = 0;
$type_value = "";
$options_value = "";
for ($i = 0; $i < $#ARGV + 1; $i++) {
if ($ARGV[$i] eq "--") {
last;
}
if ($ARGV[$i] eq "-p") {
$print_mode = 1;
next;
}
if ($ARGV[$i] eq "-t") {
$i++;
if ($i >= $#ARGV + 1) {
print STDERR wrap("\nThe -t command line option requires a valid filesystem type as argument. See 'man mount' for filesystem types supported by your system.\n");
usage();
}
$type_value = $ARGV[$i];
next;
}
if ($ARGV[$i] eq "-o") {
$i++;
if ($i >= $#ARGV + 1) {
print STDERR wrap("\nThe -o command line option requires at least one valid mount option as argument. See 'man mount' for options supported by your filesystem.\n");
usage();
}
$options_value = $ARGV[$i];
next;
}
push @arguments, $ARGV[$i];
}
# Check the options validity
if (($print_mode == 1) && (not ($type_value eq ""))) {
print STDERR wrap("\nOptions -p and -t are mutually exclusive.\n");
usage();
}
if (($print_mode == 1) && (not ($options_value eq ""))) {
print STDERR wrap("\nOptions -p and -o are mutually exclusive.\n");
print STDERR wrap("\nPlease re-run this script as the super user.\n");
exit(1);
}
# Force the path to reduce the risk of using "modified" external helpers
# If the user has a special system setup, he will be prompted for the
# proper location anyway
$ENV{'PATH'} = "/bin:/usr/bin:/sbin:/usr/sbin";
initialize_external_helpers();
if (Kernel_RunningVersion() < Kernel_MakeVersion(2, 1, 101)) {
print STDERR wrap("\nYour Linux kernel is too old to run this script. Please boot a Linux kernel version 2.1.101 or higher (including 2.2.x) and re-run this script.\n");