1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <stdint.h>
20 
21 #include <functional>
22 #include <memory>
23 #include <string>
24 #include <vector>
25 
26 #include <android-base/unique_fd.h>
27 
28 #include <libfiemap/fiemap_status.h>
29 #include <libfiemap/fiemap_writer.h>
30 
31 namespace android {
32 namespace fiemap {
33 
34 // Wrapper around FiemapWriter that is able to split images across files if
35 // necessary.
36 class SplitFiemap final {
37   public:
38     using ProgressCallback = std::function<bool(uint64_t, uint64_t)>;
39 
40     // Create a new split fiemap file. If |max_piece_size| is 0, the number of
41     // pieces will be determined automatically by detecting the filesystem.
42     // Otherwise, the file will be split evenly (with the remainder in the
43     // final file).
44     static std::unique_ptr<SplitFiemap> Create(const std::string& file_path, uint64_t file_size,
45                                                uint64_t max_piece_size,
46                                                ProgressCallback progress = {});
47     static FiemapStatus Create(const std::string& file_path, uint64_t file_size,
48                                uint64_t max_piece_size, std::unique_ptr<SplitFiemap>* out_val,
49                                ProgressCallback progress = {});
50 
51     // Open an existing split fiemap file.
52     static std::unique_ptr<SplitFiemap> Open(const std::string& file_path);
53 
54     ~SplitFiemap();
55 
56     // Return a list of all files created for a split file.
57     static bool GetSplitFileList(const std::string& file_path, std::vector<std::string>* list);
58 
59     // Destroy all components of a split file. If the root file does not exist,
60     // this returns true and does not report an error.
61     static bool RemoveSplitFiles(const std::string& file_path, std::string* message = nullptr);
62 
63     // Return whether all components of a split file still have pinned extents.
64     bool HasPinnedExtents() const;
65 
66     // Helper method for writing data that spans files. Note there is no seek
67     // method (yet); this starts at 0 and increments the position by |bytes|.
68     bool Write(const void* data, uint64_t bytes);
69 
70     // Flush all writes to all split files.
71     bool Flush();
72 
73     const std::vector<struct fiemap_extent>& extents();
74     uint32_t block_size() const;
size()75     uint64_t size() const { return total_size_; }
76     const std::string& bdev_path() const;
77 
78     // Non-copyable & Non-movable
79     SplitFiemap(const SplitFiemap&) = delete;
80     SplitFiemap& operator=(const SplitFiemap&) = delete;
81     SplitFiemap& operator=(SplitFiemap&&) = delete;
82     SplitFiemap(SplitFiemap&&) = delete;
83 
84   private:
85     SplitFiemap() = default;
86     void AddFile(FiemapUniquePtr&& file);
87 
88     bool creating_ = false;
89     std::string list_file_;
90     std::vector<FiemapUniquePtr> files_;
91     std::vector<struct fiemap_extent> extents_;
92     uint64_t total_size_ = 0;
93 
94     // Most recently open file and position for Write().
95     size_t cursor_index_ = 0;
96     uint64_t cursor_file_pos_ = 0;
97     android::base::unique_fd cursor_fd_;
98 };
99 
100 }  // namespace fiemap
101 }  // namespace android
102