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