1 
2 /*
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vintf/FileSystem.h>
19 
20 #include <dirent.h>
21 
22 #include <android-base/file.h>
23 
24 namespace android {
25 namespace vintf {
26 namespace details {
27 
fetch(const std::string & path,std::string * fetched,std::string * error) const28 status_t FileSystemImpl::fetch(const std::string& path, std::string* fetched,
29                                std::string* error) const {
30     if (!android::base::ReadFileToString(path, fetched, true /* follow_symlinks */)) {
31         int saved_errno = errno;
32         if (error) {
33             *error = "Cannot read " + path + ": " + strerror(saved_errno);
34         }
35         return saved_errno == 0 ? UNKNOWN_ERROR : -saved_errno;
36     }
37     return OK;
38 }
39 
listFiles(const std::string & path,std::vector<std::string> * out,std::string * error) const40 status_t FileSystemImpl::listFiles(const std::string& path, std::vector<std::string>* out,
41                                    std::string* error) const {
42     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
43     if (!dir) {
44         int saved_errno = errno;
45         if (error) {
46             *error = "Cannot open " + path + ": " + strerror(saved_errno);
47         }
48         return saved_errno == 0 ? UNKNOWN_ERROR : -saved_errno;
49     }
50 
51     dirent* dp;
52     while (errno = 0, dp = readdir(dir.get()), dp != nullptr) {
53         if (dp->d_type != DT_DIR) {
54             out->push_back(dp->d_name);
55         }
56     }
57     int saved_errno = errno;
58     if (saved_errno != 0) {
59         if (error) {
60             *error = "Failed while reading directory " + path + ": " + strerror(saved_errno);
61         }
62     }
63     return -saved_errno;
64 }
65 
fetch(const std::string &,std::string *,std::string *) const66 status_t FileSystemNoOp::fetch(const std::string&, std::string*, std::string*) const {
67     return NAME_NOT_FOUND;
68 }
69 
listFiles(const std::string &,std::vector<std::string> *,std::string *) const70 status_t FileSystemNoOp::listFiles(const std::string&, std::vector<std::string>*,
71                                    std::string*) const {
72     return NAME_NOT_FOUND;
73 }
74 
FileSystemUnderPath(const std::string & rootdir)75 FileSystemUnderPath::FileSystemUnderPath(const std::string& rootdir) {
76     mRootDir = rootdir;
77     if (!mRootDir.empty() && mRootDir.back() != '/') {
78         mRootDir.push_back('/');
79     }
80 }
81 
fetch(const std::string & path,std::string * fetched,std::string * error) const82 status_t FileSystemUnderPath::fetch(const std::string& path, std::string* fetched,
83                                     std::string* error) const {
84     return mImpl.fetch(mRootDir + path, fetched, error);
85 }
86 
listFiles(const std::string & path,std::vector<std::string> * out,std::string * error) const87 status_t FileSystemUnderPath::listFiles(const std::string& path, std::vector<std::string>* out,
88                                         std::string* error) const {
89     return mImpl.listFiles(mRootDir + path, out, error);
90 }
91 
getRootDir() const92 const std::string& FileSystemUnderPath::getRootDir() const {
93     return mRootDir;
94 }
95 
96 }  // namespace details
97 }  // namespace vintf
98 }  // namespace android
99