Added add_backing
This commit is contained in:
parent
b77418f0ec
commit
3c773a8dc2
158
src/backing.c
158
src/backing.c
@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
result_t check_backing_identifier(const char* backing) {
|
result_t check_backing_identifier(const char* backing) {
|
||||||
@ -69,10 +70,16 @@ result_t check_backing_exists(const char* backing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t get_backing_pool_path(char** _path) {
|
result_t get_backing_pool_path(char** _path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
return format(_path, "/var/lib/sandbox/backings");
|
return format(_path, "/var/lib/sandbox/backings");
|
||||||
}
|
}
|
||||||
|
|
||||||
result_t get_backing_path(char** _path, const char* backing) {
|
result_t get_backing_path(char** _path, const char* backing) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
// Check the backing identifier
|
// Check the backing identifier
|
||||||
result_t result = check_backing_identifier(backing);
|
result_t result = check_backing_identifier(backing);
|
||||||
if (result != success())
|
if (result != success())
|
||||||
@ -92,6 +99,9 @@ result_t get_backing_path(char** _path, const char* backing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t get_backing_default_path(char** _path) {
|
result_t get_backing_default_path(char** _path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
// Get the backing pool path
|
// Get the backing pool path
|
||||||
char* pool_path;
|
char* pool_path;
|
||||||
result_t result = get_backing_pool_path(&pool_path);
|
result_t result = get_backing_pool_path(&pool_path);
|
||||||
@ -105,6 +115,148 @@ result_t get_backing_default_path(char** _path) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t get_backing_temp_path(char** _path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
|
// Get the backing pool path
|
||||||
|
char* pool_path;
|
||||||
|
result_t result = get_backing_pool_path(&pool_path);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Format the backing path
|
||||||
|
result = format(_path, "%s/temp", pool_path);
|
||||||
|
|
||||||
|
free(pool_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_t add_backing(char** _backing, const char* container) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_backing = NULL;
|
||||||
|
|
||||||
|
// Get the container path
|
||||||
|
char* path;
|
||||||
|
result_t result = get_container_path(&path, container);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Import the container as a backing
|
||||||
|
result = import_backing(_backing, path);
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_t import_backing(char** _backing, const char* path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_backing = NULL;
|
||||||
|
|
||||||
|
// Get the temporary backing path
|
||||||
|
char* temp_path;
|
||||||
|
result_t result = get_backing_temp_path(&temp_path);
|
||||||
|
if (result != success())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Copy the disk to the temporary backing path
|
||||||
|
result = copy_file(path, temp_path);
|
||||||
|
if (result != success()) {
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the disk info to know if the disk is backed
|
||||||
|
disk_info_t info;
|
||||||
|
result = get_disk_info(&info, temp_path);
|
||||||
|
if (result != success()) {
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.backing_path != NULL) {
|
||||||
|
// Get the backing identifier of the parent
|
||||||
|
char* backing = strdup(basename(info.backing_path));
|
||||||
|
if (backing == NULL) {
|
||||||
|
free_disk_info(&info);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return failure("Failed to get the backing identifier of the parent.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the backing exists
|
||||||
|
result = check_backing_exists(backing);
|
||||||
|
if (result != success()) {
|
||||||
|
free_disk_info(&info);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
free(backing);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reback the disk to the parent
|
||||||
|
result = reback_disk(temp_path, backing);
|
||||||
|
if (result != success()) {
|
||||||
|
free_disk_info(&info);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
free(backing);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_disk_info(&info);
|
||||||
|
|
||||||
|
// Get the md5 hash of the disk as the backing identifier
|
||||||
|
char* backing;
|
||||||
|
result = md5sum(&backing, temp_path);
|
||||||
|
if (result != success()) {
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the backing already exists
|
||||||
|
result = check_backing_exists(backing);
|
||||||
|
if (result == success()) {
|
||||||
|
result = failure("Backing '%s' already exists.", backing);
|
||||||
|
free(backing);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the path of the final backing
|
||||||
|
char* backing_path;
|
||||||
|
result = get_backing_path(&backing_path, backing);
|
||||||
|
if (result != success()) {
|
||||||
|
free(backing);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the temporary backing to the final backing path
|
||||||
|
errno = 0;
|
||||||
|
if (rename(temp_path, backing_path) != 0) {
|
||||||
|
result = failure("Failed to move the temporary backing to the final backing path (%s).", strerror(errno));
|
||||||
|
free(backing);
|
||||||
|
free(backing_path);
|
||||||
|
remove(temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(backing_path);
|
||||||
|
free(temp_path);
|
||||||
|
|
||||||
|
*_backing = backing;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result_t remove_backing(const char* backing) {
|
result_t remove_backing(const char* backing) {
|
||||||
// Check that the backing exists
|
// Check that the backing exists
|
||||||
result_t result = check_backing_exists(backing);
|
result_t result = check_backing_exists(backing);
|
||||||
@ -137,6 +289,9 @@ bool backing_filter(const char* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t list_backings(char*** _backings) {
|
result_t list_backings(char*** _backings) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_backings = NULL;
|
||||||
|
|
||||||
// Get the backing pool path
|
// Get the backing pool path
|
||||||
char* pool_path;
|
char* pool_path;
|
||||||
result_t result = get_backing_pool_path(&pool_path);
|
result_t result = get_backing_pool_path(&pool_path);
|
||||||
@ -151,6 +306,9 @@ result_t list_backings(char*** _backings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t get_default_backing(char** _backing) {
|
result_t get_default_backing(char** _backing) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_backing = NULL;
|
||||||
|
|
||||||
// Get the backing default path
|
// Get the backing default path
|
||||||
char* path;
|
char* path;
|
||||||
result_t result = get_backing_default_path(&path);
|
result_t result = get_backing_default_path(&path);
|
||||||
|
@ -8,8 +8,10 @@ result_t check_backing_exists(const char* backing);
|
|||||||
result_t get_backing_pool_path(char** _path);
|
result_t get_backing_pool_path(char** _path);
|
||||||
result_t get_backing_path(char** _path, const char* backing);
|
result_t get_backing_path(char** _path, const char* backing);
|
||||||
result_t get_backing_default_path(char** _path);
|
result_t get_backing_default_path(char** _path);
|
||||||
|
result_t get_backing_temp_path(char** _path);
|
||||||
|
|
||||||
result_t add_backing(const char* backing, const char* container);
|
result_t add_backing(char** _backing, const char* container);
|
||||||
|
result_t import_backing(char** _backing, const char* path);
|
||||||
result_t remove_backing(const char* backing);
|
result_t remove_backing(const char* backing);
|
||||||
|
|
||||||
bool backing_filter(const char* file);
|
bool backing_filter(const char* file);
|
||||||
|
@ -71,10 +71,16 @@ result_t check_container_exists(const char* container) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t get_container_pool_path(char** _path) {
|
result_t get_container_pool_path(char** _path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
return format(_path, "/var/lib/sandbox/containers");
|
return format(_path, "/var/lib/sandbox/containers");
|
||||||
}
|
}
|
||||||
|
|
||||||
result_t get_container_path(char** _path, const char* container) {
|
result_t get_container_path(char** _path, const char* container) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_path = NULL;
|
||||||
|
|
||||||
// Check the container identifier
|
// Check the container identifier
|
||||||
result_t result = check_container_identifier(container);
|
result_t result = check_container_identifier(container);
|
||||||
if (result != success())
|
if (result != success())
|
||||||
@ -208,6 +214,9 @@ bool container_filter(const char* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t list_containers(char*** _containers) {
|
result_t list_containers(char*** _containers) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_containers = NULL;
|
||||||
|
|
||||||
// Get the container pool path
|
// Get the container pool path
|
||||||
char* pool_path;
|
char* pool_path;
|
||||||
result_t result = get_container_pool_path(&pool_path);
|
result_t result = get_container_pool_path(&pool_path);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "sandbox.h"
|
#include "sandbox.h"
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "backing.h"
|
||||||
|
#include "container.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -65,6 +67,13 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Parse commands from the command line
|
// TODO: Parse commands from the command line
|
||||||
|
while (1) {
|
||||||
|
char* backing2;
|
||||||
|
result_t result = add_backing(&backing2, "test2");
|
||||||
|
if (result != success()) {
|
||||||
|
fprintf(stderr, "Failed to add backing: %s\n", error());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int command_help(int argc, char* argv[]) {
|
int command_help(int argc, char* argv[]) {
|
||||||
|
140
src/utils.c
140
src/utils.c
@ -10,7 +10,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
char ERROR_BUFFER[ERROR_BUFFER_SIZE];
|
char ERROR_BUFFER[ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
@ -412,6 +412,62 @@ result_t write_file(const char* path, const char* str) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t copy_file(const char* src, const char* dst) {
|
||||||
|
// Open the source file
|
||||||
|
errno = 0;
|
||||||
|
int src_fd = open(src, O_RDONLY);
|
||||||
|
if (src_fd < 0)
|
||||||
|
return failure("Failed to open the source file '%s' (%s).", src, strerror(errno));
|
||||||
|
|
||||||
|
// Open the destination file
|
||||||
|
errno = 0;
|
||||||
|
int dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
|
if (dst_fd < 0) {
|
||||||
|
close(src_fd);
|
||||||
|
return failure("Failed to open the destination file '%s' (%s).", dst, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the source file to the destination file
|
||||||
|
char buffer[4096];
|
||||||
|
ssize_t count;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Read from the source file
|
||||||
|
errno = 0;
|
||||||
|
count = read(src_fd, buffer, sizeof(buffer));
|
||||||
|
if (count < 0) {
|
||||||
|
close(src_fd);
|
||||||
|
close(dst_fd);
|
||||||
|
return failure("Failed to read from the source file '%s' (%s).", src, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the end of the file is reached, stop copying
|
||||||
|
if (count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Write to the destination file
|
||||||
|
while (count > 0) {
|
||||||
|
errno = 0;
|
||||||
|
ssize_t written = write(dst_fd, buffer, count);
|
||||||
|
if (written < 0) {
|
||||||
|
close(src_fd);
|
||||||
|
close(dst_fd);
|
||||||
|
return failure("Failed to write to the destination file '%s' (%s).", dst, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
count -= written;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the source file
|
||||||
|
close(src_fd);
|
||||||
|
|
||||||
|
// Close the destination file
|
||||||
|
close(dst_fd);
|
||||||
|
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
result_t list_files(char*** _files, const char* path, bool (*filter)(const char*)) {
|
result_t list_files(char*** _files, const char* path, bool (*filter)(const char*)) {
|
||||||
// Initialize the output parameters
|
// Initialize the output parameters
|
||||||
*_files = NULL;
|
*_files = NULL;
|
||||||
@ -493,3 +549,85 @@ result_t list_files(char*** _files, const char* path, bool (*filter)(const char*
|
|||||||
*_files = files;
|
*_files = files;
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t md5sum(char** _md5, const char* path) {
|
||||||
|
// Initialize the output parameters
|
||||||
|
*_md5 = NULL;
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
errno = 0;
|
||||||
|
int fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return failure("Failed to open the file '%s' (%s).", path, strerror(errno));
|
||||||
|
|
||||||
|
// Initialize the MD5 context
|
||||||
|
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
|
||||||
|
if (mdctx == NULL) {
|
||||||
|
close(fd);
|
||||||
|
return failure("Failed to initialize the MD5 context.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_DigestInit_ex(mdctx, EVP_md5(), NULL) != 1) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
close(fd);
|
||||||
|
return failure("Failed to initialize the MD5 context.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file and update the MD5 context
|
||||||
|
char buffer[4096];
|
||||||
|
ssize_t count;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Read from the file
|
||||||
|
errno = 0;
|
||||||
|
count = read(fd, buffer, sizeof(buffer));
|
||||||
|
if (count < 0) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
close(fd);
|
||||||
|
return failure("Failed to read from the file '%s' (%s).", path, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the end of the file is reached, stop updating the MD5 context
|
||||||
|
if (count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Update the MD5 context
|
||||||
|
if (EVP_DigestUpdate(mdctx, buffer, count) != 1) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
close(fd);
|
||||||
|
return failure("Failed to update the MD5 context.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize the MD5 context
|
||||||
|
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int md_len;
|
||||||
|
|
||||||
|
if (EVP_DigestFinal_ex(mdctx, md_value, &md_len) != 1) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
close(fd);
|
||||||
|
return failure("Failed to finalize the MD5 context.");
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
|
||||||
|
// Close the file
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// Format the MD5 checksum
|
||||||
|
errno = 0;
|
||||||
|
char* md5 = malloc(2 * md_len + 1); // +1 for the null terminator
|
||||||
|
if (md5 == NULL)
|
||||||
|
return failure("Failed to allocate memory for the MD5 checksum (%s).", strerror(errno));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < md_len; i++)
|
||||||
|
if (snprintf(md5 + 2 * i, 3, "%02x", md_value[i]) != 2) {
|
||||||
|
free(md5);
|
||||||
|
return failure("Failed to format the MD5 checksum.");
|
||||||
|
}
|
||||||
|
md5[2 * md_len] = '\0';
|
||||||
|
|
||||||
|
// Return the MD5 checksum
|
||||||
|
*_md5 = md5;
|
||||||
|
return success();
|
||||||
|
}
|
@ -26,5 +26,8 @@ result_t read_fd(char** _str, int fd);
|
|||||||
result_t write_fd(int fd, const char* str);
|
result_t write_fd(int fd, const char* str);
|
||||||
result_t read_file(char** _str, const char* path);
|
result_t read_file(char** _str, const char* path);
|
||||||
result_t write_file(const char* path, const char* str);
|
result_t write_file(const char* path, const char* str);
|
||||||
|
result_t copy_file(const char* src, const char* dst);
|
||||||
|
|
||||||
result_t list_files(char*** _files, const char* path, bool (*filter)(const char*));
|
result_t list_files(char*** _files, const char* path, bool (*filter)(const char*));
|
||||||
|
|
||||||
|
result_t md5sum(char** _md5, const char* path);
|
||||||
|
Loading…
Reference in New Issue
Block a user