1#!/bin/sh -
2#
3# $NetBSD: gzexe,v 1.3 2004/05/01 08:22:41 wiz Exp $
4#
5# $OpenBSD: gzexe,v 1.3 2003/08/05 18:22:17 deraadt 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)
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
108# Compress a file
109compress () {
110          tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || {
111                    echo "$prog: cannot create tmp file"
112                    return 1
113          }
114          if ! cp "$1" "$tmp"; then
115                    echo "$prog: cannot copy $1 to $tmp"
116                    rm -f "$tmp"
117                    return 1
118          fi
119          if ! cp "$1" "$1"~; then
120                    echo "$prog: cannot create backup copy $1~"
121                    rm -f "$1"~ "$tmp"
122                    return 1
123          fi
124
125          # Use cp to overwrite the existing file preserving mode and owner
126          # if possible. If the file is not writable, this will produce an
127          # error.
128
129          if header "$1" > "$tmp" && gzip -vc "$1" >> "$tmp"; then
130                    if ! cp "$tmp" "$1"; then
131                              echo "$prog: cannot copy $tmp to $1"
132                              rm -f "$tmp"
133                              return 1
134                    fi
135          else
136                    echo "$prog: cannot compress $1"
137                    rm -f "$1"~ "$tmp"
138                    return 1
139          fi
140}
141
142# Is the -d flag specified?
143dflag=
144
145# Return value
146rc=0
147
148if test "X$1" = X-d; then
149          dflag=1
150          shift
151fi
152
153prog=`basename "$0"`
154USAGE="usage: $prog [-d] file ..."
155if test $# -eq 0; then
156          echo $USAGE
157          exit 1
158fi
159
160while test $# -ne 0; do
161          if test $dflag; then
162                    if ! compressed "$1"; then
163                              echo "$prog: $1 is not compressed"
164                              rc=1;
165                    elif ! decompress "$1"; then
166                              rc=$?
167                    fi
168          else
169                    if compressed "$1"; then
170                              echo "$prog: $1 is already compressed"
171                              rc=1;
172                    elif ! check "$1" || ! compress "$1"; then
173                              rc=$?
174                    fi
175          fi
176          shift
177done
178exit $rc
179