Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- $version='$Id: xbiso.pl,v 1.6 2004/06/30 08:56:17 codex Exp codex $ ';
- #
- ## xbiso.pl (c) codex(at)bogus.net 12/02/2004
- ##
- ## original c code by tonto rostenfaunt <[email protected]> (c) 2003
- ##
- ## i couldn't get the original to work with any of the libftp's i could find,
- ## so i decided to write one in perl.
- ##
- ## this is released under the GPL, as was the original c version i based
- ## this code on.
- ##
- $|=1;
- ##
- use POSIX 'ceil';
- use Getopt::Long;
- use Net::FTP;
- use Fcntl 'SEEK_SET','SEEK_CUR';
- my($XMEDHEAD)="MICROSOFT*XBOX*MEDIA";
- my($FILE_DIR)=0x10;
- ## grab command line
- GetOptions("h","v","x",
- "f=s" => \$xiso,
- "d=s" => \$dstdir,
- "t=s" => \$tmpdir,
- "u=s" => \$user,
- "p=s" => \$pass,
- "r=s" => \$rdir,
- "host=s" => \$ftphost,
- "debug=s" => \$DEBUG);
- $FTP=1 if($ftphost);
- $rdir="/f/games" if(!$rdir);
- $tmpdir=$ENV{PWD} if(!$tmpdir); ## suggested by matti hiljanen
- $ftphost="xbox" if(!$ftphost);
- $user="xbox" if(!$user);
- $pass="xbox" if(!$pass);
- if($opt_v) {
- print $version,"\n";
- exit(0);
- }
- if($opt_h) {
- print <<EOM;
- $version
- usage: xbiso.pl [-h|-v] [-host <ftp host>] [-t <tmpdir>] -f <iso> -d <destination dir>
- -h : this stuff
- -v : print version information
- -x : xiso compatibility (UNTESTED! but should work)
- -t : temporary directory for file extraction (default: $tmpdir)
- -d : destination directory (w/out full path)
- -r : top level dir on remote (default: $rdir)
- -f : xbox .iso image filename
- -host : ftp hostname for extraction directly to xbox (default: '$ftphost')
- -u : ftp username (default: '$user')
- -p : ftp password (default: '$pass')
- e.g.:
- xbiso.pl -host xbox.mynet.net -f backup.iso -d backup
- xbiso.pl -f backup.iso -d backup
- EOM
- exit(0);
- }
- if(!$xiso) {
- die "FATAL: you must specify an xbox iso image filename\n";
- }
- if(!-r $xiso) {
- die "FATAL: cannot read '$xiso': $!";
- }
- die "FATAL: no destination directory given (-d dir)" if(!$dstdir);
- if($FTP) {
- $ftp=Net::FTP->new($ftphost) || die "FATAL: could not connect to '$ftphost': $@";
- $ftp->login($user,$pass) || die "FATAL: could not login to '$ftphost', ",$ftp->message;
- $ftp->cwd($rdir) || die "FATAL: could not chdir to '$rdir', ",$ftp->message;
- $ftp->binary(); ## force binary mode xfers
- }
- my($buf);
- ## open iso image
- open(XISO,$xiso);
- ## check for validity
- sysseek(XISO,0x10000,SEEK_SET);
- sysread(XISO,$buf,0x14);
- die "FATAL: '$xiso' doesn't appear to be an xbox iso image\n" if($buf ne $XMEDHEAD);
- ## read the directory table
- sysread(XISO,$buf,4);
- my($dirtable)=unpack('V',$buf);
- sysseek(XISO,systell(XISO)+0x7d4,SEEK_SET); # skip unused info
- sysread(XISO,$buf,0x14); # read tailend of header
- die "FATAL: header tail mismatch -- possible corruption?\n" if($buf ne $XMEDHEAD);
- ## create top level dir
- if($FTP) {
- $ftp->mkdir($dstdir) || print STDERR "WARNING: could not create destination dir '$dstdir', ",$ftp->message;
- $ftp->cwd($dstdir) || die "FATAL: could not change to destination dir '$dstdir', ",$ftp->message;
- } else {
- mkdir($dstdir,0755) || print "WARNING: could not create local destination directory: $!";
- chdir($dstdir) || die "FATAL: could not change to local destination directory: $!";
- }
- ## chomp through the iso
- ChewISO($dirtable*2048,$dirtable);
- ## close the iso image
- print "EXTRACTION COMPLETED OK.\n";
- close(XISO);
- exit(0);
- ## subs
- sub ChewISO {
- my($offset,$dtable) = @_;
- my($buf,$x);
- sysseek(XISO,$offset,SEEK_SET);
- sysread(XISO,$buf,2);
- my($ltable)=unpack('v',$buf);
- sysread(XISO,$buf,2);
- my($rtable)=unpack('v',$buf);
- sysread(XISO,$buf,4);
- my($sector)=unpack('V',$buf);
- sysread(XISO,$buf,4);
- my($size)=unpack('V',$buf);
- my($attribs,$fnamelen,$fname);
- sysread(XISO,$attribs,1);
- $attribs=unpack('C',$attribs);
- sysread(XISO,$fnamelen,1);
- $fnamelen=unpack('C',$fnamelen);
- sysread(XISO,$fname,$fnamelen);
- ## xiso compatibility (UNTESTED - but should work :)
- if($opt_x) {
- if($rtable != 0) {
- my($cpos)=systell(XISO);
- sysread(XISO,$buf,32);
- if($buffer=~/^\xff{6}/) {
- my($foo)=($cpos-($dtable*2048));
- my($block)=ceil($foo/2048);
- $rtable=$block*512;
- }
- sysseek(XISO,$cpos,SEEK_SET);
- }
- }
- if($fnamelen != 0) {
- if(($attribs & $FILE_DIR) != 0) {
- print "Creating directory $fname ..\n" if($DEBUG);
- CreateDir($fname); ## create directory and change into it
- ChewISO($sector*2048,$sector);
- if($FTP) {
- $ftp->cdup() || die "FATAL: could not cdup() on '$ftphost', ",$ftp->message;
- } else {
- chdir("..");
- }
- } else {
- print "Extracting $fname .. ";
- ExtractFile($size,$fname,$sector);
- print "done\n";
- }
- ChewISO(($dtable*2048)+($rtable*4),$dtable) if($rtable != 0);
- ChewISO(($dtable*2048)+($ltable*4),$dtable) if($ltable != 0);
- }
- }
- sub ExtractFile {
- my($size,$fname,$sector) = @_;
- my($buffer);
- sysseek(XISO,$sector*2048,SEEK_SET);
- sysread(XISO,$buffer,$size);
- if($FTP) {
- ## i'm sure this could be done w/out a temp directory
- my($tmp)=TmpFile($tmpdir,"xbiso");
- open(TMPFILE,">$tmp") || die "FATAL: could not open tmpfile for write: $!";
- syswrite(TMPFILE,$buffer,$size);
- close(TMPFILE);
- $ftp->put($tmp,$fname) || die "FATAL: could not put '$fname' to '$ftphost', ",$ftp->message;
- unlink($tmp);
- } else {
- open(OUT,">$fname") || die "FATAL: could not open '$fname' for write: $!";
- syswrite(OUT,$buffer,$size);
- close(OUT);
- }
- }
- sub CreateDir {
- my($dir) = @_;
- if($FTP) {
- $ftp->mkdir($dir) || printf STDERR "WARNING: could not create '$dir' on host '$ftphost', ",$ftp->message;
- $ftp->cwd($dir) || die "FATAL: could not chdir to '$dir' on host '$ftphost', ",$ftp->message;
- } else {
- mkdir($dir,0755) || printf STDERR "WARNING: failed to create directory '$dir': $!\n";
- chdir($dir) || die "FATAL: could not change to directory '$dir': $!\n";
- }
- }
- sub systell {
- sysseek($_[0],0,SEEK_CUR);
- }
- ## create a temporary file
- sub TmpFile {
- my($dir,$prefix)=@_;
- my($tfile)=$prefix."_".RandChars();
- $tfile=$adr."_".RandChars() while(-e "$dir/$tfile");
- open(TMP,">$dir/$tfile");close(TMP);
- return($dir."/".$tfile);
- }
- sub RandChars {
- my($a,$c,$i);
- for($i=0;$i<10;$i++) {
- if(rand(100)<50) {$a=65;} else {$a=97;}
- $c .= chr(rand(26)+$a);
- }
- return($c);
- }
Advertisement
Add Comment
Please, Sign In to add comment