Added a verbose logging system
This commit is contained in:
parent
a02cd9fe20
commit
0373d159a2
362
src/backing.c
362
src/backing.c
@ -1,362 +0,0 @@
|
|||||||
#include "backing.h"
|
|
||||||
#include "container.h"
|
|
||||||
#include "disk.h"
|
|
||||||
#include "sandbox.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
result_t check_backing_identifier(const char* backing) {
|
|
||||||
// Check that the backing identifier is not null.
|
|
||||||
if (backing == NULL)
|
|
||||||
return failure("Backing identifier cannot be null.");
|
|
||||||
|
|
||||||
// Check that the backing identifier is a valid md5 hash.
|
|
||||||
size_t length = strlen(backing);
|
|
||||||
if (length != 32)
|
|
||||||
return failure("Backing identifier must be a 32-character md5 hash.");
|
|
||||||
|
|
||||||
// Check that the backing identifier only contains valid characters.
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
|
||||||
char c = backing[i];
|
|
||||||
if ((c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return failure("Backing identifier must be a 32-character md5 hash.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t get_backing_pool_path(char** _path, const config_t* config) {
|
|
||||||
// Get the path of the backing pool.
|
|
||||||
char* path = strdup(config->backing_pool);
|
|
||||||
if (path == NULL)
|
|
||||||
return failure("Failed to allocate memory for the backing pool path.");
|
|
||||||
|
|
||||||
// Output the path.
|
|
||||||
*_path = path;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t get_backing_path(char** _path, const config_t* config, const char* backing) {
|
|
||||||
// Check that the backing identifier is valid.
|
|
||||||
result_t result = check_backing_identifier(backing);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the path of the backing pool.
|
|
||||||
char* pool_path;
|
|
||||||
result = get_backing_pool_path(&pool_path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Append the backing identifier to the backing pool path.
|
|
||||||
char* path;
|
|
||||||
if (asprintf(&path, "%s/%s", pool_path, backing) == -1) {
|
|
||||||
free(pool_path);
|
|
||||||
return failure("Failed to allocate memory for the backing path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pool_path);
|
|
||||||
|
|
||||||
// Output the path.
|
|
||||||
*_path = path;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t get_backing_default_path(char** _path, const config_t* config) {
|
|
||||||
// Get the path of the backing pool.
|
|
||||||
char* pool_path;
|
|
||||||
result_t result = get_backing_pool_path(&pool_path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Append the default backing identifier to the backing pool path.
|
|
||||||
char* path;
|
|
||||||
if (asprintf(&path, "%s/default", pool_path) == -1) {
|
|
||||||
free(pool_path);
|
|
||||||
return failure("Failed to allocate memory for the default backing path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pool_path);
|
|
||||||
|
|
||||||
// Output the path.
|
|
||||||
*_path = path;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t get_backing_temporary_path(char** _path, const config_t* config) {
|
|
||||||
// Get the path of the backing pool.
|
|
||||||
char* pool_path;
|
|
||||||
result_t result = get_backing_pool_path(&pool_path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Append the temporary backing identifier to the backing pool path.
|
|
||||||
char* path;
|
|
||||||
if (asprintf(&path, "%s/temporary", pool_path) == -1) {
|
|
||||||
free(pool_path);
|
|
||||||
return failure("Failed to allocate memory for the temporary backing path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pool_path);
|
|
||||||
|
|
||||||
// Output the path.
|
|
||||||
*_path = path;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t check_backing_exists(const config_t* config, const char* backing) {
|
|
||||||
// Get the path of the backing.
|
|
||||||
char* path;
|
|
||||||
result_t result = get_backing_path(&path, config, backing);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Check whether the backing exists.
|
|
||||||
struct stat st;
|
|
||||||
if (stat(path, &st) == -1) {
|
|
||||||
free(path);
|
|
||||||
if (errno == ENOENT)
|
|
||||||
return failure("Backing '%s' does not exist.", backing);
|
|
||||||
return failure("Failed to check whether backing '%s' exists: %s.", backing, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode)) {
|
|
||||||
free(path);
|
|
||||||
return failure("Backing '%s' is not a regular file.", backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the backing path.
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t get_default_backing(char** _backing, const config_t* config) {
|
|
||||||
// Get the path of the default backing.
|
|
||||||
char* path;
|
|
||||||
result_t result = get_backing_default_path(&path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Read the backing identifier from the default backing file.
|
|
||||||
char* backing = NULL;
|
|
||||||
result = read_file(&backing, NULL, path);
|
|
||||||
if (result != success()) {
|
|
||||||
free(path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the default backing path.
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
// Check that the backing identifier is valid.
|
|
||||||
result = check_backing_identifier(backing);
|
|
||||||
if (result != success()) {
|
|
||||||
free(backing);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output the backing identifier.
|
|
||||||
*_backing = backing;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t set_default_backing(const config_t* config, const char* backing) {
|
|
||||||
// Check that the backing identifier is valid.
|
|
||||||
result_t result = check_backing_identifier(backing);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the path of the default backing.
|
|
||||||
char* path;
|
|
||||||
result = get_backing_default_path(&path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Write the backing identifier to the default backing file.
|
|
||||||
result = write_file(backing, path, sizeof(path), 0644);
|
|
||||||
if (result != success()) {
|
|
||||||
free(path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the default backing path.
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t add_backing(char** _backing, const config_t* config, const char* container) {
|
|
||||||
// Check that the container identifier is valid.
|
|
||||||
result_t result = check_container_identifier(container);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Check that the container exists.
|
|
||||||
result = check_container_exists(config, container);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the path of the container.
|
|
||||||
char* path;
|
|
||||||
result = get_container_path(&path, config, container);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the path of the temporary backing.
|
|
||||||
char* temporary_path;
|
|
||||||
result = get_backing_temporary_path(&temporary_path, config);
|
|
||||||
if (result != success()) {
|
|
||||||
free(path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the container to the temporary backing.
|
|
||||||
result = copy_file(path, temporary_path, 0644);
|
|
||||||
if (result != success()) {
|
|
||||||
free(path);
|
|
||||||
free(temporary_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the container path.
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
// Get information about the temporary backing.
|
|
||||||
disk_info_t* info;
|
|
||||||
result = read_disk_info(&info, temporary_path);
|
|
||||||
if (result != success()) {
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->backing_name != NULL) {
|
|
||||||
result = check_backing_exists(config, info->backing_name);
|
|
||||||
if (result != success()) {
|
|
||||||
free_disk_info(info);
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reback the temporary backing to a relative path.
|
|
||||||
result = reback_disk(temporary_path, info->backing_name);
|
|
||||||
if (result != success()) {
|
|
||||||
free_disk_info(info);
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_disk_info(info);
|
|
||||||
|
|
||||||
// Get the md5 hash of the temporary backing.
|
|
||||||
char* hash;
|
|
||||||
result = md5_file(&hash, temporary_path);
|
|
||||||
if (result != success()) {
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the backing already exists.
|
|
||||||
result = check_backing_exists(config, hash);
|
|
||||||
if (result == success()) {
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
|
|
||||||
result = failure("Backing '%s' already exists.", hash);
|
|
||||||
free(hash);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the temporary backing to the backing pool.
|
|
||||||
char* backing_path;
|
|
||||||
result = get_backing_path(&backing_path, config, hash);
|
|
||||||
if (result != success()) {
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
free(hash);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(temporary_path, backing_path) == -1) {
|
|
||||||
unlink(temporary_path);
|
|
||||||
free(temporary_path);
|
|
||||||
free(backing_path);
|
|
||||||
free(hash);
|
|
||||||
return failure("Failed to move temporary backing to the backing pool: %s.", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(temporary_path);
|
|
||||||
|
|
||||||
// Output the backing identifier.
|
|
||||||
*_backing = hash;
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t remove_backing(const config_t* config, const char* backing) {
|
|
||||||
// Check that the backing exists.
|
|
||||||
result_t result = check_backing_exists(config, backing);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the path of the backing.
|
|
||||||
char* path;
|
|
||||||
result = get_backing_path(&path, config, backing);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Remove the backing.
|
|
||||||
if (unlink(path) == -1) {
|
|
||||||
free(path);
|
|
||||||
return failure("Failed to remove backing '%s': %s.", backing, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the backing path.
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t list_backings(char*** _backings, const config_t* config) {
|
|
||||||
// Get the path of the backing pool.
|
|
||||||
char* pool_path;
|
|
||||||
result_t result = get_backing_pool_path(&pool_path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Get the list of backings.
|
|
||||||
return list_files(_backings, pool_path, check_backing_identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t sync_backing(const config_t* config) {
|
|
||||||
// Get the backing pool path.
|
|
||||||
char* pool_path;
|
|
||||||
result_t result = get_backing_pool_path(&pool_path, config);
|
|
||||||
if (result != success())
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Execute the synchronization script.
|
|
||||||
result = execute_file(NULL, NULL, NULL, NULL, NULL, pool_path, SYNCRONIZATION_FILE, NULL);
|
|
||||||
|
|
||||||
// Free the backing pool path.
|
|
||||||
free(pool_path);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
131
src/config.c
131
src/config.c
@ -1,31 +1,136 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "sandbox.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <json-c/json.h>
|
#include <json-c/json.h>
|
||||||
|
|
||||||
result_t init_config(config_t** _config) {
|
result_t init_config(config_t** _config) {
|
||||||
// Create the configuration.
|
result_t result;
|
||||||
config_t* config = malloc(sizeof(config_t));
|
|
||||||
if (config == NULL)
|
|
||||||
return failure("Failed to allocate memory for the configuration.");
|
|
||||||
|
|
||||||
// Initialize the configuration.
|
// Allocate the configuration.
|
||||||
config->container_pool = strdup("/var/lib/sandbox/containers");
|
config_t* config = (config_t*)malloc(sizeof(config_t));
|
||||||
config->backing_pool = strdup("/var/lib/sandbox/backings");
|
if (config == NULL) {
|
||||||
|
result = failure("Failed to allocate memory for the configuration (%s).", strerror(errno));
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
// Output the configuration.
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the configuration file.
|
||||||
|
char* config_json;
|
||||||
|
result = read_file(&config_json, NULL, CONFIGURATION_FILE);
|
||||||
|
if (result != success()) {
|
||||||
|
result = failure("Failed to read the configuration file '%s'.", CONFIGURATION_FILE);
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the configuration JSON text.
|
||||||
|
json_object* root = json_tokener_parse(config_json);
|
||||||
|
if (root == NULL) {
|
||||||
|
result = failure("Failed to parse the configuration JSON.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
free(config_json);
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the configuration JSON text as it is no longer needed.
|
||||||
|
free(config_json);
|
||||||
|
|
||||||
|
// Get the container pool path.
|
||||||
|
json_object* container_pool;
|
||||||
|
if (!json_object_object_get_ex(root, "container-pool", &container_pool)) {
|
||||||
|
result = failure("Failed to get the container pool path from the configuration JSON.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the container pool path string.
|
||||||
|
const char* container_pool_string = json_object_get_string(container_pool);
|
||||||
|
if (container_pool_string == NULL) {
|
||||||
|
result = failure("Failed to parse the container pool path from the configuration JSON.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the backing pool path.
|
||||||
|
json_object* backing_pool;
|
||||||
|
if (!json_object_object_get_ex(root, "backing-pool", &backing_pool)) {
|
||||||
|
result = failure("Failed to get the backing pool path from the configuration JSON.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the backing pool path string.
|
||||||
|
const char* backing_pool_string = json_object_get_string(backing_pool);
|
||||||
|
if (backing_pool_string == NULL) {
|
||||||
|
result = failure("Failed to parse the backing pool path from the configuration JSON.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the container pool path in the configuration.
|
||||||
|
config->container_pool = strdup(container_pool_string);
|
||||||
|
if (config->container_pool == NULL) {
|
||||||
|
result = failure("Failed to allocate memory for the container pool path.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
verbose("Configuration -> Container pool: %s", config->container_pool);
|
||||||
|
|
||||||
|
// Set the backing pool path in the configuration.
|
||||||
|
config->backing_pool = strdup(backing_pool_string);
|
||||||
|
if (config->backing_pool == NULL) {
|
||||||
|
result = failure("Failed to allocate memory for the backing pool path.");
|
||||||
|
verbose("Exception -> %s", last_error());
|
||||||
|
|
||||||
|
json_object_put(root);
|
||||||
|
free(config->container_pool);
|
||||||
|
free(config);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
verbose("Configuration -> Backing pool: %s", config->backing_pool);
|
||||||
|
|
||||||
|
// Set the configuration if requested.
|
||||||
|
if (_config != NULL)
|
||||||
*_config = config;
|
*_config = config;
|
||||||
|
else
|
||||||
|
free_config(config);
|
||||||
|
|
||||||
|
// Free the configuration JSON.
|
||||||
|
json_object_put(root);
|
||||||
|
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_config(config_t* config) {
|
void free_config(config_t* config) {
|
||||||
free(config->container_pool);
|
free(config->container_pool);
|
||||||
|
free(config->backing_pool);
|
||||||
|
|
||||||
free(config);
|
free(config);
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define CONFIGURATION_FILE "/etc/sandbox.d/config.json"
|
||||||
|
|
||||||
/// @brief Structure used to store the program configuration.
|
/// @brief Structure used to store the program configuration.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/// @brief The path of the directory where the containers are stored.
|
/// @brief The path of the directory where the containers are stored.
|
||||||
char* container_pool;
|
char* container_pool;
|
||||||
|
|
||||||
/// @brief The path of the directory where the backings are stored.
|
/// @brief The path of the directory where the backings are stored.
|
||||||
char* backing_pool;
|
char* backing_pool;
|
||||||
} config_t;
|
} config_t;
|
||||||
|
736
src/container.c
736
src/container.c
File diff suppressed because it is too large
Load Diff
@ -6,82 +6,84 @@
|
|||||||
/// @brief The maximum length of a container identifier.
|
/// @brief The maximum length of a container identifier.
|
||||||
#define MAX_CONTAINER_IDENTIFIER_LENGTH 64
|
#define MAX_CONTAINER_IDENTIFIER_LENGTH 64
|
||||||
|
|
||||||
/// @brief Checks whether the specified container identifier is valid. This call returns a failure if the identifier is invalid.
|
/// @brief Checks whether the specified container identifier is valid. This call will return an error with a message describing the problem if the identifier is invalid.
|
||||||
/// @param container The container identifier to check.
|
/// @param identifier The identifier to check.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t check_container_identifier(const char* container);
|
result_t check_container_identifier(const char* identifier);
|
||||||
|
|
||||||
/// @brief Returns the path of the container pool.
|
/// @brief Checks whether the specified container exists.
|
||||||
/// @param _path The pointer to where the path should be stored. The caller is responsible for freeing the path.
|
/// @param _exists The pointer to where the result should be stored.
|
||||||
|
/// @param config The program configuration to use.
|
||||||
|
/// @param identifier The identifier of the container to check.
|
||||||
|
/// @return The result of the operation.
|
||||||
|
result_t check_container_exists(bool* _exists, const config_t* config, const char* identifier);
|
||||||
|
|
||||||
|
/// @brief Returns the path of the container pool directory.
|
||||||
|
/// @param _path The pointer to where the path should be stored. The caller is responsible for freeing the memory.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t get_container_pool_path(char** _path, const config_t* config);
|
result_t get_container_pool_path(char** _path, const config_t* config);
|
||||||
|
|
||||||
/// @brief Returns the path of the specified container.
|
/// @brief Returns the path of the specified container.
|
||||||
/// @param _path The pointer to where the path should be stored. The caller is responsible for freeing the path.
|
/// @param _path The pointer to where the path should be stored. The caller is responsible for freeing the memory.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to get the path of.
|
/// @param identifier The identifier of the container.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t get_container_path(char** _path, const config_t* config, const char* container);
|
result_t get_container_path(char** _path, const config_t* config, const char* identifier);
|
||||||
|
|
||||||
/// @brief Checks whether the specified container exists. This call returns a failure if the container does not exist.
|
/// @brief Adds a new root container to the pool, with the specified identifier and size.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to check.
|
/// @param identifier The identifier of the container to add.
|
||||||
/// @return Whether the container exists.
|
|
||||||
result_t check_container_exists(const config_t* config, const char* container);
|
|
||||||
|
|
||||||
/// @brief Adds a new root container to the container pool, with the specified identifier and size.
|
|
||||||
/// @param config The program configuration to use.
|
|
||||||
/// @param container The identifier of the container to add.
|
|
||||||
/// @param size The size of the container to add, in bytes.
|
/// @param size The size of the container to add, in bytes.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t add_root_container(const config_t* config, const char* container, uint64_t size);
|
result_t add_root_container(const config_t* config, const char* identifier, size_t size);
|
||||||
|
|
||||||
/// @brief Adds a new backed container to the container pool, with the specified identifier and backing.
|
/// @brief Adds a new backed container to the pool, with the specified identifier and backing.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to add.
|
/// @param identifier The identifier of the container to add.
|
||||||
/// @param backing The identifier of the backing to use.
|
/// @param backing The identifier of the backing to use.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t add_backed_container(const config_t* config, const char* container, const char* backing);
|
result_t add_backed_container(const config_t* config, const char* identifier, const char* backing);
|
||||||
|
|
||||||
/// @brief Removes the specified container from the container pool.
|
/// @brief Removes the specified container from the pool.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to remove.
|
/// @param identifier The identifier of the container to remove.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t remove_container(const config_t* config, const char* container);
|
result_t remove_container(const config_t* config, const char* identifier);
|
||||||
|
|
||||||
/// @brief Resets the specified container to its original state.
|
/// @brief Resets the specified container to its original state.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to reset.
|
/// @param identifier The identifier of the container to reset.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t reset_container(const config_t* config, const char* container);
|
result_t reset_container(const config_t* config, const char* identifier);
|
||||||
|
|
||||||
/// @brief Trims the specified container.
|
/// @brief Trims the specified container.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param container The identifier of the container to trim.
|
/// @param identifier The identifier of the container to trim.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t trim_container(const config_t* config, const char* container);
|
result_t trim_container(const config_t* config, const char* identifier);
|
||||||
|
|
||||||
/// @brief Lists the containers in the container pool, and returns the result in a null-terminated array of strings.
|
/// @brief Lists the containers in the pool.
|
||||||
/// @param _containers The pointer to where the containers array should be stored. The caller is responsible for freeing the containers array as well as the strings in the array.
|
/// @param _identifiers The pointer to where the list of identifiers should be stored. The caller is responsible for freeing the strings and the array.
|
||||||
|
/// @param _count The pointer to where the count of identifiers should be stored.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t list_containers(char*** _containers, const config_t* config);
|
result_t list_containers(char*** _identifiers, size_t* _count, const config_t* config);
|
||||||
|
|
||||||
/// @brief Returns the oldest container in the container pool.
|
/// @brief Returns the available space in the pool.
|
||||||
/// @param _container The pointer to where the container should be stored. The caller is responsible for freeing the container.
|
/// @param _space The pointer to where the available space should be stored, in bytes.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t get_oldest_container(char** _container, const config_t* config);
|
result_t get_container_pool_space(size_t* _space, const config_t* config);
|
||||||
|
|
||||||
/// @brief Calculates the total available space in the container pool.
|
/// @brief Find the oldest container in the pool.
|
||||||
/// @param _size The pointer to where the size should be stored.
|
/// @param _identifier The pointer to where the identifier of the oldest container should be stored.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t get_available_space(uint64_t* _size, const config_t* config);
|
result_t find_oldest_container(char** _identifier, const config_t* config);
|
||||||
|
|
||||||
/// @brief Reserves the specified space in the container pool, by removing the oldest containers.
|
/// @brief Reserves the specified space in the pool by removing the oldest containers.
|
||||||
/// @param config The program configuration to use.
|
/// @param config The program configuration to use.
|
||||||
/// @param size The size to reserve, in bytes.
|
/// @param space The space to reserve, in bytes.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t reserve_space(const config_t* config, uint64_t size);
|
result_t reserve_container_pool_space(const config_t* config, size_t space);
|
336
src/disk.c
336
src/disk.c
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,16 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "container.h"
|
#include "container.h"
|
||||||
#include "backing.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
config_t* config;
|
config_t* config;
|
||||||
result_t result = init_config(&config);
|
result_t result = init_config(&config);
|
||||||
if (result != success()) {
|
if (result != success())
|
||||||
fprintf(stderr, "Failed to initialize the configuration: %s\n", last_error());
|
return -1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_config(config);
|
free_config(config);
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define CONFIGURATION_FILE "/etc/sandbox.d/config.json"
|
#include "utils.h"
|
||||||
#define SYNCRONIZATION_FILE "/etc/sandbox.d/sync"
|
|
||||||
|
int main(int argc, char* argv[]);
|
||||||
|
677
src/utils.c
677
src/utils.c
File diff suppressed because it is too large
Load Diff
15
src/utils.h
15
src/utils.h
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -14,6 +15,9 @@ typedef int result_t;
|
|||||||
/// @brief The error buffer, containing the last error message.
|
/// @brief The error buffer, containing the last error message.
|
||||||
extern char ERROR_BUFFER[];
|
extern char ERROR_BUFFER[];
|
||||||
|
|
||||||
|
/// @brief The verbose mode, which controls whether verbose messages are logged to the console or not.
|
||||||
|
extern bool VERBOSE;
|
||||||
|
|
||||||
/// @brief Returns a result_t representing a successful operation.
|
/// @brief Returns a result_t representing a successful operation.
|
||||||
/// @return The successful result_t.
|
/// @return The successful result_t.
|
||||||
result_t success();
|
result_t success();
|
||||||
@ -28,6 +32,15 @@ result_t failure(const char* format, ...);
|
|||||||
/// @return The last error message.
|
/// @return The last error message.
|
||||||
const char* last_error();
|
const char* last_error();
|
||||||
|
|
||||||
|
/// @brief Logs a message if verbose mode is enabled.
|
||||||
|
/// @param format The format string for the message.
|
||||||
|
/// @param ... The arguments for the format string.
|
||||||
|
void verbose(const char* format, ...);
|
||||||
|
|
||||||
|
/// @brief Enables or disables the verbose mode.
|
||||||
|
/// @param verbose The boolean value to set the verbose mode to.
|
||||||
|
void set_verbose(bool verbose);
|
||||||
|
|
||||||
/// @brief Executes the specified file using the given arguments. The standard output and error streams are captured into buffers, as well as the exit code.
|
/// @brief Executes the specified file using the given arguments. The standard output and error streams are captured into buffers, as well as the exit code.
|
||||||
/// @param _exit_code The pointer to where the exit code should be stored. This output parameter is optional, and can be NULL.
|
/// @param _exit_code The pointer to where the exit code should be stored. This output parameter is optional, and can be NULL.
|
||||||
/// @param _stdout_buffer The pointer to where the standard output buffer should be stored. This output parameter is optional, and can be NULL. The caller is responsible for freeing the buffer.
|
/// @param _stdout_buffer The pointer to where the standard output buffer should be stored. This output parameter is optional, and can be NULL. The caller is responsible for freeing the buffer.
|
||||||
@ -102,7 +115,7 @@ char* directory_name(const char* path);
|
|||||||
/// @param directory The directory to list the files of.
|
/// @param directory The directory to list the files of.
|
||||||
/// @param filter The filter function to use, or NULL to list all files. The filter function should return a success result if the file should be included in the list.
|
/// @param filter The filter function to use, or NULL to list all files. The filter function should return a success result if the file should be included in the list.
|
||||||
/// @return The result of the operation.
|
/// @return The result of the operation.
|
||||||
result_t list_files(char*** _files, const char* directory, result_t (*filter)(const char*));
|
result_t list_files(char*** _files, size_t* _count, const char* directory, result_t (*filter)(const char*));
|
||||||
|
|
||||||
/// @brief Reads the specified file descriptor, and calculates the MD5 hash of the contents.
|
/// @brief Reads the specified file descriptor, and calculates the MD5 hash of the contents.
|
||||||
/// @param _hash The pointer to where the hash should be stored. The caller is responsible for freeing the hash.
|
/// @param _hash The pointer to where the hash should be stored. The caller is responsible for freeing the hash.
|
||||||
|
Loading…
Reference in New Issue
Block a user