From f002402c168f8182ba3b8be22e48bf20adc6a946 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sat, 4 Sep 2021 15:45:33 +0300 Subject: [PATCH 01/11] Start rewriting all the code. I decide to re wrote all the code, because i notice that the previous code had a few programs. One of them is that the code was unreadable. --- CMakeLists.txt | 20 +-- README.md | 25 ++- config/config.conf | 8 +- main.c | 6 +- src/manager.c | 194 ----------------------- tools/config_parser.c | 226 +++++++-------------------- tools/include/config/config_parser.h | 4 +- tools/include/mem.h | 20 +++ 8 files changed, 115 insertions(+), 388 deletions(-) create mode 100644 tools/include/mem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cdabe76..61fe46b 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,7 +12,7 @@ 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/) @@ -36,23 +36,23 @@ 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 \n [check]\n \n diff --git a/README.md b/README.md index d2d9bda..28c0153 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,10 +21,12 @@ 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] @@ -37,6 +43,7 @@ defaultDirPath /home/username/default_sorter_path/ [done_targets] ``` + The information is as follows.
Field | Description @@ -49,6 +56,7 @@ Field | Description `[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 +64,9 @@ An example of `[check]`:
... [done_check] ``` + An example of `[targets]`:
+ ``` [targets] .py /home/username/Documents/py/ @@ -64,8 +74,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..9a8f58e 100644 --- a/config/config.conf +++ b/config/config.conf @@ -1,8 +1,8 @@ [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/ [check] diff --git a/main.c b/main.c index 81d8af1..be4d119 100644 --- a/main.c +++ b/main.c @@ -1,8 +1,12 @@ #include +#include + int main() { + struct config test; - run(); + get_config(&test); + //run(); return 0; } \ No newline at end of file diff --git a/src/manager.c b/src/manager.c index 60cd382..6fa95e8 100644 --- a/src/manager.c +++ b/src/manager.c @@ -24,197 +24,3 @@ #define DEFAULT_PARSE_INTERVAL 5000 #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; -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) { - pthread_mutex_lock(&lock); - conf = clear_config(conf); - - if (get_config(conf) == -1) make_log(PARSER_FAILED, NULL, NORMAL_LOG, WARN); - - 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; - } - interval = *(conf->c_parse_interval); - pthread_mutex_unlock(&lock); - - 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; - char *path = NULL; - int interval; - size_t tmp_len; - DIR *dir = NULL; - - while (TRUE) { - pthread_mutex_lock(&lock); - - for (int curr_check = 0; curr_check < conf->c_check_number; curr_check++) { - curr_dir = conf->c_check[curr_check]; - dir = opendir(curr_dir); - - if (dir == NULL) { - if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_OPEN_DIR, strerror(errno), DEBUG_LOG, ERROR); - continue; - } - - while ((files = readdir(dir)) != NULL) { - - 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); - - sleep(interval); - } -} - -void check_move_file(char *filepath, char *file) { - char *curr_ext = NULL; - char *check_ext = NULL; - char *move_file_to = NULL; - size_t tmp_len; - - - 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); - - 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(move_file_to); - make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); - 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); - - check_ext = strstr(file, curr_ext); - - 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; - } - - free(curr_ext); - free(move_file_to); - make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); - return; - } - else if (check_ext[tmp_len] != '\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); - - 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; - } - free(curr_ext); - free(move_file_to); - 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; - - tmp = calloc(target_len, sizeof(char)); - strncpy(tmp, target, target_len); - strtok(tmp, splitter); - - target_len = strlen(tmp); - *extension_len = target_len; - extension = calloc(target_len + 1, sizeof(char)); - strncpy(extension, tmp, target_len); - - free(tmp); - return extension; -} - -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); - - target_len = strlen(strchr(tmp, '/')) + strlen(filename) + 1; - path = calloc(target_len, sizeof(char)); - strncpy(path, strchr(tmp, '/'), target_len); - - free(tmp); - return path; -} \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index 16b7268..aba9eba 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -8,204 +8,88 @@ #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 SUCCESS_MESSAGE "Successfully parse " -#define SUCCESS_LOAD "Successfully load config" +#define SUCCESS_MESSAGE "Successfully parse " +#define SUCCESS_LOAD "Successfully load config" -#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 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 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_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" -void parse_data(struct config *conf, const char *buffer, size_t buffer_size); +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, sizeof(char)); -char **get_dependencies(const char *buffer, char *dependency, int* number); - -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 void *get_value_of(const char *option, const char *buffer) { - if (close(conf_fd)) return make_log(FAILED_TO_CLOSE, strerror(errno), NORMAL_LOG, ERROR); - make_log(SUCCESS_LOAD, NULL, NORMAL_LOG, SUCCESS); - parse_data(conf, buffer, file_stats.st_size); - free(config_path); - free(buffer); return 0; } -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); -} - -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; - } - - 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); - - return integer_value; -} +static char **get_values_of(const char *list, const char *buffer) { -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); - 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++; - } - *number = dep_counter; - - free(location_on_conf); - make_log(success_message, NULL, NORMAL_LOG, SUCCESS); - return dependencies; + return NULL; } -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; - } - - free(tmp_location); - return counter; +static void parse_data(struct config *conf, char *buffer) { + 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_values_of(DEBUG, buffer); + conf->c_targets = get_values_of(TARGETS, buffer); + conf->c_checks = get_values_of(CHECK, buffer); } -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); - return 0; -} +int get_config(struct config *conf) { + // Get the config path. + char *config_path = get_config_path(); -int get_dependency_length(const char* dependency) { - if (dependency == NULL) return 0; + // 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); - int len = 1; - for (int ln = 1; dependency[ln] != '['; ln++) ++len; + // 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); - return len; -} + // Read the config file. + char *buffer = NULL; + if (read(config_fd, buffer, file_stats.st_size) == -1) + return make_log(FAILED_TO_READ, strerror(errno), NORMAL_LOG, ERROR); -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); -} + if (close(config_fd) == -1) return make_log(FAILED_TO_CLOSE, strerror(errno), NORMAL_LOG, ERROR); -struct config *clear_config(struct config *conf) { - if (conf->c_check_interval != NULL) free(conf->c_check_interval); - 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); + make_log(SUCCESS_LOAD, NULL, NORMAL_LOG, SUCCESS); - free(conf); - return calloc(1, sizeof(struct config)); + 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..1157c51 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -6,8 +6,8 @@ struct config { int *c_parse_interval; int *c_debug_log; char *c_default_dir_path; - char **c_targets_path; - char **c_check; + char **c_targets; + char **c_checks; int c_check_number; int c_target_number; }; diff --git a/tools/include/mem.h b/tools/include/mem.h new file mode 100644 index 0000000..40dd286 --- /dev/null +++ b/tools/include/mem.h @@ -0,0 +1,20 @@ +#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) + +#endif \ No newline at end of file From d2571aba9091d0223f254a1d0189987a49052583 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sat, 4 Sep 2021 17:34:21 +0300 Subject: [PATCH 02/11] Almost done with the config parser. --- main.c | 18 ++++ tools/config_parser.c | 122 ++++++++++++++++++++++++--- tools/include/config/config_parser.h | 18 ++-- tools/include/mem.h | 14 ++- 4 files changed, 151 insertions(+), 21 deletions(-) diff --git a/main.c b/main.c index be4d119..d652fb8 100644 --- a/main.c +++ b/main.c @@ -1,12 +1,30 @@ #include #include +#include int main() { struct config test; get_config(&test); + + printf("----- OPTIONS -----\n"); + printf("%d\n", *test.c_check_interval); + printf("%d\n", *test.c_parse_interval); + printf("%d\n", *test.c_debug_log); + printf("%s\n", test.c_default_dir_path); + /*printf("----- CHECKS -----\n"); + + for (int i = 0; i < test.c_checks_s; i++) { + printf("%s\n", test.c_checks[i]); + } + + printf("----- TARGETS -----\n"); + + for (int i = 0; i < test.c_targets_s; i++) { + printf("%s\n", test.c_targets[i]); + }*/ //run(); return 0; } \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index aba9eba..75f22b8 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -19,18 +19,21 @@ #define TARGETS "[targets]" #define CHECK "[check]" -#define SUCCESS_MESSAGE "Successfully parse " +#define DONE_TARGETS "[done_targets]" +#define DONE_CHECK "[done_check]" + +#define SUCCESS_PARSE "Successfully parse" #define SUCCESS_LOAD "Successfully load config" -#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 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" static inline char *get_config_path() { @@ -38,7 +41,7 @@ static inline char *get_config_path() { 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, sizeof(char)); + ALLOCATE_MEM(config_path, config_path_s + 1, sizeof(char)); // Form the path. strcpy(config_path, "/home/"); @@ -48,23 +51,115 @@ static inline char *get_config_path() { return config_path; } -static void *get_value_of(const char *option, const char *buffer) { +static inline char *form_parse_msg(const char *option, const char *type) { + size_t parse_msg_s = strlen(type) + strlen(option); + // TODO change the allocation. + char *parse_msg = NULL; + // Allocate memory. + ALLOCATE_MEM(parse_msg, parse_msg_s + 2, sizeof(char)); + // form the error. + strcpy(parse_msg, type); + strcat(parse_msg, " "); + strcat(parse_msg, option); - return 0; + return parse_msg; } -static char **get_values_of(const char *list, const char *buffer) { +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); + return NULL; + } + + // 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; + } + + int *int_value = NULL; + // Allocate memory. + ALLOCATE_MEM(int_value, 1, sizeof(int)); + *int_value = (int) strtol(option_value, &option_value, 10); + + make_log(success_msg, NULL, NORMAL_LOG, SUCCESS); + free(error_msg); + free(success_msg); + return int_value; +} - return NULL; +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; + } + + 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"); + } + ALLOCATE_MEM(size, 1, sizeof(size_t)); + *size = lines_s - 2; + + return lines; } -static void parse_data(struct config *conf, char *buffer) { +static void parse_data(struct config *conf, const char *buffer) { 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_values_of(DEBUG, buffer); - conf->c_targets = get_values_of(TARGETS, buffer); - conf->c_checks = get_values_of(CHECK, 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_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); } @@ -82,6 +177,8 @@ int get_config(struct config *conf) { // 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); @@ -89,6 +186,7 @@ int get_config(struct config *conf) { 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 1157c51..7a692e7 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -1,15 +1,17 @@ #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; - char **c_checks; - 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; + 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 index 40dd286..078a6e6 100644 --- a/tools/include/mem.h +++ b/tools/include/mem.h @@ -8,7 +8,7 @@ #define ALLOCATE_MEM(VAR, SIZE, SIZE_OF_TYPE) do { \ (VAR) = calloc(SIZE, SIZE_OF_TYPE); \ - if ( (VAR) == NULL) { \ + if ( (VAR) == NULL ) { \ make_log(FAILED_MEMORY_MSG, \ OUT_OF_MEMORY, \ NORMAL_LOG, \ @@ -17,4 +17,16 @@ } \ } 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 From 48e2bdd8cee184187170f03c57bc91f7d6528f81 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sat, 4 Sep 2021 18:23:27 +0300 Subject: [PATCH 03/11] Done with the config parser. --- main.c | 18 ------------------ tools/config_parser.c | 12 +++++++++--- tools/include/config/config_parser.h | 4 ++-- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index d652fb8..d4baba2 100644 --- a/main.c +++ b/main.c @@ -1,30 +1,12 @@ #include #include -#include - int main() { struct config test; get_config(&test); - printf("----- OPTIONS -----\n"); - printf("%d\n", *test.c_check_interval); - printf("%d\n", *test.c_parse_interval); - printf("%d\n", *test.c_debug_log); - printf("%s\n", test.c_default_dir_path); - /*printf("----- CHECKS -----\n"); - - for (int i = 0; i < test.c_checks_s; i++) { - printf("%s\n", test.c_checks[i]); - } - - printf("----- TARGETS -----\n"); - - for (int i = 0; i < test.c_targets_s; i++) { - printf("%s\n", test.c_targets[i]); - }*/ //run(); return 0; } \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index 75f22b8..dd13986 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -25,7 +25,6 @@ #define SUCCESS_PARSE "Successfully parse" #define SUCCESS_LOAD "Successfully load config" - #define PARSE_FAILED_EMPTY "The value is empty" #define PARSE_FAILED_NO_FIELD "There is no such field" @@ -147,13 +146,20 @@ static char **get_values_of(const char *list, const char *list_end, size_t *size REALLOCATE_MEM(lines, sizeof(char *) * (++lines_s)); current_line = strtok(NULL, "\n"); } - ALLOCATE_MEM(size, 1, sizeof(size_t)); - *size = lines_s - 2; + --lines_s; + if (lines_s == 0) return NULL; + + *size = lines_s; + make_log(success_msg, NULL, NORMAL_LOG, SUCCESS); + free(error_msg); + free(success_msg); return lines; } static void parse_data(struct config *conf, const char *buffer) { + ALLOCATE_MEM(conf->c_checks_s, 1, sizeof(size_t)); + ALLOCATE_MEM(conf->c_targets, 1, sizeof(size_t)); 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); diff --git a/tools/include/config/config_parser.h b/tools/include/config/config_parser.h index 7a692e7..6cc3266 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -10,8 +10,8 @@ struct config { char *c_default_dir_path; char **c_targets; char **c_checks; - size_t *c_checks_s; - size_t *c_targets_s; + size_t *c_checks_s; + size_t *c_targets_s; }; extern int get_config(struct config *conf); From e820f9bad01b65163445fb0425967d0f4e742c74 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sat, 4 Sep 2021 18:30:09 +0300 Subject: [PATCH 04/11] Add clear. --- main.c | 4 ---- src/manager.c | 8 ++++++++ tools/config_parser.c | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index d4baba2..486fa84 100644 --- a/main.c +++ b/main.c @@ -3,10 +3,6 @@ #include int main() { - struct config test; - - get_config(&test); - //run(); return 0; } \ No newline at end of file diff --git a/src/manager.c b/src/manager.c index 6fa95e8..9345411 100644 --- a/src/manager.c +++ b/src/manager.c @@ -24,3 +24,11 @@ #define DEFAULT_PARSE_INTERVAL 5000 #define INITIAL_CHECK_WAIT 5 + + +static struct config *conf; + + +void run() { + +} \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index dd13986..e6a50ab 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -168,6 +168,24 @@ static void parse_data(struct config *conf, const char *buffer) { conf->c_checks = get_values_of(CHECK, DONE_CHECK, conf->c_checks_s, buffer); } +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) { + if (conf->c_check_interval != NULL) free(conf->c_check_interval); + 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 != 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); + struct config *tmp = NULL; + ALLOCATE_MEM(tmp, 1, sizeof(struct config)); + return tmp; +} int get_config(struct config *conf) { // Get the config path. From 119db5b0c051f609dbead1ce07d4f844a7a24b56 Mon Sep 17 00:00:00 2001 From: Constantinos Argyriou Date: Sat, 4 Sep 2021 18:31:42 +0300 Subject: [PATCH 05/11] Update README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 28c0153..48d9abd 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ The program gets the information it needs from a config file, which is like the ``` [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] @@ -48,10 +48,10 @@ 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. `[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]`. From da0298d7476f4106ce1da29ea9eecb8de2b4422d Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sat, 4 Sep 2021 18:36:08 +0300 Subject: [PATCH 06/11] Add new option. --- CMakeLists.txt | 1 + config/config.conf | 1 + tools/config_parser.c | 2 ++ tools/include/config/config_parser.h | 1 + 4 files changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61fe46b..0801910 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ file(WRITE config/config.conf 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/config/config.conf b/config/config.conf index 9a8f58e..ad2bf37 100644 --- a/config/config.conf +++ b/config/config.conf @@ -3,6 +3,7 @@ check_interval 3000 parse_interval 5000 debug_log 0 default_dir_path /home/rounnus/default_sorter_path/ +enable_default_path1 [check] diff --git a/tools/config_parser.c b/tools/config_parser.c index e6a50ab..440ce0f 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -18,6 +18,7 @@ #define DEFAULT_DIR_PATH "default_dir_path" #define TARGETS "[targets]" #define CHECK "[check]" +#define ENABLE_DEFAULT_PATH "enable_default_path" #define DONE_TARGETS "[done_targets]" #define DONE_CHECK "[done_check]" @@ -164,6 +165,7 @@ static void parse_data(struct config *conf, const char *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); } diff --git a/tools/include/config/config_parser.h b/tools/include/config/config_parser.h index 6cc3266..a43d299 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -8,6 +8,7 @@ struct config { 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; From 228275a7c1a2c9b5db9d7fd199573b129811c5a3 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sun, 5 Sep 2021 01:41:57 +0300 Subject: [PATCH 07/11] Done. --- main.c | 3 +- src/manager.c | 180 ++++++++++++++++++++++++++- tools/config_parser.c | 23 ++-- tools/include/config/config_parser.h | 4 +- 4 files changed, 197 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 486fa84..9664787 100644 --- a/main.c +++ b/main.c @@ -1,8 +1,7 @@ #include -#include int main() { - //run(); + run(); return 0; } \ No newline at end of file diff --git a/src/manager.c b/src/manager.c index 9345411..079ed6c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -10,6 +10,7 @@ #include #include #include +#include #define TRUE 1 @@ -23,12 +24,189 @@ #define SUCCESS_MOVE "File moved successfully to target directory." #define DEFAULT_PARSE_INTERVAL 5000 +#define DEFAULT_ENABLE_PATH 1 #define INITIAL_CHECK_WAIT 5 -static struct config *conf; +static struct config *conf = NULL; +pthread_mutex_t lock; + +_Noreturn void *parse(void *arg) { + int interval; + + while(TRUE) { + // Lock the mutex. + pthread_mutex_lock(&lock); + // Clear the config. + conf = clear_config(conf); + + // 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); + } + // save the interval. + interval = *(conf->c_parse_interval); + pthread_mutex_unlock(&lock); + // sleep. + //sleep(interval); + } +} + +static inline char *extract_path_from_target(const char *target) { + char *path = NULL; + char tmp[strlen(target) + 1]; + strcpy(tmp, target); + + size_t path_s = strlen(strchr(tmp, '/')); + ALLOCATE_MEM(path, path_s + 1, sizeof(char)); + strcpy(path, strchr(tmp, '/')); + + return path; +} + +static inline char *extract_extension_from_target(const char *target, size_t *ext_s) { + char *extension = NULL; + char tmp[strlen(target) + 1]; + + // Make a copy of the target. + strcpy(tmp, target); + strtok(tmp, " "); + + // Allocate the space. + size_t extension_s = strlen(tmp); + ALLOCATE_MEM(extension, extension_s + 1, sizeof(char)); + // Copy the extension. + strcpy(extension, tmp); + + *ext_s = extension_s; + return extension; +} + +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; + 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); + + free(move_file_to); + make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); +} + +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; + + if (!conf->c_targets_s && conf->c_enable_default_path) { + move_to_default_path(file_path, file_name); + return; + } + + if (!conf->c_targets_s) 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); + } + else if (check_ext[curr_ext_s] != '\0') { + free(curr_ext); + continue; + } + 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); + + 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); + return; + } + + +} + +_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); + + for (int curr_check = 0; curr_check < conf->c_checks_s; curr_check++) { + curr_dir = conf->c_checks[curr_check]; + dir = opendir(curr_dir); + + if (dir == NULL) { + if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_OPEN_DIR, strerror(errno), DEBUG_LOG, ERROR); + continue; + } + + 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); + } +} void run() { + ALLOCATE_MEM(conf, 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); } \ No newline at end of file diff --git a/tools/config_parser.c b/tools/config_parser.c index 440ce0f..7e747d3 100644 --- a/tools/config_parser.c +++ b/tools/config_parser.c @@ -53,7 +53,6 @@ static inline char *get_config_path() { static inline char *form_parse_msg(const char *option, const char *type) { size_t parse_msg_s = strlen(type) + strlen(option); - // TODO change the allocation. char *parse_msg = NULL; // Allocate memory. ALLOCATE_MEM(parse_msg, parse_msg_s + 2, sizeof(char)); @@ -78,6 +77,8 @@ static void *get_value_of(const char *option, const char *buffer) { // 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; } @@ -148,7 +149,12 @@ static char **get_values_of(const char *list, const char *list_end, size_t *size current_line = strtok(NULL, "\n"); } --lines_s; - if (lines_s == 0) return NULL; + if (lines_s == 0) { + free(error_msg); + free(success_msg); + free(lines); + return NULL; + } *size = lines_s; @@ -159,15 +165,15 @@ static char **get_values_of(const char *list, const char *list_end, size_t *size } static void parse_data(struct config *conf, const char *buffer) { - ALLOCATE_MEM(conf->c_checks_s, 1, sizeof(size_t)); - ALLOCATE_MEM(conf->c_targets, 1, sizeof(size_t)); + 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); + 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); } static inline void free_list(char **list, size_t size) { @@ -180,8 +186,9 @@ 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 != NULL) free_list(conf->c_targets, *conf->c_targets_s); - if (conf->c_checks != NULL) free_list(conf->c_checks, *conf->c_checks_s); + 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); struct config *tmp = NULL; diff --git a/tools/include/config/config_parser.h b/tools/include/config/config_parser.h index a43d299..572e4b8 100644 --- a/tools/include/config/config_parser.h +++ b/tools/include/config/config_parser.h @@ -11,8 +11,8 @@ struct config { int *c_enable_default_path; char **c_targets; char **c_checks; - size_t *c_checks_s; - size_t *c_targets_s; + size_t c_checks_s; + size_t c_targets_s; }; extern int get_config(struct config *conf); From 5af48376b8b2d5e61620433c9cb2b81a26331152 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sun, 5 Sep 2021 01:43:25 +0300 Subject: [PATCH 08/11] Now done. --- src/manager.c | 5 ++--- tools/logger.c | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/manager.c b/src/manager.c index 079ed6c..9d5828e 100644 --- a/src/manager.c +++ b/src/manager.c @@ -53,7 +53,7 @@ _Noreturn void *parse(void *arg) { interval = *(conf->c_parse_interval); pthread_mutex_unlock(&lock); // sleep. - //sleep(interval); + sleep(interval); } } @@ -187,8 +187,7 @@ _Noreturn void *move_to_dir(void *arg) { interval = *(conf->c_check_interval); pthread_mutex_unlock(&lock); - - //sleep(interval); + sleep(interval); } } 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); -} From 1f78235378832b095810dd38ea7f9ef7d2bcbc66 Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sun, 5 Sep 2021 01:52:12 +0300 Subject: [PATCH 09/11] Fix a bug. --- src/manager.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/manager.c b/src/manager.c index 9d5828e..9b9cc79 100644 --- a/src/manager.c +++ b/src/manager.c @@ -24,7 +24,6 @@ #define SUCCESS_MOVE "File moved successfully to target directory." #define DEFAULT_PARSE_INTERVAL 5000 -#define DEFAULT_ENABLE_PATH 1 #define INITIAL_CHECK_WAIT 5 @@ -109,6 +108,11 @@ static void move_file(const char *file_path, const char *file_name) { size_t move_file_to_s; size_t curr_ext_s; + if (conf->c_enable_default_path == NULL) { + move_to_default_path(file_path, file_name); + return; + } + if (!conf->c_targets_s && conf->c_enable_default_path) { move_to_default_path(file_path, file_name); return; @@ -133,6 +137,7 @@ static void move_file(const char *file_path, const char *file_name) { 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(file_path, move_file_to) != 0) { if (*(conf->c_debug_log) == 1) make_log(FAILED_TO_MOVE_FILE, strerror(errno), DEBUG_LOG, ERROR); @@ -145,10 +150,9 @@ static void move_file(const char *file_path, const char *file_name) { free(curr_ext); free(move_file_to); free(curr_path); + make_log(SUCCESS_MOVE, NULL, NORMAL_LOG, SUCCESS); return; } - - } _Noreturn void *move_to_dir(void *arg) { From 9c510794d5b6440b1020ea81790ef7f2aa87212a Mon Sep 17 00:00:00 2001 From: Konstantinos Argyriou Date: Sun, 5 Sep 2021 02:13:11 +0300 Subject: [PATCH 10/11] Done --- CMakeLists.txt | 14 ++------------ config/config.conf | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0801910..137286e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,35 +16,25 @@ 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 () file(MAKE_DIRECTORY /home/$ENV{USER}/.config/systemd/user/) - message("/home/$ENV{USER}/.config/systemd/user/ OK") 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 () file(WRITE config/config.conf @@ -53,7 +43,7 @@ file(WRITE config/config.conf parse_interval\ 5000\n debug_log\ 0\n default_dir_path\ /home/$ENV{USER}/default_sorter_path/\n - enable_default_path 1\n + enable_default_path\ 1\n \n [check]\n \n diff --git a/config/config.conf b/config/config.conf index ad2bf37..0abfd96 100644 --- a/config/config.conf +++ b/config/config.conf @@ -3,7 +3,7 @@ check_interval 3000 parse_interval 5000 debug_log 0 default_dir_path /home/rounnus/default_sorter_path/ -enable_default_path1 +enable_default_path 1 [check] From 4fd31e64aceea3b77ec245c5baf61ef25eaaecaa Mon Sep 17 00:00:00 2001 From: Constantinos Argyriou Date: Sun, 5 Sep 2021 02:17:35 +0300 Subject: [PATCH 11/11] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 48d9abd..09a8825 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Field | Description `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]`.