Added commands for managing disks
This commit is contained in:
parent
a149a838d1
commit
3e08d6a438
117
src/backing.c
117
src/backing.c
@ -49,7 +49,7 @@ Status GetBackingPoolPath(char** _backing_pool_path) {
|
|||||||
return Format(_backing_pool_path, "/var/lib/sandbox/backings");
|
return Format(_backing_pool_path, "/var/lib/sandbox/backings");
|
||||||
}
|
}
|
||||||
|
|
||||||
Status GetBackingDiskPath(const char* backing_identifier, char** _backing_path) {
|
Status GetBackingPath(const char* backing_identifier, char** _backing_path) {
|
||||||
// Check that the identifier is valid, as it will be used in a path
|
// Check that the identifier is valid, as it will be used in a path
|
||||||
if (!IsBackingIdentifierValid(backing_identifier)) {
|
if (!IsBackingIdentifierValid(backing_identifier)) {
|
||||||
Log(LOG_LEVEL_ERROR, "Invalid backing identifier '%s'.", backing_identifier);
|
Log(LOG_LEVEL_ERROR, "Invalid backing identifier '%s'.", backing_identifier);
|
||||||
@ -72,7 +72,7 @@ Status GetBackingDiskPath(const char* backing_identifier, char** _backing_path)
|
|||||||
Status DoesBackingExist(const char* backing_identifier, bool* _result) {
|
Status DoesBackingExist(const char* backing_identifier, bool* _result) {
|
||||||
// Get the backing path
|
// Get the backing path
|
||||||
char* backing_path = NULL;
|
char* backing_path = NULL;
|
||||||
Status status = GetBackingDiskPath(backing_identifier, &backing_path);
|
Status status = GetBackingPath(backing_identifier, &backing_path);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -83,3 +83,116 @@ Status DoesBackingExist(const char* backing_identifier, bool* _result) {
|
|||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status ListBackings(char*** _backings) {
|
||||||
|
*_backings = NULL;
|
||||||
|
|
||||||
|
// Open the backing pool directory
|
||||||
|
char* backing_pool_path = NULL;
|
||||||
|
Status status = GetBackingPoolPath(&backing_pool_path);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
DIR* dir = opendir(backing_pool_path);
|
||||||
|
if (dir == NULL) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to open the backing pool directory %s (%s).", backing_pool_path, strerror(errno));
|
||||||
|
free(backing_pool_path);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
free(backing_pool_path);
|
||||||
|
|
||||||
|
// Allocate memory for at least one backing (the NULL terminator)
|
||||||
|
*_backings = malloc(sizeof(char*));
|
||||||
|
if (*_backings == NULL) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to allocate memory for the backings list (%s).", strerror(errno));
|
||||||
|
closedir(dir);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
(*_backings)[0] = NULL;
|
||||||
|
|
||||||
|
// Read the files in the backing pool directory
|
||||||
|
size_t count = 0;
|
||||||
|
struct dirent* file;
|
||||||
|
while ((file = readdir(dir)) != NULL) {
|
||||||
|
if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check if the backing exists (this checks for validity)
|
||||||
|
bool exists;
|
||||||
|
Status status = DoesBackingExist(file->d_name, &exists);
|
||||||
|
if (status != SUCCESS || !exists)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Allocate memory for the new backing list
|
||||||
|
char** new_backings = realloc(*_backings, (count + 2) * sizeof(char*)); // +2 for the new entry and the NULL terminator
|
||||||
|
if (new_backings == NULL) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to reallocate memory for the backing list (%s).", strerror(errno));
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
free((*_backings)[i]);
|
||||||
|
free(*_backings);
|
||||||
|
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
*_backings = new_backings;
|
||||||
|
|
||||||
|
// Duplicate the file name and add it to the list
|
||||||
|
(*_backings)[count] = strdup(file->d_name);
|
||||||
|
if ((*_backings)[count] == NULL) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to duplicate the backing name (%s).", strerror(errno));
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
free((*_backings)[i]);
|
||||||
|
free(*_backings);
|
||||||
|
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the NULL terminator
|
||||||
|
(*_backings)[count + 1] = NULL;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status GetLatestBacking(char** _backing_identifier) {
|
||||||
|
// List the backings
|
||||||
|
char** backings = NULL;
|
||||||
|
Status status = ListBackings(&backings);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Find the latest backing
|
||||||
|
int latest_identifier_index = -1;
|
||||||
|
int latest_index = -1;
|
||||||
|
for (int i = 0; backings[i] != NULL; i++) {
|
||||||
|
int index = GetBackingIndex(backings[i]);
|
||||||
|
if (index > latest_index) {
|
||||||
|
latest_identifier_index = i;
|
||||||
|
latest_index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the latest backing
|
||||||
|
if (latest_identifier_index == -1) {
|
||||||
|
*_backing_identifier = NULL;
|
||||||
|
} else {
|
||||||
|
*_backing_identifier = strdup(backings[latest_identifier_index]);
|
||||||
|
if (*_backing_identifier == NULL) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to duplicate the backing identifier (%s).", strerror(errno));
|
||||||
|
status = FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the backings list
|
||||||
|
for (int i = 0; backings[i] != NULL; i++)
|
||||||
|
free(backings[i]);
|
||||||
|
free(backings);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ bool IsBackingIdentifierValid(const char* backing_identifier);
|
|||||||
int GetBackingIndex(const char* backing_identifier);
|
int GetBackingIndex(const char* backing_identifier);
|
||||||
|
|
||||||
Status GetBackingPoolPath(char** _backing_pool_path);
|
Status GetBackingPoolPath(char** _backing_pool_path);
|
||||||
Status GetBackingDiskPath(const char* backing_identifier, char** _backing_path);
|
Status GetBackingPath(const char* backing_identifier, char** _backing_path);
|
||||||
|
|
||||||
Status DoesBackingExist(const char* backing_identifier, bool* _result);
|
Status DoesBackingExist(const char* backing_identifier, bool* _result);
|
||||||
|
|
||||||
|
@ -103,11 +103,11 @@ Status TrimDisk(const char* path) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "create", "-f", "qcow2", "-F", "qcow2", "-O", "qcow2", "-o", backing_file_opt, tmp_path, NULL);
|
status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "convert", "-f", "qcow2", "-F", "qcow2", "-O", "qcow2", "-o", backing_file_opt, path, tmp_path, NULL);
|
||||||
|
|
||||||
free(backing_file_opt);
|
free(backing_file_opt);
|
||||||
} else
|
} else
|
||||||
status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "create", "-f", "qcow2", "-O", "qcow2", tmp_path, NULL);
|
status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "convert", "-f", "qcow2", "-O", "qcow2", path, tmp_path, NULL);
|
||||||
|
|
||||||
FreeDiskInfo(&info);
|
FreeDiskInfo(&info);
|
||||||
|
|
||||||
|
56
src/entry.c
56
src/entry.c
@ -193,23 +193,23 @@ Status ListEntries(char*** _entries) {
|
|||||||
}
|
}
|
||||||
(*_entries)[0] = NULL;
|
(*_entries)[0] = NULL;
|
||||||
|
|
||||||
// Read the entries from the directory
|
// Read the files in the entry pool directory
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
struct dirent* entry;
|
struct dirent* file;
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
while ((file = readdir(dir)) != NULL) {
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if the entry exists (this checks for validity)
|
// Check if the entry exists (this checks for validity)
|
||||||
bool exists;
|
bool exists;
|
||||||
Status status = DoesEntryExist(entry->d_name, &exists);
|
Status status = DoesEntryExist(file->d_name, &exists);
|
||||||
if (status != SUCCESS || !exists)
|
if (status != SUCCESS || !exists)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Allocate memory for the new entry list
|
// Allocate memory for the new entry list
|
||||||
char** new_entries = realloc(*_entries, (count + 2) * sizeof(char*)); // +2 for the new entry and the NULL terminator
|
char** new_entries = realloc(*_entries, (count + 2) * sizeof(char*)); // +2 for the new entry and the NULL terminator
|
||||||
if (new_entries == NULL) {
|
if (new_entries == NULL) {
|
||||||
Log(LOG_LEVEL_ERROR, "Failed to reallocate memory for the entries list (%s).", strerror(errno));
|
Log(LOG_LEVEL_ERROR, "Failed to reallocate memory for the entry list (%s).", strerror(errno));
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++)
|
||||||
@ -221,7 +221,7 @@ Status ListEntries(char*** _entries) {
|
|||||||
*_entries = new_entries;
|
*_entries = new_entries;
|
||||||
|
|
||||||
// Duplicate the entry name and add it to the list
|
// Duplicate the entry name and add it to the list
|
||||||
(*_entries)[count] = strdup(entry->d_name);
|
(*_entries)[count] = strdup(file->d_name);
|
||||||
if ((*_entries)[count] == NULL) {
|
if ((*_entries)[count] == NULL) {
|
||||||
Log(LOG_LEVEL_ERROR, "Failed to duplicate the entry name (%s).", strerror(errno));
|
Log(LOG_LEVEL_ERROR, "Failed to duplicate the entry name (%s).", strerror(errno));
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@ -266,9 +266,19 @@ Status ClearEntries() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status AddRootEntryDisk(const char* entry_identifier, uint64_t disk_size) {
|
Status AddRootEntryDisk(const char* entry_identifier, uint64_t disk_size) {
|
||||||
// Check if the disk already exists
|
// Check that the entry exists
|
||||||
bool exists;
|
bool exists;
|
||||||
Status status = DoesEntryDiskExist(entry_identifier, &exists);
|
Status status = DoesEntryExist(entry_identifier, &exists);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "The entry '%s' does not exist.", entry_identifier);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the disk already exists
|
||||||
|
status = DoesEntryDiskExist(entry_identifier, &exists);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -291,9 +301,29 @@ Status AddRootEntryDisk(const char* entry_identifier, uint64_t disk_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status AddBackedEntryDisk(const char* entry_identifier, const char* backing_identifier) {
|
Status AddBackedEntryDisk(const char* entry_identifier, const char* backing_identifier) {
|
||||||
// Check if the disk already exists
|
// Check that the entry exists
|
||||||
bool exists;
|
bool exists;
|
||||||
Status status = DoesEntryDiskExist(entry_identifier, &exists);
|
Status status = DoesEntryExist(entry_identifier, &exists);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "The entry '%s' does not exist.", entry_identifier);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the backing exists
|
||||||
|
status = DoesBackingExist(backing_identifier, &exists);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "The backing '%s' does not exist.", backing_identifier);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the disk already exists
|
||||||
|
status = DoesEntryDiskExist(entry_identifier, &exists);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -304,7 +334,7 @@ Status AddBackedEntryDisk(const char* entry_identifier, const char* backing_iden
|
|||||||
|
|
||||||
// Get the backing disk path
|
// Get the backing disk path
|
||||||
char* backing_disk_path = NULL;
|
char* backing_disk_path = NULL;
|
||||||
status = GetBackingDiskPath(backing_identifier, &backing_disk_path);
|
status = GetBackingPath(backing_identifier, &backing_disk_path);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -368,7 +398,7 @@ Status ResetEntryDisk(const char* entry_identifier, const char* backing_identifi
|
|||||||
// Get the backing disk path
|
// Get the backing disk path
|
||||||
char* backing_disk_path = NULL;
|
char* backing_disk_path = NULL;
|
||||||
if (backing_identifier != NULL) {
|
if (backing_identifier != NULL) {
|
||||||
status = GetBackingDiskPath(backing_identifier, &backing_disk_path);
|
status = GetBackingPath(backing_identifier, &backing_disk_path);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
178
src/sandbox.c
178
src/sandbox.c
@ -24,7 +24,15 @@ Command COMMANDS[] = {
|
|||||||
"TODO: Add details."},
|
"TODO: Add details."},
|
||||||
{CommandClearEntries, "clear-entries", NULL, "Clears all the entries from the sandbox.",
|
{CommandClearEntries, "clear-entries", NULL, "Clears all the entries from the sandbox.",
|
||||||
"TODO: Add details."},
|
"TODO: Add details."},
|
||||||
};
|
{},
|
||||||
|
{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."},
|
||||||
|
{CommandResetDisk, "reset-disk", "<entry id> [--update|-u] [--backing|-b <backing id>]", "Resets the disk of an entry.",
|
||||||
|
"TODO: Add details."},
|
||||||
|
{CommandTrimDisk, "trim-disk", "<entry id>", "Trims the disk of an entry.",
|
||||||
|
"TODO: Add details."}};
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
struct passwd* pw = getpwnam(SANDBOX_USER);
|
struct passwd* pw = getpwnam(SANDBOX_USER);
|
||||||
@ -149,11 +157,13 @@ int CommandAddEntry(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status = AddEntry(argv[0]);
|
char* entry_identifier = argv[0];
|
||||||
if (status != SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
Log(LOG_LEVEL_INFO, "Added entry '%s'.", argv[0]);
|
Status status = AddEntry(entry_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Added entry '%s'.", entry_identifier);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,11 +176,13 @@ int CommandRemoveEntry(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status = RemoveEntry(argv[0]);
|
char* entry_identifier = argv[0];
|
||||||
if (status != SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
Log(LOG_LEVEL_INFO, "Removed entry '%s'.", argv[0]);
|
Status status = RemoveEntry(entry_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Removed entry '%s'.", entry_identifier);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +195,7 @@ int CommandListEntries(int argc, char* argv[]) {
|
|||||||
char** entries = NULL;
|
char** entries = NULL;
|
||||||
Status status = ListEntries(&entries);
|
Status status = ListEntries(&entries);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
for (size_t i = 0; entries[i] != NULL; i++)
|
for (size_t i = 0; entries[i] != NULL; i++)
|
||||||
fprintf(stdout, "%s\n", entries[i]);
|
fprintf(stdout, "%s\n", entries[i]);
|
||||||
@ -203,8 +215,152 @@ int CommandClearEntries(int argc, char* argv[]) {
|
|||||||
|
|
||||||
Status status = ClearEntries();
|
Status status = ClearEntries();
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
return status;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
Log(LOG_LEVEL_INFO, "Cleared all entries.");
|
Log(LOG_LEVEL_INFO, "Cleared all entries.");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CommandAddDisk(int argc, char* argv[]) {
|
||||||
|
if (argc < 1) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to 'add-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* entry_identifier = argv[0];
|
||||||
|
|
||||||
|
bool root = false;
|
||||||
|
uint64_t size = 0;
|
||||||
|
|
||||||
|
bool backed = false;
|
||||||
|
const char* backing_identifier = NULL;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "--root") == 0 || strcmp(argv[i], "-r") == 0) {
|
||||||
|
if (root) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Duplicate '--root' argument supplied to 'add-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to 'add-disk'. Missing size for '--root <size>'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
root = true;
|
||||||
|
Status status = ParseSize(argv[i + 1], &size);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Invalid size '%s' supplied to 'add-disk'.", argv[i + 1]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++; // Consumes the next argument (the size)
|
||||||
|
} else if (strcmp(argv[i], "--backed") == 0 || strcmp(argv[i], "-b") == 0) {
|
||||||
|
if (backed) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Duplicate '--backed' argument supplied to 'add-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to 'add-disk'. Missing backing identifier for '--backed <backing id>'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
backed = true;
|
||||||
|
backing_identifier = argv[i + 1];
|
||||||
|
|
||||||
|
if (!IsBackingIdentifierValid(backing_identifier)) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Invalid backing identifier '%s' supplied to 'add-disk'.", backing_identifier);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++; // Consumes the next argument (the backing identifier)
|
||||||
|
} else {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Unknown argument '%s' supplied to 'add-disk'.", argv[i]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root && backed) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "The options '--root' and '--backed' cannot be used together in 'add-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
Status status = AddRootEntryDisk(entry_identifier, size);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
char* size_str = NULL;
|
||||||
|
status = FormatSize(size, &size_str);
|
||||||
|
Log(LOG_LEVEL_INFO, "Added root disk to entry '%s' with size %s.", entry_identifier, size_str);
|
||||||
|
free(size_str);
|
||||||
|
} else if (backed) {
|
||||||
|
Status status = AddBackedEntryDisk(entry_identifier, backing_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Added backed disk to entry '%s' with backing '%s'.", entry_identifier, backing_identifier);
|
||||||
|
} else {
|
||||||
|
char* backing_identifier = NULL;
|
||||||
|
Status status = GetLatestBacking(&backing_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
status = AddBackedEntryDisk(entry_identifier, backing_identifier);
|
||||||
|
if (status != SUCCESS) {
|
||||||
|
free(backing_identifier);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Added backed disk to entry '%s' with backing '%s'.", entry_identifier, backing_identifier);
|
||||||
|
free(backing_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CommandRemoveDisk(int argc, char* argv[]) {
|
||||||
|
if (argc < 1) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to 'remove-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else if (argc > 1) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to 'remove-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* entry_identifier = argv[0];
|
||||||
|
|
||||||
|
Status status = RemoveEntryDisk(entry_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Removed disk from entry '%s'.", entry_identifier);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CommandResetDisk(int argc, char* argv[]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CommandTrimDisk(int argc, char* argv[]) {
|
||||||
|
if (argc < 1) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too few arguments supplied to 'trim-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else if (argc > 1) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Too many arguments supplied to 'trim-disk'.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* entry_identifier = argv[0];
|
||||||
|
|
||||||
|
Status status = TrimEntryDisk(entry_identifier);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
Log(LOG_LEVEL_INFO, "Trimmed disk of entry '%s'.", entry_identifier);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
@ -20,4 +20,9 @@ int CommandVersion(int argc, char* argv[]);
|
|||||||
int CommandAddEntry(int argc, char* argv[]);
|
int CommandAddEntry(int argc, char* argv[]);
|
||||||
int CommandRemoveEntry(int argc, char* argv[]);
|
int CommandRemoveEntry(int argc, char* argv[]);
|
||||||
int CommandListEntries(int argc, char* argv[]);
|
int CommandListEntries(int argc, char* argv[]);
|
||||||
int CommandClearEntries(int argc, char* argv[]);
|
int CommandClearEntries(int argc, char* argv[]);
|
||||||
|
|
||||||
|
int CommandAddDisk(int argc, char* argv[]);
|
||||||
|
int CommandRemoveDisk(int argc, char* argv[]);
|
||||||
|
int CommandResetDisk(int argc, char* argv[]);
|
||||||
|
int CommandTrimDisk(int argc, char* argv[]);
|
67
src/utils.c
67
src/utils.c
@ -11,14 +11,14 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
LogLevel log_level = LOG_LEVEL_INFO;
|
LogLevel LOG_LEVEL = LOG_LEVEL_INFO;
|
||||||
|
|
||||||
void SetLogLevel(LogLevel level) {
|
void SetLogLevel(LogLevel level) {
|
||||||
log_level = level;
|
LOG_LEVEL = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log(LogLevel level, const char* format, ...) {
|
void Log(LogLevel level, const char* format, ...) {
|
||||||
if (level < log_level)
|
if (level < LOG_LEVEL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -92,6 +92,67 @@ Status Format(char** _string, const char* fmt, ...) {
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status FormatSize(uint64_t size, char** _size_str) {
|
||||||
|
*_size_str = NULL;
|
||||||
|
|
||||||
|
// Determine the unit
|
||||||
|
const char* unit;
|
||||||
|
double value = size;
|
||||||
|
|
||||||
|
if (value >= 1024ULL * 1024ULL * 1024ULL * 1024ULL) {
|
||||||
|
unit = "TiB";
|
||||||
|
value /= 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
||||||
|
} else if (value >= 1024ULL * 1024ULL * 1024ULL) {
|
||||||
|
unit = "GiB";
|
||||||
|
value /= 1024.0 * 1024.0 * 1024.0;
|
||||||
|
} else if (value >= 1024ULL * 1024ULL) {
|
||||||
|
unit = "MiB";
|
||||||
|
value /= 1024.0 * 1024.0;
|
||||||
|
} else if (value >= 1024ULL) {
|
||||||
|
unit = "KiB";
|
||||||
|
value /= 1024.0;
|
||||||
|
} else {
|
||||||
|
unit = "B";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the size
|
||||||
|
return Format(_size_str, "%.2f %s", value, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ParseSize(const char* size_str, uint64_t* _size) {
|
||||||
|
*_size = 0;
|
||||||
|
|
||||||
|
// Parse the size
|
||||||
|
char* endptr;
|
||||||
|
uint64_t size = strtoull(size_str, &endptr, 10);
|
||||||
|
if (endptr == size_str) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Failed to parse the size string.");
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*endptr == '\0') {
|
||||||
|
*_size = size;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the unit
|
||||||
|
if (strcmp(endptr, "TiB") == 0 || strcmp(endptr, "T") == 0 || strcmp(endptr, "TB") == 0)
|
||||||
|
size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||||
|
else if (strcmp(endptr, "GiB") == 0 || strcmp(endptr, "G") == 0 || strcmp(endptr, "GB") == 0)
|
||||||
|
size *= 1024ULL * 1024ULL * 1024ULL;
|
||||||
|
else if (strcmp(endptr, "MiB") == 0 || strcmp(endptr, "M") == 0 || strcmp(endptr, "MB") == 0)
|
||||||
|
size *= 1024ULL * 1024ULL;
|
||||||
|
else if (strcmp(endptr, "KiB") == 0 || strcmp(endptr, "K") == 0 || strcmp(endptr, "KB") == 0)
|
||||||
|
size *= 1024ULL;
|
||||||
|
else if (strcmp(endptr, "B") != 0) {
|
||||||
|
Log(LOG_LEVEL_ERROR, "Invalid size unit '%s'.", endptr);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_size = size;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
Status RunExecutable(int* _exit_code, char** _stdout, char** _stderr, const char* executable, ...) {
|
Status RunExecutable(int* _exit_code, char** _stdout, char** _stderr, const char* executable, ...) {
|
||||||
if (_exit_code != NULL)
|
if (_exit_code != NULL)
|
||||||
*_exit_code = -1;
|
*_exit_code = -1;
|
||||||
|
@ -15,13 +15,16 @@ typedef enum {
|
|||||||
LOG_LEVEL_ERROR,
|
LOG_LEVEL_ERROR,
|
||||||
} LogLevel;
|
} LogLevel;
|
||||||
|
|
||||||
extern LogLevel log_level;
|
extern LogLevel LOG_LEVEL;
|
||||||
|
|
||||||
void SetLogLevel(LogLevel level);
|
void SetLogLevel(LogLevel level);
|
||||||
void Log(LogLevel level, const char* format, ...);
|
void Log(LogLevel level, const char* format, ...);
|
||||||
|
|
||||||
Status Format(char** _string, const char* fmt, ...);
|
Status Format(char** _string, const char* fmt, ...);
|
||||||
|
|
||||||
|
Status FormatSize(uint64_t size, char** _size_str);
|
||||||
|
Status ParseSize(const char* size_str, uint64_t* _size);
|
||||||
|
|
||||||
Status RunExecutable(int* _exit_code, char** _stdout, char** _stderr, const char* executable, ...);
|
Status RunExecutable(int* _exit_code, char** _stdout, char** _stderr, const char* executable, ...);
|
||||||
|
|
||||||
Status ReadFileDescriptor(int fd, char** _content);
|
Status ReadFileDescriptor(int fd, char** _content);
|
||||||
@ -29,4 +32,4 @@ Status WriteFileDescriptor(int fd, const char* content);
|
|||||||
Status ReadFile(const char* path, char** _content);
|
Status ReadFile(const char* path, char** _content);
|
||||||
Status WriteFile(const char* path, const char* content);
|
Status WriteFile(const char* path, const char* content);
|
||||||
|
|
||||||
Status CopyFile(const char* source_path, const char* destination_path);
|
Status CopyFile(const char* source_path, const char* destination_path);
|
||||||
|
Loading…
Reference in New Issue
Block a user