1 /*
2 * Copyright (c) 2024-2024 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 <stdexcept>
17
18 #include "signature_tools_log.h"
19 #include "zip_entry.h"
20
21 namespace OHOS {
22 namespace SignatureTools {
Alignment(int alignNum)23 int ZipEntry::Alignment(int alignNum)
24 {
25 /* if cd extra len bigger than entry extra len, make cd and entry extra length equals */
26 if (alignNum == 0) {
27 return -1;
28 }
29 uint16_t padding = 0;
30 if (!CalZeroPaddingLengthForEntryExtra(padding)) {
31 return -1;
32 }
33 uint32_t remainder = (m_zipEntryData->GetZipEntryHeader()->GetLength() +
34 m_fileEntryInCentralDirectory->GetOffset()) % alignNum;
35 if (remainder == 0) {
36 return padding;
37 }
38 int add = alignNum - remainder;
39 uint16_t newExtraLength = m_zipEntryData->GetZipEntryHeader()->GetExtraLength() + add;
40 static constexpr int MAX_UNSIGNED_SHORT_VALUE = 0xFFFF;
41 if (newExtraLength > MAX_UNSIGNED_SHORT_VALUE) {
42 SIGNATURE_TOOLS_LOGE("can not align %s", m_zipEntryData->GetZipEntryHeader()->GetFileName().c_str());
43 return -1;
44 }
45 SetEntryHeaderNewExtraLength(newExtraLength);
46 SetCenterDirectoryNewExtraLength(newExtraLength);
47
48 return add;
49 }
50
CalZeroPaddingLengthForEntryExtra(uint16_t & padding)51 bool ZipEntry::CalZeroPaddingLengthForEntryExtra(uint16_t& padding)
52 {
53 uint16_t entryExtraLen = m_zipEntryData->GetZipEntryHeader()->GetExtraLength();
54 uint16_t cdExtraLen = m_fileEntryInCentralDirectory->GetExtraLength();
55 if (cdExtraLen > entryExtraLen) {
56 if (!SetEntryHeaderNewExtraLength(cdExtraLen)) {
57 return false;
58 }
59 padding = cdExtraLen - entryExtraLen;
60 }
61 if (cdExtraLen < entryExtraLen) {
62 if (!SetCenterDirectoryNewExtraLength(entryExtraLen)) {
63 return false;
64 }
65 padding = entryExtraLen - cdExtraLen;
66 }
67 return true;
68 }
69
SetCenterDirectoryNewExtraLength(uint16_t newLength)70 bool ZipEntry::SetCenterDirectoryNewExtraLength(uint16_t newLength)
71 {
72 const std::string oldExtraData = m_fileEntryInCentralDirectory->GetExtraData();
73 std::string newCDExtra;
74 if (!GetAlignmentNewExtra(newLength, oldExtraData, newCDExtra)) {
75 return false;
76 }
77 m_fileEntryInCentralDirectory->SetExtraData(newCDExtra);
78 m_fileEntryInCentralDirectory->SetExtraLength(newLength);
79 m_fileEntryInCentralDirectory->SetLength(CentralDirectory::CD_LENGTH +
80 m_fileEntryInCentralDirectory->GetFileNameLength() +
81 m_fileEntryInCentralDirectory->GetExtraLength() +
82 m_fileEntryInCentralDirectory->GetCommentLength());
83 return true;
84 }
85
SetEntryHeaderNewExtraLength(uint16_t newLength)86 bool ZipEntry::SetEntryHeaderNewExtraLength(uint16_t newLength)
87 {
88 ZipEntryHeader* zipEntryHeader = m_zipEntryData->GetZipEntryHeader();
89 const std::string oldExtraData = zipEntryHeader->GetExtraData();
90 std::string alignmentNewExtra;
91 if (!GetAlignmentNewExtra(newLength, oldExtraData, alignmentNewExtra)) {
92 return false;
93 }
94 zipEntryHeader->SetExtraData(alignmentNewExtra);
95 zipEntryHeader->SetExtraLength(newLength);
96 zipEntryHeader->SetLength(ZipEntryHeader::HEADER_LENGTH +
97 zipEntryHeader->GetExtraLength() + zipEntryHeader->GetFileNameLength());
98 m_zipEntryData->SetLength(zipEntryHeader->GetLength() +
99 m_zipEntryData->GetFileSize() +
100 (m_zipEntryData->GetDataDescriptor() == nullptr ? 0 : DataDescriptor::DES_LENGTH));
101 return true;
102 }
103
GetAlignmentNewExtra(uint16_t newLength,const std::string & old,std::string & res)104 bool ZipEntry::GetAlignmentNewExtra(uint16_t newLength, const std::string& old, std::string& res)
105 {
106 if (old.empty()) {
107 res = std::string(newLength, 0);
108 return true;
109 }
110 if (newLength < old.size()) {
111 SIGNATURE_TOOLS_LOGE("can not align %s", m_zipEntryData->GetZipEntryHeader()->GetFileName().c_str());
112 return false;
113 }
114
115 res = old;
116 res.resize(newLength);
117 return true;
118 }
119
GetZipEntryData()120 ZipEntryData* ZipEntry::GetZipEntryData()
121 {
122 return m_zipEntryData;
123 }
124
SetZipEntryData(ZipEntryData * zipEntryData)125 void ZipEntry::SetZipEntryData(ZipEntryData* zipEntryData)
126 {
127 m_zipEntryData = zipEntryData;
128 }
129
GetCentralDirectory()130 CentralDirectory* ZipEntry::GetCentralDirectory()
131 {
132 return m_fileEntryInCentralDirectory;
133 }
134
SetCentralDirectory(CentralDirectory * centralDirectory)135 void ZipEntry::SetCentralDirectory(CentralDirectory* centralDirectory)
136 {
137 m_fileEntryInCentralDirectory = centralDirectory;
138 }
139 } // namespace SignatureTools
140 } // namespace OHOS
141