Perfected the disk utilities

This commit is contained in:
2024-02-15 19:42:22 +01:00
parent e6bc757343
commit 01ea511b2d
10 changed files with 581 additions and 1183 deletions

View File

@@ -1,227 +0,0 @@
#include "backing.h"
#include "utils.h"
#include "sandbox.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
#include <sys/stat.h>
char* get_backings_path(void) {
return format("%s/%s", MASTER_DIRECTORY, BACKINGS_DIRECTORY);
}
bool is_valid_backing_name(const char* name) {
if (name == NULL)
return false;
// Check that the name is not empty
size_t length = strlen(name);
if (length == 0)
return false;
// Check that the name starts with a number, corresponding to the timestamp of the backing disk creation
size_t timestamp_length = 0;
for (size_t i = 0; i < length; i++)
if (name[i] >= '0' && name[i] <= '9')
timestamp_length++;
else
break;
if (timestamp_length == 0)
return false;
return true;
}
char* get_backing_path(const char* backing) {
char* backings_path = get_backings_path();
if (backings_path == NULL)
return NULL;
// Combine the backings path with the backing name
char* backing_path = format("%s/%s", backings_path, backing);
// Free the backings path
free(backings_path);
return backing_path;
}
bool backing_exists(const char* backing) {
char* backing_path = get_backing_path(backing);
if (backing_path == NULL)
return false;
// Check if the backing path exists
struct stat statbuf;
int result = stat(backing_path, &statbuf);
// Free the backing path
free(backing_path);
if (result != 0)
return false;
if (!S_ISREG(statbuf.st_mode))
return false;
return true;
}
char** list_backings(void) {
char* path = get_backings_path();
if (path == NULL)
return NULL;
// Open the directory
DIR* dir = opendir(path);
if (dir == NULL) {
log_msg(LOG_ERROR, "Failed to open directory '%s' (%s).", path, strerror(errno));
free(path);
return NULL;
}
free(path);
// Count the number of entries
size_t count = 0;
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
if (is_valid_backing_name(entry->d_name) && backing_exists(entry->d_name))
count++;
// Allocate the array of strings
char** backings = malloc((count + 1) * sizeof(char*));
if (backings == NULL) {
log_msg(LOG_ERROR, "Failed to allocate memory for the backings array.");
closedir(dir);
return NULL;
}
// Fill the array of strings
rewinddir(dir);
size_t index = 0;
while ((entry = readdir(dir)) != NULL) {
if (is_valid_backing_name(entry->d_name) && backing_exists(entry->d_name)) {
backings[index] = strdup(entry->d_name);
if (backings[index] == NULL) {
log_msg(LOG_ERROR, "Failed to allocate memory for the backing name.");
for (size_t i = 0; i < index; i++)
free(backings[i]);
free(backings);
closedir(dir);
return NULL;
}
index++;
}
}
// Terminate the array of strings
backings[count] = NULL;
// Close the directory
closedir(dir);
return backings;
}
uint64_t get_backing_creation_time(const char* backing) {
size_t length = strlen(backing);
size_t timestamp_length = 0;
// Find the length of the timestamp
for (size_t i = 0; i < length; i++)
if (backing[i] >= '0' && backing[i] <= '9')
timestamp_length++;
else
break;
// Extract the timestamp
char* timestamp = strndup(backing, timestamp_length);
if (timestamp == NULL)
return 0;
// Convert the timestamp to a number
uint64_t creation_time = strtoull(timestamp, NULL, 10);
// Free the timestamp
free(timestamp);
return creation_time;
}
char* find_latest_backing(void) {
char** backings = list_backings();
if (backings == NULL)
return NULL;
// Find the latest backing disk
char* latest_backing = NULL;
uint64_t latest_time = 0;
for (size_t i = 0; backings[i] != NULL; i++) {
uint64_t time = get_backing_creation_time(backings[i]);
if (time >= latest_time) {
latest_time = time;
latest_backing = backings[i];
}
}
// Duplicate the latest backing disk
if (latest_backing != NULL)
latest_backing = strdup(latest_backing);
// Free the backings
for (size_t i = 0; backings[i] != NULL; i++)
free(backings[i]);
free(backings);
return latest_backing;
}
bool create_backing(const char* disk, const char* description) {
// Create the backing disk name
uint64_t timestamp = (uint64_t)time(NULL);
char* backing_name = NULL;
if (description == NULL || strlen(description) == 0)
backing_name = format("%lu", timestamp);
else
backing_name = format("%lu-%s", timestamp, description);
if (backing_name == NULL) {
log_msg(LOG_ERROR, "Failed to create the backing disk name.");
return false;
}
// Create the backing disk path
char* backings_path = get_backings_path();
if (backings_path == NULL) {
free(backing_name);
return false;
}
char* backing_path = format("%s/%s", backings_path, backing_name);
free(backing_name);
free(backings_path);
if (backing_path == NULL)
return false;
// Copy the disk to the backing disk
if (!copy_file(disk, backing_path, 0755, 0, 0)) {
free(backing_path);
return false;
}
// Free the backing disk path
free(backing_path);
return true;
}