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