#!/usr/bin/perl -w # $Id: iso_test,v 1.6 1999/09/23 18:19:23 jabrown Exp $ # Jeff Brown # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # This is meant as a quick way to allow users to test ISO images. It is # dangerous to allow users to mount and umount things, though. my $operating_sys = $^O; my $mount_default = "/mnt"; my $prog_name = "iso_test"; my $fallback_shell = "/bin/sh"; my $freebsd_vnode_dev = "/dev/vn0c"; my $linux_loop_dev = "/dev/loop0"; $ENV{'PATH'}="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"; sub usage_long { print STDERR "Usage: ${prog_name} [-mount PATH] imagefile.iso\n" . "\n" . "This will attempt to mount an ISO9660 filesystem image. If the mount is\n" . "successful, a shell will be opened to allow the user to operate on the\n" . "files. Once the shell is closed, the image will be unmounted.\n" . " -mount PATH: attempt the mount at PATH. [default=${mount_default}]\n"; exit 1; } sub usage_short { print STDERR "${prog_name}: invalid command line. Use \"${prog_name} -h\" for usage info.\n"; exit 1; } my $iso_fname; my $mount_point; undef $iso_fname; undef $mount_point; if ($#ARGV < 0) { usage_short; } elsif (scalar(grep(/^${ARGV[0]}/, ("-h", "-help", "-?"))) > 0) { usage_long; } while ($#ARGV >= 0) { $arg = shift(@ARGV); if ($arg eq "-mount") { $arg = shift(@ARGV); if (defined($arg)) { $mount_point = $arg; } else { usage_short; } } elsif (!defined($iso_fname)) { # No leading "-" since that may confuse vnconfig if ($arg =~ /^-/) { print STDERR "${prog_name}: Input name may not begin with " . "'-' ('$arg')\n"; exit 1; } $iso_fname = $arg; } else { usage_short; } } if (!defined($mount_point)) { $mount_point = $mount_default; } if (!defined($iso_fname)) { usage_short; } $pid = fork(); if (!defined($pid)) { print STDERR "${prog_name}: fork() failed: $!\n"; exit 1; } elsif ($pid == 0) { # Child -- drop any suid/sgid $> = $<; $) = $(; if (! -r $iso_fname) { print STDERR "${prog_name}: cannot read input file '${iso_fname}'\n"; exit 1; } if (! -r $mount_point) { print STDERR "${prog_name}: cannot read mount directory " . "'${mount_point}'\n"; exit 1; } exit 0; } else { # Parent if ((waitpid($pid, 0) == -1) || ($? != 0)) { print STDERR "${prog_name}: access check failed, exiting...\n"; exit 1; } # If the directory was readable as the user, assume it's kosher. $mount_point =~ /(.+)/; $mount_point = $1; } sub do_shell { undef $my_shell; if (defined($ENV{'SHELL'})) { if ($ENV{'SHELL'} =~ m:^([/-\@\w.]+)$:) { $my_shell = $1; } else { print STDERR "${prog_name}: \$SHELL doesn't look right; "; } } else { print STDERR "${prog_name}: \$SHELL not defined; "; } if (!defined($my_shell)) { print STDERR "falling back to $fallback_shell.\n"; $my_shell = $fallback_shell; } @cmd_line = ("$my_shell"); if ($< == 0) { print STDERR "${prog_name}: I don't like running shells as r00t" . ", sorry.\n"; return; } print "${prog_name}: mount on ${mount_point} successful, " . "starting shell...\n"; print "\n" . "Please use this shell to inspect the ISO9660 filesystem; exit this " . "shell when\n" . "you are done to unmount the image. DO NOT erase or otherwise modify" . " the image\n" . "until it is unmounted, or you are asking for trouble.\n" . "\n"; $pid = fork(); if (!defined($pid)) { print STDERR "${prog_name}: fork() failed: $!\n"; } elsif ($pid == 0) { # Child -- drop any suid/sgid $> = $<; $) = $(; if (!chdir($mount_point)) { print STDERR "${prog_name}: could not chdir to '${mount_point}'\n"; } exec(@cmd_line) || print STDERR "${prog_name}: shell exec failed: $!\n" . " command was: @cmd_line\n"; exit 1; } else { # Parent waitpid($pid, 0); } print "${prog_name}: shell finished, unmounting ${mount_point}...\n"; } if ($operating_sys eq "freebsd") { @cmd_line = ("vnconfig", "$freebsd_vnode_dev", "$iso_fname"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: vnconfig failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; exit 1; } @cmd_line = ("mount", "-t", "cd9660", "-o", "nodev,nosuid,rdonly", "$freebsd_vnode_dev", "$mount_point"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: mount failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; } else { do_shell; @cmd_line = ("umount", "-f", "$mount_point"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: umount failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; } } @cmd_line = ("vnconfig", "-u", "$freebsd_vnode_dev"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: vnconfig failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; exit 1; } } elsif ($operating_sys eq "linux") { @cmd_line = ("mount", "-t", "iso9660", "-o", "nodev,nosuid,ro,loop=${linux_loop_dev}", "$iso_fname", "$mount_point"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: mount failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; } else { do_shell; @cmd_line = ("umount", "$mount_point"); if ($stat = system(@cmd_line)) { print STDERR "${prog_name}: umount failed, status=" . ($stat >> 8) . "\n" . " command was: @cmd_line\n"; } } } else { print STDERR "${prog_name}: unrecognized operating system " . "'${operating_sys}'\n"; exit 1; }