/* * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * A stripped-down version of Jar tool with a "-encoding" option to * support non-UTF8 encoidng for entry name and comment.
*/ publicclass zip {
String program;
PrintStream out, err;
String fname;
String zname = "";
String[] files;
Charset cs = Charset.forName("UTF-8");
Map<String, File> entryMap = new HashMap<>();
Set<File> entries = new LinkedHashSet<>();
List<String> paths = new ArrayList<>();
privatestatic ResourceBundle rsrc; static { try { // just use the jar message
rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
} catch (MissingResourceException e) { thrownew Error("Fatal: Resource for jar is missing");
}
}
publicsynchronizedboolean run(String args[]) {
ok = true; if (!parseArgs(args)) { returnfalse;
} try { if (cflag || uflag) { if (fname != null) {
zname = fname.replace(File.separatorChar, '/'); if (zname.startsWith("./")) {
zname = zname.substring(2);
}
}
} if (cflag) {
OutputStream out; if (fname != null) {
out = new FileOutputStream(fname);
} else {
out = new FileOutputStream(FileDescriptor.out); if (vflag) {
vflag = false;
}
}
expand(null, files, false);
create(new BufferedOutputStream(out, 4096));
out.close();
} elseif (uflag) {
File inputFile = null, tmpFile = null;
FileInputStream in;
FileOutputStream out; if (fname != null) {
inputFile = new File(fname);
String path = inputFile.getParent();
tmpFile = File.createTempFile("tmp", null, new File((path == null) ? "." : path));
in = new FileInputStream(inputFile);
out = new FileOutputStream(tmpFile);
} else {
in = new FileInputStream(FileDescriptor.in);
out = new FileOutputStream(FileDescriptor.out);
vflag = false;
}
expand(null, files, true); boolean updateOk = update(in, new BufferedOutputStream(out)); if (ok) {
ok = updateOk;
}
in.close();
out.close(); if (fname != null) {
inputFile.delete(); if (!tmpFile.renameTo(inputFile)) {
tmpFile.delete(); thrownew IOException(getMsg("error.write.file"));
}
tmpFile.delete();
}
} elseif (tflag) {
replaceFSC(files); if (fname != null) {
list(fname, files);
} else {
InputStream in = new FileInputStream(FileDescriptor.in); try{
list(new BufferedInputStream(in), files);
} finally {
in.close();
}
}
} elseif (xflag) {
replaceFSC(files); if (fname != null && files != null) {
extract(fname, files);
} else {
InputStream in = (fname == null)
? new FileInputStream(FileDescriptor.in)
: new FileInputStream(fname); try {
extract(new BufferedInputStream(in), files);
} finally {
in.close();
}
}
}
} catch (IOException e) {
fatalError(e);
ok = false;
} catch (Error ee) {
ee.printStackTrace();
ok = false;
} catch (Throwable t) {
t.printStackTrace();
ok = false;
}
out.flush();
err.flush(); return ok;
}
boolean parseArgs(String args[]) { try {
args = parse(args);
} catch (FileNotFoundException e) {
fatalError(formatMsg("error.cant.open", e.getMessage())); returnfalse;
} catch (IOException e) {
fatalError(e); returnfalse;
} int count = 1; try {
String flags = args[0]; if (flags.startsWith("-")) {
flags = flags.substring(1);
} for (int i = 0; i < flags.length(); i++) { switch (flags.charAt(i)) { case'c': if (xflag || tflag || uflag) {
usageError(); returnfalse;
}
cflag = true; break; case'u': if (cflag || xflag || tflag) {
usageError(); returnfalse;
}
uflag = true; break; case'x': if (cflag || uflag || tflag) {
usageError(); returnfalse;
}
xflag = true; break; case't': if (cflag || uflag || xflag) {
usageError(); returnfalse;
}
tflag = true; break; case'v':
vflag = true; break; case'f':
fname = args[count++]; break; case'0':
flag0 = true; break; default:
error(formatMsg("error.illegal.option",
String.valueOf(flags.charAt(i))));
usageError(); returnfalse;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
usageError(); returnfalse;
} if (!cflag && !tflag && !xflag && !uflag) {
error(getMsg("error.bad.option"));
usageError(); returnfalse;
} /* parse file arguments */ int n = args.length - count; if (n > 0) { int k = 0;
String[] nameBuf = new String[n]; try { for (int i = count; i < args.length; i++) { if (args[i].equals("-encoding")) {
cs = Charset.forName(args[++i]);
} elseif (args[i].equals("-C")) { /* change the directory */
String dir = args[++i];
dir = (dir.endsWith(File.separator) ?
dir : (dir + File.separator));
dir = dir.replace(File.separatorChar, '/'); while (dir.indexOf("//") > -1) {
dir = dir.replace("//", "/");
}
paths.add(dir.replace(File.separatorChar, '/'));
nameBuf[k++] = dir + args[++i];
} else {
nameBuf[k++] = args[i];
}
}
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
usageError(); returnfalse;
} if (k != 0) {
files = new String[k];
System.arraycopy(nameBuf, 0, files, 0, k);
}
} elseif (cflag || uflag) {
error(getMsg("error.bad.uflag"));
usageError(); returnfalse;
} returntrue;
}
void expand(File dir, String[] files, boolean isUpdate) { if (files == null) { return;
} for (int i = 0; i < files.length; i++) {
File f; if (dir == null) {
f = new File(files[i]);
} else {
f = new File(dir, files[i]);
} if (f.isFile()) { if (entries.add(f)) { if (isUpdate)
entryMap.put(entryName(f.getPath()), f);
}
} elseif (f.isDirectory()) { if (entries.add(f)) { if (isUpdate) {
String dirPath = f.getPath();
dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
(dirPath + File.separator);
entryMap.put(entryName(dirPath), f);
}
expand(f, f.list(), isUpdate);
}
} else {
error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
ok = false;
}
}
}
void create(OutputStream out) throws IOException
{ try (ZipOutputStream zos = new ZipOutputStream(out, cs)) { if (flag0) {
zos.setMethod(ZipOutputStream.STORED);
} for (File file: entries) {
addFile(zos, file);
}
}
}
boolean update(InputStream in, OutputStream out) throws IOException { try (ZipInputStream zis = new ZipInputStream(in, cs);
ZipOutputStream zos = new ZipOutputStream(out, cs))
{
ZipEntry e = null; byte[] buf = newbyte[1024]; int n = 0;
// put the old entries first, replace if necessary while ((e = zis.getNextEntry()) != null) {
String name = e.getName(); if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression
ZipEntry e2 = new ZipEntry(name);
e2.setMethod(e.getMethod());
e2.setTime(e.getTime());
e2.setComment(e.getComment());
e2.setExtra(e.getExtra()); if (e.getMethod() == ZipEntry.STORED) {
e2.setSize(e.getSize());
e2.setCrc(e.getCrc());
}
zos.putNextEntry(e2); while ((n = zis.read(buf, 0, buf.length)) != -1) {
zos.write(buf, 0, n);
}
} else { // replace with the new files
File f = entryMap.get(name);
addFile(zos, f);
entryMap.remove(name);
entries.remove(f);
}
}
// add the remaining new files for (File f : entries) {
addFile(zos, f);
}
} returntrue;
}
private String entryName(String name) {
name = name.replace(File.separatorChar, '/');
String matchPath = ""; for (String path : paths) { if (name.startsWith(path) && (path.length() > matchPath.length())) {
matchPath = path;
}
}
name = name.substring(matchPath.length());
if (name.startsWith("/")) {
name = name.substring(1);
} elseif (name.startsWith("./")) {
name = name.substring(2);
} return name;
}
void addFile(ZipOutputStream zos, File file) throws IOException {
String name = file.getPath(); boolean isDir = file.isDirectory(); if (isDir) {
name = name.endsWith(File.separator) ? name :
(name + File.separator);
}
name = entryName(name);
if (name.equals("") || name.equals(".") || name.equals(zname)) { return;
}
long size = isDir ? 0 : file.length();
if (vflag) {
out.print(formatMsg("out.adding", name));
}
ZipEntry e = new ZipEntry(name);
e.setTime(file.lastModified()); if (size == 0) {
e.setMethod(ZipEntry.STORED);
e.setSize(0);
e.setCrc(0);
} elseif (flag0) {
e.setSize(size);
e.setMethod(ZipEntry.STORED);
crc32File(e, file);
}
zos.putNextEntry(e); if (!isDir) { byte[] buf = newbyte[8192]; int len;
InputStream is = new BufferedInputStream(new FileInputStream(file)); while ((len = is.read(buf, 0, buf.length)) != -1) {
zos.write(buf, 0, len);
}
is.close();
}
zos.closeEntry(); /* report how much compression occurred. */ if (vflag) {
size = e.getSize(); long csize = e.getCompressedSize();
out.print(formatMsg2("out.size", String.valueOf(size),
String.valueOf(csize))); if (e.getMethod() == ZipEntry.DEFLATED) { long ratio = 0; if (size != 0) {
ratio = ((size - csize) * 100) / size;
}
output(formatMsg("out.deflated", String.valueOf(ratio)));
} else {
output(getMsg("out.stored"));
}
}
}
privatevoid crc32File(ZipEntry e, File f) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(f)); byte[] buf = newbyte[8192];
crc32.reset(); int r = 0; int nread = 0; long len = f.length(); while ((r = is.read(buf)) != -1) {
nread += r;
crc32.update(buf, 0, r);
}
is.close(); if (nread != (int) len) { thrownew ZipException(formatMsg( "error.incorrect.length", f.getPath()));
}
e.setCrc(crc32.getValue());
}
void printEntry(ZipEntry e, String[] files) throws IOException { if (files == null) {
printEntry(e);
} else {
String name = e.getName(); for (String file : files) { if (name.startsWith(file)) {
printEntry(e); return;
}
}
}
}
void printEntry(ZipEntry e) throws IOException { if (vflag) {
StringBuilder sb = new StringBuilder();
String s = Long.toString(e.getSize()); for (int i = 6 - s.length(); i > 0; --i) {
sb.append(' ');
}
sb.append(s).append(' ').append(new Date(e.getTime()).toString());
sb.append(' ').append(e.getName());
output(sb.toString());
} else {
output(e.getName());
}
}
void usageError() {
error( "Usage: zip {ctxu}[vf0] [zip-file] [-encoding encname][-C dir] files ...\n" + "Options:\n" + " -c create new archive\n" + " -t list table of contents for archive\n" + " -x extract named (or all) files from archive\n" + " -u update existing archive\n" + " -v generate verbose output on standard output\n" + " -f specify archive file name\n" + " -0 store only; use no ZIP compression\n" + " -C change to the specified directory and include the following file\n" + "If any file is a directory then it is processed recursively.\n");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.