InotifyUpdate: use class Path
This commit is contained in:
parent
5327ea13ac
commit
abb0549e4b
@ -25,11 +25,11 @@
|
|||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
|
#include "fs/FileSystem.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <string>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
|
|
||||||
@ -50,23 +50,20 @@ enum {
|
|||||||
struct WatchDirectory {
|
struct WatchDirectory {
|
||||||
WatchDirectory *parent;
|
WatchDirectory *parent;
|
||||||
|
|
||||||
char *name;
|
Path name;
|
||||||
|
|
||||||
int descriptor;
|
int descriptor;
|
||||||
|
|
||||||
std::forward_list<WatchDirectory> children;
|
std::forward_list<WatchDirectory> children;
|
||||||
|
|
||||||
WatchDirectory(WatchDirectory *_parent, const char *_name,
|
template<typename N>
|
||||||
|
WatchDirectory(WatchDirectory *_parent, N &&_name,
|
||||||
int _descriptor)
|
int _descriptor)
|
||||||
:parent(_parent), name(g_strdup(_name)),
|
:parent(_parent), name(std::forward<N>(_name)),
|
||||||
descriptor(_descriptor) {}
|
descriptor(_descriptor) {}
|
||||||
|
|
||||||
WatchDirectory(const WatchDirectory &) = delete;
|
WatchDirectory(const WatchDirectory &) = delete;
|
||||||
WatchDirectory &operator=(const WatchDirectory &) = delete;
|
WatchDirectory &operator=(const WatchDirectory &) = delete;
|
||||||
|
|
||||||
~WatchDirectory() {
|
|
||||||
g_free(name);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static InotifySource *inotify_source;
|
static InotifySource *inotify_source;
|
||||||
@ -132,22 +129,17 @@ remove_watch_directory(WatchDirectory *directory)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static Path
|
||||||
watch_directory_get_uri_fs(const WatchDirectory *directory)
|
watch_directory_get_uri_fs(const WatchDirectory *directory)
|
||||||
{
|
{
|
||||||
char *parent_uri, *uri;
|
|
||||||
|
|
||||||
if (directory->parent == NULL)
|
if (directory->parent == NULL)
|
||||||
return NULL;
|
return Path::Null();
|
||||||
|
|
||||||
parent_uri = watch_directory_get_uri_fs(directory->parent);
|
Path uri = watch_directory_get_uri_fs(directory->parent);
|
||||||
if (parent_uri == NULL)
|
if (uri.IsNull())
|
||||||
return g_strdup(directory->name);
|
return directory->name;
|
||||||
|
|
||||||
uri = g_strconcat(parent_uri, "/", directory->name, NULL);
|
return Path::Build(uri, directory->name);
|
||||||
g_free(parent_uri);
|
|
||||||
|
|
||||||
return uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't look at "." / ".." nor files with newlines in their name */
|
/* we don't look at "." / ".." nor files with newlines in their name */
|
||||||
@ -160,7 +152,7 @@ static bool skip_path(const char *path)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
recursive_watch_subdirectories(WatchDirectory *directory,
|
recursive_watch_subdirectories(WatchDirectory *directory,
|
||||||
const char *path_fs, unsigned depth)
|
const Path &path_fs, unsigned depth)
|
||||||
{
|
{
|
||||||
Error error;
|
Error error;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
@ -168,66 +160,62 @@ recursive_watch_subdirectories(WatchDirectory *directory,
|
|||||||
|
|
||||||
assert(directory != NULL);
|
assert(directory != NULL);
|
||||||
assert(depth <= inotify_max_depth);
|
assert(depth <= inotify_max_depth);
|
||||||
assert(path_fs != NULL);
|
assert(!path_fs.IsNull());
|
||||||
|
|
||||||
++depth;
|
++depth;
|
||||||
|
|
||||||
if (depth > inotify_max_depth)
|
if (depth > inotify_max_depth)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dir = opendir(path_fs);
|
dir = opendir(path_fs.c_str());
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
FormatErrno(inotify_domain,
|
FormatErrno(inotify_domain,
|
||||||
"Failed to open directory %s", path_fs);
|
"Failed to open directory %s", path_fs.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ent = readdir(dir))) {
|
while ((ent = readdir(dir))) {
|
||||||
char *child_path_fs;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (skip_path(ent->d_name))
|
if (skip_path(ent->d_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
child_path_fs = g_strconcat(path_fs, "/", ent->d_name, NULL);
|
const Path child_path_fs = Path::Build(path_fs, ent->d_name);
|
||||||
ret = stat(child_path_fs, &st);
|
ret = StatFile(child_path_fs, st);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
FormatErrno(inotify_domain,
|
FormatErrno(inotify_domain,
|
||||||
"Failed to stat %s",
|
"Failed to stat %s",
|
||||||
child_path_fs);
|
child_path_fs.c_str());
|
||||||
g_free(child_path_fs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
if (!S_ISDIR(st.st_mode))
|
||||||
g_free(child_path_fs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
ret = inotify_source->Add(child_path_fs, IN_MASK, error);
|
ret = inotify_source->Add(child_path_fs.c_str(), IN_MASK,
|
||||||
|
error);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
FormatError(error,
|
FormatError(error,
|
||||||
"Failed to register %s", child_path_fs);
|
"Failed to register %s",
|
||||||
|
child_path_fs.c_str());
|
||||||
error.Clear();
|
error.Clear();
|
||||||
g_free(child_path_fs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
WatchDirectory *child = tree_find_watch_directory(ret);
|
WatchDirectory *child = tree_find_watch_directory(ret);
|
||||||
if (child != NULL) {
|
if (child != nullptr)
|
||||||
/* already being watched */
|
/* already being watched */
|
||||||
g_free(child_path_fs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
directory->children.emplace_front(directory, ent->d_name, ret);
|
directory->children.emplace_front(directory,
|
||||||
|
Path::FromFS(ent->d_name),
|
||||||
|
ret);
|
||||||
child = &directory->children.front();
|
child = &directory->children.front();
|
||||||
|
|
||||||
tree_add_watch_directory(child);
|
tree_add_watch_directory(child);
|
||||||
|
|
||||||
recursive_watch_subdirectories(child, child_path_fs, depth);
|
recursive_watch_subdirectories(child, child_path_fs, depth);
|
||||||
g_free(child_path_fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@ -251,7 +239,6 @@ mpd_inotify_callback(int wd, unsigned mask,
|
|||||||
gcc_unused const char *name, gcc_unused void *ctx)
|
gcc_unused const char *name, gcc_unused void *ctx)
|
||||||
{
|
{
|
||||||
WatchDirectory *directory;
|
WatchDirectory *directory;
|
||||||
char *uri_fs;
|
|
||||||
|
|
||||||
/*FormatDebug(inotify_domain, "wd=%d mask=0x%x name='%s'", wd, mask, name);*/
|
/*FormatDebug(inotify_domain, "wd=%d mask=0x%x name='%s'", wd, mask, name);*/
|
||||||
|
|
||||||
@ -259,10 +246,9 @@ mpd_inotify_callback(int wd, unsigned mask,
|
|||||||
if (directory == NULL)
|
if (directory == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uri_fs = watch_directory_get_uri_fs(directory);
|
const auto uri_fs = watch_directory_get_uri_fs(directory);
|
||||||
|
|
||||||
if ((mask & (IN_DELETE_SELF|IN_MOVE_SELF)) != 0) {
|
if ((mask & (IN_DELETE_SELF|IN_MOVE_SELF)) != 0) {
|
||||||
g_free(uri_fs);
|
|
||||||
remove_watch_directory(directory);
|
remove_watch_directory(directory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -271,19 +257,14 @@ mpd_inotify_callback(int wd, unsigned mask,
|
|||||||
(mask & IN_ISDIR) != 0) {
|
(mask & IN_ISDIR) != 0) {
|
||||||
/* a sub directory was changed: register those in
|
/* a sub directory was changed: register those in
|
||||||
inotify */
|
inotify */
|
||||||
const char *root = mapper_get_music_directory_fs().c_str();
|
const Path &root = mapper_get_music_directory_fs();
|
||||||
const char *path_fs;
|
|
||||||
char *allocated = NULL;
|
|
||||||
|
|
||||||
if (uri_fs != NULL)
|
const Path path_fs = uri_fs.IsNull()
|
||||||
path_fs = allocated =
|
? root
|
||||||
g_strconcat(root, "/", uri_fs, NULL);
|
: Path::Build(root, uri_fs.c_str());
|
||||||
else
|
|
||||||
path_fs = root;
|
|
||||||
|
|
||||||
recursive_watch_subdirectories(directory, path_fs,
|
recursive_watch_subdirectories(directory, path_fs,
|
||||||
watch_directory_depth(directory));
|
watch_directory_depth(directory));
|
||||||
g_free(allocated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mask & (IN_CLOSE_WRITE|IN_MOVE|IN_DELETE)) != 0 ||
|
if ((mask & (IN_CLOSE_WRITE|IN_MOVE|IN_DELETE)) != 0 ||
|
||||||
@ -294,16 +275,14 @@ mpd_inotify_callback(int wd, unsigned mask,
|
|||||||
/* a file was changed, or a directory was
|
/* a file was changed, or a directory was
|
||||||
moved/deleted: queue a database update */
|
moved/deleted: queue a database update */
|
||||||
|
|
||||||
if (uri_fs != nullptr) {
|
if (!uri_fs.IsNull()) {
|
||||||
const std::string uri_utf8 = Path::ToUTF8(uri_fs);
|
const std::string uri_utf8 = uri_fs.ToUTF8();
|
||||||
if (!uri_utf8.empty())
|
if (!uri_utf8.empty())
|
||||||
inotify_queue->Enqueue(uri_utf8.c_str());
|
inotify_queue->Enqueue(uri_utf8.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
inotify_queue->Enqueue("");
|
inotify_queue->Enqueue("");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(uri_fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -336,11 +315,11 @@ mpd_inotify_init(unsigned max_depth)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inotify_root = new WatchDirectory(nullptr, path.c_str(), descriptor);
|
inotify_root = new WatchDirectory(nullptr, path, descriptor);
|
||||||
|
|
||||||
tree_add_watch_directory(inotify_root);
|
tree_add_watch_directory(inotify_root);
|
||||||
|
|
||||||
recursive_watch_subdirectories(inotify_root, path.c_str(), 0);
|
recursive_watch_subdirectories(inotify_root, path, 0);
|
||||||
|
|
||||||
inotify_queue = new InotifyQueue(*main_loop);
|
inotify_queue = new InotifyQueue(*main_loop);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user