mirror of
https://gitlab.com/Nanolx/patchimage.git
synced 2024-12-26 09:11:51 +01:00
add and make use of ucat/unp
This commit is contained in:
parent
cdd16430fe
commit
7da399dd68
@ -4,7 +4,11 @@ TMD_OPTS="--tt-id=K"
|
||||
TMP_FILES=(Another nsmb.d XmasNewer NewerFiles "Newer*Summer*Sun" \
|
||||
ZPW_1.1.ips Epic_Super_Bowser_World_v1.00 Riivolution Koopa \
|
||||
Cannon_Super_Mario_Bros._Wii_v1.1 riivolution "Readme*" "*.txt" "*.rtf" \
|
||||
"*.dol" "*.elf" nsmb)
|
||||
"*.dol" "*.elf" nsmb "Retro Remix")
|
||||
|
||||
if [[ -e $HOME/.patchimage.rc ]]; then
|
||||
source $HOME/.patchimage.rc
|
||||
fi
|
||||
|
||||
setup_tools () {
|
||||
|
||||
@ -134,20 +138,18 @@ check_riivolution_patch () {
|
||||
if [[ ${DOWNLOAD_LINK} ]]; then
|
||||
if [[ ! -f "${RIIVOLUTION_ZIP}" ]]; then
|
||||
wget --no-check-certificate ${DOWNLOAD_LINK} -O "${RIIVOLUTION_ZIP}"
|
||||
if [[ "${RIIVOLUTION_ZIP}" == *.zip ]]; then
|
||||
unzip "${RIIVOLUTION_ZIP}" >/dev/null
|
||||
elif [[ "${RIIVOLUTION_ZIP}" == *.rar ]]; then
|
||||
unrar x "${RIIVOLUTION_ZIP}" >/dev/null
|
||||
fi
|
||||
tools/unp "${RIIVOLUTION_ZIP}" >/dev/null
|
||||
fi
|
||||
else
|
||||
echo "no download link for ${GAMENAME} available."
|
||||
exit 1
|
||||
fi
|
||||
elif [[ -f "${RIIVOLUTION_ZIP}" && ! -d "${RIIVOLUTION_DIR}" ]]; then
|
||||
unzip "${RIIVOLUTION_ZIP}" >/dev/null
|
||||
tools/unp "${RIIVOLUTION_ZIP}" >/dev/null
|
||||
elif [[ -f "${PATCHIMAGE_RIIVOLUTION_DIR}"/"${RIIVOLUTION_ZIP}" && ! -d "${RIIVOLUTION_DIR}" ]]; then
|
||||
tools/unp "${PATCHIMAGE_RIIVOLUTION_DIR}"/"${RIIVOLUTION_ZIP}" >/dev/null
|
||||
elif [[ ! -d "${RIIVOLUTION_DIR}" ]]; then
|
||||
echo -e "please specify zip to use with --riivolution=<path>"
|
||||
echo -e "please specify zip/rar to use with --riivolution=<path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -190,11 +192,7 @@ while [[ $xcount -lt $pcount ]]; do
|
||||
--riivolution* )
|
||||
RIIVOLUTION=${1/*=}
|
||||
if [[ -e "${RIIVOLUTION}" ]]; then
|
||||
if [[ "${RIIVOLUTION}" == *.zip ]]; then
|
||||
unzip "${RIIVOLUTION}" >/dev/null
|
||||
elif [[ "${RIIVOLUTION}" == *.rar ]]; then
|
||||
unrar x "${RIIVOLUTION}" >/dev/null
|
||||
fi
|
||||
tools/unp "${RIIVOLUTION}" >/dev/null
|
||||
else
|
||||
echo -e "Riivolution patch ${RIIVOLUTION} not found."
|
||||
exit 1
|
||||
@ -204,11 +202,7 @@ while [[ $xcount -lt $pcount ]]; do
|
||||
--patch* )
|
||||
PATCH=${1/*=}
|
||||
if [[ -e "${PATCH}" ]]; then
|
||||
if [[ "${PATCH}" == *.zip ]]; then
|
||||
unzip "${PATCH}" >/dev/null
|
||||
elif [[ "${PATCH}" == *.rar ]]; then
|
||||
unrar x "${PATCH}" >/dev/null
|
||||
fi
|
||||
tools/unp "${PATCH}" >/dev/null
|
||||
else
|
||||
echo -e "PATCH patch ${PATCH} not found."
|
||||
exit 1
|
||||
|
628
tools/ucat
Executable file
628
tools/ucat
Executable file
@ -0,0 +1,628 @@
|
||||
#! /usr/bin/perl
|
||||
#
|
||||
# "unp" runs the correct unpack program depending on the file extension
|
||||
# of the given parameter.
|
||||
#
|
||||
# Author: Eduard Bloch <blade@debian.org>, 2010
|
||||
#
|
||||
# UI modelled after unp versions 1.x by Eduard Bloch (2000-2009) and original
|
||||
# unp by Andre Karwath (1997).
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
# If you make changes to this script, please feel free to forward the new
|
||||
# version to the author.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
require 5.002;
|
||||
|
||||
use Getopt::Long qw(:config no_ignore_case bundling pass_through);
|
||||
use File::Basename;
|
||||
use Cwd;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
#use diagnostics;
|
||||
|
||||
my @ifiles;
|
||||
my @xargs;
|
||||
my @tools;
|
||||
my $retcode=0;
|
||||
|
||||
my $opt_quiet;
|
||||
my $opt_debug;
|
||||
my $opt_help;
|
||||
my $opt_force;
|
||||
my $opt_formats;
|
||||
my $opt_umode;
|
||||
my $opt_umode_smart;
|
||||
my $opt_verbose;
|
||||
|
||||
BEGIN {
|
||||
eval 'use Locale::gettext';
|
||||
if ($@) {
|
||||
eval q{ sub gettext { return shift; } };
|
||||
} else {
|
||||
textdomain('unp');
|
||||
}
|
||||
}
|
||||
|
||||
my $catmode = $0=~/(^|\/ucat)$/;
|
||||
|
||||
&init_formats;
|
||||
&parse_cli;
|
||||
&process_files;
|
||||
print STDERR "WARNING: There were errors while processing files!\n" if $retcode;
|
||||
print STDERR "retcode: $retcode\n" if $opt_debug;
|
||||
# return something meaning, i.e. it may be single unpacker's only return code
|
||||
# if the status is bad but the value is zero, return at least 1
|
||||
exit ( $retcode ? ( $retcode < 256 ? $retcode : 1 ) : 0 );
|
||||
|
||||
sub show_help
|
||||
{
|
||||
printf(gettext("
|
||||
USAGE:
|
||||
%s [ options ] file [ files... ]
|
||||
file: compressed file(s) to expand/extract
|
||||
|
||||
Use -- [ ARGUMENTS ] to pass arguments to external programs, eg. some tar options:
|
||||
unp fastgl.tgz xmnt.tgz -- -C /tmp
|
||||
|
||||
Options:
|
||||
-f Continue even if program availability checks fail or directory collision occurs
|
||||
-u Special helper mode.
|
||||
For most archive types:
|
||||
- create directory <filename without suffix>/
|
||||
- extract contents there
|
||||
For Debian/Ubuntu packages:
|
||||
- extract data.tar.gz after each operation in local directory
|
||||
- extract control.tar.gz into control/<package_version_arch>/
|
||||
-U Smart mode, acts like -u (see above) if archive contains multiple
|
||||
elements but if there is only one file/directory element then it's stored
|
||||
in the current directory.
|
||||
-s Show the list of supported formats
|
||||
-v More verbosity
|
||||
-h Show this help
|
||||
"), $0) if !$catmode;
|
||||
printf(gettext("
|
||||
USAGE:
|
||||
%s [ options ] file [ files... ]
|
||||
Uncompress multiple files to STDOUT
|
||||
|
||||
Options:
|
||||
-s Show the list of supported formats
|
||||
-h Show this help
|
||||
-v More verbosity, to STDERR
|
||||
"), $0) if $catmode;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
sub init_formats
|
||||
{
|
||||
my $sh="/bin/sh";
|
||||
|
||||
# Database format:
|
||||
# - providing packages (human readable)
|
||||
# - filename suffix,
|
||||
# - libmagic (file tool) pattern,
|
||||
# - process flags (bitfield),
|
||||
# - array of command sets (=arrays of command and arguments). If the first arg
|
||||
# of the command set is an array then it's interpreted as a list of
|
||||
# requirements which need to be checked.
|
||||
#
|
||||
# Flag values:
|
||||
# 2: retry other tools calls if the first candidate failed
|
||||
# 4: pass source and extra args in different order (src args...), good for
|
||||
# shell commands using $0 and $@
|
||||
# 8: stream filters, contents may be extracted if tar format is detected. Only
|
||||
# simple syntax allowed.
|
||||
# 16: append suggested target name to calling arguments
|
||||
use constant
|
||||
{
|
||||
TRY_OTHER_TOOLS => 2,
|
||||
SHELL_STYLE_ARGS => 4,
|
||||
IS_STREAM_FILTER => 8,
|
||||
APPEND_GEN_NAME => 16
|
||||
};
|
||||
|
||||
@tools = (
|
||||
[ "tar", "tar", "tar.archive", 0,
|
||||
[ "tar", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
# shortcuts, no extra scripting needed
|
||||
[ gettext("tar with gzip"), "tgz|tar.gz", undef, 0,
|
||||
[[ "gzip" ], "tar", "-z", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[ gettext("tar with bzip2"), "tar.bz2|tbz2", undef, 0,
|
||||
[ [ "bzip2" ], "tar", "--bzip2", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[ gettext("tar with xz-utils"), "tar.xz|txz", undef, 0,
|
||||
|
||||
[ [ "xz" ], "tar", "--xz", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with lzip"), "tar.lzip", undef, 0,
|
||||
|
||||
[[ "lzip" ], "tar", "--lzip", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with lzop"), "tar.lzop|tzo", undef, 0,
|
||||
|
||||
[[ "lzop" ], "tar", "--lzop", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with compress"), "tar.z", undef, 0,
|
||||
|
||||
[ [ "compress" ], "tar", "-Z", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
# XXX: that's ok for now but if support for other unpackers is needed
|
||||
# (like multithreaded implementations) than ucat code needs to be
|
||||
# extended to check them
|
||||
[ "gzip", "gz", "gzip.compressed.data", IS_STREAM_FILTER,
|
||||
[ "gzip", "-cd" ]
|
||||
],
|
||||
|
||||
[ "bzip2", "bz2", "bzip2.compressed", IS_STREAM_FILTER,
|
||||
[ "bzip2", "-cd" ]
|
||||
],
|
||||
|
||||
[ "lzop", "lzo", "lzop.compressed", IS_STREAM_FILTER,
|
||||
[ "lzop", "-cd" ]
|
||||
],
|
||||
|
||||
[ "xz-utils", "xz", "xz.compressed", IS_STREAM_FILTER,
|
||||
[ "xzcat" ]
|
||||
],
|
||||
|
||||
[ "lzip", "lz", "lzip.compressed", IS_STREAM_FILTER,
|
||||
[ "lzip", "-cd" ]
|
||||
],
|
||||
|
||||
[ gettext("xz-utils or lzma"), "lzma", "lzma.compressed", IS_STREAM_FILTER|TRY_OTHER_TOOLS,
|
||||
[ "xzcat" ],
|
||||
[ "lzcat" ]
|
||||
],
|
||||
|
||||
[ gettext("cpio or afio"), "cpio|afio", "cpio", SHELL_STYLE_ARGS,
|
||||
[ "afio", "-Z", "-v", "-i" ],
|
||||
[ ["cpio"], $sh, "-c", 'cpio -i -d --verbose "$@" < "$0"' ]
|
||||
],
|
||||
|
||||
[ gettext("rpm2cpio and cpio"), "rpm", 'PPM\ v', SHELL_STYLE_ARGS,
|
||||
[ ["rpm2cpio", "cpio"], $sh, "-c", 'rpm2cpio < "$0" | cpio -i -d --verbose "$@"' ]
|
||||
],
|
||||
|
||||
[ gettext("formail and mpack"), "mbox", "(mail.text)|news", SHELL_STYLE_ARGS,
|
||||
[ ["formail","munpack"], $sh, "-c", 'formail -s munpack "$@" < "$0"' ]
|
||||
],
|
||||
|
||||
[ gettext("libchm-bin or archmage"), "chm", "Windows HtmlHelp Data", APPEND_GEN_NAME,
|
||||
[ 'extract_chmLib' ],
|
||||
[ 'archmage']
|
||||
],
|
||||
|
||||
[ gettext("rar or unrar or unrar-free"), "rar", "RAR.*archive", 0,
|
||||
[ "rar", "x" ],
|
||||
[ "unrar", "x" ]
|
||||
]
|
||||
,
|
||||
[ "binutils", "ar|deb", "(Debian binary package|\ ar.*archive)", 0,
|
||||
[ "ar", "-x", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "unzip", "zip|cbz|cbr|jar|war|ear|xpi|adf", "Zip.*archive", 0,
|
||||
[ "unzip" ]
|
||||
]
|
||||
,
|
||||
[ "lha", "lha|lzh", "LHa.*archive", 0,
|
||||
[ "lha", "x" ]
|
||||
]
|
||||
,
|
||||
[ "arj", "arj", "ARJ.*archive", 0,
|
||||
[ "arj", "x" ],
|
||||
[ "unarj", "x" ],
|
||||
]
|
||||
,
|
||||
[ "ppmd", "pmd", "PPmd.*archive", 0,
|
||||
[ "PPMd", "x" ]
|
||||
]
|
||||
,
|
||||
[ "zoo", "zoo", "Zoo.*archive", 0,
|
||||
[ "unzoo", "-x" ]
|
||||
]
|
||||
,
|
||||
[ "sharutils", "shar", "shell.*archive", 0,
|
||||
[ "unshar" ]
|
||||
]
|
||||
,
|
||||
[ "sharutils", "uu", "uuencoded", 0,
|
||||
[ "undecode" ]
|
||||
]
|
||||
,
|
||||
[ "tnef", "dat", "Transport Neutral Encapsulation Format", 0,
|
||||
[ "tnef", "-v" ]
|
||||
]
|
||||
,
|
||||
[ gettext("p7zip or p7zip-full"), "7z", "7-zip.*archive", 0,
|
||||
[ "7z", "x" ]
|
||||
]
|
||||
,
|
||||
[ "cabextract", "cab", "CAB file", 0,
|
||||
[ "cabextract" ]
|
||||
]
|
||||
,
|
||||
[ "unace", "ace", "ACE.*archive", 0,
|
||||
[ "unace", "e" ]
|
||||
]
|
||||
,
|
||||
[ "xdms", "dms", "DMS.*archive", 0,
|
||||
[ "xdms", "x" ]
|
||||
]
|
||||
,
|
||||
[ "unlzx", "lzx", "LZX.*archive", 0,
|
||||
[ "unace", "e" ]
|
||||
]
|
||||
,
|
||||
[ "macutils", "sea|sea\.bin", "SEA.*archive", 0,
|
||||
[ "macutils", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "macutils", "hqx", "BinHex.binary", 0,
|
||||
[ "hexbin", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "maybe orange or unzip or unrar or unarj or lha ", "exe", "executable", 3,
|
||||
[ "orange" ],
|
||||
[ "unzip" ],
|
||||
[ "unrar", "x" ],
|
||||
[ "rar", "x" ],
|
||||
[ "arj", "x" ],
|
||||
[ "lha", "x" ]
|
||||
]
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
sub show_formats
|
||||
{
|
||||
print "Known archive formats and tools:\n";
|
||||
my %t;
|
||||
my $len=0;
|
||||
foreach my $line (@tools)
|
||||
{
|
||||
my @dset = @$line;
|
||||
my $sux = $dset[1];
|
||||
$sux=~s/\|/,/g;
|
||||
$t{$sux}=$dset[0];
|
||||
$len=length($sux) if(length($sux)>$len && length($sux)<20);
|
||||
#print $sux . ":\t\t$dset[0]\n";
|
||||
}
|
||||
foreach (sort (keys %t))
|
||||
{
|
||||
print "$_:";
|
||||
my $diff=$len-length($_);
|
||||
print " "x$diff." $t{$_}\n";
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub parse_cli
|
||||
{
|
||||
my %options = (
|
||||
"q|quiet" => \$opt_quiet,
|
||||
"d|debug" => \$opt_debug,
|
||||
"h|help" => \$opt_help,
|
||||
"f|force" => \$opt_force,
|
||||
"s|show-formats" => \$opt_formats,
|
||||
"u|to-subdir" => \$opt_umode,
|
||||
"U|smart-subdir" => \$opt_umode_smart,
|
||||
"v|verbose" => \$opt_verbose
|
||||
);
|
||||
&show_help unless ( GetOptions(%options));
|
||||
&show_help if ($opt_help);
|
||||
&show_formats if ($opt_formats);
|
||||
while(@ARGV)
|
||||
{
|
||||
if("--" eq $ARGV[0])
|
||||
{
|
||||
shift(@ARGV);
|
||||
@xargs = @ARGV;
|
||||
last;
|
||||
}
|
||||
push(@ifiles, shift(@ARGV));
|
||||
}
|
||||
print STDERR join(" ; ", "ifiles", @ifiles, "xargs", @xargs, "argv", @ARGV, "\n") if $opt_debug;
|
||||
}
|
||||
|
||||
sub try_unarch
|
||||
{
|
||||
my $ifile=shift;
|
||||
my $magicdata=shift;
|
||||
print STDERR "magic string: $magicdata\n" if $opt_debug && $magicdata;
|
||||
UNPIFILE: foreach my $line (@tools)
|
||||
{
|
||||
my ($name, $suxARG, $patARG, $cmdflags) = @$line;
|
||||
|
||||
print STDERR "hm, $magicdata vs. $patARG\n" if ( $opt_debug && $magicdata);
|
||||
|
||||
# needs magic data to test against
|
||||
next if(defined($magicdata) && !defined($patARG));
|
||||
|
||||
next if($catmode && ! ($cmdflags & IS_STREAM_FILTER));
|
||||
|
||||
if(
|
||||
(defined($magicdata) && $magicdata=~/$patARG/i)
|
||||
|| ( !defined($magicdata) && $ifile =~ /.*\.($suxARG)$/i) )
|
||||
{
|
||||
print STDERR "got unpacker description for $ifile\n" if $opt_debug;
|
||||
my $misscount=0;
|
||||
my @dset = @$line;
|
||||
|
||||
TOOL: foreach my $pArgs (@dset[4..$#dset])
|
||||
{
|
||||
my @args=@$pArgs;
|
||||
my @prqs = ($args[0]);
|
||||
|
||||
# there is a list of prqs prepended, use that one and weed out the ref
|
||||
@prqs=@{shift(@args)} if( ref($args[0]) eq "ARRAY");
|
||||
|
||||
my $misscountCur=0;
|
||||
foreach(@prqs)
|
||||
{
|
||||
if(!which($_))
|
||||
{
|
||||
$misscountCur++;
|
||||
$misscount++;
|
||||
}
|
||||
}
|
||||
|
||||
# if all tools are here? Let's start...
|
||||
if(! $misscountCur)
|
||||
{
|
||||
my $rcodeprev=$retcode;
|
||||
$retcode += ($catmode ? &cat_one($ifile, $line, @args) : &unpack_one($ifile, $line, @args));
|
||||
|
||||
return 1 if($rcodeprev == $retcode);
|
||||
|
||||
# try other tools if hinted but never in cat mode in order to prevent data corruption
|
||||
return 0 if($catmode);
|
||||
next TOOL if($cmdflags & TRY_OTHER_TOOLS);
|
||||
}
|
||||
}
|
||||
if($misscount)
|
||||
{
|
||||
print STDERR gettext("Error, following packages must be installed in order to proceed:\n").$name."\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub getmagic
|
||||
{
|
||||
my $path=shift;
|
||||
print STDERR "getting magic value from $path\n" if $opt_debug;
|
||||
if(open(my $fd, "-|", "file", "-L", $path))
|
||||
{
|
||||
my $fileret=scalar <$fd>;
|
||||
#print STDERR "got: $fileret\n" if $opt_debug;
|
||||
close $fd;
|
||||
chomp $fileret;
|
||||
return $fileret;
|
||||
}
|
||||
return "G.N.D.N.";
|
||||
}
|
||||
|
||||
sub cat_file
|
||||
{
|
||||
my $file=shift;
|
||||
if(open(my $fd, $file) )
|
||||
{
|
||||
my $buf;
|
||||
while(my $len=sysread($fd, $buf, 1<<16, 0))
|
||||
{
|
||||
my $off=0;
|
||||
my $res;
|
||||
while($res=syswrite(STDOUT, $buf, $len, $off))
|
||||
{
|
||||
die "Failed to print: $!\n" if !defined($res);
|
||||
last if 0==$res;
|
||||
$off+=$res;
|
||||
last if $off>=$len;
|
||||
}
|
||||
}
|
||||
close $fd || $retcode++;
|
||||
}
|
||||
else { $retcode++; }
|
||||
}
|
||||
|
||||
sub process_files
|
||||
{
|
||||
IFILE:
|
||||
foreach my $ifile (@ifiles)
|
||||
{
|
||||
if(!-r $ifile)
|
||||
{
|
||||
printf STDERR gettext("Cannot read %s, skipping...\n"), $ifile;
|
||||
$retcode++;
|
||||
next IFILE;
|
||||
}
|
||||
|
||||
next if (&try_unarch($ifile) or &try_unarch($ifile, getmagic($ifile)));
|
||||
|
||||
printf STDERR gettext("Failed to detect file type of %s.\n"), $ifile;
|
||||
|
||||
# print the file as is in cat mode, otherwise remember that problem
|
||||
$retcode += ($catmode ? system("cat", $ifile) : 1);
|
||||
}
|
||||
}
|
||||
|
||||
sub which
|
||||
{
|
||||
my $prog=shift;
|
||||
for(split(/:/,$ENV{"PATH"})) {
|
||||
if(-x "$_/$prog") {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub cat_one
|
||||
{
|
||||
print STDERR "\ncat_one: @_\n" if $opt_debug;
|
||||
my $file=shift;
|
||||
my $toolRef=shift;
|
||||
my $flags=$toolRef->[3];
|
||||
my @cmd = (SHELL_STYLE_ARGS & $flags) ? (@_, $file, @xargs) : (@_, @xargs, $file);
|
||||
print STDERR join(" ", "test cmd line: ", @cmd, "\n") if $opt_debug;
|
||||
return (system(@cmd) >> 8);
|
||||
}
|
||||
|
||||
sub unpack_one
|
||||
{
|
||||
print STDERR "unpack_one: @_\n" if $opt_debug;
|
||||
|
||||
my $file=shift;
|
||||
my $toolRef=shift;
|
||||
my $cwd=getcwd;
|
||||
|
||||
my $ret=1;
|
||||
my $flags=@{$toolRef}[3];
|
||||
|
||||
my $sufpat=@{$toolRef}[1];
|
||||
my $tgtname=basename($file);
|
||||
$tgtname=~s/(.*)\.($sufpat)$/$1/i;
|
||||
|
||||
return special_debmode($file) if($opt_umode && $file=~/\.deb$/i);
|
||||
|
||||
# make sure that target file/directory for certain types is not occupied
|
||||
if( ( $opt_umode_smart || $opt_umode || ( $flags & (IS_STREAM_FILTER|APPEND_GEN_NAME)) ) && -e $tgtname)
|
||||
{
|
||||
printf STDERR (gettext(
|
||||
"Cannot create target %s: file already exists. Trying alternative targets...\n"),
|
||||
$tgtname);
|
||||
$tgtname.=".unp";
|
||||
if(-e $tgtname)
|
||||
{
|
||||
print STDERR sprintf(gettext(
|
||||
"Cannot create target %s: file already exists\n"), $tgtname);
|
||||
$tgtname.=".".rand;
|
||||
}
|
||||
if(-e $tgtname)
|
||||
{
|
||||
print STDERR sprintf(gettext(
|
||||
"Cannot create target %s: file already exists\n"), $tgtname);
|
||||
exit 1 if $opt_force;
|
||||
}
|
||||
print STDERR "Suggested target name: $tgtname\n";
|
||||
}
|
||||
print STDERR "tgtname: $tgtname\n" if $opt_debug;
|
||||
|
||||
my $tmpdir;
|
||||
|
||||
if($opt_umode || $opt_umode_smart)
|
||||
{
|
||||
$file=Cwd::abs_path($file);
|
||||
print STDERR "set abs.path to $file\n" if $opt_debug;
|
||||
$tmpdir="unp.".rand;
|
||||
mkdir $tmpdir;
|
||||
chdir($tmpdir) || return 23;
|
||||
}
|
||||
|
||||
my @cmd = (SHELL_STYLE_ARGS & $flags) ? (@_, $file, @xargs) : (@_, @xargs, $file);
|
||||
|
||||
|
||||
print STDERR "temp.cmd: ".join("\t", @cmd, "\n") if $opt_debug;
|
||||
|
||||
# filter commands... use shell to keep our code simple. Tar stream may be
|
||||
# inside, detect it and unpack it.
|
||||
if(IS_STREAM_FILTER & $flags)
|
||||
{
|
||||
my $magic="";
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" | file -', $file);
|
||||
if(open(my $fh, "-|", @cmd))
|
||||
{
|
||||
$magic = join('', <$fh>);
|
||||
close($fh);
|
||||
}
|
||||
print STDERR "Internal magic: $magic\n" if $opt_debug;
|
||||
if($magic=~/tar.archive/)
|
||||
{
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" | tar -v -x -f - "$@" ', $file, @xargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" > "$1"', $file, $tgtname);
|
||||
}
|
||||
}
|
||||
|
||||
push(@cmd, $tgtname) if(APPEND_GEN_NAME & $flags);
|
||||
|
||||
print STDERR join(" ", "test cmd line: ", @cmd, "\n") if $opt_debug;
|
||||
|
||||
$ret = (system(@cmd) >> 8);
|
||||
|
||||
if( $opt_umode_smart)
|
||||
{
|
||||
chdir "..";
|
||||
my @cont=(<$tmpdir/*>, <$tmpdir/.*>);
|
||||
# . and .. and one element?
|
||||
if(3==@cont)
|
||||
{
|
||||
# use same name as target, fall back to checked tgtname if that is already occupied
|
||||
my $cand=basename($cont[0]);
|
||||
if (-e $cand)
|
||||
{
|
||||
print STDERR gettext("Cannot create target directory (already exists), using alternative name\n");
|
||||
$cand=$tgtname ;
|
||||
}
|
||||
return 44 if ! (rename($cont[0], $cand) && rmdir $tmpdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
rename $tmpdir, $tgtname || return 43;
|
||||
}
|
||||
|
||||
}
|
||||
elsif ($opt_umode)
|
||||
{
|
||||
chdir "..";
|
||||
rename($tmpdir, $tgtname) || return 42;
|
||||
}
|
||||
|
||||
chdir $cwd;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub special_debmode
|
||||
{
|
||||
my $file=shift;
|
||||
basename($file)=~/^(.*)\.deb$/;
|
||||
my $bname=$1;
|
||||
die "cannot recognice package name\n" if !$bname;
|
||||
|
||||
mkdir "control";
|
||||
my $contgt="control/$bname";
|
||||
mkdir $contgt;
|
||||
|
||||
return (system("ar", "x", $file) >> 8 ) +
|
||||
(system("tar", "-z", "-x", "-v", "-f", "control.tar.gz", "-C",
|
||||
$contgt) >> 8 ) +
|
||||
( system("tar", "-z", "-x", "-v", "-f", "data.tar.gz") >> 8 );
|
||||
}
|
628
tools/unp
Executable file
628
tools/unp
Executable file
@ -0,0 +1,628 @@
|
||||
#! /usr/bin/perl
|
||||
#
|
||||
# "unp" runs the correct unpack program depending on the file extension
|
||||
# of the given parameter.
|
||||
#
|
||||
# Author: Eduard Bloch <blade@debian.org>, 2010
|
||||
#
|
||||
# UI modelled after unp versions 1.x by Eduard Bloch (2000-2009) and original
|
||||
# unp by Andre Karwath (1997).
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
# If you make changes to this script, please feel free to forward the new
|
||||
# version to the author.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
require 5.002;
|
||||
|
||||
use Getopt::Long qw(:config no_ignore_case bundling pass_through);
|
||||
use File::Basename;
|
||||
use Cwd;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
#use diagnostics;
|
||||
|
||||
my @ifiles;
|
||||
my @xargs;
|
||||
my @tools;
|
||||
my $retcode=0;
|
||||
|
||||
my $opt_quiet;
|
||||
my $opt_debug;
|
||||
my $opt_help;
|
||||
my $opt_force;
|
||||
my $opt_formats;
|
||||
my $opt_umode;
|
||||
my $opt_umode_smart;
|
||||
my $opt_verbose;
|
||||
|
||||
BEGIN {
|
||||
eval 'use Locale::gettext';
|
||||
if ($@) {
|
||||
eval q{ sub gettext { return shift; } };
|
||||
} else {
|
||||
textdomain('unp');
|
||||
}
|
||||
}
|
||||
|
||||
my $catmode = $0=~/(^|\/ucat)$/;
|
||||
|
||||
&init_formats;
|
||||
&parse_cli;
|
||||
&process_files;
|
||||
print STDERR "WARNING: There were errors while processing files!\n" if $retcode;
|
||||
print STDERR "retcode: $retcode\n" if $opt_debug;
|
||||
# return something meaning, i.e. it may be single unpacker's only return code
|
||||
# if the status is bad but the value is zero, return at least 1
|
||||
exit ( $retcode ? ( $retcode < 256 ? $retcode : 1 ) : 0 );
|
||||
|
||||
sub show_help
|
||||
{
|
||||
printf(gettext("
|
||||
USAGE:
|
||||
%s [ options ] file [ files... ]
|
||||
file: compressed file(s) to expand/extract
|
||||
|
||||
Use -- [ ARGUMENTS ] to pass arguments to external programs, eg. some tar options:
|
||||
unp fastgl.tgz xmnt.tgz -- -C /tmp
|
||||
|
||||
Options:
|
||||
-f Continue even if program availability checks fail or directory collision occurs
|
||||
-u Special helper mode.
|
||||
For most archive types:
|
||||
- create directory <filename without suffix>/
|
||||
- extract contents there
|
||||
For Debian/Ubuntu packages:
|
||||
- extract data.tar.gz after each operation in local directory
|
||||
- extract control.tar.gz into control/<package_version_arch>/
|
||||
-U Smart mode, acts like -u (see above) if archive contains multiple
|
||||
elements but if there is only one file/directory element then it's stored
|
||||
in the current directory.
|
||||
-s Show the list of supported formats
|
||||
-v More verbosity
|
||||
-h Show this help
|
||||
"), $0) if !$catmode;
|
||||
printf(gettext("
|
||||
USAGE:
|
||||
%s [ options ] file [ files... ]
|
||||
Uncompress multiple files to STDOUT
|
||||
|
||||
Options:
|
||||
-s Show the list of supported formats
|
||||
-h Show this help
|
||||
-v More verbosity, to STDERR
|
||||
"), $0) if $catmode;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
sub init_formats
|
||||
{
|
||||
my $sh="/bin/sh";
|
||||
|
||||
# Database format:
|
||||
# - providing packages (human readable)
|
||||
# - filename suffix,
|
||||
# - libmagic (file tool) pattern,
|
||||
# - process flags (bitfield),
|
||||
# - array of command sets (=arrays of command and arguments). If the first arg
|
||||
# of the command set is an array then it's interpreted as a list of
|
||||
# requirements which need to be checked.
|
||||
#
|
||||
# Flag values:
|
||||
# 2: retry other tools calls if the first candidate failed
|
||||
# 4: pass source and extra args in different order (src args...), good for
|
||||
# shell commands using $0 and $@
|
||||
# 8: stream filters, contents may be extracted if tar format is detected. Only
|
||||
# simple syntax allowed.
|
||||
# 16: append suggested target name to calling arguments
|
||||
use constant
|
||||
{
|
||||
TRY_OTHER_TOOLS => 2,
|
||||
SHELL_STYLE_ARGS => 4,
|
||||
IS_STREAM_FILTER => 8,
|
||||
APPEND_GEN_NAME => 16
|
||||
};
|
||||
|
||||
@tools = (
|
||||
[ "tar", "tar", "tar.archive", 0,
|
||||
[ "tar", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
# shortcuts, no extra scripting needed
|
||||
[ gettext("tar with gzip"), "tgz|tar.gz", undef, 0,
|
||||
[[ "gzip" ], "tar", "-z", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[ gettext("tar with bzip2"), "tar.bz2|tbz2", undef, 0,
|
||||
[ [ "bzip2" ], "tar", "--bzip2", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[ gettext("tar with xz-utils"), "tar.xz|txz", undef, 0,
|
||||
|
||||
[ [ "xz" ], "tar", "--xz", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with lzip"), "tar.lzip", undef, 0,
|
||||
|
||||
[[ "lzip" ], "tar", "--lzip", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with lzop"), "tar.lzop|tzo", undef, 0,
|
||||
|
||||
[[ "lzop" ], "tar", "--lzop", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
[gettext( "tar with compress"), "tar.z", undef, 0,
|
||||
|
||||
[ [ "compress" ], "tar", "-Z", "-x", "-v", "-f"]
|
||||
],
|
||||
|
||||
# XXX: that's ok for now but if support for other unpackers is needed
|
||||
# (like multithreaded implementations) than ucat code needs to be
|
||||
# extended to check them
|
||||
[ "gzip", "gz", "gzip.compressed.data", IS_STREAM_FILTER,
|
||||
[ "gzip", "-cd" ]
|
||||
],
|
||||
|
||||
[ "bzip2", "bz2", "bzip2.compressed", IS_STREAM_FILTER,
|
||||
[ "bzip2", "-cd" ]
|
||||
],
|
||||
|
||||
[ "lzop", "lzo", "lzop.compressed", IS_STREAM_FILTER,
|
||||
[ "lzop", "-cd" ]
|
||||
],
|
||||
|
||||
[ "xz-utils", "xz", "xz.compressed", IS_STREAM_FILTER,
|
||||
[ "xzcat" ]
|
||||
],
|
||||
|
||||
[ "lzip", "lz", "lzip.compressed", IS_STREAM_FILTER,
|
||||
[ "lzip", "-cd" ]
|
||||
],
|
||||
|
||||
[ gettext("xz-utils or lzma"), "lzma", "lzma.compressed", IS_STREAM_FILTER|TRY_OTHER_TOOLS,
|
||||
[ "xzcat" ],
|
||||
[ "lzcat" ]
|
||||
],
|
||||
|
||||
[ gettext("cpio or afio"), "cpio|afio", "cpio", SHELL_STYLE_ARGS,
|
||||
[ "afio", "-Z", "-v", "-i" ],
|
||||
[ ["cpio"], $sh, "-c", 'cpio -i -d --verbose "$@" < "$0"' ]
|
||||
],
|
||||
|
||||
[ gettext("rpm2cpio and cpio"), "rpm", 'PPM\ v', SHELL_STYLE_ARGS,
|
||||
[ ["rpm2cpio", "cpio"], $sh, "-c", 'rpm2cpio < "$0" | cpio -i -d --verbose "$@"' ]
|
||||
],
|
||||
|
||||
[ gettext("formail and mpack"), "mbox", "(mail.text)|news", SHELL_STYLE_ARGS,
|
||||
[ ["formail","munpack"], $sh, "-c", 'formail -s munpack "$@" < "$0"' ]
|
||||
],
|
||||
|
||||
[ gettext("libchm-bin or archmage"), "chm", "Windows HtmlHelp Data", APPEND_GEN_NAME,
|
||||
[ 'extract_chmLib' ],
|
||||
[ 'archmage']
|
||||
],
|
||||
|
||||
[ gettext("rar or unrar or unrar-free"), "rar", "RAR.*archive", 0,
|
||||
[ "rar", "x" ],
|
||||
[ "unrar", "x" ]
|
||||
]
|
||||
,
|
||||
[ "binutils", "ar|deb", "(Debian binary package|\ ar.*archive)", 0,
|
||||
[ "ar", "-x", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "unzip", "zip|cbz|cbr|jar|war|ear|xpi|adf", "Zip.*archive", 0,
|
||||
[ "unzip" ]
|
||||
]
|
||||
,
|
||||
[ "lha", "lha|lzh", "LHa.*archive", 0,
|
||||
[ "lha", "x" ]
|
||||
]
|
||||
,
|
||||
[ "arj", "arj", "ARJ.*archive", 0,
|
||||
[ "arj", "x" ],
|
||||
[ "unarj", "x" ],
|
||||
]
|
||||
,
|
||||
[ "ppmd", "pmd", "PPmd.*archive", 0,
|
||||
[ "PPMd", "x" ]
|
||||
]
|
||||
,
|
||||
[ "zoo", "zoo", "Zoo.*archive", 0,
|
||||
[ "unzoo", "-x" ]
|
||||
]
|
||||
,
|
||||
[ "sharutils", "shar", "shell.*archive", 0,
|
||||
[ "unshar" ]
|
||||
]
|
||||
,
|
||||
[ "sharutils", "uu", "uuencoded", 0,
|
||||
[ "undecode" ]
|
||||
]
|
||||
,
|
||||
[ "tnef", "dat", "Transport Neutral Encapsulation Format", 0,
|
||||
[ "tnef", "-v" ]
|
||||
]
|
||||
,
|
||||
[ gettext("p7zip or p7zip-full"), "7z", "7-zip.*archive", 0,
|
||||
[ "7z", "x" ]
|
||||
]
|
||||
,
|
||||
[ "cabextract", "cab", "CAB file", 0,
|
||||
[ "cabextract" ]
|
||||
]
|
||||
,
|
||||
[ "unace", "ace", "ACE.*archive", 0,
|
||||
[ "unace", "e" ]
|
||||
]
|
||||
,
|
||||
[ "xdms", "dms", "DMS.*archive", 0,
|
||||
[ "xdms", "x" ]
|
||||
]
|
||||
,
|
||||
[ "unlzx", "lzx", "LZX.*archive", 0,
|
||||
[ "unace", "e" ]
|
||||
]
|
||||
,
|
||||
[ "macutils", "sea|sea\.bin", "SEA.*archive", 0,
|
||||
[ "macutils", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "macutils", "hqx", "BinHex.binary", 0,
|
||||
[ "hexbin", "-v" ]
|
||||
]
|
||||
,
|
||||
[ "maybe orange or unzip or unrar or unarj or lha ", "exe", "executable", 3,
|
||||
[ "orange" ],
|
||||
[ "unzip" ],
|
||||
[ "unrar", "x" ],
|
||||
[ "rar", "x" ],
|
||||
[ "arj", "x" ],
|
||||
[ "lha", "x" ]
|
||||
]
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
sub show_formats
|
||||
{
|
||||
print "Known archive formats and tools:\n";
|
||||
my %t;
|
||||
my $len=0;
|
||||
foreach my $line (@tools)
|
||||
{
|
||||
my @dset = @$line;
|
||||
my $sux = $dset[1];
|
||||
$sux=~s/\|/,/g;
|
||||
$t{$sux}=$dset[0];
|
||||
$len=length($sux) if(length($sux)>$len && length($sux)<20);
|
||||
#print $sux . ":\t\t$dset[0]\n";
|
||||
}
|
||||
foreach (sort (keys %t))
|
||||
{
|
||||
print "$_:";
|
||||
my $diff=$len-length($_);
|
||||
print " "x$diff." $t{$_}\n";
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub parse_cli
|
||||
{
|
||||
my %options = (
|
||||
"q|quiet" => \$opt_quiet,
|
||||
"d|debug" => \$opt_debug,
|
||||
"h|help" => \$opt_help,
|
||||
"f|force" => \$opt_force,
|
||||
"s|show-formats" => \$opt_formats,
|
||||
"u|to-subdir" => \$opt_umode,
|
||||
"U|smart-subdir" => \$opt_umode_smart,
|
||||
"v|verbose" => \$opt_verbose
|
||||
);
|
||||
&show_help unless ( GetOptions(%options));
|
||||
&show_help if ($opt_help);
|
||||
&show_formats if ($opt_formats);
|
||||
while(@ARGV)
|
||||
{
|
||||
if("--" eq $ARGV[0])
|
||||
{
|
||||
shift(@ARGV);
|
||||
@xargs = @ARGV;
|
||||
last;
|
||||
}
|
||||
push(@ifiles, shift(@ARGV));
|
||||
}
|
||||
print STDERR join(" ; ", "ifiles", @ifiles, "xargs", @xargs, "argv", @ARGV, "\n") if $opt_debug;
|
||||
}
|
||||
|
||||
sub try_unarch
|
||||
{
|
||||
my $ifile=shift;
|
||||
my $magicdata=shift;
|
||||
print STDERR "magic string: $magicdata\n" if $opt_debug && $magicdata;
|
||||
UNPIFILE: foreach my $line (@tools)
|
||||
{
|
||||
my ($name, $suxARG, $patARG, $cmdflags) = @$line;
|
||||
|
||||
print STDERR "hm, $magicdata vs. $patARG\n" if ( $opt_debug && $magicdata);
|
||||
|
||||
# needs magic data to test against
|
||||
next if(defined($magicdata) && !defined($patARG));
|
||||
|
||||
next if($catmode && ! ($cmdflags & IS_STREAM_FILTER));
|
||||
|
||||
if(
|
||||
(defined($magicdata) && $magicdata=~/$patARG/i)
|
||||
|| ( !defined($magicdata) && $ifile =~ /.*\.($suxARG)$/i) )
|
||||
{
|
||||
print STDERR "got unpacker description for $ifile\n" if $opt_debug;
|
||||
my $misscount=0;
|
||||
my @dset = @$line;
|
||||
|
||||
TOOL: foreach my $pArgs (@dset[4..$#dset])
|
||||
{
|
||||
my @args=@$pArgs;
|
||||
my @prqs = ($args[0]);
|
||||
|
||||
# there is a list of prqs prepended, use that one and weed out the ref
|
||||
@prqs=@{shift(@args)} if( ref($args[0]) eq "ARRAY");
|
||||
|
||||
my $misscountCur=0;
|
||||
foreach(@prqs)
|
||||
{
|
||||
if(!which($_))
|
||||
{
|
||||
$misscountCur++;
|
||||
$misscount++;
|
||||
}
|
||||
}
|
||||
|
||||
# if all tools are here? Let's start...
|
||||
if(! $misscountCur)
|
||||
{
|
||||
my $rcodeprev=$retcode;
|
||||
$retcode += ($catmode ? &cat_one($ifile, $line, @args) : &unpack_one($ifile, $line, @args));
|
||||
|
||||
return 1 if($rcodeprev == $retcode);
|
||||
|
||||
# try other tools if hinted but never in cat mode in order to prevent data corruption
|
||||
return 0 if($catmode);
|
||||
next TOOL if($cmdflags & TRY_OTHER_TOOLS);
|
||||
}
|
||||
}
|
||||
if($misscount)
|
||||
{
|
||||
print STDERR gettext("Error, following packages must be installed in order to proceed:\n").$name."\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub getmagic
|
||||
{
|
||||
my $path=shift;
|
||||
print STDERR "getting magic value from $path\n" if $opt_debug;
|
||||
if(open(my $fd, "-|", "file", "-L", $path))
|
||||
{
|
||||
my $fileret=scalar <$fd>;
|
||||
#print STDERR "got: $fileret\n" if $opt_debug;
|
||||
close $fd;
|
||||
chomp $fileret;
|
||||
return $fileret;
|
||||
}
|
||||
return "G.N.D.N.";
|
||||
}
|
||||
|
||||
sub cat_file
|
||||
{
|
||||
my $file=shift;
|
||||
if(open(my $fd, $file) )
|
||||
{
|
||||
my $buf;
|
||||
while(my $len=sysread($fd, $buf, 1<<16, 0))
|
||||
{
|
||||
my $off=0;
|
||||
my $res;
|
||||
while($res=syswrite(STDOUT, $buf, $len, $off))
|
||||
{
|
||||
die "Failed to print: $!\n" if !defined($res);
|
||||
last if 0==$res;
|
||||
$off+=$res;
|
||||
last if $off>=$len;
|
||||
}
|
||||
}
|
||||
close $fd || $retcode++;
|
||||
}
|
||||
else { $retcode++; }
|
||||
}
|
||||
|
||||
sub process_files
|
||||
{
|
||||
IFILE:
|
||||
foreach my $ifile (@ifiles)
|
||||
{
|
||||
if(!-r $ifile)
|
||||
{
|
||||
printf STDERR gettext("Cannot read %s, skipping...\n"), $ifile;
|
||||
$retcode++;
|
||||
next IFILE;
|
||||
}
|
||||
|
||||
next if (&try_unarch($ifile) or &try_unarch($ifile, getmagic($ifile)));
|
||||
|
||||
printf STDERR gettext("Failed to detect file type of %s.\n"), $ifile;
|
||||
|
||||
# print the file as is in cat mode, otherwise remember that problem
|
||||
$retcode += ($catmode ? system("cat", $ifile) : 1);
|
||||
}
|
||||
}
|
||||
|
||||
sub which
|
||||
{
|
||||
my $prog=shift;
|
||||
for(split(/:/,$ENV{"PATH"})) {
|
||||
if(-x "$_/$prog") {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub cat_one
|
||||
{
|
||||
print STDERR "\ncat_one: @_\n" if $opt_debug;
|
||||
my $file=shift;
|
||||
my $toolRef=shift;
|
||||
my $flags=$toolRef->[3];
|
||||
my @cmd = (SHELL_STYLE_ARGS & $flags) ? (@_, $file, @xargs) : (@_, @xargs, $file);
|
||||
print STDERR join(" ", "test cmd line: ", @cmd, "\n") if $opt_debug;
|
||||
return (system(@cmd) >> 8);
|
||||
}
|
||||
|
||||
sub unpack_one
|
||||
{
|
||||
print STDERR "unpack_one: @_\n" if $opt_debug;
|
||||
|
||||
my $file=shift;
|
||||
my $toolRef=shift;
|
||||
my $cwd=getcwd;
|
||||
|
||||
my $ret=1;
|
||||
my $flags=@{$toolRef}[3];
|
||||
|
||||
my $sufpat=@{$toolRef}[1];
|
||||
my $tgtname=basename($file);
|
||||
$tgtname=~s/(.*)\.($sufpat)$/$1/i;
|
||||
|
||||
return special_debmode($file) if($opt_umode && $file=~/\.deb$/i);
|
||||
|
||||
# make sure that target file/directory for certain types is not occupied
|
||||
if( ( $opt_umode_smart || $opt_umode || ( $flags & (IS_STREAM_FILTER|APPEND_GEN_NAME)) ) && -e $tgtname)
|
||||
{
|
||||
printf STDERR (gettext(
|
||||
"Cannot create target %s: file already exists. Trying alternative targets...\n"),
|
||||
$tgtname);
|
||||
$tgtname.=".unp";
|
||||
if(-e $tgtname)
|
||||
{
|
||||
print STDERR sprintf(gettext(
|
||||
"Cannot create target %s: file already exists\n"), $tgtname);
|
||||
$tgtname.=".".rand;
|
||||
}
|
||||
if(-e $tgtname)
|
||||
{
|
||||
print STDERR sprintf(gettext(
|
||||
"Cannot create target %s: file already exists\n"), $tgtname);
|
||||
exit 1 if $opt_force;
|
||||
}
|
||||
print STDERR "Suggested target name: $tgtname\n";
|
||||
}
|
||||
print STDERR "tgtname: $tgtname\n" if $opt_debug;
|
||||
|
||||
my $tmpdir;
|
||||
|
||||
if($opt_umode || $opt_umode_smart)
|
||||
{
|
||||
$file=Cwd::abs_path($file);
|
||||
print STDERR "set abs.path to $file\n" if $opt_debug;
|
||||
$tmpdir="unp.".rand;
|
||||
mkdir $tmpdir;
|
||||
chdir($tmpdir) || return 23;
|
||||
}
|
||||
|
||||
my @cmd = (SHELL_STYLE_ARGS & $flags) ? (@_, $file, @xargs) : (@_, @xargs, $file);
|
||||
|
||||
|
||||
print STDERR "temp.cmd: ".join("\t", @cmd, "\n") if $opt_debug;
|
||||
|
||||
# filter commands... use shell to keep our code simple. Tar stream may be
|
||||
# inside, detect it and unpack it.
|
||||
if(IS_STREAM_FILTER & $flags)
|
||||
{
|
||||
my $magic="";
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" | file -', $file);
|
||||
if(open(my $fh, "-|", @cmd))
|
||||
{
|
||||
$magic = join('', <$fh>);
|
||||
close($fh);
|
||||
}
|
||||
print STDERR "Internal magic: $magic\n" if $opt_debug;
|
||||
if($magic=~/tar.archive/)
|
||||
{
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" | tar -v -x -f - "$@" ', $file, @xargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@cmd=("sh", "-c", join(" ", @_).' "$0" > "$1"', $file, $tgtname);
|
||||
}
|
||||
}
|
||||
|
||||
push(@cmd, $tgtname) if(APPEND_GEN_NAME & $flags);
|
||||
|
||||
print STDERR join(" ", "test cmd line: ", @cmd, "\n") if $opt_debug;
|
||||
|
||||
$ret = (system(@cmd) >> 8);
|
||||
|
||||
if( $opt_umode_smart)
|
||||
{
|
||||
chdir "..";
|
||||
my @cont=(<$tmpdir/*>, <$tmpdir/.*>);
|
||||
# . and .. and one element?
|
||||
if(3==@cont)
|
||||
{
|
||||
# use same name as target, fall back to checked tgtname if that is already occupied
|
||||
my $cand=basename($cont[0]);
|
||||
if (-e $cand)
|
||||
{
|
||||
print STDERR gettext("Cannot create target directory (already exists), using alternative name\n");
|
||||
$cand=$tgtname ;
|
||||
}
|
||||
return 44 if ! (rename($cont[0], $cand) && rmdir $tmpdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
rename $tmpdir, $tgtname || return 43;
|
||||
}
|
||||
|
||||
}
|
||||
elsif ($opt_umode)
|
||||
{
|
||||
chdir "..";
|
||||
rename($tmpdir, $tgtname) || return 42;
|
||||
}
|
||||
|
||||
chdir $cwd;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub special_debmode
|
||||
{
|
||||
my $file=shift;
|
||||
basename($file)=~/^(.*)\.deb$/;
|
||||
my $bname=$1;
|
||||
die "cannot recognice package name\n" if !$bname;
|
||||
|
||||
mkdir "control";
|
||||
my $contgt="control/$bname";
|
||||
mkdir $contgt;
|
||||
|
||||
return (system("ar", "x", $file) >> 8 ) +
|
||||
(system("tar", "-z", "-x", "-v", "-f", "control.tar.gz", "-C",
|
||||
$contgt) >> 8 ) +
|
||||
( system("tar", "-z", "-x", "-v", "-f", "data.tar.gz") >> 8 );
|
||||
}
|
Loading…
Reference in New Issue
Block a user