2024-02-19 16:01:53 +01:00
# include "container.h"
2024-02-29 10:58:47 +01:00
# include "image.h"
2024-02-19 16:01:53 +01:00
# include "disk.h"
2024-02-28 17:50:27 +01:00
# include <stdio.h>
2024-02-29 09:50:28 +01:00
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
2024-02-28 17:50:27 +01:00
# include <errno.h>
# include <sys/stat.h>
2024-02-29 09:50:28 +01:00
# include <sys/statvfs.h>
result_t check_container_identifier ( const char * identifier ) {
result_t result ;
// Check that the identifier is not null.
if ( identifier = = NULL ) {
result = failure ( " The specified container identifier is null. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
// Check that the identifier is not empty.
size_t length = strlen ( identifier ) ;
if ( length = = 0 ) {
result = failure ( " The specified container identifier is empty. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Check that the identifier is not too long.
if ( length > MAX_CONTAINER_IDENTIFIER_LENGTH ) {
result = failure ( " The specified container identifier is too long (maximum length is %d). " , MAX_CONTAINER_IDENTIFIER_LENGTH ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
return result ;
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Check that the identifier contains only alphanumeric characters and underscores.
2024-02-19 16:01:53 +01:00
for ( size_t i = 0 ; i < length ; i + + ) {
2024-02-29 09:50:28 +01:00
if ( isalnum ( identifier [ i ] ) )
2024-02-19 16:01:53 +01:00
continue ;
2024-02-29 09:50:28 +01:00
if ( ( identifier [ i ] = = ' _ ' | | identifier [ i ] = = ' - ' | | identifier [ i ] = = ' . ' ) & & i > 0 )
2024-02-19 16:01:53 +01:00
continue ;
2024-02-29 09:50:28 +01:00
result = failure ( " The specified container identifier contains an invalid character '%c' at index %zu. " , identifier [ i ] , i ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
2024-02-28 17:50:27 +01:00
}
return success ( ) ;
}
2024-02-29 09:50:28 +01:00
result_t check_container_exists ( bool * _exists , const config_t * config , const char * identifier ) {
result_t result ;
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
// Get the container path.
char * path ;
result = get_container_path ( & path , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-28 17:50:27 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
// Check that the container exists.
struct stat st ;
if ( stat ( path , & st ) = = - 1 ) {
if ( errno = = ENOENT ) {
2024-02-29 10:58:47 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
2024-02-29 10:58:47 +01:00
// The container does not exist.
2024-02-29 09:50:28 +01:00
* _exists = false ;
2024-02-29 10:58:47 +01:00
verbose ( " The container '%s' does not exist. " , identifier ) ;
2024-02-29 09:50:28 +01:00
return success ( ) ;
}
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( path ) ;
2024-02-28 17:50:27 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
free ( path ) ;
// Check that the container is a regular file.
if ( ! S_ISREG ( st . st_mode ) ) {
result = failure ( " The specified container path is not a regular file. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
// The container exists and is a regular file.
* _exists = true ;
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
verbose ( " The container '%s' exists. " , identifier ) ;
2024-02-28 17:50:27 +01:00
2024-02-19 16:01:53 +01:00
return success ( ) ;
}
2024-02-29 09:50:28 +01:00
result_t get_container_pool_path ( char * * _path , const config_t * config ) {
result_t result ;
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Check that the configuration is not null.
if ( config = = NULL ) {
result = failure ( " The specified program configuration is null. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
// Create a copy of the container pool path.
char * path = strdup ( config - > container_pool ) ;
if ( path = = NULL ) {
result = failure ( " Failed to copy the container pool path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
// Set the container pool path.
* _path = path ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
return success ( ) ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
result_t get_container_path ( char * * _path , const config_t * config , const char * identifier ) {
result_t result ;
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Check that the identifier is valid.
result = check_container_identifier ( identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " The specified container identifier is invalid. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Get the container pool path.
char * container_pool ;
result = get_container_pool_path ( & container_pool , config ) ;
2024-02-28 17:50:27 +01:00
if ( result ! = success ( ) ) {
2024-02-29 09:50:28 +01:00
result = failure ( " Failed to get the container pool path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-28 17:50:27 +01:00
return result ;
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Append the identifier to the container pool path.
char * path ;
if ( asprintf ( & path , " %s/%s " , container_pool , identifier ) = = - 1 ) {
result = failure ( " Failed to allocate memory for the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( container_pool ) ;
return result ;
}
// Free the container pool path.
free ( container_pool ) ;
// Set the container path.
* _path = path ;
2024-02-28 17:50:27 +01:00
return success ( ) ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
result_t add_root_container ( const config_t * config , const char * identifier , size_t size ) {
result_t result ;
2024-02-28 17:50:27 +01:00
// Check that the container does not already exist.
2024-02-29 09:50:28 +01:00
bool exists ;
result = check_container_exists ( & exists , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
if ( exists ) {
result = failure ( " The specified container already exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-28 17:50:27 +01:00
2024-02-19 16:01:53 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Get the container path.
char * path ;
result = get_container_path ( & path , config , identifier ) ;
2024-02-19 20:03:30 +01:00
if ( result ! = success ( ) ) {
2024-02-29 09:50:28 +01:00
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 20:03:30 +01:00
return result ;
}
2024-02-29 09:50:28 +01:00
// Create the container disk.
result = create_root_disk ( path , size ) ;
2024-02-19 16:01:53 +01:00
if ( result ! = success ( ) ) {
2024-02-29 09:50:28 +01:00
result = failure ( " Failed to create the container disk. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
2024-02-19 16:01:53 +01:00
return result ;
}
2024-02-28 17:50:27 +01:00
// Free the container path.
2024-02-19 16:01:53 +01:00
free ( path ) ;
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
verbose ( " Successfully added root container '%s' to the container pool, with a size of %zu bytes. " , identifier , size ) ;
2024-02-29 10:58:47 +01:00
return success ( ) ;
}
result_t add_backed_container ( const config_t * config , const char * identifier , const char * image ) {
result_t result ;
// Check that the container does not already exist.
bool exists ;
result = check_container_exists ( & exists , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
if ( exists ) {
result = failure ( " The specified container already exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
// Get the container path.
char * path ;
result = get_container_path ( & path , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
// Get the image path.
char * image_path ;
result = get_image_path ( & image_path , config , image ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the image path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( path ) ;
return result ;
}
// Create the container disk.
result = create_backed_disk ( path , image_path ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to create the container disk. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( image_path ) ;
free ( path ) ;
return result ;
}
// Free the image path.
free ( image_path ) ;
// Free the container path.
free ( path ) ;
verbose ( " Successfully added backed container '%s' to the container pool, backed by the image '%s'. " , identifier , image ) ;
2024-02-29 09:50:28 +01:00
2024-02-28 17:50:27 +01:00
return success ( ) ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
result_t remove_container ( const config_t * config , const char * identifier ) {
result_t result ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
// Check that the container exists.
2024-02-29 09:50:28 +01:00
bool exists ;
result = check_container_exists ( & exists , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
if ( ! exists ) {
result = failure ( " The specified container does not exist. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-28 17:50:27 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
// Get the container path.
2024-02-19 16:01:53 +01:00
char * path ;
2024-02-29 09:50:28 +01:00
result = get_container_path ( & path , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
// Remove the container disk.
if ( remove ( path ) = = - 1 ) {
result = failure ( " Failed to remove the container disk (%s). " , strerror ( errno ) ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
return result ;
2024-02-28 17:50:27 +01:00
}
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
// Free the container path.
2024-02-19 16:01:53 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
verbose ( " Successfully removed the container '%s' from the container pool. " , identifier ) ;
2024-02-19 16:01:53 +01:00
return success ( ) ;
}
2024-02-29 09:50:28 +01:00
result_t reset_container ( const config_t * config , const char * identifier ) {
result_t result ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
// Check that the container exists.
2024-02-29 09:50:28 +01:00
bool exists ;
result = check_container_exists ( & exists , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
if ( ! exists ) {
result = failure ( " The specified container does not exist. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
return result ;
}
// Get the container path.
2024-02-19 16:01:53 +01:00
char * path ;
2024-02-29 09:50:28 +01:00
result = get_container_path ( & path , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 16:01:53 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-19 16:01:53 +01:00
2024-02-29 09:50:28 +01:00
// Reset the container disk.
2024-02-19 16:01:53 +01:00
result = reset_disk ( path ) ;
2024-02-28 17:50:27 +01:00
if ( result ! = success ( ) ) {
2024-02-29 09:50:28 +01:00
result = failure ( " Failed to reset the container disk. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-28 17:50:27 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
2024-02-28 17:50:27 +01:00
return result ;
}
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
// Free the container path.
2024-02-19 16:01:53 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
verbose ( " Successfully reset the container '%s'. " , identifier ) ;
2024-02-28 17:50:27 +01:00
return success ( ) ;
2024-02-19 16:01:53 +01:00
}
2024-02-29 09:50:28 +01:00
result_t trim_container ( const config_t * config , const char * identifier ) {
result_t result ;
2024-02-19 16:01:53 +01:00
2024-02-28 17:50:27 +01:00
// Check that the container exists.
2024-02-29 09:50:28 +01:00
bool exists ;
result = check_container_exists ( & exists , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to check whether the container exists. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 20:23:26 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
if ( ! exists ) {
result = failure ( " The specified container does not exist. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 20:23:26 +01:00
2024-02-29 09:50:28 +01:00
return result ;
}
// Get the container path.
2024-02-19 20:23:26 +01:00
char * path ;
2024-02-29 09:50:28 +01:00
result = get_container_path ( & path , config , identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 20:23:26 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-19 20:23:26 +01:00
2024-02-29 09:50:28 +01:00
// Trim the container disk.
2024-02-28 17:50:27 +01:00
result = trim_disk ( path ) ;
2024-02-19 20:23:26 +01:00
if ( result ! = success ( ) ) {
2024-02-29 09:50:28 +01:00
result = failure ( " Failed to trim the container disk. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-19 20:23:26 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
2024-02-19 20:23:26 +01:00
return result ;
}
2024-02-28 17:50:27 +01:00
// Free the container path.
2024-02-19 20:23:26 +01:00
free ( path ) ;
2024-02-29 09:50:28 +01:00
verbose ( " Successfully trimmed the container '%s'. " , identifier ) ;
2024-02-19 20:23:26 +01:00
return success ( ) ;
}
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
result_t list_containers ( char * * * _identifiers , size_t * _count , const config_t * config ) {
result_t result ;
// Get the container pool path.
char * container_pool ;
result = get_container_pool_path ( & container_pool , config ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container pool path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-20 14:54:04 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
char * * identifiers ;
size_t count ;
result = list_files ( & identifiers , & count , container_pool , check_container_identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to list the containers in the pool. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( container_pool ) ;
return result ;
}
// Free the container pool path.
free ( container_pool ) ;
// Set the list of identifiers.
if ( _identifiers ! = NULL )
* _identifiers = identifiers ;
else {
for ( size_t i = 0 ; i < count ; i + + )
free ( identifiers [ i ] ) ;
free ( identifiers ) ;
}
// Set the count of identifiers.
if ( _count ! = NULL )
* _count = count ;
verbose ( " The container pool contains %zu containers. " , count ) ;
return success ( ) ;
2024-02-20 14:54:04 +01:00
}
2024-02-29 09:50:28 +01:00
result_t get_container_pool_space ( size_t * _space , const config_t * config ) {
result_t result ;
// Get the container pool path.
char * container_pool ;
result = get_container_pool_path ( & container_pool , config ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to get the container pool path. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
// Get the available space in the container pool.
struct statvfs st ;
if ( statvfs ( container_pool , & st ) = = - 1 ) {
result = failure ( " Failed to get the available space in the container pool (%s). " , strerror ( errno ) ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( container_pool ) ;
return result ;
}
// Free the container pool path.
free ( container_pool ) ;
// Set the available space.
* _space = st . f_bsize * st . f_bavail ;
verbose ( " The available space in the container pool is %zu bytes. " , st . f_bsize * st . f_bavail ) ;
return success ( ) ;
}
result_t find_oldest_container ( char * * _identifier , const config_t * config ) {
result_t result ;
2024-02-28 17:50:27 +01:00
// Get the list of containers.
2024-02-29 09:50:28 +01:00
char * * identifiers ;
size_t count ;
result = list_containers ( & identifiers , & count , config ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to find the oldest container due to a failure to list the containers. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-20 14:54:04 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-20 14:54:04 +01:00
2024-02-28 17:50:27 +01:00
// Find the oldest container.
2024-02-20 14:54:04 +01:00
time_t oldest_time = 0 ;
2024-02-29 09:50:28 +01:00
char * oldest_identifier = NULL ;
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
for ( size_t i = 0 ; i < count ; i + + ) {
// Get the container path.
2024-02-20 14:54:04 +01:00
char * path ;
2024-02-29 09:50:28 +01:00
result = get_container_path ( & path , config , identifiers [ i ] ) ;
if ( result ! = success ( ) ) {
verbose ( " Skipping the container '%s' due to an exception. " , identifiers [ i ] ) ;
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
continue ;
}
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
// Get the last access time of the container.
2024-02-20 14:54:04 +01:00
struct stat st ;
2024-02-29 09:50:28 +01:00
if ( stat ( path , & st ) = = - 1 ) {
verbose ( " Skipping the container '%s' due to a failure to get the last access time. " , identifiers [ i ] ) ;
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
free ( path ) ;
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
continue ;
2024-02-20 14:54:04 +01:00
}
2024-02-29 09:50:28 +01:00
// Check if the container is the oldest.
if ( oldest_identifier = = NULL | | st . st_mtime < oldest_time ) {
oldest_time = st . st_mtime ;
oldest_identifier = identifiers [ i ] ;
}
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
// Free the container path.
free ( path ) ;
}
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
// Set the oldest container identifier.
if ( oldest_identifier ! = NULL ) {
oldest_identifier = strdup ( oldest_identifier ) ;
if ( oldest_identifier = = NULL ) {
result = failure ( " Failed to allocate memory for the oldest container identifier. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
for ( size_t i = 0 ; i < count ; i + + )
free ( identifiers [ i ] ) ;
free ( identifiers ) ;
2024-02-20 14:54:04 +01:00
2024-02-29 09:50:28 +01:00
return result ;
}
2024-02-20 14:54:04 +01:00
}
2024-02-29 09:50:28 +01:00
// Free the list of containers.
for ( size_t i = 0 ; i < count ; i + + )
free ( identifiers [ i ] ) ;
free ( identifiers ) ;
verbose ( " The oldest container in the pool is '%s'. " , oldest_identifier ) ;
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
// Set the oldest container identifier.
* _identifier = oldest_identifier ;
2024-02-28 17:50:27 +01:00
2024-02-20 14:54:04 +01:00
return success ( ) ;
}
2024-02-29 09:50:28 +01:00
result_t reserve_container_pool_space ( const config_t * config , size_t space ) {
result_t result ;
2024-02-28 17:50:27 +01:00
for ( ; ; ) {
2024-02-29 09:50:28 +01:00
// Get the available space in the container pool.
size_t available_space ;
result = get_container_pool_space ( & available_space , config ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to reserve the container pool space due to a failure to get the available space. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-20 14:54:04 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
// Check if the available space is sufficient.
if ( available_space > = space ) {
verbose ( " Successfully reserved %zu bytes in the container pool. " , space ) ;
2024-02-20 14:54:04 +01:00
return success ( ) ;
2024-02-29 09:50:28 +01:00
}
verbose ( " Insufficient space in the container pool (Wanted: %zu bytes, Available: %zu bytes). Removing the oldest container. " , space , available_space ) ;
// Find the oldest container.
char * oldest_identifier ;
result = find_oldest_container ( & oldest_identifier , config ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to reserve the container pool space due to a failure to find the oldest container. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
2024-02-20 14:54:04 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
// Check if there are no containers to remove.
if ( oldest_identifier = = NULL ) {
result = failure ( " Insufficient space in the container pool (Wanted: %zu bytes, Available: %zu bytes), and no more containers to remove. " , space , available_space ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
return result ;
}
2024-02-20 14:54:04 +01:00
2024-02-28 17:50:27 +01:00
// Remove the oldest container.
2024-02-29 09:50:28 +01:00
result = remove_container ( config , oldest_identifier ) ;
if ( result ! = success ( ) ) {
result = failure ( " Failed to reserve the container pool space due to a failure to remove the oldest container. " ) ;
verbose ( " Exception -> %s " , last_error ( ) ) ;
free ( oldest_identifier ) ;
2024-02-20 14:54:04 +01:00
return result ;
2024-02-29 09:50:28 +01:00
}
2024-02-28 17:50:27 +01:00
2024-02-29 09:50:28 +01:00
// Free the oldest container identifier.
free ( oldest_identifier ) ;
}
2024-02-20 14:54:04 +01:00
}