diff --git a/jdk/src/share/bin/jli_util.h b/jdk/src/share/bin/jli_util.h index af1ce47e6e4..568318c95c6 100644 --- a/jdk/src/share/bin/jli_util.h +++ b/jdk/src/share/bin/jli_util.h @@ -68,12 +68,23 @@ int JLI_GetStdArgc(); #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) #define JLI_Snprintf _snprintf void JLI_CmdToArgs(char *cmdline); -#else +#define JLI_Lseek _lseeki64 +#else /* NIXES */ #include #include #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3)) #define JLI_Snprintf snprintf +#ifdef __solaris__ +#define JLI_Lseek llseek +#endif +#ifdef __linux__ +#define _LARGFILE64_SOURCE +#define JLI_Lseek lseek64 +#endif +#ifdef MACOSX +#define JLI_Lseek lseek +#endif #endif /* _WIN32 */ /* diff --git a/jdk/src/share/bin/manifest_info.h b/jdk/src/share/bin/manifest_info.h index 44341f42cf5..cd951d5cb9f 100644 --- a/jdk/src/share/bin/manifest_info.h +++ b/jdk/src/share/bin/manifest_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -37,6 +37,8 @@ #define CENSIG 0x02014b50L /* "PK\001\002" */ #define ENDSIG 0x06054b50L /* "PK\005\006" */ +#define ZIP64_ENDSIG 0x06064b50L /* "PK\006\006" */ +#define ZIP64_LOCSIG 0x07064b50L /* "PK\006\007" */ /* * Header sizes including signatures */ @@ -45,12 +47,21 @@ #define CENHDR 46 #define ENDHDR 22 +#define ZIP64_ENDHDR 56 // ZIP64 end header size +#define ZIP64_LOCHDR 20 // ZIP64 end loc header size +#define ZIP64_EXTHDR 24 // EXT header size +#define ZIP64_EXTID 1 // Extra field Zip64 header ID + +#define ZIP64_MAGICVAL 0xffffffffLL +#define ZIP64_MAGICCOUNT 0xffff + /* * Header field access macros */ #define CH(b, n) (((unsigned char *)(b))[n]) #define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8)) -#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16)) +#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL) +#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32)) #define GETSIG(b) LG(b, 0) /* @@ -101,6 +112,26 @@ #define ENDOFF(b) LG(b, 16) /* central directory offset */ #define ENDCOM(b) SH(b, 20) /* size of zip file comment */ +/* + * Macros for getting Zip64 end of central directory header fields + */ +#define ZIP64_ENDLEN(b) LL(b, 4) /* size of zip64 end of central dir */ +#define ZIP64_ENDVEM(b) SH(b, 12) /* version made by */ +#define ZIP64_ENDVER(b) SH(b, 14) /* version needed to extract */ +#define ZIP64_ENDNMD(b) LG(b, 16) /* number of this disk */ +#define ZIP64_ENDDSK(b) LG(b, 20) /* disk number of start */ +#define ZIP64_ENDTOD(b) LL(b, 24) /* total number of entries on this disk */ +#define ZIP64_ENDTOT(b) LL(b, 32) /* total number of entries */ +#define ZIP64_ENDSIZ(b) LL(b, 40) /* central directory size in bytes */ +#define ZIP64_ENDOFF(b) LL(b, 48) /* offset of first CEN header */ + +/* + * Macros for getting Zip64 end of central directory locator fields + */ +#define ZIP64_LOCDSK(b) LG(b, 4) /* disk number start */ +#define ZIP64_LOCOFF(b) LL(b, 8) /* offset of zip64 end */ +#define ZIP64_LOCTOT(b) LG(b, 16) /* total number of disks */ + /* * A comment of maximum length of 64kb can follow the END record. This * is the furthest the END record can be from the end of the file. @@ -119,7 +150,7 @@ typedef struct zentry { /* Zip file entry */ size_t isize; /* size of inflated data */ size_t csize; /* size of compressed data (zero if uncompressed) */ - off_t offset; /* position of compressed data */ + jlong offset; /* position of compressed data */ int how; /* compression method (if any) */ } zentry; diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c index eb847bf690c..ec3014931f2 100644 --- a/jdk/src/share/bin/parse_manifest.c +++ b/jdk/src/share/bin/parse_manifest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -61,7 +61,7 @@ inflate_file(int fd, zentry *entry, int *size_out) if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 ) return (NULL); - if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0) + if (JLI_Lseek(fd, entry->offset, SEEK_SET) < (jlong)0) return (NULL); if ((in = malloc(entry->csize + 1)) == NULL) return (NULL); @@ -110,6 +110,38 @@ inflate_file(int fd, zentry *entry, int *size_out) return (NULL); } +static jboolean zip64_present = JNI_FALSE; + +/* + * Checks to see if we have ZIP64 archive, and save + * the check for later use + */ +static int +haveZIP64(Byte *p) { + jlong cenlen, cenoff, centot; + cenlen = ENDSIZ(p); + cenoff = ENDOFF(p); + centot = ENDTOT(p); + zip64_present = (cenlen == ZIP64_MAGICVAL || + cenoff == ZIP64_MAGICVAL || + centot == ZIP64_MAGICCOUNT); + return zip64_present; +} + +static jlong +find_end64(int fd, Byte *ep, jlong pos) +{ + jlong end64pos; + jlong bytes; + if ((end64pos = JLI_Lseek(fd, pos - ZIP64_LOCHDR, SEEK_SET)) < (jlong)0) + return -1; + if ((bytes = read(fd, ep, ZIP64_LOCHDR)) < 0) + return -1; + if (GETSIG(ep) == ZIP64_LOCSIG) + return end64pos; + return -1; +} + /* * A very little used routine to handle the case that zip file has * a comment at the end. Believe it or not, the only way to find the @@ -122,12 +154,12 @@ inflate_file(int fd, zentry *entry, int *size_out) * Returns the offset of the END record in the file on success, * -1 on failure. */ -static off_t +static jlong find_end(int fd, Byte *eb) { - off_t len; - off_t pos; - off_t flen; + jlong len; + jlong pos; + jlong flen; int bytes; Byte *cp; Byte *endpos; @@ -136,14 +168,16 @@ find_end(int fd, Byte *eb) /* * 99.44% (or more) of the time, there will be no comment at the * end of the zip file. Try reading just enough to read the END - * record from the end of the file. + * record from the end of the file, at this time we should also + * check to see if we have a ZIP64 archive. */ - if ((pos = lseek(fd, -ENDHDR, SEEK_END)) < (off_t)0) + if ((pos = JLI_Lseek(fd, -ENDHDR, SEEK_END)) < (jlong)0) return (-1); if ((bytes = read(fd, eb, ENDHDR)) < 0) return (-1); - if (GETSIG(eb) == ENDSIG) - return (pos); + if (GETSIG(eb) == ENDSIG) { + return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; + } /* * Shucky-Darn,... There is a comment at the end of the zip file. @@ -151,10 +185,10 @@ find_end(int fd, Byte *eb) * Allocate and fill a buffer with enough of the zip file * to meet the specification for a maximal comment length. */ - if ((flen = lseek(fd, 0, SEEK_END)) < (off_t)0) + if ((flen = JLI_Lseek(fd, 0, SEEK_END)) < (jlong)0) return (-1); len = (flen < END_MAXLEN) ? flen : END_MAXLEN; - if (lseek(fd, -len, SEEK_END) < (off_t)0) + if (JLI_Lseek(fd, -len, SEEK_END) < (jlong)0) return (-1); if ((buffer = malloc(END_MAXLEN)) == NULL) return (-1); @@ -175,12 +209,92 @@ find_end(int fd, Byte *eb) (cp + ENDHDR + ENDCOM(cp) == endpos)) { (void) memcpy(eb, cp, ENDHDR); free(buffer); - return (flen - (endpos - cp)); + pos = flen - (endpos - cp); + return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; } free(buffer); return (-1); } +#define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ) +#define MINREAD 1024 + +/* + * Computes and positions at the start of the CEN header, ie. the central + * directory, this will also return the offset if there is a zip file comment + * at the end of the archive, for most cases this would be 0. + */ +static jlong +compute_cen(int fd, Byte *bp) +{ + int bytes; + Byte *p; + jlong base_offset; + jlong offset; + char buffer[MINREAD]; + p = buffer; + /* + * Read the END Header, which is the starting point for ZIP files. + * (Clearly designed to make writing a zip file easier than reading + * one. Now isn't that precious...) + */ + if ((base_offset = find_end(fd, bp)) == -1) { + return (-1); + } + p = bp; + /* + * There is a historical, but undocumented, ability to allow for + * additional "stuff" to be prepended to the zip/jar file. It seems + * that this has been used to prepend an actual java launcher + * executable to the jar on Windows. Although this is just another + * form of statically linking a small piece of the JVM to the + * application, we choose to continue to support it. Note that no + * guarantees have been made (or should be made) to the customer that + * this will continue to work. + * + * Therefore, calculate the base offset of the zip file (within the + * expanded file) by assuming that the central directory is followed + * immediately by the end record. + */ + if (zip64_present) { + if ((offset = ZIP64_LOCOFF(p)) < (jlong)0) { + return -1; + } + if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong) 0) { + return (-1); + } + if ((bytes = read(fd, buffer, MINREAD)) < 0) { + return (-1); + } + if (GETSIG(buffer) != ZIP64_ENDSIG) { + return -1; + } + if ((offset = ZIP64_ENDOFF(buffer)) < (jlong)0) { + return -1; + } + if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong)0) { + return (-1); + } + p = buffer; + base_offset = base_offset - ZIP64_ENDSIZ(p) - ZIP64_ENDOFF(p) - ZIP64_ENDHDR; + } else { + base_offset = base_offset - ENDSIZ(p) - ENDOFF(p); + /* + * The END Header indicates the start of the Central Directory + * Headers. Remember that the desired Central Directory Header (CEN) + * will almost always be the second one and the first one is a small + * directory entry ("META-INF/"). Keep the code optimized for + * that case. + * + * Seek to the beginning of the Central Directory. + */ + if (JLI_Lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (jlong) 0) { + return (-1); + } + } + return base_offset; +} + /* * Locate the manifest file with the zip/jar file. * @@ -208,9 +322,6 @@ find_end(int fd, Byte *eb) * a typical jar file (META-INF and META-INF/MANIFEST.MF). Keep this factoid * in mind when optimizing this code. */ -#define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ) -#define MINREAD 1024 - static int find_file(int fd, zentry *entry, const char *file_name) { @@ -218,7 +329,7 @@ find_file(int fd, zentry *entry, const char *file_name) int res; int entry_size; int read_size; - int base_offset; + jlong base_offset; Byte *p; Byte *bp; Byte *buffer; @@ -228,54 +339,18 @@ find_file(int fd, zentry *entry, const char *file_name) return(-1); } - p = buffer; bp = buffer; - - /* - * Read the END Header, which is the starting point for ZIP files. - * (Clearly designed to make writing a zip file easier than reading - * one. Now isn't that precious...) - */ - if ((base_offset = find_end(fd, bp)) == -1) { + base_offset = compute_cen(fd, bp); + if (base_offset == -1) { free(buffer); - return (-1); + return -1; } - /* - * There is a historical, but undocumented, ability to allow for - * additional "stuff" to be prepended to the zip/jar file. It seems - * that this has been used to prepend an actual java launcher - * executable to the jar on Windows. Although this is just another - * form of statically linking a small piece of the JVM to the - * application, we choose to continue to support it. Note that no - * guarantees have been made (or should be made) to the customer that - * this will continue to work. - * - * Therefore, calculate the base offset of the zip file (within the - * expanded file) by assuming that the central directory is followed - * immediately by the end record. - */ - base_offset = base_offset - ENDSIZ(p) - ENDOFF(p); - - /* - * The END Header indicates the start of the Central Directory - * Headers. Remember that the desired Central Directory Header (CEN) - * will almost always be the second one and the first one is a small - * directory entry ("META-INF/"). Keep the code optimized for - * that case. - * - * Begin by seeking to the beginning of the Central Directory and - * reading in the first buffer full of bits. - */ - if (lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (off_t)0) { - free(buffer); - return (-1); - } if ((bytes = read(fd, bp, MINREAD)) < 0) { free(buffer); return (-1); } - + p = bp; /* * Loop through the Central Directory Headers. Note that a valid zip/jar * must have an ENDHDR (with ENDSIG) after the Central Directory. @@ -319,7 +394,7 @@ find_file(int fd, zentry *entry, const char *file_name) */ if ((size_t)CENNAM(p) == JLI_StrLen(file_name) && memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) { - if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) { + if (JLI_Lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (jlong)0) { free(buffer); return (-1); } @@ -487,6 +562,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) char *splashscreen_name = NULL; if ((fd = open(jarfile, O_RDONLY +#ifdef O_LARGEFILE + | O_LARGEFILE /* large file mode on solaris */ +#endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif diff --git a/jdk/src/solaris/bin/jexec.c b/jdk/src/solaris/bin/jexec.c index b2efc99c48d..2e478d8f1a7 100644 --- a/jdk/src/solaris/bin/jexec.c +++ b/jdk/src/solaris/bin/jexec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -80,6 +80,7 @@ # include # include # include +# include "jni.h" # include "manifest_info.h" #endif diff --git a/jdk/test/tools/launcher/BigJar.java b/jdk/test/tools/launcher/BigJar.java new file mode 100644 index 00000000000..5c183f44e7e --- /dev/null +++ b/jdk/test/tools/launcher/BigJar.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2012, 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. + */ + +/* + * @test + * @bug 7194005 + * @summary launcher handling of zip64 archives (Scenario A and B) + * @compile -XDignore.symbol.file BigJar.java + * @run main/timeout=600 BigJar + */ +/* + * This test consists of two scenarios: + * + * Scenario A: create a jar with entries exceeding 64K, add a main class and + * see if the launcher can handle it. + * + * Scenario A1: create a jar as in A, but add a zipfile comment as well. + * + * Scenario B: create a jar with a large enough file exceeding 4GB, and + * similarly test the launcher. This test can be run optionally by using the + * following jtreg option: + * "-javaoptions:-DBigJar_testScenarioB=true" + * or set + * "BigJar_testScenarioB" environment variable. + * + * Note this test will only run iff all the disk requirements are met at runtime. + */ +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class BigJar extends TestHelper { + + private static final long GIGA = 1024 * 1024 * 1024; + private static final int BUFFER_LEN = Short.MAX_VALUE * 2; + + long getCount(long minlength) { + return (minlength / BUFFER_LEN) + 1; + } + + long computeCRC(long minlength) { + CRC32 crc = new CRC32(); + byte[] buffer = new byte[BUFFER_LEN]; + long count = getCount(minlength); + for (long i = 0; i < count; i++) { + crc.update(buffer); + } + return crc.getValue(); + } + + long computeCRC(File inFile) throws IOException { + byte[] buffer = new byte[8192]; + CRC32 crc = new CRC32(); + try (FileInputStream fis = new FileInputStream(inFile); + BufferedInputStream bis = new BufferedInputStream(fis)) { + int n = bis.read(buffer); + while (n > 0) { + crc.update(buffer, 0, n); + n = bis.read(buffer); + } + } + return crc.getValue(); + } + + void createLargeFile(OutputStream os, long minlength) throws IOException { + byte[] buffer = new byte[BUFFER_LEN]; + long count = getCount(minlength); + for (long i = 0; i < count; i++) { + os.write(buffer); + } + os.flush(); + } + + Manifest createMainClass(File javaFile) throws IOException { + javaFile.delete(); + List content = new ArrayList<>(); + content.add("public class " + baseName(javaFile) + "{"); + content.add("public static void main(String... args) {"); + content.add("System.out.println(\"Hello World\\n\");"); + content.add("System.exit(0);"); + content.add("}"); + content.add("}"); + createFile(javaFile, content); + compile(javaFile.getName()); + Manifest manifest = new Manifest(); + manifest.clear(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, baseName(javaFile)); + System.out.println(manifest.getMainAttributes().keySet()); + System.out.println(manifest.getMainAttributes().values()); + return manifest; + } + + void createJarWithLargeFile(File jarFile, long minlength) throws IOException { + File javaFile = new File("Foo.java"); + Manifest manifest = createMainClass(javaFile); + File classFile = getClassFile(javaFile); + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile), manifest); + BufferedOutputStream bos = new BufferedOutputStream(jos); + FileInputStream fis = new FileInputStream(classFile);) { + jos.setLevel(ZipOutputStream.STORED); + jos.setMethod(0); + + JarEntry je = new JarEntry("large.data"); + je.setCompressedSize(getCount(minlength) * BUFFER_LEN); + je.setSize(getCount(minlength) * BUFFER_LEN); + je.setCrc(computeCRC(minlength)); + je.setMethod(ZipEntry.STORED); + jos.putNextEntry(je); + createLargeFile(bos, minlength); + + je = new JarEntry(classFile.getName()); + je.setCompressedSize(classFile.length()); + je.setSize(classFile.length()); + je.setCrc(computeCRC(classFile)); + je.setMethod(ZipEntry.STORED); + jos.putNextEntry(je); + copyStream(fis, bos); + bos.flush(); + jos.closeEntry(); + } + } + + void createLargeJar(File jarFile, String comment) throws IOException { + final int MAX = Short.MAX_VALUE * 2 + 10; + JarEntry je = null; + File javaFile = new File("Foo.java"); + File classFile = getClassFile(javaFile); + Manifest manifest = createMainClass(javaFile); + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile), manifest); + FileInputStream fis = new FileInputStream(classFile)) { + jos.setLevel(JarOutputStream.STORED); + jos.setMethod(JarOutputStream.STORED); + for (int i = 0; i < MAX; i++) { + je = new JarEntry("X" + i + ".txt"); + je.setSize(0); + je.setCompressedSize(0); + je.setCrc(0); + jos.putNextEntry(je); + } + + // add a class file + je = new JarEntry(classFile.getName()); + je.setCompressedSize(classFile.length()); + je.setSize(classFile.length()); + je.setCrc(computeCRC(classFile)); + jos.putNextEntry(je); + copyStream(fis, jos); + jos.closeEntry(); + if (comment != null) { + jos.setComment(comment); + } + } + } + + void testTheJar(File theJar) throws Exception { + try { + TestResult tr = doExec(javaCmd, "-jar", theJar.getName()); + tr.checkPositive(); + if (!tr.testStatus) { + System.out.println(tr); + throw new Exception("Failed"); + } + } finally { + theJar.delete(); + } + } + + // a jar with entries exceeding 64k + a class file for the existential test + @Test + void testScenarioA() throws Exception { + File largeJar = new File("large.jar"); + createLargeJar(largeJar, null); + testTheJar(largeJar); + } + + // a jar with entries exceeding 64k and zip comment + @Test + void testScenarioA1() throws Exception { + File largeJar = new File("largewithcomment.jar"); + createLargeJar(largeJar, "A really large jar with a comment"); + testTheJar(largeJar); + } + + // a jar with an enormous file + a class file for the existential test + @Test + void testScenarioB() throws Exception { + final String testString = "BigJar_testScenarioB"; + if (Boolean.getBoolean(testString) == false && + System.getenv(testString) == null) { + System.out.println("Warning: testScenarioB passes vacuously"); + return; + } + final File largeJar = new File("huge.jar"); + + final Path path = largeJar.getAbsoluteFile().getParentFile().toPath(); + final long available = Files.getFileStore(path).getUsableSpace(); + final long MAX_VALUE = 0xFFFF_FFFFL; + + final long absolute = MAX_VALUE + 1L; + final long required = (long) (absolute * 1.1); // pad for sundries + System.out.println("\tavailable: " + available / GIGA + " GB"); + System.out.println("\trequired: " + required / GIGA + " GB"); + + if (available > required) { + createJarWithLargeFile(largeJar, absolute); + testTheJar(largeJar); + } else { + System.out.println("Warning: testScenarioB passes vacuously," + + " requirements exceeds available space"); + } + } + + public static void main(String... args) throws Exception { + BigJar bj = new BigJar(); + bj.run(args); + if (testExitValue > 0) { + System.out.println("Total of " + testExitValue + " failed"); + System.exit(1); + } else { + System.out.println("All tests pass"); + } + } +} diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 893b90f2f06..6738eba5e19 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -21,6 +21,8 @@ * questions. */ +import java.io.OutputStream; +import java.io.InputStream; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -243,6 +245,21 @@ public class TestHelper { return null; } + static File getClassFile(File javaFile) { + String s = javaFile.getAbsolutePath().replace(JAVA_FILE_EXT, CLASS_FILE_EXT); + return new File(s); + } + + static File getJavaFile(File classFile) { + String s = classFile.getAbsolutePath().replace(CLASS_FILE_EXT, JAVA_FILE_EXT); + return new File(s); + } + + static String baseName(File f) { + String s = f.getName(); + return s.substring(0, s.indexOf(".")); + } + /* * A convenience method to create a jar with jar file name and defs */ @@ -324,6 +341,15 @@ public class TestHelper { } } + static void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[8192]; + int n = in.read(buf); + while (n > 0) { + out.write(buf, 0, n); + n = in.read(buf); + } + } + static void copyFile(File src, File dst) throws IOException { Path parent = dst.toPath().getParent(); if (parent != null) {