From 7028cbe09c688437910a25623098762bf0fa592d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 28 Mar 2016 22:28:34 +1000 Subject: Move Irrlicht to src/others. --- .../irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp | 258 +++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 src/others/irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp') diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp new file mode 100644 index 0000000..bbc9a8c --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CTarReader.cpp @@ -0,0 +1,258 @@ +// Copyright (C) 2009-2012 Gaz Davidson +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CTarReader.h" + +#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + +#include "CFileList.h" +#include "CLimitReadFile.h" +#include "os.h" +#include "coreutil.h" +#if !defined(_IRR_WINDOWS_CE_PLATFORM_) +#include "errno.h" +#endif + +namespace irr +{ +namespace io +{ + +//! Constructor +CArchiveLoaderTAR::CArchiveLoaderTAR(io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderTAR"); + #endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderTAR::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "tar"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderTAR::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_TAR; +} + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderTAR::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop(); + } + + return archive; +} + + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderTAR::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if (file) + { + file->seek(0); + archive = new CTarReader(file, ignoreCase, ignorePaths); + } + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const +{ + // TAR files consist of blocks of 512 bytes + // if it isn't a multiple of 512 then it's not a TAR file. + if (file->getSize() % 512) + return false; + + file->seek(0); + + // read header of first file + STarHeader fHead; + file->read(&fHead, sizeof(STarHeader)); + + u32 checksum = 0; + sscanf(fHead.Checksum, "%o", &checksum); + + // verify checksum + + // some old TAR writers assume that chars are signed, others assume unsigned + // USTAR archives have a longer header, old TAR archives end after linkname + + u32 checksum1=0; + s32 checksum2=0; + + // remember to blank the checksum field! + memset(fHead.Checksum, ' ', 8); + + // old header + for (u8* p = (u8*)(&fHead); p < (u8*)(&fHead.Magic[0]); ++p) + { + checksum1 += *p; + checksum2 += c8(*p); + } + + if (!strncmp(fHead.Magic, "ustar", 5)) + { + for (u8* p = (u8*)(&fHead.Magic[0]); p < (u8*)(&fHead) + sizeof(fHead); ++p) + { + checksum1 += *p; + checksum2 += c8(*p); + } + } + return checksum1 == checksum || checksum2 == (s32)checksum; +} + +/* + TAR Archive +*/ +CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths) + : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) +{ + #ifdef _DEBUG + setDebugName("CTarReader"); + #endif + + if (File) + { + File->grab(); + + // fill the file list + populateFileList(); + + sort(); + } +} + + +CTarReader::~CTarReader() +{ + if (File) + File->drop(); +} + +const IFileList* CTarReader::getFileList() const +{ + return this; +} + + +u32 CTarReader::populateFileList() +{ + STarHeader fHead; + Files.clear(); + + u32 pos = 0; + while ( s32(pos + sizeof(STarHeader)) < File->getSize()) + { + // seek to next file header + File->seek(pos); + + // read the header + File->read(&fHead, sizeof(fHead)); + + // only add standard files for now + if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD) + { + io::path fullPath = ""; + fullPath.reserve(255); + + // USTAR archives have a filename prefix + // may not be null terminated, copy carefully! + if (!strncmp(fHead.Magic, "ustar", 5)) + { + c8* np = fHead.FileNamePrefix; + while(*np && (np - fHead.FileNamePrefix) < 155) + fullPath.append(*np); + np++; + } + + // append the file name + c8* np = fHead.FileName; + while(*np && (np - fHead.FileName) < 100) + { + fullPath.append(*np); + np++; + } + + // get size + core::stringc sSize = ""; + sSize.reserve(12); + np = fHead.Size; + while(*np && (np - fHead.Size) < 12) + { + sSize.append(*np); + np++; + } + + u32 size = strtoul(sSize.c_str(), NULL, 8); +#if !defined(_IRR_WINDOWS_CE_PLATFORM_) + if (errno == ERANGE) + os::Printer::log("File too large", fullPath, ELL_WARNING); +#endif + + // save start position + u32 offset = pos + 512; + + // move to next file header block + pos = offset + (size / 512) * 512 + ((size % 512) ? 512 : 0); + + // add file to list + addItem(fullPath, offset, size, false ); + } + else + { + // todo: ETLI_DIRECTORY, ETLI_LINK_TO_ARCHIVED_FILE + + // move to next block + pos += 512; + } + + } + + return Files.size(); +} + +//! opens a file by file name +IReadFile* CTarReader::createAndOpenFile(const io::path& filename) +{ + const s32 index = findFile(filename, false); + + if (index != -1) + return createAndOpenFile(index); + + return 0; +} + +//! opens a file by index +IReadFile* CTarReader::createAndOpenFile(u32 index) +{ + if (index >= Files.size() ) + return 0; + + const SFileListEntry &entry = Files[index]; + return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); +} + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ -- cgit v1.1