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