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 21namespace OHOS { 22namespace SignatureTools { 23int 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 51bool 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 70bool 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 86bool 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 104bool 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 120ZipEntryData* ZipEntry::GetZipEntryData() 121{ 122 return m_zipEntryData; 123} 124 125void ZipEntry::SetZipEntryData(ZipEntryData* zipEntryData) 126{ 127 m_zipEntryData = zipEntryData; 128} 129 130CentralDirectory* ZipEntry::GetCentralDirectory() 131{ 132 return m_fileEntryInCentralDirectory; 133} 134 135void ZipEntry::SetCentralDirectory(CentralDirectory* centralDirectory) 136{ 137 m_fileEntryInCentralDirectory = centralDirectory; 138} 139} // namespace SignatureTools 140} // namespace OHOS 141