• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "applypatch/partition_record.h"
17 #include <cerrno>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include "fs_manager/mount.h"
21 #include "log/log.h"
22 #include "securec.h"
23 
24 namespace updater {
GetInstance()25 PartitionRecord &PartitionRecord::GetInstance()
26 {
27     static PartitionRecord partitionRecord;
28     return partitionRecord;
29 }
IsPartitionUpdated(const std::string & partitionName)30 bool PartitionRecord::IsPartitionUpdated(const std::string &partitionName)
31 {
32     auto miscBlockDevice = GetMiscPartitionPath();
33     uint8_t buffer[PARTITION_UPDATER_RECORD_MSG_SIZE];
34     if (!miscBlockDevice.empty()) {
35         char *realPath = realpath(miscBlockDevice.c_str(), NULL);
36         UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false);
37         int fd = open(realPath, O_RDONLY | O_EXCL | O_CLOEXEC | O_BINARY);
38         free(realPath);
39         UPDATER_FILE_CHECK(fd >= 0, "PartitionRecord: Open misc to recording partition failed", return false);
40         UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_START, SEEK_CUR) >= 0,
41             "PartitionRecord: Seek misc to specific offset failed", fd, return false);
42         UPDATER_CHECK_FILE_OP(read(fd, buffer, PARTITION_UPDATER_RECORD_MSG_SIZE) == PARTITION_UPDATER_RECORD_MSG_SIZE,
43             "PartitionRecord: Read from misc partition failed", fd, return false);
44         for (uint8_t *p = buffer; p < buffer + PARTITION_UPDATER_RECORD_MSG_SIZE; p += sizeof(PartitionRecordInfo)) {
45             PartitionRecordInfo *pri = reinterpret_cast<PartitionRecordInfo*>(p);
46             if (strcmp(pri->partitionName, partitionName.c_str()) == 0) {
47                 LOG(DEBUG) << "PartitionRecord: Found " << partitionName << " record in misc partition";
48                 LOG(DEBUG) << "PartitionRecord: update status: " << pri->updated;
49                 close(fd);
50                 return pri->updated;
51             }
52         }
53         fsync(fd);
54         close(fd);
55         LOG(INFO) << "PartitionRecord: Cannot found " << partitionName << " record in misc partition";
56     }
57     return false;
58 }
59 
RecordPartitionUpdateStatus(const std::string & partitionName,bool updated)60 bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionName, bool updated)
61 {
62     auto miscBlockDevice = GetMiscPartitionPath();
63     if (!miscBlockDevice.empty()) {
64         char *realPath = realpath(miscBlockDevice.c_str(), NULL);
65         UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false);
66         int fd = open(realPath, O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY);
67         free(realPath);
68         UPDATER_FILE_CHECK(fd >= 0, "PartitionRecord: Open misc to recording partition failed", return false);
69         off_t newOffset = 0;
70         UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0,
71                 "PartitionRecord: Seek misc to record offset failed", fd, return false);
72         UPDATER_CHECK_FILE_OP(read(fd, &newOffset, sizeof(off_t)) == sizeof(off_t),
73             "PartitionRecord: Read offset failed", fd, return false);
74 
75         offset_ = newOffset;
76         UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_START + offset_, SEEK_SET) >= 0,
77             "PartitionRecord: Seek misc to specific offset failed", fd, return false);
78         if (offset_ + sizeof(PartitionRecordInfo) < PARTITION_UPDATER_RECORD_SIZE) {
79             UPDATER_CHECK_FILE_OP(memset_s(&info_, sizeof(info_), 0, sizeof(info_)) == 0,
80                 "PartitionRecord: clear partition info failed", fd, return false);
81             UPDATER_CHECK_FILE_OP(!strncpy_s(info_.partitionName, PARTITION_NAME_LEN, partitionName.c_str(),
82                 PARTITION_NAME_LEN - 1), "PartitionRecord: strncpy_s failed", fd, return false);
83             info_.updated = updated;
84             UPDATER_CHECK_FILE_OP(write(fd, &info_, sizeof(PartitionRecordInfo)) == sizeof(PartitionRecordInfo),
85                 "PartitionRecord: write failed", fd, return false);
86             offset_ += sizeof(PartitionRecordInfo);
87             UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0,
88                 "PartitionRecord: Seek misc to record offset failed", fd, return false);
89             UPDATER_CHECK_FILE_OP(write(fd, &offset_, sizeof(off_t)) == sizeof(off_t),
90                 "PartitionRecord: write  misc to record offset failed", fd, return false);
91             LOG(DEBUG) << "PartitionRecord: offset is " << offset_;
92         } else {
93             LOG(WARNING) << "PartitionRecord: partition record overflow, offset = " << offset_;
94             close(fd);
95             return false;
96         }
97         LOG(DEBUG) << "PartitionRecord: record " << partitionName << " successfully.";
98         fsync(fd);
99         close(fd);
100     }
101     return true;
102 }
103 
ClearRecordPartitionOffset()104 bool PartitionRecord::ClearRecordPartitionOffset()
105 {
106     auto miscBlockDevice = GetMiscPartitionPath();
107     if (!miscBlockDevice.empty()) {
108         int fd = open(miscBlockDevice.c_str(), O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY);
109         UPDATER_FILE_CHECK(fd >= 0, "Open misc to recording partition failed", return false);
110         UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0,
111             "Seek misc to specific offset failed", fd, return false);
112 
113         off_t initOffset = 0;
114         UPDATER_CHECK_FILE_OP(write(fd, &initOffset, sizeof(off_t)) == sizeof(off_t),
115             "StartUpdater: Write misc initOffset 0 failed", fd, return false);
116         fsync(fd);
117         close(fd);
118     }
119     return true;
120 }
121 
GetMiscPartitionPath(const std::string & misc)122 std::string PartitionRecord::GetMiscPartitionPath(const std::string &misc)
123 {
124     auto miscBlockDevice = GetBlockDeviceByMountPoint(misc);
125     if (miscBlockDevice.empty()) {
126         LOG(WARNING) << "Can not find misc partition";
127     }
128     return miscBlockDevice;
129 }
130 } // namespace updater
131