aboutsummaryrefslogtreecommitdiff
path: root/src/data_management.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data_management.c')
-rw-r--r--src/data_management.c57
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;
+}
+