1dfea36c1Sotto#!/bin/sh - 2dfea36c1Sotto# 3*3c529fc4Sotto# $OpenBSD: gzexe,v 1.4 2005/09/30 06:50:44 otto Exp $ 4dfea36c1Sotto# 5dfea36c1Sotto# Copyright (c) 2003 Otto Moerbeek <otto@drijf.net> 6dfea36c1Sotto# 7dfea36c1Sotto# Permission to use, copy, modify, and distribute this software for any 8dfea36c1Sotto# purpose with or without fee is hereby granted, provided that the above 9dfea36c1Sotto# copyright notice and this permission notice appear in all copies. 10dfea36c1Sotto# 11dfea36c1Sotto# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12dfea36c1Sotto# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13dfea36c1Sotto# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14dfea36c1Sotto# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15dfea36c1Sotto# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16dfea36c1Sotto# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17dfea36c1Sotto# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18dfea36c1Sotto# 19dfea36c1Sotto 20dfea36c1Sotto# The number of lines plus one in the on-the-fly decompression script 21c6a62e4dSottolines=19 22dfea36c1Sotto 23dfea36c1Sotto# A simple string to recognize already compressed files 24dfea36c1Sottomagic="# compressed by gzexe" 25dfea36c1Sotto 26dfea36c1Sotto# Write the decompression script to stdout 27dfea36c1Sottoheader () { 28dfea36c1Sotto typeset prog tmp 29dfea36c1Sotto # first section needs variable expansion, second not 30dfea36c1Sotto cat <<- EOF 31dfea36c1Sotto #!/bin/sh - 32dfea36c1Sotto $magic 33dfea36c1Sotto lines=$lines 34dfea36c1Sotto EOF 35dfea36c1Sotto cat <<- 'EOF' 36dfea36c1Sotto prog=`/usr/bin/basename "$0"` 37dfea36c1Sotto tmp=`/usr/bin/mktemp -d /tmp/gzexeXXXXXXXXXX` || { 38dfea36c1Sotto /bin/echo "$prog: cannot create tmp dir"; exit 1 39dfea36c1Sotto } 40dfea36c1Sotto trap '/bin/rm -rf "$tmp"' 0 41c6a62e4dSotto if /usr/bin/tail +$lines "$0" | 42c6a62e4dSotto /usr/bin/gzip -dc > "$tmp/$prog" 2> /dev/null; then 43dfea36c1Sotto /bin/chmod u+x "$tmp/$prog" 44dfea36c1Sotto "$tmp/$prog" ${1+"$@"} 45dfea36c1Sotto ret=$? 46dfea36c1Sotto else 47dfea36c1Sotto /bin/echo "$prog: cannot decompress $0" 48dfea36c1Sotto ret=1 49dfea36c1Sotto fi 50dfea36c1Sotto exit $ret 51dfea36c1Sotto EOF 52dfea36c1Sotto} 53dfea36c1Sotto 54dfea36c1Sotto# Test if a file is compressed by checking the magic line 55dfea36c1Sottocompressed () { 56dfea36c1Sotto test "X`sed -n 2p "$1" 2> /dev/null`" = "X$magic" 57dfea36c1Sotto} 58dfea36c1Sotto 59dfea36c1Sotto# Decompress a file 60dfea36c1Sottodecompress () { 61dfea36c1Sotto tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || { 62dfea36c1Sotto echo "$prog: cannot create tmp file" 63dfea36c1Sotto return 1 64dfea36c1Sotto } 65dfea36c1Sotto if ! cp "$1" "$tmp"; then 66dfea36c1Sotto echo "$prog: cannot copy $1 to $tmp" 67dfea36c1Sotto rm -f "$tmp" 68dfea36c1Sotto return 1 69dfea36c1Sotto fi 70dfea36c1Sotto if ! tail +$lines "$tmp" | gzip -vdc > "$1"; then 71dfea36c1Sotto echo "$prog: cannot decompress $1" 72dfea36c1Sotto cp "$tmp" "$1" 73dfea36c1Sotto rm -f "$tmp" 74dfea36c1Sotto return 1 75dfea36c1Sotto fi 76dfea36c1Sotto} 77dfea36c1Sotto 78dfea36c1Sotto# Perform some sanity checks on the file 79dfea36c1Sottocheck () { 80dfea36c1Sotto if test ! -e "$1"; then 81dfea36c1Sotto echo "$prog: cannot compress non-existing file $1" 82dfea36c1Sotto return 1 83dfea36c1Sotto fi 84dfea36c1Sotto 85dfea36c1Sotto if test ! -f "$1"; then 86dfea36c1Sotto echo "$prog: cannot compress non-regular file $1" 87dfea36c1Sotto return 1 88dfea36c1Sotto fi 89dfea36c1Sotto 90dfea36c1Sotto case `basename "$1"` in 91*3c529fc4Sotto sh | mktemp | rm | echo | tail | gzip | chmod | basename) 92dfea36c1Sotto echo "$prog: cannot compress $1, I depend on it" 93dfea36c1Sotto return 1 94dfea36c1Sotto esac 95dfea36c1Sotto 96dfea36c1Sotto if test ! -x "$1"; then 97dfea36c1Sotto echo "$prog: cannot compress $1, it is not executable" 98dfea36c1Sotto return 1 99dfea36c1Sotto fi 100dfea36c1Sotto 101dfea36c1Sotto if test -u "$1" -o -g "$1"; then 102dfea36c1Sotto echo "$prog: cannot compress $1, it has an s bit set" 103dfea36c1Sotto return 1 104dfea36c1Sotto fi 105*3c529fc4Sotto 106*3c529fc4Sotto # Build a list of files we should not compress. 107*3c529fc4Sotto # * files we need to decompress 108*3c529fc4Sotto CHECK_LIST=" 109*3c529fc4Sotto /bin/chmod 110*3c529fc4Sotto /bin/echo 111*3c529fc4Sotto /bin/sh 112*3c529fc4Sotto /bin/rm 113*3c529fc4Sotto /usr/bin/basename 114*3c529fc4Sotto /usr/bin/gzip 115*3c529fc4Sotto /usr/bin/mktemp 116*3c529fc4Sotto /usr/bin/tail 117*3c529fc4Sotto " 118*3c529fc4Sotto # * files in /bin and /sbin (decompression fails if /usr/bin is not mounted) 119*3c529fc4Sotto # (You could skip these if /usr/bin is always mounted on the same mount point.) 120*3c529fc4Sotto CHECK_LIST="$CHECK_LIST 121*3c529fc4Sotto /bin/* 122*3c529fc4Sotto /sbin/* 123*3c529fc4Sotto " 124*3c529fc4Sotto # See if the program we are trying to compress is in the list. 125*3c529fc4Sotto # To avoid compressing hardlinked files (eg compress & gzip) 126*3c529fc4Sotto # we compare the device & inode. 127*3c529fc4Sotto PROG_STAT_INFO=`stat -f '%d %i' "$1"` 128*3c529fc4Sotto for CHECK in $CHECK_LIST; do 129*3c529fc4Sotto if test -f "$CHECK"; then 130*3c529fc4Sotto CHECK_STAT_INFO=`stat -f '%d %i' "$CHECK"` 131*3c529fc4Sotto if test "X$PROG_STAT_INFO" == "X$CHECK_STAT_INFO"; then 132*3c529fc4Sotto echo "$prog: cannot compress $1, it is the same file as $CHECK" 133*3c529fc4Sotto return 1 134*3c529fc4Sotto fi 135*3c529fc4Sotto fi 136*3c529fc4Sotto done 137dfea36c1Sotto} 138dfea36c1Sotto 139dfea36c1Sotto# Compress a file 140dfea36c1Sottocompress () { 141dfea36c1Sotto tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || { 142dfea36c1Sotto echo "$prog: cannot create tmp file" 143dfea36c1Sotto return 1 144dfea36c1Sotto } 145dfea36c1Sotto if ! cp "$1" "$tmp"; then 146dfea36c1Sotto echo "$prog: cannot copy $1 to $tmp" 147dfea36c1Sotto rm -f "$tmp" 148dfea36c1Sotto return 1 149dfea36c1Sotto fi 150dfea36c1Sotto if ! cp "$1" "$1"~; then 151dfea36c1Sotto echo "$prog: cannot create backup copy $1~" 152dfea36c1Sotto rm -f "$1"~ "$tmp" 153dfea36c1Sotto return 1 154dfea36c1Sotto fi 155dfea36c1Sotto 156dfea36c1Sotto # Use cp to overwrite the existing file preserving mode and owner 157dfea36c1Sotto # if possible. If the file is not writable, this will produce an 158dfea36c1Sotto # error. 159dfea36c1Sotto 160dfea36c1Sotto if header "$1" > "$tmp" && gzip -vc "$1" >> "$tmp"; then 161dfea36c1Sotto if ! cp "$tmp" "$1"; then 162dfea36c1Sotto echo "$prog: cannot copy $tmp to $1" 163dfea36c1Sotto rm -f "$tmp" 164dfea36c1Sotto return 1 165dfea36c1Sotto fi 166dfea36c1Sotto else 167dfea36c1Sotto echo "$prog: cannot compress $1" 168dfea36c1Sotto rm -f "$1"~ "$tmp" 169dfea36c1Sotto return 1 170dfea36c1Sotto fi 171dfea36c1Sotto} 172dfea36c1Sotto 173dfea36c1Sotto# Is the -d flag specified? 174dfea36c1Sottodflag= 175dfea36c1Sotto 176dfea36c1Sotto# Return value 177dfea36c1Sottorc=0 178dfea36c1Sotto 179dfea36c1Sottoif test "X$1" = X-d; then 180dfea36c1Sotto dflag=1 181dfea36c1Sotto shift 182dfea36c1Sottofi 183dfea36c1Sotto 184dfea36c1Sottoprog=`basename "$0"` 185dfea36c1SottoUSAGE="usage: $prog [-d] file ..." 186dfea36c1Sottoif test $# -eq 0; then 187dfea36c1Sotto echo $USAGE 188dfea36c1Sotto exit 1 189dfea36c1Sottofi 190dfea36c1Sotto 191dfea36c1Sottowhile test $# -ne 0; do 192dfea36c1Sotto if test $dflag; then 193dfea36c1Sotto if ! compressed "$1"; then 194dfea36c1Sotto echo "$prog: $1 is not compressed" 195dfea36c1Sotto rc=1; 196dfea36c1Sotto elif ! decompress "$1"; then 197dfea36c1Sotto rc=$? 198dfea36c1Sotto fi 199dfea36c1Sotto else 200dfea36c1Sotto if compressed "$1"; then 201dfea36c1Sotto echo "$prog: $1 is already compressed" 202dfea36c1Sotto rc=1; 203dfea36c1Sotto elif ! check "$1" || ! compress "$1"; then 204dfea36c1Sotto rc=$? 205dfea36c1Sotto fi 206dfea36c1Sotto fi 207dfea36c1Sotto shift 208dfea36c1Sottodone 209dfea36c1Sottoexit $rc 210