2024-02-15 00:17:20 +01:00
|
|
|
#include "sandbox.h"
|
|
|
|
|
2024-02-17 00:40:09 +01:00
|
|
|
#include "entry.h"
|
2024-02-18 00:28:42 +01:00
|
|
|
#include "backing.h"
|
2024-02-15 00:17:20 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
2024-02-15 19:42:22 +01:00
|
|
|
#include <stdlib.h>
|
2024-02-16 17:13:52 +01:00
|
|
|
#include <string.h>
|
2024-02-17 23:59:38 +01:00
|
|
|
#include <errno.h>
|
2024-02-17 15:15:40 +01:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <unistd.h>
|
2024-02-18 14:38:31 +01:00
|
|
|
#include <time.h>
|
2024-02-17 23:59:38 +01:00
|
|
|
|
|
|
|
Command COMMANDS[] = {
|
|
|
|
{CommandHelp, "help", "[command]", "Prints this help message.",
|
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandVersion, "version", NULL, "Prints the version of the program.",
|
|
|
|
"TODO: Add details."},
|
2024-02-18 00:07:44 +01:00
|
|
|
{},
|
|
|
|
{CommandAddEntry, "add-entry", "<entry id>", "Adds a new entry to the sandbox.",
|
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandRemoveEntry, "remove-entry", "<entry id>", "Removes an entry from the sandbox.",
|
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandListEntries, "list-entries", NULL, "Lists all the entries in the sandbox.",
|
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandClearEntries, "clear-entries", NULL, "Clears all the entries from the sandbox.",
|
|
|
|
"TODO: Add details."},
|
2024-02-18 14:05:04 +01:00
|
|
|
{},
|
|
|
|
{CommandAddDisk, "add-disk", "<entry id> [--root|-r <size>] [--backed|-b <backing id>]", "Adds a new disk to an entry.",
|
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandRemoveDisk, "remove-disk", "<entry id>", "Removes the disk from an entry.",
|
|
|
|
"TODO: Add details."},
|
2024-02-18 14:38:31 +01:00
|
|
|
{CommandResetDisk, "reset-disk", "<entry id> [--update|-u] [--backed|-b <backing id>]", "Resets the disk of an entry.",
|
2024-02-18 14:05:04 +01:00
|
|
|
"TODO: Add details."},
|
|
|
|
{CommandTrimDisk, "trim-disk", "<entry id>", "Trims the disk of an entry.",
|
|
|
|
"TODO: Add details."}};
|
2024-02-17 00:40:09 +01:00
|
|
|
|
2024-02-15 00:17:20 +01:00
|
|
|
int main(int argc, char* argv[]) {
|
2024-02-17 23:59:38 +01:00
|
|
|
struct passwd* pw = getpwnam(SANDBOX_USER);
|
|
|
|
if (pw == NULL) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Failed to get the 'sandbox' user (%s).", strerror(errno));
|
2024-02-17 15:15:40 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
// Check if the current user is root or the 'sandbox' user
|
|
|
|
if (getuid() != 0 && getuid() != pw->pw_uid) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "You must be root or the 'sandbox' user to use this program.");
|
2024-02-17 15:15:40 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
// Try and switch to the 'sandbox' user if we are root
|
2024-02-17 15:15:40 +01:00
|
|
|
if (geteuid() == 0) {
|
2024-02-17 23:59:38 +01:00
|
|
|
if (setregid(pw->pw_gid, pw->pw_gid) == -1) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Failed to set the real and effective group ID to the 'sandbox' user (%s).", strerror(errno));
|
2024-02-17 15:15:40 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
if (setreuid(pw->pw_uid, pw->pw_uid) == -1) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Failed to set the real and effective user ID to the 'sandbox' user (%s).", strerror(errno));
|
2024-02-17 15:15:40 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
// If there are no arguments, print the help message
|
|
|
|
if (argc == 1)
|
|
|
|
return CommandHelp(0, NULL);
|
2024-02-17 00:40:09 +01:00
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
const char* input = argv[1];
|
|
|
|
size_t input_length = strlen(input);
|
2024-02-17 00:40:09 +01:00
|
|
|
|
2024-02-18 02:06:49 +01:00
|
|
|
// Try and find the best matching command
|
2024-02-17 00:40:09 +01:00
|
|
|
const Command* command = NULL;
|
2024-02-17 23:59:38 +01:00
|
|
|
for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) {
|
2024-02-17 00:40:09 +01:00
|
|
|
if (COMMANDS[i].name == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (input_length > strlen(COMMANDS[i].name))
|
|
|
|
continue;
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
if (strncmp(input, COMMANDS[i].name, input_length) == 0) {
|
2024-02-18 02:06:49 +01:00
|
|
|
// If we have already found a matching command, then the input is ambiguous
|
2024-02-17 00:40:09 +01:00
|
|
|
if (command != NULL) {
|
2024-02-17 23:59:38 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Ambiguous command '%s'.", input);
|
2024-02-17 00:40:09 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
command = &COMMANDS[i];
|
|
|
|
}
|
2024-02-16 17:13:52 +01:00
|
|
|
}
|
2024-02-16 16:53:02 +01:00
|
|
|
|
2024-02-16 17:13:52 +01:00
|
|
|
if (command == NULL) {
|
2024-02-17 23:59:38 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Unknown command '%s'.", input);
|
2024-02-17 00:40:09 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-16 17:13:52 +01:00
|
|
|
}
|
2024-02-16 16:53:02 +01:00
|
|
|
|
2024-02-17 00:40:09 +01:00
|
|
|
return command->handler(argc - 2, argv + 2);
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
int CommandHelp(int argc, char* argv[]) {
|
2024-02-18 02:06:49 +01:00
|
|
|
// If there are no arguments, print the general help message
|
2024-02-17 00:40:09 +01:00
|
|
|
if (argc == 0) {
|
2024-02-17 23:59:38 +01:00
|
|
|
fprintf(stdout, "Usage: sandbox <command> [arguments] [options]\n");
|
|
|
|
fprintf(stdout, "\n");
|
2024-02-17 00:40:09 +01:00
|
|
|
fprintf(stdout, "Commands:\n");
|
2024-02-17 23:59:38 +01:00
|
|
|
for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) {
|
|
|
|
if (COMMANDS[i].name == NULL) {
|
|
|
|
fprintf(stdout, "\n");
|
2024-02-17 00:40:09 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-02-16 23:26:29 +01:00
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
fprintf(stdout, " %s", COMMANDS[i].name);
|
|
|
|
if (COMMANDS[i].arguments != NULL)
|
|
|
|
fprintf(stdout, " %s", COMMANDS[i].arguments);
|
|
|
|
fprintf(stdout, " - %s\n", COMMANDS[i].description);
|
2024-02-17 00:40:09 +01:00
|
|
|
}
|
2024-02-16 17:19:56 +01:00
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
fprintf(stdout, "\nFor more information, run 'sandbox help <command>'.\n");
|
2024-02-18 02:06:49 +01:00
|
|
|
} else if (argc == 1) { // If there is one argument, print the help message for the command
|
2024-02-17 23:59:38 +01:00
|
|
|
const char* input = argv[0];
|
2024-02-17 14:38:52 +01:00
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) {
|
|
|
|
if (COMMANDS[i].name == NULL)
|
|
|
|
continue;
|
2024-02-17 14:38:52 +01:00
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
if (strcmp(input, COMMANDS[i].name) == 0) {
|
|
|
|
fprintf(stdout, "Usage: sandbox %s", COMMANDS[i].name);
|
|
|
|
if (COMMANDS[i].arguments != NULL)
|
|
|
|
fprintf(stdout, " %s", COMMANDS[i].arguments);
|
2024-02-18 00:07:44 +01:00
|
|
|
fprintf(stdout, "\n %s\n\n %s\n", COMMANDS[i].description, COMMANDS[i].details);
|
2024-02-17 23:59:38 +01:00
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
2024-02-17 14:38:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Unknown command '%s'.", input);
|
2024-02-17 14:38:52 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 02:06:49 +01:00
|
|
|
} else { // If there are too many arguments, print an error message
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'help'.");
|
2024-02-17 15:15:40 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-17 12:00:17 +01:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
int CommandVersion(int argc, char* argv[]) {
|
2024-02-18 14:38:31 +01:00
|
|
|
if (argc > 0) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'version'.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-17 23:59:38 +01:00
|
|
|
fprintf(stdout, "Sandbox utility v%s\n", VERSION);
|
2024-02-17 12:00:17 +01:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
2024-02-18 00:07:44 +01:00
|
|
|
|
|
|
|
int CommandAddEntry(int argc, char* argv[]) {
|
|
|
|
if (argc < 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'add-entry'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (argc > 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'add-entry'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Create the entry
|
|
|
|
Status status = AddEntry(entry_id);
|
2024-02-18 00:28:42 +01:00
|
|
|
if (status != SUCCESS)
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 00:28:42 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully added entry '%s'.", entry_id);
|
2024-02-18 00:28:42 +01:00
|
|
|
return EXIT_SUCCESS;
|
2024-02-18 00:07:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int CommandRemoveEntry(int argc, char* argv[]) {
|
|
|
|
if (argc < 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'remove-entry'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (argc > 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'remove-entry'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Remove the entry
|
|
|
|
Status status = RemoveEntry(entry_id);
|
2024-02-18 00:28:42 +01:00
|
|
|
if (status != SUCCESS)
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 00:28:42 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully removed entry '%s'.", entry_id);
|
2024-02-18 00:28:42 +01:00
|
|
|
return EXIT_SUCCESS;
|
2024-02-18 00:07:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int CommandListEntries(int argc, char* argv[]) {
|
|
|
|
if (argc > 0) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'list-entries'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// List the entries
|
2024-02-18 00:07:44 +01:00
|
|
|
char** entries = NULL;
|
|
|
|
Status status = ListEntries(&entries);
|
|
|
|
if (status != SUCCESS)
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 00:07:44 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Calculate the maximum length of the entries
|
|
|
|
size_t max_length = 0;
|
|
|
|
for (size_t i = 0; entries[i] != NULL; i++) {
|
|
|
|
size_t length = strlen(entries[i]);
|
|
|
|
if (length > max_length)
|
|
|
|
max_length = length;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the entries
|
|
|
|
for (size_t i = 0; entries[i] != NULL; i++) {
|
|
|
|
bool has_disk;
|
|
|
|
status = DoesEntryDiskExist(entries[i], &has_disk);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
2024-02-18 00:07:44 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
if (has_disk)
|
|
|
|
fprintf(stdout, "%zu | %-*s | %s |\n", i, (int)max_length, entries[i], "Has disk");
|
|
|
|
else
|
|
|
|
fprintf(stdout, "%zu | %-*s | %s |\n", i, (int)max_length, entries[i], "No disk ");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the entries
|
2024-02-18 00:07:44 +01:00
|
|
|
for (size_t i = 0; entries[i] != NULL; i++)
|
|
|
|
free(entries[i]);
|
|
|
|
free(entries);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CommandClearEntries(int argc, char* argv[]) {
|
|
|
|
if (argc > 0) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'clear-entries'.");
|
2024-02-18 00:07:44 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Clear the entries
|
2024-02-18 00:28:42 +01:00
|
|
|
Status status = ClearEntries();
|
|
|
|
if (status != SUCCESS)
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 00:28:42 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully cleared all entries.");
|
2024-02-18 00:28:42 +01:00
|
|
|
return EXIT_SUCCESS;
|
2024-02-18 00:07:44 +01:00
|
|
|
}
|
2024-02-18 14:05:04 +01:00
|
|
|
|
|
|
|
int CommandAddDisk(int argc, char* argv[]) {
|
|
|
|
if (argc < 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'add-disk'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the options
|
2024-02-18 14:05:04 +01:00
|
|
|
bool root = false;
|
2024-02-18 14:38:31 +01:00
|
|
|
const char* size_str = NULL;
|
2024-02-18 14:05:04 +01:00
|
|
|
|
|
|
|
bool backed = false;
|
2024-02-18 14:38:31 +01:00
|
|
|
const char* backing_id = NULL;
|
2024-02-18 14:05:04 +01:00
|
|
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
if (strcmp(argv[i], "--root") == 0 || strcmp(argv[i], "-r") == 0) {
|
2024-02-18 14:38:31 +01:00
|
|
|
// Check if the option is duplicated
|
2024-02-18 14:05:04 +01:00
|
|
|
if (root) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Duplicate option '--root'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Check if the option is the last argument
|
|
|
|
if (i + 1 == argc) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Missing argument for option '--root <size>'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the size
|
|
|
|
size_str = argv[i + 1];
|
2024-02-18 14:05:04 +01:00
|
|
|
root = true;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Skip the next argument as it is the size
|
|
|
|
i++;
|
2024-02-18 14:05:04 +01:00
|
|
|
} else if (strcmp(argv[i], "--backed") == 0 || strcmp(argv[i], "-b") == 0) {
|
2024-02-18 14:38:31 +01:00
|
|
|
// Check if the option is duplicated
|
2024-02-18 14:05:04 +01:00
|
|
|
if (backed) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Duplicate option '--backed'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Check if the option is the last argument
|
|
|
|
if (i + 1 == argc) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Missing argument for option '--backed <backing id>'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the backing identifier
|
|
|
|
backing_id = argv[i + 1];
|
2024-02-18 14:05:04 +01:00
|
|
|
backed = true;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Skip the next argument as it is the backing identifier
|
|
|
|
i++;
|
2024-02-18 14:05:04 +01:00
|
|
|
} else {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Unknown option '%s'.", argv[i]);
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Don't allow both root and backed options
|
2024-02-18 14:05:04 +01:00
|
|
|
if (root && backed) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Cannot use both '--root' and '--backed' options.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (root) {
|
2024-02-18 14:38:31 +01:00
|
|
|
// Parse the size
|
|
|
|
uint64_t size;
|
|
|
|
Status status = ParseSize(size_str, &size);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
// Add the root disk
|
|
|
|
status = AddRootEntryDisk(entry_id, size);
|
2024-02-18 14:05:04 +01:00
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Format the size
|
|
|
|
char* size_fmt;
|
|
|
|
status = FormatSize(size, &size_fmt);
|
|
|
|
|
|
|
|
Log(LOG_LEVEL_INFO, "Successfully added root disk to entry '%s' of size %s.", entry_id, size_fmt);
|
|
|
|
|
|
|
|
free(size_fmt);
|
|
|
|
return EXIT_SUCCESS;
|
2024-02-18 14:05:04 +01:00
|
|
|
} else if (backed) {
|
2024-02-18 14:38:31 +01:00
|
|
|
// Check if the backing exists
|
|
|
|
Status status = AddBackedEntryDisk(entry_id, backing_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully added backed disk to entry '%s' with backing '%s'.", entry_id, backing_id);
|
|
|
|
return EXIT_SUCCESS;
|
2024-02-18 14:05:04 +01:00
|
|
|
} else {
|
2024-02-18 14:38:31 +01:00
|
|
|
// Get the latest backing to use as the default backing
|
|
|
|
char* backing_id;
|
|
|
|
Status status = GetLatestBacking(&backing_id);
|
|
|
|
if (status != SUCCESS) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Failed to get the latest backing to use as the default backing.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
2024-02-18 14:38:31 +01:00
|
|
|
}
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Add the backed disk
|
|
|
|
status = AddBackedEntryDisk(entry_id, backing_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
if (status != SUCCESS) {
|
2024-02-18 14:38:31 +01:00
|
|
|
free(backing_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully added backed disk to entry '%s' with backing '%s'.", entry_id, backing_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
free(backing_id);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
2024-02-18 14:05:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int CommandRemoveDisk(int argc, char* argv[]) {
|
|
|
|
if (argc < 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'remove-disk'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (argc > 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'remove-disk'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Remove the disk
|
|
|
|
Status status = RemoveEntryDisk(entry_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully removed disk from entry '%s'.", entry_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CommandResetDisk(int argc, char* argv[]) {
|
2024-02-18 14:43:38 +01:00
|
|
|
if (argc < 1) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'reset-disk'.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
|
|
|
|
|
|
|
// Extract the options
|
|
|
|
bool update = false;
|
|
|
|
bool backed = false;
|
|
|
|
const char* backing_id = NULL;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
if (strcmp(argv[i], "--update") == 0 || strcmp(argv[i], "-u") == 0) {
|
|
|
|
// Check if the option is duplicated
|
|
|
|
if (update) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Duplicate option '--update'.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
update = true;
|
|
|
|
} else if (strcmp(argv[i], "--backed") == 0 || strcmp(argv[i], "-b") == 0) {
|
|
|
|
// Check if the option is duplicated
|
|
|
|
if (backed) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Duplicate option '--backed'.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the option is the last argument
|
|
|
|
if (i + 1 == argc) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Missing argument for option '--backed <backing id>'.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the backing identifier
|
|
|
|
backing_id = argv[i + 1];
|
|
|
|
backed = true;
|
|
|
|
|
|
|
|
// Skip the next argument as it is the backing identifier
|
|
|
|
i++;
|
|
|
|
} else {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Unknown option '%s'.", argv[i]);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow both update and backed options
|
|
|
|
if (update && backed) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Cannot use both '--update' and '--backed' options.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (update) {
|
|
|
|
char* backing_id;
|
|
|
|
Status status = GetLatestBacking(&backing_id);
|
|
|
|
if (status != SUCCESS) {
|
|
|
|
Log(LOG_LEVEL_ERROR, "Failed to get the latest backing to use as the default backing.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the disk
|
|
|
|
status = ResetEntryDisk(entry_id, backing_id);
|
|
|
|
if (status != SUCCESS) {
|
|
|
|
free(backing_id);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Log(LOG_LEVEL_INFO, "Successfully reset disk from entry '%s' with backing '%s'.", entry_id, backing_id);
|
|
|
|
|
|
|
|
free(backing_id);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
} else if (backed) {
|
|
|
|
// Reset the disk with the specified backing
|
|
|
|
Status status = ResetEntryDisk(entry_id, backing_id);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
Log(LOG_LEVEL_INFO, "Successfully reset disk from entry '%s' with backing '%s'.", entry_id, backing_id);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
} else {
|
|
|
|
// Reset the disk
|
|
|
|
Status status = ResetEntryDisk(entry_id, NULL);
|
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
Log(LOG_LEVEL_INFO, "Successfully reset disk from entry '%s'.", entry_id);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
2024-02-18 14:05:04 +01:00
|
|
|
}
|
|
|
|
int CommandTrimDisk(int argc, char* argv[]) {
|
|
|
|
if (argc < 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'trim-disk'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (argc > 1) {
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'trim-disk'.");
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Extract the entry identifier
|
|
|
|
const char* entry_id = argv[0];
|
2024-02-18 14:05:04 +01:00
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
// Trim the disk
|
|
|
|
Status status = TrimEntryDisk(entry_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
if (status != SUCCESS)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
2024-02-18 14:38:31 +01:00
|
|
|
Log(LOG_LEVEL_INFO, "Successfully trimmed disk from entry '%s'.", entry_id);
|
2024-02-18 14:05:04 +01:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|