Cleanup global FileFetcher
This global instance is modifiable everywhere and
is hard to maintain. It also contains references as
out-variables, which is not the standard.
Clean it up by refactoring it into a public (i.e.
not in details namespace) class, FileSystem.
Introduce VintfObject::InitFileSystem that allows
the behavior to be changed before any files are read.
Bug: 37999212
Test: host and target libvintf_test, vintf_object_test
Change-Id: I1c64b31fd37119450be89dfd1d2bfe76a71ccf3d
Merged-In: I1c64b31fd37119450be89dfd1d2bfe76a71ccf3d
diff --git a/Android.bp b/Android.bp
index cb3a4f8..38a3bd2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,6 +32,7 @@
"parse_string.cpp",
"parse_xml.cpp",
"CompatibilityMatrix.cpp",
+ "FileSystem.cpp",
"HalManifest.cpp",
"HalInterface.cpp",
"KernelConfigTypedValue.cpp",
@@ -42,12 +43,12 @@
"MatrixHal.cpp",
"MatrixInstance.cpp",
"MatrixKernel.cpp",
+ "PropertyFetcher.cpp",
"Regex.cpp",
"SystemSdk.cpp",
"TransportArch.cpp",
"VintfObject.cpp",
"XmlFile.cpp",
- "utils-common.cpp",
],
shared_libs: [
"libbase",
diff --git a/FileSystem.cpp b/FileSystem.cpp
new file mode 100644
index 0000000..5b871ee
--- /dev/null
+++ b/FileSystem.cpp
@@ -0,0 +1,104 @@
+
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vintf/FileSystem.h>
+
+#include <dirent.h>
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+namespace android {
+namespace vintf {
+namespace details {
+
+static std::mutex sFileSystemMutex;
+static std::unique_ptr<FileSystem> sFileSystem{};
+
+bool initFileSystem(std::unique_ptr<FileSystem>&& value) {
+ std::lock_guard<std::mutex> lock(sFileSystemMutex);
+ if (sFileSystem != nullptr) return false;
+ sFileSystem = std::move(value);
+ return true;
+}
+
+FileSystem& getFileSystem() {
+ std::lock_guard<std::mutex> lock(sFileSystemMutex);
+ if (sFileSystem == nullptr) {
+#ifdef LIBVINTF_TARGET
+ sFileSystem = std::make_unique<details::FileSystemImpl>();
+#else
+ sFileSystem = std::make_unique<details::FileSystemNoOp>();
+#endif
+ }
+ return *sFileSystem;
+}
+
+status_t FileSystemImpl::fetch(const std::string& path, std::string* fetched,
+ std::string* error) const {
+ std::ifstream in;
+
+ errno = 0;
+ in.open(path);
+ if (!in || errno != 0) {
+ if (error) {
+ *error = "Cannot open " + path + ": " + strerror(errno);
+ }
+ return -errno;
+ }
+
+ std::stringstream ss;
+ ss << in.rdbuf();
+ *fetched = ss.str();
+
+ return -errno;
+}
+
+status_t FileSystemImpl::listFiles(const std::string& path, std::vector<std::string>* out,
+ std::string* error) const {
+ errno = 0;
+ DIR* dirp = opendir(path.c_str());
+ if (!dirp || errno != 0) {
+ if (error) {
+ *error = "Cannot open " + path + ": " + strerror(errno);
+ }
+ return -errno;
+ }
+
+ std::unique_ptr<DIR, decltype(&closedir)> dir(dirp, closedir);
+ dirent* dp;
+ while ((dp = readdir(dir.get())) != nullptr) {
+ if (dp->d_type != DT_DIR) {
+ out->push_back(dp->d_name);
+ }
+ }
+ return -errno;
+}
+
+status_t FileSystemNoOp::fetch(const std::string&, std::string*, std::string*) const {
+ return NAME_NOT_FOUND;
+}
+
+status_t FileSystemNoOp::listFiles(const std::string&, std::vector<std::string>*,
+ std::string*) const {
+ return NAME_NOT_FOUND;
+}
+
+} // namespace details
+} // namespace vintf
+} // namespace android
diff --git a/utils-common.cpp b/PropertyFetcher.cpp
similarity index 95%
rename from utils-common.cpp
rename to PropertyFetcher.cpp
index 3e7e736..28caee3 100644
--- a/utils-common.cpp
+++ b/PropertyFetcher.cpp
@@ -17,8 +17,6 @@
#include "utils.h"
-// Default implementations for classes defined in utils.h
-
namespace android {
namespace vintf {
namespace details {
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 38ef0df..0e757ca 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -165,7 +165,7 @@
status_t VintfObject::AddDirectoryManifests(const std::string& directory, HalManifest* manifest,
std::string* error) {
std::vector<std::string> fileNames;
- status_t err = details::gFetcher->listFiles(directory, &fileNames, error);
+ status_t err = details::getFileSystem().listFiles(directory, &fileNames, error);
// if the directory isn't there, that's okay
if (err == NAME_NOT_FOUND) return OK;
if (err != OK) return err;
@@ -304,7 +304,7 @@
std::vector<std::string> fileNames;
std::vector<Named<CompatibilityMatrix>> results;
- if (details::gFetcher->listFiles(kSystemVintfDir, &fileNames, error) != OK) {
+ if (details::getFileSystem().listFiles(kSystemVintfDir, &fileNames, error) != OK) {
return {};
}
for (const std::string& fileName : fileNames) {
@@ -312,7 +312,7 @@
std::string content;
std::string fetchError;
- status_t status = details::gFetcher->fetch(path, content, &fetchError);
+ status_t status = details::getFileSystem().fetch(path, &content, &fetchError);
if (status != OK) {
if (error) {
*error += "Framework Matrix: Ignore file " + path + ": " + fetchError + "\n";
@@ -753,5 +753,9 @@
return CheckDeprecation(inManifest, error);
}
+bool VintfObject::InitFileSystem(std::unique_ptr<FileSystem>&& fileSystem) {
+ return details::initFileSystem(std::move(fileSystem));
+}
+
} // namespace vintf
} // namespace android
diff --git a/check_vintf.cpp b/check_vintf.cpp
index 6acc311..c85cbe3 100644
--- a/check_vintf.cpp
+++ b/check_vintf.cpp
@@ -43,37 +43,33 @@
// command line arguments
using Args = std::multimap<Option, std::string>;
-class HostFileFetcher : public FileFetcher {
+class HostFileSystem : public FileSystem {
public:
- void setRootDir(const std::string& rootdir) {
+ HostFileSystem(const std::string& rootdir) {
mRootDir = rootdir;
if (!mRootDir.empty() && mRootDir.back() != '/') {
mRootDir.push_back('/');
}
}
- virtual status_t fetch(const std::string& path, std::string& fetched, std::string* error) {
- return HostFileFetcher::fetchInternal(path, fetched, error);
+ status_t fetch(const std::string& path, std::string* fetched,
+ std::string* error) const override {
+ status_t status = mImpl.fetch(mRootDir + path, fetched, error);
+ std::cerr << "Debug: Fetch '" << mRootDir << path << "': " << toString(status) << std::endl;
+ return status;
}
- virtual status_t fetch(const std::string& path, std::string& fetched) {
- return HostFileFetcher::fetchInternal(path, fetched, nullptr);
- }
- virtual status_t listFiles(const std::string& path, std::vector<std::string>* out,
- std::string* error) {
- status_t status = FileFetcher::listFiles(mRootDir + path, out, error);
+ status_t listFiles(const std::string& path, std::vector<std::string>* out,
+ std::string* error) const override {
+ status_t status = mImpl.listFiles(mRootDir + path, out, error);
std::cerr << "Debug: List '" << mRootDir << path << "': " << toString(status) << std::endl;
return status;
}
private:
- status_t fetchInternal(const std::string& path, std::string& fetched, std::string* error) {
- status_t status = FileFetcher::fetchInternal(mRootDir + path, fetched, error);
- std::cerr << "Debug: Fetch '" << mRootDir << path << "': " << toString(status) << std::endl;
- return status;
- }
static std::string toString(status_t status) {
return status == OK ? "SUCCESS" : strerror(-status);
}
std::string mRootDir;
+ FileSystemImpl mImpl;
};
class PresetPropertyFetcher : public PropertyFetcher {
@@ -112,9 +108,6 @@
};
// globals
-static HostFileFetcher hostFileFetcher;
-FileFetcher* gFetcher = &hostFileFetcher;
-
static PartitionMounter partitionMounter;
PartitionMounter* gPartitionMounter = &partitionMounter;
@@ -131,7 +124,7 @@
std::unique_ptr<T> readObject(const std::string& path, const XmlConverter<T>& converter) {
std::string xml;
std::string error;
- status_t err = details::gFetcher->fetch(path, xml, &error);
+ status_t err = details::getFileSystem().fetch(path, &xml, &error);
if (err != OK) {
std::cerr << "Error: Cannot read '" << path << "' (" << strerror(-err) << "): " << error
<< std::endl;
@@ -146,6 +139,11 @@
}
int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) {
+ if (!VintfObject::InitFileSystem(std::make_unique<FileSystemImpl>())) {
+ std::cerr << "Cannot initialize FileSystem object." << std::endl;
+ return NO_INIT;
+ }
+
auto manifest = readObject(manifestPath, gHalManifestConverter);
auto matrix = readObject(matrixPath, gCompatibilityMatrixConverter);
if (manifest == nullptr || matrix == nullptr) {
@@ -242,7 +240,10 @@
}
int checkAllFiles(const std::string& rootdir, const Properties& props, std::string* error) {
- hostFileFetcher.setRootDir(rootdir);
+ if (!VintfObject::InitFileSystem(std::make_unique<HostFileSystem>(rootdir))) {
+ std::cerr << "Cannot initialize FileSystem object." << std::endl;
+ return NO_INIT;
+ }
hostPropertyFetcher.setProperties(props);
return VintfObject::CheckCompatibility({} /* packageInfo */, error, DISABLE_RUNTIME_INFO);
diff --git a/include/vintf/FileSystem.h b/include/vintf/FileSystem.h
new file mode 100644
index 0000000..202557d
--- /dev/null
+++ b/include/vintf/FileSystem.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VINTF_FILE_SYSTEM_H
+#define ANDROID_VINTF_FILE_SYSTEM_H
+
+#include <memory>
+#include <mutex>
+
+#include <utils/Errors.h>
+#include <vintf/RuntimeInfo.h>
+#include <vintf/parse_xml.h>
+
+namespace android {
+namespace vintf {
+
+// Queries the file system in the correct way. Files can come from
+// an actual file system, a sub-directory, or from ADB, depending on the
+// implementation.
+//
+// This class can be used to create a mock for overriding.
+class FileSystem {
+ public:
+ virtual ~FileSystem(){};
+ // Return NAME_NOT_FOUND if file is not found,
+ // OK if file is retrieved and written to "fetched".
+ virtual status_t fetch(const std::string& path, std::string* fetched,
+ std::string* error) const = 0;
+ // Return NAME_NOT_FOUND if directory is not found,
+ // OK if file names are retrieved and written to out.
+ virtual status_t listFiles(const std::string& path, std::vector<std::string>* out,
+ std::string* error) const = 0;
+};
+
+namespace details {
+
+// Initialize the global instance.
+__attribute__((warn_unused_result)) bool initFileSystem(std::unique_ptr<FileSystem>&& value);
+
+// Return the instance provided through init(), or a default implementation
+// if init() is not called. The default implementation queries the actual
+// file system on the device and does nothing on host.
+// Once get(), cannot be init()-ed again.
+FileSystem& getFileSystem();
+
+// Class that actually queries the file system.
+class FileSystemImpl : public FileSystem {
+ public:
+ status_t fetch(const std::string&, std::string*, std::string*) const;
+ status_t listFiles(const std::string&, std::vector<std::string>*, std::string*) const;
+};
+
+// Class that does nothing.
+class FileSystemNoOp : public FileSystem {
+ public:
+ status_t fetch(const std::string&, std::string*, std::string*) const;
+ status_t listFiles(const std::string&, std::vector<std::string>*, std::string*) const;
+};
+
+} // namespace details
+} // namespace vintf
+} // namespace android
+
+#endif
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 38b20b3..875a25a 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -21,6 +21,7 @@
#include "CompatibilityMatrix.h"
#include "DisabledChecks.h"
+#include "FileSystem.h"
#include "HalManifest.h"
#include "Named.h"
#include "RuntimeInfo.h"
@@ -148,6 +149,14 @@
*/
static int32_t CheckDeprecation(std::string* error = nullptr);
+ // Specify how the file system should be queried.
+ // Can only be initialized before VintfObject is queried, preferably in main().
+ static bool InitFileSystem(std::unique_ptr<FileSystem>&&);
+
+ protected:
+ private:
+ static std::unique_ptr<FileSystem> sInstance;
+
private:
static status_t GetCombinedFrameworkMatrix(
const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
diff --git a/test/utils-fake.cpp b/test/utils-fake.cpp
index 38f6ab0..a04ba79 100644
--- a/test/utils-fake.cpp
+++ b/test/utils-fake.cpp
@@ -22,8 +22,6 @@
// Do not create the mock objects here as InitGoogleMock must be called
// first.
-FileFetcher* gFetcher = nullptr;
-
PartitionMounter* gPartitionMounter = nullptr;
ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = nullptr;
diff --git a/test/utils-fake.h b/test/utils-fake.h
index 0253bca..f07ae48 100644
--- a/test/utils-fake.h
+++ b/test/utils-fake.h
@@ -27,28 +27,20 @@
namespace vintf {
namespace details {
-class MockFileFetcher : public FileFetcher {
+class MockFileSystem : public FileSystem {
public:
- MockFileFetcher() {
- // By default call through to the original.
- ON_CALL(*this, fetch(_, _)).WillByDefault(Invoke([this](const auto& path, auto& fetched) {
- return real_.fetchInternal(path, fetched, nullptr);
- }));
- ON_CALL(*this, listFiles(_, _, _))
- .WillByDefault(
- Invoke([this](const std::string& path, std::vector<std::string>* out,
- std::string* error) { return real_.listFiles(path, out, error); }));
+ MockFileSystem() {}
+
+ MOCK_CONST_METHOD2(fetch, status_t(const std::string& path, std::string& fetched));
+ MOCK_CONST_METHOD3(listFiles,
+ status_t(const std::string&, std::vector<std::string>*, std::string*));
+
+ status_t fetch(const std::string& path, std::string* fetched, std::string*) const override {
+ // Call the mocked function
+ return fetch(path, *fetched);
}
-
- MOCK_METHOD2(fetch, status_t(const std::string& path, std::string& fetched));
- MOCK_METHOD3(listFiles, status_t(const std::string&, std::vector<std::string>*, std::string*));
-
- status_t fetch(const std::string& path, std::string& fetched, std::string*) override final {
- return fetch(path, fetched);
- }
-
private:
- FileFetcher real_;
+ FileSystemImpl mImpl;
};
class MockPartitionMounter : public PartitionMounter {
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 2baeee3..77d62cb 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -275,67 +275,67 @@
" </hal>\n"
"</compatibility-matrix>\n"};
-// Setup the MockFileFetcher used by the fetchAllInformation template
+static MockPartitionMounter& mounter() {
+ return *static_cast<MockPartitionMounter*>(gPartitionMounter);
+}
+static MockFileSystem& fetcher() {
+ return static_cast<MockFileSystem&>(details::getFileSystem());
+}
+
+// Setup the MockFileSystem used by the fetchAllInformation template
// so it returns the given metadata info instead of fetching from device.
void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
const std::string& systemManifestXml, const std::string& vendorMatrixXml,
const std::string& productModel) {
- MockFileFetcher* fetcher = static_cast<MockFileFetcher*>(gFetcher);
-
- ON_CALL(*fetcher, listFiles(StrEq(kVendorManifestFragmentDir), _, _))
+ ON_CALL(fetcher(), listFiles(StrEq(kVendorManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
- ON_CALL(*fetcher, listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+ ON_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
- ON_CALL(*fetcher, listFiles(StrEq(kOdmManifestFragmentDir), _, _))
+ ON_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
if (!productModel.empty()) {
- ON_CALL(*fetcher, fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
+ ON_CALL(fetcher(),
+ fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
- ON_CALL(*fetcher, fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
+ ON_CALL(fetcher(), fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
}
- ON_CALL(*fetcher, fetch(StrEq(kOdmLegacyManifest), _))
+ ON_CALL(fetcher(), fetch(StrEq(kOdmLegacyManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
- ON_CALL(*fetcher, fetch(StrEq(kOdmManifest), _))
+ ON_CALL(fetcher(), fetch(StrEq(kOdmManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
- ON_CALL(*fetcher, fetch(StrEq(kVendorManifest), _))
+ ON_CALL(fetcher(), fetch(StrEq(kVendorManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
- ON_CALL(*fetcher, fetch(StrEq(kVendorLegacyManifest), _))
+ ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyManifest), _))
.WillByDefault(Invoke([vendorManifestXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = vendorManifestXml;
return 0;
}));
- ON_CALL(*fetcher, fetch(StrEq(kSystemManifest), _))
+ ON_CALL(fetcher(), fetch(StrEq(kSystemManifest), _))
.WillByDefault(Invoke([systemManifestXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = systemManifestXml;
return 0;
}));
- ON_CALL(*fetcher, fetch(StrEq(kVendorMatrix), _))
+ ON_CALL(fetcher(), fetch(StrEq(kVendorMatrix), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
- ON_CALL(*fetcher, fetch(StrEq(kVendorLegacyMatrix), _))
+ ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyMatrix), _))
.WillByDefault(Invoke([vendorMatrixXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = vendorMatrixXml;
return 0;
}));
- ON_CALL(*fetcher, fetch(StrEq(kSystemLegacyMatrix), _))
+ ON_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _))
.WillByDefault(Invoke([systemMatrixXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = systemMatrixXml;
return 0;
}));
// Don't list /system/etc/vintf unless otherwise specified.
- ON_CALL(*fetcher, listFiles(StrEq(kSystemVintfDir), _, _)).WillByDefault(Return(::android::OK));
-}
-
-static MockPartitionMounter &mounter() {
- return *static_cast<MockPartitionMounter *>(gPartitionMounter);
-}
-static MockFileFetcher &fetcher() {
- return *static_cast<MockFileFetcher*>(gFetcher);
+ ON_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
+ .WillByDefault(Return(::android::OK));
}
class VintfObjectTestBase : public testing::Test {
@@ -1230,8 +1230,10 @@
int main(int argc, char** argv) {
::testing::InitGoogleMock(&argc, argv);
- NiceMock<MockFileFetcher> fetcher;
- gFetcher = &fetcher;
+ if (!VintfObject::InitFileSystem(std::make_unique<NiceMock<MockFileSystem>>())) {
+ LOG(FATAL) << "Cannot set mock file system because it is already initialized.";
+ return 1;
+ }
NiceMock<MockPartitionMounter> mounter;
gPartitionMounter = &mounter;
diff --git a/utils.cpp b/utils.cpp
index 5b2bb7d..c6425d8 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -17,6 +17,7 @@
#include "utils.h"
#ifdef LIBVINTF_TARGET
+#include <android-base/logging.h>
#include <android-base/properties.h>
#endif
@@ -24,9 +25,6 @@
namespace vintf {
namespace details {
-static FileFetcher fetcher;
-FileFetcher* gFetcher = &fetcher;
-
static PartitionMounter partitionMounter;
PartitionMounter* gPartitionMounter = &partitionMounter;
diff --git a/utils.h b/utils.h
index 783d40b..e33d283 100644
--- a/utils.h
+++ b/utils.h
@@ -17,14 +17,11 @@
#ifndef ANDROID_VINTF_UTILS_H
#define ANDROID_VINTF_UTILS_H
-#include <dirent.h>
-
-#include <fstream>
-#include <iostream>
#include <memory>
-#include <sstream>
+#include <mutex>
#include <utils/Errors.h>
+#include <vintf/FileSystem.h>
#include <vintf/RuntimeInfo.h>
#include <vintf/parse_xml.h>
@@ -32,57 +29,6 @@
namespace vintf {
namespace details {
-// Return the file from the given location as a string.
-//
-// This class can be used to create a mock for overriding.
-class FileFetcher {
- public:
- virtual ~FileFetcher() {}
- status_t fetchInternal(const std::string& path, std::string& fetched, std::string* error) {
- std::ifstream in;
-
- in.open(path);
- if (!in.is_open()) {
- if (error) {
- *error = "Cannot open " + path;
- }
- return NAME_NOT_FOUND;
- }
-
- std::stringstream ss;
- ss << in.rdbuf();
- fetched = ss.str();
-
- return OK;
- }
- virtual status_t fetch(const std::string& path, std::string& fetched, std::string* error) {
- return fetchInternal(path, fetched, error);
- }
- virtual status_t fetch(const std::string& path, std::string& fetched) {
- return fetchInternal(path, fetched, nullptr);
- }
- virtual status_t listFiles(const std::string& path, std::vector<std::string>* out,
- std::string* error) {
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
- if (!dir) {
- if (error) {
- *error = "Cannot open " + path;
- }
- return NAME_NOT_FOUND;
- }
-
- dirent* dp;
- while ((dp = readdir(dir.get())) != nullptr) {
- if (dp->d_type != DT_DIR) {
- out->push_back(dp->d_name);
- }
- }
- return OK;
- }
-};
-
-extern FileFetcher* gFetcher;
-
class PartitionMounter {
public:
virtual ~PartitionMounter() {}
@@ -99,12 +45,7 @@
T* outObject, std::string* error = nullptr) {
std::string info;
- if (gFetcher == nullptr) {
- // Should never happen.
- return NO_INIT;
- }
-
- status_t result = gFetcher->fetch(path, info, error);
+ status_t result = getFileSystem().fetch(path, &info, error);
if (result != OK) {
return result;