#include "container.h" #include "disk.h" #include "backing.h" #include #include #include #include #include #include result_t check_container_identifier(const char* container) { // Check that the container identifier is not null if (container == NULL) return failure("Container identifier cannot be null."); // Check that the container identifier is not empty, nor too long size_t length = strlen(container); if (length == 0) return failure("Container identifier cannot be empty."); if (length > CONTAINER_IDENTIFIER_MAX_LENGTH) return failure("Container identifier cannot be longer than %d characters.", CONTAINER_IDENTIFIER_MAX_LENGTH); // Check that the container identifier only contains allowed characters for (size_t i = 0; i < length; i++) { char c = container[i]; if (c >= 'a' && c <= 'z') continue; if (c >= 'A' && c <= 'Z') continue; if (c >= '0' && c <= '9') continue; if ((c == '-' || c == '_' || c == '.') && i > 0) // Not at the beginning continue; return failure("Container identifier cannot contain the character '%c' at index %d.", c, i); } return success(); } result_t check_container_exists(const char* container) { // Get the container path char* path; result_t result = get_container_path(&path, container); if (result != success()) return result; // Check that the container exists struct stat st; errno = 0; if (stat(path, &st) != 0) { if (errno == ENOENT) result = failure("Container '%s' does not exist.", container); else result = failure("Failed to check if container '%s' exists (%s).", container, strerror(errno)); free(path); return result; } // Check that the container is a file if (!S_ISREG(st.st_mode)) { result = failure("Container '%s' is not a file.", container); free(path); return result; } free(path); return success(); } result_t get_container_pool_path(char** _path) { // Initialize the output parameters *_path = NULL; return format(_path, "/var/lib/sandbox/containers"); } result_t get_container_path(char** _path, const char* container) { // Initialize the output parameters *_path = NULL; // Check the container identifier result_t result = check_container_identifier(container); if (result != success()) return result; // Get the container pool path char* pool_path; result = get_container_pool_path(&pool_path); if (result != success()) return result; // Format the container path result = format(_path, "%s/%s", pool_path, container); free(pool_path); return result; } result_t add_root_container(const char* container, uint64_t size) { // Check that the container does not already exist result_t result = check_container_exists(container); if (result == success()) return failure("Container '%s' already exists.", container); // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Create the root container result = create_root_disk(path, size); free(path); return result; } result_t add_backed_container(const char* container, const char* backing) { // Check that the container does not already exist result_t result = check_container_exists(container); if (result == success()) return failure("Container '%s' already exists.", container); // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Check that the backing exists result = check_backing_exists(backing); if (result != success()) { free(path); return result; } // Get the backing path char* backing_path; result = get_backing_path(&backing_path, backing); if (result != success()) { free(path); return result; } // Create the backed container result = create_backed_disk(path, backing_path); free(backing_path); free(path); return result; } result_t remove_container(const char* container) { // Check that the container exists result_t result = check_container_exists(container); if (result != success()) return result; // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Delete the container errno = 0; remove(path); free(path); if (errno != 0) return failure("Failed to remove container '%s' (%s).", container, strerror(errno)); return success(); } result_t trim_container(const char* container) { // Check that the container exists result_t result = check_container_exists(container); if (result != success()) return result; // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Trim the container result = trim_disk(path); free(path); return result; } result_t reset_container(const char* container) { // Check that the container exists result_t result = check_container_exists(container); if (result != success()) return result; // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Reset the container result = reset_disk(path); free(path); return result; } bool container_filter(const char* file) { // Check that a container with the same name exists return check_container_exists(file) == success(); } result_t list_containers(char*** _containers) { // Initialize the output parameters *_containers = NULL; // Get the container pool path char* pool_path; result_t result = get_container_pool_path(&pool_path); if (result != success()) return result; // List the files in the container pool result = list_files(_containers, pool_path, container_filter); free(pool_path); return result; } result_t get_container_backing(char** _backing, const char* container) { // Initialize the output parameters *_backing = NULL; // Check that the container exists result_t result = check_container_exists(container); if (result != success()) return result; // Get the container path char* path; result = get_container_path(&path, container); if (result != success()) return result; // Get the disk information disk_info_t info; result = get_disk_info(&info, path); if (result != success()) { free(path); return result; } // Free the container path as it is no longer needed free(path); // Check if the disk is backed if (info.backing_path == NULL) { free_disk_info(&info); success(); } // Get the backing identifier char* backing = strdup(basename(info.backing_path)); // Free the disk information as it is no longer needed free_disk_info(&info); if (backing == NULL) return failure("Failed to get backing identifier for container '%s'.", container); *_backing = backing; return success(); }