From 9ae7f186bc43749383594807b1d751b5389161e7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 29 Jan 2014 18:14:57 +0100 Subject: LocalStorage: new API abstracting filesystem walk Prepare to make this a new plugin API, for example to use a SMB share for the music_directory. --- src/db/update/Archive.cxx | 18 +++-- src/db/update/Container.cxx | 27 ++++--- src/db/update/UpdateIO.cxx | 91 ++++++++++------------ src/db/update/UpdateIO.hxx | 28 ++++--- src/db/update/UpdateSong.cxx | 15 ++-- src/db/update/Walk.cxx | 179 ++++++++++++++++++++++++------------------- src/db/update/Walk.hxx | 27 ++++--- 7 files changed, 211 insertions(+), 174 deletions(-) (limited to 'src/db/update') diff --git a/src/db/update/Archive.cxx b/src/db/update/Archive.cxx index 0d7127685..9874eb1f2 100644 --- a/src/db/update/Archive.cxx +++ b/src/db/update/Archive.cxx @@ -23,8 +23,8 @@ #include "db/DatabaseLock.hxx" #include "db/Directory.hxx" #include "db/Song.hxx" -#include "Mapper.hxx" #include "fs/AllocatedPath.hxx" +#include "storage/FileInfo.hxx" #include "archive/ArchiveList.hxx" #include "archive/ArchivePlugin.hxx" #include "archive/ArchiveFile.hxx" @@ -103,20 +103,24 @@ class UpdateArchiveVisitor final : public ArchiveVisitor { */ void UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name, - const struct stat *st, + const FileInfo &info, const archive_plugin &plugin) { db_lock(); Directory *directory = parent.FindChild(name); db_unlock(); - if (directory != nullptr && directory->mtime == st->st_mtime && + if (directory != nullptr && directory->mtime == info.mtime && !walk_discard) /* MPD has already scanned the archive, and it hasn't changed since - don't consider updating it */ return; - const auto path_fs = map_directory_child_fs(parent, name); + const auto path_fs = storage.MapChildFS(parent.GetPath(), name); + if (path_fs.IsNull()) + /* not a local file: skip, because the archive API + supports only local files */ + return; /* open archive */ Error error; @@ -141,7 +145,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name, db_unlock(); } - directory->mtime = st->st_mtime; + directory->mtime = info.mtime; UpdateArchiveVisitor visitor(*this, directory); file->Visit(visitor); @@ -151,13 +155,13 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name, bool UpdateWalk::UpdateArchiveFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st) + const FileInfo &info) { const struct archive_plugin *plugin = archive_plugin_from_suffix(suffix); if (plugin == nullptr) return false; - UpdateArchiveFile(directory, name, st, *plugin); + UpdateArchiveFile(directory, name, info, *plugin); return true; } diff --git a/src/db/update/Container.cxx b/src/db/update/Container.cxx index 33e29953d..956db7209 100644 --- a/src/db/update/Container.cxx +++ b/src/db/update/Container.cxx @@ -25,8 +25,8 @@ #include "db/Song.hxx" #include "decoder/DecoderPlugin.hxx" #include "decoder/DecoderList.hxx" -#include "Mapper.hxx" #include "fs/AllocatedPath.hxx" +#include "storage/FileInfo.hxx" #include "tag/TagHandler.hxx" #include "tag/TagBuilder.hxx" #include "Log.hxx" @@ -37,13 +37,13 @@ Directory * UpdateWalk::MakeDirectoryIfModified(Directory &parent, const char *name, - const struct stat *st) + const FileInfo &info) { Directory *directory = parent.FindChild(name); // directory exists already if (directory != nullptr) { - if (directory->mtime == st->st_mtime && !walk_discard) { + if (directory->mtime == info.mtime && !walk_discard) { /* not modified */ return nullptr; } @@ -53,7 +53,7 @@ UpdateWalk::MakeDirectoryIfModified(Directory &parent, const char *name, } directory = parent.MakeChild(name); - directory->mtime = st->st_mtime; + directory->mtime = info.mtime; return directory; } @@ -67,7 +67,7 @@ SupportsContainerSuffix(const DecoderPlugin &plugin, const char *suffix) bool UpdateWalk::UpdateContainerFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st) + const FileInfo &info) { const DecoderPlugin *_plugin = decoder_plugins_find([suffix](const DecoderPlugin &plugin){ return SupportsContainerSuffix(plugin, suffix); @@ -77,7 +77,7 @@ UpdateWalk::UpdateContainerFile(Directory &directory, const DecoderPlugin &plugin = *_plugin; db_lock(); - Directory *contdir = MakeDirectoryIfModified(directory, name, st); + Directory *contdir = MakeDirectoryIfModified(directory, name, info); if (contdir == nullptr) { /* not modified */ db_unlock(); @@ -87,7 +87,13 @@ UpdateWalk::UpdateContainerFile(Directory &directory, contdir->device = DEVICE_CONTAINER; db_unlock(); - const auto pathname = map_directory_child_fs(directory, name); + const auto pathname = storage.MapFS(contdir->GetPath()); + if (pathname.IsNull()) { + /* not a local file: skip, because the container API + supports only local files */ + editor.LockDeleteDirectory(contdir); + return false; + } char *vtrack; unsigned int tnum = 0; @@ -96,11 +102,10 @@ UpdateWalk::UpdateContainerFile(Directory &directory, Song *song = Song::NewFile(vtrack, *contdir); // shouldn't be necessary but it's there.. - song->mtime = st->st_mtime; - - const auto child_path_fs = - map_directory_child_fs(*contdir, vtrack); + song->mtime = info.mtime; + const auto child_path_fs = AllocatedPath::Build(pathname, + vtrack); plugin.ScanFile(child_path_fs.c_str(), add_tag_handler, &tag_builder); diff --git a/src/db/update/UpdateIO.cxx b/src/db/update/UpdateIO.cxx index f91caf359..58b1fe296 100644 --- a/src/db/update/UpdateIO.cxx +++ b/src/db/update/UpdateIO.cxx @@ -21,91 +21,84 @@ #include "UpdateIO.hxx" #include "UpdateDomain.hxx" #include "db/Directory.hxx" -#include "Mapper.hxx" -#include "fs/AllocatedPath.hxx" +#include "storage/FileInfo.hxx" +#include "storage/LocalStorage.hxx" +#include "fs/Traits.hxx" #include "fs/FileSystem.hxx" +#include "util/Error.hxx" #include "Log.hxx" #include #include -int -stat_directory(const Directory &directory, struct stat *st) +bool +GetInfo(LocalStorage &storage, const char *uri_utf8, FileInfo &info) { - const auto path_fs = map_directory_fs(directory); - if (path_fs.IsNull()) - return -1; - - if (!StatFile(path_fs, *st)) { - int error = errno; - const std::string path_utf8 = path_fs.ToUTF8(); - FormatErrno(update_domain, error, - "Failed to stat %s", path_utf8.c_str()); - return -1; - } - - return 0; + Error error; + bool success = storage.GetInfo(uri_utf8, true, info, error); + if (!success) + LogError(error); + return success; } -int -stat_directory_child(const Directory &parent, const char *name, - struct stat *st) +bool +GetInfo(LocalDirectoryReader &reader, FileInfo &info) { - const auto path_fs = map_directory_child_fs(parent, name); - if (path_fs.IsNull()) - return -1; - - if (!StatFile(path_fs, *st)) { - int error = errno; - const std::string path_utf8 = path_fs.ToUTF8(); - FormatErrno(update_domain, error, - "Failed to stat %s", path_utf8.c_str()); - return -1; - } - - return 0; + Error error; + bool success = reader.GetInfo(true, info, error); + if (!success) + LogError(error); + return success; } bool -directory_exists(const Directory &directory) +DirectoryExists(LocalStorage &storage, const Directory &directory) { - const auto path_fs = map_directory_fs(directory); - if (path_fs.IsNull()) - /* invalid path: cannot exist */ + FileInfo info; + if (!storage.GetInfo(directory.GetPath(), true, info, IgnoreError())) return false; return directory.device == DEVICE_INARCHIVE || directory.device == DEVICE_CONTAINER - ? FileExists(path_fs) - : DirectoryExists(path_fs); + ? info.IsRegular() + : info.IsDirectory(); +} + +static bool +GetDirectoryChildInfo(LocalStorage &storage, const Directory &directory, + const char *name_utf8, FileInfo &info, Error &error) +{ + const auto uri_utf8 = PathTraitsUTF8::Build(directory.GetPath(), + name_utf8); + return storage.GetInfo(uri_utf8.c_str(), true, info, error); } bool -directory_child_is_regular(const Directory &directory, +directory_child_is_regular(LocalStorage &storage, const Directory &directory, const char *name_utf8) { - const auto path_fs = map_directory_child_fs(directory, name_utf8); - if (path_fs.IsNull()) - return false; - - return FileExists(path_fs); + FileInfo info; + return GetDirectoryChildInfo(storage, directory, name_utf8, info, + IgnoreError()) && + info.IsRegular(); } bool -directory_child_access(const Directory &directory, +directory_child_access(LocalStorage &storage, const Directory &directory, const char *name, int mode) { #ifdef WIN32 /* CheckAccess() is useless on WIN32 */ + (void)storage; (void)directory; (void)name; (void)mode; return true; #else - const auto path = map_directory_child_fs(directory, name); + const auto path = storage.MapChildFS(directory.GetPath(), name); if (path.IsNull()) - /* something went wrong, but that isn't a permission - problem */ + /* does not point to local file: silently ignore the + check */ return true; return CheckAccess(path, mode) || errno != EACCES; diff --git a/src/db/update/UpdateIO.hxx b/src/db/update/UpdateIO.hxx index c33b79dc0..d5cbb2a5b 100644 --- a/src/db/update/UpdateIO.hxx +++ b/src/db/update/UpdateIO.hxx @@ -23,24 +23,32 @@ #include "check.h" #include "Compiler.h" -#include - struct Directory; +struct FileInfo; +class LocalStorage; +class LocalDirectoryReader; -int -stat_directory(const Directory &directory, struct stat *st); +/** + * Wrapper for LocalStorage::GetInfo() that logs errors instead of + * returning them. + */ +bool +GetInfo(LocalStorage &storage, const char *uri_utf8, FileInfo &info); -int -stat_directory_child(const Directory &parent, const char *name, - struct stat *st); +/** + * Wrapper for LocalDirectoryReader::GetInfo() that logs errors + * instead of returning them. + */ +bool +GetInfo(LocalDirectoryReader &reader, FileInfo &info); gcc_pure bool -directory_exists(const Directory &directory); +DirectoryExists(LocalStorage &storage, const Directory &directory); gcc_pure bool -directory_child_is_regular(const Directory &directory, +directory_child_is_regular(LocalStorage &storage, const Directory &directory, const char *name_utf8); /** @@ -48,7 +56,7 @@ directory_child_is_regular(const Directory &directory, */ gcc_pure bool -directory_child_access(const Directory &directory, +directory_child_access(LocalStorage &storage, const Directory &directory, const char *name, int mode); #endif diff --git a/src/db/update/UpdateSong.cxx b/src/db/update/UpdateSong.cxx index 751d8bfe9..2868249e7 100644 --- a/src/db/update/UpdateSong.cxx +++ b/src/db/update/UpdateSong.cxx @@ -25,6 +25,7 @@ #include "db/Directory.hxx" #include "db/Song.hxx" #include "decoder/DecoderList.hxx" +#include "storage/FileInfo.hxx" #include "Log.hxx" #include @@ -32,13 +33,13 @@ inline void UpdateWalk::UpdateSongFile2(Directory &directory, const char *name, const char *suffix, - const struct stat *st) + const FileInfo &info) { db_lock(); Song *song = directory.FindSong(name); db_unlock(); - if (!directory_child_access(directory, name, R_OK)) { + if (!directory_child_access(storage, directory, name, R_OK)) { FormatError(update_domain, "no read permissions on %s/%s", directory.GetPath(), name); @@ -48,9 +49,9 @@ UpdateWalk::UpdateSongFile2(Directory &directory, return; } - if (!(song != nullptr && st->st_mtime == song->mtime && + if (!(song != nullptr && info.mtime == song->mtime && !walk_discard) && - UpdateContainerFile(directory, name, suffix, st)) { + UpdateContainerFile(directory, name, suffix, info)) { if (song != nullptr) editor.LockDeleteSong(directory, song); @@ -75,7 +76,7 @@ UpdateWalk::UpdateSongFile2(Directory &directory, modified = true; FormatDefault(update_domain, "added %s/%s", directory.GetPath(), name); - } else if (st->st_mtime != song->mtime || walk_discard) { + } else if (info.mtime != song->mtime || walk_discard) { FormatDefault(update_domain, "updating %s/%s", directory.GetPath(), name); if (!song->UpdateFile()) { @@ -92,11 +93,11 @@ UpdateWalk::UpdateSongFile2(Directory &directory, bool UpdateWalk::UpdateSongFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st) + const FileInfo &info) { if (!decoder_plugins_supports_suffix(suffix)) return false; - UpdateSongFile2(directory, name, suffix, st); + UpdateSongFile2(directory, name, suffix, info); return true; } diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index c54d5a8d7..e6bfdcfd9 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -35,9 +35,10 @@ #include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" -#include "fs/DirectoryReader.hxx" +#include "storage/FileInfo.hxx" #include "util/Alloc.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "Log.hxx" #include @@ -47,7 +48,9 @@ #include UpdateWalk::UpdateWalk(EventLoop &_loop, DatabaseListener &_listener) - :editor(_loop, _listener) + :storage(mapper_get_music_directory_utf8(), + mapper_get_music_directory_fs()), + editor(_loop, _listener) { #ifndef WIN32 follow_inside_symlinks = @@ -61,10 +64,10 @@ UpdateWalk::UpdateWalk(EventLoop &_loop, DatabaseListener &_listener) } static void -directory_set_stat(Directory &dir, const struct stat *st) +directory_set_stat(Directory &dir, const FileInfo &info) { - dir.inode = st->st_ino; - dir.device = st->st_dev; + dir.inode = info.inode; + dir.device = info.device; dir.have_stat = true; } @@ -103,7 +106,7 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) { Directory *child, *n; directory_for_each_child_safe(child, n, directory) { - if (directory_exists(*child)) + if (DirectoryExists(storage, *child)) continue; editor.LockDeleteDirectory(child); @@ -113,8 +116,8 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) Song *song, *ns; directory_for_each_song_safe(song, ns, directory) { - const auto path = map_song_fs(*song); - if (path.IsNull() || !FileExists(path)) { + if (!directory_child_is_regular(storage, directory, + song->uri)) { editor.LockDeleteSong(directory, song); modified = true; @@ -124,7 +127,8 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) for (auto i = directory.playlists.begin(), end = directory.playlists.end(); i != end;) { - if (!directory_child_is_regular(directory, i->name.c_str())) { + if (!directory_child_is_regular(storage, directory, + i->name.c_str())) { db_lock(); i = directory.playlists.erase(i); db_unlock(); @@ -134,24 +138,26 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) } #ifndef WIN32 -static int -update_directory_stat(Directory &directory) +static bool +update_directory_stat(LocalStorage &storage, Directory &directory) { - struct stat st; - if (stat_directory(directory, &st) < 0) - return -1; + FileInfo info; + if (!GetInfo(storage, directory.GetPath(), info)) + return false; - directory_set_stat(directory, &st); - return 0; + directory_set_stat(directory, info); + return true; } #endif static int -find_inode_ancestor(Directory *parent, ino_t inode, dev_t device) +find_inode_ancestor(LocalStorage &storage, Directory *parent, + unsigned inode, unsigned device) { #ifndef WIN32 while (parent) { - if (!parent->have_stat && update_directory_stat(*parent) < 0) + if (!parent->have_stat && + !update_directory_stat(storage, *parent)) return -1; if (parent->inode == inode && parent->device == device) { @@ -162,6 +168,7 @@ find_inode_ancestor(Directory *parent, ino_t inode, dev_t device) parent = parent->parent; } #else + (void)storage; (void)parent; (void)inode; (void)device; @@ -173,12 +180,12 @@ find_inode_ancestor(Directory *parent, ino_t inode, dev_t device) inline bool UpdateWalk::UpdatePlaylistFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st) + const FileInfo &info) { if (!playlist_suffix_supported(suffix)) return false; - PlaylistInfo pi(name, st->st_mtime); + PlaylistInfo pi(name, info.mtime); db_lock(); if (directory.playlists.UpdateOrInsert(std::move(pi))) @@ -189,27 +196,28 @@ UpdateWalk::UpdatePlaylistFile(Directory &directory, inline bool UpdateWalk::UpdateRegularFile(Directory &directory, - const char *name, const struct stat *st) + const char *name, const FileInfo &info) { const char *suffix = uri_get_suffix(name); if (suffix == nullptr) return false; - return UpdateSongFile(directory, name, suffix, st) || - UpdateArchiveFile(directory, name, suffix, st) || - UpdatePlaylistFile(directory, name, suffix, st); + return UpdateSongFile(directory, name, suffix, info) || + UpdateArchiveFile(directory, name, suffix, info) || + UpdatePlaylistFile(directory, name, suffix, info); } void UpdateWalk::UpdateDirectoryChild(Directory &directory, - const char *name, const struct stat *st) + const char *name, const FileInfo &info) { assert(strchr(name, '/') == nullptr); - if (S_ISREG(st->st_mode)) { - UpdateRegularFile(directory, name, st); - } else if (S_ISDIR(st->st_mode)) { - if (find_inode_ancestor(&directory, st->st_ino, st->st_dev)) + if (info.IsRegular()) { + UpdateRegularFile(directory, name, info); + } else if (info.IsDirectory()) { + if (find_inode_ancestor(storage, &directory, + info.inode, info.device)) return; db_lock(); @@ -218,7 +226,7 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory, assert(&directory == subdir->parent); - if (!UpdateDirectory(*subdir, st)) + if (!UpdateDirectory(*subdir, info)) editor.LockDeleteDirectory(subdir); } else { FormatDebug(update_domain, @@ -228,12 +236,10 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory, /* we don't look at "." / ".." nor files with newlines in their name */ gcc_pure -static bool skip_path(Path path_fs) +static bool +skip_path(const char *name_utf8) { - const char *path = path_fs.c_str(); - return (path[0] == '.' && path[1] == 0) || - (path[0] == '.' && path[1] == '.' && path[2] == 0) || - strchr(path, '\n') != nullptr; + return strchr(name_utf8, '\n') != nullptr; } gcc_pure @@ -242,9 +248,11 @@ UpdateWalk::SkipSymlink(const Directory *directory, const char *utf8_name) const { #ifndef WIN32 - const auto path_fs = map_directory_child_fs(*directory, utf8_name); + const auto path_fs = storage.MapChildFS(directory->GetPath(), + utf8_name); if (path_fs.IsNull()) - return true; + /* not a local file: don't skip */ + return false; const auto target = ReadLink(path_fs); if (target.IsNull()) @@ -304,63 +312,68 @@ UpdateWalk::SkipSymlink(const Directory *directory, } bool -UpdateWalk::UpdateDirectory(Directory &directory, const struct stat *st) +UpdateWalk::UpdateDirectory(Directory &directory, const FileInfo &info) { - assert(S_ISDIR(st->st_mode)); + assert(info.IsDirectory()); - directory_set_stat(directory, st); + directory_set_stat(directory, info); - const auto path_fs = map_directory_fs(directory); - if (path_fs.IsNull()) - return false; - - DirectoryReader reader(path_fs); - if (reader.HasFailed()) { - int error = errno; - const auto path_utf8 = path_fs.ToUTF8(); - FormatErrno(update_domain, error, - "Failed to open directory %s", - path_utf8.c_str()); + Error error; + LocalDirectoryReader *const reader = + storage.OpenDirectory(directory.GetPath(), error); + if (reader == nullptr) { + LogError(error); return false; } ExcludeList exclude_list; - exclude_list.LoadFile(AllocatedPath::Build(path_fs, ".mpdignore")); + + { + const auto exclude_path_fs = + storage.MapChildFS(directory.GetPath(), ".mpdignore"); + if (!exclude_path_fs.IsNull()) + exclude_list.LoadFile(exclude_path_fs); + } if (!exclude_list.IsEmpty()) RemoveExcludedFromDirectory(directory, exclude_list); PurgeDeletedFromDirectory(directory); - while (reader.ReadEntry()) { - const auto entry = reader.GetEntry(); - - if (skip_path(entry) || exclude_list.Check(entry)) + const char *name_utf8; + while ((name_utf8 = reader->Read()) != nullptr) { + if (skip_path(name_utf8)) continue; - const std::string utf8 = entry.ToUTF8(); - if (utf8.empty()) + { + const auto name_fs = AllocatedPath::FromUTF8(name_utf8); + if (name_fs.IsNull() || exclude_list.Check(name_fs)) + continue; + } + + if (SkipSymlink(&directory, name_utf8)) { + modified |= editor.DeleteNameIn(directory, name_utf8); continue; + } - if (SkipSymlink(&directory, utf8.c_str())) { - modified |= editor.DeleteNameIn(directory, utf8.c_str()); + FileInfo info2; + if (!GetInfo(*reader, info2)) { + modified |= editor.DeleteNameIn(directory, name_utf8); continue; } - struct stat st2; - if (stat_directory_child(directory, utf8.c_str(), &st2) == 0) - UpdateDirectoryChild(directory, utf8.c_str(), &st2); - else - modified |= editor.DeleteNameIn(directory, utf8.c_str()); + UpdateDirectoryChild(directory, name_utf8, info2); } - directory.mtime = st->st_mtime; + directory.mtime = info.mtime; return true; } inline Directory * -UpdateWalk::DirectoryMakeChildChecked(Directory &parent, const char *name_utf8) +UpdateWalk::DirectoryMakeChildChecked(Directory &parent, + const char *uri_utf8, + const char *name_utf8) { db_lock(); Directory *directory = parent.FindChild(name_utf8); @@ -369,9 +382,9 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent, const char *name_utf8) if (directory != nullptr) return directory; - struct stat st; - if (stat_directory_child(parent, name_utf8, &st) < 0 || - find_inode_ancestor(&parent, st.st_ino, st.st_dev)) + FileInfo info; + if (!GetInfo(storage, uri_utf8, info) || + find_inode_ancestor(storage, &parent, info.inode, info.device)) return nullptr; if (SkipSymlink(&parent, name_utf8)) @@ -387,7 +400,7 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent, const char *name_utf8) directory = parent.CreateChild(name_utf8); db_unlock(); - directory_set_stat(*directory, &st); + directory_set_stat(*directory, info); return directory; } @@ -405,6 +418,7 @@ UpdateWalk::DirectoryMakeUriParentChecked(Directory &root, const char *uri) continue; directory = DirectoryMakeChildChecked(*directory, + duplicated, name_utf8); if (directory == nullptr) break; @@ -425,12 +439,18 @@ UpdateWalk::UpdateUri(Directory &root, const char *uri) const char *name = PathTraitsUTF8::GetBase(uri); - struct stat st; - if (!SkipSymlink(parent, name) && - stat_directory_child(*parent, name, &st) == 0) - UpdateDirectoryChild(*parent, name, &st); - else + if (SkipSymlink(parent, name)) { modified |= editor.DeleteNameIn(*parent, name); + return; + } + + FileInfo info; + if (!GetInfo(storage, uri, info)) { + modified |= editor.DeleteNameIn(*parent, name); + return; + } + + UpdateDirectoryChild(*parent, name, info); } bool @@ -442,10 +462,11 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) if (path != nullptr && !isRootDirectory(path)) { UpdateUri(root, path); } else { - struct stat st; + FileInfo info; + if (!GetInfo(storage, "", info)) + return false; - if (stat_directory(root, &st) == 0) - UpdateDirectory(root, &st); + UpdateDirectory(root, info); } return modified; diff --git a/src/db/update/Walk.hxx b/src/db/update/Walk.hxx index aa4516917..c465ea7e1 100644 --- a/src/db/update/Walk.hxx +++ b/src/db/update/Walk.hxx @@ -22,10 +22,12 @@ #include "check.h" #include "Editor.hxx" +#include "storage/LocalStorage.hxx" #include struct stat; +struct FileInfo; struct Directory; struct archive_plugin; class ExcludeList; @@ -46,6 +48,8 @@ class UpdateWalk final { bool walk_discard; bool modified; + LocalStorage storage; + DatabaseEditor editor; public: @@ -68,15 +72,15 @@ private: void UpdateSongFile2(Directory &directory, const char *name, const char *suffix, - const struct stat *st); + const FileInfo &info); bool UpdateSongFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st); + const FileInfo &info); bool UpdateContainerFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st); + const FileInfo &info); #ifdef ENABLE_ARCHIVE @@ -84,10 +88,10 @@ private: bool UpdateArchiveFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st); + const FileInfo &info); void UpdateArchiveFile(Directory &directory, const char *name, - const struct stat *st, + const FileInfo &info, const archive_plugin &plugin); @@ -95,22 +99,22 @@ private: bool UpdateArchiveFile(gcc_unused Directory &directory, gcc_unused const char *name, gcc_unused const char *suffix, - gcc_unused const struct stat *st) { + gcc_unused const FileInfo &info) { return false; } #endif bool UpdatePlaylistFile(Directory &directory, const char *name, const char *suffix, - const struct stat *st); + const FileInfo &info); bool UpdateRegularFile(Directory &directory, - const char *name, const struct stat *st); + const char *name, const FileInfo &info); void UpdateDirectoryChild(Directory &directory, - const char *name, const struct stat *st); + const char *name, const FileInfo &info); - bool UpdateDirectory(Directory &directory, const struct stat *st); + bool UpdateDirectory(Directory &directory, const FileInfo &info); /** * Create the specified directory object if it does not exist @@ -121,9 +125,10 @@ private: * The caller must lock the database. */ Directory *MakeDirectoryIfModified(Directory &parent, const char *name, - const struct stat *st); + const FileInfo &info); Directory *DirectoryMakeChildChecked(Directory &parent, + const char *uri_utf8, const char *name_utf8); Directory *DirectoryMakeUriParentChecked(Directory &root, -- cgit v1.2.3