1 //  Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #ifndef ROCKSDB_LITE
7 
8 #include "env/fs_remap.h"
9 
10 namespace ROCKSDB_NAMESPACE {
11 
RemapFileSystem(const std::shared_ptr<FileSystem> & base)12 RemapFileSystem::RemapFileSystem(const std::shared_ptr<FileSystem>& base)
13     : FileSystemWrapper(base) {}
14 
EncodePathWithNewBasename(const std::string & path)15 std::pair<IOStatus, std::string> RemapFileSystem::EncodePathWithNewBasename(
16     const std::string& path) {
17   // No difference by default
18   return EncodePath(path);
19 }
20 
RegisterDbPaths(const std::vector<std::string> & paths)21 Status RemapFileSystem::RegisterDbPaths(const std::vector<std::string>& paths) {
22   std::vector<std::string> encoded_paths;
23   encoded_paths.reserve(paths.size());
24   for (auto& path : paths) {
25     auto status_and_enc_path = EncodePathWithNewBasename(path);
26     if (!status_and_enc_path.first.ok()) {
27       return status_and_enc_path.first;
28     }
29     encoded_paths.emplace_back(status_and_enc_path.second);
30   }
31   return FileSystemWrapper::RegisterDbPaths(encoded_paths);
32 }
33 
UnregisterDbPaths(const std::vector<std::string> & paths)34 Status RemapFileSystem::UnregisterDbPaths(
35     const std::vector<std::string>& paths) {
36   std::vector<std::string> encoded_paths;
37   encoded_paths.reserve(paths.size());
38   for (auto& path : paths) {
39     auto status_and_enc_path = EncodePathWithNewBasename(path);
40     if (!status_and_enc_path.first.ok()) {
41       return status_and_enc_path.first;
42     }
43     encoded_paths.emplace_back(status_and_enc_path.second);
44   }
45   return FileSystemWrapper::UnregisterDbPaths(encoded_paths);
46 }
47 
NewSequentialFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSSequentialFile> * result,IODebugContext * dbg)48 IOStatus RemapFileSystem::NewSequentialFile(
49     const std::string& fname, const FileOptions& options,
50     std::unique_ptr<FSSequentialFile>* result, IODebugContext* dbg) {
51   auto status_and_enc_path = EncodePathWithNewBasename(fname);
52   if (!status_and_enc_path.first.ok()) {
53     return status_and_enc_path.first;
54   }
55   return FileSystemWrapper::NewSequentialFile(status_and_enc_path.second,
56                                               options, result, dbg);
57 }
58 
NewRandomAccessFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomAccessFile> * result,IODebugContext * dbg)59 IOStatus RemapFileSystem::NewRandomAccessFile(
60     const std::string& fname, const FileOptions& options,
61     std::unique_ptr<FSRandomAccessFile>* result, IODebugContext* dbg) {
62   auto status_and_enc_path = EncodePathWithNewBasename(fname);
63   if (!status_and_enc_path.first.ok()) {
64     return status_and_enc_path.first;
65   }
66   return FileSystemWrapper::NewRandomAccessFile(status_and_enc_path.second,
67                                                 options, result, dbg);
68 }
69 
NewWritableFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)70 IOStatus RemapFileSystem::NewWritableFile(
71     const std::string& fname, const FileOptions& options,
72     std::unique_ptr<FSWritableFile>* result, IODebugContext* dbg) {
73   auto status_and_enc_path = EncodePathWithNewBasename(fname);
74   if (!status_and_enc_path.first.ok()) {
75     return status_and_enc_path.first;
76   }
77   return FileSystemWrapper::NewWritableFile(status_and_enc_path.second, options,
78                                             result, dbg);
79 }
80 
ReuseWritableFile(const std::string & fname,const std::string & old_fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)81 IOStatus RemapFileSystem::ReuseWritableFile(
82     const std::string& fname, const std::string& old_fname,
83     const FileOptions& options, std::unique_ptr<FSWritableFile>* result,
84     IODebugContext* dbg) {
85   auto status_and_enc_path = EncodePathWithNewBasename(fname);
86   if (!status_and_enc_path.first.ok()) {
87     return status_and_enc_path.first;
88   }
89   auto status_and_old_enc_path = EncodePath(old_fname);
90   if (!status_and_old_enc_path.first.ok()) {
91     return status_and_old_enc_path.first;
92   }
93   return FileSystemWrapper::ReuseWritableFile(status_and_old_enc_path.second,
94                                               status_and_old_enc_path.second,
95                                               options, result, dbg);
96 }
97 
NewRandomRWFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomRWFile> * result,IODebugContext * dbg)98 IOStatus RemapFileSystem::NewRandomRWFile(
99     const std::string& fname, const FileOptions& options,
100     std::unique_ptr<FSRandomRWFile>* result, IODebugContext* dbg) {
101   auto status_and_enc_path = EncodePathWithNewBasename(fname);
102   if (!status_and_enc_path.first.ok()) {
103     return status_and_enc_path.first;
104   }
105   return FileSystemWrapper::NewRandomRWFile(status_and_enc_path.second, options,
106                                             result, dbg);
107 }
108 
NewDirectory(const std::string & dir,const IOOptions & options,std::unique_ptr<FSDirectory> * result,IODebugContext * dbg)109 IOStatus RemapFileSystem::NewDirectory(const std::string& dir,
110                                        const IOOptions& options,
111                                        std::unique_ptr<FSDirectory>* result,
112                                        IODebugContext* dbg) {
113   auto status_and_enc_path = EncodePathWithNewBasename(dir);
114   if (!status_and_enc_path.first.ok()) {
115     return status_and_enc_path.first;
116   }
117   return FileSystemWrapper::NewDirectory(status_and_enc_path.second, options,
118                                          result, dbg);
119 }
120 
FileExists(const std::string & fname,const IOOptions & options,IODebugContext * dbg)121 IOStatus RemapFileSystem::FileExists(const std::string& fname,
122                                      const IOOptions& options,
123                                      IODebugContext* dbg) {
124   auto status_and_enc_path = EncodePathWithNewBasename(fname);
125   if (!status_and_enc_path.first.ok()) {
126     return status_and_enc_path.first;
127   }
128   return FileSystemWrapper::FileExists(status_and_enc_path.second, options,
129                                        dbg);
130 }
131 
GetChildren(const std::string & dir,const IOOptions & options,std::vector<std::string> * result,IODebugContext * dbg)132 IOStatus RemapFileSystem::GetChildren(const std::string& dir,
133                                       const IOOptions& options,
134                                       std::vector<std::string>* result,
135                                       IODebugContext* dbg) {
136   auto status_and_enc_path = EncodePath(dir);
137   if (!status_and_enc_path.first.ok()) {
138     return status_and_enc_path.first;
139   }
140   return FileSystemWrapper::GetChildren(status_and_enc_path.second, options,
141                                         result, dbg);
142 }
143 
GetChildrenFileAttributes(const std::string & dir,const IOOptions & options,std::vector<FileAttributes> * result,IODebugContext * dbg)144 IOStatus RemapFileSystem::GetChildrenFileAttributes(
145     const std::string& dir, const IOOptions& options,
146     std::vector<FileAttributes>* result, IODebugContext* dbg) {
147   auto status_and_enc_path = EncodePath(dir);
148   if (!status_and_enc_path.first.ok()) {
149     return status_and_enc_path.first;
150   }
151   return FileSystemWrapper::GetChildrenFileAttributes(
152       status_and_enc_path.second, options, result, dbg);
153 }
154 
DeleteFile(const std::string & fname,const IOOptions & options,IODebugContext * dbg)155 IOStatus RemapFileSystem::DeleteFile(const std::string& fname,
156                                      const IOOptions& options,
157                                      IODebugContext* dbg) {
158   auto status_and_enc_path = EncodePath(fname);
159   if (!status_and_enc_path.first.ok()) {
160     return status_and_enc_path.first;
161   }
162   return FileSystemWrapper::DeleteFile(status_and_enc_path.second, options,
163                                        dbg);
164 }
165 
CreateDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)166 IOStatus RemapFileSystem::CreateDir(const std::string& dirname,
167                                     const IOOptions& options,
168                                     IODebugContext* dbg) {
169   auto status_and_enc_path = EncodePathWithNewBasename(dirname);
170   if (!status_and_enc_path.first.ok()) {
171     return status_and_enc_path.first;
172   }
173   return FileSystemWrapper::CreateDir(status_and_enc_path.second, options, dbg);
174 }
175 
CreateDirIfMissing(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)176 IOStatus RemapFileSystem::CreateDirIfMissing(const std::string& dirname,
177                                              const IOOptions& options,
178                                              IODebugContext* dbg) {
179   auto status_and_enc_path = EncodePathWithNewBasename(dirname);
180   if (!status_and_enc_path.first.ok()) {
181     return status_and_enc_path.first;
182   }
183   return FileSystemWrapper::CreateDirIfMissing(status_and_enc_path.second,
184                                                options, dbg);
185 }
186 
DeleteDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)187 IOStatus RemapFileSystem::DeleteDir(const std::string& dirname,
188                                     const IOOptions& options,
189                                     IODebugContext* dbg) {
190   auto status_and_enc_path = EncodePath(dirname);
191   if (!status_and_enc_path.first.ok()) {
192     return status_and_enc_path.first;
193   }
194   return FileSystemWrapper::DeleteDir(status_and_enc_path.second, options, dbg);
195 }
196 
GetFileSize(const std::string & fname,const IOOptions & options,uint64_t * file_size,IODebugContext * dbg)197 IOStatus RemapFileSystem::GetFileSize(const std::string& fname,
198                                       const IOOptions& options,
199                                       uint64_t* file_size,
200                                       IODebugContext* dbg) {
201   auto status_and_enc_path = EncodePath(fname);
202   if (!status_and_enc_path.first.ok()) {
203     return status_and_enc_path.first;
204   }
205   return FileSystemWrapper::GetFileSize(status_and_enc_path.second, options,
206                                         file_size, dbg);
207 }
208 
GetFileModificationTime(const std::string & fname,const IOOptions & options,uint64_t * file_mtime,IODebugContext * dbg)209 IOStatus RemapFileSystem::GetFileModificationTime(const std::string& fname,
210                                                   const IOOptions& options,
211                                                   uint64_t* file_mtime,
212                                                   IODebugContext* dbg) {
213   auto status_and_enc_path = EncodePath(fname);
214   if (!status_and_enc_path.first.ok()) {
215     return status_and_enc_path.first;
216   }
217   return FileSystemWrapper::GetFileModificationTime(status_and_enc_path.second,
218                                                     options, file_mtime, dbg);
219 }
220 
IsDirectory(const std::string & path,const IOOptions & options,bool * is_dir,IODebugContext * dbg)221 IOStatus RemapFileSystem::IsDirectory(const std::string& path,
222                                       const IOOptions& options, bool* is_dir,
223                                       IODebugContext* dbg) {
224   auto status_and_enc_path = EncodePath(path);
225   if (!status_and_enc_path.first.ok()) {
226     return status_and_enc_path.first;
227   }
228   return FileSystemWrapper::IsDirectory(status_and_enc_path.second, options,
229                                         is_dir, dbg);
230 }
231 
RenameFile(const std::string & src,const std::string & dest,const IOOptions & options,IODebugContext * dbg)232 IOStatus RemapFileSystem::RenameFile(const std::string& src,
233                                      const std::string& dest,
234                                      const IOOptions& options,
235                                      IODebugContext* dbg) {
236   auto status_and_src_enc_path = EncodePath(src);
237   if (!status_and_src_enc_path.first.ok()) {
238     return status_and_src_enc_path.first;
239   }
240   auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
241   if (!status_and_dest_enc_path.first.ok()) {
242     return status_and_dest_enc_path.first;
243   }
244   return FileSystemWrapper::RenameFile(status_and_src_enc_path.second,
245                                        status_and_dest_enc_path.second, options,
246                                        dbg);
247 }
248 
LinkFile(const std::string & src,const std::string & dest,const IOOptions & options,IODebugContext * dbg)249 IOStatus RemapFileSystem::LinkFile(const std::string& src,
250                                    const std::string& dest,
251                                    const IOOptions& options,
252                                    IODebugContext* dbg) {
253   auto status_and_src_enc_path = EncodePath(src);
254   if (!status_and_src_enc_path.first.ok()) {
255     return status_and_src_enc_path.first;
256   }
257   auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
258   if (!status_and_dest_enc_path.first.ok()) {
259     return status_and_dest_enc_path.first;
260   }
261   return FileSystemWrapper::LinkFile(status_and_src_enc_path.second,
262                                      status_and_dest_enc_path.second, options,
263                                      dbg);
264 }
265 
LockFile(const std::string & fname,const IOOptions & options,FileLock ** lock,IODebugContext * dbg)266 IOStatus RemapFileSystem::LockFile(const std::string& fname,
267                                    const IOOptions& options, FileLock** lock,
268                                    IODebugContext* dbg) {
269   auto status_and_enc_path = EncodePathWithNewBasename(fname);
270   if (!status_and_enc_path.first.ok()) {
271     return status_and_enc_path.first;
272   }
273   // FileLock subclasses may store path (e.g., PosixFileLock stores it). We
274   // can skip stripping the chroot directory from this path because callers
275   // shouldn't use it.
276   return FileSystemWrapper::LockFile(status_and_enc_path.second, options, lock,
277                                      dbg);
278 }
279 
NewLogger(const std::string & fname,const IOOptions & options,std::shared_ptr<Logger> * result,IODebugContext * dbg)280 IOStatus RemapFileSystem::NewLogger(const std::string& fname,
281                                     const IOOptions& options,
282                                     std::shared_ptr<Logger>* result,
283                                     IODebugContext* dbg) {
284   auto status_and_enc_path = EncodePathWithNewBasename(fname);
285   if (!status_and_enc_path.first.ok()) {
286     return status_and_enc_path.first;
287   }
288   return FileSystemWrapper::NewLogger(status_and_enc_path.second, options,
289                                       result, dbg);
290 }
291 
GetAbsolutePath(const std::string & db_path,const IOOptions & options,std::string * output_path,IODebugContext * dbg)292 IOStatus RemapFileSystem::GetAbsolutePath(const std::string& db_path,
293                                           const IOOptions& options,
294                                           std::string* output_path,
295                                           IODebugContext* dbg) {
296   auto status_and_enc_path = EncodePath(db_path);
297   if (!status_and_enc_path.first.ok()) {
298     return status_and_enc_path.first;
299   }
300   return FileSystemWrapper::GetAbsolutePath(status_and_enc_path.second, options,
301                                             output_path, dbg);
302 }
303 
304 }  // namespace ROCKSDB_NAMESPACE
305 
306 #endif  // ROCKSDB_LITE
307