Commit 96019f4a authored by Denis Krjuchkov's avatar Denis Krjuchkov

UpdateWalk, ExcludeList: use Path, file system API, DirectoryReader, log in UTF8

parent 896015bf
......@@ -63,14 +63,14 @@ ExcludeList::LoadFile(const Path &path_fs)
}
bool
ExcludeList::Check(const char *name_fs) const
ExcludeList::Check(const Path &name_fs) const
{
assert(name_fs != NULL);
assert(!name_fs.IsNull());
/* XXX include full path name in check */
for (const auto &i : patterns)
if (i.Check(name_fs))
if (i.Check(name_fs.c_str()))
return true;
return false;
......
......@@ -73,7 +73,7 @@ public:
* Checks whether one of the patterns in the .mpdignore file matches
* the specified file name.
*/
bool Check(const char *name_fs) const;
bool Check(const Path &name_fs) const;
};
......
......@@ -34,6 +34,7 @@
#include "conf.h"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "fs/DirectoryReader.hxx"
#include "util/UriUtil.hxx"
#include <glib.h>
......@@ -102,7 +103,7 @@ remove_excluded_from_directory(Directory *directory,
directory_for_each_child_safe(child, n, directory) {
const Path name_fs = Path::FromUTF8(child->GetName());
if (name_fs.IsNull() || exclude_list.Check(name_fs.c_str())) {
if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
delete_directory(child);
modified = true;
}
......@@ -113,7 +114,7 @@ remove_excluded_from_directory(Directory *directory,
assert(song->parent == directory);
const Path name_fs = Path::FromUTF8(song->uri);
if (name_fs.IsNull() || exclude_list.Check(name_fs.c_str())) {
if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
delete_song(directory, song);
modified = true;
}
......@@ -261,8 +262,9 @@ update_directory_child(Directory *directory,
/* we don't look at "." / ".." nor files with newlines in their name */
G_GNUC_PURE
static bool skip_path(const char *path)
static bool skip_path(const Path &path_fs)
{
const char *path = path_fs.c_str();
return (path[0] == '.' && path[1] == 0) ||
(path[0] == '.' && path[1] == '.' && path[2] == 0) ||
strchr(path, '\n') != NULL;
......@@ -277,20 +279,11 @@ skip_symlink(const Directory *directory, const char *utf8_name)
if (path_fs.IsNull())
return true;
char buffer[MPD_PATH_MAX];
ssize_t length = readlink(path_fs.c_str(), buffer, sizeof(buffer));
if (length < 0)
const Path target = ReadLink(path_fs);
if (target.IsNull())
/* don't skip if this is not a symlink */
return errno != EINVAL;
if ((size_t)length >= sizeof(buffer))
/* skip symlinks when the buffer is too small for the
link target */
return true;
/* null-terminate the buffer, because readlink() will not */
buffer[length] = 0;
if (!follow_inside_symlinks && !follow_outside_symlinks) {
/* ignore all symlinks */
return true;
......@@ -299,16 +292,18 @@ skip_symlink(const Directory *directory, const char *utf8_name)
return false;
}
if (g_path_is_absolute(buffer)) {
const char *target_str = target.c_str();
if (g_path_is_absolute(target_str)) {
/* if the symlink points to an absolute path, see if
that path is inside the music directory */
const char *relative = map_to_relative_path(buffer);
return relative > buffer
const char *relative = map_to_relative_path(target_str);
return relative > target_str
? !follow_inside_symlinks
: !follow_outside_symlinks;
}
const char *p = buffer;
const char *p = target_str;
while (*p == '.') {
if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) {
/* "../" moves to parent directory */
......@@ -352,10 +347,12 @@ update_directory(Directory *directory, const struct stat *st)
if (path_fs.IsNull())
return false;
DIR *dir = opendir(path_fs.c_str());
if (!dir) {
DirectoryReader reader(path_fs);
if (reader.HasFailed()) {
int error = errno;
const auto path_utf8 = path_fs.ToUTF8();
g_warning("Failed to open directory %s: %s",
path_fs.c_str(), g_strerror(errno));
path_utf8.c_str(), g_strerror(error));
return false;
}
......@@ -367,15 +364,16 @@ update_directory(Directory *directory, const struct stat *st)
purge_deleted_from_directory(directory);
struct dirent *ent;
while ((ent = readdir(dir))) {
while (reader.ReadEntry()) {
std::string utf8;
struct stat st2;
if (skip_path(ent->d_name) || exclude_list.Check(ent->d_name))
const Path entry = reader.GetEntry();
if (skip_path(entry) || exclude_list.Check(entry))
continue;
utf8 = Path::ToUTF8(ent->d_name);
utf8 = entry.ToUTF8();
if (utf8.empty())
continue;
......@@ -390,8 +388,6 @@ update_directory(Directory *directory, const struct stat *st)
modified |= delete_name_in(directory, utf8.c_str());
}
closedir(dir);
directory->mtime = st->st_mtime;
return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment