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.
-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); |