aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2023-12-26 22:33:51 -0600
committerLibravatar bigfoot547 <[email protected]>2023-12-26 22:33:51 -0600
commit7f4b7142b09205dc773a915e3fe3cb7954f6d041 (patch)
tree34fed74ba2f3715ce2a6a6922cfbd440882b2895 /src
parentimplement remaining commands (but badly) (diff)
refactor instances
Diffstat (limited to 'src')
-rw-r--r--src/cmd-instance.c286
-rw-r--r--src/command.c64
-rw-r--r--src/command.h42
-rw-r--r--src/instance.c36
-rw-r--r--src/instance.h9
5 files changed, 217 insertions, 220 deletions
diff --git a/src/cmd-instance.c b/src/cmd-instance.c
index 6982eb3..c81eb7c 100644
--- a/src/cmd-instance.c
+++ b/src/cmd-instance.c
@@ -15,9 +15,39 @@
#include <ftw.h>
#include <unistd.h>
+#define CMD_MSG_INSTANCE_LOAD_ERR "Error loading instances"
+#define CMD_MSG_INSTANCE_ADD_ERR "Error adding the instance"
+#define CMD_MSG_INSTANCE_SAVE_ERR "Error saving the instance"
+#define CMD_MSG_INSTANCE_DEL_ERR "Error removing the instance"
+#define CMD_MSG_INSTANCE_RENAME_ERR "Error renaming the instance"
+
+#define CMD_MSG_INSTANCE_INVALID_NAME "The instance name is invalid."
+#define CMD_MSG_INSTANCE_DUPLICATE "An instance named '%s' already exists."
+#define CMD_MSG_INSTANCE_DIR_CREATE_E "Error creating instance directory: %s"
+#define CMD_MSG_INSTANCE_DIR_CHECK_E "Error checking instance directory: %s"
+#define CMD_MSG_INSTANCE_DIR_DIRTY "The instance directory '%s' is not empty. If this is intentional, rerun the command with --force."
+
+#define CMD_MSG_INSTANCE_NAME_NOT_FOUND "An instance by the name '%s' could not be found."
+#define CMD_MSG_INSTANCE_UUID_NOT_FOUND "An instance by the UUID '%s' could not be found."
+
+#define CMD_MSG_INSTANCE_DELDIR_ERR(_msg) "Error deleting instance directory: " _msg
+
+#define CMD_INSTANCE_CHECK(_res, _v, _msg) do { \
+ switch (((_res) = (_v))) { \
+ case INSTANCE_SUCCESS: break; \
+ case INSTANCE_ERRNO: \
+ CMD_FATAL(_msg ": %s: %s", l2_instance_errormsg[(_res)], strerror(errno)); \
+ break; \
+ default: \
+ CMD_FATAL(_msg ": %s", l2_instance_errormsg[(_res)]); \
+ } \
+} while (0)
+
+void cmd_instance__check_name(const char *instname);
+
unsigned cmd_instance_add(struct l2_context_node *ctx, char **args)
{
- int res = l2_instance_load_all();
+ int res;
char *name = NULL;
char *path = NULL;
char *newpath = NULL;
@@ -30,78 +60,40 @@ unsigned cmd_instance_add(struct l2_context_node *ctx, char **args)
if (!strcmp(*cur, "--force")) {
flag_force = true;
} else {
- fprintf(stderr, "fatal: Unknown argument '%s'.\n", *cur);
- return CMD_RESULT_FAIL;
+ CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *cur);
}
}
- if (res != INSTANCE_SUCCESS) {
- if (res == INSTANCE_ERRNO) {
- fprintf(stderr, "fatal: Error loading instances: %s\n", strerror(errno));
- } else {
- fprintf(stderr, "fatal: Error loading instances (%d)\n", res);
- }
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_load_all(), CMD_MSG_INSTANCE_LOAD_ERR);
/* get the name and path (if it exists) */
- for (struct l2_context_node *cur = ctx; cur; cur = cur->next) {
- if (cur->node->type != CMD_NODE_TYPE_ARGUMENT) continue;
- if (!strcmp("name", cur->node->name)) {
- name = cur->value;
- } else if (!strcmp("location", cur->node->name)) {
- path = cur->value;
- }
- }
+ l2_cmd_collect_args(ctx, 2, "name", &name, "#location", &path);
/* make sure the name and path make sense (path should be an absolute path, name shouldn't be empty) */
- if (!name || !*name) {
- fputs("fatal: The specified name is invalid\n", stderr);
- return CMD_RESULT_FAIL;
- }
-
- for (char *cur = name; *cur; ++cur) {
- if (*cur < ' ') {
- fputs("fatal: The specified name contains invalid characters\n", stderr);
- return CMD_RESULT_FAIL;
- }
- }
+ cmd_instance__check_name(name);
/* make sure there is not a profile with that name already */
- for (struct l2_instance *cur = l2_state.instance_head; cur; cur = cur->next) {
- if (!strcmp(cur->name, name)) {
- fprintf(stderr, "fatal: An instance by the name '%s' already exists.\n", cur->name);
- return CMD_RESULT_FAIL;
- }
+ if (l2_instance_find_by_name(name)) {
+ CMD_FATAL(CMD_MSG_INSTANCE_DUPLICATE, name);
}
/* also find an unused UUID through rejection sampling */
- bool found;
- do {
- found = false;
+ while (true) {
l2_uuid_random(&uuid);
- for (struct l2_instance *cur = l2_state.instance_head; cur; cur = cur->next) {
- if (!l2_uuid_compare(&cur->uuid, &uuid)) {
- found = true;
- break;
- }
- }
- } while (found);
+ if (!l2_instance_find_by_uuid(&uuid)) break;
+ }
/* create the directory at "path" (if it isn't empty, complain) */
if (path) {
newpath = realpath(path, NULL);
if (!newpath) {
- fprintf(stderr, "fatal: Failed to canonicalize specified path: %s\n", strerror(errno));
- return CMD_RESULT_FAIL;
+ CMD_FATAL0(CMD_MSG_ALLOCATION_FAILED);
}
} else if (!path) {
newpath = strdup(l2_state.paths.data);
if (!newpath) {
newpath_append_fail:
- free(newpath);
- fprintf(stderr, "fatal: Allocation failed: %s\n", strerror(errno));
- return CMD_RESULT_FAIL;
+ CMD_FATAL0(CMD_MSG_ALLOCATION_FAILED);
}
newpath = l2_launcher_strapp(newpath, "/instances/");
@@ -116,38 +108,32 @@ unsigned cmd_instance_add(struct l2_context_node *ctx, char **args)
/* TODO: now create the directory for realsies */
if (l2_launcher_mkdir_parents(path) < 0) {
- fprintf(stderr, "fatal: Could not create instance directory: %s\n", strerror(errno));
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL(CMD_MSG_INSTANCE_DIR_CREATE_E, strerror(errno));
}
if (!flag_force) {
dir = opendir(path);
if (!dir) {
- fprintf(stderr, "fatal: Could not check instance directory: %s\n", strerror(errno));
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL(CMD_MSG_INSTANCE_DIR_CHECK_E, strerror(errno));
}
struct dirent *ent;
- errno = 0;
+ errno = 0; /* readdir can return NULL on success */
while ((ent = readdir(dir))) {
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) {
- fprintf(stderr, "fatal: Instance directory '%s' is not empty. If this is intentional, rerun the command with --force.\n", path);
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL(CMD_MSG_INSTANCE_DIR_DIRTY, path);
}
- }
- closedir(dir);
- dir = NULL;
+ errno = 0;
+ }
if (errno) {
- fprintf(stderr, "fatal: Error scanning instance directory: %s\n", strerror(errno));
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL(CMD_MSG_INSTANCE_DIR_CHECK_E, strerror(errno));
}
- }
+
+ closedir(dir);
+ dir = NULL;
+ }
/* add the instance */
@@ -157,24 +143,14 @@ unsigned cmd_instance_add(struct l2_context_node *ctx, char **args)
inst.name = name;
inst.path = path;
- if ((res = l2_instance_add_instance(&inst)) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to add instance (%d)\n", res);
- res = CMD_RESULT_FAIL;
- goto cleanup;
- }
-
- if ((res = l2_instance_save_all()) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to add instance (%d)\n", res);
- res = CMD_RESULT_FAIL;
- goto cleanup;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_add_instance(&inst), CMD_MSG_INSTANCE_ADD_ERR);
- res = CMD_RESULT_SUCCESS;
+ CMD_INSTANCE_CHECK(res, l2_instance_save_all(), CMD_MSG_INSTANCE_SAVE_ERR);
-cleanup:
if (dir) closedir(dir);
free(newpath);
- return res;
+
+ return CMD_RESULT_SUCCESS;
}
int cmd__delete_with_reckless_abandon(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
@@ -208,6 +184,7 @@ unsigned cmd_instance_remove(struct l2_context_node *ctx, char **args)
uuid_t instid = UUID_NULL_INIT;
struct l2_instance *to_remove = NULL;
char *removepath = NULL;
+ char instid_pretty[UUID_STRLEN + 1];
for (char **cur = args; *cur; ++cur) {
if (!strcmp("--delete", *cur)) {
@@ -215,121 +192,73 @@ unsigned cmd_instance_remove(struct l2_context_node *ctx, char **args)
} else if (!strcmp("--id", *cur)) {
flag_byid = true;
} else {
- fprintf(stderr, "fatal: Unknown argument '%s'\n", *cur);
- return CMD_RESULT_FAIL;
- }
- }
-
- for (struct l2_context_node *cur = ctx; cur; cur = cur->next) {
- if (cur->node->type != CMD_NODE_TYPE_ARGUMENT) continue;
-
- if (!strcmp("name", cur->node->name)) {
- name = cur->value;
+ CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *cur);
}
}
- if (!name) {
- fputs("fatal: Name not specified\n", stderr);
- return CMD_RESULT_FAIL;
- }
+ l2_cmd_collect_args(ctx, 1, "name", &name);
if (flag_byid && !l2_uuid_from_string(&instid, name)) {
- fprintf(stderr, "Failed to parse instance UUID '%s'.\n", name);
- return CMD_RESULT_FAIL;
+ CMD_FATAL(CMD_MSG_INVALID_UUID, name);
}
- res = l2_instance_load_all();
- if (res != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to load instances (%d).\n", res);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_load_all(), CMD_MSG_INSTANCE_LOAD_ERR);
/* find the thing */
if (flag_byid) {
- for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) {
- if (!l2_uuid_compare(&inst->uuid, &instid)) {
- to_remove = inst;
- break;
- }
+ to_remove = l2_instance_find_by_uuid(&instid);
+ if (!to_remove) {
+ l2_uuid_to_string(&instid, instid_pretty);
+ CMD_FATAL(CMD_MSG_INSTANCE_UUID_NOT_FOUND, instid_pretty);
}
} else {
- for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) {
- if (!strcmp(inst->name, name)) {
- to_remove = inst;
- break;
- }
- }
- }
-
- if (!to_remove) {
- fputs("fatal: Instance not found.\n", stderr);
- return CMD_RESULT_FAIL;
+ to_remove = l2_instance_find_by_name(name);
+ if (!to_remove) CMD_FATAL(CMD_MSG_INSTANCE_NAME_NOT_FOUND, name);
}
if (flag_remove) {
removepath = strdup(to_remove->path);
if (!removepath) {
- fputs("fatal: Failed to create path.\n", stderr);
- return CMD_RESULT_FAIL;
+ CMD_FATAL0(CMD_MSG_ALLOCATION_FAILED);
}
}
/* remove the thing */
- if ((res = l2_instance_del_instance(to_remove)) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to remove instance (%d).\n", res);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_del_instance(to_remove), CMD_MSG_INSTANCE_DEL_ERR);
to_remove = NULL; /* del_instance frees the instance */
- if ((res = l2_instance_save_all()) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to save instances (%d).\n", res);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_save_all(), CMD_MSG_INSTANCE_SAVE_ERR);
/* delete the thing if it is necessary */
if (flag_remove) {
res = nftw(removepath, &cmd__delete_with_reckless_abandon, 128, FTW_DEPTH | FTW_PHYS);
switch (res) {
case -2:
- fputs("Unreadable file/folder encountered while walking file tree.\n", stderr);
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL0(CMD_MSG_INSTANCE_DELDIR_ERR("unreadable file/folder encountered"));
case -1:
- fputs("Error walking file tree.\n", stderr);
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL0(CMD_MSG_INSTANCE_DELDIR_ERR("error walking file tree"));
case 0:
break;
default:
- fprintf(stderr, "Error removing a file: %s\n", strerror(res));
- res = CMD_RESULT_FAIL;
- goto cleanup;
+ CMD_FATAL(CMD_MSG_INSTANCE_DELDIR_ERR("error removing a file: %s"), strerror(res));
}
}
- res = CMD_RESULT_SUCCESS;
-
-cleanup:
if (removepath) free(removepath);
- return res;
+ return CMD_RESULT_SUCCESS;
}
unsigned cmd_instance_list(struct l2_context_node *ctx, char **args)
{
L2_UNUSED(ctx);
+ int res;
if (*args) {
- fprintf(stderr, "fatal: Unknown argument '%s'.\n", *args);
- return CMD_RESULT_FAIL;
+ CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args);
}
- int res = l2_instance_load_all();
-
- if (res != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to load instances. (%d)\n", res);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_load_all(), CMD_MSG_INSTANCE_LOAD_ERR);
if (l2_state.instance_head) {
char idstr[UUID_STRLEN + 1];
@@ -352,53 +281,40 @@ unsigned cmd_instance_rename(struct l2_context_node *ctx, char **args)
struct l2_instance *to_rename = NULL;
if (*args) {
- fprintf(stderr, "fatal: Unknown argument '%s'.\n", *args);
- return CMD_RESULT_FAIL;
+ CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *args);
}
- res = l2_instance_load_all();
+ CMD_INSTANCE_CHECK(res, l2_instance_load_all(), CMD_MSG_INSTANCE_LOAD_ERR);
- if (res != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to load instances. (%d)\n", res);
- return CMD_RESULT_FAIL;
- }
+ l2_cmd_collect_args(ctx, 2, "oldname", &oldname, "newname", &newname);
- for (struct l2_context_node *cur = ctx; cur; cur = cur->next) {
- if (!strcmp("oldname", cur->node->name)) {
- oldname = cur->value;
- } else if (!strcmp("newname", cur->node->name)) {
- newname = cur->value;
- }
- }
+ cmd_instance__check_name(newname);
- if (!(oldname && newname)) { /* TODO: sanitize newname like in "instance add" */
- fputs("fatal: Invalid usage.\n", stderr);
- return CMD_RESULT_FAIL;
+ if (l2_instance_find_by_name(newname)) {
+ CMD_FATAL(CMD_MSG_INSTANCE_DUPLICATE, newname);
}
- for (struct l2_instance *cur = l2_state.instance_head; cur; cur = cur->next) {
- if (!strcmp(cur->name, oldname)) {
- to_rename = cur;
- } else if (!strcmp(cur->name, newname)) {
- fprintf(stderr, "fatal: An instance by the name '%s' already exists.\n", newname);
- return CMD_RESULT_FAIL;
- }
+ if (!(to_rename = l2_instance_find_by_name(oldname))) {
+ CMD_FATAL(CMD_MSG_INSTANCE_NAME_NOT_FOUND, oldname);
}
- if (!to_rename) {
- fprintf(stderr, "fatal: No instance found by the name '%s'.\n", oldname);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_rename_instance(to_rename, newname), CMD_MSG_INSTANCE_RENAME_ERR);
- if ((res = l2_instance_rename_instance(to_rename, newname)) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to rename the instance. (%d)\n", res);
- return CMD_RESULT_FAIL;
- }
+ CMD_INSTANCE_CHECK(res, l2_instance_save_all(), CMD_MSG_INSTANCE_SAVE_ERR);
+
+ return CMD_RESULT_SUCCESS;
+}
- if ((res = l2_instance_save_all()) != INSTANCE_SUCCESS) {
- fprintf(stderr, "fatal: Failed to save instances. (%d)\n", res);
- return CMD_RESULT_FAIL;
+void cmd_instance__check_name(const char *instname)
+{
+ if (!*instname) goto failure;
+
+ for (const char *cur = instname; *cur; ++cur) {
+ if (*cur <= ' ') goto failure; /* not like you couldn't just use a unicode NBSP or something */
}
- return CMD_RESULT_SUCCESS;
+ return;
+
+failure:
+ CMD_FATAL0(CMD_MSG_INSTANCE_INVALID_NAME);
}
diff --git a/src/command.c b/src/command.c
index 6be2fb5..2f91db0 100644
--- a/src/command.c
+++ b/src/command.c
@@ -199,41 +199,45 @@ void l2_cmd_free_ctx(struct l2_context_node *ctx)
} while (ctx);
}
-#if 0
-#include "uuid/uuid.h"
-#include <inttypes.h>
-
-int main(int argc, char **argv)
+void l2_cmd_collect_args(struct l2_context_node *ctx, unsigned argc, ...)
{
- char **argvcur = argv + 1;
-
- if (!*argvcur) {
- printf("done\n");
- return 1;
+ va_list ap;
+ if (argc == 0) return;
+
+ struct tag_cmd_arg_t {
+ const char *name;
+ char **target;
+ bool optional;
+ } args[argc]; /* ooooo c99 VLA this is exciting */
+
+ va_start(ap, argc);
+
+ for (unsigned i = 0; i < argc; ++i) {
+ args[i].name = va_arg(ap, const char *);
+ args[i].target = va_arg(ap, char **);
+ if (*args[i].name == '#') {
+ ++args[i].name;
+ args[i].optional = true;
+ } else {
+ args[i].optional = false;
+ }
}
- ((void)argc);
-
- struct l2_context_node *cur;
- struct l2_parseinfo parseinfo;
- memset(&parseinfo, 0, sizeof(struct l2_parseinfo));
-
- unsigned res = l2_cmd_parse_command(argv + 1, &parseinfo);
-
- printf("%p %s\n", (void *)parseinfo.ctx, parseinfo.argv ? *parseinfo.argv : "(null)");
+ va_end(ap);
- if (res == CMD_PARSE_SUCCESS) {
- cur = parseinfo.ctx;
- while (cur) {
- printf("%s\n", cur->value);
- cur = cur->next;
+ for (struct l2_context_node *cur = ctx; cur; cur = cur->next) {
+ if (cur->node->type != CMD_NODE_TYPE_ARGUMENT) continue;
+ for (unsigned i = 0; i < argc; ++i) {
+ if (!strcmp(cur->node->name, args[i].name)) {
+ *args[i].target = cur->value;
+ args[i].optional = true;
+ }
}
-
- printf("command returned: %u\n", (parseinfo.proc)(parseinfo.ctx, parseinfo.argv));
-
- l2_cmd_free_ctx(parseinfo.ctx);
}
- return 0;
+ for (unsigned i = 0; i < argc; ++i) {
+ if (!args[i].optional) {
+ CMD_FATAL(CMD_MSG_REQ_ARG_UNSPECIFIED, args[i].name);
+ }
+ }
}
-#endif
diff --git a/src/command.h b/src/command.h
index 469422c..7709292 100644
--- a/src/command.h
+++ b/src/command.h
@@ -3,6 +3,11 @@
#include <stddef.h>
+/* for CMD_ macros */
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
enum {
CMD_NODE_TYPE_NULL,
CMD_NODE_TYPE_LITERAL,
@@ -32,6 +37,29 @@ enum {
CMD_PARSE_EUSAGE /* function was called with NULL arguments */
};
+#define CMD_FATAL_(_op) do { \
+ _op; \
+ exit(EXIT_FAILURE); \
+} while (0)
+
+#define CMD_MSG(_l, _s, ...) fprintf(stderr, _l ": " _s "\n", __VA_ARGS__)
+#define CMD_MSG0(_l, _s) fputs(_l ": " _s "\n", stderr);
+
+#define CMD_FATAL(_s, ...) CMD_FATAL_(CMD_MSG("fatal", _s, __VA_ARGS__))
+#define CMD_FATAL0(_s) CMD_FATAL_(CMD_MSG0("fatal", _s))
+
+#define CMD_ERROR(_s, ...) CMD_MSG("error", _s, __VA_ARGS__)
+#define CMD_ERROR0(_s) CMD_MSG0("error", _s)
+
+#define CMD_WARN(_s, ...) CMD_MSG("warn", _s, __VA_ARGS__)
+#define CMD_WARN0(_s) CMD_MSG0("warn", _s)
+
+#define CMD_MSG_UNKNOWN_ARGUMENT "Unknown argument '%s'."
+#define CMD_MSG_REQ_ARG_UNSPECIFIED "Required argument '%s' not specified."
+#define CMD_MSG_INVALID_UUID "Invalid UUID '%s'."
+
+#define CMD_MSG_ALLOCATION_FAILED "Allocation failed."
+
struct l2_command_node;
struct l2_context_node {
@@ -74,4 +102,18 @@ struct l2_parseinfo {
unsigned l2_cmd_parse_command(char **argv, struct l2_parseinfo *parseinfo);
void l2_cmd_free_ctx(struct l2_context_node *ctx);
+/* DESCRIPTION:
+ * This function is for unpacking a bunch of arguments from a parsed command into
+ * string variables.
+ *
+ * HOW TO USE:
+ * Pass your command context followed by your arguments (const char *name, char **pvalue).
+ * Prefix the name with "#" if it is optional.
+ *
+ * This function will exit if a required value was not present.
+ *
+ * Example: l2_cmd_collect_args(ctx, 2, "name", &name, "#location", &path);
+ */
+void l2_cmd_collect_args(struct l2_context_node *ctx, unsigned argc, ...);
+
#endif /* include guard */
diff --git a/src/instance.c b/src/instance.c
index ca80a45..8d62e1e 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -11,6 +11,14 @@
#include <errno.h>
+const char *const l2_instance_errormsg[] = {
+ "Success",
+ "OS error",
+ "JSON error",
+ "Malformed instance file",
+ NULL
+};
+
int l2_instance__load_all_from_object(json_t *obj);
json_t *l2_instance__save_all_to_object(void);
@@ -116,8 +124,8 @@ int l2_instance_del_instance(struct l2_instance *inst)
l2_state.instance_head = inst->next;
}
- free((char *)inst->name); /* okay to cast away const because any instance in the list will be allocated with strdup */
- free((char *)inst->path);
+ free(inst->name); /* okay to cast away const because any instance in the list will be allocated with strdup */
+ free(inst->path);
free(inst);
return INSTANCE_SUCCESS;
@@ -128,11 +136,33 @@ int l2_instance_rename_instance(struct l2_instance *inst, const char *newname)
char *nn = strdup(newname);
if (!nn) return INSTANCE_ERRNO;
- free((char *)inst->name);
+ free(inst->name);
inst->name = nn;
return INSTANCE_SUCCESS;
}
+struct l2_instance *l2_instance_find_by_uuid(const uuid_t *id)
+{
+ for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) {
+ if (!memcmp(id, &inst->uuid, sizeof(uuid_t))) {
+ return inst;
+ }
+ }
+
+ return NULL;
+}
+
+struct l2_instance *l2_instance_find_by_name(const char *name)
+{
+ for (struct l2_instance *inst = l2_state.instance_head; inst; inst = inst->next) {
+ if (!strcmp(inst->name, name)) {
+ return inst;
+ }
+ }
+
+ return NULL;
+}
+
/* internal utilities */
int l2_instance__load_all_from_object(json_t *obj)
diff --git a/src/instance.h b/src/instance.h
index 1e60df8..bcded1c 100644
--- a/src/instance.h
+++ b/src/instance.h
@@ -5,8 +5,8 @@
struct l2_instance {
uuid_t uuid;
- const char *name;
- const char *path;
+ char *name;
+ char *path;
struct l2_instance *next;
struct l2_instance *prev;
@@ -19,6 +19,8 @@ enum {
INSTANCE_EFORMAT /* instance file is malformed */
};
+extern const char *const l2_instance_errormsg[];
+
/* load all instances (must be called after initialization) */
int l2_instance_load_all(void);
@@ -28,4 +30,7 @@ int l2_instance_add_instance(const struct l2_instance *inst);
int l2_instance_del_instance(struct l2_instance *inst);
int l2_instance_rename_instance(struct l2_instance *inst, const char *newname);
+struct l2_instance *l2_instance_find_by_uuid(const uuid_t *id);
+struct l2_instance *l2_instance_find_by_name(const char *name);
+
#endif /* include guard */