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");
|
||||
}
|
||||
|
||||
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
|
||||
if (!IsBackingIdentifierValid(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) {
|
||||
// Get the backing path
|
||||
char* backing_path = NULL;
|
||||
Status status = GetBackingDiskPath(backing_identifier, &backing_path);
|
||||
Status status = GetBackingPath(backing_identifier, &backing_path);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
|
||||
@ -83,3 +83,116 @@ Status DoesBackingExist(const char* backing_identifier, bool* _result) {
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -103,11 +103,11 @@ Status TrimDisk(const char* path) {
|
||||
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);
|
||||
} 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);
|
||||
|
||||
|
56
src/entry.c
56
src/entry.c
@ -193,23 +193,23 @@ Status ListEntries(char*** _entries) {
|
||||
}
|
||||
(*_entries)[0] = NULL;
|
||||
|
||||
// Read the entries from the directory
|
||||
// Read the files in the entry pool directory
|
||||
size_t count = 0;
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
struct dirent* file;
|
||||
while ((file = readdir(dir)) != NULL) {
|
||||
if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
// Check if the entry exists (this checks for validity)
|
||||
bool exists;
|
||||
Status status = DoesEntryExist(entry->d_name, &exists);
|
||||
Status status = DoesEntryExist(file->d_name, &exists);
|
||||
if (status != SUCCESS || !exists)
|
||||
continue;
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
@ -221,7 +221,7 @@ Status ListEntries(char*** _entries) {
|
||||
*_entries = new_entries;
|
||||
|
||||
// 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) {
|
||||
Log(LOG_LEVEL_ERROR, "Failed to duplicate the entry name (%s).", strerror(errno));
|
||||
closedir(dir);
|
||||
@ -266,9 +266,19 @@ Status ClearEntries() {
|
||||
}
|
||||
|
||||
Status AddRootEntryDisk(const char* entry_identifier, uint64_t disk_size) {
|
||||
// Check if the disk already exists
|
||||
// Check that the entry 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)
|
||||
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) {
|
||||
// Check if the disk already exists
|
||||
// Check that the entry 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)
|
||||
return status;
|
||||
|
||||
@ -304,7 +334,7 @@ Status AddBackedEntryDisk(const char* entry_identifier, const char* backing_iden
|
||||
|
||||
// Get the backing disk path
|
||||
char* backing_disk_path = NULL;
|
||||
status = GetBackingDiskPath(backing_identifier, &backing_disk_path);
|
||||
status = GetBackingPath(backing_identifier, &backing_disk_path);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
|
||||
@ -368,7 +398,7 @@ Status ResetEntryDisk(const char* entry_identifier, const char* backing_identifi
|
||||
// Get the backing disk path
|
||||
char* backing_disk_path = NULL;
|
||||
if (backing_identifier != NULL) {
|
||||
status = GetBackingDiskPath(backing_identifier, &backing_disk_path);
|
||||
status = GetBackingPath(backing_identifier, &backing_disk_path);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
178
src/sandbox.c
178
src/sandbox.c
@ -24,7 +24,15 @@ Command COMMANDS[] = {
|
||||
"TODO: Add details."},
|
||||
{CommandClearEntries, "clear-entries", NULL, "Clears all the entries from the sandbox.",
|
||||
"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[]) {
|
||||
struct passwd* pw = getpwnam(SANDBOX_USER);
|
||||
@ -149,11 +157,13 @@ int CommandAddEntry(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Status status = AddEntry(argv[0]);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
char* entry_identifier = argv[0];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -166,11 +176,13 @@ int CommandRemoveEntry(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Status status = RemoveEntry(argv[0]);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
char* entry_identifier = argv[0];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -183,7 +195,7 @@ int CommandListEntries(int argc, char* argv[]) {
|
||||
char** entries = NULL;
|
||||
Status status = ListEntries(&entries);
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
return EXIT_FAILURE;
|
||||
|
||||
for (size_t i = 0; entries[i] != NULL; i++)
|
||||
fprintf(stdout, "%s\n", entries[i]);
|
||||
@ -203,8 +215,152 @@ int CommandClearEntries(int argc, char* argv[]) {
|
||||
|
||||
Status status = ClearEntries();
|
||||
if (status != SUCCESS)
|
||||
return status;
|
||||
return EXIT_FAILURE;
|
||||
|
||||
Log(LOG_LEVEL_INFO, "Cleared all entries.");
|
||||
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;
|
||||
}
|
||||
|
@ -21,3 +21,8 @@ int CommandAddEntry(int argc, char* argv[]);
|
||||
int CommandRemoveEntry(int argc, char* argv[]);
|
||||
int CommandListEntries(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/types.h>
|
||||
|
||||
LogLevel log_level = LOG_LEVEL_INFO;
|
||||
LogLevel LOG_LEVEL = LOG_LEVEL_INFO;
|
||||
|
||||
void SetLogLevel(LogLevel level) {
|
||||
log_level = level;
|
||||
LOG_LEVEL = level;
|
||||
}
|
||||
|
||||
void Log(LogLevel level, const char* format, ...) {
|
||||
if (level < log_level)
|
||||
if (level < LOG_LEVEL)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
@ -92,6 +92,67 @@ Status Format(char** _string, const char* fmt, ...) {
|
||||
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, ...) {
|
||||
if (_exit_code != NULL)
|
||||
*_exit_code = -1;
|
||||
|
@ -15,13 +15,16 @@ typedef enum {
|
||||
LOG_LEVEL_ERROR,
|
||||
} LogLevel;
|
||||
|
||||
extern LogLevel log_level;
|
||||
extern LogLevel LOG_LEVEL;
|
||||
|
||||
void SetLogLevel(LogLevel level);
|
||||
void Log(LogLevel level, const char* format, ...);
|
||||
|
||||
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 ReadFileDescriptor(int fd, char** _content);
|
||||
|
Loading…
Reference in New Issue
Block a user