#!/bin/sh # # $NetBSD: extract,v 1.20 2006/02/19 15:38:23 adrianp Exp $ # # Copyright (c) 2006 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by Johnny C. Lam. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the NetBSD # Foundation, Inc. and its contributors. # 4. Neither the name of The NetBSD Foundation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ###################################################################### # # NAME # extract -- extract distfile, regardless of format # # SYNOPSIS # extract [options] distfile [file ...] # # DESCRIPTION # extract will unpack the contents of the named distfile into the # current working directory. If any optional files are specified then # only they will be extracted from the distfile, provided that the # underlying tool supports this ability. If the distfile's file # extension doesn't match any known archive format's, then the # distfile is simply copied into the current working directory. If # "-" is given as the distfile, then standard input is used as the # contents of the archive, provided that the underlying tool supports # this ability. # # OPTIONS # -d dir Extract the files into the specified dir instead # of the current working directory. If the directory # doesn't exist, then it is created along with any # intermediate directories using the current umask. # # -f format Force interpretation of the distfile's archive # format to be the specified format. # # -t tarprog This specifies the tool to use to extract tar/ustar # archives, and may be either "tar" or "pax", or the # full path to the program. # # -X excludefile excludefile is a list of file patterns to exclude # from extraction. If the -X option is specified # then any optional files listed on the command line # are ignored. # # -x This causes the optional files listed on the # command line to be excluded from extraction, # provided the underlying tool supports this # ability. # # ENVIRONMENT # EXTRACT_OPTS_BIN # EXTRACT_OPTS_LHA # EXTRACT_OPTS_PAX # EXTRACT_OPTS_RAR # EXTRACT_OPTS_TAR # EXTRACT_OPTS_ZIP # EXTRACT_OPTS_ZOO # These variables set additional arguments passed to the # underlying extraction tool to unpack their respective # archive formats. # ###################################################################### set -e # exit on errors set -u # treat undefined variables as errors : ${BZCAT:=bzcat} : ${CAT:=cat} : ${CP:=cp} : ${ECHO:=echo} : ${GZCAT:=gzcat} : ${LHA:=lha} : ${MKDIR:=mkdir} : ${PAX:=pax} : ${RM:=rm} : ${SH:=sh} : ${TAR:=tar} : ${TEST:=test} : ${UNRAR:=unrar} : ${UNZIP_CMD:=unzip} : ${UNZOO:=unzoo} : ${TMPDIR:=/tmp} self="${0##*/}" usage() { ${ECHO} 1>&2 "usage: $self [-d dir] [-f format] [-t tarprog] [-X excludefile | -x] distfile [file ...]" } exclude=no exclude_file= exclude_flag= extract_dir=. extract_using=tar format= # Process optional arguments while ${TEST} $# -gt 0; do case "$1" in -d) extract_dir="$2"; shift 2 ;; -f) format="$2"; shift 2 ;; -t) extract_using="$2"; shift 2 ;; -X) exclude_file="$2"; shift 2 ;; -x) exclude=yes; shift ;; --) shift; break ;; -?*) ${ECHO} 1>&2 "$self: unknown option -- ${1#-}" usage exit 1 ;; *) break ;; esac done case "$extract_using" in /*tar|/*pax) tarprog="$extract_using" ;; *tar) tarprog="${TAR}" ;; *pax) tarprog="${PAX}" ;; *) tarprog="${TAR}" ;; esac if ${TEST} -n "$exclude_file" -a ! -f "$exclude_file"; then ${ECHO} 1>&2 "$self: exclude file missing: $exclude_file" exit 1 fi # Process required arguments ${TEST} $# -gt 0 || { usage; exit 1; } distfile="$1"; shift # Make distfile an absolute path, because we will change the current # directory soon. case "$distfile" in /*) ;; *) distfile=`exec pwd`/"$distfile" ;; esac # Set the command to decompress the file and write the contents to stdout. case "$distfile" in *.gz|*.tgz|*.z) decompress_cat="${GZCAT}" ;; *.bz2|*.tbz|*.tbz2|*.bz) decompress_cat="${BZCAT}" ;; *.Z) decompress_cat="${GZCAT}" ;; *) decompress_cat="${CAT}" ;; esac # Derive the format of the archive based on the file extension. case "$distfile" in *.tar.gz|*.tgz|*_tar.gz|*.tar.bz2|*.tbz|*.tbz2|*.tar.Z|*.tar.z|*.tar|*.tar.bz) _format=tar ;; *.shar.gz|*.shar.bz2|*.shar.Z|*.shar|*.shr.gz|*.shr.bz2|*.shr.Z|*.shr) _format=shar ;; *.zip|*.ZIP) _format=zip ;; *.lha|*.lzh) _format=lha ;; *.Z|*.bz2|*.gz|*.z) _format=compressed ;; *.zoo) _format=zoo ;; *.rar) _format=rar ;; *.bin) _format=jre-bin ;; *) _format=none ;; esac ${TEST} -n "$format" || format="$_format" case "$format" in tar|shar) ;; *) if ${TEST} "$distfile" = "-"; then ${ECHO} 1>&2 "$self: archive format cannot be given on standard input -- $format" exit 1 fi ;; esac ${TEST} -d "$extract_dir" || ${MKDIR} -p "$extract_dir" cd "$extract_dir" # Use the correct tool and extraction procedure to perform the extraction # based on the archive format. # case "$format" in tar) case "$extract_using" in *pax) : ${EXTRACT_OPTS_PAX=} case "$extract_using" in /*) paxprog="$extract_using" ;; *) paxprog="${PAX}" ;; esac if ${TEST} -n "$exclude_file"; then exclude=yes set -- dummy `${CAT} "$exclude_file"`; shift fi ${TEST} "$exclude" = no || exclude_flag="-c" $decompress_cat "$distfile" | $paxprog ${EXTRACT_OPTS_PAX} $exclude_flag -O -r ${1+"$@"} ;; *tar) : ${EXTRACT_OPTS_TAR=} case "$extract_using" in /*) tarprog="$extract_using" ;; *) tarprog="${TAR}" ;; esac tmpfile= if ${TEST} "$exclude" = "yes"; then tmpfile="${TMPDIR}/$self.$$" ${RM} -f "$tmpfile" trap "\${RM} -f \"\$tmpfile\"" 0 for i in ${1+"$@"}; do ${ECHO} "$i" >> "$tmpfile" done exclude_file="$tmpfile" fi if ${TEST} -n "$exclude_file"; then exclude_flag="-X $exclude_file" set -- dummy; shift fi $decompress_cat "$distfile" | $tarprog ${EXTRACT_OPTS_TAR} $exclude_flag -xf - ${1+"$@"} ;; *) ${ECHO} 1>&2 "$self: unknown tar program: $extract_using" exit 1 esac ;; shar) $decompress_cat "$distfile" | ${SH} ;; zip) : ${EXTRACT_OPTS_ZIP=-Laqo} ${TEST} "$exclude" = "no" || exclude_flag="-x" if ${TEST} -n "$exclude_file"; then set -- dummy `${CAT} "$exclude_file"`; shift fi ${UNZIP_CMD} ${EXTRACT_OPTS_ZIP} "$distfile" $exclude_flag ${1+"$@"} ;; lha) : ${EXTRACT_OPTS_LHA=q} ${LHA} x${EXTRACT_OPTS_LHA} "$distfile" ${1+"$@"} ;; compressed) target="${distfile##*/}"; target="${target%.*}" $decompress_cat "$distfile" > "$target" ;; zoo) : ${EXTRACT_OPTS_ZOO=} ${UNZOO} -x ${EXTRACT_OPTS_ZOO} "$distfile" ${1+"$@"} ;; rar) : ${EXTRACT_OPTS_RAR=-inul} ${UNRAR} x ${EXTRACT_OPTS_RAR} "$distfile" ${1+"$@"} ;; jre-bin) : ${EXTRACT_OPTS_BIN=} ${ECHO} yes | "$distfile" ${EXTRACT_OPTS_BIN} >/dev/null ;; none) # By default, copy the distfile over to the current working directory. ${CP} "$distfile" . ;; *) ${ECHO} 1>&2 "$self: archive format not recognized -- $format" exit 1 ;; esac exit 0