bool Allocator::_Check() const { bool res = true; for (BlockNode* pNode = m_pBlocks ; pNode != NULL ; pNode = pNode->pNext) { Header* pHeader = reinterpret_cast<Header*>(pNode->pBlock); Footer* pFooter = reinterpret_cast<Footer*>(pNode->pBlock+sizeof(Header)+pHeader->m_iSize); res &= pHeader->Check(); res &= pFooter->Check(); } return true; }
void Allocator::_Free(void* ptr, const char* file_name, unsigned int line_num) { //LOG("%s:%d free(%p)\n", file_name, line_num, ptr); byte* pBlock = (byte*)ptr - sizeof(Header); Header* pHeader = reinterpret_cast<Header*>(pBlock); Footer* pFooter = reinterpret_cast<Footer*>((byte*)ptr+pHeader->m_iSize); ASSERT(pHeader->Check()); ASSERT(pFooter->Check()); ASSERT(pHeader->m_pBlockNode != NULL); RemBlock(pBlock); free(pBlock); }
void TarExtractor::Extract (/*[in]*/ Stream * pStreamIn_, /*[in]*/ const PathName & destDir, /*[in]*/ bool makeDirectories, /*[in]*/ IExtractCallback * pCallback, /*[in]*/ const char * lpszPrefix) { try { pStreamIn = pStreamIn_; totalBytesRead = 0; traceStream->WriteFormattedLine ("libextractor", T_("extracting to %s (%s)"), Q_(destDir), (makeDirectories ? T_("make directories") : T_("don't make directories"))); size_t len; Header header; size_t prefixLen = (lpszPrefix == 0 ? 0 : StrLen(lpszPrefix)); unsigned fileCount = 0; bool checkHeader = true; CharBuffer<char> buffer; buffer.Reserve (1024 * 1024); while ((len = Read(&header, sizeof(header))) > 0) { // read next header if (len != sizeof(header)) { FATAL_EXTRACTOR_ERROR ("TarExtractor::Extract", T_("Invalid package archive file."), 0); } if (header.IsEndOfArchive()) { break; } if (checkHeader) { if (! header.Check()) { FATAL_EXTRACTOR_ERROR ("TarExtractor::Extract", T_("Invalid package archive file."), 0); } #if ! defined(MIKTEX_DEBUG) checkHeader = false; #endif } PathName dest = header.GetFileName(); size_t size = header.GetFileSize(); if (! header.IsNormalFile()) { if (header.GetType() == Header::LongName) { if (size >= BLOCKSIZE) { UNEXPECTED_CONDITION ("TarExtractor::Extract"); } char longNameData[BLOCKSIZE]; ReadBlock (longNameData); longNameData[size] = 0; longName = longNameData; haveLongName = true; } else { Skip (((size + sizeof(Header) - 1) / sizeof(Header)) * sizeof(Header)); } continue; } if (haveLongName) { dest = longName; haveLongName = false; } // skip directory prefix if (lpszPrefix != 0 && PathName::Compare(lpszPrefix, dest, prefixLen) == 0) { PathName tmp (dest); dest = tmp.Get() + prefixLen; } // make the destination path name PathName path (destDir); if (! makeDirectories) { dest.RemoveDirectorySpec (); } path += dest; // notify the client if (pCallback != 0) { pCallback->OnBeginFileExtraction (path.Get(), size); } // create the destination directory Directory::Create (PathName(path).RemoveFileSpec()); // remove the existing file if (File::Exists(path)) { File::Delete (path, true); } // extract the file FileStream streamOut (File::Open(path, FileMode::Create, FileAccess::Write, false)); size_t bytesRead = 0; while (bytesRead < size) { size_t remaining = size - bytesRead; size_t n = (remaining > buffer.GetCapacity() ? buffer.GetCapacity() : remaining); if (Read(buffer.GetBuffer(), n) != n) { FATAL_EXTRACTOR_ERROR ("TarExtractor::Extract", T_("Invalid package archive file."), 0); } streamOut.Write (buffer.Get(), n); bytesRead += n; } streamOut.Close (); // skip extra bytes if (bytesRead % sizeof(Header) > 0) { Skip (sizeof(Header) - bytesRead % sizeof(Header)); } fileCount += 1; // set time when the file was created time_t time = header.GetLastModificationTime(); File::SetTimes (path, time, time, time); #if 0 // set file attributes File::SetAttributes (path, todo); #endif // notify the client if (pCallback != 0) { pCallback->OnEndFileExtraction (0, size); } } traceStream->WriteFormattedLine ("libextractor", T_("extracted %u file(s)"), fileCount); } catch (const exception &) { traceStream->WriteFormattedLine ("libextractor", T_("%u bytes were read from the tar stream"), static_cast<unsigned>(totalBytesRead)); throw; } }