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