2 # Copyright (C) 2006 Free Software Foundation
3 # Written by Paolo Bonzini.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published
7 # by the Free Software Foundation; either version 2 of the License,
8 # or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # POSIX and NLS nuisances, taken from autoconf.
21 if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
24 # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
25 # is contrary to our usage. Disable this feature.
26 alias -g '${1+"$@"}'='"$@"'
29 case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
31 BIN_SH=xpg4; export BIN_SH # for Tru64
32 DUALCASE=1; export DUALCASE # for MKS sh
34 if test "${LANG+set}" = set; then LANG=C; export LANG; fi
35 if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
36 if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
37 if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
39 # Also make sure CDPATH is empty, and IFS is space, tab, \n in that order.
40 # Be careful to avoid that editors munge IFS
41 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
50 # Emit a usage message and exit with error status 1
53 Usage: $0 {ctxu}[vfm0Mi@] [jar-file] [manifest-file] {[-C dir] files} ...
56 -t list table of contents for archive
57 -x extract named (or all) files from archive
58 -u update existing archive
59 -v generate verbose output on standard output
60 -f specify archive file name
61 -m include manifest information from specified manifest file
62 -0 store only; use no ZIP compression
63 -M do not create a manifest file for the entries
64 -i generate index information for the specified jar files
65 -@ instead of {[-C dir] files} ... accept one or more response files,
66 each containing one command-line argument
67 -C change to the specified directory and include the following file
68 If any file is a directory then it is processed recursively.
69 The manifest file name and the archive file name needs to be specified
70 in the same order the 'm' and 'f' flags are specified.
72 Example 1: to archive two class files into an archive called classes.jar:
73 jar cvf classes.jar Foo.class Bar.class
74 Example 2: use an existing manifest file 'mymanifest' and archive all the
75 files in the foo/ directory into 'classes.jar':
76 jar cvfm classes.jar mymanifest -C foo/ .
82 # Emit an error message and exit with error status 1
84 echo "$progname: $*" >&2
88 # Usage: copy SRC DEST
89 # Copy file SRC to directory DEST, which is the staging area of the jar file.
90 # Fail if it is already present or if it is not a regular file.
93 # A simple optimization. Optimistically assuming that ln will work
94 # cuts 60% of the run-time!
95 if ln "$1" "$2"/"$1" > /dev/null 2>&1; then
99 if test -e "$2"/"$1"; then
100 error "$1": Duplicate entry.
104 ln "$1" "$2"/"$1" > /dev/null 2>&1 || cp "$1" "$2"/"$1"
105 elif test -e "$1"; then
106 error "$1": Invalid file type.
108 error "$1": File not found.
112 # Make a temporary directory and store its name in the JARTMP variable.
114 test -n "$JARTMP" && return
117 JARTMP=`(umask 077 && mktemp -d "$TMPDIR/jarXXXXXX") 2>/dev/null` &&
118 test -n "$JARTMP" && test -d "$JARTMP"
120 JARTMP=$TMPDIR/jar$$-$RANDOM
121 (umask 077 && mkdir "$JARTMP")
125 if test -n "$JARTMP"; then rm -rf "$JARTMP"; fi
129 # Usage: make_manifest destfile kind [source-manifest]
130 # Create a manifest file and store it in destfile. KIND can be "default",
131 # or "user", in which case SOURCE-MANIFEST must be specified as well.
138 Manifest-Version: 1.0
139 Created-By: @VERSION@
149 # Usage: set_var var [value]
150 # Exit with an error if set_var was already called for the same VAR. Else
151 # set the variable VAR to the value VALUE (or the empty value if no parameter
154 if eval test x\$set_$1 = xset; then
155 error Incompatible or repeated options.
162 # Process the arguments, including -C options, and copy the whole tree
163 # to $JARTMP/files so that zip can be invoked later from there.
166 if $process_response_files; then
192 # Usage: make_files_1 ARG
193 # Process one argument, ARG.
208 cd `expr "$1" : '-C\(.*\)' `
212 if test -d "$1"; then
213 $mkdir_p "$JARTMP"/files/"$1"
214 find "$1" | while read file; do
215 if test -d "$file"; then
216 $mkdir_p "$JARTMP"/files/"$file"
218 copy "$file" "$JARTMP"/files
222 copy "$1" "$JARTMP"/files
229 # Same as "jar tf $1".
232 sed '1,/^ ----/d;/^ ----/,$d;s/^ *[0-9]* ..-..-.. ..:.. //'
235 # Same as "jar tvf $1".
236 jar_list_verbose () {
238 @AWK@ 'BEGIN { yes = 0 }
239 /^ ----/ { yes = !yes; next }
244 d[3] += (d[3] < 80) ? 2000 : 1900
245 timestamp=d[3] " " d[1] " " d[2] " " t[1] " " t[2] " 00"
246 gsub (/^ *[0-9]* ..-..-.. ..:.. /, "")
247 printf "%6d %s %s\n", size, strftime ("%a %b %d %H:%M:%S %Z %Y", mktime (timestamp)), $0
251 # mkdir -p emulation based on the mkinstalldirs script.
269 test "x$d" = x && continue
272 -*) pathcomp=./$pathcomp ;;
275 if test ! -d "$pathcomp"; then
276 mkdir "$pathcomp" || lasterr=$?
277 test -d "$pathcomp" || errstatus=$lasterr
286 # On NextStep and OpenStep, the `mkdir' command does not
287 # recognize any option. It will interpret all options as
288 # directories to create, and then abort because `.' already
290 if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
294 test -d ./-p && rmdir ./-p
295 test -d ./--version && rmdir ./--version
298 # Process the first command line option.
300 -*) commands=`echo X"$1" | sed 's/^X-//' ` ;;
305 # Operation to perform on the JAR file
308 # First -C option on the command line
311 # Base directory for -C options
313 # JAR file to operate on
316 # default for no {m,M} option, user for "m" option, none for "M" option
317 manifest_kind=default
319 # "-0" if the "0" option was given
322 # true if the "v" option was given
325 # true if the non-standard "@" option was given
326 process_response_files=false
328 # An exec command if we need to redirect the zip/unzip commands' output
331 while test -n "$commands"; do
332 # Process a letter at a time
333 command=`expr "$commands" : '\(.\)'`
334 commands=`expr "$commands" : '.\(.*\)'`
351 # Multiple "f" options are accepted by Sun's JAR tool.
353 test -z "$jarfile" && usage
358 # Multiple "m" options are accepted by Sun's JAR tool, but
359 # M always overrides m.
360 test "$manifest_kind" = default && manifest_kind=user
362 test -z "$manifest_file" && usage
372 # Not yet implemented, and probably never will.
383 process_response_files=: ;;
393 # Work on stdin/stdout. Messages go to stderr, and if we need an input
394 # JAR file we save it temporarily in the temporary directory.
396 $mkdir_p "$JARTMP"/out
397 jarfile="$JARTMP"/out/tmp-stdin.jar
398 out_redirect='exec >&2'
401 if $process_response_files && test $# = 0; then
402 error Cannot use stdin for response file.
404 cat > "$JARTMP"/out/tmp-stdin.jar
410 # Make an absolute path.
411 dir=`dirname "$jarfile"`
412 jarfile=`cd $dir && pwd`/`basename "$jarfile"`
416 # Make an absolute path from a filename in the current directory.
417 jarfile=`pwd`/`basename "$jarfile"`
421 # Perform a -C option if given right away.
432 # Extract the list of files in the JAR file
433 jar_list "$jarfile" > "$JARTMP"/list
435 # If there are files on the command line, expand directories and skip -C
436 # command line arguments
447 escaped=`echo "X$arg" | sed 's/^X//; s/[].[^$\\*]/\\\\&/g' `
448 grep "^$escaped/" "$JARTMP"/list >> "$JARTMP"/chosen || :
449 grep "^$escaped\$" "$JARTMP"/list >> "$JARTMP"/chosen || :
452 test -f "$JARTMP"/chosen || cp "$JARTMP"/list "$JARTMP"/chosen
454 # Really execute unzip
456 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" | \
457 sed -ne 's/^ creating/ created/p' -e 's/^ inflating/extracted/p'
459 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" > /dev/null
465 $mkdir_p "$JARTMP"/out
466 $mkdir_p "$JARTMP"/files
468 # Do not overwrite the JAR file if something goes wrong
469 tmp_jarfile="$JARTMP"/out/`basename "$jarfile"`
471 # Prepare the files in the temporary directory. This is necessary to
472 # support -C and still save relative paths in the JAR file.
474 if test $manifest_kind != none; then
475 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
480 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -rv "$tmp_jarfile" $store .)
482 (cd "$JARTMP/files" && $ZIP -r "$tmp_jarfile" $store . > /dev/null)
484 test "$jarfile" = "$tmp_jarfile" || mv "$tmp_jarfile" "$jarfile"
489 $mkdir_p "$JARTMP"/files
492 # Same as above, but zip takes care of not overwriting the file
493 case $manifest_kind in
495 $verbose && (eval $out_redirect; echo removing manifest)
496 $ZIP -d "$jarfile" META-INF/MANIFEST.MF > /dev/null 2>&1 || :
499 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
503 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -ruv "$jarfile" $store .)
505 (cd "$JARTMP"/files && $ZIP -ru "$jarfile" $store . > /dev/null)
510 # Everything's done in the functions
512 jar_list_verbose "$jarfile"
518 if test "$out_redirect" != :; then
519 # Cat back to stdout if necessary
521 create|update) cat "$JARTMP"/out/tmp-stdin.jar ;;