xref: /dflybsd-src/usr.bin/gzip/gzexe (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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