: # feed this into perl -w eval 'exec perl -w -S $0 ${1+"$@"}' if 0; # # TODO: # Keep track of "inode" number to reconstruct hard links. # use strict; use Getopt::Long; use File::Copy; use Time::Local; my %months; $months{'Jan'} = 0; $months{'Feb'} = 1; $months{'Mar'} = 2; $months{'Apr'} = 3; $months{'May'} = 4; $months{'Jun'} = 5; $months{'Jul'} = 6; $months{'Aug'} = 7; $months{'Sep'} = 8; $months{'Oct'} = 9; $months{'Nov'} = 10; $months{'Dec'} = 11; my $help = 0; if (! GetOptions("help|H|?" => \$help)) { die "See isox --help for usage info.\n"; } if ($help) { print "isox - extract files from iso image to a directory usage: isox [--help] isofile directory --help Print this message and exit. Uses the isoinfo utility to extract the directory structure and files from an iso image, creating directory and storing all the files in it.\n"; exit(0); } if (scalar(@ARGV) != 2) { die "Must have exactly two arguments, run with --help for usage.\n"; } if (! -r $ARGV[0]) { die "Cannot read iso file: $!\n"; } if (-e $ARGV[1]) { die "$ARGV[1] already exists, will not overwrite.\n"; } # The dirlist array will contain all the directory names and permission # strings and timestamp for each directory. my @dirlist; # Much like dirlist, the filelist array will contain all the file names # and permission strings, and timestamp. my @filelist; # translate ls -l style permission string into a mode value # sub permval { my $perms = shift; $perms=~s/[d-]/0/g; $perms=~s/[^0]/1/g; return oct("0b$perms"); } # Run isoinfo to read the list of directories and files and build up # the dirlist and filelist arrays... my $fh; my $lastdirname; my $perms; my $file; my $month; my $day; my $year; my $stamp; open($fh, '-|', "isoinfo -l -R -i '$ARGV[0]'") || die "Cannot run command isoinfo -l -R -i '$ARGV[0]' : $!\n"; while (<$fh>) { chomp; if (/^Directory listing of (.+)$/) { $lastdirname = $1; } elsif (/^(\S+)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\S+)\s+(\d+)\s+(\d+)\s+\[\s*\d+\s+\d+\] (.+)$/) { $perms = $1; $month = $2; $day = $3; $year = $4; $file = $5; # Sigh.. The isoinfo program apparently adds 1 space to the end of # all the file names, so chop it off if there is a space there. if ($file=~/\s+$/) { chop($file); } # Unfortunately isoinfo won't tell us more than the day, so # midnight is as close as we can get to the time. $stamp = timelocal(0,0,0,$day+0,$months{$month},$year+0); if ($perms=~/^d/) { if ($file eq ".") { push(@dirlist, [ $lastdirname, $perms, $stamp ]); } } else { push(@filelist, [ "${lastdirname}$file", $perms, $stamp ]); } } } close($fh); # Now run through the dirlist, creating all the directories writable # by me (so I have permission to write the files). my $root=$ARGV[1]; foreach $_ (@dirlist) { $file = ${$_}[0]; $file = "${root}$file"; if (! mkdir($file, 0700)) { die "Unable to create directory $file : $!\n"; } } # Once the directories are there, we can write the files by extracting # each one using isoinfo and File::Copy to write stdout from isoinfo # to disk. foreach $_ (@filelist) { $file = ${$_}[0]; $perms = ${$_}[1]; $stamp = ${$_}[2]; print "Extracting: $file ...\n"; my $origmask = umask(077); open($fh, '-|', "isoinfo -R -i '$ARGV[0]' -x '$file'") || die "Cannot run isoinfo -R -i '$ARGV[0]' -x '$file' : $!\n"; copy($fh, "${root}$file"); close($fh); umask($origmask); utime($stamp, $stamp, "${root}$file"); chmod(permval($perms), "${root}$file"); } # Now that we have extracted all the file, it is safe to utime and chmod the # directories (in reverse order so we will do the deep ones first). while (scalar(@dirlist) > 0) { $_ = pop(@dirlist); $file = ${$_}[0]; $file = "${root}$file"; $perms = ${$_}[1]; $stamp = ${$_}[2]; utime($stamp, $stamp, $file); chmod(permval($perms), $file); }