aboutsummaryrefslogtreecommitdiffstats
path: root/src/cmd-instance.c
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/cmd-instance.c
parentimplement remaining commands (but badly) (diff)
refactor instances
Diffstat (limited to 'src/cmd-instance.c')
-rw-r--r--src/cmd-instance.c286
1 files changed, 101 insertions, 185 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);
}