From 16fa1e77b29c946f39c961a5c4d7265fd0701d1e Mon Sep 17 00:00:00 2001 From: Wolfgang Scherer Date: Thu, 9 Nov 2017 01:16:44 +0100 Subject: [PATCH] [scan] Configuration option to follow symlinks --- forked-daapd.conf.in | 3 +++ src/conffile.c | 1 + src/library/filescanner.c | 29 ++++++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/forked-daapd.conf.in b/forked-daapd.conf.in index 41562ff2..62efd456 100644 --- a/forked-daapd.conf.in +++ b/forked-daapd.conf.in @@ -62,6 +62,9 @@ library { # Directories to index directories = { "/srv/music" } + # Follow symlinks. Default: true. +# follow_symlinks = true + # Directories containing podcasts # For each directory that is indexed the path is matched against these # names. If there is a match all items in the directory are marked as diff --git a/src/conffile.c b/src/conffile.c index 0db89299..dc463dd8 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -73,6 +73,7 @@ static cfg_opt_t sec_library[] = CFG_INT("port", 3689, CFGF_NONE), CFG_STR("password", NULL, CFGF_NONE), CFG_STR_LIST("directories", NULL, CFGF_NONE), + CFG_BOOL("follow_symlinks", cfg_true, CFGF_NONE), CFG_STR_LIST("podcasts", NULL, CFGF_NONE), CFG_STR_LIST("audiobooks", NULL, CFGF_NONE), CFG_STR_LIST("compilations", NULL, CFGF_NONE), diff --git a/src/library/filescanner.c b/src/library/filescanner.c index 81572f0c..72a7c481 100644 --- a/src/library/filescanner.c +++ b/src/library/filescanner.c @@ -679,10 +679,12 @@ create_virtual_path(char *path, char *virtual_path, int virtual_path_len) * The return value is 0 if the operation is successful, or -1 on failure */ static int -read_attributes(char *resolved_path, const char *path, struct stat *sb) +read_attributes(char *resolved_path, const char *path, struct stat *sb, int *is_link) { int ret; + *is_link = 0; + ret = lstat(path, sb); if (ret < 0) { @@ -692,6 +694,8 @@ read_attributes(char *resolved_path, const char *path, struct stat *sb) if (S_ISLNK(sb->st_mode)) { + *is_link = 1; + if (!realpath(path, resolved_path)) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, could not dereference symlink: %s\n", path, strerror(errno)); @@ -721,6 +725,8 @@ process_directory(char *path, int parent_id, int flags) char entry[PATH_MAX]; char resolved_path[PATH_MAX]; struct stat sb; + int is_link; + int follow_symlinks; struct watch_info wi; int type; char virtual_path[PATH_MAX]; @@ -758,6 +764,8 @@ process_directory(char *path, int parent_id, int flags) if (check_speciallib(path, "audiobooks")) type |= F_SCAN_TYPE_AUDIOBOOK; + follow_symlinks = cfg_getbool(cfg_getsec(cfg, "library"), "follow_symlinks"); + for (;;) { if (library_is_exiting()) @@ -786,7 +794,7 @@ process_directory(char *path, int parent_id, int flags) continue; } - ret = read_attributes(resolved_path, entry, &sb); + ret = read_attributes(resolved_path, entry, &sb, &is_link); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, read_attributes() failed\n", entry); @@ -794,6 +802,12 @@ process_directory(char *path, int parent_id, int flags) continue; } + if (is_link && !follow_symlinks) + { + DPRINTF(E_DBG, L_SCAN, "Ignore symlink %s\n", entry); + continue; + } + if (S_ISDIR(sb.st_mode)) { push_dir(&dirstack, resolved_path, dir_id); @@ -1179,6 +1193,7 @@ static void process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie) { struct stat sb; + int is_link; uint32_t path_hash; char *file = path; char resolved_path[PATH_MAX]; @@ -1306,6 +1321,8 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie if (ie->mask & IN_CLOSE_WRITE) { + int follow_symlinks = cfg_getbool(cfg_getsec(cfg, "library"), "follow_symlinks"); + DPRINTF(E_DBG, L_SCAN, "File closed: %s\n", path); // File has been closed so remove from the IN_ATTRIB ignore list @@ -1317,7 +1334,7 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie incomingfiles_buffer[i] = 0; } - ret = read_attributes(resolved_path, path, &sb); + ret = read_attributes(resolved_path, path, &sb, &is_link); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, read_attributes() failed\n", path); @@ -1325,6 +1342,12 @@ process_inotify_file(struct watch_info *wi, char *path, struct inotify_event *ie return; } + if (is_link && !follow_symlinks) + { + DPRINTF(E_DBG, L_SCAN, "Ignore symlink %s\n", path); + return; + } + type = 0; if (check_speciallib(path, "compilations")) type |= F_SCAN_TYPE_COMPILATION;