summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-09-17 14:43:05 +0200
committerMax Kellermann <max@musicpd.org>2020-09-17 14:44:20 +0200
commit0acc398c52bd668a41507993ac0f01949345dd20 (patch)
treec520e11e615f20f034e5379a704bc0cf0911d4ac /src
parente8380cf2aa9ff7517d5ea3ada33a40df09d8542c (diff)
parent4c1cfca95b8a6dd2c0d9a7b6df065912eb8b4231 (diff)
Merge branch 'v0.21.x' into master
Diffstat (limited to 'src')
-rw-r--r--src/command/FileCommands.cxx4
-rw-r--r--src/db/update/InotifyUpdate.cxx95
-rw-r--r--src/player/Thread.cxx13
-rw-r--r--src/storage/plugins/NfsStorage.cxx4
-rw-r--r--src/storage/plugins/SmbclientStorage.cxx6
5 files changed, 76 insertions, 46 deletions
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index ebe229ebd..814289321 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
@@ -50,9 +50,7 @@ gcc_pure
static bool
SkipNameFS(PathTraitsFS::const_pointer name_fs) noexcept
{
- return name_fs[0] == '.' &&
- (name_fs[1] == 0 ||
- (name_fs[1] == '.' && name_fs[2] == 0));
+ return PathTraitsFS::IsSpecialFilename(name_fs);
}
gcc_pure
diff --git a/src/db/update/InotifyUpdate.cxx b/src/db/update/InotifyUpdate.cxx
index ff6257b99..957f4cf8d 100644
--- a/src/db/update/InotifyUpdate.cxx
+++ b/src/db/update/InotifyUpdate.cxx
@@ -21,19 +21,25 @@
#include "InotifySource.hxx"
#include "InotifyQueue.hxx"
#include "InotifyDomain.hxx"
+#include "ExcludeList.hxx"
#include "storage/StorageInterface.hxx"
+#include "input/InputStream.hxx"
+#include "input/Error.hxx"
#include "fs/AllocatedPath.hxx"
+#include "fs/DirectoryReader.hxx"
#include "fs/FileInfo.hxx"
#include "fs/Traits.hxx"
+#include "thread/Mutex.hxx"
+#include "util/Compiler.h"
#include "Log.hxx"
#include <cassert>
+#include <cstring>
#include <forward_list>
#include <map>
#include <string>
#include <sys/inotify.h>
-#include <string.h>
#include <dirent.h>
static constexpr unsigned IN_MASK =
@@ -50,17 +56,28 @@ struct WatchDirectory {
int descriptor;
+ ExcludeList exclude_list;
+
std::forward_list<WatchDirectory> children;
template<typename N>
- WatchDirectory(WatchDirectory *_parent, N &&_name,
+ WatchDirectory(N &&_name,
int _descriptor)
- :parent(_parent), name(std::forward<N>(_name)),
+ :parent(nullptr), name(std::forward<N>(_name)),
descriptor(_descriptor) {}
+ template<typename N>
+ WatchDirectory(WatchDirectory &_parent, N &&_name,
+ int _descriptor)
+ :parent(&_parent), name(std::forward<N>(_name)),
+ descriptor(_descriptor),
+ exclude_list(_parent.exclude_list) {}
+
WatchDirectory(const WatchDirectory &) = delete;
WatchDirectory &operator=(const WatchDirectory &) = delete;
+ void LoadExcludeList(Path directory_path) noexcept;
+
[[nodiscard]] gcc_pure
unsigned GetDepth() const noexcept;
@@ -68,6 +85,18 @@ struct WatchDirectory {
AllocatedPath GetUriFS() const noexcept;
};
+void
+WatchDirectory::LoadExcludeList(Path directory_path) noexcept
+try {
+ Mutex mutex;
+ auto is = InputStream::OpenReady((directory_path / Path::FromFS(".mpdignore")).c_str(),
+ mutex);
+ exclude_list.Load(std::move(is));
+} catch (...) {
+ if (!IsFileNotFound(std::current_exception()))
+ LogError(std::current_exception());
+}
+
static InotifySource *inotify_source;
static InotifyQueue *inotify_queue;
@@ -145,20 +174,19 @@ WatchDirectory::GetUriFS() const noexcept
}
/* we don't look at "." / ".." nor files with newlines in their name */
-static bool skip_path(const char *path)
+gcc_pure
+static bool
+SkipFilename(Path name) noexcept
{
- return PathTraitsFS::IsSpecialFilename(path) ||
- std::strchr(path, '\n') != nullptr;
+ return PathTraitsFS::IsSpecialFilename(name.c_str()) ||
+ name.HasNewline();
}
static void
-recursive_watch_subdirectories(WatchDirectory *directory,
- const AllocatedPath &path_fs, unsigned depth)
-{
- DIR *dir;
- struct dirent *ent;
-
- assert(directory != nullptr);
+recursive_watch_subdirectories(WatchDirectory &parent,
+ const Path path_fs,
+ unsigned depth)
+try {
assert(depth <= inotify_max_depth);
assert(!path_fs.IsNull());
@@ -167,20 +195,17 @@ recursive_watch_subdirectories(WatchDirectory *directory,
if (depth > inotify_max_depth)
return;
- dir = opendir(path_fs.c_str());
- if (dir == nullptr) {
- FormatErrno(inotify_domain,
- "Failed to open directory %s", path_fs.c_str());
- return;
- }
-
- while ((ent = readdir(dir))) {
+ DirectoryReader dir(path_fs);
+ while (dir.ReadEntry()) {
int ret;
- if (skip_path(ent->d_name))
+ const Path name_fs = dir.GetEntry();
+ if (SkipFilename(name_fs))
+ continue;
+
+ if (parent.exclude_list.Check(name_fs))
continue;
- const auto name_fs = Path::FromFS(ent->d_name);
const auto child_path_fs = path_fs / name_fs;
FileInfo fi;
@@ -209,17 +234,18 @@ recursive_watch_subdirectories(WatchDirectory *directory,
/* already being watched */
continue;
- directory->children.emplace_front(directory,
- name_fs,
- ret);
- child = &directory->children.front();
+ parent.children.emplace_front(parent,
+ name_fs,
+ ret);
+ child = &parent.children.front();
+ child->LoadExcludeList(child_path_fs);
tree_add_watch_directory(child);
- recursive_watch_subdirectories(child, child_path_fs, depth);
+ recursive_watch_subdirectories(*child, child_path_fs, depth);
}
-
- closedir(dir);
+} catch (...) {
+ LogError(std::current_exception());
}
gcc_pure
@@ -240,8 +266,6 @@ mpd_inotify_callback(int wd, unsigned mask,
{
WatchDirectory *directory;
- /*FormatDebug(inotify_domain, "wd=%d mask=0x%x name='%s'", wd, mask, name);*/
-
directory = tree_find_watch_directory(wd);
if (directory == nullptr)
return;
@@ -263,7 +287,7 @@ mpd_inotify_callback(int wd, unsigned mask,
? root
: (root / uri_fs);
- recursive_watch_subdirectories(directory, path_fs,
+ recursive_watch_subdirectories(*directory, path_fs,
directory->GetDepth());
}
@@ -318,11 +342,12 @@ mpd_inotify_init(EventLoop &loop, Storage &storage, UpdateService &update,
return;
}
- inotify_root = new WatchDirectory(nullptr, path, descriptor);
+ inotify_root = new WatchDirectory(path, descriptor);
+ inotify_root->LoadExcludeList(path);
tree_add_watch_directory(inotify_root);
- recursive_watch_subdirectories(inotify_root, path, 0);
+ recursive_watch_subdirectories(*inotify_root, path, 0);
inotify_queue = new InotifyQueue(loop, update);
diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx
index e53c5832a..3a109f12d 100644
--- a/src/player/Thread.cxx
+++ b/src/player/Thread.cxx
@@ -443,7 +443,7 @@ Player::ActivateDecoder() noexcept
pc.audio_format.Clear();
{
- /* call syncPlaylistWithQueue() in the main thread */
+ /* call playlist::SyncWithPlayer() in the main thread */
const ScopeUnlock unlock(pc.mutex);
pc.listener.OnPlayerSync();
}
@@ -684,6 +684,12 @@ Player::SeekDecoder(std::unique_lock<Mutex> &lock) noexcept
/* re-fill the buffer after seeking */
buffering = true;
+ {
+ /* call syncPlaylistWithQueue() in the main thread */
+ const ScopeUnlock unlock(pc.mutex);
+ pc.listener.OnPlayerSync();
+ }
+
return true;
}
@@ -1175,6 +1181,11 @@ try {
{
const ScopeUnlock unlock(mutex);
do_play(*this, dc, buffer);
+
+ /* give the main thread a chance to
+ queue another song, just in case
+ we've stopped playback
+ spuriously */
listener.OnPlayerSync();
}
diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index a93ccefb9..fbe18e96b 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
@@ -305,9 +305,7 @@ gcc_pure
static bool
SkipNameFS(PathTraitsFS::const_pointer name) noexcept
{
- return name[0] == '.' &&
- (name[1] == 0 ||
- (name[1] == '.' && name[2] == 0));
+ return PathTraitsFS::IsSpecialFilename(name);
}
static void
diff --git a/src/storage/plugins/SmbclientStorage.cxx b/src/storage/plugins/SmbclientStorage.cxx
index e62c95902..390cb8c4a 100644
--- a/src/storage/plugins/SmbclientStorage.cxx
+++ b/src/storage/plugins/SmbclientStorage.cxx
@@ -151,11 +151,9 @@ SmbclientStorage::OpenDirectory(std::string_view uri_utf8)
gcc_pure
static bool
-SkipNameFS(const char *name) noexcept
+SkipNameFS(PathTraitsFS::const_pointer name) noexcept
{
- return name[0] == '.' &&
- (name[1] == 0 ||
- (name[1] == '.' && name[2] == 0));
+ return PathTraitsFS::IsSpecialFilename(name);
}
SmbclientDirectoryReader::~SmbclientDirectoryReader()