UpdateWalk, ExcludeList: use Path, file system API, DirectoryReader, log in UTF8
This commit is contained in:
@@ -63,14 +63,14 @@ ExcludeList::LoadFile(const Path &path_fs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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 */
|
/* XXX include full path name in check */
|
||||||
|
|
||||||
for (const auto &i : patterns)
|
for (const auto &i : patterns)
|
||||||
if (i.Check(name_fs))
|
if (i.Check(name_fs.c_str()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -73,7 +73,7 @@ public:
|
|||||||
* Checks whether one of the patterns in the .mpdignore file matches
|
* Checks whether one of the patterns in the .mpdignore file matches
|
||||||
* the specified file name.
|
* 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 "conf.h"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
|
#include "fs/DirectoryReader.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@@ -102,7 +103,7 @@ remove_excluded_from_directory(Directory *directory,
|
|||||||
directory_for_each_child_safe(child, n, directory) {
|
directory_for_each_child_safe(child, n, directory) {
|
||||||
const Path name_fs = Path::FromUTF8(child->GetName());
|
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);
|
delete_directory(child);
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ remove_excluded_from_directory(Directory *directory,
|
|||||||
assert(song->parent == directory);
|
assert(song->parent == directory);
|
||||||
|
|
||||||
const Path name_fs = Path::FromUTF8(song->uri);
|
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);
|
delete_song(directory, song);
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
@@ -261,8 +262,9 @@ update_directory_child(Directory *directory,
|
|||||||
|
|
||||||
/* we don't look at "." / ".." nor files with newlines in their name */
|
/* we don't look at "." / ".." nor files with newlines in their name */
|
||||||
G_GNUC_PURE
|
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) ||
|
return (path[0] == '.' && path[1] == 0) ||
|
||||||
(path[0] == '.' && path[1] == '.' && path[2] == 0) ||
|
(path[0] == '.' && path[1] == '.' && path[2] == 0) ||
|
||||||
strchr(path, '\n') != NULL;
|
strchr(path, '\n') != NULL;
|
||||||
@@ -277,20 +279,11 @@ skip_symlink(const Directory *directory, const char *utf8_name)
|
|||||||
if (path_fs.IsNull())
|
if (path_fs.IsNull())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
char buffer[MPD_PATH_MAX];
|
const Path target = ReadLink(path_fs);
|
||||||
ssize_t length = readlink(path_fs.c_str(), buffer, sizeof(buffer));
|
if (target.IsNull())
|
||||||
if (length < 0)
|
|
||||||
/* don't skip if this is not a symlink */
|
/* don't skip if this is not a symlink */
|
||||||
return errno != EINVAL;
|
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) {
|
if (!follow_inside_symlinks && !follow_outside_symlinks) {
|
||||||
/* ignore all symlinks */
|
/* ignore all symlinks */
|
||||||
return true;
|
return true;
|
||||||
@@ -299,16 +292,18 @@ skip_symlink(const Directory *directory, const char *utf8_name)
|
|||||||
return false;
|
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
|
/* if the symlink points to an absolute path, see if
|
||||||
that path is inside the music directory */
|
that path is inside the music directory */
|
||||||
const char *relative = map_to_relative_path(buffer);
|
const char *relative = map_to_relative_path(target_str);
|
||||||
return relative > buffer
|
return relative > target_str
|
||||||
? !follow_inside_symlinks
|
? !follow_inside_symlinks
|
||||||
: !follow_outside_symlinks;
|
: !follow_outside_symlinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *p = buffer;
|
const char *p = target_str;
|
||||||
while (*p == '.') {
|
while (*p == '.') {
|
||||||
if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) {
|
if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) {
|
||||||
/* "../" moves to parent directory */
|
/* "../" moves to parent directory */
|
||||||
@@ -352,10 +347,12 @@ update_directory(Directory *directory, const struct stat *st)
|
|||||||
if (path_fs.IsNull())
|
if (path_fs.IsNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
DIR *dir = opendir(path_fs.c_str());
|
DirectoryReader reader(path_fs);
|
||||||
if (!dir) {
|
if (reader.HasFailed()) {
|
||||||
|
int error = errno;
|
||||||
|
const auto path_utf8 = path_fs.ToUTF8();
|
||||||
g_warning("Failed to open directory %s: %s",
|
g_warning("Failed to open directory %s: %s",
|
||||||
path_fs.c_str(), g_strerror(errno));
|
path_utf8.c_str(), g_strerror(error));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,15 +364,16 @@ update_directory(Directory *directory, const struct stat *st)
|
|||||||
|
|
||||||
purge_deleted_from_directory(directory);
|
purge_deleted_from_directory(directory);
|
||||||
|
|
||||||
struct dirent *ent;
|
while (reader.ReadEntry()) {
|
||||||
while ((ent = readdir(dir))) {
|
|
||||||
std::string utf8;
|
std::string utf8;
|
||||||
struct stat st2;
|
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;
|
continue;
|
||||||
|
|
||||||
utf8 = Path::ToUTF8(ent->d_name);
|
utf8 = entry.ToUTF8();
|
||||||
if (utf8.empty())
|
if (utf8.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -390,8 +388,6 @@ update_directory(Directory *directory, const struct stat *st)
|
|||||||
modified |= delete_name_in(directory, utf8.c_str());
|
modified |= delete_name_in(directory, utf8.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
directory->mtime = st->st_mtime;
|
directory->mtime = st->st_mtime;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user