1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci 16fb299fa2Sopenharmony_ci#include "applypatch/partition_record.h" 17fb299fa2Sopenharmony_ci#include <cerrno> 18fb299fa2Sopenharmony_ci#include <fcntl.h> 19fb299fa2Sopenharmony_ci#include <unistd.h> 20fb299fa2Sopenharmony_ci#include "fs_manager/mount.h" 21fb299fa2Sopenharmony_ci#include "log/log.h" 22fb299fa2Sopenharmony_ci#include "securec.h" 23fb299fa2Sopenharmony_ci 24fb299fa2Sopenharmony_cinamespace Updater { 25fb299fa2Sopenharmony_ciPartitionRecord &PartitionRecord::GetInstance() 26fb299fa2Sopenharmony_ci{ 27fb299fa2Sopenharmony_ci static PartitionRecord partitionRecord; 28fb299fa2Sopenharmony_ci return partitionRecord; 29fb299fa2Sopenharmony_ci} 30fb299fa2Sopenharmony_cibool PartitionRecord::IsPartitionUpdated(const std::string &partitionName) 31fb299fa2Sopenharmony_ci{ 32fb299fa2Sopenharmony_ci auto miscBlockDevice = GetMiscPartitionPath(); 33fb299fa2Sopenharmony_ci uint8_t buffer[PARTITION_UPDATER_RECORD_MSG_SIZE]; 34fb299fa2Sopenharmony_ci if (!miscBlockDevice.empty()) { 35fb299fa2Sopenharmony_ci char *realPath = realpath(miscBlockDevice.c_str(), NULL); 36fb299fa2Sopenharmony_ci if (realPath == nullptr) { 37fb299fa2Sopenharmony_ci LOG(ERROR) << "realPath is NULL" << " : " << strerror(errno); 38fb299fa2Sopenharmony_ci return false; 39fb299fa2Sopenharmony_ci } 40fb299fa2Sopenharmony_ci int fd = open(realPath, O_RDONLY | O_EXCL | O_CLOEXEC | O_BINARY); 41fb299fa2Sopenharmony_ci free(realPath); 42fb299fa2Sopenharmony_ci if (fd < 0) { 43fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Open misc to recording partition failed" << " : " << strerror(errno); 44fb299fa2Sopenharmony_ci return false; 45fb299fa2Sopenharmony_ci } 46fb299fa2Sopenharmony_ci if (lseek(fd, PARTITION_RECORD_START, SEEK_CUR) < 0) { 47fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Seek misc to specific offset failed" << " : " << strerror(errno); 48fb299fa2Sopenharmony_ci close(fd); 49fb299fa2Sopenharmony_ci return false; 50fb299fa2Sopenharmony_ci } 51fb299fa2Sopenharmony_ci if (read(fd, buffer, PARTITION_UPDATER_RECORD_MSG_SIZE) != PARTITION_UPDATER_RECORD_MSG_SIZE) { 52fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Read from misc partition failed" << " : " << strerror(errno); 53fb299fa2Sopenharmony_ci close(fd); 54fb299fa2Sopenharmony_ci return false; 55fb299fa2Sopenharmony_ci } 56fb299fa2Sopenharmony_ci for (uint8_t *p = buffer; p < buffer + PARTITION_UPDATER_RECORD_MSG_SIZE; p += sizeof(PartitionRecordInfo)) { 57fb299fa2Sopenharmony_ci PartitionRecordInfo *pri = reinterpret_cast<PartitionRecordInfo*>(p); 58fb299fa2Sopenharmony_ci if (strcmp(pri->partitionName, partitionName.c_str()) == 0) { 59fb299fa2Sopenharmony_ci LOG(DEBUG) << "PartitionRecord: Found " << partitionName << " record in misc partition"; 60fb299fa2Sopenharmony_ci LOG(DEBUG) << "PartitionRecord: update status: " << pri->updated; 61fb299fa2Sopenharmony_ci close(fd); 62fb299fa2Sopenharmony_ci return pri->updated; 63fb299fa2Sopenharmony_ci } 64fb299fa2Sopenharmony_ci } 65fb299fa2Sopenharmony_ci fsync(fd); 66fb299fa2Sopenharmony_ci close(fd); 67fb299fa2Sopenharmony_ci LOG(INFO) << "PartitionRecord: Cannot found " << partitionName << " record in misc partition"; 68fb299fa2Sopenharmony_ci } 69fb299fa2Sopenharmony_ci return false; 70fb299fa2Sopenharmony_ci} 71fb299fa2Sopenharmony_ci 72fb299fa2Sopenharmony_cibool PartitionRecord::RecordPartitionSetOffset(int fd) 73fb299fa2Sopenharmony_ci{ 74fb299fa2Sopenharmony_ci off_t newOffset = 0; 75fb299fa2Sopenharmony_ci if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) { 76fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Seek misc to record offset failed: " << strerror(errno); 77fb299fa2Sopenharmony_ci return false; 78fb299fa2Sopenharmony_ci } 79fb299fa2Sopenharmony_ci if (read(fd, &newOffset, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) { 80fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Read offset failed: " << strerror(errno); 81fb299fa2Sopenharmony_ci return false; 82fb299fa2Sopenharmony_ci } 83fb299fa2Sopenharmony_ci offset_ = newOffset; 84fb299fa2Sopenharmony_ci if (lseek(fd, PARTITION_RECORD_START + offset_, SEEK_SET) < 0) { 85fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Seek misc to specific offset failed: " << strerror(errno); 86fb299fa2Sopenharmony_ci return false; 87fb299fa2Sopenharmony_ci } 88fb299fa2Sopenharmony_ci return true; 89fb299fa2Sopenharmony_ci} 90fb299fa2Sopenharmony_ci 91fb299fa2Sopenharmony_cibool PartitionRecord::RecordPartitionSetInfo(const std::string &partitionName, bool updated, int fd) 92fb299fa2Sopenharmony_ci{ 93fb299fa2Sopenharmony_ci (void)memset_s(&info_, sizeof(info_), 0, sizeof(info_)); 94fb299fa2Sopenharmony_ci if (strncpy_s(info_.partitionName, PARTITION_NAME_LEN, partitionName.c_str(), PARTITION_NAME_LEN - 1) != EOK) { 95fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: strncpy_s failed: " << strerror(errno); 96fb299fa2Sopenharmony_ci return false; 97fb299fa2Sopenharmony_ci } 98fb299fa2Sopenharmony_ci info_.updated = updated; 99fb299fa2Sopenharmony_ci if (write(fd, &info_, sizeof(PartitionRecordInfo)) != static_cast<ssize_t>(sizeof(PartitionRecordInfo))) { 100fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: write failed: " << strerror(errno); 101fb299fa2Sopenharmony_ci return false; 102fb299fa2Sopenharmony_ci } 103fb299fa2Sopenharmony_ci offset_ += static_cast<off_t>(sizeof(PartitionRecordInfo)); 104fb299fa2Sopenharmony_ci if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) { 105fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Seek misc to record offset failed: " << strerror(errno); 106fb299fa2Sopenharmony_ci return false; 107fb299fa2Sopenharmony_ci } 108fb299fa2Sopenharmony_ci if (write(fd, &offset_, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) { 109fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: write misc to record offset failed: " << strerror(errno); 110fb299fa2Sopenharmony_ci return false; 111fb299fa2Sopenharmony_ci } 112fb299fa2Sopenharmony_ci return true; 113fb299fa2Sopenharmony_ci} 114fb299fa2Sopenharmony_ci 115fb299fa2Sopenharmony_cibool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionName, bool updated) 116fb299fa2Sopenharmony_ci{ 117fb299fa2Sopenharmony_ci auto miscBlockDevice = GetMiscPartitionPath(); 118fb299fa2Sopenharmony_ci if (!miscBlockDevice.empty()) { 119fb299fa2Sopenharmony_ci char *realPath = realpath(miscBlockDevice.c_str(), NULL); 120fb299fa2Sopenharmony_ci if (realPath == nullptr) { 121fb299fa2Sopenharmony_ci LOG(ERROR) << "realPath is NULL" << " : " << strerror(errno); 122fb299fa2Sopenharmony_ci return false; 123fb299fa2Sopenharmony_ci } 124fb299fa2Sopenharmony_ci int fd = open(realPath, O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY); 125fb299fa2Sopenharmony_ci free(realPath); 126fb299fa2Sopenharmony_ci if (fd < 0) { 127fb299fa2Sopenharmony_ci LOG(ERROR) << "PartitionRecord: Open misc to recording partition failed" << " : " << strerror(errno); 128fb299fa2Sopenharmony_ci return false; 129fb299fa2Sopenharmony_ci } 130fb299fa2Sopenharmony_ci if (!RecordPartitionSetOffset(fd)) { 131fb299fa2Sopenharmony_ci close(fd); 132fb299fa2Sopenharmony_ci return false; 133fb299fa2Sopenharmony_ci } 134fb299fa2Sopenharmony_ci if (offset_ + static_cast<off_t>(sizeof(PartitionRecordInfo)) < PARTITION_UPDATER_RECORD_SIZE) { 135fb299fa2Sopenharmony_ci if (!RecordPartitionSetInfo(partitionName, updated, fd)) { 136fb299fa2Sopenharmony_ci close(fd); 137fb299fa2Sopenharmony_ci return false; 138fb299fa2Sopenharmony_ci } 139fb299fa2Sopenharmony_ci LOG(DEBUG) << "PartitionRecord: offset is " << offset_; 140fb299fa2Sopenharmony_ci } else { 141fb299fa2Sopenharmony_ci LOG(WARNING) << "PartitionRecord: partition record overflow, offset = " << offset_; 142fb299fa2Sopenharmony_ci close(fd); 143fb299fa2Sopenharmony_ci return false; 144fb299fa2Sopenharmony_ci } 145fb299fa2Sopenharmony_ci LOG(DEBUG) << "PartitionRecord: record " << partitionName << " successfully."; 146fb299fa2Sopenharmony_ci fsync(fd); 147fb299fa2Sopenharmony_ci close(fd); 148fb299fa2Sopenharmony_ci } 149fb299fa2Sopenharmony_ci return true; 150fb299fa2Sopenharmony_ci} 151fb299fa2Sopenharmony_ci 152fb299fa2Sopenharmony_cibool PartitionRecord::ClearRecordPartitionOffset() 153fb299fa2Sopenharmony_ci{ 154fb299fa2Sopenharmony_ci auto miscBlockDevice = GetMiscPartitionPath(); 155fb299fa2Sopenharmony_ci if (!miscBlockDevice.empty()) { 156fb299fa2Sopenharmony_ci int fd = open(miscBlockDevice.c_str(), O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY); 157fb299fa2Sopenharmony_ci if (fd < 0) { 158fb299fa2Sopenharmony_ci LOG(ERROR) << "Open misc to recording partition failed" << " : " << strerror(errno); 159fb299fa2Sopenharmony_ci return false; 160fb299fa2Sopenharmony_ci } 161fb299fa2Sopenharmony_ci if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) { 162fb299fa2Sopenharmony_ci LOG(ERROR) << "Seek misc to specific offset failed" << " : " << strerror(errno); 163fb299fa2Sopenharmony_ci close(fd); 164fb299fa2Sopenharmony_ci return false; 165fb299fa2Sopenharmony_ci } 166fb299fa2Sopenharmony_ci 167fb299fa2Sopenharmony_ci off_t initOffset = 0; 168fb299fa2Sopenharmony_ci if (write(fd, &initOffset, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) { 169fb299fa2Sopenharmony_ci LOG(ERROR) << "StartUpdater: Write misc initOffset 0 failed" << " : " << strerror(errno); 170fb299fa2Sopenharmony_ci close(fd); 171fb299fa2Sopenharmony_ci return false; 172fb299fa2Sopenharmony_ci } 173fb299fa2Sopenharmony_ci fsync(fd); 174fb299fa2Sopenharmony_ci close(fd); 175fb299fa2Sopenharmony_ci } 176fb299fa2Sopenharmony_ci return true; 177fb299fa2Sopenharmony_ci} 178fb299fa2Sopenharmony_ci 179fb299fa2Sopenharmony_cistd::string PartitionRecord::GetMiscPartitionPath(const std::string &misc) 180fb299fa2Sopenharmony_ci{ 181fb299fa2Sopenharmony_ci auto miscBlockDevice = GetBlockDeviceByMountPoint(misc); 182fb299fa2Sopenharmony_ci if (miscBlockDevice.empty()) { 183fb299fa2Sopenharmony_ci LOG(WARNING) << "Can not find misc partition"; 184fb299fa2Sopenharmony_ci } 185fb299fa2Sopenharmony_ci return miscBlockDevice; 186fb299fa2Sopenharmony_ci} 187fb299fa2Sopenharmony_ci} // namespace Updater 188