#!/bin/sh
# $Id: archive,v 1.10 2018/07/28 15:30:55 tom Exp $
# archive, unarchive -- tar and compress source for archival storage
CDPATH=
command=`basename $0`
 
#-- parse command line options
set -- `getopt 'bBdhlrtuvxzZ' $*`
if [ $? != 0 ]
then
        eval $0 -h
        exit 1
fi
 
debug="eval"
extract="-xp"
listonly=""
remove="n"
touch="n"
unarchive="n"
verbose=""
suffix="tgz"
compress="gzip"
 
while [ $# != 0 ]
do
        opt=$1
        shift
        case $opt in
        -b)     compress="bzip2";suffix="tar.bz2";;
        -B)     compress="bzip2";suffix="tbz";;
        -d)     debug="echo";;
        -l)     extract="-tv"listonly="#";;
        -r)     remove="y";;
        -t)     touch="y";;
        -u)     unarchive="y";;
        -v)     verbose="v";;
        -x)     compress="xz";suffix="tar.xz";;
        -z)     compress="gzip";suffix="tar.gz";;
        -Z)     compress="compress";suffix="tar.Z";;
        -h)     cat <<eof
Usage: 
$command [options] [archive_name]
 
Options:
  -b     use bzip2 and suffix .tar.bz2
  -B     use bzip2 and suffix .tbz
  -d     debug
  -l     list-only (don't extract files)
  -r     remove directory (leave tar in parent)
  -t     touch archive (latest file)
  -u     un archive
  -v     verbose (lists filenames)
  -x     use xz and .tar.xz
  -z     use gzip and .tar.gz
  -Z     use compress and suffix .tar.Z
 
Parameters:
    archive_name   name for archive (default is current directory name)
 
By default, archive uses gzip to produce a gzip'd tar archive with suffix .tgz
eof

                exit;;
        --)     break;;
        -*)     eval $0 -h; exit 1;;
        esac
done
 
#-- if script is invoked as 'unarchive' do same as -u option
if [ $command = unarchive ]
then    unarchive="y"
fi
 
#-- figure out where we are
paths=`/bin/pwd`
 
#-- Provide default archive-name
if [ $# = 1 ]
then    dir="$1"
        arg="$1"
else    dir=$paths
        arg=.
fi
 
myfile=
SUF=".tar.gz .tgz .tar.bz2 .tbz .tar.Z .tar.xz .tz"
 
# Try to decide what the parameter is, and deduce the archive-file and its
# directory:
if [ -f "$dir" ]
then
        myfile="$dir"
        dir=`echo "$dir" |sed -e 's@/[^/]*$@@'`
        if [ "$dir" = "$myfile" ]
        then
                dir=.
        fi
        cmp=`basename $myfile`
        for suf in $SUF none
        do
                tst=`basename $myfile $suf`
                if [ "$cmp" != "$tst" ]
                then
                        break
                fi
        done
elif [ -d "$dir" ]
then
        for suf in $SUF none
        do
                tst=$dir/`basename $dir`$suf
                if [ -f "$tst" ]
                then
                        myfile="$tst"
                        break
                fi
        done
else
        echo "Neither a directory nor a file: $dir"
        exit 1
fi
 
if [ $unarchive = "y" ]
then
        if [ -z "$myfile" ]
        then
                echo "Cannot determine archive-file for $dir"
                exit 1
        fi
 
        case $suf in #(vi
        .tar.gz|.tgz) #(vi
                decomp="gzip -d"
                ;;
        .tar.bz2|.tbz) #(vi
                decomp="bzip2 -d"
                ;;
        .tar.xz|.tz) #(vi
                decomp="xz -d"
                ;;
        .tar.Z) #(vi
                decomp="uncompress"
                ;;
        *) #(vi
                echo "No archive found in ${dir}."
                exit 1
        esac
 
        if [ ! -w . -a ".$listonly" = "." ]
        then
                $debug "chmod u+w ."
                if [ $? != 0 ]
                then
                        echo "archive: chmod error"
                        exit 1
                fi
        fi
 
        if [ "$dir" != "$paths" ]
        then
                $debug cd "$dir"
                if [ "$debug" = echo ]
                then
                        cd "$dir"
                fi
        fi
        myfile=`basename "$myfile"`
 
        #-- uncompress and untar
        if [ ".$listonly" = "." ]
        then
                if [ ! -w . ]
                then
                        $debug chmod u+w .
                fi
                if [ -w .. ]
                then
                        $debug  "mv $myfile .."
                        if [ $? != 0 ]
                        then
                                echo "archive: mv error"
                                exit 1
                        fi
                        myfile="../$myfile"
                fi
        fi
 
        $debug  "umask 0;$decomp -c $myfile | tar ${extract}${verbose}f - 2>&1"
        if [ $? != 0 ]
        then
                echo "archive: $decomp/tar error"
                exit 1
        fi
 
        #-- remove archive
        if [ ".$listonly" = "." ]
        then
                $debug  "rm -f $myfile"
        fi
 
elif [ ".$listonly" != "." ]
then
        echo "archive: -l option applies only to dearchiving"
        exit 1
else
        test -z "$myfile" && myfile="${dir}.$suffix"
        if [ -f "$myfile" ]
        then
                echo "Archive $myfile already present."
                exit 1
        fi
        myfile=`basename "$myfile"`
 
        if [ $arg = . ]
        then    all='`ls -A`'
        else    all='`ls -Ad '$arg'`'
        fi
        $debug  "tar -c${verbose}f - $all | $compress -c >../$myfile"
        if [ $? != 0 ]
        then
                echo "archive: tar error"
                exit 1
        fi
 
        #-- obtain date for "-t" option
        if [ $touch = "y" ]
        then
                last=`find $arg -type f -print |sed -e 's/^/"/' -e 's/$/"/'`
                if [ ".$last" != "." ]
                then
                        last=`eval ls -1t $last | head -1`
                        $debug cpd $last ../$myfile
                        if [ ".$verbose" = ".v" ]
                        then
                                echo last=$last
                        fi
                fi
        fi
 
        #-- remove current sources
        $debug  "chmod u+w ."
        $debug  "find $arg -type d -exec chmod u+w {} \\;"
        $debug  "rm -rf $all"
 
        if [ $remove = "y" ]
        then    #-- move archive to parent, removing leaf
                leaf=`basename $paths`
                $debug  "cd ..;rmdir $leaf"
        else    #-- move archive back in
                $debug  "mv ../$myfile ."
                if [ $arg = . ]
                then
                        $debug  "chmod -w ."
                fi
                if [ $touch = "y" ]
                then
                        $debug cpd $myfile .
                fi
        fi
fi