diff --git a/src/kivm/native/java_io_FileOutputStream.cpp b/src/kivm/native/java_io_FileOutputStream.cpp index eff80b6..fd33b4e 100644 --- a/src/kivm/native/java_io_FileOutputStream.cpp +++ b/src/kivm/native/java_io_FileOutputStream.cpp @@ -3,10 +3,56 @@ // #include +#include +#include #include +#include +#include +#include +#include using namespace kivm; JAVA_NATIVE void Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass java_io_FileOutputStream) { D("java/io/FileOutputStream.initIDs()V"); } + +JAVA_NATIVE void Java_java_io_FileOutputStream_writeBytes(JNIEnv *env, jobject javaOutputStream, + jbyteArray b, jint off, jint len, jboolean append) { + static auto CLASS = (InstanceKlass *) BootstrapClassLoader::get() + ->loadClass(L"java/io/FileOutputStream"); + static auto FD_CLASS = (InstanceKlass *) BootstrapClassLoader::get() + ->loadClass(L"java/io/FileDescriptor"); + static auto FD_FIELD = CLASS->getInstanceFieldInfo(CLASS->getName(), L"fd", L"Ljava/io/FileDescriptor;"); + static auto FD_INT_FIELD = FD_CLASS->getInstanceFieldInfo(FD_CLASS->getName(), L"fd", L"I"); + + auto byteArray = Resolver::typeArray(b); + if (byteArray == nullptr) { + SHOULD_NOT_REACH_HERE(); + } + + if (byteArray->getLength() <= off && byteArray->getLength() < (off + len)) { + PANIC("java.lang.ArrayIndexOutOfBoundsException"); + } + + auto streamOop = Resolver::instance(javaOutputStream); + instanceOop fdOop = nullptr; + if (!streamOop->getFieldValue(FD_FIELD, (oop *) &fdOop)) { + SHOULD_NOT_REACH_HERE(); + } + + intOop fdInt = nullptr; + if (!fdOop->getFieldValue(FD_INT_FIELD, (oop *) &fdInt)) { + SHOULD_NOT_REACH_HERE(); + } + + int fd = fdInt->getValue(); + auto *buf = (char *) Universe::allocCObject(sizeof(char) * len); + for (int i = off, j = 0; i < off + len; i++, j++) { + buf[j] = (char) ((intOop) byteArray->getElementAt(i))->getValue(); + } + if (write(fd, buf, (size_t) len) == -1) { + PANIC("java.lang.IOException"); + } + Universe::deallocCObject(buf); +}