src/share/classes/org/openjdk/jigsaw/ModuleFile.java
Print this page
*** 60,69 ****
--- 60,72 ----
private DataInputStream stream;
private File destination;
private boolean deflate;
private HashType hashtype;
+ private File natlibs;
+ private File natcmds;
+ private File configs;
private static class CountingInputStream extends FilterInputStream {
int count;
public CountingInputStream(InputStream stream, int count) {
super(stream);
*** 178,193 ****
}
}
public void readRest() throws IOException {
extract = false;
! readRest(null, false);
}
public void readRest(File dst, boolean deflate) throws IOException {
! this.destination = dst;
this.deflate = deflate;
try {
if (extract)
Files.store(moduleInfoBytes, computeRealPath("info"));
// Module-Info and Signature, if present, have been consumed
--- 181,206 ----
}
}
public void readRest() throws IOException {
extract = false;
! readRest(null, false, null, null, null);
}
public void readRest(File dst, boolean deflate) throws IOException {
! readRest(dst, deflate, null, null, null);
! }
!
! public void readRest(File dst, boolean deflate, File natlibs,
! File natcmds, File configs)
! throws IOException
! {
! this.destination = dst.getCanonicalFile();
this.deflate = deflate;
+ this.natlibs = natlibs != null ? natlibs : new File(destination, "lib");
+ this.natcmds = natcmds != null ? natcmds : new File(destination, "bin");
+ this.configs = configs != null ? configs : new File(destination, "etc");
try {
if (extract)
Files.store(moduleInfoBytes, computeRealPath("info"));
// Module-Info and Signature, if present, have been consumed
*** 258,267 ****
--- 271,281 ----
return contentStream;
}
public void close() throws IOException {
try {
+ try {
if (contentStream != null) {
contentStream.close();
contentStream = null;
}
} finally {
*** 268,279 ****
--- 282,300 ----
if (fileIn != null) {
fileIn.close();
fileIn = null;
}
}
+ } finally {
+ if (filesWriter != null) {
+ filesWriter.close();
+ filesWriter = null;
}
+ }
+ }
+
public void readModule() throws IOException {
extract = false;
readStart();
readRest();
}
*** 428,438 ****
OutputStream out = openOutputStream(type, header.getPath())) {
copyStream(gin, out);
}
if (extract)
! markNativeCodeExecutable(type, currentPath);
}
public void readUncompressedFile(DataInputStream in,
SectionType type,
int csize)
--- 449,459 ----
OutputStream out = openOutputStream(type, header.getPath())) {
copyStream(gin, out);
}
if (extract)
! postExtract(type, currentPath);
}
public void readUncompressedFile(DataInputStream in,
SectionType type,
int csize)
*** 446,457 ****
byte[] buf = new byte[8192];
int n;
while ((n = cin.read(buf)) >= 0)
out.write(buf, 0, n);
}
! markNativeCodeExecutable(type, currentPath);
}
public byte[] readModuleInfo(DataInputStream in, int csize)
throws IOException
{
CountingInputStream cin = new CountingInputStream(in, csize);
--- 467,480 ----
byte[] buf = new byte[8192];
int n;
while ((n = cin.read(buf)) >= 0)
out.write(buf, 0, n);
}
! if (extract) {
! postExtract(type, currentPath);
}
+ }
public byte[] readModuleInfo(DataInputStream in, int csize)
throws IOException
{
CountingInputStream cin = new CountingInputStream(in, csize);
*** 467,498 ****
throws IOException
{
return readModuleInfo(in, csize); // signature has the same format
}
! private File computeRealPath(String storedpath) throws IOException {
! String convertedpath = storedpath.replace('/', File.separatorChar);
! File path = new File(convertedpath);
! // Absolute path names are not permitted.
! ensureNonAbsolute(path);
! path = resolveAndNormalize(destination, convertedpath);
! // Create the parent directories if necessary
! File parent = path.getParentFile();
! if (!parent.exists())
! Files.mkdirs(parent, path.getName());
! return path;
}
! private File computeRealPath(SectionType type,
! String storedpath)
throws IOException
{
! String dir = getSubdirOfSection(type);
! return computeRealPath(dir + File.separatorChar + storedpath);
}
private static void markNativeCodeExecutable(SectionType type,
File file)
{
--- 490,571 ----
throws IOException
{
return readModuleInfo(in, csize); // signature has the same format
}
! // Track files installed outside the module library. For later removal.
! // files are relative to the modules directory.
! private PrintWriter filesWriter;
! private void trackFiles(SectionType type, File file)
! throws IOException
! {
! if (file == null || file.toPath().startsWith(destination.toPath()))
! return;
! // Lazy construction, not all modules will need this.
! if (filesWriter == null)
! filesWriter = new PrintWriter(computeRealPath("files"), "UTF-8");
! filesWriter.println(Files.convertSeparator(relativize(destination, file)));
! filesWriter.flush();
}
! void remove() throws IOException {
! ModuleFile.Reader.remove(destination);
! }
!
! // Removes a module, given its module install directory
! static void remove(File moduleDir) throws IOException {
! // Firstly remove any files installed outside of the module dir
! File files = new File(moduleDir, "files");
! if (files.exists()) {
! try (FileInputStream fis = new FileInputStream(files);
! InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
! BufferedReader in = new BufferedReader(isr)) {
! String filename;
! while ((filename = in.readLine()) != null)
! Files.delete(new File(moduleDir,
! Files.platformSeparator(filename)));
! }
! }
!
! Files.deleteTree(moduleDir);
! }
!
! // Returns the absolute path of the given section type.
! private File getDirOfSection(SectionType type) {
! if (type == SectionType.NATIVE_LIBS)
! return natlibs;
! else if (type == SectionType.NATIVE_CMDS)
! return natcmds;
! else if (type == SectionType.CONFIG)
! return configs;
!
! // resolve sub dir section paths against the modules directory
! return new File(destination, ModuleFile.getSubdirOfSection(type));
! }
!
! private File computeRealPath(String path) throws IOException {
! return resolveAndNormalize(destination, path);
! }
!
! private File computeRealPath(SectionType type, String storedpath)
throws IOException
{
! File sectionPath = getDirOfSection(type);
! File realpath = new File(sectionPath,
! Files.ensureNonAbsolute(Files.platformSeparator(storedpath)));
!
! validatePath(sectionPath, realpath);
!
! // Create the parent directories if necessary
! File parent = realpath.getParentFile();
! if (!parent.exists())
! Files.mkdirs(parent, realpath.getName());
!
! return realpath;
}
private static void markNativeCodeExecutable(SectionType type,
File file)
{
*** 502,511 ****
--- 575,591 ----
{
file.setExecutable(true);
}
}
+ private void postExtract(SectionType type, File path)
+ throws IOException
+ {
+ markNativeCodeExecutable(type, path);
+ trackFiles(type, path);
+ }
+
private void unpack200gzip(DataInputStream in) throws IOException {
GZIPInputStream gis = new GZIPInputStream(in) {
public void close() throws IOException {}
};
Pack200.Unpacker unpacker = Pack200.newUnpacker();
*** 577,591 ****
throws IOException
{
copyStream(in, (DataOutput) new DataOutputStream(out), count);
}
- private static void ensureNonAbsolute(File path) throws IOException {
- if (path.isAbsolute())
- throw new IOException("Abolute path instead of relative: " + path);
- }
-
private static void ensureNonNegativity(long size, String parameter) {
if (size < 0)
throw new IllegalArgumentException(parameter + "<0: " + size);
}
--- 657,666 ----
*** 674,683 ****
--- 749,774 ----
throw new IOException("Bogus relative path: " + path);
return realpath;
}
+
+ private static String relativize(File directory, File path) throws IOException {
+ return (directory.toPath().relativize(path.toPath().toRealPath())).toString();
+ }
+
+ private static void validatePath(File parent, File child)
+ throws IOException
+ {
+ if (!child.toPath().startsWith(parent.toPath()) )
+ throw new IOException("Bogus relative path: " + child);
+ if (child.exists()) {
+ // conflict, for now just fail
+ throw new IOException("File " + child + " already exists");
+ }
+ }
+
private static short readHashLength(DataInputStream in) throws IOException {
final short hashLength = in.readShort();
ensureNonNegativity(hashLength, "hashLength");
return hashLength;