[BACK]Return to gzexe CVS log [TXT][DIR] Up to [local] / src / usr.bin / compress

File: [local] / src / usr.bin / compress / gzexe (download)

Revision 1.4, Fri Sep 30 06:50:44 2005 UTC (18 years, 7 months ago) by otto
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, OPENBSD_6_3_BASE, OPENBSD_6_3, OPENBSD_6_2_BASE, OPENBSD_6_2, OPENBSD_6_1_BASE, OPENBSD_6_1, OPENBSD_6_0_BASE, OPENBSD_6_0, OPENBSD_5_9_BASE, OPENBSD_5_9, OPENBSD_5_8_BASE, OPENBSD_5_8, OPENBSD_5_7_BASE, OPENBSD_5_7, OPENBSD_5_6_BASE, OPENBSD_5_6, OPENBSD_5_5_BASE, OPENBSD_5_5, OPENBSD_5_4_BASE, OPENBSD_5_4, OPENBSD_5_3_BASE, OPENBSD_5_3, OPENBSD_5_2_BASE, OPENBSD_5_2, OPENBSD_5_1_BASE, OPENBSD_5_1, OPENBSD_5_0_BASE, OPENBSD_5_0, OPENBSD_4_9_BASE, OPENBSD_4_9, OPENBSD_4_8_BASE, OPENBSD_4_8, OPENBSD_4_7_BASE, OPENBSD_4_7, OPENBSD_4_6_BASE, OPENBSD_4_6, OPENBSD_4_5_BASE, OPENBSD_4_5, OPENBSD_4_4_BASE, OPENBSD_4_4, OPENBSD_4_3_BASE, OPENBSD_4_3, OPENBSD_4_2_BASE, OPENBSD_4_2, OPENBSD_4_1_BASE, OPENBSD_4_1, OPENBSD_4_0_BASE, OPENBSD_4_0, OPENBSD_3_9_BASE, OPENBSD_3_9, HEAD
Changes since 1.3: +34 -2 lines

Ensure we do not compress files we need for decompressing by also
checking hard links. From Andrew Dalgleish. ok deraadt@

#!/bin/sh -
#
# $OpenBSD: gzexe,v 1.4 2005/09/30 06:50:44 otto Exp $
#
#  Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
#
#  Permission to use, copy, modify, and distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#
#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

# The number of lines plus one in the on-the-fly decompression script
lines=19

# A simple string to recognize already compressed files
magic="# compressed by gzexe"

# Write the decompression script to stdout
header () {
	typeset prog tmp
	# first section needs variable expansion, second not
	cat <<- EOF
		#!/bin/sh -
		$magic
		lines=$lines
	EOF
	cat <<- 'EOF'
		prog=`/usr/bin/basename "$0"`
		tmp=`/usr/bin/mktemp -d /tmp/gzexeXXXXXXXXXX` || {
			/bin/echo "$prog: cannot create tmp dir"; exit 1
		}
		trap '/bin/rm -rf "$tmp"' 0
		if /usr/bin/tail +$lines "$0" |
		    /usr/bin/gzip -dc > "$tmp/$prog" 2> /dev/null; then
			/bin/chmod u+x "$tmp/$prog"
			"$tmp/$prog" ${1+"$@"}
			ret=$?
		else
			/bin/echo "$prog: cannot decompress $0"
			ret=1
		fi
		exit $ret
	EOF
}

# Test if a file is compressed by checking the magic line
compressed () {
	test "X`sed -n 2p "$1" 2> /dev/null`" = "X$magic"
}

# Decompress a file
decompress () {
	tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || {
		echo "$prog: cannot create tmp file"
		return 1
	}
	if ! cp "$1" "$tmp"; then
		echo "$prog: cannot copy $1 to $tmp"
		rm -f "$tmp"
		return 1
	fi
	if ! tail +$lines "$tmp" | gzip -vdc > "$1"; then
		echo "$prog: cannot decompress $1"
		cp "$tmp" "$1"
		rm -f "$tmp"
		return 1
	fi
}

# Perform some sanity checks on the file
check () {
	if test ! -e "$1"; then
		echo "$prog: cannot compress non-existing file $1"
		return 1
	fi

	if test ! -f "$1"; then
		echo "$prog: cannot compress non-regular file $1"
		return 1
	fi

	case `basename "$1"` in
		sh | mktemp | rm | echo | tail | gzip | chmod | basename)
			echo "$prog: cannot compress $1, I depend on it"
			return 1
	esac

	if test ! -x "$1"; then
		echo "$prog: cannot compress $1, it is not executable"
		return 1
	fi

	if test -u "$1" -o -g "$1"; then
		echo "$prog: cannot compress $1, it has an s bit set"
		return 1
	fi

	# Build a list of files we should not compress.
	# * files we need to decompress
	CHECK_LIST="
	/bin/chmod
	/bin/echo
	/bin/sh
	/bin/rm
	/usr/bin/basename
	/usr/bin/gzip
	/usr/bin/mktemp
	/usr/bin/tail
	"
	# * files in /bin and /sbin (decompression fails if /usr/bin is not mounted)
	# (You could skip these if /usr/bin is always mounted on the same mount point.)
	CHECK_LIST="$CHECK_LIST
	/bin/*
	/sbin/*
	"
	# See if the program we are trying to compress is in the list.
	# To avoid compressing hardlinked files (eg compress & gzip)
	# we compare the device & inode.
	PROG_STAT_INFO=`stat -f '%d %i' "$1"`
	for CHECK in $CHECK_LIST; do
		if test -f "$CHECK"; then
			CHECK_STAT_INFO=`stat -f '%d %i' "$CHECK"`
			if test "X$PROG_STAT_INFO" == "X$CHECK_STAT_INFO"; then
				echo "$prog: cannot compress $1, it is the same file as $CHECK"
				return 1
			fi
		fi
	done
}

# Compress a file
compress () {
	tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || {
		echo "$prog: cannot create tmp file"
		return 1
	}
	if ! cp "$1" "$tmp"; then
		echo "$prog: cannot copy $1 to $tmp"
		rm -f "$tmp"
		return 1
	fi
	if ! cp "$1" "$1"~; then
		echo "$prog: cannot create backup copy $1~"
		rm -f "$1"~ "$tmp"
		return 1
	fi

	# Use cp to overwrite the existing file preserving mode and owner
	# if possible. If the file is not writable, this will produce an
	# error.

	if header "$1" > "$tmp" && gzip -vc "$1" >> "$tmp"; then
		if ! cp "$tmp" "$1"; then
			echo "$prog: cannot copy $tmp to $1"
			rm -f "$tmp"
			return 1
		fi
	else
		echo "$prog: cannot compress $1"
		rm -f "$1"~ "$tmp"
		return 1
	fi
}

# Is the -d flag specified?
dflag=

# Return value
rc=0

if test "X$1" = X-d; then
	dflag=1
	shift
fi

prog=`basename "$0"`
USAGE="usage: $prog [-d] file ..."
if test $# -eq 0; then
	echo $USAGE
	exit 1
fi

while test $# -ne 0; do
	if test $dflag; then
		if ! compressed "$1"; then
			echo "$prog: $1 is not compressed"
			rc=1;
		elif ! decompress "$1"; then
			rc=$?
		fi
	else
		if compressed "$1"; then
			echo "$prog: $1 is already compressed"
			rc=1;
		elif ! check "$1" || ! compress "$1"; then
			rc=$?
		fi
	fi
	shift
done
exit $rc