diff options
author | Max Kellermann <max@duempel.org> | 2008-10-14 11:10:54 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-10-14 11:10:54 +0200 |
commit | 197caee151f7b8a53eeaebc5b88f833a708fd8b8 (patch) | |
tree | 783a0a197a69e1a65e3e04e92c811bdfd46eaa2c | |
parent | f521c12d2022f13d3d15408ba320cde77a646363 (diff) | |
download | mpd-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.c | 45 |
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); |