InotifyUpdate: use class Path

This commit is contained in:
Max Kellermann 2013-10-17 01:16:46 +02:00
parent 5327ea13ac
commit abb0549e4b

View File

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