diff --git a/src/backing.c b/src/backing.c new file mode 100644 index 0000000..d51781a --- /dev/null +++ b/src/backing.c @@ -0,0 +1,74 @@ +#include "backing.h" + +#include +#include + +bool is_valid_backing_name(const char* name) { + if (name == NULL) + return false; + + size_t len = strlen(name); + if (len == 0) + return false; + + for (size_t i = 0; i < len; i++) + if (name[i] == '/') + return false; + + if (name[0] < '0' || name[0] > '9') + return false; + + return true; +} + +char* get_backing_path(const char* name) { + if (name == NULL) + return NULL; + + return format("%s/%s", "/var/lib/sandbox/backings", name); +} + +bool backing_exists(const char* name) { + if (name == NULL) + return false; + + char* path = get_backing_path(name); + if (path == NULL) + return false; + + // Check if the backing exists + struct stat st; + if (stat(path, &st) != 0) { + free(path); + return false; + } + + // Free the path, as it is no longer needed + free(path); + + if (!S_ISREG(st.st_mode)) + return false; + + return true; +} + +time_t get_backing_ctime(const char* name) { + // As the name starts with the ctime, we can just convert the first part of the name to a time_t + size_t len = strlen(name); + size_t ctime_len = 0; + for (size_t i = 0; i < len; i++) { + if (name[i] < '0' || name[i] > '9') + break; + + ctime_len++; + } + + char* ctime_str = strndup(name, ctime_len); + if (ctime_str == NULL) + return 0; + + time_t ctime = (time_t)strtoull(ctime_str, NULL, 10); + free(ctime_str); + + return ctime; +} diff --git a/src/backing.h b/src/backing.h new file mode 100644 index 0000000..a8863d2 --- /dev/null +++ b/src/backing.h @@ -0,0 +1,41 @@ +#pragma once + +#include "sandbox.h" + +#include +#include +#include + +/// @brief Returns whether the given name is a valid backing name. Backing names are valid if they start with a number (used as the ctime). +/// @param name The name to check. +/// @return Whether the name is valid or not. +bool is_valid_backing_name(const char* name); + +/// @brief Returns the backing path for the given name. +/// @param name The name of the backing. Note: This function does not check if the name is valid. +/// @return The backing path. +char* get_backing_path(const char* name); + +/// @brief Returns the backing path for the given name. +/// @param name The name of the backing. Note: This function does not check if the name is valid. +/// @return The backing path. +bool backing_exists(const char* name); + +/// @brief Returns an array of all the backing names, terminated by a NULL pointer. +/// @return An array of all the backing names. Note: The array must be freed by the caller, including every string in the array. +char** list_backings(void); + +/// @brief Returns the ctime of the backing with the given name. +/// @param name The name of the backing. +/// @return The ctime of the backing. +time_t get_backing_ctime(const char* name); + +/// @brief Returns the latest backing's name. +/// @return The latest backing's name. +char* get_latest_backing(void); + +/// @brief Creates a new backing with the given name from the given source disk. +/// @param name The name of the new backing. +/// @param source_disk The source disk to create the backing from. Note: If the source disk has a backing file, it must be a existing sandbox backing disk. +/// @return Whether the backing was created successfully or not. +bool create_backing(const char* name, const char* source_disk); diff --git a/src/sandbox.c b/src/sandbox.c index 9970a34..03418e2 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -9,9 +9,5 @@ #include int main(int argc, char* argv[]) { - create_empty_disk("test.qcow2", 1024 * 1024 * 1024); - create_backed_disk("test2.qcow2", "test.qcow2"); - rebase_disk("test2.qcow2", "test.qcow2"); - return 0; } \ No newline at end of file