mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
add support for accessing embedded JARs as if they were directories
This allows OpenJDK to access time zone data which is normally found under java.home, but which we must embed in the executable itself to create a self-contained build. The VM intercepts various file operations, looking for paths which start with a prefix specified by the avian.embed.prefix property and redirecting those operations to an embedded JAR. For example, if avian.embed.prefix is "/avian-embedded", and code calls File.exists() with a path of "/avian-embedded/javahomeJar/foo.txt", the VM looks for a function named javahomeJar via dlsym, calls the function to find the memory region containing the embeded JAR, and finally consults the JAR to see if the file "foo.txt" exists.
This commit is contained in:
parent
4cb796d2fb
commit
d0a6096eb0
53
makefile
53
makefile
@ -52,25 +52,29 @@ classpath = avian
|
|||||||
|
|
||||||
test-executable = $(executable)
|
test-executable = $(executable)
|
||||||
boot-classpath = $(classpath-build)
|
boot-classpath = $(classpath-build)
|
||||||
java-home = /avian-embedded
|
embed-prefix = /avian-embedded
|
||||||
|
|
||||||
ifdef openjdk
|
ifdef openjdk
|
||||||
ifdef openjdk-src
|
ifdef openjdk-src
|
||||||
include openjdk-src.mk
|
include openjdk-src.mk
|
||||||
options := $(options)-openjdk-src
|
options := $(options)-openjdk-src
|
||||||
classpath-objects = $(openjdk-objects)
|
classpath-objects = $(openjdk-objects)
|
||||||
classpath-cflags = -DAVIAN_OPENJDK_SRC
|
classpath-cflags = -DAVIAN_OPENJDK_SRC -DBOOT_JAVAHOME
|
||||||
openjdk-jar-dep = $(build)/openjdk-jar.dep
|
openjdk-jar-dep = $(build)/openjdk-jar.dep
|
||||||
classpath-jar-dep = $(openjdk-jar-dep)
|
classpath-jar-dep = $(openjdk-jar-dep)
|
||||||
|
javahome = $(embed-prefix)/javahomeJar
|
||||||
|
javahome-files = lib/zi
|
||||||
|
javahome-object = $(build)/javahome-jar.o
|
||||||
else
|
else
|
||||||
options := $(options)-openjdk
|
options := $(options)-openjdk
|
||||||
test-executable = $(executable-dynamic)
|
test-executable = $(executable-dynamic)
|
||||||
library-path = LD_LIBRARY_PATH=$(build)
|
library-path = LD_LIBRARY_PATH=$(build)
|
||||||
java-home = $(openjdk)/jre
|
javahome = $(openjdk)/jre
|
||||||
endif
|
endif
|
||||||
|
|
||||||
classpath = openjdk
|
classpath = openjdk
|
||||||
boot-classpath := $(boot-classpath):$(openjdk)/jre/lib/rt.jar
|
boot-classpath := $(boot-classpath):$(openjdk)/jre/lib/rt.jar
|
||||||
|
build-javahome = $(openjdk)/jre
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(classpath),avian)
|
ifeq ($(classpath),avian)
|
||||||
@ -120,7 +124,8 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
|
|||||||
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
||||||
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \
|
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \
|
||||||
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
||||||
-DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(java-home)\"
|
-DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \
|
||||||
|
-DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\"
|
||||||
|
|
||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
||||||
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
||||||
@ -593,12 +598,6 @@ $(driver-dynamic-object): $(driver-source)
|
|||||||
$(boot-object): $(boot-source)
|
$(boot-object): $(boot-source)
|
||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
|
|
||||||
@echo "creating $(@)"
|
|
||||||
(wd=$$(pwd) && \
|
|
||||||
cd $(classpath-build) && \
|
|
||||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
|
||||||
|
|
||||||
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
||||||
$(build-cxx) -c $(^) -o $(@)
|
$(build-cxx) -c $(^) -o $(@)
|
||||||
|
|
||||||
@ -620,11 +619,28 @@ $(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
|
|||||||
$(converter): $(converter-objects)
|
$(converter): $(converter-objects)
|
||||||
$(build-cxx) $(^) -o $(@)
|
$(build-cxx) $(^) -o $(@)
|
||||||
|
|
||||||
|
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
|
||||||
|
@echo "creating $(@)"
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(classpath-build) && \
|
||||||
|
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
||||||
|
|
||||||
$(classpath-object): $(build)/classpath.jar $(converter)
|
$(classpath-object): $(build)/classpath.jar $(converter)
|
||||||
@echo "creating $(@)"
|
@echo "creating $(@)"
|
||||||
$(converter) $(<) $(@) _binary_classpath_jar_start \
|
$(converter) $(<) $(@) _binary_classpath_jar_start \
|
||||||
_binary_classpath_jar_end $(platform) $(arch)
|
_binary_classpath_jar_end $(platform) $(arch)
|
||||||
|
|
||||||
|
$(build)/javahome.jar: $(foreach x,$(javahome-files),$(build-javahome)/$(x))
|
||||||
|
@echo "creating $(@)"
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(build-javahome) && \
|
||||||
|
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $(javahome-files))
|
||||||
|
|
||||||
|
$(javahome-object): $(build)/javahome.jar $(converter)
|
||||||
|
@echo "creating $(@)"
|
||||||
|
$(converter) $(<) $(@) _binary_javahome_jar_start \
|
||||||
|
_binary_javahome_jar_end $(platform) $(arch)
|
||||||
|
|
||||||
$(generator-objects): $(generator-depends)
|
$(generator-objects): $(generator-depends)
|
||||||
$(generator-objects): $(build)/%-build.o: $(src)/%.cpp
|
$(generator-objects): $(build)/%-build.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@ -651,7 +667,8 @@ $(bootimage-object): $(bootimage-bin) $(converter)
|
|||||||
writable executable
|
writable executable
|
||||||
|
|
||||||
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
|
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
|
||||||
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object)
|
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
|
||||||
|
$(javahome-object)
|
||||||
|
|
||||||
$(executable): $(executable-objects)
|
$(executable): $(executable-objects)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
@ -696,18 +713,16 @@ else
|
|||||||
$(ld) $(^) $(rdynamic) $(lflags) -o $(@)
|
$(ld) $(^) $(rdynamic) $(lflags) -o $(@)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dynamic-library-objects = $(vm-objects) $(dynamic-object) \
|
$(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \
|
||||||
$(classpath-objects) $(vm-heapwalk-objects) $(boot-object) \
|
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
|
||||||
$(vm-classpath-object) $(classpath-libraries)
|
$(classpath-libraries) $(javahome-object)
|
||||||
|
|
||||||
$(dynamic-library): $(dynamic-library-objects)
|
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
ifdef msvc
|
ifdef msvc
|
||||||
$(ld) $(shared) $(lflags) $(dynamic-library-objects) -out:$(@) \
|
$(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \
|
||||||
-PDB:$(@).pdb -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest
|
-IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest
|
||||||
$(mt) -manifest $(@).manifest -outputresource:"$(@);2"
|
$(mt) -manifest $(@).manifest -outputresource:"$(@);2"
|
||||||
else
|
else
|
||||||
$(ld) $(dynamic-library-objects) -Wl,--version-script=openjdk.ld \
|
$(ld) $(^) -Wl,--version-script=openjdk.ld \
|
||||||
$(shared) $(lflags) $(bootimage-lflags) -o $(@)
|
$(shared) $(lflags) $(bootimage-lflags) -o $(@)
|
||||||
endif
|
endif
|
||||||
$(strip) $(strip-all) $(@)
|
$(strip) $(strip-all) $(@)
|
||||||
|
30
src/boot.cpp
30
src/boot.cpp
@ -52,6 +52,8 @@ extern "C" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SYMBOL
|
||||||
|
|
||||||
#endif//BOOT_IMAGE
|
#endif//BOOT_IMAGE
|
||||||
|
|
||||||
#ifdef BOOT_CLASSPATH
|
#ifdef BOOT_CLASSPATH
|
||||||
@ -76,4 +78,32 @@ extern "C" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SYMBOL
|
||||||
|
|
||||||
#endif//BOOT_CLASSPATH
|
#endif//BOOT_CLASSPATH
|
||||||
|
|
||||||
|
#ifdef BOOT_JAVAHOME
|
||||||
|
|
||||||
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
|
# define SYMBOL(x) binary_javahome_jar_##x
|
||||||
|
#else
|
||||||
|
# define SYMBOL(x) _binary_javahome_jar_##x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
extern const uint8_t SYMBOL(start)[];
|
||||||
|
extern const uint8_t SYMBOL(end)[];
|
||||||
|
|
||||||
|
EXPORT const uint8_t*
|
||||||
|
javahomeJar(unsigned* size)
|
||||||
|
{
|
||||||
|
*size = SYMBOL(end) - SYMBOL(start);
|
||||||
|
return SYMBOL(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SYMBOL
|
||||||
|
|
||||||
|
#endif//BOOT_JAVAHOME
|
||||||
|
@ -85,8 +85,9 @@ Avian_avian_SystemClassLoader_resourceExists
|
|||||||
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
||||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
bool r = static_cast<Finder*>(systemClassLoaderFinder(t, loader))->exists
|
unsigned length;
|
||||||
(RUNTIME_ARRAY_BODY(n));
|
bool r = static_cast<Finder*>(systemClassLoaderFinder(t, loader))->stat
|
||||||
|
(RUNTIME_ARRAY_BODY(n), &length) == System::TypeFile;
|
||||||
|
|
||||||
// fprintf(stderr, "resource %s exists? %d\n", n, r);
|
// fprintf(stderr, "resource %s exists? %d\n", n, r);
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Classpath*
|
Classpath*
|
||||||
makeClasspath(System*, Allocator* allocator, const char*)
|
makeClasspath(System*, Allocator* allocator, const char*, const char*)
|
||||||
{
|
{
|
||||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||||
local::MyClasspath(allocator);
|
local::MyClasspath(allocator);
|
||||||
|
@ -88,6 +88,7 @@ namespace local {
|
|||||||
|
|
||||||
const unsigned InterfaceVersion = 4;
|
const unsigned InterfaceVersion = 4;
|
||||||
const unsigned PageSize = 4 * 1024;
|
const unsigned PageSize = 4 * 1024;
|
||||||
|
const int VirtualFileBase = 1000000000;
|
||||||
|
|
||||||
Machine* globalMachine;
|
Machine* globalMachine;
|
||||||
|
|
||||||
@ -145,7 +146,6 @@ makeClassNameString(Thread* t, object name)
|
|||||||
return makeString(t, "%s", s);
|
return makeString(t, "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AVIAN_OPENJDK_SRC
|
|
||||||
// only safe to call during bootstrap when there's only one thread
|
// only safe to call during bootstrap when there's only one thread
|
||||||
// running:
|
// running:
|
||||||
void
|
void
|
||||||
@ -171,51 +171,20 @@ intercept(Thread* t, object c, const char* name, const char* spec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
|
||||||
zipLibrary(Thread*);
|
|
||||||
|
|
||||||
int64_t JNICALL
|
int64_t JNICALL
|
||||||
getFileAttributes
|
getFileAttributes
|
||||||
(Thread* t, object method, uintptr_t* arguments)
|
(Thread* t, object method, uintptr_t* arguments);
|
||||||
{
|
|
||||||
const unsigned Exists = 1;
|
|
||||||
const unsigned Regular = 2;
|
|
||||||
|
|
||||||
object file = reinterpret_cast<object>(arguments[1]);
|
int64_t JNICALL
|
||||||
|
getLength
|
||||||
object pathField = findFieldInClass2
|
(Thread* t, object method, uintptr_t* arguments);
|
||||||
(t, objectClass(t, file), "path", "Ljava/lang/String;");
|
|
||||||
|
|
||||||
if (pathField) {
|
|
||||||
object path = cast<object>(file, fieldOffset(t, pathField));
|
|
||||||
|
|
||||||
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
|
||||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
|
||||||
|
|
||||||
if (strcmp(zipLibrary(t), p) == 0) {
|
|
||||||
return Exists | Regular;
|
|
||||||
} else {
|
|
||||||
object r = t->m->processor->invoke
|
|
||||||
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
|
||||||
reinterpret_cast<object>(arguments[0]), file);
|
|
||||||
return (r ? intValue(t, r) : 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
object message = makeString
|
|
||||||
(t, "path Ljava/lang/String; not found in %s",
|
|
||||||
&byteArrayBody(t, className(t, objectClass(t, file)), 0));
|
|
||||||
t->exception = t->m->classpath->makeThrowable
|
|
||||||
(t, Machine::RuntimeExceptionType, message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // AVIAN_OPENJDK_SRC
|
|
||||||
|
|
||||||
class MyClasspath : public Classpath {
|
class MyClasspath : public Classpath {
|
||||||
public:
|
public:
|
||||||
static const unsigned BufferSize = 1024;
|
static const unsigned BufferSize = 1024;
|
||||||
|
|
||||||
MyClasspath(System* s, Allocator* allocator, const char* javaHome):
|
MyClasspath(System* s, Allocator* allocator, const char* javaHome,
|
||||||
|
const char* embedPrefix):
|
||||||
allocator(allocator)
|
allocator(allocator)
|
||||||
{
|
{
|
||||||
class StringBuilder {
|
class StringBuilder {
|
||||||
@ -285,6 +254,11 @@ class MyClasspath : public Classpath {
|
|||||||
sb.append(LIBRARY_PREFIX);
|
sb.append(LIBRARY_PREFIX);
|
||||||
sb.append("zip");
|
sb.append("zip");
|
||||||
sb.append(LIBRARY_SUFFIX);
|
sb.append(LIBRARY_SUFFIX);
|
||||||
|
sb.append('\0');
|
||||||
|
|
||||||
|
this->embedPrefix = sb.pointer;
|
||||||
|
sb.append(embedPrefix);
|
||||||
|
this->embedPrefixLength = sb.pointer - this->embedPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
@ -377,13 +351,32 @@ class MyClasspath : public Classpath {
|
|||||||
globalMachine = t->m;
|
globalMachine = t->m;
|
||||||
|
|
||||||
#ifdef AVIAN_OPENJDK_SRC
|
#ifdef AVIAN_OPENJDK_SRC
|
||||||
{ object c = resolveClass
|
{ object ufsClass = resolveClass
|
||||||
(t, root(t, Machine::BootLoader), "java/io/UnixFileSystem");
|
(t, root(t, Machine::BootLoader), "java/io/UnixFileSystem");
|
||||||
|
|
||||||
if (c) {
|
if (ufsClass) {
|
||||||
intercept(t, c, "getBooleanAttributes0", "(Ljava/io/File;)I",
|
PROTECT(t, ufsClass);
|
||||||
voidPointer(getFileAttributes));
|
|
||||||
|
object fileClass = resolveClass
|
||||||
|
(t, root(t, Machine::BootLoader), "java/io/File");
|
||||||
|
|
||||||
|
if (fileClass) {
|
||||||
|
object pathField = findFieldInClass2
|
||||||
|
(t, fileClass, "path", "Ljava/lang/String;");
|
||||||
|
|
||||||
|
if (pathField) {
|
||||||
|
this->pathField = fieldOffset(t, pathField);
|
||||||
|
|
||||||
|
intercept(t, ufsClass, "getBooleanAttributes0",
|
||||||
|
"(Ljava/io/File;)I", voidPointer(getFileAttributes));
|
||||||
|
|
||||||
|
intercept(t, ufsClass, "getLength", "(Ljava/io/File;)J",
|
||||||
|
voidPointer(getLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
}
|
}
|
||||||
#else // not AVIAN_OPENJDK_SRC
|
#else // not AVIAN_OPENJDK_SRC
|
||||||
if (loadLibrary(t, libraryPath, "java", true, true) == 0) {
|
if (loadLibrary(t, libraryPath, "java", true, true) == 0) {
|
||||||
@ -437,7 +430,7 @@ class MyClasspath : public Classpath {
|
|||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose()
|
dispose()
|
||||||
{
|
{
|
||||||
allocator->free(this, sizeof(*this));
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,33 +439,202 @@ class MyClasspath : public Classpath {
|
|||||||
const char* classpath;
|
const char* classpath;
|
||||||
const char* libraryPath;
|
const char* libraryPath;
|
||||||
const char* zipLibrary;
|
const char* zipLibrary;
|
||||||
|
const char* embedPrefix;
|
||||||
|
unsigned embedPrefixLength;
|
||||||
|
unsigned pathField;
|
||||||
char buffer[BufferSize];
|
char buffer[BufferSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JVM_ExceptionTableEntryType{
|
struct JVM_ExceptionTableEntryType {
|
||||||
jint start_pc;
|
jint start_pc;
|
||||||
jint end_pc;
|
jint end_pc;
|
||||||
jint handler_pc;
|
jint handler_pc;
|
||||||
jint catchType;
|
jint catchType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct jvm_version_info {
|
struct jvm_version_info {
|
||||||
unsigned int jvm_version;
|
unsigned jvm_version;
|
||||||
unsigned int update_version: 8;
|
unsigned update_version: 8;
|
||||||
unsigned int special_update_version: 8;
|
unsigned special_update_version: 8;
|
||||||
unsigned int reserved1: 16;
|
unsigned reserved1: 16;
|
||||||
unsigned int reserved2;
|
unsigned reserved2;
|
||||||
unsigned int is_attach_supported: 1;
|
unsigned is_attach_supported: 1;
|
||||||
unsigned int is_kernel_jvm: 1;
|
unsigned is_kernel_jvm: 1;
|
||||||
unsigned int: 30;
|
unsigned: 30;
|
||||||
unsigned int: 32;
|
unsigned: 32;
|
||||||
unsigned int: 32;
|
unsigned: 32;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char*
|
Finder*
|
||||||
zipLibrary(Thread* t)
|
getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||||
{
|
{
|
||||||
return static_cast<MyClasspath*>(t->m->classpath)->zipLibrary;
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
for (object p = root(t, Machine::VirtualFileFinders);
|
||||||
|
p; p = finderNext(t, p))
|
||||||
|
{
|
||||||
|
if (byteArrayLength(t, finderName(t, p)) == nameLength
|
||||||
|
and strncmp(reinterpret_cast<const char*>
|
||||||
|
(&byteArrayBody(t, finderName(t, p), 0)),
|
||||||
|
name, nameLength))
|
||||||
|
{
|
||||||
|
return static_cast<Finder*>(finderFinder(t, p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object n = makeByteArray(t, nameLength + 1);
|
||||||
|
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
|
||||||
|
|
||||||
|
void* p = t->m->libraries->resolve
|
||||||
|
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
|
||||||
|
if (p) {
|
||||||
|
uint8_t* (*function)(unsigned*);
|
||||||
|
memcpy(&function, &p, BytesPerWord);
|
||||||
|
|
||||||
|
unsigned size;
|
||||||
|
uint8_t* data = function(&size);
|
||||||
|
if (data) {
|
||||||
|
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
||||||
|
object finder = makeFinder
|
||||||
|
(t, f, n, root(t, Machine::VirtualFileFinders));
|
||||||
|
|
||||||
|
setRoot(t, Machine::VirtualFileFinders, finder);
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmbeddedFile {
|
||||||
|
public:
|
||||||
|
EmbeddedFile(MyClasspath* cp, const char* path, unsigned pathLength) {
|
||||||
|
if (strncmp(cp->embedPrefix, path, cp->embedPrefixLength) == 0) {
|
||||||
|
const char* p = path + cp->embedPrefixLength;
|
||||||
|
while (*p == '/') ++ p;
|
||||||
|
|
||||||
|
this->jar = p;
|
||||||
|
|
||||||
|
if (*p == 0) {
|
||||||
|
this->jarLength = 0;
|
||||||
|
this->path = 0;
|
||||||
|
this->pathLength = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p and *p != '/') ++p;
|
||||||
|
|
||||||
|
this->jarLength = p - this->jar;
|
||||||
|
|
||||||
|
while (*p == '/') ++p;
|
||||||
|
|
||||||
|
this->path = p;
|
||||||
|
this->pathLength = pathLength - (p - path);
|
||||||
|
} else {
|
||||||
|
this->jar = 0;
|
||||||
|
this->jarLength =0;
|
||||||
|
this->path = 0;
|
||||||
|
this->pathLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* jar;
|
||||||
|
const char* path;
|
||||||
|
unsigned jarLength;
|
||||||
|
unsigned pathLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getFileAttributes
|
||||||
|
(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
const unsigned Exists = 1;
|
||||||
|
const unsigned Regular = 2;
|
||||||
|
const unsigned Directory = 4;
|
||||||
|
|
||||||
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
object file = reinterpret_cast<object>(arguments[1]);
|
||||||
|
object path = cast<object>(file, cp->pathField);
|
||||||
|
|
||||||
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||||
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||||
|
|
||||||
|
if (strcmp(cp->zipLibrary, RUNTIME_ARRAY_BODY(p)) == 0) {
|
||||||
|
return Exists | Regular;
|
||||||
|
} else {
|
||||||
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
||||||
|
if (ef.jar) {
|
||||||
|
if (ef.jarLength == 0) {
|
||||||
|
return Exists | Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
||||||
|
if (finder) {
|
||||||
|
if (ef.pathLength == 0) {
|
||||||
|
return Exists | Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned length;
|
||||||
|
System::FileType type = finder->stat(ef.path, &length, true);
|
||||||
|
switch (type) {
|
||||||
|
case System::TypeUnknown: return Exists;
|
||||||
|
case System::TypeDoesNotExist: return 0;
|
||||||
|
case System::TypeFile: return Exists | Regular;
|
||||||
|
case System::TypeDirectory: return Exists | Directory;
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
object r = t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
||||||
|
reinterpret_cast<object>(arguments[0]), file);
|
||||||
|
|
||||||
|
return (r ? intValue(t, r) : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t JNICALL
|
||||||
|
getLength
|
||||||
|
(Thread* t, object method, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
object file = reinterpret_cast<object>(arguments[1]);
|
||||||
|
object path = cast<object>(file, cp->pathField);
|
||||||
|
|
||||||
|
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||||
|
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||||
|
|
||||||
|
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
||||||
|
if (ef.jar) {
|
||||||
|
if (ef.jarLength == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
||||||
|
if (finder) {
|
||||||
|
if (ef.pathLength == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned fileLength;
|
||||||
|
finder->stat(ef.path, &fileLength);
|
||||||
|
return fileLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
object r = t->m->processor->invoke
|
||||||
|
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
||||||
|
reinterpret_cast<object>(arguments[0]), file);
|
||||||
|
|
||||||
|
return (r ? longValue(t, r) : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -735,10 +897,11 @@ interruptLock(Thread* t, object thread)
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Classpath*
|
Classpath*
|
||||||
makeClasspath(System* s, Allocator* allocator, const char* javaHome)
|
makeClasspath(System* s, Allocator* allocator, const char* javaHome,
|
||||||
|
const char* embedPrefix)
|
||||||
{
|
{
|
||||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||||
local::MyClasspath(s, allocator, javaHome);
|
local::MyClasspath(s, allocator, javaHome, embedPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
@ -1308,7 +1471,9 @@ JVM_LoadLibrary(const char* name)
|
|||||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
|
|
||||||
#ifdef AVIAN_OPENJDK_SRC
|
#ifdef AVIAN_OPENJDK_SRC
|
||||||
if (strcmp(local::zipLibrary(t), name) == 0) {
|
if (strcmp(static_cast<local::MyClasspath*>(t->m->classpath)->zipLibrary,
|
||||||
|
name) == 0)
|
||||||
|
{
|
||||||
return t->m->libraries;
|
return t->m->libraries;
|
||||||
}
|
}
|
||||||
#endif // AVIAN_OPENJDK_SRC
|
#endif // AVIAN_OPENJDK_SRC
|
||||||
@ -2475,21 +2640,126 @@ JVM_NativePath(char* path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
JVM_Open(const char* name, jint flags, jint mode)
|
JVM_Open(const char* path, jint flags, jint mode)
|
||||||
{
|
{
|
||||||
return OPEN(name, flags, mode);
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
|
local::MyClasspath* cp = static_cast<local::MyClasspath*>(t->m->classpath);
|
||||||
|
|
||||||
|
local::EmbeddedFile ef(cp, path, strlen(path));
|
||||||
|
if (ef.jar) {
|
||||||
|
if (flags != O_RDONLY) {
|
||||||
|
errno = EACCES;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ef.jarLength == 0 or ef.pathLength == 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder* finder = local::getFinder(t, ef.jar, ef.jarLength);
|
||||||
|
if (finder == 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Region* r = finder->find(ef.path);
|
||||||
|
if (r == 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
unsigned oldLength = root(t, Machine::VirtualFiles)
|
||||||
|
? arrayLength(t, root(t, Machine::VirtualFiles)) : 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < oldLength; ++i) {
|
||||||
|
if (arrayBody(t, root(t, Machine::VirtualFiles), i) == 0) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
object newArray = growArray(t, root(t, Machine::VirtualFiles));
|
||||||
|
setRoot(t, Machine::VirtualFiles, newArray);
|
||||||
|
index = oldLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
object region = makeRegion(t, r, 0);
|
||||||
|
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
||||||
|
region);
|
||||||
|
|
||||||
|
return index + local::VirtualFileBase;
|
||||||
|
} else {
|
||||||
|
int r = OPEN(path, flags, mode);
|
||||||
|
expect(t, r < local::VirtualFileBase);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
JVM_Close(jint fd)
|
JVM_Close(jint fd)
|
||||||
{
|
{
|
||||||
return CLOSE(fd);
|
if (fd >= local::VirtualFileBase) {
|
||||||
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
|
unsigned index = fd - local::VirtualFileBase;
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||||
|
if (region) {
|
||||||
|
static_cast<System::Region*>(regionRegion(t, region))->dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
||||||
|
0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return CLOSE(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
JVM_Read(jint fd, char* dst, jint length)
|
JVM_Read(jint fd, char* dst, jint length)
|
||||||
{
|
{
|
||||||
return READ(fd, dst, length);
|
if (fd >= local::VirtualFileBase) {
|
||||||
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
|
unsigned index = fd - local::VirtualFileBase;
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||||
|
if (region) {
|
||||||
|
System::Region* r = static_cast<System::Region*>
|
||||||
|
(regionRegion(t, region));
|
||||||
|
|
||||||
|
int available = r->length() - regionPosition(t, region);
|
||||||
|
if (length > available) {
|
||||||
|
length = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dst, r->start(), length);
|
||||||
|
|
||||||
|
regionPosition(t, region) += length;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
} else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return READ(fd, dst, length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
@ -2501,34 +2771,94 @@ JVM_Write(jint fd, char* src, jint length)
|
|||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
JVM_Available(jint fd, jlong* result)
|
JVM_Available(jint fd, jlong* result)
|
||||||
{
|
{
|
||||||
struct stat buffer;
|
if (fd >= local::VirtualFileBase) {
|
||||||
int n;
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
if (FSTAT(fd, &buffer) >= 0
|
unsigned index = fd - local::VirtualFileBase;
|
||||||
and (S_ISCHR(buffer.st_mode)
|
|
||||||
or S_ISFIFO(buffer.st_mode)
|
ENTER(t, Thread::ActiveState);
|
||||||
or S_ISSOCK(buffer.st_mode))
|
|
||||||
and ioctl(fd, FIONREAD, &n) >= 0)
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
{
|
|
||||||
*result = n;
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||||
|
if (region) {
|
||||||
|
return static_cast<System::Region*>(regionRegion(t, region))->length()
|
||||||
|
- regionPosition(t, region);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct stat buffer;
|
||||||
|
int n;
|
||||||
|
if (FSTAT(fd, &buffer) >= 0
|
||||||
|
and (S_ISCHR(buffer.st_mode)
|
||||||
|
or S_ISFIFO(buffer.st_mode)
|
||||||
|
or S_ISSOCK(buffer.st_mode))
|
||||||
|
and ioctl(fd, FIONREAD, &n) >= 0)
|
||||||
|
{
|
||||||
|
*result = n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int current = LSEEK(fd, 0, SEEK_CUR);
|
||||||
|
if (current == -1) return 0;
|
||||||
|
|
||||||
|
int end = LSEEK(fd, 0, SEEK_END);
|
||||||
|
if (end == -1) return 0;
|
||||||
|
|
||||||
|
if (LSEEK(fd, current, SEEK_SET) == -1) return 0;
|
||||||
|
|
||||||
|
*result = end - current;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int current = LSEEK(fd, 0, SEEK_CUR);
|
|
||||||
if (current == -1) return 0;
|
|
||||||
|
|
||||||
int end = LSEEK(fd, 0, SEEK_END);
|
|
||||||
if (end == -1) return 0;
|
|
||||||
|
|
||||||
if (LSEEK(fd, current, SEEK_SET) == -1) return 0;
|
|
||||||
|
|
||||||
*result = end - current;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
JVM_Lseek(jint fd, jlong offset, jint start)
|
JVM_Lseek(jint fd, jlong offset, jint seek)
|
||||||
{
|
{
|
||||||
return LSEEK(fd, offset, start);
|
if (fd >= local::VirtualFileBase) {
|
||||||
|
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||||
|
unsigned index = fd - local::VirtualFileBase;
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||||
|
if (region) {
|
||||||
|
System::Region* r = static_cast<System::Region*>
|
||||||
|
(regionRegion(t, region));
|
||||||
|
|
||||||
|
switch (seek) {
|
||||||
|
case SEEK_SET:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
offset += regionPosition(t, region);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
offset += r->length();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset >= 0 and offset <= static_cast<int>(r->length())) {
|
||||||
|
regionPosition(t, region) = offset;
|
||||||
|
return offset;
|
||||||
|
} else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return LSEEK(fd, offset, seek);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
@ -7156,7 +7156,7 @@ class SegFaultHandler: public System::SignalHandler {
|
|||||||
t->exception = root(t, Machine::NullPointerException);
|
t->exception = root(t, Machine::NullPointerException);
|
||||||
}
|
}
|
||||||
|
|
||||||
// printTrace(t, t->exception);
|
printTrace(t, t->exception);
|
||||||
|
|
||||||
object continuation;
|
object continuation;
|
||||||
findUnwindTarget(t, ip, base, stack, &continuation);
|
findUnwindTarget(t, ip, base, stack, &continuation);
|
||||||
|
269
src/finder.cpp
269
src/finder.cpp
@ -20,12 +20,12 @@ namespace {
|
|||||||
const bool DebugFind = false;
|
const bool DebugFind = false;
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
append(System* s, const char* a, const char* b, const char* c)
|
append(Allocator* allocator, const char* a, const char* b, const char* c)
|
||||||
{
|
{
|
||||||
unsigned al = strlen(a);
|
unsigned al = strlen(a);
|
||||||
unsigned bl = strlen(b);
|
unsigned bl = strlen(b);
|
||||||
unsigned cl = strlen(c);
|
unsigned cl = strlen(c);
|
||||||
char* p = static_cast<char*>(allocate(s, (al + bl + cl) + 1));
|
char* p = static_cast<char*>(allocator->allocate((al + bl + cl) + 1));
|
||||||
memcpy(p, a, al);
|
memcpy(p, a, al);
|
||||||
memcpy(p + al, b, bl);
|
memcpy(p + al, b, bl);
|
||||||
memcpy(p + al + bl, c, cl + 1);
|
memcpy(p + al + bl, c, cl + 1);
|
||||||
@ -33,10 +33,10 @@ append(System* s, const char* a, const char* b, const char* c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
copy(System* s, const char* a)
|
copy(Allocator* allocator, const char* a)
|
||||||
{
|
{
|
||||||
unsigned al = strlen(a);
|
unsigned al = strlen(a);
|
||||||
char* p = static_cast<char*>(allocate(s, al + 1));
|
char* p = static_cast<char*>(allocator->allocate(al + 1));
|
||||||
memcpy(p, a, al + 1);
|
memcpy(p, a, al + 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -63,7 +63,8 @@ class Element {
|
|||||||
|
|
||||||
virtual Iterator* iterator() = 0;
|
virtual Iterator* iterator() = 0;
|
||||||
virtual System::Region* find(const char* name) = 0;
|
virtual System::Region* find(const char* name) = 0;
|
||||||
virtual bool exists(const char* name) = 0;
|
virtual System::FileType stat(const char* name, unsigned* length,
|
||||||
|
bool tryDirectory) = 0;
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
|
|
||||||
Element* next;
|
Element* next;
|
||||||
@ -73,8 +74,9 @@ class DirectoryElement: public Element {
|
|||||||
public:
|
public:
|
||||||
class Iterator: public Element::Iterator {
|
class Iterator: public Element::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator(System* s, const char* name, unsigned skip):
|
Iterator(System* s, Allocator* allocator, const char* name, unsigned skip):
|
||||||
s(s), name(name), skip(skip), directory(0), last(0), it(0)
|
s(s), allocator(allocator), name(name), skip(skip), directory(0),
|
||||||
|
last(0), it(0)
|
||||||
{
|
{
|
||||||
if (not s->success(s->open(&directory, name))) {
|
if (not s->success(s->open(&directory, name))) {
|
||||||
directory = 0;
|
directory = 0;
|
||||||
@ -93,15 +95,17 @@ class DirectoryElement: public Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
s->free(last);
|
allocator->free(last, strlen(last) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directory) {
|
if (directory) {
|
||||||
for (const char* v = directory->next(); v; v = directory->next()) {
|
for (const char* v = directory->next(); v; v = directory->next()) {
|
||||||
if (v[0] != '.') {
|
if (v[0] != '.') {
|
||||||
last = append(s, name, "/", v);
|
last = append(allocator, name, "/", v);
|
||||||
if (s->identify(last) == System::TypeDirectory) {
|
unsigned length;
|
||||||
it = new (allocate(s, sizeof(Iterator))) Iterator(s, last, skip);
|
if (s->stat(last, &length) == System::TypeDirectory) {
|
||||||
|
it = new (allocator->allocate(sizeof(Iterator)))
|
||||||
|
Iterator(s, allocator, last, skip);
|
||||||
it->name = last;
|
it->name = last;
|
||||||
}
|
}
|
||||||
const char* result = last + skip;
|
const char* result = last + skip;
|
||||||
@ -116,10 +120,11 @@ class DirectoryElement: public Element {
|
|||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
directory->dispose();
|
directory->dispose();
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
const char* name;
|
const char* name;
|
||||||
unsigned skip;
|
unsigned skip;
|
||||||
System::Directory* directory;
|
System::Directory* directory;
|
||||||
@ -127,20 +132,20 @@ class DirectoryElement: public Element {
|
|||||||
Iterator* it;
|
Iterator* it;
|
||||||
};
|
};
|
||||||
|
|
||||||
DirectoryElement(System* s, const char* name):
|
DirectoryElement(System* s, Allocator* allocator, const char* name):
|
||||||
s(s), name(name)
|
s(s), allocator(allocator), name(name)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual Element::Iterator* iterator() {
|
virtual Element::Iterator* iterator() {
|
||||||
return new (allocate(s, sizeof(Iterator)))
|
return new (allocator->allocate(sizeof(Iterator)))
|
||||||
Iterator(s, name, strlen(name) + 1);
|
Iterator(s, allocator, name, strlen(name) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual System::Region* find(const char* name) {
|
virtual System::Region* find(const char* name) {
|
||||||
const char* file = append(s, this->name, "/", name);
|
const char* file = append(allocator, this->name, "/", name);
|
||||||
System::Region* region;
|
System::Region* region;
|
||||||
System::Status status = s->map(®ion, file);
|
System::Status status = s->map(®ion, file);
|
||||||
s->free(file);
|
allocator->free(file, strlen(file) + 1);
|
||||||
|
|
||||||
if (s->success(status)) {
|
if (s->success(status)) {
|
||||||
if (DebugFind) {
|
if (DebugFind) {
|
||||||
@ -155,26 +160,29 @@ class DirectoryElement: public Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool exists(const char* name) {
|
virtual System::FileType stat(const char* name, unsigned* length, bool) {
|
||||||
const char* file = append(s, this->name, "/", name);
|
const char* file = append(allocator, this->name, "/", name);
|
||||||
System::FileType type = s->identify(file);
|
System::FileType type = s->stat(file, length);
|
||||||
s->free(file);
|
allocator->free(file, strlen(file) + 1);
|
||||||
return type != System::TypeDoesNotExist;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
s->free(name);
|
allocator->free(name, strlen(name) + 1);
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PointerRegion: public System::Region {
|
class PointerRegion: public System::Region {
|
||||||
public:
|
public:
|
||||||
PointerRegion(System* s, const uint8_t* start, size_t length):
|
PointerRegion(System* s, Allocator* allocator, const uint8_t* start,
|
||||||
|
size_t length):
|
||||||
s(s),
|
s(s),
|
||||||
|
allocator(allocator),
|
||||||
start_(start),
|
start_(start),
|
||||||
length_(length)
|
length_(length)
|
||||||
{ }
|
{ }
|
||||||
@ -188,18 +196,20 @@ class PointerRegion: public System::Region {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
const uint8_t* start_;
|
const uint8_t* start_;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataRegion: public System::Region {
|
class DataRegion: public System::Region {
|
||||||
public:
|
public:
|
||||||
DataRegion(System* s, size_t length):
|
DataRegion(System* s, Allocator* allocator, size_t length):
|
||||||
s(s),
|
s(s),
|
||||||
|
allocator(allocator),
|
||||||
length_(length)
|
length_(length)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -212,10 +222,11 @@ class DataRegion: public System::Region {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
};
|
};
|
||||||
@ -241,11 +252,12 @@ class JarIndex {
|
|||||||
Node* next;
|
Node* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
JarIndex(System* s, unsigned capacity):
|
JarIndex(System* s, Allocator* allocator, unsigned capacity):
|
||||||
s(s),
|
s(s),
|
||||||
|
allocator(allocator),
|
||||||
capacity(capacity),
|
capacity(capacity),
|
||||||
position(0),
|
position(0),
|
||||||
nodes(static_cast<Node*>(allocate(s, sizeof(Node) * capacity)))
|
nodes(static_cast<Node*>(allocator->allocate(sizeof(Node) * capacity)))
|
||||||
{
|
{
|
||||||
memset(table, 0, sizeof(Node*) * capacity);
|
memset(table, 0, sizeof(Node*) * capacity);
|
||||||
}
|
}
|
||||||
@ -322,14 +334,16 @@ class JarIndex {
|
|||||||
commentFieldLength(p);
|
commentFieldLength(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JarIndex* make(System* s, unsigned capacity) {
|
static JarIndex* make(System* s, Allocator* allocator, unsigned capacity) {
|
||||||
return new
|
return new
|
||||||
(allocate(s, sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
(allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
||||||
JarIndex(s, capacity);
|
JarIndex(s, allocator, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JarIndex* open(System* s, System::Region* region) {
|
static JarIndex* open(System* s, Allocator* allocator,
|
||||||
JarIndex* index = make(s, 32);
|
System::Region* region)
|
||||||
|
{
|
||||||
|
JarIndex* index = make(s, allocator, 32);
|
||||||
|
|
||||||
const uint8_t* start = region->start();
|
const uint8_t* start = region->start();
|
||||||
const uint8_t* end = start + region->length();
|
const uint8_t* end = start + region->length();
|
||||||
@ -362,7 +376,7 @@ class JarIndex {
|
|||||||
table[i] = new (nodes + (position++)) Node(hash, entry, table[i]);
|
table[i] = new (nodes + (position++)) Node(hash, entry, table[i]);
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
JarIndex* index = make(s, capacity * 2);
|
JarIndex* index = make(s, allocator, capacity * 2);
|
||||||
for (unsigned i = 0; i < capacity; ++i) {
|
for (unsigned i = 0; i < capacity; ++i) {
|
||||||
index->add(nodes[i].hash, nodes[i].entry);
|
index->add(nodes[i].hash, nodes[i].entry);
|
||||||
}
|
}
|
||||||
@ -390,15 +404,15 @@ class JarIndex {
|
|||||||
const uint8_t* p = n->entry;
|
const uint8_t* p = n->entry;
|
||||||
switch (compressionMethod(p)) {
|
switch (compressionMethod(p)) {
|
||||||
case Stored: {
|
case Stored: {
|
||||||
return new (allocate(s, sizeof(PointerRegion)))
|
return new (allocator->allocate(sizeof(PointerRegion)))
|
||||||
PointerRegion(s, fileData(start + localHeaderOffset(p)),
|
PointerRegion(s, allocator, fileData(start + localHeaderOffset(p)),
|
||||||
compressedSize(p));
|
compressedSize(p));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Deflated: {
|
case Deflated: {
|
||||||
DataRegion* region = new
|
DataRegion* region = new
|
||||||
(allocate(s, sizeof(DataRegion) + uncompressedSize(p)))
|
(allocator->allocate(sizeof(DataRegion) + uncompressedSize(p)))
|
||||||
DataRegion(s, uncompressedSize(p));
|
DataRegion(s, allocator, uncompressedSize(p));
|
||||||
|
|
||||||
z_stream zStream; memset(&zStream, 0, sizeof(z_stream));
|
z_stream zStream; memset(&zStream, 0, sizeof(z_stream));
|
||||||
|
|
||||||
@ -428,16 +442,41 @@ class JarIndex {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exists(const char* name) {
|
System::FileType stat(const char* name, unsigned* length, bool tryDirectory)
|
||||||
return findNode(name) != 0;
|
{
|
||||||
|
Node* node = findNode(name);
|
||||||
|
if (node) {
|
||||||
|
*length = uncompressedSize(node->entry);
|
||||||
|
return System::TypeFile;
|
||||||
|
} else if (tryDirectory) {
|
||||||
|
*length = 0;
|
||||||
|
|
||||||
|
// try again with '/' appended
|
||||||
|
unsigned length = strlen(name);
|
||||||
|
RUNTIME_ARRAY(char, n, length + 2);
|
||||||
|
memcpy(RUNTIME_ARRAY_BODY(n), name, length);
|
||||||
|
RUNTIME_ARRAY_BODY(n)[length] = '/';
|
||||||
|
RUNTIME_ARRAY_BODY(n)[length + 1] = 0;
|
||||||
|
|
||||||
|
node = findNode(n);
|
||||||
|
if (node) {
|
||||||
|
return System::TypeDirectory;
|
||||||
|
} else {
|
||||||
|
return System::TypeDoesNotExist;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*length = 0;
|
||||||
|
return System::TypeDoesNotExist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
s->free(nodes);
|
allocator->free(nodes, sizeof(Node) * capacity);
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this) + (sizeof(Node*) * capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
unsigned position;
|
unsigned position;
|
||||||
|
|
||||||
@ -449,7 +488,9 @@ class JarElement: public Element {
|
|||||||
public:
|
public:
|
||||||
class Iterator: public Element::Iterator {
|
class Iterator: public Element::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator(System* s, JarIndex* index): s(s), index(index), position(0) { }
|
Iterator(System* s, Allocator* allocator, JarIndex* index):
|
||||||
|
s(s), allocator(allocator), index(index), position(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
virtual const char* next(unsigned* size) {
|
virtual const char* next(unsigned* size) {
|
||||||
if (position < index->position) {
|
if (position < index->position) {
|
||||||
@ -462,22 +503,34 @@ class JarElement: public Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
JarIndex* index;
|
JarIndex* index;
|
||||||
unsigned position;
|
unsigned position;
|
||||||
};
|
};
|
||||||
|
|
||||||
JarElement(System* s, const char* name):
|
JarElement(System* s, Allocator* allocator, const char* name):
|
||||||
s(s), name(name), region(0), index(0)
|
s(s), allocator(allocator), name(name), region(0), index(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
JarElement(System* s, Allocator* allocator, const uint8_t* jarData,
|
||||||
|
unsigned jarLength):
|
||||||
|
s(s),
|
||||||
|
allocator(allocator),
|
||||||
|
name(0),
|
||||||
|
region(new (allocator->allocate(sizeof(PointerRegion)))
|
||||||
|
PointerRegion(s, allocator, jarData, jarLength)),
|
||||||
|
index(JarIndex::open(s, allocator, region))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual Element::Iterator* iterator() {
|
virtual Element::Iterator* iterator() {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
return new (allocate(s, sizeof(Iterator))) Iterator(s, index);
|
return new (allocator->allocate(sizeof(Iterator)))
|
||||||
|
Iterator(s, allocator, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void init() {
|
virtual void init() {
|
||||||
@ -485,7 +538,7 @@ class JarElement: public Element {
|
|||||||
System::Region* r;
|
System::Region* r;
|
||||||
if (s->success(s->map(&r, name))) {
|
if (s->success(s->map(&r, name))) {
|
||||||
region = r;
|
region = r;
|
||||||
index = JarIndex::open(s, r);
|
index = JarIndex::open(s, allocator, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,26 +559,34 @@ class JarElement: public Element {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool exists(const char* name) {
|
virtual System::FileType stat(const char* name, unsigned* length,
|
||||||
|
bool tryDirectory)
|
||||||
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
while (*name == '/') name++;
|
while (*name == '/') name++;
|
||||||
|
|
||||||
return (index ? index->exists(name) : 0);
|
return (index ? index->stat(name, length, tryDirectory)
|
||||||
|
: System::TypeDoesNotExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
s->free(name);
|
dispose(sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose(unsigned size) {
|
||||||
|
allocator->free(name, strlen(name) + 1);
|
||||||
if (index) {
|
if (index) {
|
||||||
index->dispose();
|
index->dispose();
|
||||||
}
|
}
|
||||||
if (region) {
|
if (region) {
|
||||||
region->dispose();
|
region->dispose();
|
||||||
}
|
}
|
||||||
s->free(this);
|
allocator->free(this, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
const char* name;
|
const char* name;
|
||||||
System::Region* region;
|
System::Region* region;
|
||||||
JarIndex* index;
|
JarIndex* index;
|
||||||
@ -533,9 +594,10 @@ class JarElement: public Element {
|
|||||||
|
|
||||||
class BuiltinElement: public JarElement {
|
class BuiltinElement: public JarElement {
|
||||||
public:
|
public:
|
||||||
BuiltinElement(System* s, const char* name, const char* libraryName):
|
BuiltinElement(System* s, Allocator* allocator, const char* name,
|
||||||
JarElement(s, name),
|
const char* libraryName):
|
||||||
libraryName(libraryName ? copy(s, libraryName) : 0)
|
JarElement(s, allocator, name),
|
||||||
|
libraryName(libraryName ? copy(allocator, libraryName) : 0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void init() {
|
virtual void init() {
|
||||||
@ -549,9 +611,9 @@ class BuiltinElement: public JarElement {
|
|||||||
unsigned size;
|
unsigned size;
|
||||||
uint8_t* data = function(&size);
|
uint8_t* data = function(&size);
|
||||||
if (data) {
|
if (data) {
|
||||||
region = new (allocate(s, sizeof(PointerRegion)))
|
region = new (allocator->allocate(sizeof(PointerRegion)))
|
||||||
PointerRegion(s, data, size);
|
PointerRegion(s, allocator, data, size);
|
||||||
index = JarIndex::open(s, region);
|
index = JarIndex::open(s, allocator, region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,8 +622,10 @@ class BuiltinElement: public JarElement {
|
|||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
library->disposeAll();
|
library->disposeAll();
|
||||||
s->free(libraryName);
|
if (libraryName) {
|
||||||
JarElement::dispose();
|
allocator->free(libraryName, strlen(libraryName) + 1);
|
||||||
|
}
|
||||||
|
JarElement::dispose(sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Library* library;
|
System::Library* library;
|
||||||
@ -569,7 +633,8 @@ class BuiltinElement: public JarElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Element*
|
Element*
|
||||||
parsePath(System* s, const char* path, const char* bootLibrary)
|
parsePath(System* s, Allocator* allocator, const char* path,
|
||||||
|
const char* bootLibrary)
|
||||||
{
|
{
|
||||||
Element* first = 0;
|
Element* first = 0;
|
||||||
Element* prev = 0;
|
Element* prev = 0;
|
||||||
@ -578,29 +643,31 @@ parsePath(System* s, const char* path, const char* bootLibrary)
|
|||||||
|
|
||||||
Element* e;
|
Element* e;
|
||||||
if (*token.s == '[' and token.s[token.length - 1] == ']') {
|
if (*token.s == '[' and token.s[token.length - 1] == ']') {
|
||||||
char* name = static_cast<char*>(allocate(s, token.length - 1));
|
char* name = static_cast<char*>(allocator->allocate(token.length - 1));
|
||||||
memcpy(name, token.s + 1, token.length - 1);
|
memcpy(name, token.s + 1, token.length - 1);
|
||||||
name[token.length - 2] = 0;
|
name[token.length - 2] = 0;
|
||||||
|
|
||||||
e = new (allocate(s, sizeof(BuiltinElement)))
|
e = new (allocator->allocate(sizeof(BuiltinElement)))
|
||||||
BuiltinElement(s, name, bootLibrary);
|
BuiltinElement(s, allocator, name, bootLibrary);
|
||||||
} else {
|
} else {
|
||||||
char* name = static_cast<char*>(allocate(s, token.length + 1));
|
char* name = static_cast<char*>(allocator->allocate(token.length + 1));
|
||||||
memcpy(name, token.s, token.length);
|
memcpy(name, token.s, token.length);
|
||||||
name[token.length] = 0;
|
name[token.length] = 0;
|
||||||
|
|
||||||
switch (s->identify(name)) {
|
unsigned length;
|
||||||
|
switch (s->stat(name, &length)) {
|
||||||
case System::TypeFile: {
|
case System::TypeFile: {
|
||||||
e = new (allocate(s, sizeof(JarElement))) JarElement(s, name);
|
e = new (allocator->allocate(sizeof(JarElement)))
|
||||||
|
JarElement(s, allocator, name);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case System::TypeDirectory: {
|
case System::TypeDirectory: {
|
||||||
e = new (allocate(s, sizeof(DirectoryElement)))
|
e = new (allocator->allocate(sizeof(DirectoryElement)))
|
||||||
DirectoryElement(s, name);
|
DirectoryElement(s, allocator, name);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
s->free(name);
|
allocator->free(name, strlen(name) + 1);
|
||||||
e = 0;
|
e = 0;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -621,8 +688,9 @@ parsePath(System* s, const char* path, const char* bootLibrary)
|
|||||||
|
|
||||||
class MyIterator: public Finder::IteratorImp {
|
class MyIterator: public Finder::IteratorImp {
|
||||||
public:
|
public:
|
||||||
MyIterator(System* s, Element* path):
|
MyIterator(System* s, Allocator* allocator, Element* path):
|
||||||
s(s), e(path ? path->next : 0), it(path ? path->iterator() : 0)
|
s(s), allocator(allocator), e(path ? path->next : 0),
|
||||||
|
it(path ? path->iterator() : 0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual const char* next(unsigned* size) {
|
virtual const char* next(unsigned* size) {
|
||||||
@ -645,25 +713,37 @@ class MyIterator: public Finder::IteratorImp {
|
|||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
if (it) it->dispose();
|
if (it) it->dispose();
|
||||||
s->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
Allocator* allocator;
|
||||||
Element* e;
|
Element* e;
|
||||||
Element::Iterator* it;
|
Element::Iterator* it;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyFinder: public Finder {
|
class MyFinder: public Finder {
|
||||||
public:
|
public:
|
||||||
MyFinder(System* system, const char* path, const char* bootLibrary):
|
MyFinder(System* system, Allocator* allocator, const char* path,
|
||||||
|
const char* bootLibrary):
|
||||||
system(system),
|
system(system),
|
||||||
path_(parsePath(system, path, bootLibrary)),
|
allocator(allocator),
|
||||||
pathString(copy(system, path))
|
path_(parsePath(system, allocator, path, bootLibrary)),
|
||||||
|
pathString(copy(allocator, path))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
MyFinder(System* system, Allocator* allocator, const uint8_t* jarData,
|
||||||
|
unsigned jarLength):
|
||||||
|
system(system),
|
||||||
|
allocator(allocator),
|
||||||
|
path_(new (allocator->allocate(sizeof(JarElement)))
|
||||||
|
JarElement(system, allocator, jarData, jarLength)),
|
||||||
|
pathString(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual IteratorImp* iterator() {
|
virtual IteratorImp* iterator() {
|
||||||
return new (allocate(system, sizeof(MyIterator)))
|
return new (allocator->allocate(sizeof(MyIterator)))
|
||||||
MyIterator(system, path_);
|
MyIterator(system, allocator, path_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual System::Region* find(const char* name) {
|
virtual System::Region* find(const char* name) {
|
||||||
@ -677,14 +757,17 @@ class MyFinder: public Finder {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool exists(const char* name) {
|
virtual System::FileType stat(const char* name, unsigned* length,
|
||||||
|
bool tryDirectory)
|
||||||
|
{
|
||||||
for (Element* e = path_; e; e = e->next) {
|
for (Element* e = path_; e; e = e->next) {
|
||||||
if (e->exists(name)) {
|
System::FileType type = e->stat(name, length, tryDirectory);
|
||||||
return true;
|
if (type != System::TypeDoesNotExist) {
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return System::TypeDoesNotExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* path() {
|
virtual const char* path() {
|
||||||
@ -697,11 +780,12 @@ class MyFinder: public Finder {
|
|||||||
e = e->next;
|
e = e->next;
|
||||||
t->dispose();
|
t->dispose();
|
||||||
}
|
}
|
||||||
system->free(pathString);
|
allocator->free(pathString, strlen(pathString) + 1);
|
||||||
system->free(this);
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
System* system;
|
System* system;
|
||||||
|
Allocator* allocator;
|
||||||
Element* path_;
|
Element* path_;
|
||||||
const char* pathString;
|
const char* pathString;
|
||||||
};
|
};
|
||||||
@ -711,9 +795,16 @@ class MyFinder: public Finder {
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Finder*
|
Finder*
|
||||||
makeFinder(System* s, const char* path, const char* bootLibrary)
|
makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary)
|
||||||
{
|
{
|
||||||
return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path, bootLibrary);
|
return new (a->allocate(sizeof(MyFinder))) MyFinder(s, a, path, bootLibrary);
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder*
|
||||||
|
makeFinder(System* s, Allocator* a, const uint8_t* jarData, unsigned jarLength)
|
||||||
|
{
|
||||||
|
return new (a->allocate(sizeof(MyFinder)))
|
||||||
|
MyFinder(s, a, jarData, jarLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
10
src/finder.h
10
src/finder.h
@ -60,13 +60,19 @@ class Finder {
|
|||||||
|
|
||||||
virtual IteratorImp* iterator() = 0;
|
virtual IteratorImp* iterator() = 0;
|
||||||
virtual System::Region* find(const char* name) = 0;
|
virtual System::Region* find(const char* name) = 0;
|
||||||
virtual bool exists(const char* name) = 0;
|
virtual System::FileType stat(const char* name,
|
||||||
|
unsigned* length,
|
||||||
|
bool tryDirectory = false) = 0;
|
||||||
virtual const char* path() = 0;
|
virtual const char* path() = 0;
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Finder*
|
Finder*
|
||||||
makeFinder(System* s, const char* path, const char* bootLibrary);
|
makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary);
|
||||||
|
|
||||||
|
Finder*
|
||||||
|
makeFinder(System* s, Allocator* a, const uint8_t* jarData,
|
||||||
|
unsigned jarLength);
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
@ -2228,6 +2228,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
|||||||
|
|
||||||
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
|
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
|
||||||
#define CRASHDIR_PROPERTY "avian.crash.dir"
|
#define CRASHDIR_PROPERTY "avian.crash.dir"
|
||||||
|
#define EMBED_PREFIX_PROPERTY "avian.embed.prefix"
|
||||||
#define CLASSPATH_PROPERTY "java.class.path"
|
#define CLASSPATH_PROPERTY "java.class.path"
|
||||||
#define JAVA_HOME_PROPERTY "java.home"
|
#define JAVA_HOME_PROPERTY "java.home"
|
||||||
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
|
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
|
||||||
@ -2250,6 +2251,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
|||||||
const char* bootLibrary = 0;
|
const char* bootLibrary = 0;
|
||||||
const char* classpath = 0;
|
const char* classpath = 0;
|
||||||
const char* javaHome = AVIAN_JAVA_HOME;
|
const char* javaHome = AVIAN_JAVA_HOME;
|
||||||
|
const char* embedPrefix = AVIAN_EMBED_PREFIX;
|
||||||
const char* bootClasspathPrepend = "";
|
const char* bootClasspathPrepend = "";
|
||||||
const char* bootClasspath = 0;
|
const char* bootClasspath = 0;
|
||||||
const char* bootClasspathAppend = "";
|
const char* bootClasspathAppend = "";
|
||||||
@ -2293,6 +2295,10 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
|||||||
sizeof(JAVA_HOME_PROPERTY)) == 0)
|
sizeof(JAVA_HOME_PROPERTY)) == 0)
|
||||||
{
|
{
|
||||||
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
|
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
|
||||||
|
} else if (strncmp(p, EMBED_PREFIX_PROPERTY "=",
|
||||||
|
sizeof(EMBED_PREFIX_PROPERTY)) == 0)
|
||||||
|
{
|
||||||
|
embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
++ propertyCount;
|
++ propertyCount;
|
||||||
@ -2305,7 +2311,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
|||||||
|
|
||||||
System* s = makeSystem(crashDumpDirectory);
|
System* s = makeSystem(crashDumpDirectory);
|
||||||
Heap* h = makeHeap(s, heapLimit);
|
Heap* h = makeHeap(s, heapLimit);
|
||||||
Classpath* c = makeClasspath(s, h, javaHome);
|
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
||||||
|
|
||||||
if (bootClasspath == 0) {
|
if (bootClasspath == 0) {
|
||||||
bootClasspath = c->bootClasspath();
|
bootClasspath = c->bootClasspath();
|
||||||
@ -2325,8 +2331,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
|||||||
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
||||||
|
|
||||||
Finder* bf = makeFinder
|
Finder* bf = makeFinder
|
||||||
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
||||||
Finder* af = makeFinder(s, classpath, bootLibrary);
|
Finder* af = makeFinder(s, h, classpath, bootLibrary);
|
||||||
Processor* p = makeProcessor(s, h, true);
|
Processor* p = makeProcessor(s, h, true);
|
||||||
|
|
||||||
const char** properties = static_cast<const char**>
|
const char** properties = static_cast<const char**>
|
||||||
|
@ -193,6 +193,23 @@ turnOffTheLights(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root(t, Machine::VirtualFiles)) {
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, root(t, Machine::VirtualFiles));
|
||||||
|
++i)
|
||||||
|
{
|
||||||
|
object region = arrayBody(t, root(t, Machine::VirtualFiles), i);
|
||||||
|
if (region) {
|
||||||
|
static_cast<System::Region*>(regionRegion(t, region))->dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (object p = root(t, Machine::VirtualFileFinders);
|
||||||
|
p; p = finderNext(t, p))
|
||||||
|
{
|
||||||
|
static_cast<Finder*>(finderFinder(t, p))->dispose();
|
||||||
|
}
|
||||||
|
|
||||||
Machine* m = t->m;
|
Machine* m = t->m;
|
||||||
|
|
||||||
disposeAll(t, t->m->rootThread);
|
disposeAll(t, t->m->rootThread);
|
||||||
@ -204,13 +221,13 @@ turnOffTheLights(Thread* t)
|
|||||||
Finder* bf = m->bootFinder;
|
Finder* bf = m->bootFinder;
|
||||||
Finder* af = m->appFinder;
|
Finder* af = m->appFinder;
|
||||||
|
|
||||||
|
c->dispose();
|
||||||
m->dispose();
|
m->dispose();
|
||||||
h->disposeFixies();
|
h->disposeFixies();
|
||||||
c->dispose();
|
|
||||||
p->dispose();
|
p->dispose();
|
||||||
h->dispose();
|
|
||||||
bf->dispose();
|
bf->dispose();
|
||||||
af->dispose();
|
af->dispose();
|
||||||
|
h->dispose();
|
||||||
s->dispose();
|
s->dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,10 +1198,12 @@ class Machine {
|
|||||||
ShutdownHooks,
|
ShutdownHooks,
|
||||||
ObjectsToFinalize,
|
ObjectsToFinalize,
|
||||||
NullPointerException,
|
NullPointerException,
|
||||||
ArrayIndexOutOfBoundsException
|
ArrayIndexOutOfBoundsException,
|
||||||
|
VirtualFileFinders,
|
||||||
|
VirtualFiles
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1;
|
static const unsigned RootCount = VirtualFiles + 1;
|
||||||
|
|
||||||
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
||||||
Processor* processor, Classpath* classpath, const char** properties,
|
Processor* processor, Classpath* classpath, const char** properties,
|
||||||
@ -1446,7 +1448,8 @@ runJavaThread(Thread* t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Classpath*
|
Classpath*
|
||||||
makeClasspath(System* system, Allocator* allocator, const char* javaHome);
|
makeClasspath(System* system, Allocator* allocator, const char* javaHome,
|
||||||
|
const char* embedPrefix);
|
||||||
|
|
||||||
typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
|
typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
@ -698,18 +698,22 @@ class MySystem: public System {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual FileType identify(const char* name) {
|
virtual FileType stat(const char* name, unsigned* length) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
int r = stat(name, &s);
|
int r = ::stat(name, &s);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
if (S_ISREG(s.st_mode)) {
|
if (S_ISREG(s.st_mode)) {
|
||||||
|
*length = s.st_size;
|
||||||
return TypeFile;
|
return TypeFile;
|
||||||
} else if (S_ISDIR(s.st_mode)) {
|
} else if (S_ISDIR(s.st_mode)) {
|
||||||
|
*length = 0;
|
||||||
return TypeDirectory;
|
return TypeDirectory;
|
||||||
} else {
|
} else {
|
||||||
|
*length = 0;
|
||||||
return TypeUnknown;
|
return TypeUnknown;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
*length = 0;
|
||||||
return TypeDoesNotExist;
|
return TypeDoesNotExist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ class System {
|
|||||||
unsigned count, unsigned size,
|
unsigned count, unsigned size,
|
||||||
unsigned returnType) = 0;
|
unsigned returnType) = 0;
|
||||||
virtual Status map(Region**, const char* name) = 0;
|
virtual Status map(Region**, const char* name) = 0;
|
||||||
virtual FileType identify(const char* name) = 0;
|
virtual FileType stat(const char* name, unsigned* length) = 0;
|
||||||
virtual Status open(Directory**, const char* name) = 0;
|
virtual Status open(Directory**, const char* name) = 0;
|
||||||
virtual const char* libraryPrefix() = 0;
|
virtual const char* libraryPrefix() = 0;
|
||||||
virtual const char* librarySuffix() = 0;
|
virtual const char* librarySuffix() = 0;
|
||||||
|
@ -2213,7 +2213,31 @@ main(int ac, char** av)
|
|||||||
}
|
}
|
||||||
|
|
||||||
System* system = makeSystem(0);
|
System* system = makeSystem(0);
|
||||||
Finder* finder = makeFinder(system, av[1], 0);
|
|
||||||
|
class MyAllocator: public Allocator {
|
||||||
|
public:
|
||||||
|
MyAllocator(System* s): s(s) { }
|
||||||
|
|
||||||
|
virtual void* tryAllocate(unsigned size) {
|
||||||
|
return s->tryAllocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* allocate(unsigned size) {
|
||||||
|
void* p = tryAllocate(size);
|
||||||
|
if (p == 0) {
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void free(const void* p, unsigned) {
|
||||||
|
s->free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
System* s;
|
||||||
|
} allocator(system);
|
||||||
|
|
||||||
|
Finder* finder = makeFinder(system, &allocator, av[1], 0);
|
||||||
|
|
||||||
FILE* inStream = ::fopen(av[2], "rb");
|
FILE* inStream = ::fopen(av[2], "rb");
|
||||||
if (inStream == 0) {
|
if (inStream == 0) {
|
||||||
|
@ -48,6 +48,15 @@
|
|||||||
(extends native)
|
(extends native)
|
||||||
(object original))
|
(object original))
|
||||||
|
|
||||||
|
(type finder
|
||||||
|
(void* finder)
|
||||||
|
(object name)
|
||||||
|
(object next))
|
||||||
|
|
||||||
|
(type region
|
||||||
|
(void* region)
|
||||||
|
(unsigned position))
|
||||||
|
|
||||||
(pod exceptionHandler
|
(pod exceptionHandler
|
||||||
(uint16_t start)
|
(uint16_t start)
|
||||||
(uint16_t end)
|
(uint16_t end)
|
||||||
|
21
src/util.cpp
21
src/util.cpp
@ -529,11 +529,6 @@ vectorAppend(Thread* t, object vector, object value)
|
|||||||
vectorSize(t, vector) * BytesPerWord);
|
vectorSize(t, vector) * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&vectorBody(t, newVector, vectorSize(t, vector) + 1),
|
|
||||||
0,
|
|
||||||
(vectorLength(t, newVector) - vectorSize(t, vector) - 1)
|
|
||||||
* BytesPerWord);
|
|
||||||
|
|
||||||
vector = newVector;
|
vector = newVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +537,22 @@ vectorAppend(Thread* t, object vector, object value)
|
|||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
growArray(Thread* t, object array)
|
||||||
|
{
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
object newArray = makeArray
|
||||||
|
(t, array == 0 ? 16 : (arrayLength(t, array) * 2));
|
||||||
|
|
||||||
|
if (array) {
|
||||||
|
memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0),
|
||||||
|
arrayLength(t, array));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newArray;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
|
@ -84,6 +84,9 @@ listAppend(Thread* t, object list, object value);
|
|||||||
object
|
object
|
||||||
vectorAppend(Thread* t, object vector, object value);
|
vectorAppend(Thread* t, object vector, object value);
|
||||||
|
|
||||||
|
object
|
||||||
|
growArray(Thread* t, object array);
|
||||||
|
|
||||||
object
|
object
|
||||||
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||||
|
@ -204,5 +204,7 @@ public class Misc {
|
|||||||
} while (x != 1);
|
} while (x != 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println(java.util.Calendar.getInstance().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user