From 96bb989ad50b56fdc0a96e2d5e8ef4ced244d3ec Mon Sep 17 00:00:00 2001 From: mae Date: Sun, 16 Nov 2025 15:09:29 -0600 Subject: [PATCH] write to fd --- cmd/plt-build/src/main/go/pltbuild.c | 26 +++++++++++++ cmd/plt-build/src/main/go/pltbuild.go | 38 +++++++++++++++++++ cmd/plt-build/src/main/go/pltbuild.h | 17 +++++++++ .../kotlin/moe/rosa/planterette/dsl/DSL.kt | 20 +++++++++- .../kotlin/moe/rosa/planterette/jni/GoFile.kt | 5 +++ 5 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 cmd/plt-build/src/main/go/pltbuild.c create mode 100644 cmd/plt-build/src/main/go/pltbuild.go create mode 100644 cmd/plt-build/src/main/go/pltbuild.h create mode 100644 cmd/plt-build/src/main/kotlin/moe/rosa/planterette/jni/GoFile.kt diff --git a/cmd/plt-build/src/main/go/pltbuild.c b/cmd/plt-build/src/main/go/pltbuild.c new file mode 100644 index 0000000..7b1759a --- /dev/null +++ b/cmd/plt-build/src/main/go/pltbuild.c @@ -0,0 +1,26 @@ +#include "pltbuild.h" + +jint throwIOException( JNIEnv *env, char *message) { + jclass exClass; + char *className = "java/io/IOException"; + + exClass = (*env)->FindClass(env, className); + return (*env)->ThrowNew(env, exClass, message); +} + +JNIEXPORT void JNICALL Java_moe_rosa_planterette_jni_GoFile_write__ILnet_java_String_2(JNIEnv *env, jobject obj, jint fd, jstring str) { + char *s = (*env)->GetStringUTFChars(env, str, 0); + size_t sz = (*env)->GetStringUTFLength(env, str); + + uintptr_t *errno_p = NULL; + char **err_str_p = NULL; + + planterette_write(fd, s, sz, errno_p, err_str_p); + + if(errno_p || *err_str_p ) { + throwIOException(env, **err_str_p ? *err_str_p : strerror(*errno_p)); + } + + (*env)->ReleaseStringUTFChars(env, str, s); + free(err_str_p); +} diff --git a/cmd/plt-build/src/main/go/pltbuild.go b/cmd/plt-build/src/main/go/pltbuild.go new file mode 100644 index 0000000..6d91761 --- /dev/null +++ b/cmd/plt-build/src/main/go/pltbuild.go @@ -0,0 +1,38 @@ +package _go + +//#cgo CFLAGS: -I "$JAVA_HOME/include" -I "$JAVA_HOME/include/linux" +//#include "pltbuild.h" +import "C" +import ( + "errors" + "os" + "strconv" + "syscall" +) + +//export planterette_write +func planterette_write( + fd C.int, + str_p *C.char, str_sz C.size_t, + errno_p *C.uintptr_t, + err_str_p **C.char, +) { + f := os.NewFile(uintptr(fd), strconv.Itoa(int(fd))) + defer f.Close() + _, err := f.WriteString(C.GoStringN(str_p, C.int(str_sz))) + if err == nil { + return + } + + var pathError *os.PathError + if errors.As(err, &pathError) { + var errno syscall.Errno + if errors.As(pathError.Err, &errno) { + *errno_p = C.uintptr_t(errno) + return + } + } + + *err_str_p = C.CString(err.Error()) + return +} diff --git a/cmd/plt-build/src/main/go/pltbuild.h b/cmd/plt-build/src/main/go/pltbuild.h new file mode 100644 index 0000000..93e3cec --- /dev/null +++ b/cmd/plt-build/src/main/go/pltbuild.h @@ -0,0 +1,17 @@ +#include + +#include +#include +#include + +#ifndef _PLTBUILD_H +#define _PLTBUILD_H + +/* + * moe/rosa/planterette/jni/GoFile#write(ILnet/java/String;)V + */ +JNIEXPORT void JNICALL Java_moe_rosa_planterette_jni_GoFile_write__ILnet_java_String_2(JNIEnv *, jobject, jint, jstring); + +extern void planterette_write(int fd, char *str_p, size_t str_sz, uintptr_t *errno_p, char **err_str_p); + +#endif \ No newline at end of file diff --git a/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/dsl/DSL.kt b/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/dsl/DSL.kt index 91185f5..1b25526 100644 --- a/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/dsl/DSL.kt +++ b/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/dsl/DSL.kt @@ -1,8 +1,11 @@ @file:Suppress("unused") package moe.rosa.planterette.dsl +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json import moe.rosa.planterette.api.Capability import moe.rosa.planterette.api.Manifest +import moe.rosa.planterette.jni.GoFile @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @@ -38,8 +41,21 @@ data class PlanteretteBlock( var metadata: MetadataBlock, var executable: ExecutableBlock, var capabilities: CapabilitiesBlock, - var permissions: PermissionsBlock -) + var permissions: PermissionsBlock, + var buildGuard: Boolean = false +) { + // NOTE the two underscores are because this function is only intended to be added at runtime + @OptIn(ExperimentalSerializationApi::class) + @Suppress("FunctionName") + fun __build(args: Array): PlanteretteBlock { + if(!buildGuard) { + val manifest = Manifest(metadata.metadata, executable.executable, capabilities.capabilities, permissions.permissions) + GoFile.write(args[0].toInt(), Json.encodeToString(manifest)) + buildGuard = true + } + return this; + } +} @MetadataBlockMarker data class MetadataBlock(var metadata: Manifest.Metadata) diff --git a/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/jni/GoFile.kt b/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/jni/GoFile.kt new file mode 100644 index 0000000..0fc62f5 --- /dev/null +++ b/cmd/plt-build/src/main/kotlin/moe/rosa/planterette/jni/GoFile.kt @@ -0,0 +1,5 @@ +package moe.rosa.planterette.jni + +object GoFile { + external fun write(fd: Int, str: String) +} \ No newline at end of file