aboutsummaryrefslogtreecommitdiffstats
path: root/src/InotifyUpdate.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/InotifyUpdate.cxx')
-rw-r--r--src/InotifyUpdate.cxx339
1 files changed, 0 insertions, 339 deletions
diff --git a/src/InotifyUpdate.cxx b/src/InotifyUpdate.cxx
deleted file mode 100644
index 5a015508a..000000000
--- a/src/InotifyUpdate.cxx
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h" /* must be first for large file support */
-#include "InotifyUpdate.hxx"
-#include "InotifySource.hxx"
-#include "InotifyQueue.hxx"
-#include "InotifyDomain.hxx"
-#include "Mapper.hxx"
-#include "Main.hxx"
-#include "fs/AllocatedPath.hxx"
-#include "fs/FileSystem.hxx"
-#include "util/Error.hxx"
-#include "Log.hxx"
-
-#include <string>
-#include <map>
-#include <forward_list>
-
-#include <assert.h>
-#include <sys/inotify.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <dirent.h>
-
-static constexpr unsigned IN_MASK =
-#ifdef IN_ONLYDIR
- IN_ONLYDIR|
-#endif
- IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF
- |IN_MOVE|IN_MOVE_SELF;
-
-struct WatchDirectory {
- WatchDirectory *parent;
-
- AllocatedPath name;
-
- int descriptor;
-
- std::forward_list<WatchDirectory> children;
-
- template<typename N>
- WatchDirectory(WatchDirectory *_parent, N &&_name,
- int _descriptor)
- :parent(_parent), name(std::forward<N>(_name)),
- descriptor(_descriptor) {}
-
- WatchDirectory(const WatchDirectory &) = delete;
- WatchDirectory &operator=(const WatchDirectory &) = delete;
-};
-
-static InotifySource *inotify_source;
-static InotifyQueue *inotify_queue;
-
-static unsigned inotify_max_depth;
-static WatchDirectory *inotify_root;
-static std::map<int, WatchDirectory *> inotify_directories;
-
-static void
-tree_add_watch_directory(WatchDirectory *directory)
-{
- inotify_directories.insert(std::make_pair(directory->descriptor,
- directory));
-}
-
-static void
-tree_remove_watch_directory(WatchDirectory *directory)
-{
- auto i = inotify_directories.find(directory->descriptor);
- assert(i != inotify_directories.end());
- inotify_directories.erase(i);
-}
-
-static WatchDirectory *
-tree_find_watch_directory(int wd)
-{
- auto i = inotify_directories.find(wd);
- if (i == inotify_directories.end())
- return nullptr;
-
- return i->second;
-}
-
-static void
-disable_watch_directory(WatchDirectory &directory)
-{
- tree_remove_watch_directory(&directory);
-
- for (WatchDirectory &child : directory.children)
- disable_watch_directory(child);
-
- inotify_source->Remove(directory.descriptor);
-}
-
-static void
-remove_watch_directory(WatchDirectory *directory)
-{
- assert(directory != nullptr);
-
- if (directory->parent == nullptr) {
- LogWarning(inotify_domain,
- "music directory was removed - "
- "cannot continue to watch it");
- return;
- }
-
- disable_watch_directory(*directory);
-
- /* remove it from the parent, which effectively deletes it */
- directory->parent->children.remove_if([directory](const WatchDirectory &child){
- return &child == directory;
- });
-}
-
-static AllocatedPath
-watch_directory_get_uri_fs(const WatchDirectory *directory)
-{
- if (directory->parent == nullptr)
- return AllocatedPath::Null();
-
- const auto uri = watch_directory_get_uri_fs(directory->parent);
- if (uri.IsNull())
- return directory->name;
-
- return AllocatedPath::Build(uri, directory->name);
-}
-
-/* we don't look at "." / ".." nor files with newlines in their name */
-static bool skip_path(const char *path)
-{
- return (path[0] == '.' && path[1] == 0) ||
- (path[0] == '.' && path[1] == '.' && path[2] == 0) ||
- strchr(path, '\n') != nullptr;
-}
-
-static void
-recursive_watch_subdirectories(WatchDirectory *directory,
- const AllocatedPath &path_fs, unsigned depth)
-{
- Error error;
- DIR *dir;
- struct dirent *ent;
-
- assert(directory != nullptr);
- assert(depth <= inotify_max_depth);
- assert(!path_fs.IsNull());
-
- ++depth;
-
- 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))) {
- struct stat st;
- int ret;
-
- if (skip_path(ent->d_name))
- continue;
-
- const auto child_path_fs =
- AllocatedPath::Build(path_fs, ent->d_name);
- ret = StatFile(child_path_fs, st);
- if (ret < 0) {
- FormatErrno(inotify_domain,
- "Failed to stat %s",
- child_path_fs.c_str());
- continue;
- }
-
- if (!S_ISDIR(st.st_mode))
- continue;
-
- ret = inotify_source->Add(child_path_fs.c_str(), IN_MASK,
- error);
- if (ret < 0) {
- FormatError(error,
- "Failed to register %s",
- child_path_fs.c_str());
- error.Clear();
- continue;
- }
-
- WatchDirectory *child = tree_find_watch_directory(ret);
- if (child != nullptr)
- /* already being watched */
- continue;
-
- directory->children.emplace_front(directory,
- AllocatedPath::FromFS(ent->d_name),
- ret);
- child = &directory->children.front();
-
- tree_add_watch_directory(child);
-
- recursive_watch_subdirectories(child, child_path_fs, depth);
- }
-
- closedir(dir);
-}
-
-gcc_pure
-static unsigned
-watch_directory_depth(const WatchDirectory *d)
-{
- assert(d != nullptr);
-
- unsigned depth = 0;
- while ((d = d->parent) != nullptr)
- ++depth;
-
- return depth;
-}
-
-static void
-mpd_inotify_callback(int wd, unsigned mask,
- gcc_unused const char *name, gcc_unused void *ctx)
-{
- 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;
-
- const auto uri_fs = watch_directory_get_uri_fs(directory);
-
- if ((mask & (IN_DELETE_SELF|IN_MOVE_SELF)) != 0) {
- remove_watch_directory(directory);
- return;
- }
-
- if ((mask & (IN_ATTRIB|IN_CREATE|IN_MOVE)) != 0 &&
- (mask & IN_ISDIR) != 0) {
- /* a sub directory was changed: register those in
- inotify */
- const auto &root = mapper_get_music_directory_fs();
-
- const auto path_fs = uri_fs.IsNull()
- ? root
- : AllocatedPath::Build(root, uri_fs.c_str());
-
- recursive_watch_subdirectories(directory, path_fs,
- watch_directory_depth(directory));
- }
-
- if ((mask & (IN_CLOSE_WRITE|IN_MOVE|IN_DELETE)) != 0 ||
- /* at the maximum depth, we watch out for newly created
- directories */
- (watch_directory_depth(directory) == inotify_max_depth &&
- (mask & (IN_CREATE|IN_ISDIR)) == (IN_CREATE|IN_ISDIR))) {
- /* a file was changed, or a directory was
- moved/deleted: queue a database update */
-
- if (!uri_fs.IsNull()) {
- const std::string uri_utf8 = uri_fs.ToUTF8();
- if (!uri_utf8.empty())
- inotify_queue->Enqueue(uri_utf8.c_str());
- }
- else
- inotify_queue->Enqueue("");
- }
-}
-
-void
-mpd_inotify_init(unsigned max_depth)
-{
- LogDebug(inotify_domain, "initializing inotify");
-
- const auto &path = mapper_get_music_directory_fs();
- if (path.IsNull()) {
- LogDebug(inotify_domain, "no music directory configured");
- return;
- }
-
- Error error;
- inotify_source = InotifySource::Create(*main_loop,
- mpd_inotify_callback, nullptr,
- error);
- if (inotify_source == nullptr) {
- LogError(error);
- return;
- }
-
- inotify_max_depth = max_depth;
-
- int descriptor = inotify_source->Add(path.c_str(), IN_MASK, error);
- if (descriptor < 0) {
- LogError(error);
- delete inotify_source;
- inotify_source = nullptr;
- return;
- }
-
- inotify_root = new WatchDirectory(nullptr, path, descriptor);
-
- tree_add_watch_directory(inotify_root);
-
- recursive_watch_subdirectories(inotify_root, path, 0);
-
- inotify_queue = new InotifyQueue(*main_loop);
-
- LogDebug(inotify_domain, "watching music directory");
-}
-
-void
-mpd_inotify_finish(void)
-{
- if (inotify_source == nullptr)
- return;
-
- delete inotify_queue;
- delete inotify_source;
- delete inotify_root;
- inotify_directories.clear();
-}