1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "proxy_filesystem.h"
17
18 #include <algorithm>
19 #include <cstring>
20
21 #include <base/containers/iterator.h>
22 #include <base/containers/string.h>
23 #include <base/containers/string_view.h>
24 #include <base/containers/type_traits.h>
25 #include <base/containers/unique_ptr.h>
26 #include <base/containers/vector.h>
27 #include <base/namespace.h>
28 #include <core/io/intf_directory.h>
29 #include <core/io/intf_file.h>
30 #include <core/namespace.h>
31
32 #include "file_manager.h"
33 #include "path_tools.h"
34 #include "proxy_directory.h"
35
36 CORE_BEGIN_NAMESPACE()
37 using BASE_NS::move;
38 using BASE_NS::string;
39 using BASE_NS::string_view;
40 using BASE_NS::vector;
41
ProxyFilesystem(FileManager & fileManager,const string_view destination)42 ProxyFilesystem::ProxyFilesystem(FileManager& fileManager, const string_view destination)
43 : fileManager_(fileManager), destinations_()
44 {
45 AppendSearchPath(destination);
46 }
47
AppendSearchPath(string_view path)48 void ProxyFilesystem::AppendSearchPath(string_view path)
49 {
50 if (path.empty()) {
51 return;
52 }
53 if (path.back() == '/') {
54 path.remove_suffix(1);
55 }
56 destinations_.emplace_back(path);
57 }
58
PrependSearchPath(string_view path)59 void ProxyFilesystem::PrependSearchPath(string_view path)
60 {
61 if (path.empty()) {
62 return;
63 }
64 if (path.back() == '/') {
65 path.remove_suffix(1);
66 }
67 destinations_.emplace(destinations_.begin(), path);
68 }
69
RemoveSearchPath(string_view destination)70 void ProxyFilesystem::RemoveSearchPath(string_view destination)
71 {
72 if (destination.empty()) {
73 return;
74 }
75 if (destination.back() == '/') {
76 destination.remove_suffix(1);
77 }
78 const auto it = std::find(destinations_.cbegin(), destinations_.cend(), destination);
79 if (it != destinations_.cend()) {
80 destinations_.erase(it);
81 }
82 }
83
GetEntry(const string_view path)84 IDirectory::Entry ProxyFilesystem::GetEntry(const string_view path)
85 {
86 auto normalizedPath = NormalizePath(path);
87 if (!normalizedPath.empty()) {
88 for (auto&& destination : destinations_) {
89 auto file = fileManager_.GetEntry(destination + normalizedPath);
90 if (file.type != IDirectory::Entry::UNKNOWN) {
91 return file;
92 }
93 }
94 }
95 return {};
96 }
97
OpenFile(const string_view path,const IFile::Mode mode)98 IFile::Ptr ProxyFilesystem::OpenFile(const string_view path, const IFile::Mode mode)
99 {
100 auto normalizedPath = NormalizePath(path);
101 if (!normalizedPath.empty()) {
102 for (auto&& destination : destinations_) {
103 auto file = fileManager_.OpenFile(destination + normalizedPath, mode);
104 if (file) {
105 return file;
106 }
107 }
108 }
109
110 return {};
111 }
112
CreateFile(const string_view path)113 IFile::Ptr ProxyFilesystem::CreateFile(const string_view path)
114 {
115 auto normalizedPath = NormalizePath(path);
116 if (!normalizedPath.empty()) {
117 for (auto&& destination : destinations_) {
118 auto file = fileManager_.CreateFile(destination + normalizedPath);
119 if (file) {
120 return file;
121 }
122 }
123 }
124
125 return {};
126 }
127
DeleteFile(const string_view path)128 bool ProxyFilesystem::DeleteFile(const string_view path)
129 {
130 auto normalizedPath = NormalizePath(path);
131 if (!normalizedPath.empty()) {
132 for (auto&& destination : destinations_) {
133 if (fileManager_.DeleteFile(destination + normalizedPath)) {
134 return true;
135 }
136 }
137 }
138
139 return false;
140 }
141
FileExists(const string_view path) const142 bool ProxyFilesystem::FileExists(const string_view path) const
143 {
144 auto normalizedPath = NormalizePath(path);
145 if (!normalizedPath.empty()) {
146 for (auto&& destination : destinations_) {
147 if (fileManager_.FileExists(destination + normalizedPath)) {
148 return true;
149 }
150 }
151 }
152
153 return false;
154 }
155
OpenDirectory(const string_view path)156 IDirectory::Ptr ProxyFilesystem::OpenDirectory(const string_view path)
157 {
158 IDirectory::Ptr proxyDirectory;
159 vector<IDirectory::Ptr> directories;
160 auto normalizedPath = NormalizePath(path);
161 if (!normalizedPath.empty()) {
162 for (auto&& destination : destinations_) {
163 auto directory = fileManager_.OpenDirectory(destination + normalizedPath);
164 if (directory) {
165 directories.push_back(move(directory));
166 }
167 }
168 }
169
170 if (!directories.empty()) {
171 proxyDirectory.reset(new ProxyDirectory(move(directories)));
172 }
173
174 return proxyDirectory;
175 }
176
CreateDirectory(const string_view path)177 IDirectory::Ptr ProxyFilesystem::CreateDirectory(const string_view path)
178 {
179 auto normalizedPath = NormalizePath(path);
180 if (!normalizedPath.empty()) {
181 for (auto&& destination : destinations_) {
182 auto directory = fileManager_.CreateDirectory(destination + normalizedPath);
183 if (directory) {
184 return directory;
185 }
186 }
187 }
188
189 return {};
190 }
191
DeleteDirectory(const string_view path)192 bool ProxyFilesystem::DeleteDirectory(const string_view path)
193 {
194 auto normalizedPath = NormalizePath(path);
195 if (!normalizedPath.empty()) {
196 for (auto&& destination : destinations_) {
197 if (fileManager_.DeleteDirectory(destination + normalizedPath)) {
198 return true;
199 }
200 }
201 }
202
203 return false;
204 }
205
DirectoryExists(const string_view path) const206 bool ProxyFilesystem::DirectoryExists(const string_view path) const
207 {
208 auto normalizedPath = NormalizePath(path);
209 if (!normalizedPath.empty()) {
210 for (auto&& destination : destinations_) {
211 if (fileManager_.DirectoryExists(destination + normalizedPath)) {
212 return true;
213 }
214 }
215 }
216
217 return false;
218 }
219
Rename(const string_view fromPath,const string_view toPath)220 bool ProxyFilesystem::Rename(const string_view fromPath, const string_view toPath)
221 {
222 if (!fromPath.empty() && !toPath.empty()) {
223 auto pathFrom = NormalizePath(fromPath);
224 auto pathTo = NormalizePath(toPath);
225 for (auto&& destination : destinations_) {
226 if (fileManager_.Rename(destination + pathFrom, destination + pathTo)) {
227 return true;
228 }
229 }
230 }
231
232 return false;
233 }
234
GetUriPaths(const string_view uri) const235 vector<string> ProxyFilesystem::GetUriPaths(const string_view uri) const
236 {
237 vector<string> paths;
238
239 auto path = NormalizePath(uri);
240 if (!path.empty()) {
241 for (auto&& destination : destinations_) {
242 auto directory = fileManager_.OpenDirectory(destination + path);
243 if (directory) {
244 paths.push_back(destination + path);
245 }
246 }
247 }
248
249 return paths;
250 }
251 CORE_END_NAMESPACE()
252