• 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         if (realPath == nullptr) {
37             LOG(ERROR) << "realPath is NULL" << " : " << strerror(errno);
38             return false;
39         }
40         int fd = open(realPath, O_RDONLY | O_EXCL | O_CLOEXEC | O_BINARY);
41         free(realPath);
42         if (fd < 0) {
43             LOG(ERROR) << "PartitionRecord: Open misc to recording partition failed" << " : " << strerror(errno);
44             return false;
45         }
46         if (lseek(fd, PARTITION_RECORD_START, SEEK_CUR) < 0) {
47             LOG(ERROR) << "PartitionRecord: Seek misc to specific offset failed" << " : " << strerror(errno);
48             close(fd);
49             return false;
50         }
51         if (read(fd, buffer, PARTITION_UPDATER_RECORD_MSG_SIZE) != PARTITION_UPDATER_RECORD_MSG_SIZE) {
52             LOG(ERROR) << "PartitionRecord: Read from misc partition failed" << " : " << strerror(errno);
53             close(fd);
54             return false;
55         }
56         for (uint8_t *p = buffer; p < buffer + PARTITION_UPDATER_RECORD_MSG_SIZE; p += sizeof(PartitionRecordInfo)) {
57             PartitionRecordInfo *pri = reinterpret_cast<PartitionRecordInfo*>(p);
58             if (strcmp(pri->partitionName, partitionName.c_str()) == 0) {
59                 LOG(DEBUG) << "PartitionRecord: Found " << partitionName << " record in misc partition";
60                 LOG(DEBUG) << "PartitionRecord: update status: " << pri->updated;
61                 close(fd);
62                 return pri->updated;
63             }
64         }
65         fsync(fd);
66         close(fd);
67         LOG(INFO) << "PartitionRecord: Cannot found " << partitionName << " record in misc partition";
68     }
69     return false;
70 }
71 
RecordPartitionSetOffset(int fd)72 bool PartitionRecord::RecordPartitionSetOffset(int fd)
73 {
74     off_t newOffset = 0;
75     if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) {
76         LOG(ERROR) << "PartitionRecord: Seek misc to record offset failed: " << strerror(errno);
77         return false;
78     }
79     if (read(fd, &newOffset, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) {
80         LOG(ERROR) << "PartitionRecord: Read offset failed: " << strerror(errno);
81         return false;
82     }
83     offset_ = newOffset;
84     if (lseek(fd, PARTITION_RECORD_START + offset_, SEEK_SET) < 0) {
85         LOG(ERROR) << "PartitionRecord: Seek misc to specific offset failed: " << strerror(errno);
86         return false;
87     }
88     return true;
89 }
90 
RecordPartitionSetInfo(const std::string & partitionName,bool updated,int fd)91 bool PartitionRecord::RecordPartitionSetInfo(const std::string &partitionName, bool updated, int fd)
92 {
93     (void)memset_s(&info_, sizeof(info_), 0, sizeof(info_));
94     if (strncpy_s(info_.partitionName, PARTITION_NAME_LEN, partitionName.c_str(), PARTITION_NAME_LEN - 1) != EOK) {
95         LOG(ERROR) << "PartitionRecord: strncpy_s failed: " << strerror(errno);
96         return false;
97     }
98     info_.updated = updated;
99     if (write(fd, &info_, sizeof(PartitionRecordInfo)) != static_cast<ssize_t>(sizeof(PartitionRecordInfo))) {
100         LOG(ERROR) << "PartitionRecord: write failed: " << strerror(errno);
101         return false;
102     }
103     offset_ += static_cast<off_t>(sizeof(PartitionRecordInfo));
104     if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) {
105         LOG(ERROR) << "PartitionRecord: Seek misc to record offset failed: " << strerror(errno);
106         return false;
107     }
108     if (write(fd, &offset_, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) {
109         LOG(ERROR) << "PartitionRecord: write misc to record offset failed: " << strerror(errno);
110         return false;
111     }
112     return true;
113 }
114 
RecordPartitionUpdateStatus(const std::string & partitionName,bool updated)115 bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionName, bool updated)
116 {
117     auto miscBlockDevice = GetMiscPartitionPath();
118     if (!miscBlockDevice.empty()) {
119         char *realPath = realpath(miscBlockDevice.c_str(), NULL);
120         if (realPath == nullptr) {
121             LOG(ERROR) << "realPath is NULL" << " : " << strerror(errno);
122             return false;
123         }
124         int fd = open(realPath, O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY);
125         free(realPath);
126         if (fd < 0) {
127             LOG(ERROR) << "PartitionRecord: Open misc to recording partition failed" << " : " << strerror(errno);
128             return false;
129         }
130         if (!RecordPartitionSetOffset(fd)) {
131             close(fd);
132             return false;
133         }
134         if (offset_ + static_cast<off_t>(sizeof(PartitionRecordInfo)) < PARTITION_UPDATER_RECORD_SIZE) {
135             if (!RecordPartitionSetInfo(partitionName, updated, fd)) {
136                 close(fd);
137                 return false;
138             }
139             LOG(DEBUG) << "PartitionRecord: offset is " << offset_;
140         } else {
141             LOG(WARNING) << "PartitionRecord: partition record overflow, offset = " << offset_;
142             close(fd);
143             return false;
144         }
145         LOG(DEBUG) << "PartitionRecord: record " << partitionName << " successfully.";
146         fsync(fd);
147         close(fd);
148     }
149     return true;
150 }
151 
ClearRecordPartitionOffset()152 bool PartitionRecord::ClearRecordPartitionOffset()
153 {
154     auto miscBlockDevice = GetMiscPartitionPath();
155     if (!miscBlockDevice.empty()) {
156         int fd = open(miscBlockDevice.c_str(), O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY);
157         if (fd < 0) {
158             LOG(ERROR) << "Open misc to recording partition failed" << " : " << strerror(errno);
159             return false;
160         }
161         if (lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) < 0) {
162             LOG(ERROR) << "Seek misc to specific offset failed" << " : " << strerror(errno);
163             close(fd);
164             return false;
165         }
166 
167         off_t initOffset = 0;
168         if (write(fd, &initOffset, sizeof(off_t)) != static_cast<ssize_t>(sizeof(off_t))) {
169             LOG(ERROR) << "StartUpdater: Write misc initOffset 0 failed" << " : " << strerror(errno);
170             close(fd);
171             return false;
172         }
173         fsync(fd);
174         close(fd);
175     }
176     return true;
177 }
178 
GetMiscPartitionPath(const std::string & misc)179 std::string PartitionRecord::GetMiscPartitionPath(const std::string &misc)
180 {
181     auto miscBlockDevice = GetBlockDeviceByMountPoint(misc);
182     if (miscBlockDevice.empty()) {
183         LOG(WARNING) << "Can not find misc partition";
184     }
185     return miscBlockDevice;
186 }
187 } // namespace Updater
188