diff --git a/src/disk.c b/src/disk.c index 3578799..06762e6 100644 --- a/src/disk.c +++ b/src/disk.c @@ -5,6 +5,7 @@ #include #include #include +#include #include Result create_root_disk(const char* path, uint64_t size, mode_t permissions) { @@ -98,6 +99,82 @@ Result create_backed_disk(const char* path, const char* backing_disk, mode_t per return SUCCESS; } +Result trim_disk(const char* path) { + char* tmp_path; + Result result = format(&tmp_path, "%s.tmp", path); + if (result != SUCCESS) + return result; + + DiskInfo info; + result = get_disk_info(path, &info); + if (result != SUCCESS) { + free(tmp_path); + return result; + } + + // Create the trimmed disk + int exit_code; + char* stderr_buffer = NULL; + + if (info.backing_file == NULL) { + // If the disk is not backed, we can simply convert it to a new disk + result = run_executable(&exit_code, NULL, &stderr_buffer, "qemu-img", "convert", "-f", "qcow2", "-O", "qcow2", path, tmp_path, NULL); + } else { + // If the disk is backed, we need to specify the backing file + char* backing_disk_arg; + result = format(&backing_disk_arg, "backing_file=%s", info.backing_file); + if (result != SUCCESS) { + free(tmp_path); + free_disk_info(&info); + return result; + } + + result = run_executable(&exit_code, NULL, &stderr_buffer, "qemu-img", "convert", "-f", "qcow2", "-F", "qcow2", "-O", "qcow2", "-o", backing_disk_arg, path, tmp_path, NULL); + + free(backing_disk_arg); + } + + // Free the disk info as it is no longer needed + free_disk_info(&info); + + if (result != SUCCESS) { + free(tmp_path); + free(stderr_buffer); + return result; + } + + // Check the exit code + if (exit_code != EXIT_SUCCESS) { + if (stderr_buffer == NULL) + log_message(LOG_LEVEL_ERROR, "Failed to trim the disk '%s'.", path); + else { + // Remove newlines from the error message + for (size_t i = 0; i < strlen(stderr_buffer); i++) + if (stderr_buffer[i] == '\n') + stderr_buffer[i] = ' '; + + log_message(LOG_LEVEL_ERROR, "Failed to trim the disk '%s' (%s).", path, stderr_buffer); + free(stderr_buffer); + } + + free(tmp_path); + return FAILURE; + } + + // Replace the original disk with the trimmed disk + if (rename(tmp_path, path) != 0) { + log_message(LOG_LEVEL_ERROR, "Failed to replace the disk '%s' with the trimmed disk '%s' (%s).", path, tmp_path, strerror(errno)); + + unlink(tmp_path); + free(tmp_path); + return FAILURE; + } + + // Free the temporary path + free(tmp_path); + return SUCCESS; +} + Result rebase_disk(const char* path, const char* backing_disk) { // Rebase the disk int exit_code; diff --git a/src/entry.h b/src/entry.h index 8abe526..85d31ec 100644 --- a/src/entry.h +++ b/src/entry.h @@ -56,3 +56,5 @@ Result clear_entries(void); /// @param out_path The pointer to the output path string. The caller is responsible for freeing the memory. /// @return The result of the operation. Result get_entry_disk_path(const char* entry_id, char** out_path); + +// TODO: Implement a function to reserve disk space to avoid running out of space while the sandbox is running. \ No newline at end of file diff --git a/src/sandbox.c b/src/sandbox.c index 7ee5e84..04a30ab 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -127,6 +127,7 @@ int command_add_backing(int argc, char* argv[]) { return EXIT_FAILURE; } + trim_disk("test2"); // TODO: Call add_backing return EXIT_SUCCESS;