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