1 /*
2 * Copyright (c) 2024 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.back() == '/') {
51 path.remove_suffix(1);
52 }
53 destinations_.emplace_back(path);
54 }
55
PrependSearchPath(string_view path)56 void ProxyFilesystem::PrependSearchPath(string_view path)
57 {
58 if (path.back() == '/') {
59 path.remove_suffix(1);
60 }
61 destinations_.emplace(destinations_.begin(), path);
62 }
63
RemoveSearchPath(string_view destination)64 void ProxyFilesystem::RemoveSearchPath(string_view destination)
65 {
66 if (destination.back() == '/') {
67 destination.remove_suffix(1);
68 }
69 const auto it = std::find(destinations_.cbegin(), destinations_.cend(), destination);
70 if (it != destinations_.cend()) {
71 destinations_.erase(it);
72 }
73 }
74
GetEntry(const string_view path)75 IDirectory::Entry ProxyFilesystem::GetEntry(const string_view path)
76 {
77 auto normalizedPath = NormalizePath(path);
78 if (!normalizedPath.empty()) {
79 for (auto&& destination : destinations_) {
80 auto file = fileManager_.GetEntry(destination + normalizedPath);
81 if (file.type != IDirectory::Entry::UNKNOWN) {
82 return file;
83 }
84 }
85 }
86 return {};
87 }
OpenFile(const string_view path)88 IFile::Ptr ProxyFilesystem::OpenFile(const string_view path)
89 {
90 auto normalizedPath = NormalizePath(path);
91 if (!normalizedPath.empty()) {
92 for (auto&& destination : destinations_) {
93 auto file = fileManager_.OpenFile(destination + normalizedPath);
94 if (file) {
95 return file;
96 }
97 }
98 }
99
100 return IFile::Ptr();
101 }
102
CreateFile(const string_view path)103 IFile::Ptr ProxyFilesystem::CreateFile(const string_view path)
104 {
105 auto normalizedPath = NormalizePath(path);
106 if (!normalizedPath.empty()) {
107 for (auto&& destination : destinations_) {
108 auto file = fileManager_.CreateFile(destination + normalizedPath);
109 if (file) {
110 return file;
111 }
112 }
113 }
114
115 return IFile::Ptr();
116 }
117
DeleteFile(const string_view path)118 bool ProxyFilesystem::DeleteFile(const string_view path)
119 {
120 auto normalizedPath = NormalizePath(path);
121 if (!normalizedPath.empty()) {
122 for (auto&& destination : destinations_) {
123 if (fileManager_.DeleteFile(destination + normalizedPath)) {
124 return true;
125 }
126 }
127 }
128
129 return false;
130 }
131
OpenDirectory(const string_view path)132 IDirectory::Ptr ProxyFilesystem::OpenDirectory(const string_view path)
133 {
134 IDirectory::Ptr proxyDirectory;
135 vector<IDirectory::Ptr> directories;
136 auto normalizedPath = NormalizePath(path);
137 if (!normalizedPath.empty()) {
138 for (auto&& destination : destinations_) {
139 auto directory = fileManager_.OpenDirectory(destination + normalizedPath);
140 if (directory) {
141 directories.push_back(move(directory));
142 }
143 }
144 }
145
146 if (!directories.empty()) {
147 proxyDirectory.reset(new ProxyDirectory(move(directories)));
148 }
149
150 return proxyDirectory;
151 }
152
CreateDirectory(const string_view path)153 IDirectory::Ptr ProxyFilesystem::CreateDirectory(const string_view path)
154 {
155 auto normalizedPath = NormalizePath(path);
156 if (!normalizedPath.empty()) {
157 for (auto&& destination : destinations_) {
158 auto directory = fileManager_.CreateDirectory(destination + normalizedPath);
159 if (directory) {
160 return directory;
161 }
162 }
163 }
164
165 return IDirectory::Ptr();
166 }
167
DeleteDirectory(const string_view path)168 bool ProxyFilesystem::DeleteDirectory(const string_view path)
169 {
170 auto normalizedPath = NormalizePath(path);
171 if (!normalizedPath.empty()) {
172 for (auto&& destination : destinations_) {
173 if (fileManager_.DeleteDirectory(destination + normalizedPath)) {
174 return true;
175 }
176 }
177 }
178
179 return false;
180 }
181
Rename(const string_view fromPath,const string_view toPath)182 bool ProxyFilesystem::Rename(const string_view fromPath, const string_view toPath)
183 {
184 if (!fromPath.empty() && !toPath.empty()) {
185 auto pathFrom = NormalizePath(fromPath);
186 auto pathTo = NormalizePath(toPath);
187 for (auto&& destination : destinations_) {
188 if (fileManager_.Rename(destination + pathFrom, destination + pathTo)) {
189 return true;
190 }
191 }
192 }
193
194 return false;
195 }
196
GetUriPaths(const string_view uri) const197 vector<string> ProxyFilesystem::GetUriPaths(const string_view uri) const
198 {
199 vector<string> paths;
200
201 auto path = NormalizePath(uri);
202 if (!path.empty()) {
203 for (auto&& destination : destinations_) {
204 auto directory = fileManager_.OpenDirectory(destination + path);
205 if (directory) {
206 paths.push_back(destination + path);
207 }
208 }
209 }
210
211 return paths;
212 }
213 CORE_END_NAMESPACE()
214