diff --git a/src/entry.c b/src/entry.c index 63c5276..c46e858 100644 --- a/src/entry.c +++ b/src/entry.c @@ -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)); diff --git a/src/sandbox.c b/src/sandbox.c index f68e6d3..1b6a6e2 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -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; } diff --git a/src/utils.c b/src/utils.c index 944c9f6..8951117 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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; +} diff --git a/src/utils.h b/src/utils.h index ab55e7f..a0c10c9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -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); \ No newline at end of file