Perfected the disk utilities
This commit is contained in:
227
src/backing.c
227
src/backing.c
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user