diff --git a/CMakeLists.txt b/CMakeLists.txt index cdabe76..137286e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(File_Sorter_Core C) set(CMAKE_C_STANDARD 99) -add_executable(file-sorter main.c tools/logger.c tools/include/log/logger.h tools/config_parser.c tools/include/config/config_parser.h src/manager.c src/include/manager.h) +add_executable(file-sorter main.c tools/logger.c tools/include/log/logger.h tools/config_parser.c tools/include/config/config_parser.h src/manager.c src/include/manager.h tools/include/mem.h) include_directories( src/include @@ -12,47 +12,38 @@ include_directories( set(GCC_COVERAGE_COMPILE_FLAGS "-pthread") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") file(MAKE_DIRECTORY /home/$ENV{USER}/.local/share/file_sorter/) -message("/home/$ENV{USER}/.local/share/file_sorter/ OK") + file(MAKE_DIRECTORY /home/$ENV{USER}/.local/share/file_sorter/config/) -message("/home/$ENV{USER}/.local/share/file_sorter/config/ OK") file(MAKE_DIRECTORY /home/$ENV{USER}/default_sorter_path/) -message("/home/$ENV{USER}/default_sorter_path/ OK") file(MAKE_DIRECTORY config/) -message("config/ OK") file(MAKE_DIRECTORY service/) -message("service/ OK") file(MAKE_DIRECTORY autostart/) -message("autostart/ OK") if (EXISTS /home/$ENV{USER}/.config/systemd/) - message("/home/$ENV{USER}/.config/systemd/ OK") if (EXISTS /home/$ENV{USER}/.config/systemd/user/) - message("/home/$ENV{USER}/.config/systemd/user/ OK") - else() + else () file(MAKE_DIRECTORY /home/$ENV{USER}/.config/systemd/user/) - message("/home/$ENV{USER}/.config/systemd/user/ OK") - endif() -else() + endif () +else () file(MAKE_DIRECTORY /home/$ENV{USER}/.config/systemd/) - message("/home/$ENV{USER}/.config/systemd/ OK") file(MAKE_DIRECTORY /home/$ENV{USER}/.config/systemd/user/) - message("/home/$ENV{USER}/.config/systemd/user/ OK") -endif() +endif () file(WRITE config/config.conf [basic_config]\n - checkInterval\ 3000\n - parseInterval\ 5000\n - debugLog\ 0\n - defaultDirPath\ /home/$ENV{USER}/default_sorter_path/\n + check_interval\ 3000\n + parse_interval\ 5000\n + debug_log\ 0\n + default_dir_path\ /home/$ENV{USER}/default_sorter_path/\n + enable_default_path\ 1\n \n [check]\n \n diff --git a/README.md b/README.md index d2d9bda..09a8825 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ # Introduction -This program transfers all files outside of folders -to the specific folders to which they belong. +This program transfers all files outside of folders to the specific folders to which they belong. # Download & Build -First download the program from github and go to the File-Sorter-Core folder. + +First download the program from GitHub and go to the File-Sorter-Core folder. + ``` % git clone https://github.com/rounnus/File-Sorter-Core.git % cd File-Sorter-Core/ ``` -After installation the program must be built. In order to build the program, the following instructions must be followed.
+ +After installation the program must be built. In order to build the program, the following instructions must be +followed.
+ ``` % mkdir build % cd build/ @@ -17,17 +21,19 @@ After installation the program must be built. In order to build the program, the % make % sudo make install ``` + After this the program will be installed and ready to run. # Config -The program gets the information it needs from a config file, which is like the following + +The program gets the information it needs from a config file, which is like the following ``` [basic_config] -checkInterval 3000 -parseInterval 5000 -debugLog 0 -defaultDirPath /home/username/default_sorter_path/ +check_interval 3000 +parse_interval 5000 +debug_log 0 +default_dir_path /home/username/default_sorter_path/ [check] @@ -37,18 +43,21 @@ defaultDirPath /home/username/default_sorter_path/ [done_targets] ``` + The information is as follows.
Field | Description ---------|-------------- -`checkInterval` | The time between checks (for new files etc). -`parseInterval` | The time to read the config file again for any changes. -`debugLog` | For debugging. To enter debug mode, the value of the debugLog field must be changed to 1. -`defaultDirPath` | If a file is found outside of a folder and no specific location has been specified to which it should be moved, then it will go to defaultDirPath. +`check_interval` | The time between checks (for new files etc). +`parse_interval` | The time to read the config file again for any changes. +`debug_log` | For debugging. To enter debug mode, the value of the debugLog field must be changed to 1. +`default_dir_path` | If a file is found outside of a folder and no specific location has been specified to which it should be moved, then it will go to default_dir_path. +`enable_default_path` | If this option is enabled, no files are transferred to the default folder. `[check]` | This field includes all locations where the program will look for files. Each location that enters this field must be entered before `[done_check]`. `[targets]` | This field contains all the file extensions and all the locations that these files should be sent to. Each line in this field consists of two elements that are separated by a space. The first element is the extension of the file and the second is the location where this file should be sent. Also each new line must be entered before `[done_targets]`. An example of `[check]`:
+ ``` [check] /home/username/ @@ -56,7 +65,9 @@ An example of `[check]`:
... [done_check] ``` + An example of `[targets]`:
+ ``` [targets] .py /home/username/Documents/py/ @@ -64,8 +75,11 @@ An example of `[targets]`:
... [done_targets] ``` -In the example above the first part consists of the extensions `.py` and `.cpp` and the second part of the locations `/home/username/ Documents/py/` and `/home/username/Documents/cpp/`. + +In the example above the first part consists of the extensions `.py` and `.cpp` and the second part of the +locations `/home/username/ Documents/py/` and `/home/username/Documents/cpp/`. # Service + The program can be run using `systemd`. To start the program from `systemd` the following must be performed.
``` systemctl --user start file-sorter``` diff --git a/config/config.conf b/config/config.conf index 3b9aaf9..0abfd96 100644 --- a/config/config.conf +++ b/config/config.conf @@ -1,8 +1,9 @@ [basic_config] -checkInterval 3000 -parseInterval 5000 -debugLog 0 -defaultDirPath /home/rounnus/default_sorter_path/ +check_interval 3000 +parse_interval 5000 +debug_log 0 +default_dir_path /home/rounnus/default_sorter_path/ +enable_default_path 1 [check] diff --git a/main.c b/main.c index 81d8af1..9664787 100644 --- a/main.c +++ b/main.c @@ -2,7 +2,6 @@ int main() { - run(); return 0; } \ No newline at end of file diff --git a/src/manager.c b/src/manager.c index 60cd382..9b9cc79 100644 --- a/src/manager.c +++ b/src/manager.c @@ -10,6 +10,7 @@ #include #include #include +#include #define TRUE 1 @@ -26,195 +27,189 @@ #define INITIAL_CHECK_WAIT 5 -_Noreturn void *parse(void *arg); - -_Noreturn void *move_to_dir(void *arg); - -void check_move_file(char *filepath, char *file); - -char *extract_file_extension_from_target(char *target, size_t *extension_len); - -char *extract_path_from_target(char *target, char *filename); - -struct config *conf; +static struct config *conf = NULL; pthread_mutex_t lock; -void run() { - conf = calloc(1, sizeof(struct config)); - pthread_t move_to_dir_thread; - pthread_t parse_thread; - - if (pthread_mutex_init(&lock, NULL) != 0) make_log(FAILED_TO_INITIALIZE_MUTEX, strerror(errno), DEBUG_LOG, WARN); - - if (pthread_create(&parse_thread, NULL, parse, NULL) != 0) - make_log(FAILED_TO_CREATE_THREAD, strerror(errno), DEBUG_LOG, WARN); - if (pthread_create(&move_to_dir_thread, NULL, move_to_dir, NULL) != 0) - make_log(FAILED_TO_CREATE_THREAD, strerror(errno), DEBUG_LOG, WARN); - - pthread_join(parse_thread, NULL); - pthread_join(move_to_dir_thread, NULL); - pthread_mutex_destroy(&lock); -} - _Noreturn void *parse(void *arg) { int interval; - while (TRUE) { + while(TRUE) { + // Lock the mutex. pthread_mutex_lock(&lock); + // Clear the config. conf = clear_config(conf); - if (get_config(conf) == -1) make_log(PARSER_FAILED, NULL, NORMAL_LOG, WARN); + // Get the config. + if (get_config(conf) == -1) + make_log(PARSER_FAILED, NULL, NORMAL_LOG, WARN); + // Check if interval parser exists. if (conf->c_parse_interval == NULL) { sleep(DEFAULT_PARSE_INTERVAL); if (*(conf->c_debug_log) == 1) make_log(PARSE_INTERVAL_NOT_FOUND, NULL, DEBUG_LOG, WARN); - continue; } + // save the interval. interval = *(conf->c_parse_interval); pthread_mutex_unlock(&lock); - + // sleep. sleep(interval); } } - -_Noreturn void *move_to_dir(void *arg) { - sleep(INITIAL_CHECK_WAIT); // wait to make the first parse. - struct dirent *files = NULL; - char *curr_dir = NULL; +static inline char *extract_path_from_target(const char *target) { char *path = NULL; - int interval; - size_t tmp_len; - DIR *dir = NULL; + char tmp[strlen(target) + 1]; + strcpy(tmp, target); - while (TRUE) { - pthread_mutex_lock(&lock); + size_t path_s = strlen(strchr(tmp, '/')); + ALLOCATE_MEM(path, path_s + 1, sizeof(char)); + strcpy(path, strchr(tmp, '/')); - for (int curr_check = 0; curr_check < conf->c_check_number; curr_check++) { - curr_dir = conf->c_check[curr_check]; - dir = opendir(curr_dir); + return path; +} - if (dir == NULL) { - if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_OPEN_DIR, strerror(errno), DEBUG_LOG, ERROR); - continue; - } +static inline char *extract_extension_from_target(const char *target, size_t *ext_s) { + char *extension = NULL; + char tmp[strlen(target) + 1]; - while ((files = readdir(dir)) != NULL) { + // Make a copy of the target. + strcpy(tmp, target); + strtok(tmp, " "); - if (files->d_type == DT_REG && files->d_name[0] != '.') { - tmp_len = strlen(curr_dir) + strlen(files->d_name) + 1; - path = calloc(tmp_len, sizeof(char)); - strncpy(path, curr_dir, tmp_len); - strcat(path, files->d_name); - check_move_file(path, files->d_name); - free(path); - } - } - closedir(dir); - } - interval = *(conf->c_check_interval); - pthread_mutex_unlock(&lock); + // Allocate the space. + size_t extension_s = strlen(tmp); + ALLOCATE_MEM(extension, extension_s + 1, sizeof(char)); + // Copy the extension. + strcpy(extension, tmp); - sleep(interval); - } + *ext_s = extension_s; + return extension; } -void check_move_file(char *filepath, char *file) { - char *curr_ext = NULL; - char *check_ext = NULL; +static inline void move_to_default_path(const char *file_path, const char *file) { + size_t move_file_to_s = strlen(conf->c_default_dir_path) + strlen(file); char *move_file_to = NULL; - size_t tmp_len; + ALLOCATE_MEM(move_file_to, move_file_to_s + 1, sizeof(char)); + strcpy(move_file_to, conf->c_default_dir_path); + strcat(move_file_to, file); + if (rename(file_path, move_file_to) != 0) + if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_MOVE_FILE, strerror(errno), DEBUG_LOG, ERROR); - if (conf->c_target_number == 0) { - tmp_len = strlen(conf->c_default_dir_path) + strlen(file) + 1; - move_file_to = calloc(tmp_len, sizeof(char)); - strncpy(move_file_to, conf->c_default_dir_path, tmp_len); - strcat(move_file_to, file); + free(move_file_to); + make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); +} - if (rename(filepath, move_file_to) != 0) - if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_MOVE_FILE, strerror(errno), DEBUG_LOG, ERROR); +static void move_file(const char *file_path, const char *file_name) { + char *move_file_to = NULL; + char *curr_ext = NULL; + char *check_ext = NULL; + char *curr_path = NULL; + size_t move_file_to_s; + size_t curr_ext_s; - free(move_file_to); - make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); + if (conf->c_enable_default_path == NULL) { + move_to_default_path(file_path, file_name); return; } - for (int target = 0; target < conf->c_target_number; target++) { - curr_ext = extract_file_extension_from_target(conf->c_targets_path[target], &tmp_len); + if (!conf->c_targets_s && conf->c_enable_default_path) { + move_to_default_path(file_path, file_name); + return; + } - check_ext = strstr(file, curr_ext); + if (!conf->c_targets_s) return; - if (target+1 == conf->c_target_number && check_ext == NULL || check_ext[tmp_len] != '\0' && target + 1 == conf->c_target_number) { - tmp_len = strlen(conf->c_default_dir_path) + strlen(file) + 1; - move_file_to = calloc(tmp_len, sizeof(char)); - strncpy(move_file_to, conf->c_default_dir_path, tmp_len); - strcat(move_file_to, file); - - if (rename(filepath, move_file_to) != 0) { - if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_MOVE_FILE, strerror(errno), DEBUG_LOG, ERROR); - free(curr_ext); - free(move_file_to); - return; - } + for (int target = 0; target < conf->c_targets_s; target++) { + curr_ext = extract_extension_from_target(conf->c_targets[target], &curr_ext_s); + check_ext = strstr(file_name, curr_ext); + if (target + 1 == conf->c_targets_s && check_ext == NULL || + check_ext[curr_ext_s] != '\0' && target + 1 == conf->c_targets_s) { + move_to_default_path(file_path, file_name); free(curr_ext); - free(move_file_to); - make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); - return; } - else if (check_ext[tmp_len] != '\0') { + else if (check_ext[curr_ext_s] != '\0') { free(curr_ext); continue; } - move_file_to = extract_path_from_target(conf->c_targets_path[target], file); - // insert the file into the path as destination name. - strcat(move_file_to, file); + curr_path = extract_path_from_target(conf->c_targets[target]); + move_file_to_s = strlen(curr_path) + strlen(file_name); + ALLOCATE_MEM(move_file_to, move_file_to_s + 1, sizeof(char)); + strcpy(move_file_to, curr_path); + strcat(move_file_to, file_name); - if (rename(filepath, move_file_to) != 0) { + if (rename(file_path, move_file_to) != 0) { if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_MOVE_FILE, strerror(errno), DEBUG_LOG, ERROR); free(curr_ext); + free(curr_path); free(move_file_to); return; } + free(curr_ext); free(move_file_to); + free(curr_path); make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); return; } } -char *extract_file_extension_from_target(char *target, size_t *extension_len) { - char *extension = NULL; - char *tmp = NULL; - char *splitter = " "; - size_t target_len = strlen(target) + 1; +_Noreturn void *move_to_dir(void *arg) { + sleep(INITIAL_CHECK_WAIT); // wait to make the first parse. + char *curr_dir = NULL; + char *path = NULL; + size_t path_s; + struct dirent *files = NULL; + DIR *dir = NULL; + int interval; + + while (TRUE) { + pthread_mutex_lock(&lock); - tmp = calloc(target_len, sizeof(char)); - strncpy(tmp, target, target_len); - strtok(tmp, splitter); + for (int curr_check = 0; curr_check < conf->c_checks_s; curr_check++) { + curr_dir = conf->c_checks[curr_check]; + dir = opendir(curr_dir); - target_len = strlen(tmp); - *extension_len = target_len; - extension = calloc(target_len + 1, sizeof(char)); - strncpy(extension, tmp, target_len); + if (dir == NULL) { + if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_OPEN_DIR, strerror(errno), DEBUG_LOG, ERROR); + continue; + } - free(tmp); - return extension; + while ((files = readdir(dir)) != NULL) { + if (files->d_type == DT_REG && files->d_name[0] != '.') { + path_s = strlen(curr_dir) + strlen(files->d_name); + ALLOCATE_MEM(path, path_s + 1, sizeof(char)); + strcpy(path, curr_dir); + strcat(path, files->d_name); + move_file(path, files->d_name); + free(path); + } + } + closedir(dir); + } + + interval = *(conf->c_check_interval); + pthread_mutex_unlock(&lock); + sleep(interval); + } } -char *extract_path_from_target(char *target, char *filename) { - char *path = NULL; - char *tmp = NULL; - size_t target_len = strlen(target) + 1; - tmp = calloc(target_len, sizeof(char)); - strncpy(tmp, target, target_len); +void run() { + ALLOCATE_MEM(conf, 1, sizeof(struct config)); - target_len = strlen(strchr(tmp, '/')) + strlen(filename) + 1; - path = calloc(target_len, sizeof(char)); - strncpy(path, strchr(tmp, '/'), target_len); + pthread_t move_to_dir_thread; + pthread_t parse_thread; - free(tmp); - return path; + if (pthread_mutex_init(&lock, NULL) != 0) make_log(FAILED_TO_INITIALIZE_MUTEX, strerror(errno), DEBUG_LOG, WARN); + + if (pthread_create(&parse_thread, NULL, parse, NULL) != 0) + make_log(FAILED_TO_CREATE_THREAD, strerror(errno), DEBUG_LOG, WARN); + if (pthread_create(&move_to_dir_thread, NULL, move_to_dir, NULL) != 0) + make_log(FAILED_TO_CREATE_THREAD, strerror(errno), DEBUG_LOG, WARN); + + pthread_join(parse_thread, NULL); + pthread_join(move_to_dir_thread, NULL); + pthread_mutex_destroy(&lock); } \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index 16b7268..7e747d3 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -8,192 +8,177 @@ #include #include +#include -#define CONFIG_PATH "/.local/share/file_sorter/config/config.conf" +#define CONFIG_REL_PATH "/.local/share/file_sorter/config/config.conf" -#define CHECK_INTERVAL "checkInterval" -#define PARSE_INTERVAL "parseInterval" -#define DEBUG "debugLog" -#define DEFAULT_DIR_PATH "defaultDirPath" -#define TARGETS "[targets]" -#define CHECK "[check]" +#define CHECK_INTERVAL "check_interval" +#define PARSE_INTERVAL "parse_interval" +#define DEBUG "debug_log" +#define DEFAULT_DIR_PATH "default_dir_path" +#define TARGETS "[targets]" +#define CHECK "[check]" +#define ENABLE_DEFAULT_PATH "enable_default_path" -#define SUCCESS_MESSAGE "Successfully parse " -#define SUCCESS_LOAD "Successfully load config" +#define DONE_TARGETS "[done_targets]" +#define DONE_CHECK "[done_check]" -#define ERROR_MESSAGE "Failed to parse " -#define PARSE_FAILED_EMPTY "The value is empty" -#define PARSE_FAILED_NOTHING "There is no value" -#define PARSE_FAILED_NO_FIELD "There is no such field" +#define SUCCESS_PARSE "Successfully parse" +#define SUCCESS_LOAD "Successfully load config" -#define FAILED_TO_OPEN "Failed to open config file" -#define FAILED_TO_READ_SIZE "Failed to read config size" -#define FAILED_TO_READ "Failed to read config file" -#define FAILED_TO_CLOSE "Failed to close config file" +#define PARSE_FAILED_EMPTY "The value is empty" +#define PARSE_FAILED_NO_FIELD "There is no such field" +#define FAILED_TO_OPEN "Failed to open config file" +#define FAILED_TO_READ_SIZE "Failed to read config size" +#define FAILED_TO_READ "Failed to read config file" +#define FAILED_TO_CLOSE "Failed to close config file" +#define FAILED_TO_PARSE "Failed to parse" -void parse_data(struct config *conf, const char *buffer, size_t buffer_size); -char **get_dependencies(const char *buffer, char *dependency, int* number); +static inline char *get_config_path() { + char *username = getlogin(); + size_t config_path_s = strlen("/home/") + strlen(username) + strlen(CONFIG_REL_PATH); + char *config_path = NULL; + // Allocate memory using macro. + ALLOCATE_MEM(config_path, config_path_s + 1, sizeof(char)); -int count_targets(char *location_of_targets, int len); - -int get_dependency_length(const char* dependency); - -int get_value_by_key_validator(const char *location_on_conf, const char *message, int index1, int index2); - -void *get_value_by_key(const char* buffer, char* key, int is_integer, size_t buffer_size); - -int get_config(struct config *conf) { - char* username = getlogin(); - char* config_path = malloc(sizeof(char) * (strlen(CONFIG_PATH) + strlen(username) + strlen("home") + 3)); + // Form the path. strcpy(config_path, "/home/"); strcat(config_path, username); - strcat(config_path, CONFIG_PATH); + strcat(config_path, CONFIG_REL_PATH); - int conf_fd = open(config_path, O_RDONLY); - char *buffer = NULL; - // error handling. - if (conf_fd == -1) return make_log(FAILED_TO_OPEN, strerror(errno), NORMAL_LOG, ERROR); - struct stat file_stats; + return config_path; +} - if (lstat(config_path, &file_stats) == -1) return make_log(FAILED_TO_READ_SIZE, strerror(errno), NORMAL_LOG, ERROR); - // make the size of the buffer equal to the config file size. - buffer = malloc(sizeof(char) * file_stats.st_size); - // error handling. - if (read(conf_fd, buffer, file_stats.st_size) == -1) - return make_log(FAILED_TO_READ, strerror(errno), NORMAL_LOG, ERROR); +static inline char *form_parse_msg(const char *option, const char *type) { + size_t parse_msg_s = strlen(type) + strlen(option); + char *parse_msg = NULL; + // Allocate memory. + ALLOCATE_MEM(parse_msg, parse_msg_s + 2, sizeof(char)); - if (close(conf_fd)) return make_log(FAILED_TO_CLOSE, strerror(errno), NORMAL_LOG, ERROR); + // form the error. + strcpy(parse_msg, type); + strcat(parse_msg, " "); + strcat(parse_msg, option); - make_log(SUCCESS_LOAD, NULL, NORMAL_LOG, SUCCESS); - parse_data(conf, buffer, file_stats.st_size); - free(config_path); - free(buffer); - return 0; + return parse_msg; } -void parse_data(struct config *conf, const char *buffer, size_t buffer_size) { - conf->c_check_interval = (int *) get_value_by_key(buffer, CHECK_INTERVAL, 1, buffer_size); - conf->c_parse_interval = (int *) get_value_by_key(buffer, PARSE_INTERVAL, 1, buffer_size); - conf->c_debug_log = (int *) get_value_by_key(buffer, DEBUG, 1, buffer_size); - conf->c_default_dir_path = (char *) get_value_by_key(buffer, DEFAULT_DIR_PATH, 0, buffer_size); - conf->c_targets_path = get_dependencies(buffer, TARGETS, &conf->c_target_number); - conf->c_check = get_dependencies(buffer, CHECK, &conf->c_check_number); -} +static void *get_value_of(const char *option, const char *buffer) { + // Make a copy of the buffer. + char tmp_buffer[strlen(buffer) + 1]; + strcpy(tmp_buffer, buffer); + // Find the location of the option inside the config. + char *option_location = strstr(tmp_buffer, option); + char *error_msg = form_parse_msg(option, FAILED_TO_PARSE); + char *success_msg = form_parse_msg(option, SUCCESS_PARSE); + + // Check if the option exist. + if (option_location == NULL) { + make_log(error_msg, PARSE_FAILED_NO_FIELD, NORMAL_LOG, ERROR); + free(error_msg); + free(success_msg); + return NULL; + } -void *get_value_by_key(const char* buffer, char* key, int is_integer, size_t buffer_size) { - char *tmp = NULL; - tmp = malloc(sizeof(char) * (buffer_size)); - strncpy(tmp, buffer, buffer_size); - - char *location_on_conf = strstr(tmp, key); - char error_message[50] = ERROR_MESSAGE; - char success_message[50] = SUCCESS_MESSAGE; - strcat(error_message, key); - strcat(success_message, key); - - int key_len = (int) strlen(key); - if (get_value_by_key_validator(location_on_conf, error_message, key_len, key_len + 1)) return NULL; - - strtok(location_on_conf, " "); - char *value = strtok(NULL, "\n"); - - if (!is_integer) { - if (get_value_by_key_validator(location_on_conf, error_message, key_len, key_len + 1)) return NULL; - size_t value_len = strlen(value) + 1; - char *returned_value = malloc(sizeof(char) * value_len); - strncpy(returned_value, value, value_len); - make_log(success_message, NULL, NORMAL_LOG, SUCCESS); - free(tmp); - return returned_value; + // Split the option and the value. + char *option_value = strtok(option_location, " "); + if (option_value == NULL) { + make_log(error_msg, PARSE_FAILED_EMPTY, NORMAL_LOG, ERROR); + free(error_msg); + free(success_msg); + return NULL; + } + // Get the value. + option_value = strtok(NULL, "\n"); + + if (strcmp(option, DEFAULT_DIR_PATH) == 0) { + make_log(success_msg, NULL, NORMAL_LOG, SUCCESS); + free(error_msg); + free(success_msg); + // Result. + char *result = NULL; + ALLOCATE_MEM(result, strlen(option_value) + 1, sizeof(char)); + strcpy(result, option_value); + return result; } - if (get_value_by_key_validator(location_on_conf, error_message, key_len, key_len + 1)) return NULL; - long tmp_integer = strtol(value, &value, 10); - int *integer_value = malloc(sizeof(int)); - *integer_value = (int) tmp_integer; - free(tmp); - make_log(success_message, NULL, NORMAL_LOG, SUCCESS); + int *int_value = NULL; + // Allocate memory. + ALLOCATE_MEM(int_value, 1, sizeof(int)); + *int_value = (int) strtol(option_value, &option_value, 10); - return integer_value; + make_log(success_msg, NULL, NORMAL_LOG, SUCCESS); + free(error_msg); + free(success_msg); + return int_value; } -char **get_dependencies(const char *buffer, char *dependency, int* number) { - int location_len = get_dependency_length(strstr(buffer, dependency)); - char *location_on_conf = calloc(location_len + 1, sizeof(char)); - strncpy(location_on_conf, strstr(buffer, dependency), location_len); - - char error_message[20] = ERROR_MESSAGE; - char success_message[20] = SUCCESS_MESSAGE; - strcat(error_message, dependency); - strcat(success_message, dependency); - - if (location_len == 0) { - make_log(error_message, PARSE_FAILED_EMPTY, NORMAL_LOG, ERROR); +static char **get_values_of(const char *list, const char *list_end, size_t *size, const char *buffer) { + // Make a copy of the buffer content. + char tmp_buffer[strlen(buffer) + 1]; + char *error_msg = form_parse_msg(list, FAILED_TO_PARSE); + char *success_msg = form_parse_msg(list, SUCCESS_PARSE); + strcpy(tmp_buffer, buffer); + + // Find the location in the config. + char *list_location = strstr(buffer, list); + if (list_location == NULL) { + make_log(FAILED_TO_PARSE, error_msg, NORMAL_LOG, ERROR); + free(error_msg); + free(success_msg); return NULL; } - char *splitter = "\n"; - int dep_counter = count_targets(location_on_conf, location_len); - - char *current_dependency = strtok(location_on_conf, splitter); - char **dependencies = malloc(sizeof(char *) * (dep_counter + 1)); - int save_counter = 0; - size_t tmp_len; - // erase garbage. - current_dependency = strtok(NULL, splitter); - while (current_dependency != NULL && save_counter < dep_counter) { - tmp_len = strlen(current_dependency); - dependencies[save_counter] = calloc(tmp_len + 1, sizeof(char)); - strncpy(dependencies[save_counter], current_dependency, tmp_len); - current_dependency = strtok(NULL, splitter); - save_counter++; + size_t lines_s = 1; + char **lines = NULL; + // Allocate space for one line. + ALLOCATE_MEM(lines, lines_s, sizeof(char *)); + // skip the first line. + strtok(list_location, "\n"); + char *current_line = strtok(NULL, "\n"); + // Save the rest. + while (strcmp(current_line, list_end) != 0) { + // Allocate space for the current line. + ALLOCATE_MEM(lines[lines_s - 1], strlen(current_line) + 1, sizeof(char )); + // save the content + strcpy(lines[lines_s - 1], current_line); + // increase the size of the array to make it fit the next line. + REALLOCATE_MEM(lines, sizeof(char *) * (++lines_s)); + current_line = strtok(NULL, "\n"); } - *number = dep_counter; - - free(location_on_conf); - make_log(success_message, NULL, NORMAL_LOG, SUCCESS); - return dependencies; -} - -int count_targets(char *location_of_targets, int len) { - char* tmp_location = calloc(len + 1, sizeof(char)); - strncpy(tmp_location, location_of_targets, len); - char* tmp = strtok(tmp_location, "\n"); - - int counter = -1; - while (tmp != NULL) { - tmp = strtok(NULL, "\n"); - ++counter; + --lines_s; + if (lines_s == 0) { + free(error_msg); + free(success_msg); + free(lines); + return NULL; } - free(tmp_location); - return counter; -} - -int get_value_by_key_validator(const char *location_on_conf, const char *message, int index1, int index2) { - if (location_on_conf == NULL) return make_log(message, PARSE_FAILED_NO_FIELD, NORMAL_LOG, ERROR); - else if (location_on_conf[index1] == '\n') return make_log(message, PARSE_FAILED_NOTHING, NORMAL_LOG, ERROR); - else if (location_on_conf[index2] == '\n') return make_log(message, PARSE_FAILED_EMPTY, NORMAL_LOG, ERROR); + *size = lines_s; - return 0; + make_log(success_msg, NULL, NORMAL_LOG, SUCCESS); + free(error_msg); + free(success_msg); + return lines; } -int get_dependency_length(const char* dependency) { - if (dependency == NULL) return 0; - - int len = 1; - for (int ln = 1; dependency[ln] != '['; ln++) ++len; - - return len; +static void parse_data(struct config *conf, const char *buffer) { + conf->c_checks_s = 0; + conf->c_targets_s = 0; + conf->c_check_interval = (int *) get_value_of(CHECK_INTERVAL, buffer); + conf->c_parse_interval = (int *) get_value_of(PARSE_INTERVAL, buffer); + conf->c_debug_log = (int *) get_value_of(DEBUG, buffer); + conf->c_default_dir_path = (char *) get_value_of(DEFAULT_DIR_PATH, buffer); + conf->c_enable_default_path = (int *) get_value_of(ENABLE_DEFAULT_PATH, buffer); + conf->c_targets = get_values_of(TARGETS, DONE_TARGETS, &conf->c_targets_s, buffer); + conf->c_checks = get_values_of(CHECK, DONE_CHECK, &conf->c_checks_s, buffer); } -void freeDependencies(char** dependencies, int depNumber) { - for (int curr_free = 0; curr_free < depNumber; curr_free++) { - if (dependencies[curr_free] != NULL) free(dependencies[curr_free]); - } - free(dependencies); +static inline void free_list(char **list, size_t size) { + for (int line = 0; line < size; line++) free(list[line]); + free(list); } struct config *clear_config(struct config *conf) { @@ -201,11 +186,41 @@ struct config *clear_config(struct config *conf) { if (conf->c_parse_interval != NULL) free(conf->c_parse_interval); if (conf->c_debug_log != NULL) free(conf->c_debug_log); if (conf->c_default_dir_path != NULL) free(conf->c_default_dir_path); - if (conf->c_targets_path != NULL) freeDependencies(conf->c_targets_path, conf->c_target_number); - if (conf->c_check != NULL) freeDependencies(conf->c_check, conf->c_check_number); + if (conf->c_enable_default_path != NULL) free(conf->c_enable_default_path); + if (conf->c_targets != NULL) free_list(conf->c_targets, conf->c_targets_s); + if (conf->c_checks != NULL) free_list(conf->c_checks, conf->c_checks_s); free(conf); - return calloc(1, sizeof(struct config)); + struct config *tmp = NULL; + ALLOCATE_MEM(tmp, 1, sizeof(struct config)); + return tmp; } +int get_config(struct config *conf) { + // Get the config path. + char *config_path = get_config_path(); + + // Try to open the config. + int config_fd = open(config_path, O_RDONLY); + if (config_fd == -1) return make_log(FAILED_TO_OPEN, strerror(errno), NORMAL_LOG, ERROR); + // Get the size of the config file. + struct stat file_stats; + if (lstat(config_path, &file_stats) == -1) return make_log(FAILED_TO_READ_SIZE, strerror(errno), NORMAL_LOG, ERROR); + + // Read the config file. + char *buffer = NULL; + // Allocate space. + ALLOCATE_MEM(buffer, file_stats.st_size + 1, sizeof(char)); + if (read(config_fd, buffer, file_stats.st_size) == -1) + return make_log(FAILED_TO_READ, strerror(errno), NORMAL_LOG, ERROR); + + if (close(config_fd) == -1) return make_log(FAILED_TO_CLOSE, strerror(errno), NORMAL_LOG, ERROR); + + make_log(SUCCESS_LOAD, NULL, NORMAL_LOG, SUCCESS); + + parse_data(conf, buffer); + free(config_path); + free(buffer); + return 0; +} diff --git a/tools/include/config/config_parser.h b/tools/include/config/config_parser.h index 4ea1149..572e4b8 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -1,15 +1,18 @@ #ifndef FILE_MANAGER_CONFIGPARSER_H #define FILE_MANAGER_CONFIGPARSER_H 1 +#include + struct config { - int *c_check_interval; - int *c_parse_interval; - int *c_debug_log; - char *c_default_dir_path; - char **c_targets_path; - char **c_check; - int c_check_number; - int c_target_number; + int *c_check_interval; + int *c_parse_interval; + int *c_debug_log; + char *c_default_dir_path; + int *c_enable_default_path; + char **c_targets; + char **c_checks; + size_t c_checks_s; + size_t c_targets_s; }; extern int get_config(struct config *conf); diff --git a/tools/include/mem.h b/tools/include/mem.h new file mode 100644 index 0000000..078a6e6 --- /dev/null +++ b/tools/include/mem.h @@ -0,0 +1,32 @@ +#ifndef FILE_SORTER_CORE_MEM_H +#define FILE_SORTER_CORE_MEM_H 1 + +#include + +#define OUT_OF_MEMORY "Out Of Memory." +#define FAILED_MEMORY_MSG "Failed to allocate memory." + +#define ALLOCATE_MEM(VAR, SIZE, SIZE_OF_TYPE) do { \ + (VAR) = calloc(SIZE, SIZE_OF_TYPE); \ + if ( (VAR) == NULL ) { \ + make_log(FAILED_MEMORY_MSG, \ + OUT_OF_MEMORY, \ + NORMAL_LOG, \ + ERROR); \ + exit(1); \ + } \ + } while(0) + +#define REALLOCATE_MEM(VAR, NEW_SIZE) do { \ + (VAR) = realloc((VAR), NEW_SIZE); \ + if ( (VAR) == NULL ) { \ + make_log(FAILED_MEMORY_MSG, \ + OUT_OF_MEMORY, \ + NORMAL_LOG, \ + ERROR); \ + exit(1); \ + } \ + } while(0) + + +#endif \ No newline at end of file diff --git a/tools/logger.c b/tools/logger.c index fa055a0..953fc12 100644 --- a/tools/logger.c +++ b/tools/logger.c @@ -9,7 +9,17 @@ #define SUCCESS_PREFIX "[SUCCESS]" #define WARN_PREFIX "[WARN]" -void show_logs(const char *message, const char *log_type_prefix, const char *seriousness_type, const char *reason); +static inline void show_logs(const char *message, + const char *log_type_prefix, + const char *seriousness_type, + const char *reason) { + if (reason) { + printf("%s %s %s [reason] %s\n", log_type_prefix, seriousness_type, message, reason); + return; + } + printf("%s %s %s\n", log_type_prefix, seriousness_type, message); + +} int make_log(const char *message, const char *reason, int log_type, int seriousness) { char *prefix; @@ -28,14 +38,4 @@ int make_log(const char *message, const char *reason, int log_type, int seriousn return 0; } -void show_logs(const char *message, - const char *log_type_prefix, - const char *seriousness_type, - const char *reason) { - if (reason) { - printf("%s %s %s [reason] %s\n", log_type_prefix, seriousness_type, message, reason); - return; - } - printf("%s %s %s\n", log_type_prefix, seriousness_type, message); -}