xref: /dragonfly/usr.bin/gzip/gzexe (revision a4da4a90)
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