Resurrect z*grep script to support gzip'ped files.
[dragonfly.git] / usr.bin / gzip / gzexe
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
23 lines=19
24
25 # A simple string to recognize already compressed files
26 magic="# compressed by gzexe"
27
28 # Write the decompression script to stdout
29 header () {
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
56 compressed () {
57         test "X`sed -n 2p "$1" 2> /dev/null`" = "X$magic"
58 }
59
60 # Decompress a file
61 decompress () {
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
80 check () {
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
141 compress () {
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?
175 dflag=
176
177 # Return value
178 rc=0
179
180 if test "X$1" = X-d; then
181         dflag=1
182         shift
183 fi
184
185 prog=`basename "$0"`
186 USAGE="usage: $prog [-d] file ..."
187 if test $# -eq 0; then
188         echo $USAGE
189         exit 1
190 fi
191
192 while 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
209 done
210 exit $rc