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,256 +0,0 @@
#include "entry.h"
#include "sandbox.h"
#include "utils.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <dirent.h>
char* get_entries_path(void) {
return format("%s/%s", MASTER_DIRECTORY, ENTRIES_DIRECTORY);
}
bool is_valid_entry_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 does not contain /
for (size_t i = 0; i < length; i++)
if (name[i] == '/')
return false;
// Check that the name is not . or ..
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
return false;
return true;
}
char* get_entry_path(const char* entry) {
char* entries_path = get_entries_path();
if (entries_path == NULL)
return NULL;
// Combine the entries path with the entry name
char* entry_path = format("%s/%s", entries_path, entry);
// Free the entries path
free(entries_path);
return entry_path;
}
bool entry_exists(const char* entry) {
char* entry_path = get_entry_path(entry);
if (entry_path == NULL)
return false;
// Check if the entry path exists
struct stat statbuf;
int result = stat(entry_path, &statbuf);
// Free the entry path
free(entry_path);
if (result != 0)
return false;
if (!S_ISDIR(statbuf.st_mode))
return false;
return true;
}
char* get_entry_disk_path(const char* entry) {
char* entry_path = get_entry_path(entry);
if (entry_path == NULL)
return NULL;
// Combine the entry path with the disk name
char* disk_path = format("%s/%s", entry_path, DISK_PATH);
// Free the entry path
free(entry_path);
return disk_path;
}
char** list_entries(void) {
char* path = get_entries_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_entry_name(entry->d_name) && entry_exists(entry->d_name))
count++;
// Allocate the array of entries
char** entries = malloc((count + 1) * sizeof(char*));
if (entries == NULL) {
log_msg(LOG_ERROR, "Failed to allocate memory for the entries array.");
closedir(dir);
return NULL;
}
// Fill the array of entries
rewinddir(dir);
size_t index = 0;
while ((entry = readdir(dir)) != NULL) {
if (is_valid_entry_name(entry->d_name) && entry_exists(entry->d_name)) {
entries[index] = strdup(entry->d_name);
if (entries[index] == NULL) {
log_msg(LOG_ERROR, "Failed to allocate memory for the entry name.");
for (size_t i = 0; i < index; i++)
free(entries[i]);
free(entries);
closedir(dir);
return NULL;
}
index++;
}
}
// Terminate the array of entries
entries[count] = NULL;
// Close the directory
closedir(dir);
return entries;
}
uint64_t get_entry_last_access(const char* entry) {
char* disk = get_entry_disk_path(entry);
if (disk == NULL)
return 0;
// Get the last access time of the disk
struct stat statbuf;
int result = stat(disk, &statbuf);
// Free the disk path
free(disk);
if (result != 0)
return 0;
return statbuf.st_atime;
}
char* find_oldest_entry(void) {
char** entries = list_entries();
if (entries == NULL)
return NULL;
// Find the oldest entry
char* oldest_entry = NULL;
uint64_t oldest_time = UINT64_MAX;
for (size_t i = 0; entries[i] != NULL; i++) {
uint64_t time = get_entry_last_access(entries[i]);
if (time <= oldest_time) {
oldest_time = time;
oldest_entry = entries[i];
}
}
// Duplicate the oldest entry
if (oldest_entry != NULL)
oldest_entry = strdup(oldest_entry);
// Free the entries
for (size_t i = 0; entries[i] != NULL; i++)
free(entries[i]);
free(entries);
return oldest_entry;
}
bool create_entry(const char* entry) {
char* entry_path = get_entry_path(entry);
if (entry_path == NULL)
return false;
// Create the entry directory
bool result = create_directory(entry_path, 0700, 0, 0);
// Free the entry path
free(entry_path);
return result;
}
bool delete_entry(const char* entry) {
char* entry_path = get_entry_path(entry);
if (entry_path == NULL)
return false;
// Delete the entry directory
bool result = delete_directory(entry_path, 0);
// Free the entry path
free(entry_path);
return result;
}
uint64_t get_available_space(void) {
char* entries_path = get_entries_path();
if (entries_path == NULL)
return 0;
// Get the available space in the entries directory
struct statvfs statbuf;
int result = statvfs(entries_path, &statbuf);
// Free the entries path
free(entries_path);
if (result != 0)
return -1;
return statbuf.f_bsize * statbuf.f_bavail;
}
bool reserve_space(uint64_t space) {
// While the available space is not enough, delete the oldest entry
while (get_available_space() < space) {
char* oldest_entry = find_oldest_entry();
if (oldest_entry == NULL)
return false;
bool result = delete_entry(oldest_entry);
free(oldest_entry);
if (!result)
return false;
}
return true;
}