Implemented the add-entry command

This commit is contained in:
Alexei KADIR 2024-02-17 14:38:52 +01:00
parent 8821519a12
commit f0dd2ca5fb
4 changed files with 162 additions and 1 deletions

View File

@ -199,6 +199,18 @@ Result add_root_entry(const char* entry_id, uint64_t size) {
return SUCCESS;
}
Result add_backed_entry(const char* entry_id, const char* backing_id) {
// TODO: Implement
return FAILURE;
}
Result add_automatic_entry(const char* entry_id) {
// TODO: Implement
return FAILURE;
}
Result remove_entry(const char* entry_id) {
// Check that it exists
bool exists;
@ -217,6 +229,48 @@ Result remove_entry(const char* entry_id) {
if (result != SUCCESS)
return result;
// Remove all the files in the directory
DIR* dir = opendir(entry_path);
if (dir == NULL) {
log_message(LOG_LEVEL_ERROR, "Failed to open the directory '%s' (%s).", entry_path, strerror(errno));
free(entry_path);
return FAILURE;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
// Skip the current and parent directories
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
// Get the path of the file
char* file_path;
result = format(&file_path, "%s/%s", entry_path, entry->d_name);
if (result != SUCCESS) {
closedir(dir);
free(entry_path);
return result;
}
// Remove the file
if (unlink(file_path) == -1) {
log_message(LOG_LEVEL_ERROR, "Failed to remove the file '%s' (%s).", file_path, strerror(errno));
free(file_path);
closedir(dir);
free(entry_path);
return FAILURE;
}
// Free the entry file path
free(file_path);
}
// Close the directory
closedir(dir);
// Remove the directory
if (rmdir(entry_path) == -1) {
log_message(LOG_LEVEL_ERROR, "Failed to remove the directory '%s' (%s).", entry_path, strerror(errno));

View File

@ -119,7 +119,71 @@ int command_version(int argc, char* argv[]) {
}
int command_add_entry(int argc, char* argv[]) {
// TODO: Call add_root_entry or add_backed_entry depending on the options
// Extract the primary arguments
if (argc < 1) {
log_message(LOG_LEVEL_ERROR, "Missing entry id.");
return EXIT_FAILURE;
}
const char* entry_id = argv[0];
// Extract the options
bool is_root = false;
uint64_t size = 0;
bool is_backed = false;
const char* backing_id = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--root") == 0 || strcmp(argv[i], "-r") == 0) {
if (is_backed) {
log_message(LOG_LEVEL_ERROR, "Cannot specify both --root and --backed options.");
return EXIT_FAILURE;
}
is_root = true;
if (i + 1 >= argc) {
log_message(LOG_LEVEL_ERROR, "Missing size for root entry.");
return EXIT_FAILURE;
}
Result result = parse_size(argv[i + 1], &size);
if (result != SUCCESS)
return EXIT_FAILURE;
i++; // Consume the next argument
} else if (strcmp(argv[i], "--backed") == 0 || strcmp(argv[i], "-b") == 0) {
if (is_root) {
log_message(LOG_LEVEL_ERROR, "Cannot specify both --root and --backed options.");
return EXIT_FAILURE;
}
is_backed = true;
if (i + 1 >= argc) {
log_message(LOG_LEVEL_ERROR, "Missing backing id for backed entry.");
return EXIT_FAILURE;
}
backing_id = argv[i + 1];
i++; // Consume the next argument
} else {
log_message(LOG_LEVEL_ERROR, "Unknown option '%s'.", argv[i]);
return EXIT_FAILURE;
}
}
Result result;
if (is_root)
result = add_root_entry(entry_id, size);
else if (is_backed)
result = add_backed_entry(entry_id, backing_id);
else
result = add_automatic_entry(entry_id);
if (result != SUCCESS)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

View File

@ -427,3 +427,40 @@ Result format_size(uint64_t size, char** out_string) {
// Format the string
return format(out_string, "%.2f%s", value, unit);
}
Result parse_size(const char* string, uint64_t* out_size) {
// Parse the size
char* endptr;
uint64_t size = strtoull(string, &endptr, 10);
if (endptr == string) {
log_message(LOG_LEVEL_ERROR, "Failed to parse the size '%s'.", string);
return FAILURE;
}
// Determine the unit
if (*endptr == '\0') {
// No unit
*out_size = size;
} else if (strcmp(endptr, "K") == 0 || strcmp(endptr, "KB") == 0 || strcmp(endptr, "KiB") == 0) {
// Kilobytes
*out_size = size * 1024;
} else if (strcmp(endptr, "M") == 0 || strcmp(endptr, "MB") == 0 || strcmp(endptr, "MiB") == 0) {
// Megabytes
*out_size = size * 1024 * 1024;
} else if (strcmp(endptr, "G") == 0 || strcmp(endptr, "GB") == 0 || strcmp(endptr, "GiB") == 0) {
// Gigabytes
*out_size = size * 1024 * 1024 * 1024;
} else if (strcmp(endptr, "T") == 0 || strcmp(endptr, "TB") == 0 || strcmp(endptr, "TiB") == 0) {
// Terabytes
*out_size = size * 1024 * 1024 * 1024 * 1024;
} else if (strcmp(endptr, "P") == 0 || strcmp(endptr, "PB") == 0 || strcmp(endptr, "PiB") == 0) {
// Petabytes
*out_size = size * 1024 * 1024 * 1024 * 1024 * 1024;
} else {
log_message(LOG_LEVEL_ERROR, "Unknown unit '%s'.", endptr);
return FAILURE;
}
return SUCCESS;
}

View File

@ -82,3 +82,9 @@ Result copy_file(const char* src_path, const char* dst_path, mode_t mode);
/// @param out_string The pointer to the output string. The caller is responsible for freeing the memory.
/// @return The result of the operation.
Result format_size(uint64_t size, char** out_string);
/// @brief Parses a size from a human-readable string.
/// @param string The string to parse.
/// @param out_size The pointer to the output size.
/// @return The result of the operation.
Result parse_size(const char* string, uint64_t* out_size);