bool CZipCentralDir::RemoveDataDescr(bool bFromBuffer) { // this will not work if there are bytes before zip CZipFileMapping fm; char* pFile; ZIP_SIZE_TYPE uSize; if (bFromBuffer) { uSize = m_pStorage->m_uBytesInWriteBuffer; pFile = m_pStorage->m_pWriteBuffer; } else { uSize = (ZIP_SIZE_TYPE)m_pStorage->m_pFile->GetLength(); // we cannot use CZipMemFile in multi-volume archive // so it must be CZipFile if (!fm.CreateMapping(static_cast<CZipFile*>(m_pStorage->m_pFile))) return false; pFile = fm.GetMappedMemory(); } ZIP_SIZE_TYPE uOffsetToChange = 4; ZIP_SIZE_TYPE uPosInBuffer = 0; WORD uExtraHeaderLen; ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize(); for (ZIP_INDEX_TYPE i = 0; i < uCount; i++) { CZipFileHeader* pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i]; char* pSource = pFile + pHeader->m_uOffset; if (pHeader->NeedsDataDescriptor()) uExtraHeaderLen = (WORD)(pHeader->IsEncrypted() ? 0 : 4); else { uExtraHeaderLen = pHeader->GetDataDescriptorSize(true); // removing data descriptor pHeader->m_uFlag &= ~8; // update local header: // write modified flag in the local header CBytesWriter::WriteBytes(pSource + 6, pHeader->m_uFlag); pHeader->WriteSmallDataDescriptor(pSource + 14, false); } ZIP_SIZE_TYPE uToCopy = (i == (uCount - 1) ? uSize : (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)(i + 1)]->m_uOffset) - pHeader->m_uOffset - uExtraHeaderLen; if (uToCopy > 0) // TODO: [postponed] the size_t limit on uToCopy, but creating such a big segment is unlikely (at least at the moment of writing) memmove(pFile + uPosInBuffer, pSource, (size_t)uToCopy); uPosInBuffer += uToCopy; pHeader->m_uOffset -= uOffsetToChange; uOffsetToChange += uExtraHeaderLen; } if (bFromBuffer) m_pStorage->m_uBytesInWriteBuffer = (DWORD)uPosInBuffer; else { m_pStorage->m_uBytesWritten = uPosInBuffer; fm.RemoveMapping(); m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)uPosInBuffer); } return true; }