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 -f "$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.
268 test "x$d" = x && continue
271 -*) pathcomp=./$pathcomp ;;
274 if test ! -d "$pathcomp"; then
275 mkdir "$pathcomp" || lasterr=$?
276 test -d "$pathcomp" || errstatus=$lasterr
285 # On NextStep and OpenStep, the `mkdir' command does not
286 # recognize any option. It will interpret all options as
287 # directories to create, and then abort because `.' already
289 if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
292 mkdir_p='func_mkdir_p'
293 test -d ./-p && rmdir ./-p
294 test -d ./--version && rmdir ./--version
297 # Process the first command line option.
299 -*) commands=`echo X"$1" | sed 's/^X-//' ` ;;
304 # Operation to perform on the JAR file
307 # First -C option on the command line
310 # Base directory for -C options
312 # JAR file to operate on
315 # default for no {m,M} option, user for "m" option, none for "M" option
316 manifest_kind=default
318 # "-0" if the "0" option was given
321 # true if the "v" option was given
324 # true if the non-standard "@" option was given
325 process_response_files=false
327 # An exec command if we need to redirect the zip/unzip commands' output
330 while test -n "$commands"; do
331 # Process a letter at a time
332 command=`expr "$commands" : '\(.\)'`
333 commands=`expr "$commands" : '.\(.*\)'`
350 # Multiple "f" options are accepted by Sun's JAR tool.
352 test -z "$jarfile" && usage
357 # Multiple "m" options are accepted by Sun's JAR tool, but
358 # M always overrides m.
359 test "$manifest_kind" = default && manifest_kind=user
361 test -z "$manifest_file" && usage
371 # Not yet implemented, and probably never will.
382 process_response_files=: ;;
392 # Work on stdin/stdout. Messages go to stderr, and if we need an input
393 # JAR file we save it temporarily in the temporary directory.
395 $mkdir_p "$JARTMP"/out
396 jarfile="$JARTMP"/out/tmp-stdin.jar
397 out_redirect='exec >&2'
400 if $process_response_files && test $# = 0; then
401 error Cannot use stdin for response file.
403 cat > "$JARTMP"/out/tmp-stdin.jar
409 # Make an absolute path.
410 dir=`dirname "$jarfile"`
411 jarfile=`cd $dir && pwd`/`basename "$jarfile"`
415 # Make an absolute path from a filename in the current directory.
416 jarfile=`pwd`/`basename "$jarfile"`
420 # Perform a -C option if given right away.
431 # Extract the list of files in the JAR file
432 jar_list "$jarfile" > "$JARTMP"/list
434 # If there are files on the command line, expand directories and skip -C
435 # command line arguments
446 escaped=`echo "X$arg" | sed 's/^X//; s/[].[^$\\*]/\\\\&/g' `
447 grep "^$escaped/" "$JARTMP"/list >> "$JARTMP"/chosen || :
448 grep "^$escaped\$" "$JARTMP"/list >> "$JARTMP"/chosen || :
451 test -f "$JARTMP"/chosen || cp "$JARTMP"/list "$JARTMP"/chosen
453 # Really execute unzip
455 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" | \
456 sed -ne 's/^ creating/ created/p' -e 's/^ inflating/extracted/p'
458 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" > /dev/null
464 $mkdir_p "$JARTMP"/out
465 $mkdir_p "$JARTMP"/files
467 # Do not overwrite the JAR file if something goes wrong
468 tmp_jarfile="$JARTMP"/out/`basename "$jarfile"`
470 # Prepare the files in the temporary directory. This is necessary to
471 # support -C and still save relative paths in the JAR file.
473 if test $manifest_kind != none; then
474 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
479 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -rv "$tmp_jarfile" $store .)
481 (cd "$JARTMP/files" && $ZIP -r "$tmp_jarfile" $store . > /dev/null)
483 test "$jarfile" = "$tmp_jarfile" || mv "$tmp_jarfile" "$jarfile"
488 $mkdir_p "$JARTMP"/files
491 # Same as above, but zip takes care of not overwriting the file
492 case $manifest_kind in
494 $verbose && (eval $out_redirect; echo removing manifest)
495 $ZIP -d "$jarfile" META-INF/MANIFEST.MF > /dev/null 2>&1 || :
498 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
502 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -ruv "$jarfile" $store .)
504 (cd "$JARTMP"/files && $ZIP -ru "$jarfile" $store . > /dev/null)
509 # Everything's done in the functions
511 jar_list_verbose "$jarfile"
517 if test "$out_redirect" != :; then
518 # Cat back to stdout if necessary
520 create|update) cat "$JARTMP"/out/tmp-stdin.jar ;;