186d7f5d3SJohn Marino#!/bin/sh - 286d7f5d3SJohn Marino# 386d7f5d3SJohn Marino# $NetBSD: gzexe,v 1.2 2003/12/28 12:43:43 wiz Exp $ 486d7f5d3SJohn Marino# $DragonFly: src/usr.bin/gzip/gzexe,v 1.1 2004/10/26 11:19:31 joerg Exp $ 586d7f5d3SJohn Marino# $OpenBSD: gzexe,v 1.4 2005/09/30 06:50:44 otto Exp $ 686d7f5d3SJohn Marino# 786d7f5d3SJohn Marino# Copyright (c) 2003 Otto Moerbeek <otto@drijf.net> 886d7f5d3SJohn Marino# 986d7f5d3SJohn Marino# Permission to use, copy, modify, and distribute this software for any 1086d7f5d3SJohn Marino# purpose with or without fee is hereby granted, provided that the above 1186d7f5d3SJohn Marino# copyright notice and this permission notice appear in all copies. 1286d7f5d3SJohn Marino# 1386d7f5d3SJohn Marino# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1486d7f5d3SJohn Marino# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1586d7f5d3SJohn Marino# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1686d7f5d3SJohn Marino# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1786d7f5d3SJohn Marino# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1886d7f5d3SJohn Marino# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1986d7f5d3SJohn Marino# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2086d7f5d3SJohn Marino# 2186d7f5d3SJohn Marino 2286d7f5d3SJohn Marino# The number of lines plus one in the on-the-fly decompression script 2386d7f5d3SJohn Marinolines=19 2486d7f5d3SJohn Marino 2586d7f5d3SJohn Marino# A simple string to recognize already compressed files 2686d7f5d3SJohn Marinomagic="# compressed by gzexe" 2786d7f5d3SJohn Marino 2886d7f5d3SJohn Marino# Write the decompression script to stdout 2986d7f5d3SJohn Marinoheader () { 3086d7f5d3SJohn Marino # first section needs variable expansion, second not 3186d7f5d3SJohn Marino cat <<- EOF 3286d7f5d3SJohn Marino #!/bin/sh - 3386d7f5d3SJohn Marino $magic 3486d7f5d3SJohn Marino lines=$lines 3586d7f5d3SJohn Marino EOF 3686d7f5d3SJohn Marino cat <<- 'EOF' 3786d7f5d3SJohn Marino prog=`/usr/bin/basename "$0"` 3886d7f5d3SJohn Marino tmp=`/usr/bin/mktemp -d /tmp/gzexeXXXXXXXXXX` || { 3986d7f5d3SJohn Marino /bin/echo "$prog: cannot create tmp dir"; exit 1 4086d7f5d3SJohn Marino } 4186d7f5d3SJohn Marino trap '/bin/rm -rf "$tmp"' 0 4286d7f5d3SJohn Marino if /usr/bin/tail +$lines "$0" | 4386d7f5d3SJohn Marino /usr/bin/gzip -dc > "$tmp/$prog" 2> /dev/null; then 4486d7f5d3SJohn Marino /bin/chmod u+x "$tmp/$prog" 4586d7f5d3SJohn Marino "$tmp/$prog" ${1+"$@"} 4686d7f5d3SJohn Marino ret=$? 4786d7f5d3SJohn Marino else 4886d7f5d3SJohn Marino /bin/echo "$prog: cannot decompress $0" 4986d7f5d3SJohn Marino ret=1 5086d7f5d3SJohn Marino fi 5186d7f5d3SJohn Marino exit $ret 5286d7f5d3SJohn Marino EOF 5386d7f5d3SJohn Marino} 5486d7f5d3SJohn Marino 5586d7f5d3SJohn Marino# Test if a file is compressed by checking the magic line 5686d7f5d3SJohn Marinocompressed () { 5786d7f5d3SJohn Marino test "X`sed -n 2p "$1" 2> /dev/null`" = "X$magic" 5886d7f5d3SJohn Marino} 5986d7f5d3SJohn Marino 6086d7f5d3SJohn Marino# Decompress a file 6186d7f5d3SJohn Marinodecompress () { 6286d7f5d3SJohn Marino tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || { 6386d7f5d3SJohn Marino echo "$prog: cannot create tmp file" 6486d7f5d3SJohn Marino return 1 6586d7f5d3SJohn Marino } 6686d7f5d3SJohn Marino if ! cp "$1" "$tmp"; then 6786d7f5d3SJohn Marino echo "$prog: cannot copy $1 to $tmp" 6886d7f5d3SJohn Marino rm -f "$tmp" 6986d7f5d3SJohn Marino return 1 7086d7f5d3SJohn Marino fi 7186d7f5d3SJohn Marino if ! tail +$lines "$tmp" | gzip -vdc > "$1"; then 7286d7f5d3SJohn Marino echo "$prog: cannot decompress $1" 7386d7f5d3SJohn Marino cp "$tmp" "$1" 7486d7f5d3SJohn Marino rm -f "$tmp" 7586d7f5d3SJohn Marino return 1 7686d7f5d3SJohn Marino fi 7786d7f5d3SJohn Marino} 7886d7f5d3SJohn Marino 7986d7f5d3SJohn Marino# Perform some sanity checks on the file 8086d7f5d3SJohn Marinocheck () { 8186d7f5d3SJohn Marino if test ! -e "$1"; then 8286d7f5d3SJohn Marino echo "$prog: cannot compress non-existing file $1" 8386d7f5d3SJohn Marino return 1 8486d7f5d3SJohn Marino fi 8586d7f5d3SJohn Marino 8686d7f5d3SJohn Marino if test ! -f "$1"; then 8786d7f5d3SJohn Marino echo "$prog: cannot compress non-regular file $1" 8886d7f5d3SJohn Marino return 1 8986d7f5d3SJohn Marino fi 9086d7f5d3SJohn Marino 9186d7f5d3SJohn Marino case `basename "$1"` in 9286d7f5d3SJohn Marino sh | mktemp | rm | echo | tail | gzip | chmod | basename) 9386d7f5d3SJohn Marino echo "$prog: cannot compress $1, I depend on it" 9486d7f5d3SJohn Marino return 1 9586d7f5d3SJohn Marino esac 9686d7f5d3SJohn Marino 9786d7f5d3SJohn Marino if test ! -x "$1"; then 9886d7f5d3SJohn Marino echo "$prog: cannot compress $1, it is not executable" 9986d7f5d3SJohn Marino return 1 10086d7f5d3SJohn Marino fi 10186d7f5d3SJohn Marino 10286d7f5d3SJohn Marino if test -u "$1" -o -g "$1"; then 10386d7f5d3SJohn Marino echo "$prog: cannot compress $1, it has an s bit set" 10486d7f5d3SJohn Marino return 1 10586d7f5d3SJohn Marino fi 10686d7f5d3SJohn Marino 10786d7f5d3SJohn Marino # Build a list of files we should not compress. 10886d7f5d3SJohn Marino # * files we need to decompress 10986d7f5d3SJohn Marino CHECK_LIST=" 11086d7f5d3SJohn Marino /bin/chmod 11186d7f5d3SJohn Marino /bin/echo 11286d7f5d3SJohn Marino /bin/sh 11386d7f5d3SJohn Marino /bin/rm 11486d7f5d3SJohn Marino /usr/bin/basename 11586d7f5d3SJohn Marino /usr/bin/gzip 11686d7f5d3SJohn Marino /usr/bin/mktemp 11786d7f5d3SJohn Marino /usr/bin/tail 11886d7f5d3SJohn Marino " 11986d7f5d3SJohn Marino # * files in /bin and /sbin (decompression fails if /usr/bin is not mounted) 12086d7f5d3SJohn Marino # (You could skip these if /usr/bin is always mounted on the same mount point.) 12186d7f5d3SJohn Marino CHECK_LIST="$CHECK_LIST 12286d7f5d3SJohn Marino /bin/* 12386d7f5d3SJohn Marino /sbin/* 12486d7f5d3SJohn Marino " 12586d7f5d3SJohn Marino # See if the program we are trying to compress is in the list. 12686d7f5d3SJohn Marino # To avoid compressing hardlinked files (eg compress & gzip) 12786d7f5d3SJohn Marino # we compare the device & inode. 12886d7f5d3SJohn Marino PROG_STAT_INFO=`stat -f '%d %i' "$1"` 12986d7f5d3SJohn Marino for CHECK in $CHECK_LIST; do 13086d7f5d3SJohn Marino if test -f "$CHECK"; then 13186d7f5d3SJohn Marino CHECK_STAT_INFO=`stat -f '%d %i' "$CHECK"` 13286d7f5d3SJohn Marino if test "X$PROG_STAT_INFO" == "X$CHECK_STAT_INFO"; then 13386d7f5d3SJohn Marino echo "$prog: cannot compress $1, it is the same file as $CHECK" 13486d7f5d3SJohn Marino return 1 13586d7f5d3SJohn Marino fi 13686d7f5d3SJohn Marino fi 13786d7f5d3SJohn Marino done 13886d7f5d3SJohn Marino} 13986d7f5d3SJohn Marino 14086d7f5d3SJohn Marino# Compress a file 14186d7f5d3SJohn Marinocompress () { 14286d7f5d3SJohn Marino tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || { 14386d7f5d3SJohn Marino echo "$prog: cannot create tmp file" 14486d7f5d3SJohn Marino return 1 14586d7f5d3SJohn Marino } 14686d7f5d3SJohn Marino if ! cp "$1" "$tmp"; then 14786d7f5d3SJohn Marino echo "$prog: cannot copy $1 to $tmp" 14886d7f5d3SJohn Marino rm -f "$tmp" 14986d7f5d3SJohn Marino return 1 15086d7f5d3SJohn Marino fi 15186d7f5d3SJohn Marino if ! cp "$1" "$1"~; then 15286d7f5d3SJohn Marino echo "$prog: cannot create backup copy $1~" 15386d7f5d3SJohn Marino rm -f "$1"~ "$tmp" 15486d7f5d3SJohn Marino return 1 15586d7f5d3SJohn Marino fi 15686d7f5d3SJohn Marino 15786d7f5d3SJohn Marino # Use cp to overwrite the existing file preserving mode and owner 15886d7f5d3SJohn Marino # if possible. If the file is not writable, this will produce an 15986d7f5d3SJohn Marino # error. 16086d7f5d3SJohn Marino 16186d7f5d3SJohn Marino if header "$1" > "$tmp" && gzip -vc "$1" >> "$tmp"; then 16286d7f5d3SJohn Marino if ! cp "$tmp" "$1"; then 16386d7f5d3SJohn Marino echo "$prog: cannot copy $tmp to $1" 16486d7f5d3SJohn Marino rm -f "$tmp" 16586d7f5d3SJohn Marino return 1 16686d7f5d3SJohn Marino fi 16786d7f5d3SJohn Marino else 16886d7f5d3SJohn Marino echo "$prog: cannot compress $1" 16986d7f5d3SJohn Marino rm -f "$1"~ "$tmp" 17086d7f5d3SJohn Marino return 1 17186d7f5d3SJohn Marino fi 17286d7f5d3SJohn Marino} 17386d7f5d3SJohn Marino 17486d7f5d3SJohn Marino# Is the -d flag specified? 17586d7f5d3SJohn Marinodflag= 17686d7f5d3SJohn Marino 17786d7f5d3SJohn Marino# Return value 17886d7f5d3SJohn Marinorc=0 17986d7f5d3SJohn Marino 18086d7f5d3SJohn Marinoif test "X$1" = X-d; then 18186d7f5d3SJohn Marino dflag=1 18286d7f5d3SJohn Marino shift 18386d7f5d3SJohn Marinofi 18486d7f5d3SJohn Marino 18586d7f5d3SJohn Marinoprog=`basename "$0"` 18686d7f5d3SJohn MarinoUSAGE="usage: $prog [-d] file ..." 18786d7f5d3SJohn Marinoif test $# -eq 0; then 18886d7f5d3SJohn Marino echo $USAGE 18986d7f5d3SJohn Marino exit 1 19086d7f5d3SJohn Marinofi 19186d7f5d3SJohn Marino 19286d7f5d3SJohn Marinowhile test $# -ne 0; do 19386d7f5d3SJohn Marino if test $dflag; then 19486d7f5d3SJohn Marino if ! compressed "$1"; then 19586d7f5d3SJohn Marino echo "$prog: $1 is not compressed" 19686d7f5d3SJohn Marino rc=1; 19786d7f5d3SJohn Marino elif ! decompress "$1"; then 19886d7f5d3SJohn Marino rc=$? 19986d7f5d3SJohn Marino fi 20086d7f5d3SJohn Marino else 20186d7f5d3SJohn Marino if compressed "$1"; then 20286d7f5d3SJohn Marino echo "$prog: $1 is already compressed" 20386d7f5d3SJohn Marino rc=1; 20486d7f5d3SJohn Marino elif ! check "$1" || ! compress "$1"; then 20586d7f5d3SJohn Marino rc=$? 20686d7f5d3SJohn Marino fi 20786d7f5d3SJohn Marino fi 20886d7f5d3SJohn Marino shift 20986d7f5d3SJohn Marinodone 21086d7f5d3SJohn Marinoexit $rc 211