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 #include <fcntl.h>
18 #include <stdint.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21
22 #if defined(__linux__)
23 #include <linux/fs.h>
24 #include <sys/ioctl.h>
25 #endif
26
27 #include <android-base/file.h>
28 #include <ext4_utils/ext4_utils.h>
29 #include <openssl/sha.h>
30
31 #ifdef __ANDROID__
32 #include <cutils/android_get_control_file.h>
33 #endif
34
35 #include "utility.h"
36
37 namespace android {
38 namespace fs_mgr {
39
GetDescriptorSize(int fd,uint64_t * size)40 bool GetDescriptorSize(int fd, uint64_t* size) {
41 #if !defined(_WIN32)
42 struct stat s;
43 if (fstat(fd, &s) < 0) {
44 PERROR << __PRETTY_FUNCTION__ << "fstat failed";
45 return false;
46 }
47
48 if (S_ISBLK(s.st_mode)) {
49 *size = get_block_device_size(fd);
50 return *size != 0;
51 }
52 #endif
53
54 int64_t result = SeekFile64(fd, 0, SEEK_END);
55 if (result == -1) {
56 PERROR << __PRETTY_FUNCTION__ << "lseek failed";
57 return false;
58 }
59
60 *size = result;
61 return true;
62 }
63
SeekFile64(int fd,int64_t offset,int whence)64 int64_t SeekFile64(int fd, int64_t offset, int whence) {
65 static_assert(sizeof(off_t) == sizeof(int64_t), "Need 64-bit lseek");
66 return lseek(fd, offset, whence);
67 }
68
GetPrimaryGeometryOffset()69 int64_t GetPrimaryGeometryOffset() {
70 return LP_PARTITION_RESERVED_BYTES;
71 }
72
GetBackupGeometryOffset()73 int64_t GetBackupGeometryOffset() {
74 return GetPrimaryGeometryOffset() + LP_METADATA_GEOMETRY_SIZE;
75 }
76
GetPrimaryMetadataOffset(const LpMetadataGeometry & geometry,uint32_t slot_number)77 int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
78 CHECK(slot_number < geometry.metadata_slot_count);
79 int64_t offset = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
80 geometry.metadata_max_size * slot_number;
81 return offset;
82 }
83
GetBackupMetadataOffset(const LpMetadataGeometry & geometry,uint32_t slot_number)84 int64_t GetBackupMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
85 CHECK(slot_number < geometry.metadata_slot_count);
86 int64_t start = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
87 int64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
88 return start + int64_t(geometry.metadata_max_size * slot_number);
89 }
90
GetTotalMetadataSize(uint32_t metadata_max_size,uint32_t max_slots)91 uint64_t GetTotalMetadataSize(uint32_t metadata_max_size, uint32_t max_slots) {
92 return LP_PARTITION_RESERVED_BYTES +
93 (LP_METADATA_GEOMETRY_SIZE + metadata_max_size * max_slots) * 2;
94 }
95
GetMetadataSuperBlockDevice(const LpMetadata & metadata)96 const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata) {
97 if (metadata.block_devices.empty()) {
98 return nullptr;
99 }
100 return &metadata.block_devices[0];
101 }
102
SHA256(const void * data,size_t length,uint8_t out[32])103 void SHA256(const void* data, size_t length, uint8_t out[32]) {
104 SHA256_CTX c;
105 SHA256_Init(&c);
106 SHA256_Update(&c, data, length);
107 SHA256_Final(out, &c);
108 }
109
SlotNumberForSlotSuffix(const std::string & suffix)110 uint32_t SlotNumberForSlotSuffix(const std::string& suffix) {
111 if (suffix.empty() || suffix == "a" || suffix == "_a") {
112 return 0;
113 } else if (suffix == "b" || suffix == "_b") {
114 return 1;
115 } else {
116 LERROR << __PRETTY_FUNCTION__ << "slot '" << suffix
117 << "' does not have a recognized format.";
118 return 0;
119 }
120 }
121
GetTotalSuperPartitionSize(const LpMetadata & metadata)122 uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata) {
123 uint64_t size = 0;
124 for (const auto& block_device : metadata.block_devices) {
125 size += block_device.size;
126 }
127 return size;
128 }
129
GetBlockDevicePartitionNames(const LpMetadata & metadata)130 std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata) {
131 std::vector<std::string> list;
132 for (const auto& block_device : metadata.block_devices) {
133 list.emplace_back(GetBlockDevicePartitionName(block_device));
134 }
135 return list;
136 }
137
GetPartitionSlotSuffix(const std::string & partition_name)138 std::string GetPartitionSlotSuffix(const std::string& partition_name) {
139 if (partition_name.size() <= 2) {
140 return "";
141 }
142 std::string suffix = partition_name.substr(partition_name.size() - 2);
143 return (suffix == "_a" || suffix == "_b") ? suffix : "";
144 }
145
SlotSuffixForSlotNumber(uint32_t slot_number)146 std::string SlotSuffixForSlotNumber(uint32_t slot_number) {
147 CHECK(slot_number == 0 || slot_number == 1);
148 return (slot_number == 0) ? "_a" : "_b";
149 }
150
UpdateBlockDevicePartitionName(LpMetadataBlockDevice * device,const std::string & name)151 bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name) {
152 if (name.size() > sizeof(device->partition_name)) {
153 return false;
154 }
155 strncpy(device->partition_name, name.c_str(), sizeof(device->partition_name));
156 return true;
157 }
158
UpdatePartitionGroupName(LpMetadataPartitionGroup * group,const std::string & name)159 bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name) {
160 if (name.size() > sizeof(group->name)) {
161 return false;
162 }
163 strncpy(group->name, name.c_str(), sizeof(group->name));
164 return true;
165 }
166
SetBlockReadonly(int fd,bool readonly)167 bool SetBlockReadonly(int fd, bool readonly) {
168 #if defined(__linux__)
169 int val = readonly;
170 return ioctl(fd, BLKROSET, &val) == 0;
171 #else
172 (void)fd;
173 (void)readonly;
174 return true;
175 #endif
176 }
177
GetControlFileOrOpen(const char * path,int flags)178 base::unique_fd GetControlFileOrOpen(const char* path, int flags) {
179 #if defined(__ANDROID__)
180 int fd = android_get_control_file(path);
181 if (fd >= 0) {
182 int newfd = TEMP_FAILURE_RETRY(dup(fd));
183 if (newfd >= 0) {
184 return base::unique_fd(newfd);
185 }
186 PERROR << "Cannot dup fd for already controlled file: " << path << ", reopening...";
187 }
188 #endif
189 return base::unique_fd(open(path, flags));
190 }
191
192 } // namespace fs_mgr
193 } // namespace android
194