vessel/old/temple.c
2025-06-13 17:58:13 +03:00

206 lines
4.6 KiB
C

#include "include/conf.h"
#include <vessel/mem.h>
#include <vessel/file.h>
#include <vessel/stream.h>
#include <vessel/blake2s.h>
#include "include/temple.h"
/* TODO: Implement temple */
Bool Temple_init(Temple *temple) {
if (!temple)
return False;
if (!File_init(&temple->f, NULL))
return False;
return True;
}
Bool Temple_open(Temple *temple, const char *path) {
if (!temple)
return False;
if (!File_open(&temple->f, path, FILEF_RD, FILEM_NONE))
return False;
/* Check basic conditions. */
FileStat s;
if (!File_stat(&temple->f, &s))
goto error;
if (s.size < 38) /* Minimum possible file size is 38 */
goto error;
/* Magic */
if (File_read(&temple->f, &temple->magic, 6) != 6)
goto error;
if (memcmp(temple->magic, "temple", 6) != 0)
goto error;
/* Digest */
if (File_read(&temple->f, &temple->digest, 32) != 32)
goto error;
const uint64_t pos_after_digest = File_seek(&temple->f, 0, FILES_CUR);
/* Version */
if (File_read(&temple->f, &temple->version, 2) != 2)
goto error;
temple->version = TO_ULE16(temple->version);
if (temple->version != 1)
goto error;
/* Flags */
if (File_read(&temple->f, &temple->flags, 4) != 4)
goto error;
temple->flags = TO_ULE32(temple->flags);
if ((temple->flags & TEMPLE_FLAG_PERFORM_SANITY_CHECKS) ||
(0 == (temple->flags & TEMPLE_FLAG_ALLOW_TAMPERING))) {
/* Will be used for jump checks */
temple->code_start = File_seek(&temple->f, 0, FILES_CUR);
}
/* Digest verification */
if (0 == (temple->flags & TEMPLE_FLAG_ALLOW_TAMPERING)) {
if (File_seek(&temple->f, pos_after_digest, FILES_SET) != pos_after_digest)
goto error;
uint64_t read_sz;
Blake2sCtx b;
const uint64_t size = TO_ULE64(s.size);
if (!Blake2sCtx_init(&b, 32, &size, 8))
goto error;
uint8_t *buf = Malloc(STREAM_BUFSZ);
if (!buf)
goto error;
while ((read_sz = File_read(&temple->f, buf, STREAM_BUFSZ)) != 0) {
if (!Blake2sCtx_update(&b, buf, read_sz)) {
Free(buf);
goto error;
}
}
if (!Blake2sCtx_final(&b)) {
Free(buf);
goto error;
}
if (memcmp(temple->digest, b.digest, 32) != 0) {
Free(buf);
goto error;
}
Free(buf);
/* Go back to code */
if (File_seek(&temple->f, temple->code_start, FILES_SET) != temple->code_start)
goto error;
}
return True;
error:
File_close(&temple->f);
return False;
}
Bool Temple_destroy(Temple *temple) {
if (!temple)
return False;
return File_destroy(&temple->f);
}
Bool TempleState_init(TempleState *state, Temple *temple) {
if (!state || temple->flags == TEMPLE_FLAG_NONE)
return False;
if (!Lock_init(&state->lock))
return False;
if (!Lock_lock(&state->lock)) {
Lock_destroy(&state->lock);
return False;
}
state->render = True;
state->start = 0.0;
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ)) {
if (!HMap_init(&state->vars))
goto error;
}
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK) {
state->stack = Malloc(TEMPLE_STACK_MAX * sizeof(*state->stack));
if (!state->stack) {
Free(state->stack);
goto error;
}
state->sdx = 0;
}
if ((temple->flags) & TEMPLE_FLAG_ALLOW_LABELS) {
state->cdx = File_seek(&temple->f, 0, FILES_CUR);
state->old_cdx = 0;
}
if (!Lock_unlock(&state->lock)) {
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ))
HMap_destroy(&state->vars);
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK)
Free(state->stack);
goto error;
}
return True;
error:
Lock_unlock(&state->lock);
Lock_destroy(&state->lock);
return False;
}
Bool TempleState_destroy(TempleState *state, const Temple *temple) {
if (!state || !Lock_lock(&state->lock))
return False;
Bool res = True;
state->render = False;
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ))
if (!HMap_destroy_free(&state->vars))
res = False;
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK)
Free(state->stack);
if (!Lock_unlock(&state->lock))
res = False;
if (!Lock_destroy(&state->lock))
res = False;
return res;
}