diff --git a/src/backing.c b/src/backing.c index 2aa8245..71a58ae 100644 --- a/src/backing.c +++ b/src/backing.c @@ -84,6 +84,124 @@ Status DoesBackingExist(const char* backing_identifier, bool* _result) { return SUCCESS; } +Status AddBacking(const char* backing_identifier, const char* entry_identifier) { + // Check that the backing does not already exist + bool exists; + Status status = DoesBackingExist(backing_identifier, &exists); + if (status != SUCCESS) + return status; + + if (exists) { + Log(LOG_LEVEL_ERROR, "The backing '%s' already exists.", backing_identifier); + return FAILURE; + } + + // Check that the entry disk exists + status = DoesEntryDiskExist(entry_identifier, &exists); + if (status != SUCCESS) + return status; + + if (!exists) { + Log(LOG_LEVEL_ERROR, "The entry disk '%s' does not exist. Cannot create backing from it.", entry_identifier); + return FAILURE; + } + + // Get information about the entry disk + DiskInfo entry_info; + status = GetEntryDiskInfo(entry_identifier, &entry_info); + if (status != SUCCESS) + return status; + + // Check that the backing used by the entry actually exists (broken backing chain) + if (entry_info.backing_identifier != NULL) { + status = DoesBackingExist(entry_info.backing_identifier, &exists); + if (status != SUCCESS) { + FreeDiskInfo(&entry_info); + return status; + } + + if (!exists) { + Log(LOG_LEVEL_ERROR, "The backing '%s' of the entry disk '%s' does not exist.", entry_info.backing_identifier, entry_identifier); + + FreeDiskInfo(&entry_info); + return FAILURE; + } + } + + // Copy the entry disk to the backing disk + char* entry_disk_path = NULL; + status = GetEntryDiskPath(entry_identifier, &entry_disk_path); + if (status != SUCCESS) { + FreeDiskInfo(&entry_info); + return status; + } + + char* backing_path = NULL; + status = GetBackingPath(backing_identifier, &backing_path); + if (status != SUCCESS) { + free(entry_disk_path); + FreeDiskInfo(&entry_info); + return status; + } + + status = CopyFile(entry_disk_path, backing_path); + if (status != SUCCESS) { + free(entry_disk_path); + free(backing_path); + FreeDiskInfo(&entry_info); + return status; + } + + free(entry_disk_path); + + // If the entry disk has a backing, rebase the backing to the new backing + if (entry_info.backing_identifier != NULL) { + status = RebaseDisk(backing_path, entry_info.backing_identifier); + if (status != SUCCESS) { + RemoveBacking(backing_identifier); + + free(backing_path); + FreeDiskInfo(&entry_info); + return status; + } + } + + free(backing_path); + FreeDiskInfo(&entry_info); + return SUCCESS; +} + +Status RemoveBacking(const char* backing_identifier) { + // Check that the backing exists + bool exists; + Status 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; + } + + // Get the backing path + char* backing_path = NULL; + status = GetBackingPath(backing_identifier, &backing_path); + if (status != SUCCESS) + return status; + + // Remove the backing + if (unlink(backing_path) != 0) { + Log(LOG_LEVEL_ERROR, "Failed to remove the backing '%s' (%s).", backing_identifier, strerror(errno)); + free(backing_path); + return FAILURE; + } + free(backing_path); + + // TODO: Remove all the backings that use this backing as a base + + return SUCCESS; +} + Status ListBackings(char*** _backings) { *_backings = NULL; diff --git a/src/disk.c b/src/disk.c index 4bbf4bb..f29c224 100644 --- a/src/disk.c +++ b/src/disk.c @@ -155,7 +155,7 @@ Status RebaseDisk(const char* path, const char* backing_file) { // char* stdout; char* stderrb; - Status status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "rebase", "-u", "-b", backing_file, path, NULL); + Status status = RunExecutable(&exit_code, NULL, &stderrb, "/usr/bin/qemu-img", "rebase", "-f", "qcow2", "-F", "qcow2", "-u", "-b", backing_file, path, NULL); // Check if the disk was created successfully if (status != SUCCESS) diff --git a/src/sandbox.c b/src/sandbox.c index e8ab3e1..9774ebf 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -33,7 +33,13 @@ Command COMMANDS[] = { {CommandResetDisk, "reset-disk", " [--update|-u] [--backed|-b ]", "Resets the disk of an entry.", "TODO: Add details."}, {CommandTrimDisk, "trim-disk", "", "Trims the disk of an entry.", - "TODO: Add details."}}; + "TODO: Add details."}, + {}, + {CommandAddBacking, "add-backing", " ", "Adds a new backing to the sandbox.", + "TODO: Add details."}, + {CommandRemoveBacking, "remove-backing", "", "Removes a backing from the sandbox.", + "TODO: Add details."}, +}; int main(int argc, char* argv[]) { struct passwd* pw = getpwnam(SANDBOX_USER); @@ -149,6 +155,9 @@ int CommandVersion(int argc, char* argv[]) { } fprintf(stdout, "Sandbox utility v%s\n", VERSION); + + AddBacking("2 - Test", "test"); + return EXIT_SUCCESS; } @@ -365,6 +374,11 @@ int CommandAddDisk(int argc, char* argv[]) { return EXIT_FAILURE; } + if (backing_id == NULL) { + Log(LOG_LEVEL_ERROR, "No backings exist to use as the default backing."); + return EXIT_FAILURE; + } + // Add the backed disk status = AddBackedEntryDisk(entry_id, backing_id); if (status != SUCCESS) { @@ -462,6 +476,11 @@ int CommandResetDisk(int argc, char* argv[]) { return EXIT_FAILURE; } + if (backing_id == NULL) { + Log(LOG_LEVEL_ERROR, "No backings exist to use as the default backing."); + return EXIT_FAILURE; + } + // Reset the disk status = ResetEntryDisk(entry_id, backing_id); if (status != SUCCESS) { @@ -511,3 +530,46 @@ int CommandTrimDisk(int argc, char* argv[]) { Log(LOG_LEVEL_INFO, "Successfully trimmed disk from entry '%s'.", entry_id); return EXIT_SUCCESS; } + +int CommandAddBacking(int argc, char* argv[]) { + if (argc < 2) { + Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'add-backing'."); + return EXIT_FAILURE; + } else if (argc > 2) { + Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'add-backing'."); + return EXIT_FAILURE; + } + + // Extract the backing identifier and entry identifier + const char* backing_id = argv[0]; + const char* entry_id = argv[1]; + + // Add the backing + Status status = AddBacking(backing_id, entry_id); + if (status != SUCCESS) + return EXIT_FAILURE; + + Log(LOG_LEVEL_INFO, "Successfully added backing '%s' from entry '%s'.", backing_id, entry_id); + return EXIT_SUCCESS; +} + +int CommandRemoveBacking(int argc, char* argv[]) { + if (argc < 1) { + Log(LOG_LEVEL_ERROR, "Too few arguments supplied to command 'remove-backing'."); + return EXIT_FAILURE; + } else if (argc > 1) { + Log(LOG_LEVEL_ERROR, "Too many arguments supplied to command 'remove-backing'."); + return EXIT_FAILURE; + } + + // Extract the backing identifier + const char* backing_id = argv[0]; + + // Remove the backing + Status status = RemoveBacking(backing_id); + if (status != SUCCESS) + return EXIT_FAILURE; + + Log(LOG_LEVEL_INFO, "Successfully removed backing '%s'.", backing_id); + return EXIT_SUCCESS; +} diff --git a/src/sandbox.h b/src/sandbox.h index 366e577..e875ca0 100644 --- a/src/sandbox.h +++ b/src/sandbox.h @@ -25,4 +25,7 @@ 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[]); \ No newline at end of file +int CommandTrimDisk(int argc, char* argv[]); + +int CommandAddBacking(int argc, char* argv[]); +int CommandRemoveBacking(int argc, char* argv[]);