6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 import java.io.*;
25 import java.nio.charset.Charset;
26 import java.util.*;
27 import java.util.zip.*;
28 import java.text.MessageFormat;
29
30 /**
31 * A stripped-down version of Jar tool with a "-encoding" option to
32 * support non-UTF8 encoidng for entry name and comment.
33 */
34 public class zip {
35 String program;
36 PrintStream out, err;
37 String fname;
38 String zname = "";
39 String[] files;
40 Charset cs = Charset.forName("UTF-8");
41
42 Map<String, File> entryMap = new HashMap<String, File>();
43 Set<File> entries = new LinkedHashSet<File>();
44 List<String> paths = new ArrayList<String>();
45
46 CRC32 crc32 = new CRC32();
47 /*
48 * cflag: create
49 * uflag: update
50 * xflag: xtract
51 * tflag: table
52 * vflag: verbose
53 * flag0: no zip compression (store only)
54 */
55 boolean cflag, uflag, xflag, tflag, vflag, flag0;
56
57 private static ResourceBundle rsrc;
58 static {
59 try {
60 // just use the jar message
61 rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
62 } catch (MissingResourceException e) {
63 throw new Error("Fatal: Resource for jar is missing");
64 }
313 }
314 } else {
315 error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
316 ok = false;
317 }
318 }
319 }
320
321 void create(OutputStream out) throws IOException
322 {
323 try (ZipOutputStream zos = new ZipOutputStream(out, cs)) {
324 if (flag0) {
325 zos.setMethod(ZipOutputStream.STORED);
326 }
327 for (File file: entries) {
328 addFile(zos, file);
329 }
330 }
331 }
332
333 boolean update(InputStream in, OutputStream out) throws IOException
334 {
335 try (ZipInputStream zis = new ZipInputStream(in, cs);
336 ZipOutputStream zos = new ZipOutputStream(out, cs))
337 {
338 ZipEntry e = null;
339 byte[] buf = new byte[1024];
340 int n = 0;
341 boolean updateOk = true;
342
343 // put the old entries first, replace if necessary
344 while ((e = zis.getNextEntry()) != null) {
345 String name = e.getName();
346 if (!entryMap.containsKey(name)) { // copy the old stuff
347 // do our own compression
348 ZipEntry e2 = new ZipEntry(name);
349 e2.setMethod(e.getMethod());
350 e2.setTime(e.getTime());
351 e2.setComment(e.getComment());
352 e2.setExtra(e.getExtra());
353 if (e.getMethod() == ZipEntry.STORED) {
354 e2.setSize(e.getSize());
355 e2.setCrc(e.getCrc());
356 }
357 zos.putNextEntry(e2);
358 while ((n = zis.read(buf, 0, buf.length)) != -1) {
359 zos.write(buf, 0, n);
360 }
361 } else { // replace with the new files
362 File f = entryMap.get(name);
363 addFile(zos, f);
364 entryMap.remove(name);
365 entries.remove(f);
366 }
367 }
368
369 // add the remaining new files
370 for (File f: entries) {
371 addFile(zos, f);
372 }
373 }
374 return updateOk;
375 }
376
377 private String entryName(String name) {
378 name = name.replace(File.separatorChar, '/');
379 String matchPath = "";
380 for (String path : paths) {
381 if (name.startsWith(path) && (path.length() > matchPath.length())) {
382 matchPath = path;
383 }
384 }
385 name = name.substring(matchPath.length());
386
387 if (name.startsWith("/")) {
388 name = name.substring(1);
389 } else if (name.startsWith("./")) {
390 name = name.substring(2);
391 }
392 return name;
393 }
394
462 crc32.update(buf, 0, r);
463 }
464 is.close();
465 if (nread != (int) len) {
466 throw new ZipException(formatMsg(
467 "error.incorrect.length", f.getPath()));
468 }
469 e.setCrc(crc32.getValue());
470 }
471
472 void replaceFSC(String files[]) {
473 if (files != null) {
474 for (String file : files) {
475 file = file.replace(File.separatorChar, '/');
476 }
477 }
478 }
479
480 Set<ZipEntry> newDirSet() {
481 return new HashSet<ZipEntry>() {
482 public boolean add(ZipEntry e) {
483 return (e == null || super.add(e));
484 }};
485 }
486
487 void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException {
488 for (ZipEntry ze : zes) {
489 long lastModified = ze.getTime();
490 if (lastModified != -1) {
491 File f = new File(ze.getName().replace('/', File.separatorChar));
492 f.setLastModified(lastModified);
493 }
494 }
495 }
496
497 void extract(InputStream in, String files[]) throws IOException {
498 ZipInputStream zis = new ZipInputStream(in, cs);
499 ZipEntry e;
500 Set<ZipEntry> dirs = newDirSet();
501 while ((e = zis.getNextEntry()) != null) {
503 dirs.add(extractFile(zis, e));
504 } else {
505 String name = e.getName();
506 for (String file : files) {
507 if (name.startsWith(file)) {
508 dirs.add(extractFile(zis, e));
509 break;
510 }
511 }
512 }
513 }
514 updateLastModifiedTime(dirs);
515 }
516
517 void extract(String fname, String files[]) throws IOException {
518 try (ZipFile zf = new ZipFile(fname, cs)) {
519 Set<ZipEntry> dirs = newDirSet();
520 Enumeration<? extends ZipEntry> zes = zf.entries();
521 while (zes.hasMoreElements()) {
522 ZipEntry e = zes.nextElement();
523 InputStream is;
524 if (files == null) {
525 dirs.add(extractFile(zf.getInputStream(e), e));
526 } else {
527 String name = e.getName();
528 for (String file : files) {
529 if (name.startsWith(file)) {
530 dirs.add(extractFile(zf.getInputStream(e), e));
531 break;
532 }
533 }
534 }
535 }
536 }
537 updateLastModifiedTime(dirs);
538 }
539
540 ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
541 ZipEntry rc = null;
542 String name = e.getName();
543 File f = new File(e.getName().replace('/', File.separatorChar));
544 if (e.isDirectory()) {
545 if (f.exists()) {
546 if (!f.isDirectory()) {
547 throw new IOException(formatMsg("error.create.dir",
548 f.getPath()));
549 }
550 } else {
551 if (!f.mkdirs()) {
552 throw new IOException(formatMsg("error.create.dir",
553 f.getPath()));
554 } else {
555 rc = e;
556 }
557 }
710 } else {
711 loadCmdFile(arg, newArgs);
712 }
713 } else {
714 newArgs.add(arg);
715 }
716 }
717 return newArgs.toArray(new String[newArgs.size()]);
718 }
719
720 private static void loadCmdFile(String name, List<String> args) throws IOException
721 {
722 Reader r = new BufferedReader(new FileReader(name));
723 StreamTokenizer st = new StreamTokenizer(r);
724 st.resetSyntax();
725 st.wordChars(' ', 255);
726 st.whitespaceChars(0, ' ');
727 st.commentChar('#');
728 st.quoteChar('"');
729 st.quoteChar('\'');
730 while (st.nextToken() != st.TT_EOF) {
731 args.add(st.sval);
732 }
733 r.close();
734 }
735
736 public static void main(String args[]) {
737 zip z = new zip(System.out, System.err, "zip");
738 System.exit(z.run(args) ? 0 : 1);
739 }
740 }
741
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 import java.io.*;
25 import java.nio.charset.Charset;
26 import java.text.MessageFormat;
27 import java.util.*;
28 import java.util.zip.CRC32;
29 import java.util.zip.ZipEntry;
30 import java.util.zip.ZipException;
31 import java.util.zip.ZipFile;
32 import java.util.zip.ZipInputStream;
33 import java.util.zip.ZipOutputStream;
34
35 /**
36 * A stripped-down version of Jar tool with a "-encoding" option to
37 * support non-UTF8 encoidng for entry name and comment.
38 */
39 public class zip {
40 String program;
41 PrintStream out, err;
42 String fname;
43 String zname = "";
44 String[] files;
45 Charset cs = Charset.forName("UTF-8");
46
47 Map<String, File> entryMap = new HashMap<>();
48 Set<File> entries = new LinkedHashSet<>();
49 List<String> paths = new ArrayList<>();
50
51 CRC32 crc32 = new CRC32();
52 /*
53 * cflag: create
54 * uflag: update
55 * xflag: xtract
56 * tflag: table
57 * vflag: verbose
58 * flag0: no zip compression (store only)
59 */
60 boolean cflag, uflag, xflag, tflag, vflag, flag0;
61
62 private static ResourceBundle rsrc;
63 static {
64 try {
65 // just use the jar message
66 rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
67 } catch (MissingResourceException e) {
68 throw new Error("Fatal: Resource for jar is missing");
69 }
318 }
319 } else {
320 error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
321 ok = false;
322 }
323 }
324 }
325
326 void create(OutputStream out) throws IOException
327 {
328 try (ZipOutputStream zos = new ZipOutputStream(out, cs)) {
329 if (flag0) {
330 zos.setMethod(ZipOutputStream.STORED);
331 }
332 for (File file: entries) {
333 addFile(zos, file);
334 }
335 }
336 }
337
338 boolean update(InputStream in, OutputStream out) throws IOException {
339 try (ZipInputStream zis = new ZipInputStream(in, cs);
340 ZipOutputStream zos = new ZipOutputStream(out, cs))
341 {
342 ZipEntry e = null;
343 byte[] buf = new byte[1024];
344 int n = 0;
345
346 // put the old entries first, replace if necessary
347 while ((e = zis.getNextEntry()) != null) {
348 String name = e.getName();
349 if (!entryMap.containsKey(name)) { // copy the old stuff
350 // do our own compression
351 ZipEntry e2 = new ZipEntry(name);
352 e2.setMethod(e.getMethod());
353 e2.setTime(e.getTime());
354 e2.setComment(e.getComment());
355 e2.setExtra(e.getExtra());
356 if (e.getMethod() == ZipEntry.STORED) {
357 e2.setSize(e.getSize());
358 e2.setCrc(e.getCrc());
359 }
360 zos.putNextEntry(e2);
361 while ((n = zis.read(buf, 0, buf.length)) != -1) {
362 zos.write(buf, 0, n);
363 }
364 } else { // replace with the new files
365 File f = entryMap.get(name);
366 addFile(zos, f);
367 entryMap.remove(name);
368 entries.remove(f);
369 }
370 }
371
372 // add the remaining new files
373 for (File f : entries) {
374 addFile(zos, f);
375 }
376 }
377 return true;
378 }
379
380 private String entryName(String name) {
381 name = name.replace(File.separatorChar, '/');
382 String matchPath = "";
383 for (String path : paths) {
384 if (name.startsWith(path) && (path.length() > matchPath.length())) {
385 matchPath = path;
386 }
387 }
388 name = name.substring(matchPath.length());
389
390 if (name.startsWith("/")) {
391 name = name.substring(1);
392 } else if (name.startsWith("./")) {
393 name = name.substring(2);
394 }
395 return name;
396 }
397
465 crc32.update(buf, 0, r);
466 }
467 is.close();
468 if (nread != (int) len) {
469 throw new ZipException(formatMsg(
470 "error.incorrect.length", f.getPath()));
471 }
472 e.setCrc(crc32.getValue());
473 }
474
475 void replaceFSC(String files[]) {
476 if (files != null) {
477 for (String file : files) {
478 file = file.replace(File.separatorChar, '/');
479 }
480 }
481 }
482
483 Set<ZipEntry> newDirSet() {
484 return new HashSet<ZipEntry>() {
485 private static final long serialVersionUID = 4547977575248028254L;
486
487 public boolean add(ZipEntry e) {
488 return (e == null || super.add(e));
489 }};
490 }
491
492 void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException {
493 for (ZipEntry ze : zes) {
494 long lastModified = ze.getTime();
495 if (lastModified != -1) {
496 File f = new File(ze.getName().replace('/', File.separatorChar));
497 f.setLastModified(lastModified);
498 }
499 }
500 }
501
502 void extract(InputStream in, String files[]) throws IOException {
503 ZipInputStream zis = new ZipInputStream(in, cs);
504 ZipEntry e;
505 Set<ZipEntry> dirs = newDirSet();
506 while ((e = zis.getNextEntry()) != null) {
508 dirs.add(extractFile(zis, e));
509 } else {
510 String name = e.getName();
511 for (String file : files) {
512 if (name.startsWith(file)) {
513 dirs.add(extractFile(zis, e));
514 break;
515 }
516 }
517 }
518 }
519 updateLastModifiedTime(dirs);
520 }
521
522 void extract(String fname, String files[]) throws IOException {
523 try (ZipFile zf = new ZipFile(fname, cs)) {
524 Set<ZipEntry> dirs = newDirSet();
525 Enumeration<? extends ZipEntry> zes = zf.entries();
526 while (zes.hasMoreElements()) {
527 ZipEntry e = zes.nextElement();
528 if (files == null) {
529 dirs.add(extractFile(zf.getInputStream(e), e));
530 } else {
531 String name = e.getName();
532 for (String file : files) {
533 if (name.startsWith(file)) {
534 dirs.add(extractFile(zf.getInputStream(e), e));
535 break;
536 }
537 }
538 }
539 }
540 updateLastModifiedTime(dirs);
541 }
542 }
543
544 ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
545 ZipEntry rc = null;
546 String name = e.getName();
547 File f = new File(e.getName().replace('/', File.separatorChar));
548 if (e.isDirectory()) {
549 if (f.exists()) {
550 if (!f.isDirectory()) {
551 throw new IOException(formatMsg("error.create.dir",
552 f.getPath()));
553 }
554 } else {
555 if (!f.mkdirs()) {
556 throw new IOException(formatMsg("error.create.dir",
557 f.getPath()));
558 } else {
559 rc = e;
560 }
561 }
714 } else {
715 loadCmdFile(arg, newArgs);
716 }
717 } else {
718 newArgs.add(arg);
719 }
720 }
721 return newArgs.toArray(new String[newArgs.size()]);
722 }
723
724 private static void loadCmdFile(String name, List<String> args) throws IOException
725 {
726 Reader r = new BufferedReader(new FileReader(name));
727 StreamTokenizer st = new StreamTokenizer(r);
728 st.resetSyntax();
729 st.wordChars(' ', 255);
730 st.whitespaceChars(0, ' ');
731 st.commentChar('#');
732 st.quoteChar('"');
733 st.quoteChar('\'');
734 while (st.nextToken() != StreamTokenizer.TT_EOF) {
735 args.add(st.sval);
736 }
737 r.close();
738 }
739
740 public static void main(String args[]) {
741 zip z = new zip(System.out, System.err, "zip");
742 System.exit(z.run(args) ? 0 : 1);
743 }
744 }
|