diff --git a/Makefile.am b/Makefile.am index ebe358d6d..2720e4ad9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -600,7 +600,7 @@ libfs_a_SOURCES = \ src/fs/Glob.hxx \ src/fs/StandardDirectory.cxx src/fs/StandardDirectory.hxx \ src/fs/CheckFile.cxx src/fs/CheckFile.hxx \ - src/fs/DirectoryReader.hxx + src/fs/DirectoryReader.cxx src/fs/DirectoryReader.hxx libfs_a_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) if ENABLE_ZLIB diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index 0bd17b2a2..196641289 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -174,7 +174,7 @@ LoadPlaylistFileInfo(PlaylistInfo &info, } PlaylistVector -ListPlaylistFiles(Error &error) +ListPlaylistFiles() { PlaylistVector list; @@ -182,10 +182,6 @@ ListPlaylistFiles(Error &error) assert(!parent_path_fs.IsNull()); DirectoryReader reader(parent_path_fs); - if (reader.HasFailed()) { - error.SetErrno(); - return list; - } PlaylistInfo info; while (reader.ReadEntry()) { diff --git a/src/PlaylistFile.hxx b/src/PlaylistFile.hxx index 150d35710..5a12f314b 100644 --- a/src/PlaylistFile.hxx +++ b/src/PlaylistFile.hxx @@ -50,11 +50,10 @@ AllocatedPath spl_map_to_fs(const char *name_utf8); /** - * Returns a list of stored_playlist_info struct pointers. Returns - * nullptr if an error occurred. + * Returns a list of stored_playlist_info struct pointers. */ PlaylistVector -ListPlaylistFiles(Error &error); +ListPlaylistFiles(); PlaylistFileContents LoadPlaylistFile(const char *utf8path); diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 486c00d89..3d7f3356a 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -70,15 +70,9 @@ skip_path(Path name_fs) #endif CommandResult -handle_listfiles_local(Response &r, - const char *path_utf8, Path path_fs) +handle_listfiles_local(Response &r, Path path_fs) { DirectoryReader reader(path_fs); - if (reader.HasFailed()) { - Error error; - error.FormatErrno("Failed to open '%s'", path_utf8); - return print_error(r, error); - } while (reader.ReadEntry()) { const Path name_fs = reader.GetEntry(); diff --git a/src/command/FileCommands.hxx b/src/command/FileCommands.hxx index 9c6631df5..92cf59367 100644 --- a/src/command/FileCommands.hxx +++ b/src/command/FileCommands.hxx @@ -28,8 +28,7 @@ class Response; class Path; CommandResult -handle_listfiles_local(Response &response, - const char *path_utf8, Path path_fs); +handle_listfiles_local(Response &response, Path path_fs); CommandResult handle_read_comments(Client &client, Request request, Response &response); diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx index 0b298f33e..3824e5d55 100644 --- a/src/command/OtherCommands.cxx +++ b/src/command/OtherCommands.cxx @@ -49,6 +49,7 @@ #include "Partition.hxx" #include "Instance.hxx" #include "Idle.hxx" +#include "Log.hxx" #ifdef ENABLE_DATABASE #include "DatabaseCommands.hxx" @@ -161,8 +162,7 @@ handle_listfiles(Client &client, Request args, Response &r) case LocatedUri::Type::PATH: /* list local directory */ - return handle_listfiles_local(r, located_uri.canonical_uri, - located_uri.path); + return handle_listfiles_local(r, located_uri.path); } gcc_unreachable(); @@ -197,9 +197,11 @@ handle_lsinfo_relative(Client &client, Response &r, const char *uri) #endif if (isRootDirectory(uri)) { - Error error; - const auto &list = ListPlaylistFiles(error); - print_spl_list(r, list); + try { + print_spl_list(r, ListPlaylistFiles()); + } catch (const std::exception &e) { + LogError(e); + } } else { #ifndef ENABLE_DATABASE r.Error(ACK_ERROR_NO_EXIST, "No database"); diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx index 10135467b..1c5de81fe 100644 --- a/src/command/PlaylistCommands.cxx +++ b/src/command/PlaylistCommands.cxx @@ -198,11 +198,6 @@ CommandResult handle_listplaylists(gcc_unused Client &client, gcc_unused Request args, Response &r) { - Error error; - const auto list = ListPlaylistFiles(error); - if (list.empty() && error.IsDefined()) - return print_error(r, error); - - print_spl_list(r, list); + print_spl_list(r, ListPlaylistFiles()); return CommandResult::OK; } diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index f1f2f9bcc..a374af073 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -218,7 +218,7 @@ void UpdateWalk::UpdateDirectoryChild(Directory &directory, const ExcludeList &exclude_list, const char *name, const StorageFileInfo &info) -{ +try { assert(strchr(name, '/') == nullptr); if (info.IsRegular()) { @@ -242,6 +242,8 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory, FormatDebug(update_domain, "%s is not a directory, archive or music", name); } +} catch (const std::exception &e) { + LogError(e); } /* we don't look at "." / ".." nor files with newlines in their name */ @@ -455,7 +457,7 @@ UpdateWalk::DirectoryMakeUriParentChecked(Directory &root, const char *uri) inline void UpdateWalk::UpdateUri(Directory &root, const char *uri) -{ +try { Directory *parent = DirectoryMakeUriParentChecked(root, uri); if (parent == nullptr) return; @@ -476,6 +478,8 @@ UpdateWalk::UpdateUri(Directory &root, const char *uri) ExcludeList exclude_list; UpdateDirectoryChild(*parent, exclude_list, name, info); +} catch (const std::exception &e) { + LogError(e); } bool diff --git a/src/fs/CheckFile.cxx b/src/fs/CheckFile.cxx index e900fe9af..87064604a 100644 --- a/src/fs/CheckFile.cxx +++ b/src/fs/CheckFile.cxx @@ -25,6 +25,7 @@ #include "Path.hxx" #include "AllocatedPath.hxx" #include "DirectoryReader.hxx" +#include "system/Error.hxx" #include #include @@ -58,11 +59,12 @@ CheckDirectoryReadable(Path path_fs) } #endif - const DirectoryReader reader(path_fs); - if (reader.HasFailed() && errno == EACCES) { - const auto path_utf8 = path_fs.ToUTF8(); - FormatError(config_domain, - "No permission to read directory: %s", - path_utf8.c_str()); + try { + const DirectoryReader reader(path_fs); + } catch (const std::system_error &e) { + if (IsAccessDenied(e)) + FormatError(config_domain, + "No permission to read directory: %s", + path_fs.ToUTF8().c_str()); } } diff --git a/src/fs/DirectoryReader.cxx b/src/fs/DirectoryReader.cxx new file mode 100644 index 000000000..700cb2b2d --- /dev/null +++ b/src/fs/DirectoryReader.cxx @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003-2015 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DirectoryReader.hxx" +#include "system/Error.hxx" + +#ifdef WIN32 + +DirectoryReader::DirectoryReader(Path dir) + :handle(FindFirstFile(MakeWildcardPath(dir.c_str()), &data)) +{ + if (handle == INVALID_HANDLE_VALUE) + throw FormatLastError("Failed to open %s", dir.c_str()); +} + +#else + +DirectoryReader::DirectoryReader(Path dir) + :dirp(opendir(dir.c_str())) +{ + if (dirp == nullptr) + throw FormatErrno("Failed to open %s", dir.c_str()); +} + +#endif diff --git a/src/fs/DirectoryReader.hxx b/src/fs/DirectoryReader.hxx index 88af5b184..b4c140ada 100644 --- a/src/fs/DirectoryReader.hxx +++ b/src/fs/DirectoryReader.hxx @@ -61,10 +61,10 @@ class DirectoryReader { public: /** * Creates new directory reader for the specified #dir. + * + * Throws std::system_error on error. */ - explicit DirectoryReader(Path dir) - :handle(FindFirstFile(MakeWildcardPath(dir.c_str()), &data)) { - } + explicit DirectoryReader(Path dir); DirectoryReader(const DirectoryReader &other) = delete; DirectoryReader &operator=(const DirectoryReader &other) = delete; @@ -73,15 +73,7 @@ public: * Destroys this instance. */ ~DirectoryReader() { - if (!HasFailed()) - FindClose(handle); - } - - /** - * Checks if directory failed to open. - */ - bool HasFailed() const { - return handle == INVALID_HANDLE_VALUE; + FindClose(handle); } /** @@ -118,10 +110,10 @@ class DirectoryReader { public: /** * Creates new directory reader for the specified #dir. + * + * Throws std::system_error on error. */ - explicit DirectoryReader(Path dir) - :dirp(opendir(dir.c_str())) { - } + explicit DirectoryReader(Path dir); DirectoryReader(const DirectoryReader &other) = delete; DirectoryReader &operator=(const DirectoryReader &other) = delete; @@ -130,22 +122,13 @@ public: * Destroys this instance. */ ~DirectoryReader() { - if (!HasFailed()) - closedir(dirp); - } - - /** - * Checks if directory failed to open. - */ - bool HasFailed() const { - return dirp == nullptr; + closedir(dirp); } /** * Checks if directory entry is available. */ bool HasEntry() const { - assert(!HasFailed()); return ent != nullptr; } @@ -153,7 +136,6 @@ public: * Reads next directory entry. */ bool ReadEntry() { - assert(!HasFailed()); ent = readdir(dirp); return HasEntry(); } diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx index b35161dd1..91bbb8957 100644 --- a/src/storage/plugins/LocalStorage.cxx +++ b/src/storage/plugins/LocalStorage.cxx @@ -41,10 +41,6 @@ public: LocalDirectoryReader(AllocatedPath &&_base_fs) :base_fs(std::move(_base_fs)), reader(base_fs) {} - bool HasFailed() { - return reader.HasFailed(); - } - /* virtual methods from class StorageDirectoryReader */ const char *Read() override; bool GetInfo(bool follow, StorageFileInfo &info, @@ -160,15 +156,7 @@ LocalStorage::OpenDirectory(const char *uri_utf8, Error &error) if (path_fs.IsNull()) return nullptr; - LocalDirectoryReader *reader = - new LocalDirectoryReader(std::move(path_fs)); - if (reader->HasFailed()) { - error.FormatErrno("Failed to open '%s'", uri_utf8); - delete reader; - return nullptr; - } - - return reader; + return new LocalDirectoryReader(std::move(path_fs)); } gcc_pure