aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-10-14 11:10:54 +0200
committerMax Kellermann <max@duempel.org>2008-10-14 11:10:54 +0200
commit197caee151f7b8a53eeaebc5b88f833a708fd8b8 (patch)
tree783a0a197a69e1a65e3e04e92c811bdfd46eaa2c
parentf521c12d2022f13d3d15408ba320cde77a646363 (diff)
downloadmpd-197caee151f7b8a53eeaebc5b88f833a708fd8b8.tar.gz
mpd-197caee151f7b8a53eeaebc5b88f833a708fd8b8.tar.xz
mpd-197caee151f7b8a53eeaebc5b88f833a708fd8b8.zip
update: don't follow relative symlinks
Don't follow relative symlinks which point into the music directory. This allows you to organize music with symbolic links, without MPD managing separate copies of each song.
Diffstat (limited to '')
-rw-r--r--src/update.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/src/update.c b/src/update.c
index e36a980dd..219806a4c 100644
--- a/src/update.c
+++ b/src/update.c
@@ -313,6 +313,48 @@ static int skip_path(const char *path)
}
static bool
+skip_symlink(const struct directory *directory, const char *utf8_name)
+{
+ char buffer[MPD_PATH_MAX];
+ const char *p;
+ ssize_t ret;
+
+ p = map_directory_child_fs(directory, utf8_name, buffer);
+ if (p == NULL)
+ return true;
+
+ ret = readlink(p, buffer, sizeof(buffer));
+ if (ret < 0)
+ /* don't skip if this is not a symlink */
+ return errno != EINVAL;
+
+ if (buffer[0] == '/')
+ return false;
+
+ p = buffer;
+ while (*p == '.') {
+ if (p[1] == '.' && p[2] == '/') {
+ /* "../" moves to parent directory */
+ directory = directory->parent;
+ if (directory == NULL)
+ /* we have moved outside the music
+ directory - don't skip this
+ symlink */
+ return false;
+ p += 3;
+ } else if (p[1] == '/')
+ /* eliminate "./" */
+ p += 2;
+ else
+ break;
+ }
+
+ /* we are still in the music directory, so this symlink points
+ to a song which is already in the database - skip it */
+ return true;
+}
+
+static bool
updateDirectory(struct directory *directory, const struct stat *st)
{
DIR *dir;
@@ -338,7 +380,8 @@ updateDirectory(struct directory *directory, const struct stat *st)
char *utf8;
struct stat st2;
- if (skip_path(ent->d_name))
+ if (skip_path(ent->d_name) ||
+ skip_symlink(directory, ent->d_name))
continue;
utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name);