diff options
| author | 2023-12-25 06:05:40 -0600 | |
|---|---|---|
| committer | 2023-12-25 06:05:40 -0600 | |
| commit | 6d1d4d0a5506dce90c833ef8dd141058fea3c33a (patch) | |
| tree | 12a95579dbf04c4310e5b42ad8cae399d81f1189 /src/instance.c | |
| parent | initial commit (diff) | |
[WIP] Add instances
still need to do the following:
- check if the folder exists
- try and find some way to canonicalize the path name
Diffstat (limited to 'src/instance.c')
| -rw-r--r-- | src/instance.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/instance.c b/src/instance.c new file mode 100644 index 0000000..20c0f59 --- /dev/null +++ b/src/instance.c @@ -0,0 +1,193 @@ +#include "instance.h" +#include "l2su.h" +#include "uuid/uuid.h" + +#include <stdlib.h> +#include <jansson.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#include <errno.h> + +int l2_instance__load_all_from_object(json_t *obj); +json_t *l2_instance__save_all_to_object(void); + +/* da main functionality */ + +int l2_instance_load_all(void) +{ + /* open + openat because I am too lazy to concatenate the path with the filename */ + int instfd = l2_launcher_open_config("instance.json", O_RDONLY, 0); + if (instfd < 0) { + return errno == ENOENT ? INSTANCE_SUCCESS : INSTANCE_ERRNO; + } + + json_error_t jserr; + json_t *js = json_loadfd(instfd, JSON_REJECT_DUPLICATES, &jserr); + + if (!js) { + fprintf(stderr, "error: JSON error in instance.json: %s (%s:%d:%d)\n", jserr.text, jserr.source, jserr.line, jserr.column); + return INSTANCE_EJSON; + } + + if (!json_is_object(js)) { + fprintf(stderr, "error: instances.json value is not an object (is actually %d)\n", json_typeof(js)); + json_decref(js); + return INSTANCE_EFORMAT; + } + + int res = l2_instance__load_all_from_object(js); + json_decref(js); + return res; +} + +int l2_instance_save_all(void) +{ + json_t *js = NULL; + int instfd = l2_launcher_open_config("instance.json", O_WRONLY | O_CREAT, 0644); + if (instfd < 0) return INSTANCE_ERRNO; + + int retval = INSTANCE_SUCCESS; + + js = l2_instance__save_all_to_object(); + if (!js) { + retval = INSTANCE_EJSON; + goto save_done; + } + + if (json_dumpfd(js, instfd, JSON_INDENT(4)) < 0) { + retval = INSTANCE_EJSON; + } + +save_done: + close(instfd); + json_decref(js); + return retval; +} + +/* public utilities */ + +int l2_instance_add_instance(const struct l2_instance *inst) +{ + char *path = strdup(inst->path); + if (!path) return INSTANCE_ERRNO; + + char *name = strdup(inst->name); + if (!name) { + free(path); + return INSTANCE_ERRNO; + } + + struct l2_instance *newinst = calloc(1, sizeof(struct l2_instance)); + if (!newinst) { + free(path); + free(name); + return INSTANCE_ERRNO; + } + + newinst->uuid = inst->uuid; + newinst->path = path; + newinst->name = name; + + if (l2_state.instance_head && l2_state.instance_tail) { + l2_state.instance_tail->next = newinst; + newinst->prev = l2_state.instance_tail; + l2_state.instance_tail = newinst; + } else { + l2_state.instance_head = l2_state.instance_tail = newinst; + } + + return INSTANCE_SUCCESS; +} + +int l2_instance_del_instance(struct l2_instance *inst) +{ + if (inst->next) { + inst->next->prev = inst->prev; + } else { + l2_state.instance_tail = inst->prev; + } + + if (inst->prev) { + inst->prev->next = inst->next; + } else { + l2_state.instance_head = inst->next; + } + + return INSTANCE_SUCCESS; +} + +/* internal utilities */ + +int l2_instance__load_all_from_object(json_t *obj) +{ + const char *key; + json_t *val; + json_t *tempval; + int res; + + struct l2_instance inst; + + json_object_foreach(obj, key, val) { + if (!json_is_object(val)) { + return INSTANCE_EFORMAT; + } + + if (!l2_uuid_from_string(&inst.uuid, key)) { + return INSTANCE_EFORMAT; /* invalid UUID */ + } + + tempval = json_object_get(val, "name"); + if (!json_is_string(tempval)) { + return INSTANCE_EFORMAT; + } + + /* it's okay to discard const here because add_instance duplicates the string */ + inst.name = (char *)json_string_value(tempval); + + tempval = json_object_get(val, "path"); + if (!json_is_string(tempval)) { + return INSTANCE_EFORMAT; + } + + inst.path = (char *)json_string_value(tempval); + + if ((res = l2_instance_add_instance(&inst)) != INSTANCE_SUCCESS) { + return res; + } + } + + return INSTANCE_SUCCESS; +} + +json_t *l2_instance__save_all_to_object(void) +{ + json_t *obj = json_object(); + json_t *jinst; + if (!obj) return NULL; + + char uuidbuf[UUID_STRLEN + 1]; + + for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) { + l2_uuid_to_string(&inst->uuid, uuidbuf); + if (json_object_set_new(obj, uuidbuf, jinst = json_object()) < 0) { + goto save_err; /* jinst is decref'd anyway (undocumented) */ + } + + if (json_object_set_new(jinst, "name", json_string(inst->name)) < 0) { + goto save_err; + } + + if (json_object_set_new(jinst, "path", json_string(inst->path)) < 0) { + goto save_err; + } + } + + return obj; + +save_err: + json_decref(obj); + return NULL; +} |
