diff options
Diffstat (limited to 'src/data_management.c')
| -rw-r--r-- | src/data_management.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/data_management.c b/src/data_management.c index 1ee8134..a6d8a0b 100644 --- a/src/data_management.c +++ b/src/data_management.c @@ -9,7 +9,10 @@ #include <string.h> #include <errno.h> #include <dirent.h> +#include <unistd.h> +#include <stdbool.h> #include <sys/stat.h> +#include <sys/types.h> #include "output.h" #include "data_management.h" @@ -50,6 +53,7 @@ inline struct list_node *create_node(char *fname, struct stat *ln_stat) { length = 255; } node->next = NULL; + node->symlink_target = NULL; explicit_bzero(node->fname, 256); memcpy(node->fname, fname, length); memcpy(&(node->ln_stat), ln_stat, sizeof(struct stat)); @@ -64,10 +68,16 @@ inline void destroy_list(struct list_head *list) { while (list->first != NULL) { ptr = list->first->next; if (ptr == NULL) { + if (list->first->symlink_target != NULL) { + free(list->first->symlink_target); + } free(list->first); break; } list->first->next = ptr->next; + if (ptr->symlink_target != NULL) { + free(ptr->symlink_target); + } free(ptr); } free(list); @@ -193,6 +203,35 @@ inline struct list_head *create_list_sort_reversed(struct list_head *list) { return lh; } +inline char *get_symlink_target_name(char *symlink, struct stat st) { + char *name = NULL; + ssize_t name_length = 0; + size_t tmp = 0; + + if ( symlink == NULL || (! S_ISLNK(st.st_mode)) ) { + return NULL; + } + + /* Suppressing warning __off_t to size_t only with the failsafe check */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" + tmp = ( (st.st_size<0) ? 0 : st.st_size+1 ); +#pragma GCC diagnostic pop + if (tmp == 0) { return NULL; } + + if ((name = calloc(tmp, sizeof(char))) == NULL) { + LOGERR("ERROR: Failed to allocate heap memory.\n"); + return NULL; + } + + if ((name_length = readlink(symlink, name, tmp)) == -1) { + LOGERR("ERROR: readlink(\"%s\", name, %lu) failed: %s (errno %d)\n", + symlink, (st.st_size+1), strerror(errno), errno); + free(name); + return NULL; + } + return name; +} /* This function contains the only time critical code. The loop over * the directory content. @@ -252,6 +291,9 @@ struct list_head *get_data_from_directory(char *path) { LOGERR("ERROR: Skipping entry %s\n", de->d_name); continue; } + if (option_resolve_symlinks && S_ISLNK(stat_res.st_mode)) { + tmp->symlink_target = get_symlink_target_name(fullpath, stat_res); + } /* Performance: Put every node on the stack and do the sorting afterwards */ tmp->next = lnstack; lnstack = tmp; @@ -286,3 +328,18 @@ struct list_head *get_data_from_directory(char *path) { return list; } +bool contains_resolved_symlinks(struct list_head *list) { + struct list_node *ptr = NULL; + + if (list == NULL) { return false; } + + ptr = list->first; + while (ptr != NULL) { + if (ptr->symlink_target != NULL) + return true; + ptr = ptr->next; + } + + return false; +} + |
