1 /*
2 * Copyright (C) 2023 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 <core/namespace.h>
22
23 #include "file_manager.h"
24 #include "path_tools.h"
25 #include "proxy_directory.h"
26
27 CORE_BEGIN_NAMESPACE()
28 using BASE_NS::move;
29 using BASE_NS::string;
30 using BASE_NS::string_view;
31 using BASE_NS::vector;
32
ProxyFilesystem(FileManager & fileManager,const string_view destination)33 ProxyFilesystem::ProxyFilesystem(FileManager& fileManager, const string_view destination)
34 : fileManager_(fileManager), destinations_()
35 {
36 AppendSearchPath(destination);
37 }
38
AppendSearchPath(const string_view destination)39 void ProxyFilesystem::AppendSearchPath(const string_view destination)
40 {
41 auto dst = destination;
42 if (dst.back() == '/') {
43 dst = dst.substr(0, dst.size() - 1);
44 }
45 destinations_.emplace_back(dst);
46 }
47
PrependSearchPath(const string_view uri)48 void ProxyFilesystem::PrependSearchPath(const string_view uri)
49 {
50 auto dst = uri;
51 if (dst.back() == '/') {
52 dst = dst.substr(0, dst.size() - 1);
53 }
54 destinations_.emplace(destinations_.begin(), dst);
55 }
56
RemoveSearchPath(const string_view destination)57 void ProxyFilesystem::RemoveSearchPath(const string_view destination)
58 {
59 auto dst = destination;
60 if (dst.back() == '/') {
61 dst = dst.substr(0, dst.size() - 1);
62 }
63 const auto it = std::find(destinations_.begin(), destinations_.end(), dst);
64 if (it != destinations_.end()) {
65 destinations_.erase(it);
66 }
67 }
68
GetEntry(const string_view pathIn)69 IDirectory::Entry ProxyFilesystem::GetEntry(const string_view pathIn)
70 {
71 auto path = NormalizePath(pathIn);
72 if (!path.empty()) {
73 for (auto&& destination : destinations_) {
74 auto file = fileManager_.GetEntry(destination + path);
75 if (file.type != IDirectory::Entry::UNKNOWN) {
76 return file;
77 }
78 }
79 }
80 return {};
81 }
OpenFile(const string_view pathIn)82 IFile::Ptr ProxyFilesystem::OpenFile(const string_view pathIn)
83 {
84 auto path = NormalizePath(pathIn);
85 if (!path.empty()) {
86 for (auto&& destination : destinations_) {
87 auto file = fileManager_.OpenFile(destination + path);
88 if (file) {
89 return file;
90 }
91 }
92 }
93
94 return IFile::Ptr();
95 }
96
CreateFile(const string_view pathIn)97 IFile::Ptr ProxyFilesystem::CreateFile(const string_view pathIn)
98 {
99 auto path = NormalizePath(pathIn);
100 if (!path.empty()) {
101 for (auto&& destination : destinations_) {
102 auto file = fileManager_.CreateFile(destination + path);
103 if (file) {
104 return file;
105 }
106 }
107 }
108
109 return IFile::Ptr();
110 }
111
DeleteFile(const string_view pathIn)112 bool ProxyFilesystem::DeleteFile(const string_view pathIn)
113 {
114 auto path = NormalizePath(pathIn);
115 if (!path.empty()) {
116 for (auto&& destination : destinations_) {
117 if (fileManager_.DeleteFile(destination + path)) {
118 return true;
119 }
120 }
121 }
122
123 return false;
124 }
125
OpenDirectory(const string_view pathIn)126 IDirectory::Ptr ProxyFilesystem::OpenDirectory(const string_view pathIn)
127 {
128 IDirectory::Ptr proxyDirectory;
129 vector<IDirectory::Ptr> directories;
130 auto path = NormalizePath(pathIn);
131 if (!path.empty()) {
132 for (auto&& destination : destinations_) {
133 auto directory = fileManager_.OpenDirectory(destination + path);
134 if (directory) {
135 directories.emplace_back(move(directory));
136 }
137 }
138 }
139
140 if (!directories.empty()) {
141 proxyDirectory.reset(new ProxyDirectory(move(directories)));
142 }
143
144 return proxyDirectory;
145 }
146
CreateDirectory(const string_view pathIn)147 IDirectory::Ptr ProxyFilesystem::CreateDirectory(const string_view pathIn)
148 {
149 auto path = NormalizePath(pathIn);
150 if (!path.empty()) {
151 for (auto&& destination : destinations_) {
152 auto directory = fileManager_.CreateDirectory(destination + path);
153 if (directory) {
154 return directory;
155 }
156 }
157 }
158
159 return IDirectory::Ptr();
160 }
161
DeleteDirectory(const string_view pathIn)162 bool ProxyFilesystem::DeleteDirectory(const string_view pathIn)
163 {
164 auto path = NormalizePath(pathIn);
165 if (!path.empty()) {
166 for (auto&& destination : destinations_) {
167 if (fileManager_.DeleteDirectory(destination + path)) {
168 return true;
169 }
170 }
171 }
172
173 return false;
174 }
175
Rename(const string_view pathFrom,const string_view pathTo)176 bool ProxyFilesystem::Rename(const string_view pathFrom, const string_view pathTo)
177 {
178 auto fromPath = NormalizePath(pathFrom);
179 auto toPath = NormalizePath(pathTo);
180 if (!pathFrom.empty() && !pathTo.empty()) {
181 for (auto&& destination : destinations_) {
182 if (fileManager_.Rename(destination + fromPath, destination + toPath)) {
183 return true;
184 }
185 }
186 }
187
188 return false;
189 }
190
GetUriPaths(const string_view uri) const191 vector<string> ProxyFilesystem::GetUriPaths(const string_view uri) const
192 {
193 vector<string> paths;
194
195 auto path = NormalizePath(uri);
196 if (!path.empty()) {
197 for (auto&& destination : destinations_) {
198 auto directory = fileManager_.OpenDirectory(destination + path);
199 if (directory) {
200 paths.emplace_back(destination + path);
201 }
202 }
203 }
204
205 return paths;
206 }
207 CORE_END_NAMESPACE()
208