• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 <linux/fiemap.h>
20 #include <stdint.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 #include <functional>
25 #include <string>
26 #include <vector>
27 
28 #include <android-base/unique_fd.h>
29 
30 #include <libfiemap/fiemap_status.h>
31 
32 namespace android {
33 namespace fiemap {
34 
35 class FiemapWriter;
36 using FiemapUniquePtr = std::unique_ptr<FiemapWriter>;
37 
38 class FiemapWriter final {
39   public:
40     // Factory method for FiemapWriter.
41     // The method returns FiemapUniquePtr that contains all the data necessary to be able to write
42     // to the given file directly using raw block i/o. The optional progress callback will be
43     // invoked, if create is true, while the file is being initialized. It receives the bytes
44     // written and the number of total bytes. If the callback returns false, the operation will
45     // fail.
46     //
47     // Note: when create is true, the file size will be aligned up to the nearest file system
48     // block.
49     static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size,
50                                 bool create = true,
51                                 std::function<bool(uint64_t, uint64_t)> progress = {});
52     static FiemapStatus Open(const std::string& file_path, uint64_t file_size, FiemapUniquePtr* out,
53                              bool create = true,
54                              std::function<bool(uint64_t, uint64_t)> progress = {});
55 
56     // Check that a file still has the same extents since it was last opened with FiemapWriter,
57     // assuming the file was not resized outside of FiemapWriter. Returns false either on error
58     // or if the file was not pinned.
59     //
60     // This will always return true on Ext4. On F2FS, it will return true if either of the
61     // following cases are true:
62     //   - The file was never pinned.
63     //   - The file is pinned and has not been moved by the GC.
64     // Thus, this method should only be called for pinned files (such as those returned by
65     // FiemapWriter::Open).
66     static bool HasPinnedExtents(const std::string& file_path);
67 
68     // Returns the underlying block device of a file. This will look past device-mapper layers
69     // as long as each layer would not change block mappings (i.e., dm-crypt, dm-bow, and dm-
70     // default-key tables are okay; dm-linear is not). If a mapping such as dm-linear is found,
71     // it will be returned in place of any physical block device.
72     //
73     // It is the caller's responsibility to check whether the returned block device is acceptable.
74     // Gsid, for example, will only accept /dev/block/by-name/userdata as the bottom device.
75     // Callers can check the device name (dm- or loop prefix), inspect sysfs, or compare the major
76     // number against a boot device.
77     //
78     // If device-mapper nodes were encountered, then |uses_dm| will be set to true.
79     static bool GetBlockDeviceForFile(const std::string& file_path, std::string* bdev_path,
80                                       bool* uses_dm = nullptr);
81 
82     ~FiemapWriter() = default;
83 
file_path()84     const std::string& file_path() const { return file_path_; };
size()85     uint64_t size() const { return file_size_; };
bdev_path()86     const std::string& bdev_path() const { return bdev_path_; };
block_size()87     uint64_t block_size() const { return block_size_; };
extents()88     const std::vector<struct fiemap_extent>& extents() { return extents_; };
fs_type()89     uint32_t fs_type() const { return fs_type_; }
90 
91     // Non-copyable & Non-movable
92     FiemapWriter(const FiemapWriter&) = delete;
93     FiemapWriter& operator=(const FiemapWriter&) = delete;
94     FiemapWriter& operator=(FiemapWriter&&) = delete;
95     FiemapWriter(FiemapWriter&&) = delete;
96 
97   private:
98     // Name of the file managed by this class.
99     std::string file_path_;
100     // Block device on which we have created the file.
101     std::string bdev_path_;
102 
103     // Size in bytes of the file this class is writing
104     uint64_t file_size_;
105 
106     // total size in bytes of the block device
107     uint64_t bdev_size_;
108 
109     // Filesystem type where the file is being created.
110     // See: <uapi/linux/magic.h> for filesystem magic numbers
111     uint32_t fs_type_;
112 
113     // block size as reported by the kernel of the underlying block device;
114     uint64_t block_size_;
115 
116     // This file's fiemap
117     std::vector<struct fiemap_extent> extents_;
118 
119     FiemapWriter() = default;
120 };
121 
122 }  // namespace fiemap
123 }  // namespace android
124